'''
    #################################################################################################################################################################################################
    # This code library is an adaptation of the original Transformers and was designed, developed and programmed by Sapiens Technology®.                                                            #
    # Any alteration and/or disclosure of this code without prior authorization is strictly prohibited and is subject to legal action that will be forwarded by the Sapiens Technology® legal team. #
    # This set of algorithms aims to download, train, fine-tune and/or infer large language models from various sources and slopes.                                                                 #
    #################################################################################################################################################################################################
'''
from torch.optim.lr_scheduler import LambdaLR
from typing import Optional, Union
from torch.optim import Optimizer
from enum import Enum
import math
class SchedulerType(Enum):
    LINEAR = 'linear'
    COSINE = 'cosine'
    COSINE_WITH_RESTARTS = 'cosine_with_restarts'
    POLYNOMIAL = 'polynomial'
    CONSTANT = 'constant'
    CONSTANT_WITH_WARMUP = 'constant_with_warmup'
    PIECEWISE_CONSTANT = 'piecewise_constant'
def get_constant_schedule(optimizer: Optimizer, last_epoch: int=-1) -> LambdaLR:
    """Args:"""
    return LambdaLR(optimizer, lambda _: 1, last_epoch=last_epoch)
def get_constant_schedule_with_warmup(optimizer: Optimizer, num_warmup_steps: int, last_epoch: int=-1) -> LambdaLR:
    """Args:"""
    def lr_lambda(current_step: int):
        if current_step < num_warmup_steps: return float(current_step) / float(max(1.0, num_warmup_steps))
        return 1.0
    return LambdaLR(optimizer, lr_lambda, last_epoch=last_epoch)
def get_piecewise_constant_schedule(optimizer: Optimizer, step_rules: str, last_epoch: int=-1) -> LambdaLR:
    """Args:"""
    rules_dict = {}
    rule_list = step_rules.split(',')
    for rule_str in rule_list[:-1]:
        value_str, steps_str = rule_str.split(':')
        steps = int(steps_str)
        value = float(value_str)
        rules_dict[steps] = value
    last_lr_multiple = float(rule_list[-1])
    def create_rules_function(rules_dict, last_lr_multiple):
        def rule_func(steps: int) -> float:
            sorted_steps = sorted(rules_dict.keys())
            for i, sorted_step in enumerate(sorted_steps):
                if steps < sorted_step: return rules_dict[sorted_steps[i]]
            return last_lr_multiple
        return rule_func
    rules_func = create_rules_function(rules_dict, last_lr_multiple)
    return LambdaLR(optimizer, rules_func, last_epoch=last_epoch)
def get_linear_schedule_with_warmup(optimizer: Optimizer, num_warmup_steps: int, num_training_steps: int, last_epoch: int=-1) -> LambdaLR:
    """Args:"""
    def lr_lambda(current_step: int):
        if current_step < num_warmup_steps: return float(current_step) / float(max(1, num_warmup_steps))
        return max(0.0, float(num_training_steps - current_step) / float(max(1, num_training_steps - num_warmup_steps)))
    return LambdaLR(optimizer, lr_lambda, last_epoch)
def get_cosine_schedule_with_warmup(optimizer: Optimizer, num_warmup_steps: int, num_training_steps: int, num_cycles: float=0.5, last_epoch: int=-1) -> LambdaLR:
    """Args:"""
    def lr_lambda(current_step):
        if current_step < num_warmup_steps: return float(current_step) / float(max(1, num_warmup_steps))
        progress = float(current_step - num_warmup_steps) / float(max(1, num_training_steps - num_warmup_steps))
        return max(0.0, 0.5 * (1.0 + math.cos(math.pi * float(num_cycles) * 2.0 * progress)))
    return LambdaLR(optimizer, lr_lambda, last_epoch)
def get_cosine_with_hard_restarts_schedule_with_warmup(optimizer: Optimizer, num_warmup_steps: int, num_training_steps: int, num_cycles: int=1, last_epoch: int=-1) -> LambdaLR:
    """Args:"""
    def lr_lambda(current_step):
        if current_step < num_warmup_steps: return float(current_step) / float(max(1, num_warmup_steps))
        progress = float(current_step - num_warmup_steps) / float(max(1, num_training_steps - num_warmup_steps))
        if progress >= 1.0: return 0.0
        return max(0.0, 0.5 * (1.0 + math.cos(math.pi * (float(num_cycles) * progress % 1.0))))
    return LambdaLR(optimizer, lr_lambda, last_epoch)
def get_polynomial_decay_schedule_with_warmup(optimizer: Optimizer, num_warmup_steps: int, num_training_steps: int, lr_end: float=1e-07, power: float=1.0, last_epoch: int=-1) -> LambdaLR:
    """Args:"""
    lr_init = optimizer.defaults['lr']
    if not lr_init > lr_end: raise ValueError(f'lr_end ({lr_end}) must be be smaller than initial lr ({lr_init})')
    def lr_lambda(current_step: int):
        if current_step < num_warmup_steps: return float(current_step) / float(max(1, num_warmup_steps))
        elif current_step > num_training_steps: return lr_end / lr_init
        else:
            lr_range = lr_init - lr_end
            decay_steps = num_training_steps - num_warmup_steps
            pct_remaining = 1 - (current_step - num_warmup_steps) / decay_steps
            decay = lr_range * pct_remaining ** power + lr_end
            return decay / lr_init
    return LambdaLR(optimizer, lr_lambda, last_epoch)
TYPE_TO_SCHEDULER_FUNCTION = {SchedulerType.LINEAR: get_linear_schedule_with_warmup, SchedulerType.COSINE: get_cosine_schedule_with_warmup, SchedulerType.COSINE_WITH_RESTARTS: get_cosine_with_hard_restarts_schedule_with_warmup, SchedulerType.POLYNOMIAL: get_polynomial_decay_schedule_with_warmup, SchedulerType.CONSTANT: get_constant_schedule, SchedulerType.CONSTANT_WITH_WARMUP: get_constant_schedule_with_warmup, SchedulerType.PIECEWISE_CONSTANT: get_piecewise_constant_schedule}
def get_scheduler(name: Union[str, SchedulerType], optimizer: Optimizer, step_rules: Optional[str]=None, num_warmup_steps: Optional[int]=None, num_training_steps: Optional[int]=None, num_cycles: int=1, power: float=1.0, last_epoch: int=-1) -> LambdaLR:
    """Args:"""
    name = SchedulerType(name)
    schedule_func = TYPE_TO_SCHEDULER_FUNCTION[name]
    if name == SchedulerType.CONSTANT: return schedule_func(optimizer, last_epoch=last_epoch)
    if name == SchedulerType.PIECEWISE_CONSTANT: return schedule_func(optimizer, step_rules=step_rules, last_epoch=last_epoch)
    if num_warmup_steps is None: raise ValueError(f'{name} requires `num_warmup_steps`, please provide that argument.')
    if name == SchedulerType.CONSTANT_WITH_WARMUP: return schedule_func(optimizer, num_warmup_steps=num_warmup_steps, last_epoch=last_epoch)
    if num_training_steps is None: raise ValueError(f'{name} requires `num_training_steps`, please provide that argument.')
    if name == SchedulerType.COSINE_WITH_RESTARTS: return schedule_func(optimizer, num_warmup_steps=num_warmup_steps, num_training_steps=num_training_steps, num_cycles=num_cycles, last_epoch=last_epoch)
    if name == SchedulerType.POLYNOMIAL: return schedule_func(optimizer, num_warmup_steps=num_warmup_steps, num_training_steps=num_training_steps, power=power, last_epoch=last_epoch)
    return schedule_func(optimizer, num_warmup_steps=num_warmup_steps, num_training_steps=num_training_steps, last_epoch=last_epoch)
'''
    #################################################################################################################################################################################################
    # This code library is an adaptation of the original Transformers and was designed, developed and programmed by Sapiens Technology®.                                                            #
    # Any alteration and/or disclosure of this code without prior authorization is strictly prohibited and is subject to legal action that will be forwarded by the Sapiens Technology® legal team. #
    # This set of algorithms aims to download, train, fine-tune and/or infer large language models from various sources and slopes.                                                                 #
    #################################################################################################################################################################################################
'''
