
    GJj              	           d dl Z d dlmZmZ d dlmZ dededefdZdedede	defdZ
dded	e	d
edefdZdee   dee	   defdZded
ede	defdZy)    N)CallableListinit
decay_ratereturnc                       fd}|S )a   Make an exponential decay scheduler.

    Args:
        init (float): Initial value.
        decay_rate (float): Multiplicative factor to decay by.

    Example:
        >>> lr_schedule = optim.exponential_decay(1e-1, 0.9)
        >>> optimizer = optim.SGD(learning_rate=lr_schedule)
        >>> optimizer.learning_rate
        array(0.1, dtype=float32)
        >>>
        >>> for _ in range(5): optimizer.update({}, {})
        ...
        >>> optimizer.learning_rate
        array(0.06561, dtype=float32)
    c                     | z  z  S N )stepr   r   s    c/Users/ahmed/devFolder/claude-voice/.venv/lib/python3.12/site-packages/mlx/optimizers/schedulers.pyschedulez#exponential_decay.<locals>.schedule   s    j$&&&    r   )r   r   r   s   `` r   exponential_decayr   	   s    &' Or   	step_sizec                       fd}|S )a/  Make a step decay scheduler.

    Args:
        init (float): Initial value.
        decay_rate (float): Multiplicative factor to decay by.
        step_size (int): Decay every ``step_size`` steps.

    Example:

        >>> lr_schedule = optim.step_decay(1e-1, 0.9, 10)
        >>> optimizer = optim.SGD(learning_rate=lr_schedule)
        >>> optimizer.learning_rate
        array(0.1, dtype=float32)
        >>>
        >>> for _ in range(21): optimizer.update({}, {})
        ...
        >>> optimizer.learning_rate
        array(0.081, dtype=float32)
    c                     | z  z  z  S r
   r   )r   r   r   r   s    r   r   zstep_decay.<locals>.schedule7   s    zdi&7899r   r   )r   r   r   r   s   ``` r   
step_decayr   "   s    *: Or   decay_stepsendc                       fd}|S )a  Make a cosine decay scheduler.

    Args:
        init (float): Initial value.
        decay_steps (int): Number of steps to decay over. The decayed
            value is constant for steps beyond ``decay_steps``.
        end (float, optional): Final value to decay to. Default: ``0``.

    Example:

        >>> lr_schedule = optim.cosine_decay(1e-1, 1000)
        >>> optimizer = optim.SGD(learning_rate=lr_schedule)
        >>> optimizer.learning_rate
        array(0.1, dtype=float32)
        >>>
        >>> for _ in range(5): optimizer.update({}, {})
        ...
        >>> optimizer.learning_rate
        array(0.0999961, dtype=float32)
    c                     t        j                  |       }ddt        j                  t        j                  z  |z        z   z  }|z
  z  z   S )Ng      ?g      ?)mxminimumcosmathpi)r   sdecayr   r   r   s      r   r   zcosine_decay.<locals>.scheduleS   sM    JJt[)sRVVTWW{%:a$?@@AUdSj)))r   r   )r   r   r   r   s   ``` r   cosine_decayr    =   s    ,*
 Or   	schedules
boundariesc                      t               dk(  rt        d      t               t              dz   k7  r't        dt               dt               dz
   d       fd}|S )ag  Join multiple schedules to create a new schedule.

    Args:
        schedules (list(Callable)): A list of schedules. Schedule :math:`i+1`
          receives a step count indicating the number of steps since
          the :math:`i`-th boundary.
        boundaries (list(int)): A list of integers of length ``len(schedules) - 1``
          that indicates when to transition between schedules.

    Example:
        >>> linear = optim.linear_schedule(0, 1e-1, steps=10)
        >>> cosine = optim.cosine_decay(1e-1, 200)
        >>> lr_schedule = optim.join_schedules([linear, cosine], [10])
        >>> optimizer = optim.Adam(learning_rate=lr_schedule)
        >>> optimizer.learning_rate
        array(0.0, dtype=float32)
        >>> for _ in range(12): optimizer.update({}, {})
        ...
        >>> optimizer.learning_rate
        array(0.0999938, dtype=float32)
    r   z)Must provide at least 1 schedule to join.   z	Received z boundaries but expected .c           	           d   |       }t        dd        D ](  \  }}t        j                  | |k  | || |z
              }* |S )Nr   r$   )zipr   where)r   outputboundaryr   r"   r!   s       r   r   z join_schedules.<locals>.schedulez   sT    1d#"%j)AB-"@HhXXdXovxx7PQF #Ar   )len
ValueError)r!   r"   r   s   `` r   join_schedulesr-   [   sr    , 9~DEE
9~Z1,,J( )I*+1.
 	

 Or   stepsc                 B     dk  rt        d d       fd}|S )aL  Make a linear scheduler.

    Args:
        init (float): Initial value.
        end (float): Final value.
        steps (int): Number of steps to apply the schedule over. The value is
          ``end`` for any steps beyond ``steps``.

    Example:

        >>> lr_schedule = optim.linear_schedule(0, 1e-1, 100)
        >>> optimizer = optim.Adam(learning_rate=lr_schedule)
        >>> optimizer.learning_rate
        array(0.0, dtype=float32)
        >>> for _ in range(101): optimizer.update({}, {})
        ...
        >>> optimizer.learning_rate
        array(0.1, dtype=float32)
    r$   z&steps must be greater than 0, but got r%   c                 L    t        j                  |       } | z
  z  z  z   S r
   )r   r   )r   r   r   r.   s    r   r   z!linear_schedule.<locals>.schedule   s,    zz$&d
e+,t33r   )r,   )r   r   r.   r   s   ``` r   linear_scheduler1      s-    ( qyA%JKK4 Or   )g        )r   typingr   r   mlx.corecorer   floatr   intr   r    r-   r1   r   r   r   <module>r7      s     ! E u  2U  # ( 6u 3 U X <%d8n %$s) % %P% e C H r   