text: """ The Code is under Tencent Youtu Public Rule
  """
  import math
  
  import numpy as np
  from torch.optim.lr_scheduler import LambdaLR, _LRScheduler
  
  # schedule option "cosine_schedule_with_warmup"
  # code in this file is adpated from
  # https://github.com/salesforce/CoMatch/blob/main/utils.py
  # thanks!
  
  """
  
  schedule option "cosine_schedule_with_warmup"
  code in this file is adpated from
  https://github.com/salesforce/CoMatch/blob/main/utils.py
  thanks!
  
  """
  
  def cosine_schedule_with_warmup(optimizer,
                                  num_warmup_steps,
                                  num_training_steps,
                                  num_cycles=7. / 16.,
                                  last_epoch=-1):
      def _lr_lambda(current_step):
          if current_step < num_warmup_steps:
              return float(current_step) / float(max(1, num_warmup_steps))
          no_progress = float(current_step - num_warmup_steps) / \
              float(max(1, num_training_steps - num_warmup_steps))
          return max(0., math.cos(math.pi * num_cycles * no_progress))
  
      return LambdaLR(optimizer, _lr_lambda, last_epoch)
  
  
  # used in comatch but the same with the on above
  class WarmupCosineLrScheduler(_LRScheduler):
  
      def __init__(
              self,
              optimizer,
              max_iter,
              warmup_iter,
              warmup_ratio=5e-4,
              warmup='exp',
              last_epoch=-1,
      ):
          self.max_iter = max_iter
          self.warmup_iter = warmup_iter
          self.warmup_ratio = warmup_ratio
          self.warmup = warmup
          super(WarmupCosineLrScheduler, self).__init__(optimizer, last_epoch)
  
      # get learning rate
      def get_lr(self):
          ratio = self.get_lr_ratio()
          lrs = [ratio * lr for lr in self.base_lrs]
          return lrs
  
      def get_lr_ratio(self):
          if self.last_epoch < self.warmup_iter:
              ratio = self.get_warmup_ratio()
          else:
              real_iter = self.last_epoch - self.warmup_iter
              real_max_iter = self.max_iter - self.warmup_iter
              ratio = np.cos((7 * np.pi * real_iter) / (16 * real_max_iter))
              #ratio = 0.5 * (1. + np.cos(np.pi * real_iter / real_max_iter))
          return ratio
  
      def get_warmup_ratio(self):
          assert self.warmup in ('linear', 'exp')
          alpha = self.last_epoch / self.warmup_iter
          if self.warmup == 'linear':
              ratio = self.warmup_ratio + (1 - self.warmup_ratio) * alpha
          elif self.warmup == 'exp':
              ratio = self.warmup_ratio ** (1. - alpha)
          return ratio
  