





import collections

from .utils import ExplicitEnum, is_torch_available, logging


if is_torch_available():
						import torch


UpperCamelCase_     =logging.get_logger(__name__)




class 				_a		:






				def __init__(				self	:					List[str],				lowerCAmelCase__	:					Optional[Any],				lowerCAmelCase__	:					Union[str, Any]=2_1,				lowerCAmelCase__	:					Dict=[],				lowerCAmelCase__	:					List[Any]=None							)			->   Tuple:




										'''simple docstring'''



										_UpperCamelCase    :      Optional[Any]						     =					model
										_UpperCamelCase    :      List[str]						     =					trace_batch_nums
										_UpperCamelCase    :      Dict						     =					abort_after_batch_num

										# keep a LIFO buffer of frames to dump as soon as inf/nan is encountered to give context to the problem emergence
										_UpperCamelCase    :      Optional[Any]						     =					collections.deque([],				lowerCAmelCase__							)
										_UpperCamelCase    :      Union[str, Any]						     =					[]
										_UpperCamelCase    :      Dict						     =					0
										_UpperCamelCase    :      List[Any]						     =					0
										_UpperCamelCase    :      List[Any]						     =					False
										_UpperCamelCase    :      str						     =					'''                 '''

										self.analyse_model()

										self.register_forward_hook()






				def        snake_case			(				self	:					List[str],				lowerCAmelCase__	:					Tuple=None							)			->   Tuple:




										'''simple docstring'''



										if frame is not None:
																self.expand_frame(lowerCAmelCase__							)
										self.frames.append('''\n'''.join(self.frame							)							)
										_UpperCamelCase    :      Tuple						     =					[]  # start a new frame






				def        snake_case			(				self	:					Any,				lowerCAmelCase__	:					List[str]							)			->   int:




										'''simple docstring'''



										self.frame.append(lowerCAmelCase__							)






				def        snake_case			(				self	:					List[str]							)			->   Optional[Any]:




										'''simple docstring'''



										print('''\n'''.join(self.frames							)							)
										_UpperCamelCase    :      Dict						     =					[]






				def        snake_case			(				self	:					Optional[Any]							)			->   Optional[int]:




										'''simple docstring'''



										_UpperCamelCase    :      Any						     =					[]






				def        snake_case			(				self	:					List[str]							)			->   int:




										'''simple docstring'''



										print(f"""\nDetected inf/nan during batch_number={self.batch_number}"""							)
										print(f"""Last {len(self.frames							)} forward frames:"""							)
										print(f"""{'abs min':8} {'abs max':8} metadata"""							)
										print('''\n'''.join(self.frames							)							)
										print('''\n\n'''							)
										_UpperCamelCase    :      int						     =					[]






				def        snake_case			(				self	:					List[str]							)			->   Optional[int]:




										'''simple docstring'''



										_UpperCamelCase    :      Union[str, Any]						     =					{m: name for name, m in self.model.named_modules()}
										# self.longest_module_name = max(len(v) for v in self.module_names.values())






				def        snake_case			(				self	:					List[Any],				lowerCAmelCase__	:					int,				lowerCAmelCase__	:					int							)			->   Union[str, Any]:




										'''simple docstring'''



										if torch.is_tensor(lowerCAmelCase__							):
																self.expand_frame(get_abs_min_max(lowerCAmelCase__,				lowerCAmelCase__							)							)
																if detect_overflow(lowerCAmelCase__,				lowerCAmelCase__							):
																						_UpperCamelCase    :      int						     =					True
										elif var is None:
																self.expand_frame(f"""{'None':>17} {ctx}"""							)
										else:
																self.expand_frame(f"""{'not a tensor':>17} {ctx}"""							)






				def        snake_case			(				self	:					int							)			->   Tuple:




										'''simple docstring'''



										self.expand_frame(f"""\n\n{self.prefix} *** Starting batch number={self.batch_number} ***"""							)
										self.expand_frame(f"""{'abs min':8} {'abs max':8} metadata"""							)






				def        snake_case			(				self	:					str							)			->   Tuple:




										'''simple docstring'''



										self.expand_frame(f"""{self.prefix} *** Finished batch number={self.batch_number-1} ***\n\n"""							)






				def        snake_case			(				self	:					Dict,				lowerCAmelCase__	:					Union[str, Any],				lowerCAmelCase__	:					int,				lowerCAmelCase__	:					Optional[int]							)			->   Dict:




										'''simple docstring'''



										self.expand_frame(f"""{self.prefix} {self.module_names[module]} {module.__class__.__name__}"""							)

										# params
										for name, p in module.named_parameters(recurse=lowerCAmelCase__							):
																self.analyse_variable(lowerCAmelCase__,				lowerCAmelCase__							)

										# inputs
										if isinstance(lowerCAmelCase__,				lowerCAmelCase__							):
																for i, x in enumerate(lowerCAmelCase__							):
																						self.analyse_variable(lowerCAmelCase__,				f"""input[{i}]"""							)
										else:
																self.analyse_variable(lowerCAmelCase__,				'''input'''							)

										# outputs
										if isinstance(lowerCAmelCase__,				lowerCAmelCase__							):
																for i, x in enumerate(lowerCAmelCase__							):
																						# possibly a tuple of tuples
																						if isinstance(lowerCAmelCase__,				lowerCAmelCase__							):
																												for j, y in enumerate(lowerCAmelCase__							):
																																		self.analyse_variable(lowerCAmelCase__,				f"""output[{i}][{j}]"""							)
																						else:
																												self.analyse_variable(lowerCAmelCase__,				f"""output[{i}]"""							)
										else:
																self.analyse_variable(lowerCAmelCase__,				'''output'''							)

										self.save_frame()






				def        snake_case			(				self	:					Optional[Any]							)			->   Any:




										'''simple docstring'''



										self.model.apply(self._register_forward_hook							)






				def        snake_case			(				self	:					int,				lowerCAmelCase__	:					Tuple							)			->   str:




										'''simple docstring'''



										module.register_forward_hook(self.forward_hook							)






				def        snake_case			(				self	:					Union[str, Any],				lowerCAmelCase__	:					List[str],				lowerCAmelCase__	:					Optional[Any],				lowerCAmelCase__	:					Optional[int]							)			->   Optional[Any]:




										'''simple docstring'''



										_UpperCamelCase    :      Dict						     =					False

										_UpperCamelCase    :      Optional[int]						     =					True if self.batch_number in self.trace_batch_nums else False
										if trace_mode:
																self.reset_saved_frames()

										if self.total_calls == 0:
																self.batch_start_frame()
										self.total_calls += 1

										# count batch numbers - the very first forward hook of the batch will be called when the
										# batch completes - i.e. it gets called very last - we know this batch has finished
										if module == self.model:
																self.batch_number += 1
																_UpperCamelCase    :      Union[str, Any]						     =					True

										self.create_frame(lowerCAmelCase__,				lowerCAmelCase__,				lowerCAmelCase__							)

										# if last_frame_of_batch:
										#     self.batch_end_frame()

										if trace_mode:
																self.trace_frames()

										if last_frame_of_batch:
																self.batch_start_frame()

										if self.detected_overflow and not trace_mode:
																self.dump_saved_frames()

																# now we can abort, as it's pointless to continue running
																raise ValueError(
																    '''DebugUnderflowOverflow: inf/nan detected, aborting as there is no point running further. '''
																    '''Please scroll up above this traceback to see the activation values prior to this event.'''							)

										# abort after certain batch if requested to do so
										if self.abort_after_batch_num is not None and self.batch_number > self.abort_after_batch_num:
																raise ValueError(
																    f"""DebugUnderflowOverflow: aborting after {self.batch_number} batches due to"""
																    f""" `abort_after_batch_num={self.abort_after_batch_num}` arg"""							)





def  a_       (							_lowercase ,		_lowercase     ):
						_UpperCamelCase    :      Optional[int]						     =					var.abs()
						return F"""{abs_var.min():8.2e} {abs_var.max():8.2e} {ctx}"""





def  a_       (							_lowercase ,		_lowercase     ):
						_UpperCamelCase    :      Any						     =					False
						if torch.isnan(_lowercase     ).any().item():
												_UpperCamelCase    :      Tuple						     =					True
												print(F"""{ctx} has nans"""     )
						if torch.isinf(_lowercase     ).any().item():
												_UpperCamelCase    :      str						     =					True
												print(F"""{ctx} has infs"""     )

						# if needed to monitor large elements can enable the following
						if 0:  # and detected:
												_UpperCamelCase    :      List[str]						     =					var[torch.ge(var.abs() ,		100     )]
												if naaa.numel() > 0:
																		print(F"""{ctx}:  n100={naaa.numel()}"""     )
												_UpperCamelCase    :      List[str]						     =					var[torch.ge(var.abs() ,		1000     )]
												if naaaa.numel() > 0:
																		print(F"""{ctx}: n1000={naaaa.numel()}"""     )
												_UpperCamelCase    :      Tuple						     =					var[torch.ge(var.abs() ,		1_0000     )]
												if naaaaa.numel() > 0:
																		print(F"""{ctx}: n10000={naaaaa.numel()}"""     )

						if 0:
												print(F"""min={var.min():9.2e} max={var.max():9.2e}"""     )

						if 0:
												print(F"""min={var.min():9.2e} max={var.max():9.2e} var={var.var():9.2e} mean={var.mean():9.2e} ({ctx})"""     )

						return detected






class 				_a		(   _lowerCAmelCase       ):
				UpperCamelCase			=					'''underflow_overflow'''
				UpperCamelCase			=					'''tpu_metrics_debug'''










"""simple docstring"""




def  a_       (							_lowercase ,		_lowercase ,		_lowercase ,		_lowercase     ):
						return len_board * len_board_column * row + column





def  a_       (							_lowercase ,		_lowercase ,		_lowercase ,		_lowercase ,		_lowercase ,		_lowercase ,		):

						if board[row][column] != word[word_index]:
												return False

						if word_index == len(_lowercase     ) - 1:
												return True

						_UpperCamelCase    :      Union[str, Any]						     =					[(0, 1), (0, -1), (-1, 0), (1, 0)]
						_UpperCamelCase    :      List[str]						     =					len(_lowercase     )
						_UpperCamelCase    :      Optional[Any]						     =					len(board[0]     )
						for direction in traverts_directions:
												_UpperCamelCase    :      Union[str, Any]						     =					row + direction[0]
												_UpperCamelCase    :      List[Any]						     =					column + direction[1]
												if not (0 <= next_i < len_board and 0 <= next_j < len_board_column):
																		continue

												_UpperCamelCase    :      Optional[Any]						     =					get_point_key(_lowercase ,		_lowercase ,		_lowercase ,		_lowercase     )
												if key in visited_points_set:
																		continue

												visited_points_set.add(_lowercase     )
												if exits_word(_lowercase ,		_lowercase ,		_lowercase ,		_lowercase ,		word_index + 1 ,		_lowercase     ):
																		return True

												visited_points_set.remove(_lowercase     )

						return False





def  a_       (							_lowercase ,		_lowercase     ):
						_UpperCamelCase    :      Optional[Any]						     =					(
						    '''The board should be a non empty matrix of single chars strings.'''
						)

						_UpperCamelCase    :      int						     =					len(_lowercase     )
						if not isinstance(_lowercase ,		_lowercase     ) or len(_lowercase     ) == 0:
												raise ValueError(_lowercase     )

						for row in board:
												if not isinstance(_lowercase ,		_lowercase     ) or len(_lowercase     ) == 0:
																		raise ValueError(_lowercase     )

												for item in row:
																		if not isinstance(_lowercase ,		_lowercase     ) or len(_lowercase     ) != 1:
																								raise ValueError(_lowercase     )

    # Validate word
						if not isinstance(_lowercase ,		_lowercase     ) or len(_lowercase     ) == 0:
												raise ValueError(
												    '''The word parameter should be a string of length greater than 0.'''     )

						_UpperCamelCase    :      List[str]						     =					len(board[0]     )
						for i in range(_lowercase     ):
												for j in range(_lowercase     ):
																		if exits_word(
																		    _lowercase ,		_lowercase ,		_lowercase ,		_lowercase ,		0 ,		{get_point_key(_lowercase ,		_lowercase ,		_lowercase ,		_lowercase     )}     ):
																								return True

						return False


if __name__ == "__main__":
						import doctest

						doctest.testmod()



