o
    zi                     @   s\   d dl mZ d dlmZmZ d dlZd dlmZ ddlm	Z	m
Z
mZ dZG dd	 d	eZdS )
    )defaultdict)AnyDictN)	Optimizer   )OptFloatOptLossClosureState)	Lookaheadc                	       s   e Zd ZdZ	ddedededdfd	d
Zdee	e
f ddfddZddedefddZdef fddZdeddf fddZdddZde	fddZ  ZS )r
   a  Implements Lookahead optimization algorithm.

    It has been proposed in `Lookahead Optimizer: k steps forward, 1
    step back`__

    Arguments:
        optimizer: base inner optimizer optimize, like Yogi, DiffGrad or Adam.
        k: number of lookahead steps (default: 5)
        alpha: linear interpolation factor. 1.0 recovers the inner optimizer.
            (default: 5)

    Example:
        >>> import torch_optimizer as optim
        >>> yogi = optim.Yogi(model.parameters(), lr=0.1)
        >>> optimizer = optim.Lookahead(yogi, k=5, alpha=0.5)
        >>> optimizer.zero_grad()
        >>> loss_fn(model(input), target).backward()
        >>> optimizer.step()

    __ https://arxiv.org/abs/1907.08610

    Note:
        Reference code: https://github.com/alphadl/lookahead.pytorch
             ?	optimizerkalphareturnNc                 C   st   |dk rt d||dk rt d||| _|| _|| _| jj| _tt| _| jj| _	| jD ]}d|d< q1d S )Ng        z%Invalid number of lookahead steps: {}r   z'Invalid linear interpolation factor: {}counter)

ValueErrorformatr   r   r   param_groupsr   dictstate
fast_state)selfr   r   r   group r   M/home/ubuntu/.local/lib/python3.10/site-packages/torch_optimizer/lookahead.py__init__&   s   




zLookahead.__init__r   c                 C   sj   |d D ].}| j | }d|vrt|j |d< |d }|j| jj|d| j d |j| qd S )Nparams
slow_paramg      ?)r   )	r   torchclonedatadetachmul_r   add_copy_)r   r   fastparam_stateslowr   r   r   _update9   s   
zLookahead._updateclosurec                 C   sJ   | j j|d}| jD ]}|d dkr| | |d d | j |d< q
|S )zPerforms a single optimization step.

        Arguments:
            closure: A closure that reevaluates the model and returns the loss.
        )r*   r   r   r   )r   stepr   r)   r   )r   r*   lossr   r   r   r   r+   C   s   

zLookahead.stepc                    s8   t t|  }| j }|d }|d }||d |dS )a  Returns the state of the optimizer as a :class:`dict`.

        It contains two entries:
        * state - a dict holding current optimization state. Its content
            differs between optimizer classes.
        * param_groups - a dict containing all parameter groups
        r   r   )r   
slow_stater   )superr
   
state_dictr   )r   slow_state_dictfast_state_dictr   r   	__class__r   r   r/   P   s   
zLookahead.state_dictr/   c                    sN   |d |d d}|d |d d}t t| | | j| | jj| _dS )zLoads the optimizer state.

        Arguments:
            state_dict: optimizer state. Should be an object returned
                from a call to :meth:`state_dict`.
        r-   r   )r   r   r   N)r.   r
   load_state_dictr   r   r   )r   r/   r0   r1   r2   r   r   r4   b   s   zLookahead.load_state_dictc                 C   s   | j   dS )z>Clears the gradients of all optimized :class:`torch.Tensor` s.N)r   	zero_grad)r   r   r   r   r5   u   s   zLookahead.zero_gradc                 C   sZ   | j  }| jjd }|d7 }|d| j7 }|d| j7 }||7 }|d7 }|d7 }|S )Nz (
zk: {}
z
alpha: {}
))r   __repr__r3   __name__r   r   r   )r   base_strformat_stringr   r   r   r8   y   s   
zLookahead.__repr__)r   r   )N)r   N)r9   
__module____qualname____doc__r   intfloatr   r   strr   r)   r   r   r+   r	   r/   r4   r5   r8   __classcell__r   r   r2   r   r
      s$    


r
   )collectionsr   typingr   r   r   torch.optim.optimizerr   typesr   r   r	   __all__r
   r   r   r   r   <module>   s    