code: def test_lr_scheduler(torch_lr_scheduler_cls, kwargs):
      if torch_lr_scheduler_cls is None:
          return
  
      tensor = torch.zeros([1], requires_grad=True)
      optimizer1 = torch.optim.SGD([tensor], lr=0.01)
      optimizer2 = torch.optim.SGD([tensor], lr=0.01)
      optimizer3 = torch.optim.SGD([tensor], lr=0.01)
      opt_state_dict1 = optimizer1.state_dict()
      opt_state_dict2 = optimizer2.state_dict()
      opt_state_dict3 = optimizer3.state_dict()
  
      torch_lr_scheduler1 = torch_lr_scheduler_cls(
          optimizer=optimizer1, **kwargs
      )
      scheduler1 = LRScheduler(torch_lr_scheduler1)
      state_dict1 = scheduler1.state_dict()
  
      torch_lr_scheduler2 = torch_lr_scheduler_cls(
          optimizer=optimizer2, **kwargs
      )
      with pytest.warns(
          UserWarning,
          match=r"the first lr value from the optimizer, otherwise it will be skipped",
      ):
          scheduler2 = LRScheduler(torch_lr_scheduler2, use_legacy=True)
      state_dict2 = scheduler2.state_dict()
  
      torch_lr_scheduler3 = torch_lr_scheduler_cls(
          optimizer=optimizer3, **kwargs
      )
      state_dict3 = torch_lr_scheduler3.state_dict()
  
      def dummy_update(engine, batch):
          optimizer1.step()
          optimizer2.step()
          optimizer3.step()
  
      trainer = Engine(dummy_update)
      trainer.add_event_handler(Events.ITERATION_STARTED, scheduler1)
  
      @trainer.on(Events.ITERATION_STARTED)
      def save_lr1(engine):
          lrs1.append(optimizer1.param_groups[0]["lr"])
  
      @trainer.on(Events.ITERATION_STARTED)
      def save_lr2(engine):
          lrs2.append(optimizer2.param_groups[0]["lr"])
  
      @trainer.on(Events.ITERATION_STARTED)
      def save_true_lr(engine):
          lrs_true.append(optimizer3.param_groups[0]["lr"])
  
      @trainer.on(Events.ITERATION_COMPLETED)
      def torch_lr_scheduler_step(engine):
          torch_lr_scheduler3.step()
  
      trainer.add_event_handler(Events.ITERATION_COMPLETED, scheduler2)
  
      for _ in range(2):
          lrs1 = []
          lrs2 = []
          lrs_true = []
          data = [0] * 10
          max_epochs = 2
          trainer.run(data, max_epochs=max_epochs)
          assert lrs_true == pytest.approx(
              lrs1
          ), f"{_}: {lrs_true} ({len(lrs_true)}) vs {lrs1} ({len(lrs1)})"
          assert lrs_true == pytest.approx(
              lrs2
          ), f"{_}: {lrs_true} ({len(lrs_true)}) vs {lrs2} ({len(lrs2)})"
          optimizer1.load_state_dict(opt_state_dict1)
          scheduler1.load_state_dict(state_dict1)
          optimizer2.load_state_dict(opt_state_dict2)
          scheduler2.load_state_dict(state_dict2)
          optimizer3.load_state_dict(opt_state_dict3)
          torch_lr_scheduler3.load_state_dict(state_dict3)
  
      optimizer4 = torch.optim.SGD([tensor], lr=0.01)
      torch_lr_scheduler4 = torch_lr_scheduler_cls(
          optimizer=optimizer4, **kwargs
      )
  
      simulated_values = LRScheduler.simulate_values(
          num_events=len(data) * max_epochs,
          lr_scheduler=torch_lr_scheduler4,
      )
      assert lrs1 == pytest.approx([v for i, v in simulated_values])
      assert lrs2 == pytest.approx([v for i, v in simulated_values])
  
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 13 for calling a global function with example usage: test_lr_scheduler(torch_lr_scheduler_cls, kwargs) without return types