U
    •Ê¹jG  ã                   @   sÐ   d dl Z d dlmZmZmZmZmZmZmZ d dl	Z	d dl	m
Z
mZ d dlmZmZ ee	j
ee	j
 f ZdddgZdeeeeee e	j
d
œdd„Zdeeeeee e	j
d
œdd„Zdeeee ddœdd„ZdS )é    N)ÚUnionÚIterableÚListÚDictÚTupleÚOptionalÚcast)ÚTensorÚinf)Ú"_group_tensors_by_device_and_dtypeÚ_has_foreach_supportÚclip_grad_norm_Úclip_grad_normÚclip_grad_value_ç       @F)Ú
parametersÚmax_normÚ	norm_typeÚerror_if_nonfiniteÚforeachÚreturnc                    s  t | tjƒr| g} dd„ | D ƒ}t|ƒ}tˆƒ‰t|ƒdkrFt d¡S |d j‰ tdd„ |D ƒgƒ}ˆtkr¤‡ fdd„|D ƒ}t|ƒdkr’|d nt 	t 
|¡¡}n g }| ¡ D ]p\\}	}
\\}}
|dksÎ|rît||	d	�rî| t |ˆ¡¡ q°|�rtd
|	j› d�ƒ‚q°| ‡fdd„|D ƒ¡ q°tj t 
‡ fdd„|D ƒ¡ˆ¡}|�rpt | ¡ | ¡ ¡�rptdˆ› d�ƒ‚||d  }tj|dd�}| ¡ D ]„\\}	}
\\}}
|dk�s´|�rÖt||	d	��rÖt || |	¡¡ n>|�rðtd
|	j› d�ƒ‚n$| |	¡}|D ]}| ¡  |¡ �qþ�q’|S )aD  Clips gradient norm of an iterable of parameters.

    The norm is computed over all gradients together, as if they were
    concatenated into a single vector. Gradients are modified in-place.

    Args:
        parameters (Iterable[Tensor] or Tensor): an iterable of Tensors or a
            single Tensor that will have gradients normalized
        max_norm (float): max norm of the gradients
        norm_type (float): type of the used p-norm. Can be ``'inf'`` for
            infinity norm.
        error_if_nonfinite (bool): if True, an error is thrown if the total
            norm of the gradients from :attr:`parameters` is ``nan``,
            ``inf``, or ``-inf``. Default: False (will switch to True in the future)
        foreach (bool): use the faster foreach-based implementation.
            If ``None``, use the foreach implementation for CUDA and CPU native tensors and silently
            fall back to the slow implementation for other device types.
            Default: ``None``

    Returns:
        Total norm of the parameter gradients (viewed as a single vector).
    c                 S   s   g | ]}|j d k	r|j ‘qS ©N©Úgrad©Ú.0Úp© r   úW/var/www/html/bwave/python/venv/lib/python3.8/site-packages/torch/nn/utils/clip_grad.pyÚ
<listcomp>'   s     
 z#clip_grad_norm_.<locals>.<listcomp>r   g        c                 S   s   g | ]}|  ¡ ‘qS r   )Údetach©r   Úgr   r   r   r   .   s     c                    s$   g | ]}t j | ¡ t¡ ˆ ¡‘qS r   )ÚtorchÚlinalgÚvector_normr    r
   Útor!   ©Úfirst_devicer   r   r   1   s     é   N©Údeviceú:foreach=True was passed, but can't use the foreach API on ú tensorsc                    s   g | ]}t j |ˆ ¡‘qS r   )r#   r$   r%   r!   )r   r   r   r   ;   s     c                    s   g | ]}|  ˆ ¡‘qS r   )r&   )r   Znormr'   r   r   r   =   s     zThe total norm of order z´ for gradients from `parameters` is non-finite, so it cannot be clipped. To disable this error and scale the gradients by the non-finite norm anyway, set `error_if_nonfinite=False`g�íµ ÷Æ°>g      ð?)Úmax)Ú
isinstancer#   r	   ÚfloatÚlenZtensorr+   r   r
   r.   ÚstackÚitemsr   ÚextendZ_foreach_normÚRuntimeErrorÚtyper$   r%   Ú
logical_orÚisnanÚisinfÚclampZ_foreach_mul_r&   r    Zmul_)r   r   r   r   r   ÚgradsÚgrouped_gradsZnormsZ
total_normr+   Ú_Z	clip_coefZclip_coef_clampedZclip_coef_clamped_devicer"   r   )r(   r   r   r      sH    

ÿ&"
ÿ
c                 C   s   t jddd� t| ||||ƒS )zªClips gradient norm of an iterable of parameters.

    .. warning::
        This method is now deprecated in favor of
        :func:`torch.nn.utils.clip_grad_norm_`.
    z[torch.nn.utils.clip_grad_norm is now deprecated in favor of torch.nn.utils.clip_grad_norm_.é   )Ú
stacklevel)ÚwarningsÚwarnr   )r   r   r   r   r   r   r   r   r   W   s    	ÿ)r   Ú
clip_valuer   r   c              
   C   sð   t | tjƒr| g} t|ƒ}dd„ | D ƒ}t|gƒ}| ¡ D ]°\\}}\\}}|dksX|ržtttt |ƒ|d�ržt 	ttt |ƒ| ¡ t 
ttt |ƒ|¡ q:|r¶td|j› d�ƒ‚q:t ¡ �& |D ]}tt|ƒj| |d� qÄW 5 Q R X q:dS )aÐ  Clips gradient of an iterable of parameters at specified value.

    Gradients are modified in-place.

    Args:
        parameters (Iterable[Tensor] or Tensor): an iterable of Tensors or a
            single Tensor that will have gradients normalized
        clip_value (float): maximum allowed value of the gradients.
            The gradients are clipped in the range
            :math:`\left[\text{-clip\_value}, \text{clip\_value}\right]`
        foreach (bool): use the faster foreach-based implementation
            If ``None``, use the foreach implementation for CUDA and CPU native tensors and
            silently fall back to the slow implementation for other device types.
            Default: ``None``
    c                 S   s   g | ]}|j d k	r|j ‘qS r   r   r   r   r   r   r   y   s     
 z$clip_grad_value_.<locals>.<listcomp>Nr*   r,   r-   )Úminr.   )r/   r#   r	   r0   r   r3   r   r   r   Z_foreach_clamp_min_Z_foreach_clamp_max_r5   r6   Zno_gradZclamp_)r   rB   r   r;   r<   r+   r=   r   r   r   r   r   e   s    
"
)r   FN)r   FN)N)r@   Útypingr   r   r   r   r   r   r   r#   r	   r
   Ztorch.utils._foreach_utilsr   r   Z_tensor_or_tensorsÚ__all__r0   Úboolr   r   r   r   r   r   r   Ú<module>   s:   $
    þ    þL    þ    þ