
    BVh                      D   d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddl	m
Z
 ddl	mZ dd	l	mZ dd
l	mZ ddl	mZ ddlmZ ddZd Z G d dej&                        Z G d de      Z G d de      Z G d dej.                        Z G d dej.                        Zy)z6Contains testing utilities related to mixed precision.    )dtypes)ops)tensor_conversion)regularizers)
base_layer)	array_ops)	check_opscondcustom_gradient)math_ops)nestNc                 H     t         j                    fd       f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                 F     t        j                           fd} |fS )z8Function that asserts it's gradient has a certain value.c                    r&| j                   k(  sJ dd| j                          t        j                  | j                   d      }t        j                  g      5  t        j                  | |      }ddd       t        j                  g      5  t        j                  |       } ddd       | S # 1 sw Y   ?xY w# 1 sw Y   | S xY w)z@Gradient function that asserts the gradient has a certain value.zdx.dtype should be z	 but is: expected_gradient)dtypenameN)	r   r   "convert_to_tensor_v2_with_dispatchr   control_dependenciesr	   assert_equalr   identity)dxexpected_tensor	assert_opexpected_dtyper   xs      a/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/keras/mixed_precision/test_util.pygradzScreate_identity_with_grad_check_fn.<locals>._identity_with_grad_check.<locals>.grad3   s    	xx>) 	M2@"((K	M))LL
2882Eo ##QC( @**2?	@##YK0 $#$i	@ @$is   "B7C7C Cr   r   )r   r    r   r   s   ` r   _identity_with_grad_checkzEcreate_identity_with_grad_check_fn.<locals>._identity_with_grad_check/   s%     	1A  d7N    c                      |       S N )r   r"   s    r   identity_with_grad_checkzDcreate_identity_with_grad_check_fn.<locals>.identity_with_grad_checkF   s    $Q''r#   r   )r   r   r'   r"   s   `` @r   "create_identity_with_grad_check_fnr(      s(    " "" #,(	!!r#   c                 D     t         j                    fd       fd}|S )ad  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                 @    t        j                  |       } fd}| |fS )z@Function whose gradient is NaN iff `have_nan_gradients` is True.c                 @     t        j                    fd fd      S )Nc                        t        d      z  S )NNaN)floatr   s   r   <lambda>zkcreate_identity_with_nan_gradients_fn.<locals>._identity_with_nan_gradients.<locals>.grad.<locals>.<lambda>b   s    "uU|# r#   c                       S r%   r&   r/   s   r   r0   zkcreate_identity_with_nan_gradients_fn.<locals>._identity_with_nan_gradients.<locals>.grad.<locals>.<lambda>c   s    " r#   r
   )r   have_nan_gradientss   `r   r    zYcreate_identity_with_nan_gradients_fn.<locals>._identity_with_nan_gradients.<locals>.grad_   s    YY

#
 r#   r!   )r   r    r2   s     r   _identity_with_nan_gradientszKcreate_identity_with_nan_gradients_fn.<locals>._identity_with_nan_gradients[   s%     	1A d7Nr#   c                      |       S r%   r&   )r   r3   s    r   identity_with_nan_gradientszJcreate_identity_with_nan_gradients_fn.<locals>.identity_with_nan_gradientsh   s    '**r#   r   )r2   r5   r3   s   ` @r   %create_identity_with_nan_gradients_fnr6   K   s(      ""	 #	+	$$r#   c                   *     e Zd ZdZd fd	Zd Z xZS )AssertTypeLayerz5A layer which asserts it's inputs are a certain type.c                 |    |rt        j                  |      j                  nd | _        t	        t
        |   di | y )Nr&   )r   as_dtyper   _assert_typesuperr8   __init__)selfassert_typekwargs	__class__s      r   r=   zAssertTypeLayer.__init__p   s4    >I5::" 		/4)3F3r#   c                     | j                   rkt        j                  |      }|D ]P  }|j                  j                  | j                   k(  r'J d|j                  j
                  d| j                           yy)zEAsserts `inputs` are of the correct type. Should be called in call().zInput tensor has type z" which does not match assert type N)r;   r   flattenr   
base_dtyper   )r>   inputsinputs_flattenedinps       r   assert_input_typesz"AssertTypeLayer.assert_input_typesu   sk    f-! 1#yy##t'8'88 	1YY^^T..0	181 r#   r%   )__name__
__module____qualname____doc__r=   rH   __classcell__rA   s   @r   r8   r8   m   s    =4
1r#   r8   c                   H     e Zd ZdZ	 	 	 	 d fd	Zd Zd Zd Z fdZ xZ	S )MultiplyLayerz8A layer which multiplies its input by a scalar variable.c                 L   || _         t        |t              r$t        j                  |t                     | _         || _        t        |t              r$t        j                  |t                     | _        || _        || _        t        t        | .  dd| j                  i| y)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<   rP   r=   )r>   regularizerrS   use_operatorvar_namer@   rA   s         r   r=   zMultiplyLayer.__init__   s    $ $D+t$&22;BI)Md!5D&-#/#;#;
wy$:d  &DDN	-' C!77C;ACr#   c                 n    | j                  | j                  dd| j                        | _        d| _        y )Nr&   ones)initializerr\   T)
add_weightr[   rT   vbuilt)r>   _s     r   buildzMultiplyLayer.build   s2    __D<M<M  ODFDJr#   c                 \    | j                  |       | j                  || j                        S r%   )rH   	_multiplyrc   r>   rE   s     r   callzMultiplyLayer.call   s%    F#>>&$&&))r#   c                 P    | j                   r||z  S t        j                  ||      S r%   )rZ   r   multiply)r>   r   ys      r   rh   zMultiplyLayer._multiply   s'    Ulq!$$r#   c                    t         t        |          }t        j                  | j
                        |d<   t        j                  | j                        |d<   | j                  |d<   | j                  |d<   | j                  |d<   |S )Nr\   rS   r]   r^   r?   )
r<   rP   
get_configr   	serializerT   rY   rZ   r[   r;   )r>   configrA   s     r   ro   zMultiplyLayer.get_config   s    =$24F(2243D3DEF=%1%;%;""&$F!"!//F>F: --F=Mr#   )NNFrc   )
rI   rJ   rK   rL   r=   rf   rj   rh   ro   rM   rN   s   @r   rP   rP      s4    @  $(!	C@
*% r#   rP   c                       e Zd ZdZd Zd Zy)MultiplyLayerWithoutAutoCastz:Same as MultiplyLayer, but does not use AutoCastVariables.c                     | j                   }|dv rd}| j                  ddd|d| j                        | _        d| _        y )	N)float16bfloat16float32rc   r&   r`   F)ra   r   experimental_autocastr\   T)r   rb   rT   rc   rd   )r>   re   r   s      r   rf   z"MultiplyLayerWithoutAutoCast.build   sN    JJE''e__R#%%  'DF DJr#   c                    | j                  |       | j                  j                  t        j                  t        j
                  fv sJ | j                  |t        j                  | j                  |j                              S r%   )	rH   rc   r   r   rw   float64rh   r   castri   s     r   rj   z!MultiplyLayerWithoutAutoCast.call   sW    F#66<<FNNFNN;;;;>>&(--"EFFr#   N)rI   rJ   rK   rL   rf   rj   r&   r#   r   rs   rs      s    B
Gr#   rs   c                       e Zd Zd Zd Zy)IdentityRegularizerc                 j    |j                   t        j                  k(  sJ t        j                  |      S r%   )r   r   rw   r   r   r>   r   s     r   __call__zIdentityRegularizer.__call__   s)    77fnn$$$a  r#   c                     i S r%   r&   r>   s    r   ro   zIdentityRegularizer.get_config       Ir#   NrI   rJ   rK   r   ro   r&   r#   r   r}   r}      s    !r#   r}   c                       e Zd Zd Zd Zy)ReduceSumRegularizerc                 ,    t        j                  |      S r%   )r   
reduce_sumr   s     r   r   zReduceSumRegularizer.__call__   s    q!!r#   c                     i S r%   r&   r   s    r   ro   zReduceSumRegularizer.get_config   r   r#   Nr   r&   r#   r   r   r      s    "r#   r   r%   )rL   tensorflow.python.frameworkr   r   r   tensorflow.python.kerasr   tensorflow.python.keras.enginer   tensorflow.python.opsr   r	   r   r   r   tensorflow.python.utilr   r(   r6   Layerr8   rP   rs   Regularizerr}   r   r&   r#   r   <module>r      s    = . + 9 0 5 + + & 1 * '*"Z%D1j&& 1$:O :zG= G*,22 <33 r#   