code: def test_simulate_and_plot_values():
      import matplotlib
  
      matplotlib.use("Agg")
  
      def _test(scheduler_cls, **scheduler_kwargs):
          if scheduler_cls == LRScheduler:
              optimizer = scheduler_kwargs["lr_scheduler"].optimizer
          elif scheduler_cls == ConcatScheduler:
              optimizer = scheduler_kwargs["optimizer"]
              del scheduler_kwargs["optimizer"]
          else:
              tensor = torch.zeros([1], requires_grad=True)
              scheduler_kwargs["optimizer"] = torch.optim.SGD(
                  [tensor], lr=0.1
              )
              optimizer = scheduler_kwargs["optimizer"]
  
          max_epochs = 2
          data = [0] * 10
          simulated_values = scheduler_cls.simulate_values(
              num_events=len(data) * max_epochs, **scheduler_kwargs
          )
  
          scheduler = scheduler_cls(**scheduler_kwargs)
  
          lrs = []
  
          def save_lr(engine):
              lrs.append(optimizer.param_groups[0]["lr"])
  
          trainer = Engine(lambda engine, batch: None)
          trainer.add_event_handler(Events.ITERATION_STARTED, scheduler)
          trainer.add_event_handler(Events.ITERATION_STARTED, save_lr)
          trainer.run(data, max_epochs=max_epochs)
  
          assert lrs == pytest.approx([v for i, v in simulated_values])
  
          # reexecute to check if no internal changes
          # simulated_values = scheduler_cls.simulate_values(num_events=len(data) * max_epochs,
          #                                                  save_history=True,  # this will be removed
          #                                                  **scheduler_kwargs)
          # assert lrs == pytest.approx([v for i, v in simulated_values])
  
          # launch plot values
          scheduler_cls.plot_values(
              num_events=len(data) * max_epochs, **scheduler_kwargs
          )
  
      # LinearCyclicalScheduler
      _test(
          LinearCyclicalScheduler,
          param_name="lr",
          start_value=1.0,
          end_value=0.0,
          cycle_size=10,
      )
  
      # CosineAnnealingScheduler
      _test(
          CosineAnnealingScheduler,
          param_name="lr",
          start_value=1.0,
          end_value=0.0,
          cycle_size=10,
      )
  
      # LRScheduler
      tensor = torch.zeros([1], requires_grad=True)
      optimizer = torch.optim.SGD([tensor], lr=0.1)
      torch_lr_scheduler = torch.optim.lr_scheduler.ExponentialLR(
          optimizer=optimizer, gamma=0.5
      )
  
      _test(LRScheduler, lr_scheduler=torch_lr_scheduler)
  
      # ConcatScheduler = [LinearCyclicalScheduler, CosineAnnealingScheduler]
      scheduler_1 = LinearCyclicalScheduler(
          optimizer, "lr", start_value=1.0, end_value=0.0, cycle_size=20
      )
      scheduler_2 = CosineAnnealingScheduler(
          optimizer, "lr", start_value=0.0, end_value=1.0, cycle_size=10
      )
      durations = [10]
      _test(
          ConcatScheduler,
          optimizer=optimizer,
          schedulers=[scheduler_1, scheduler_2],
          durations=durations,
      )
  
      # ConcatScheduler = [LinearCyclicalScheduler, LRScheduler]
      tensor = torch.ones([1], requires_grad=True)
      optimizer = torch.optim.SGD([tensor], lr=0.001)
      torch_lr_scheduler = torch.optim.lr_scheduler.ExponentialLR(
          optimizer=optimizer, gamma=1.5
      )
      scheduler_1 = LRScheduler(torch_lr_scheduler)
      scheduler_2 = LinearCyclicalScheduler(
          optimizer, "lr", start_value=0.1, end_value=0.0, cycle_size=10
      )
      durations = [10]
      _test(
          ConcatScheduler,
          optimizer=optimizer,
          schedulers=[scheduler_1, scheduler_2],
          durations=durations,
      )
  
      # PiecewiseLinear
      tensor = torch.ones([1], requires_grad=True)
      optimizer = torch.optim.SGD([tensor], lr=0.001)
      _test(
          PiecewiseLinear,
          optimizer=optimizer,
          param_name="lr",
          milestones_values=[
              (10, 0.5),
              (20, 0.45),
              (21, 0.3),
              (30, 0.1),
              (40, 0.1),
          ],
      )
  
      with pytest.raises(
          ModuleNotFoundError,
          match=r"This method requires matplotlib to be installed.",
      ):
          with patch.dict("sys.modules", {"matplotlib.pyplot": None}):
              _test(
                  PiecewiseLinear,
                  optimizer=optimizer,
                  param_name="lr",
                  milestones_values=[
                      (10, 0.5),
                      (20, 0.45),
                      (21, 0.3),
                      (30, 0.1),
                      (40, 0.1),
                  ],
              )
  
imports: from unittest.mock import MagicMock, patch
  import numpy
  import pytest
  import torch
  from torch.optim.lr_scheduler import CosineAnnealingWarmRestarts, ExponentialLR, StepLR
  from ignite.engine import Engine, Events
  from ignite.handlers.param_scheduler import ConcatScheduler, CosineAnnealingScheduler, create_lr_scheduler_with_warmup, LinearCyclicalScheduler, LRScheduler, ParamGroupScheduler, ParamScheduler, PiecewiseLinear, ReduceLROnPlateauScheduler
  from tests.ignite.contrib.handlers import MockFP16DeepSpeedZeroOptimizer
label_desc: Use image node_id 16 for calling a global function with example usage: test_simulate_and_plot_values() without return types