code: def _create_optimizer(ctx, o, optimizer_states_checkpoint):
      class Optimizer:
          pass
  
      optimizer = Optimizer()
  
      optimizer.proto = o
      optimizer.comm = current_communicator()
      comm_size = optimizer.comm.size if optimizer.comm else 1
      optimizer.start_iter = (
          (o.start_iter - 1) // comm_size + 1 if o.start_iter > 0 else 0
      )
      optimizer.end_iter = (
          (o.end_iter - 1) // comm_size + 1 if o.end_iter > 0 else 0
      )
      optimizer.name = o.name
      optimizer.order = o.order
      optimizer.update_interval = (
          o.update_interval if o.update_interval > 0 else 1
      )
      optimizer.network = None
      if optimizer_states_checkpoint:
          for k, v in optimizer_states_checkpoint.items():
              if optimizer.name == k:
                  optimizer.solver_checkpoint = v
  
      with nn.context_scope(ctx):
          if o.solver.type == "Adagrad":
              optimizer.solver = S.Adagrad(
                  o.solver.adagrad_param.lr, o.solver.adagrad_param.eps
              )
              init_lr = o.solver.adagrad_param.lr
          elif o.solver.type == "Adadelta":
              optimizer.solver = S.Adadelta(
                  o.solver.adadelta_param.lr,
                  o.solver.adadelta_param.decay,
                  o.solver.adadelta_param.eps,
              )
              init_lr = o.solver.adadelta_param.lr
          elif o.solver.type == "AdaBelief":
              optimizer.solver = S.AdaBelief(
                  o.solver.adabelief_param.alpha,
                  o.solver.adabelief_param.beta1,
                  o.solver.adabelief_param.beta2,
                  o.solver.adabelief_param.eps,
                  o.solver.adabelief_param.wd,
                  o.solver.adabelief_param.amsgrad,
                  o.solver.adabelief_param.weight_decouple,
                  o.solver.adabelief_param.fixed_decay,
                  o.solver.adabelief_param.rectify,
              )
              init_lr = o.solver.adabelief_param.alpha
          elif o.solver.type == "Adam":
              optimizer.solver = S.Adam(
                  o.solver.adam_param.alpha,
                  o.solver.adam_param.beta1,
                  o.solver.adam_param.beta2,
                  o.solver.adam_param.eps,
              )
              init_lr = o.solver.adam_param.alpha
          elif o.solver.type == "AdamW":
              optimizer.solver = S.AdamW(
                  o.solver.adamw_param.alpha,
                  o.solver.adamw_param.beta1,
                  o.solver.adamw_param.beta2,
                  o.solver.adamw_param.eps,
                  o.solver.adamw_param.wd,
              )
              init_lr = o.solver.adamw_param.alpha
          elif o.solver.type == "Adamax":
              optimizer.solver = S.Adamax(
                  o.solver.adamax_param.alpha,
                  o.solver.adamax_param.beta1,
                  o.solver.adamax_param.beta2,
                  o.solver.adamax_param.eps,
              )
              init_lr = o.solver.adamax_param.alpha
          elif o.solver.type == "AdaBound":
              optimizer.solver = S.AdaBound(
                  o.solver.adabound_param.alpha,
                  o.solver.adabound_param.beta1,
                  o.solver.adabound_param.beta2,
                  o.solver.adabound_param.eps,
                  o.solver.adabound_param.final_lr,
                  o.solver.adabound_param.gamma,
              )
              init_lr = o.solver.adabound_param.alpha
          elif o.solver.type == "AMSGRAD":
              optimizer.solver = S.AMSGRAD(
                  o.solver.amsgrad_param.alpha,
                  o.solver.amsgrad_param.beta1,
                  o.solver.amsgrad_param.beta2,
                  o.solver.amsgrad_param.eps,
              )
              init_lr = o.solver.amsgrad_param.alpha
          elif o.solver.type == "AMSBound":
              optimizer.solver = S.AMSBound(
                  o.solver.amsbound_param.alpha,
                  o.solver.amsbound_param.beta1,
                  o.solver.amsbound_param.beta2,
                  o.solver.amsbound_param.eps,
                  o.solver.amsbound_param.final_lr,
                  o.solver.amsbound_param.gamma,
              )
              init_lr = o.solver.amsbound_param.alpha
          elif o.solver.type == "Eve":
              p = o.solver.eve_param
              optimizer.solver = S.Eve(
                  p.alpha, p.beta1, p.beta2, p.beta3, p.k, p.k2, p.eps
              )
              init_lr = p.alpha
          elif o.solver.type == "Lars":
              optimizer.solver = S.Lars(
                  o.solver.lars_param.lr,
                  o.solver.lars_param.momentum,
                  o.solver.lars_param.coefficient,
                  o.solver.lars_param.eps,
              )
              init_lr = o.solver.lars_param.lr
          elif o.solver.type == "Momentum":
              optimizer.solver = S.Momentum(
                  o.solver.momentum_param.lr,
                  o.solver.momentum_param.momentum,
              )
              init_lr = o.solver.momentum_param.lr
          elif o.solver.type == "Nesterov":
              optimizer.solver = S.Nesterov(
                  o.solver.nesterov_param.lr,
                  o.solver.nesterov_param.momentum,
              )
              init_lr = o.solver.nesterov_param.lr
          elif o.solver.type == "RMSprop":
              optimizer.solver = S.RMSprop(
                  o.solver.rmsprop_param.lr,
                  o.solver.rmsprop_param.decay,
                  o.solver.rmsprop_param.eps,
              )
              init_lr = o.solver.rmsprop_param.lr
          elif o.solver.type == "RMSpropGraves":
              optimizer.solver = S.RMSpropGraves(
                  o.solver.rmsprop_graves_param.lr,
                  o.solver.rmsprop_graves_param.decay,
                  o.solver.rmsprop_graves_param.momentum,
                  o.solver.rmsprop_graves_param.eps,
              )
              init_lr = o.solver.rmsprop_graves_param.lr
          elif o.solver.type == "Sgd" or o.solver.type == "SGD":
              optimizer.solver = S.Sgd(o.solver.sgd_param.lr)
              init_lr = o.solver.sgd_param.lr
          elif o.solver.type == "SgdW":
              optimizer.solver = S.SgdW(
                  o.solver.sgdw_param.lr,
                  o.solver.sgdw_param.momentum,
                  o.solver.sgdw_param.wd,
              )
              init_lr = o.solver.sgdw_param.lr
          else:
              raise ValueError(
                  'Solver "' + o.solver.type + '" is not supported.'
              )
  
      optimizer.weight_decay = o.solver.weight_decay
  
      # keep following 2 lines for backward compatibility
      optimizer.lr_decay = (
          o.solver.lr_decay if o.solver.lr_decay > 0.0 else 1.0
      )
      optimizer.lr_decay_interval = (
          o.solver.lr_decay_interval
          if o.solver.lr_decay_interval > 0
          else 1
      )
  
      optimizer.comm = current_communicator()
      comm_size = optimizer.comm.size if optimizer.comm else 1
      optimizer.scheduler = ExponentialScheduler(init_lr, 1.0, 1)
  
      if o.solver.lr_scheduler_type == "Polynomial":
          if o.solver.polynomial_scheduler_param.power != 0.0:
              optimizer.scheduler = PolynomialScheduler(
                  init_lr,
                  o.solver.polynomial_scheduler_param.max_iter
                  // comm_size,
                  o.solver.polynomial_scheduler_param.power,
              )
      elif o.solver.lr_scheduler_type == "Cosine":
          optimizer.scheduler = CosineScheduler(
              init_lr,
              o.solver.cosine_scheduler_param.max_iter // comm_size,
          )
      elif o.solver.lr_scheduler_type == "Exponential":
          if o.solver.exponential_scheduler_param.gamma != 1.0:
              optimizer.scheduler = ExponentialScheduler(
                  init_lr,
                  o.solver.exponential_scheduler_param.gamma,
                  o.solver.exponential_scheduler_param.iter_interval
                  // comm_size
                  if o.solver.exponential_scheduler_param.iter_interval
                  > comm_size
                  else 1,
              )
      elif o.solver.lr_scheduler_type == "Step":
          if (
              o.solver.step_scheduler_param.gamma != 1.0
              and len(o.solver.step_scheduler_param.iter_steps) > 0
          ):
              optimizer.scheduler = StepScheduler(
                  init_lr,
                  o.solver.step_scheduler_param.gamma,
                  [
                      step // comm_size
                      for step in o.solver.step_scheduler_param.iter_steps
                  ],
              )
      elif o.solver.lr_scheduler_type == "Custom":
          # ToDo
          raise NotImplementedError()
      elif o.solver.lr_scheduler_type == "":
          if (
              o.solver.lr_decay_interval != 0
              or o.solver.lr_decay != 0.0
          ):
              optimizer.scheduler = ExponentialScheduler(
                  init_lr,
                  o.solver.lr_decay if o.solver.lr_decay > 0.0 else 1.0,
                  o.solver.lr_decay_interval // comm_size
                  if o.solver.lr_decay_interval > comm_size
                  else 1,
              )
      else:
          raise ValueError(
              'Learning Rate Scheduler "'
              + o.solver.lr_scheduler_type
              + '" is not supported.'
          )
  
      if o.solver.lr_warmup_scheduler_type == "Linear":
          if (
              o.solver.linear_warmup_scheduler_param.warmup_iter
              >= comm_size
          ):
              optimizer.scheduler = LinearWarmupScheduler(
                  optimizer.scheduler,
                  o.solver.linear_warmup_scheduler_param.warmup_iter
                  // comm_size,
              )
  
      return optimizer
  
imports: import itertools
  import os
  import re
  from collections import OrderedDict
  import nnabla
  import nnabla.functions
  import nnabla.solver
  import numpy
  from nnabla.core.graph_optimizer import IdentityRemover
  from nnabla.initializer import NormalInitializer, UniformInitializer, ConstantInitializer, RangeInitializer
  from nnabla.logger import logger
  from nnabla.utils import nnabla_pb2
  from nnabla.utils.communicator_util import current_communicator, single_or_rankzero
  from nnabla.utils.create_cache import CreateCache
  from nnabla.utils.data_iterator import data_iterator_csv_dataset, data_iterator_cache
  from nnabla.utils.get_file_handle import get_initial_file_loader, load_files
  from nnabla.utils.learning_rate_scheduler import PolynomialScheduler, CosineScheduler, ExponentialScheduler, StepScheduler, LinearWarmupScheduler
label_desc: Use image node_id 5 for calling a global function with example usage: _create_optimizer(ctx, o, optimizer_states_checkpoint) and returns: optimizer