






import unittest

from transformers import is_tf_available
from transformers.testing_utils import require_tf


if is_tf_available():
	import tensorflow as tf
	from tensorflow.python.eager import context
	from tensorflow.python.framework import ops

	from transformers import GradientAccumulator, create_optimizer


@require_tf
class    _lowerCAmelCase			(		unittest.TestCase      ):



				"""simple docstring"""



				def 					__magic_name__							(      self    :    str			,		UpperCamelCase__    :    Optional[Any]			,		UpperCamelCase__    :    Optional[int]			,		UpperCamelCase__    :    List[Any]):






											'''simple docstring'''







											self.assertEqual(len(UpperCamelCase__)			,		len(UpperCamelCase__))
											for a, b in zip(UpperCamelCase__			,		UpperCamelCase__):
																		self.assertAlmostEqual(UpperCamelCase__			,		UpperCamelCase__			,		delta=UpperCamelCase__)



				def 					__magic_name__							(      self    :    str):






											'''simple docstring'''







											snake_case__	  =       GradientAccumulator()
											accumulator([tf.constant([1.0, 2.0])])
											accumulator([tf.constant([-2.0, 1.0])])
											accumulator([tf.constant([-1.0, 2.0])])
											with self.assertRaises(UpperCamelCase__):
																		accumulator([tf.constant([1.0, 1.0]), tf.constant([2.0, 2.0])])
											self.assertEqual(accumulator.step			,		3)
											self.assertEqual(len(accumulator.gradients)			,		1)
											self.assertListAlmostEqual(accumulator.gradients[0].numpy().tolist()			,		[-2.0, 5.0]			,		tol=1E-2)
											accumulator.reset()
											self.assertEqual(accumulator.step			,		0)
											self.assertListAlmostEqual(accumulator.gradients[0].numpy().tolist()			,		[0.0, 0.0]			,		tol=1E-2)



				def 					__magic_name__							(      self    :    List[Any]):






											'''simple docstring'''







											snake_case__	  =       None
											ops.enable_eager_execution_internal()
											snake_case__	  =       tf.config.list_physical_devices("""CPU""")
											if len(UpperCamelCase__) == 1:
																		tf.config.set_logical_device_configuration(
																		    physical_devices[0]			,		[tf.config.LogicalDeviceConfiguration(), tf.config.LogicalDeviceConfiguration()])
											snake_case__	  =       tf.config.list_logical_devices(device_type="""CPU""")
											snake_case__	  =       tf.distribute.MirroredStrategy(devices=devices[:2])

											with strategy.scope():
																		snake_case__	  =       GradientAccumulator()
																		snake_case__	  =       tf.Variable([4.0, 3.0])
																		snake_case__  , snake_case__	  =       create_optimizer(5E-5			,		1_0			,		5)
																		snake_case__	  =       tf.Variable([0.0, 0.0]			,		trainable=UpperCamelCase__)

											def accumulate_on_replica(UpperCamelCase__    :    List[Any]):
																		accumulator([gradient])

											def apply_on_replica():
																		optimizer.apply_gradients(list(zip(accumulator.gradients			,		[variable])))

											@tf.function
											def accumulate(UpperCamelCase__    :    Tuple			,		UpperCamelCase__    :    Optional[int]):
																		with strategy.scope():
																									snake_case__	  =       strategy.experimental_local_results(UpperCamelCase__)
																									local_variables[0].assign(UpperCamelCase__)
																									local_variables[1].assign(UpperCamelCase__)
																									strategy.run(UpperCamelCase__			,		args=(gradient_placeholder,))

											@tf.function
											def apply_grad():
																		with strategy.scope():
																									strategy.run(UpperCamelCase__)

											def _check_local_values(UpperCamelCase__    :    Optional[int]			,		UpperCamelCase__    :    Tuple):
																		snake_case__	  =       strategy.experimental_local_results(accumulator._gradients[0])
																		self.assertListAlmostEqual(values[0].value()			,		UpperCamelCase__			,		tol=1E-2)
																		self.assertListAlmostEqual(values[1].value()			,		UpperCamelCase__			,		tol=1E-2)

											accumulate([1.0, 2.0]			,		[-1.0, 1.0])
											accumulate([3.0, -1.0]			,		[-1.0, -1.0])
											accumulate([-2.0, 2.0]			,		[3.0, -2.0])
											self.assertEqual(accumulator.step			,		3)
											_check_local_values([2.0, 3.0]			,		[1.0, -2.0])
											apply_grad()
											self.assertListAlmostEqual(variable.value()			,		[4.0, 3.0]			,		tol=1E-2)
											accumulator.reset()
											self.assertEqual(accumulator.step			,		0)
											_check_local_values([0.0, 0.0]			,		[0.0, 0.0])








from math import factorial

a__       =     {str(digit): factorial(digit) for digit in range(1_0)}

def _UpperCAmelCase   (	a						:	int ):
							if not isinstance(a  ,					a ):
														raise TypeError("""Parameter number must be int""" )

							if number < 0:
														raise ValueError("""Parameter number must be greater than or equal to 0""" )

							# Converts number in string to iterate on its digits and adds its factorial.
							return sum(DIGIT_FACTORIAL[digit] for digit in str(a ) )

def _UpperCAmelCase   (	a						:	int = 60  ,					a						:	int = 100_0000 ):

							if not isinstance(a  ,					a ) or not isinstance(a  ,					a ):
														raise TypeError("""Parameters chain_length and number_limit must be int""" )

							if chain_length <= 0 or number_limit <= 0:
														raise ValueError(
														    """Parameters chain_length and number_limit must be greater than 0""" )

							# the counter for the chains with the exact desired length
							snake_case__	  =       0
							# the cached sizes of the previous chains
							snake_case__	  =       {}

							for start_chain_element in range(1  ,					a ):
														# The temporary set will contain the elements of the chain
														snake_case__	  =       set()
														snake_case__	  =       0

														# Stop computing the chain when you find a cached size, a repeating item or the
														# length is greater then the desired one.
														snake_case__	  =       start_chain_element
														while (
														    chain_element not in chain_sets_lengths
														    and chain_element not in chain_set
														    and chain_set_length <= chain_length
														):
																					chain_set.add(a )
																					chain_set_length += 1
																					snake_case__	  =       digit_factorial_sum(a )

														if chain_element in chain_sets_lengths:
																					chain_set_length += chain_sets_lengths[chain_element]

														snake_case__	  =       chain_set_length

														# If chain contains the exact amount of elements increase the counter
														if chain_set_length == chain_length:
																					chains_counter += 1

							return chains_counter


if __name__ == "__main__":
	import doctest

	doctest.testmod()
	print(F'''{solution()}''')
