o
    i e?!                     @   s   d Z ddlm  mZ ddlmZ ddlmZ dddZ	dd Z
G d	d
 d
ejZG dd deZG dd deZG dd dejZG dd dejZdS )z6Contains testing utilities related to mixed precision.    N)regularizers)
base_layerc                    s$   t jfdd  fdd}|S )a  Returns a function that asserts it's gradient has a certain value.

    This serves as a hook to assert intermediate gradients have a certain value.
    This returns an identity function. The identity's gradient function is also
    the identity function, except it asserts that the gradient equals
    `expected_gradient` and has dtype `expected_dtype`.

    Args:
      expected_gradient: The gradient function asserts that the gradient is this
        value.
      expected_dtype: The gradient function asserts the gradient has this dtype.

    Returns:
      An identity function whose gradient function asserts the gradient has a
      certain value.
    c                    s"   t    fdd} |fS )z8Function that asserts it's gradient has a certain value.c                    s    r| j  ksJ d  d| j  tj| j dd}tg tjj| |}W d   n1 s4w   Y  t|g t| } W d   | S 1 sPw   Y  | S )zLGradient function that asserts the gradient has a certain
            value.zdx.dtype should be z	 but is: expected_gradient)dtypenameN)r   tfconvert_to_tensorcontrol_dependenciescompatv1assert_equalidentity)dxexpected_tensor	assert_op)expected_dtyper   x R/var/www/myenv/lib/python3.10/site-packages/keras/src/mixed_precision/test_util.pygrad.   s    
zScreate_identity_with_grad_check_fn.<locals>._identity_with_grad_check.<locals>.gradr   r   r   r   )r   r   r   r   _identity_with_grad_check)   s   
zEcreate_identity_with_grad_check_fn.<locals>._identity_with_grad_checkc                        | S Nr   r   )r   r   r   identity_with_grad_checkE      zDcreate_identity_with_grad_check_fn.<locals>.identity_with_grad_checkr   custom_gradient)r   r   r   r   )r   r   r   r   "create_identity_with_grad_check_fn   s   r    c                    s"   t jfdd  fdd}|S )a{  Returns a function that optionally has NaN gradients.

    This serves as a hook to introduce NaN gradients to a model. This returns an
    identity function. The identity's gradient function will check if the
    boolean tensor `have_nan_gradients` is True. If so, the gradient will be
    NaN.  Otherwise, the gradient will also be the identity.

    Args:
      have_nan_gradients: A scalar boolean tensor. If True, gradients will be
        NaN. Otherwise, the gradient function is the identity function.

    Returns:
      An identity function whose gradient function will return NaNs, if
      `have_nan_gradients` is True.
    c                    s   t | }  fdd}| |fS )z@Function whose gradient is NaN iff `have_nan_gradients` is True.c                    s   t  fdd fddS )Nc                      s    t d S )NNaN)floatr   r   r   r   <lambda>c   s    zkcreate_identity_with_nan_gradients_fn.<locals>._identity_with_nan_gradients.<locals>.grad.<locals>.<lambda>c                      s    S r   r   r   r#   r   r   r$   c   s    )r   condr#   have_nan_gradientsr#   r   r   a   s   zYcreate_identity_with_nan_gradients_fn.<locals>._identity_with_nan_gradients.<locals>.gradr   r   r&   r   r   _identity_with_nan_gradients\   s   
zKcreate_identity_with_nan_gradients_fn.<locals>._identity_with_nan_gradientsc                    r   r   r   r   )r(   r   r   identity_with_nan_gradientsj   r   zJcreate_identity_with_nan_gradients_fn.<locals>.identity_with_nan_gradientsr   )r'   r)   r   )r(   r'   r   %create_identity_with_nan_gradients_fnK   s   r*   c                       s*   e Zd ZdZd fdd	Zdd Z  ZS )AssertTypeLayerz5A layer which asserts it's inputs are a certain type.Nc                    s,   |rt |jnd | _t jdi | d S )Nr   )r   as_dtyper   _assert_typesuper__init__)selfassert_typekwargs	__class__r   r   r/   s   s   zAssertTypeLayer.__init__c                 C   sH   | j r tj|}|D ]}|jj| j ksJ d|jj| j f qdS dS )zMAsserts `inputs` are of the correct type. Should be called in
        call().z<Input tensor has type %s which does not match assert type %sN)r-   r   nestflattenr   
base_dtyper   )r0   inputsinputs_flattenedinpr   r   r   assert_input_typesy   s   z"AssertTypeLayer.assert_input_typesr   )__name__
__module____qualname____doc__r/   r;   __classcell__r   r   r3   r   r+   p   s    r+   c                       sN   e Zd ZdZ				d fdd	Zdd Zd	d
 Zdd Z fddZ  Z	S )MultiplyLayerz8A layer which multiplies its input by a scalar variable.NFvc                    sl   || _ t|trtj|t d| _ || _t|tr"tj|t d| _|| _|| _t	 j
dd| ji| dS )a"  Initializes the MultiplyLayer.

        Args:
          regularizer: The weight regularizer on the scalar variable.
          activity_regularizer: The activity regularizer.
          use_operator: If True, add using the * operator. If False, add using
            tf.multiply.
          var_name: The name of the variable. It can be useful to pass a name
            other than 'v', to test having the attribute name (self.v) being
            different from the variable name.
          **kwargs: Passed to AssertTypeLayer constructor.
        )custom_objectsactivity_regularizerNr   )_regularizer
isinstancedictr   deserializeglobals_activity_regularizer_use_operator	_var_namer.   r/   )r0   regularizerrD   use_operatorvar_namer2   r3   r   r   r/      s"   



zMultiplyLayer.__init__c                 C   s"   | j | jdd| jd| _d| _d S )Nr   ones)initializerrM   T)
add_weightrL   rE   rB   built)r0   _r   r   r   build   s   
zMultiplyLayer.buildc                 C   s   |  | | || jS r   )r;   	_multiplyrB   r0   r8   r   r   r   call   s   
zMultiplyLayer.callc                 C   s   | j r|| S t||S r   )rK   r   multiply)r0   r   yr   r   r   rV      s   zMultiplyLayer._multiplyc                    sL   t   }t| j|d< t| j|d< | j|d< | j|d< | j|d< |S )NrM   rD   rN   rO   r1   )	r.   
get_configr   	serializerE   rJ   rK   rL   r-   )r0   configr3   r   r   r[      s   



zMultiplyLayer.get_config)NNFrB   )
r<   r=   r>   r?   r/   rU   rX   rV   r[   r@   r   r   r3   r   rA      s    %	rA   c                   @   s    e Zd ZdZdd Zdd ZdS )MultiplyLayerWithoutAutoCastz:Same as MultiplyLayer, but does not use AutoCastVariables.c                 C   s6   | j }|dv r	d}| jddd|d| jd| _d| _d S )	N)float16bfloat16float32rB   r   rP   F)rQ   r   experimental_autocastrM   T)r   rR   rE   rB   rS   )r0   rT   r   r   r   r   rU      s   
z"MultiplyLayerWithoutAutoCast.buildc                 C   s:   |  | | jjtjtjfv sJ | |t| j|jS r   )r;   rB   r   r   ra   float64rV   castrW   r   r   r   rX      s   
z!MultiplyLayerWithoutAutoCast.callN)r<   r=   r>   r?   rU   rX   r   r   r   r   r^      s    r^   c                   @      e Zd Zdd Zdd ZdS )IdentityRegularizerc                 C   s   |j tjksJ t|S r   )r   r   ra   r   r0   r   r   r   r   __call__   s   
zIdentityRegularizer.__call__c                 C      i S r   r   r0   r   r   r   r[         zIdentityRegularizer.get_configNr<   r=   r>   rh   r[   r   r   r   r   rf      s    rf   c                   @   re   )ReduceSumRegularizerc                 C   s
   t |S r   )r   
reduce_sumrg   r   r   r   rh      s   
zReduceSumRegularizer.__call__c                 C   ri   r   r   rj   r   r   r   r[      rk   zReduceSumRegularizer.get_configNrl   r   r   r   r   rm      s    rm   r   )r?   tensorflow.compat.v2r
   v2r   	keras.srcr   keras.src.enginer   r    r*   Layerr+   rA   r^   Regularizerrf   rm   r   r   r   r   <module>   s   
4%G	