class_docstr: This class is used to wrap the user optimizers and handle properly the backward and optimizer_step logic across
  accelerators, AMP, accumulate_grad_batches.
  
  Note: The purpose of this wrapper is only to define new methods and redirect the `.step()` call. The internal
  state ``__dict__`` is not kept in sync with the internal state of the original optimizer, but the Trainer never
  relies on the internal state of the wrapper.
docstr: Performs a single optimization step (parameter update).
  
  Args:
      closure: An optional optimizer closure.
      kwargs: Any additional arguments to the ``optimizer.step()`` call.
  
  Returns:
      The output from the step call, which is generally the output of the closure execution.
  
  Example::
  
      # Scenario for a GAN using manual optimization
      def training_step(self, batch, batch_idx):
          opt_gen, opt_dis = self.optimizers()
  
          ...
  
          # compute generator loss
          loss_gen = self.compute_generator_loss(...)
          # zero_grad needs to be called before backward
          opt_gen.zero_grad()
          self.manual_backward(loss_gen)
          opt_gen.step()
  
          # compute discriminator loss
          loss_dis = self.compute_discriminator_loss(...)
  
          # zero_grad needs to be called before backward
          opt_dis.zero_grad()
          self.manual_backward(loss_dis)
          opt_dis.step()
  
  
      # A more advanced example
      def training_step(self, batch, batch_idx):
          opt_gen, opt_dis = self.optimizers()
  
          ...
          accumulated_grad_batches = batch_idx % 2 == 0
  
          # compute generator loss
          def closure_gen():
              loss_gen = self.compute_generator_loss(...)
              self.manual_backward(loss_gen)
              if accumulated_grad_batches:
                  opt_gen.zero_grad()
  
          with opt_gen.toggle_model(sync_grad=accumulated_grad_batches):
              opt_gen.step(closure=closure_gen)
  
          def closure_dis():
              loss_dis = self.compute_discriminator_loss(...)
              self.manual_backward(loss_dis)
              if accumulated_grad_batches:
                  opt_dis.zero_grad()
  
          with opt_dis.toggle_model(sync_grad=accumulated_grad_batches):
              opt_dis.step(closure=closure_dis)
docstr_tok: ["Performs","a","single","optimization","step","(","parameter","update",")",".","Args",":","closure",":","An","optional","optimizer","closure",".","kwargs",":","Any","additional","arguments","to","the","``","optimizer.step","(",")","``","call",".","Returns",":","The","output","from","the","step","call",",","which","is","generally","the","output","of","the","closure","execution",".","Example",":",":","#","Scenario","for","a","GAN","using","manual","optimization","def","training_step","(","self",",","batch",",","batch_idx",")",":","opt_gen",",","opt_dis","=","self.optimizers","(",")","...","#","compute","generator","loss","loss_gen","=","self.compute_generator_loss","(","...",")","#","zero_grad","needs","to","be","called","before","backward","opt_gen.zero_grad","(",")","self.manual_backward","(","loss_gen",")","opt_gen.step","(",")","#","compute","discriminator","loss","loss_dis","=","self.compute_discriminator_loss","(","...",")","#","zero_grad","needs","to","be","called","before","backward","opt_dis.zero_grad","(",")","self.manual_backward","(","loss_dis",")","opt_dis.step","(",")","#","A","more","advanced","example","def","training_step","(","self",",","batch",",","batch_idx",")",":","opt_gen",",","opt_dis","=","self.optimizers","(",")","...","accumulated_grad_batches","=","batch_idx","%","2","==","0","#","compute","generator","loss","def","closure_gen","(",")",":","loss_gen","=","self.compute_generator_loss","(","...",")","self.manual_backward","(","loss_gen",")","if","accumulated_grad_batches",":","opt_gen.zero_grad","(",")","with","opt_gen.toggle_model","(","sync_grad=accumulated_grad_batches",")",":","opt_gen.step","(","closure=closure_gen",")","def","closure_dis","(",")",":","loss_dis","=","self.compute_discriminator_loss","(","...",")","self.manual_backward","(","loss_dis",")","if","accumulated_grad_batches",":","opt_dis.zero_grad","(",")","with","opt_dis.toggle_model","(","sync_grad=accumulated_grad_batches",")",":","opt_dis.step","(","closure=closure_dis",")"]
code: def step(
      self, closure: Optional[Callable[[], Any]] = None, **kwargs: Any
  ) -> Any:
      """Performs a single optimization step (parameter update).
  
      Args:
          closure: An optional optimizer closure.
          kwargs: Any additional arguments to the ``optimizer.step()`` call.
  
      Returns:
          The output from the step call, which is generally the output of the closure execution.
  
      Example::
  
          # Scenario for a GAN using manual optimization
          def training_step(self, batch, batch_idx):
              opt_gen, opt_dis = self.optimizers()
  
              ...
  
              # compute generator loss
              loss_gen = self.compute_generator_loss(...)
              # zero_grad needs to be called before backward
              opt_gen.zero_grad()
              self.manual_backward(loss_gen)
              opt_gen.step()
  
              # compute discriminator loss
              loss_dis = self.compute_discriminator_loss(...)
  
              # zero_grad needs to be called before backward
              opt_dis.zero_grad()
              self.manual_backward(loss_dis)
              opt_dis.step()
  
  
          # A more advanced example
          def training_step(self, batch, batch_idx):
              opt_gen, opt_dis = self.optimizers()
  
              ...
              accumulated_grad_batches = batch_idx % 2 == 0
  
              # compute generator loss
              def closure_gen():
                  loss_gen = self.compute_generator_loss(...)
                  self.manual_backward(loss_gen)
                  if accumulated_grad_batches:
                      opt_gen.zero_grad()
  
              with opt_gen.toggle_model(sync_grad=accumulated_grad_batches):
                  opt_gen.step(closure=closure_gen)
  
              def closure_dis():
                  loss_dis = self.compute_discriminator_loss(...)
                  self.manual_backward(loss_dis)
                  if accumulated_grad_batches:
                      opt_dis.zero_grad()
  
              with opt_dis.toggle_model(sync_grad=accumulated_grad_batches):
                  opt_dis.step(closure=closure_dis)
  
      """
      self._on_before_step()
  
      if closure is None:
          closure = do_nothing_closure
      elif not callable(closure):
          raise MisconfigurationException(
              "When `optimizer.step(closure)` is called, the closure should be callable"
          )
  
      assert self._strategy is not None
      step_output = self._strategy.optimizer_step(
          self._optimizer, closure, **kwargs
      )
  
      self._on_after_step()
  
      return step_output
  
imports: from contextlib import contextmanager
  from dataclasses import fields
  from typing import Any, Callable, Dict, Generator, List, Optional, Tuple, Union, overload
  from weakref import proxy
  import torch
  from torch import optim
  from torch.optim import Optimizer
  from typing_extensions import override
  import lightning.pytorch
  from lightning.fabric.utilities.types import Optimizable, ReduceLROnPlateau, _Stateful
  from lightning.pytorch.utilities.exceptions import MisconfigurationException
  from lightning.pytorch.utilities.model_helpers import is_overridden
  from lightning.pytorch.utilities.rank_zero import rank_zero_warn
  from lightning.pytorch.utilities.signature_utils import is_param_in_hook_signature
  from lightning.pytorch.utilities.types import LRSchedulerConfig, LRSchedulerTypeTuple
label_desc: Use image node_id 4 for calling the LightningOptimizer obj's underlying member method code with example usage: obj.step(closure) and returns: step_output