





"""simple docstring"""






import os
import tempfile
import unittest

from transformers import is_torch_available
from transformers.testing_utils import require_torch


if is_torch_available():
    import torch
    from torch import nn

    from transformers import (
        Adafactor,
        AdamW,
        get_constant_schedule,
        get_constant_schedule_with_warmup,
        get_cosine_schedule_with_warmup,
        get_cosine_with_hard_restarts_schedule_with_warmup,
        get_inverse_sqrt_schedule,
        get_linear_schedule_with_warmup,
        get_polynomial_decay_schedule_with_warmup,
    )

def       __lowerCamelCase    (       SCREAMING_SNAKE_CASE,SCREAMING_SNAKE_CASE=10							)		->       str:






       """simple docstring"""




       _UpperCAmelCase     =     []
       for _ in range(SCREAMING_SNAKE_CASE							):
              lrs.append(scheduler.get_lr()[0]							)
              scheduler.step()
       return lrs

def       __lowerCamelCase    (       SCREAMING_SNAKE_CASE,SCREAMING_SNAKE_CASE=10							)		->       Any:






       """simple docstring"""




       _UpperCAmelCase     =     []
       for step in range(SCREAMING_SNAKE_CASE							):
              lrs.append(scheduler.get_lr()[0]							)
              scheduler.step()
              if step == num_steps // 2:
                     with tempfile.TemporaryDirectory() as tmpdirname:
                            _UpperCAmelCase     =     os.path.join(SCREAMING_SNAKE_CASE,'schedule.bin'							)
                            torch.save(scheduler.state_dict(),SCREAMING_SNAKE_CASE							)

                            _UpperCAmelCase     =     torch.load(SCREAMING_SNAKE_CASE							)
                            scheduler.load_state_dict(SCREAMING_SNAKE_CASE							)
       return lrs



@require_torch
class 	lowerCAmelCase					(      unittest.TestCase							):






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






       def 							__A (   self     ):
              _UpperCAmelCase     =     torch.tensor([0.1, -0.2, -0.1]    ,  requires_grad=a__     )
              _UpperCAmelCase     =     torch.tensor([0.4, 0.2, -0.5]     )
              _UpperCAmelCase     =     nn.MSELoss()
              # No warmup, constant schedule, no gradient clipping
              _UpperCAmelCase     =     AdamW(params=[w]    ,  lr=2E-1    ,  weight_decay=0.0     )
              for _ in range(1_00     ):
                     _UpperCAmelCase     =     criterion(a__    ,  a__     )
                     loss.backward()
                     optimizer.step()
                     w.grad.detach_()  # No zero_grad() function on simple tensors. we do it ourselves.
                     w.grad.zero_()
              self.assertListAlmostEqual(w.tolist()    ,  [0.4, 0.2, -0.5]    ,  tol=1E-2     )






       def 							__A (   self     ):
              _UpperCAmelCase     =     torch.tensor([0.1, -0.2, -0.1]    ,  requires_grad=a__     )
              _UpperCAmelCase     =     torch.tensor([0.4, 0.2, -0.5]     )
              _UpperCAmelCase     =     nn.MSELoss()
              # No warmup, constant schedule, no gradient clipping
              _UpperCAmelCase     =     Adafactor(
                  params=[w]    ,  lr=1E-2    ,  eps=(1E-30, 1E-3)    ,  clip_threshold=1.0    ,  decay_rate=-0.8    ,  betaa=a__    ,  weight_decay=0.0    ,  relative_step=a__    ,  scale_parameter=a__    ,  warmup_init=a__    ,  )
              for _ in range(10_00     ):
                     _UpperCAmelCase     =     criterion(a__    ,  a__     )
                     loss.backward()
                     optimizer.step()
                     w.grad.detach_()  # No zero_grad() function on simple tensors. we do it ourselves.
                     w.grad.zero_()
              self.assertListAlmostEqual(w.tolist()    ,  [0.4, 0.2, -0.5]    ,  tol=1E-2     )



@require_torch
class 	lowerCAmelCase					(      unittest.TestCase							):
       lowerCAmelCase__						 =  nn.Linear(50			,	50							) if is_torch_available() else None
       lowerCAmelCase__						 =  AdamW(m.parameters()			,	lr=10.0							) if is_torch_available() else None
       lowerCAmelCase__						 =  10






       def 							__A (   self    ,  a__    ,  a__    ,  a__    ,  a__=None     ):
              self.assertEqual(len(a__     )    ,  len(a__     )     )
              for a, b in zip(a__    ,  a__     ):
                     self.assertAlmostEqual(a__    ,  a__    ,  delta=a__    ,  msg=a__     )






       def 							__A (   self     ):
              _UpperCAmelCase     =     {'num_warmup_steps': 2, 'num_training_steps': 10}
              # schedulers doct format
              # function: (sched_args_dict, expected_learning_rates)
              _UpperCAmelCase     =     {
                  get_constant_schedule: ({}, [10.0] * self.num_steps),
                  get_constant_schedule_with_warmup: (
                      {'num_warmup_steps': 4},
                      [0.0, 2.5, 5.0, 7.5, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0],
                  ),
                  get_linear_schedule_with_warmup: (
                      {**common_kwargs},
                      [0.0, 5.0, 10.0, 8.75, 7.5, 6.25, 5.0, 3.75, 2.5, 1.25],
                  ),
                  get_cosine_schedule_with_warmup: (
                      {**common_kwargs},
                      [0.0, 5.0, 10.0, 9.61, 8.53, 6.91, 5.0, 3.08, 1.46, 0.38],
                  ),
                  get_cosine_with_hard_restarts_schedule_with_warmup: (
                      {**common_kwargs, 'num_cycles': 2},
                      [0.0, 5.0, 10.0, 8.53, 5.0, 1.46, 10.0, 8.53, 5.0, 1.46],
                  ),
                  get_polynomial_decay_schedule_with_warmup: (
                      {**common_kwargs, 'power': 2.0, 'lr_end': 1E-7},
                      [0.0, 5.0, 10.0, 7.656, 5.625, 3.906, 2.5, 1.406, 0.625, 0.156],
                  ),
                  get_inverse_sqrt_schedule: (
                      {'num_warmup_steps': 2},
                      [0.0, 5.0, 10.0, 8.165, 7.071, 6.325, 5.774, 5.345, 5.0, 4.714],
                  ),
              }

              for scheduler_func, data in scheds.items():
                     _UpperCAmelCase    ,							_UpperCAmelCase     =     data

                     _UpperCAmelCase     =     scheduler_func(self.optimizer    ,  **a__     )
                     self.assertEqual(len([scheduler.get_lr()[0]]     )    ,  1     )
                     _UpperCAmelCase     =     unwrap_schedule(a__    ,  self.num_steps     )
                     self.assertListAlmostEqual(
                         a__    ,  a__    ,  tol=1E-2    ,  msg=f"""failed for {scheduler_func} in normal scheduler"""    ,  )

                     _UpperCAmelCase     =     scheduler_func(self.optimizer    ,  **a__     )
                     if scheduler_func.__name__ != "get_constant_schedule":
                            LambdaScheduleWrapper.wrap_scheduler(a__     )  # wrap to test picklability of the schedule
                     _UpperCAmelCase     =     unwrap_and_save_reload_schedule(a__    ,  self.num_steps     )
                     self.assertListEqual(a__    ,  a__    ,  msg=f"""failed for {scheduler_func} in save and reload"""     )



class 	lowerCAmelCase					:






       def __init__(   self    ,  a__     ):
              _UpperCAmelCase     =     fn






       def __call__(   self    ,  *a__    ,  **a__     ):
              return self.fn(*a__    ,  **a__     )






       @classmethod
       def 							__A (   self    ,  a__     ):
              _UpperCAmelCase     =     list(map(self    ,  scheduler.lr_lambdas     )     )













"""simple docstring"""






from itertools import product

def       __lowerCamelCase    (       SCREAMING_SNAKE_CASE,SCREAMING_SNAKE_CASE							)		->       list[int]:






       """simple docstring"""




       _UpperCAmelCase     =     sides_number
       _UpperCAmelCase     =     max_face_number * dice_number
       _UpperCAmelCase     =     [0] * (max_total + 1)

       _UpperCAmelCase     =     1
       _UpperCAmelCase     =     range(SCREAMING_SNAKE_CASE,max_face_number + 1							)
       for dice_numbers in product(SCREAMING_SNAKE_CASE,repeat=SCREAMING_SNAKE_CASE							):
              _UpperCAmelCase     =     sum(SCREAMING_SNAKE_CASE							)
              totals_frequencies[total] += 1

       return totals_frequencies

def       __lowerCamelCase    (       )		->       float:






       """simple docstring"""




       _UpperCAmelCase     =     total_frequency_distribution(
           sides_number=4,dice_number=9							)
       _UpperCAmelCase     =     total_frequency_distribution(
           sides_number=6,dice_number=6							)

       _UpperCAmelCase     =     0
       _UpperCAmelCase     =     9
       _UpperCAmelCase     =     4 * 9
       _UpperCAmelCase     =     6
       for peter_total in range(SCREAMING_SNAKE_CASE,max_peter_total + 1							):
              peter_wins_count += peter_totals_frequencies[peter_total] * sum(
                  colin_totals_frequencies[min_colin_total:peter_total]							)

       _UpperCAmelCase     =     (4**9) * (6**6)
       _UpperCAmelCase     =     peter_wins_count / total_games_number

       _UpperCAmelCase     =     round(SCREAMING_SNAKE_CASE,ndigits=7							)

       return rounded_peter_win_probability


if __name__ == "__main__":
    print(F'''{solution() = }''')






