


import inspect
import warnings

import torch

from .state import AcceleratorState, GradientState
from .utils import DistributedType, honor_type, is_tpu_available


if is_tpu_available(check_device=False):
					import torch_xla.core.xla_model as xm
def 				UpperCamelCase_	(					__snake_case      :    Union[str, Any]						,      __snake_case      :    Dict  )->   Any:




						'''simple docstring'''
						if isinstance(__snake_case						,      (list, tuple)  ):
												return honor_type(__snake_case						,      (move_to_device(__snake_case						,      __snake_case  ) for t in state)  )
						elif isinstance(__snake_case						,      __snake_case  ):
												return type(__snake_case  )({k: move_to_device(__snake_case						,      __snake_case  ) for k, v in state.items()}  )
						elif isinstance(__snake_case						,      torch.Tensor  ):
												return state.to(__snake_case  )
						return state




class      __snake_case				(   torch.optim.Optimizer):
					def __init__(						self       :						str	,      _lowerCAmelCase       :						Union[str, Any]	,      _lowerCAmelCase       :						List[str]=True	,      _lowerCAmelCase       :						Tuple=None  )							->					List[Any]:



											'''simple docstring'''





											__magic_name__					=      optimizer
											__magic_name__					=      scaler
											__magic_name__					=      AcceleratorState()
											__magic_name__					=      GradientState()
											__magic_name__					=      device_placement
											__magic_name__					=      False
											__magic_name__					=      None

											# Handle device placement
											if device_placement:
																	__magic_name__					=      self.optimizer.state_dict()
																	if self.accelerator_state.distributed_type == DistributedType.TPU:
																							xm.send_cpu_data_to_device(_lowerCAmelCase	,      self.accelerator_state.device  )
																	else:
																							__magic_name__					=      move_to_device(_lowerCAmelCase	,      self.accelerator_state.device  )
																	self.optimizer.load_state_dict(_lowerCAmelCase  )
					@property
					def 	a			(						self       :						Dict  )							->					Optional[int]:



											'''simple docstring'''





											return self.optimizer.state
					@state.setter
					def 	a			(						self       :						List[str]	,      _lowerCAmelCase       :						List[str]  )							->					List[Any]:



											'''simple docstring'''





											__magic_name__					=      state
					@property
					def 	a			(						self       :						Dict  )							->					Union[str, Any]:



											'''simple docstring'''





											return self.optimizer.param_groups
					@param_groups.setter
					def 	a			(						self       :						str	,      _lowerCAmelCase       :						Optional[Any]  )							->					Dict:



											'''simple docstring'''





											__magic_name__					=      param_groups
					@property
					def 	a			(						self       :						Tuple  )							->					Dict:



											'''simple docstring'''





											return self.optimizer.defaults
					@defaults.setter
					def 	a			(						self       :						str	,      _lowerCAmelCase       :						Tuple  )							->					Optional[Any]:



											'''simple docstring'''





											__magic_name__					=      defaults
					def 	a			(						self       :						Union[str, Any]	,      _lowerCAmelCase       :						List[str]  )							->					Tuple:



											'''simple docstring'''





											self.optimizer.add_param_group(_lowerCAmelCase  )
					def 	a			(						self       :						Tuple	,      _lowerCAmelCase       :						List[Any]  )							->					int:



											'''simple docstring'''





											if self.accelerator_state.distributed_type == DistributedType.TPU and self.device_placement:
																	xm.send_cpu_data_to_device(_lowerCAmelCase	,      self.accelerator_state.device  )
											self.optimizer.load_state_dict(_lowerCAmelCase  )
					def 	a			(						self       :						str  )							->					Optional[int]:



											'''simple docstring'''





											return self.optimizer.state_dict()
					def 	a			(						self       :						Tuple	,      _lowerCAmelCase       :						Any=None  )							->					List[Any]:



											'''simple docstring'''





											if self.gradient_state.sync_gradients:
																	__magic_name__					=      'set_to_none' in inspect.signature(self.optimizer.zero_grad  ).parameters
																	if accept_arg:
																							if set_to_none is None:
																													__magic_name__					=      False
																							self.optimizer.zero_grad(set_to_none=_lowerCAmelCase  )
																	else:
																							if set_to_none is not None:
																													raise ValueError('`set_to_none` for Optimizer.zero_grad` is not supported by this optimizer.'  )
																							self.optimizer.zero_grad()
					def 	a			(						self       :						Dict	,      _lowerCAmelCase       :						int=None  )							->					List[str]:



											'''simple docstring'''





											if self.gradient_state.sync_gradients:
																	if self.accelerator_state.distributed_type == DistributedType.TPU:
																							__magic_name__					=      {'closure': closure} if closure is not None else {}
																							xm.optimizer_step(self.optimizer	,      optimizer_args=_lowerCAmelCase  )
																	elif self.scaler is not None:
																							__magic_name__					=      False
																							if self._last_scale is None:
																													# `get_scale` is an async operation requiring full synchronization
																													# on CPU and GPUs before finishing. As a result, we store away
																													# the prior one to reduce the call overhead
																													__magic_name__					=      self.scaler.get_scale()
																													__magic_name__					=      True
																							self.scaler.step(self.optimizer	,      _lowerCAmelCase  )
																							self.scaler.update()
																							__magic_name__					=      self.scaler.get_scale()
																							if not new_scale:
																													# If we reduced the loss scale, it means the optimizer step was skipped because of gradient overflow.
																													__magic_name__					=      scale_after < self._last_scale
																							__magic_name__					=      scale_after

																	else:
																							self.optimizer.step(_lowerCAmelCase  )
					def 	a			(						self       :						Dict	,      _lowerCAmelCase       :						Any  )							->					List[Any]:



											'''simple docstring'''





											for param_group in self.optimizer.param_groups:
																	__magic_name__					=      [parameters_map.get(_lowerCAmelCase	,      _lowerCAmelCase  ) for p in param_group['params']]
					@property
					def 	a			(						self       :						Optional[Any]  )							->					List[str]:



											'''simple docstring'''





											warnings.warn(
											    'The `is_overflow` property is deprecated and will be removed in version 1.0 of Accelerate use '
											    '`optimizer.step_was_skipped` instead.'	,      _lowerCAmelCase	,      )
											return self._is_overflow
					@property
					def 	a			(						self       :						Union[str, Any]  )							->					Optional[Any]:



											'''simple docstring'''





											return self._is_overflow
					def __getstate__(						self       :						Tuple  )							->					List[str]:



											'''simple docstring'''





											return self.__dict__.copy()







					def __setstate__(						self       :						Dict	,      _lowerCAmelCase       :						int  )							->					Union[str, Any]:



											'''simple docstring'''





											self.__dict__.update(_lowerCAmelCase  )





from collections import OrderedDict
from dataclasses import fields
from typing import Any, Tuple

import numpy as np

from .import_utils import is_torch_available
def 				UpperCamelCase_	(					__snake_case      :    Dict  )->   str:




						'''simple docstring'''
						if is_torch_available():
												import torch

												if isinstance(__snake_case						,      torch.Tensor  ):
																		return True

						return isinstance(__snake_case						,      np.ndarray  )




class      __snake_case				(   _UpperCAmelCase):
					def 	a			(						self       :						Optional[Any]  )							->					Optional[Any]:



											'''simple docstring'''





											__magic_name__					=      fields(self  )

											# Safety and consistency checks
											if not len(_lowerCAmelCase  ):
																	raise ValueError(F'''{self.__class__.__name__} has no fields.'''  )

											__magic_name__					=      getattr(self	,      class_fields[0].name  )
											__magic_name__					=      all(getattr(self	,      field.name  ) is None for field in class_fields[1:]  )

											if other_fields_are_none and isinstance(_lowerCAmelCase	,      _lowerCAmelCase  ):
																	for key, value in first_field.items():
																							__magic_name__					=      value
											else:
																	for field in class_fields:
																							__magic_name__					=      getattr(self	,      field.name  )
																							if v is not None:
																													__magic_name__					=      v
					def __delitem__(						self       :						Dict	,      *_lowerCAmelCase       :						List[str]	,      **_lowerCAmelCase       :						List[str]  )							->					List[str]:



											'''simple docstring'''





											raise Exception(F'''You cannot use ``__delitem__`` on a {self.__class__.__name__} instance.'''  )
					def 	a			(						self       :						Optional[int]	,      *_lowerCAmelCase       :						Optional[Any]	,      **_lowerCAmelCase       :						Optional[Any]  )							->					str:



											'''simple docstring'''





											raise Exception(F'''You cannot use ``setdefault`` on a {self.__class__.__name__} instance.'''  )
					def 	a			(						self       :						Union[str, Any]	,      *_lowerCAmelCase       :						List[str]	,      **_lowerCAmelCase       :						Any  )							->					str:



											'''simple docstring'''





											raise Exception(F'''You cannot use ``pop`` on a {self.__class__.__name__} instance.'''  )
					def 	a			(						self       :						Any	,      *_lowerCAmelCase       :						str	,      **_lowerCAmelCase       :						Optional[int]  )							->					List[Any]:



											'''simple docstring'''





											raise Exception(F'''You cannot use ``update`` on a {self.__class__.__name__} instance.'''  )
					def __getitem__(						self       :						Optional[Any]	,      _lowerCAmelCase       :						Any  )							->					Tuple:



											'''simple docstring'''





											if isinstance(_lowerCAmelCase	,      _lowerCAmelCase  ):
																	__magic_name__					=      dict(self.items()  )
																	return inner_dict[k]
											else:
																	return self.to_tuple()[k]
					def __setattr__(						self       :						str	,      _lowerCAmelCase       :						Optional[Any]	,      _lowerCAmelCase       :						Optional[int]  )							->					int:



											'''simple docstring'''





											if name in self.keys() and value is not None:
																	# Don't call self.__setitem__ to avoid recursion errors
																	super().__setitem__(_lowerCAmelCase	,      _lowerCAmelCase  )
											super().__setattr__(_lowerCAmelCase	,      _lowerCAmelCase  )
					def __setitem__(						self       :						Optional[Any]	,      _lowerCAmelCase       :						Optional[Any]	,      _lowerCAmelCase       :						List[str]  )							->					Optional[int]:



											'''simple docstring'''





											super().__setitem__(_lowerCAmelCase	,      _lowerCAmelCase  )
											# Don't call self.__setattr__ to avoid recursion errors
											super().__setattr__(_lowerCAmelCase	,      _lowerCAmelCase  )







					def 	a			(						self       :						str  )							->					Tuple[Any]:



											'''simple docstring'''





											return tuple(self[k] for k in self.keys()  )

