code: def test_save_param_history():
      tensor = torch.zeros([1], requires_grad=True)
      optimizer = torch.optim.SGD([tensor], lr=0)
  
      scheduler = LinearCyclicalScheduler(
          optimizer, "lr", 1, 0, 10, save_history=True
      )
      lrs = []
  
      def save_lr(engine):
          lrs.append(optimizer.param_groups[0]["lr"])
  
      trainer = Engine(lambda engine, batch: None)
      assert not hasattr(trainer.state, "param_history")
  
      trainer.add_event_handler(Events.ITERATION_STARTED, scheduler)
      trainer.add_event_handler(Events.ITERATION_COMPLETED, save_lr)
      trainer.run([0] * 10, max_epochs=2)
  
      state_lrs = trainer.state.param_history["lr"]
      assert len(state_lrs) == len(lrs)
      # Unpack singleton lists
      assert [group[0] for group in state_lrs] == lrs
  
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 11 for calling a global function with example usage: test_save_param_history() without return types