class_docstr: Performs automatic optimization (forward, zero grad, backward, optimizer step)
docstr: Runs closure (train step + backward) together with optimization if necessary.
  
  Args:
      kwargs: the kwargs passed down to the hooks
      batch_idx: the current batch index.
      optimizer: the optimizer
code: def run(
      self, optimizer: Optimizer, batch_idx: int, kwargs: OrderedDict
  ) -> _OUTPUTS_TYPE:
      """Runs closure (train step + backward) together with optimization if necessary.
  
      Args:
          kwargs: the kwargs passed down to the hooks
          batch_idx: the current batch index.
          optimizer: the optimizer
  
      """
      closure = self._make_closure(kwargs, optimizer, batch_idx)
  
      if (
          # when the strategy handles accumulation, we want to always call the optimizer step
          not self.trainer.strategy.handles_gradient_accumulation
          and self.trainer.fit_loop._should_accumulate()
      ):
          # For gradient accumulation
  
          # -------------------
          # calculate loss (train step + train step end)
          # -------------------
          # automatic_optimization=True: perform ddp sync only when performing optimizer_step
          with _block_parallel_sync_behavior(
              self.trainer.strategy, block=True
          ):
              closure()
  
      # ------------------------------
      # BACKWARD PASS
      # ------------------------------
      # gradient update with accumulated gradients
      else:
          self._optimizer_step(batch_idx, closure)
  
      result = closure.consume_result()
      if result.loss is None:
          return {}
      return result.asdict()
  
imports: from dataclasses import dataclass, field
  from functools import partial
  from typing import Any, Callable, Dict, Mapping, Optional, OrderedDict
  import torch
  from torch import Tensor
  from torch.optim import Optimizer
  from typing_extensions import override
  import lightning.pytorch
  from lightning.pytorch.loops.loop import _Loop
  from lightning.pytorch.loops.optimization.closure import AbstractClosure, OutputResult
  from lightning.pytorch.loops.progress import _OptimizationProgress
  from lightning.pytorch.loops.utilities import _block_parallel_sync_behavior
  from lightning.pytorch.trainer import call
  from lightning.pytorch.utilities.exceptions import MisconfigurationException
  from lightning.pytorch.utilities.rank_zero import WarningCache
  from lightning.pytorch.utilities.types import STEP_OUTPUT
label_desc: Use image node_id 2 for calling the _AutomaticOptimization obj's underlying member method code with example usage: obj.run(optimizer, batch_idx, kwargs) and returns: result, dict