o
    @T¼iH  ã                   @   s2   d dl Z d dlZd dlmZ G dd„ dejƒZdS )é    Nc                       sŽ   e Zd ZdZ					ddeded	ed
edededdf‡ fdd„Zdd„ Zdej	fdd„Z
dej	fdd„Zdefdd„Zdefdd„Z‡  ZS )ÚHardConcretea“  A HarcConcrete module.
    Use this module to create a mask of size N, which you can
    then use to perform L0 regularization.

    To obtain a mask, simply run a forward pass through the module
    with no input data. The mask is sampled in training mode, and
    fixed during evaluation mode, e.g.:

    >>> module = HardConcrete(n_in=100)
    >>> mask = module()
    >>> norm = module.l0_norm()
    ç      à?ç{®Gáz„?çUUUUUUå?çš™™™™™¹?çíµ ÷Æ°>Ún_inÚ	init_meanÚinit_stdÚtemperatureÚstretchÚepsÚreturnNc                    s|   t ƒ  ¡  || _| | _d| | _t t |¡¡| _	|| _
|| _|| _| j
 t | j | j ¡ | _|| _d| _|  ¡  dS )aÂ  Initialize the HardConcrete module.
        Parameters
        ----------
        n_in : int
            The number of hard concrete variables in this mask.
        init_mean : float, optional
            Initial drop rate for hard concrete parameter,
            by default 0.5.,
        init_std: float, optional
            Used to initialize the hard concrete parameters,
            by default 0.01.
        temperature : float, optional
            Temperature used to control the sharpness of the
            distribution, by default 1.0
        stretch : float, optional
            Stretch the sampled value from [0, 1] to the interval
            [-stretch, 1 + stretch], by default 0.1.
        ç      ð?N)ÚsuperÚ__init__r   Úlimit_lÚlimit_rÚnnÚ	ParameterÚtorchÚzerosÚ	log_alphaÚbetar	   r
   ÚmathÚlogÚbiasr   Úcompiled_maskÚreset_parameters)Úselfr   r	   r
   r   r   r   ©Ú	__class__© úQ/home/ubuntu/.local/lib/python3.10/site-packages/linacodec/module/hardconcrete.pyr      s   

zHardConcrete.__init__c                 C   s8   d| _ t d| j ¡t | j¡ }| jj || j¡ dS )z$Reset the parameters of this module.Né   )r   r   r   r	   r   ÚdataÚnormal_r
   )r   Úmeanr"   r"   r#   r   ?   s   zHardConcrete.reset_parametersc                 C   s   | j | j  ¡  ¡ S )zŠCompute the expected L0 norm of this mask.
        Returns
        -------
        torch.Tensor
            The expected L0 norm.
        )r   r   ÚsigmoidÚsum©r   r"   r"   r#   Úl0_normE   s   zHardConcrete.l0_normc           	      C   sÜ   | j r;d| _| j | j¡ | jd| j ¡}t t 	|d|  ¡| j | j
 ¡}|| j| j  | j }|jddd}|S | jdu ri| j|  ¡  ¡  }t|ƒ}t | j| j
 d ¡}tj||dd\}}d||< || _| j}|S )	z~Sample a hard concrete mask.
        Returns
        -------
        torch.Tensor
            The sampled binary mask
        Nr$   g        r   )ÚminÚmaxgš™™™™™é?F)ÚkÚlargest)Útrainingr   r   Únewr   Úuniform_r   r   r(   r   r   r   r   Úclampr+   ÚitemÚroundÚtopk)	r   ÚuÚsÚmaskÚexpected_num_zerosÚ	num_zerosÚ	soft_maskÚ_Úindicesr"   r"   r#   ÚforwardN   s    $
ózHardConcrete.forwardc                 C   s
   t | jƒS )N)Ústrr   r*   r"   r"   r#   Ú
extra_repro   s   
zHardConcrete.extra_reprc                 C   s   d  | jj|  ¡ ¡S )Nz{}({}))Úformatr!   Ú__name__rA   r*   r"   r"   r#   Ú__repr__r   s   zHardConcrete.__repr__)r   r   r   r   r   )rC   Ú
__module__Ú__qualname__Ú__doc__ÚintÚfloatr   r   r   ÚTensorr+   r?   r@   rA   rD   Ú__classcell__r"   r"   r    r#   r      s6    ùþýüûúùø*	!r   )r   r   Útorch.nnr   ÚModuler   r"   r"   r"   r#   Ú<module>   s    