
    BVh,                     *   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  G d d      Z G d de      Z G d de      Z G d de      Z G d de      Z G d de      ZeZeZeZeZeZeZeZeZd ZddZd Zy)z@Constraints: functions that impose constraints on weight values.    )tensor_shape)backend)deserialize_keras_objectserialize_keras_object)	array_ops)array_ops_stack)math_ops)
while_loop)doc_controlsc                       e Zd ZdZd Zd Zy)
ConstraintaK  Base class for weight constraints.

  A `Constraint` instance works like a stateless function.
  Users who subclass this
  class should override the `__call__` method, which takes a single
  weight parameter and return a projected version of that parameter
  (e.g. normalized or clipped). Constraints can be used with various Keras
  layers via the `kernel_constraint` or `bias_constraint` arguments.

  Here's a simple example of a non-negative weight constraint:

  >>> class NonNegative(tf.keras.constraints.Constraint):
  ...
  ...  def __call__(self, w):
  ...    return w * tf.cast(tf.math.greater_equal(w, 0.), w.dtype)

  >>> weight = tf.constant((-1.0, 1.0))
  >>> NonNegative()(weight)
  <tf.Tensor: shape=(2,), dtype=float32, numpy=array([0.,  1.], dtype=float32)>

  >>> tf.keras.layers.Dense(4, kernel_constraint=NonNegative())
  c                     |S )aG  Applies the constraint to the input weight variable.

    By default, the inputs weight variable is not modified.
    Users should override this method to implement their own projection
    function.

    Args:
      w: Input weight variable.

    Returns:
      Projected variable (by default, returns unmodified inputs).
     selfws     S/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/keras/constraints.py__call__zConstraint.__call__6   s	     H    c                     i S )a  Returns a Python dict of the object config.

    A constraint config is a Python dictionary (JSON-serializable) that can
    be used to reinstantiate the same object.

    Returns:
      Python dict containing the configuration of the constraint object.
    r   r   s    r   
get_configzConstraint.get_configE   s	     Ir   N)__name__
__module____qualname____doc__r   r   r   r   r   r   r      s    .	r   r   c                   `    e Zd ZdZddZej                  d        Zej                  d        Zy)MaxNorma/  MaxNorm weight constraint.

  Constrains the weights incident to each hidden unit
  to have a norm less than or equal to a desired value.

  Also available via the shortcut function `tf.keras.constraints.max_norm`.

  Args:
    max_value: the maximum norm value for the incoming weights.
    axis: integer, axis along which to calculate weight norms.
      For instance, in a `Dense` layer the weight matrix
      has shape `(input_dim, output_dim)`,
      set `axis` to `0` to constrain each weight vector
      of length `(input_dim,)`.
      In a `Conv2D` layer with `data_format="channels_last"`,
      the weight tensor has shape
      `(rows, cols, input_depth, output_depth)`,
      set `axis` to `[0, 1, 2]`
      to constrain the weights of each filter tensor of size
      `(rows, cols, input_depth)`.

  c                      || _         || _        y N	max_valueaxis)r   r#   r$   s      r   __init__zMaxNorm.__init__i   s    DNDIr   c                    t        j                  t        j                  t        j                  |      | j
                  d            }t        j                  |d| j                        }||t        j                         |z   z  z  S )NTr$   keepdimsr   )	r   sqrtr
   
reduce_sumsquarer$   clipr#   epsilonr   r   normsdesireds       r   r   zMaxNorm.__call__m   sb    LLHOOA.TYYNPEll5!T^^4G7??,u4566r   c                 4    | j                   | j                  dS )Nr"   r"   r   s    r   r   zMaxNorm.get_configt   s    ;;r   N)   r   	r   r   r   r   r%   r   do_not_generate_docsr   r   r   r   r   r   r   Q   s@    . $$7 %7 $$< %<r   r   c                       e Zd ZdZd Zy)NonNegzyConstrains the weights to be non-negative.

  Also available via the shortcut function `tf.keras.constraints.non_neg`.
  c                     |t        j                  t        j                  |d      t        j                               z  S )N        )r
   castgreater_equalr   floatxr   s     r   r   zNonNeg.__call__   s,    x}}X33Ar:GNN<LMMMr   N)r   r   r   r   r   r   r   r   r6   r6   y   s    
Nr   r6   c                   `    e Zd ZdZddZej                  d        Zej                  d        Zy)UnitNorma  Constrains the weights incident to each hidden unit to have unit norm.

  Also available via the shortcut function `tf.keras.constraints.unit_norm`.

  Args:
    axis: integer, axis along which to calculate weight norms.
      For instance, in a `Dense` layer the weight matrix
      has shape `(input_dim, output_dim)`,
      set `axis` to `0` to constrain each weight vector
      of length `(input_dim,)`.
      In a `Conv2D` layer with `data_format="channels_last"`,
      the weight tensor has shape
      `(rows, cols, input_depth, output_depth)`,
      set `axis` to `[0, 1, 2]`
      to constrain the weights of each filter tensor of size
      `(rows, cols, input_depth)`.
  c                     || _         y r!   r$   )r   r$   s     r   r%   zUnitNorm.__init__   s	    DIr   c           	          |t        j                         t        j                  t        j                  t        j
                  |      | j                  d            z   z  S )NTr'   )r   r-   r)   r
   r*   r+   r$   r   s     r   r   zUnitNorm.__call__   sP    GLL"TCD 	DE Er   c                     d| j                   iS )Nr$   r?   r   s    r   r   zUnitNorm.get_config   s    DIIr   N)r   r3   r   r   r   r=   r=      sB    $ $$E %E $$ %r   r=   c                   `    e Zd ZdZddZej                  d        Zej                  d        Zy)
MinMaxNorma  MinMaxNorm weight constraint.

  Constrains the weights incident to each hidden unit
  to have the norm between a lower bound and an upper bound.

  Also available via the shortcut function `tf.keras.constraints.min_max_norm`.

  Args:
    min_value: the minimum norm for the incoming weights.
    max_value: the maximum norm for the incoming weights.
    rate: rate for enforcing the constraint: weights will be
      rescaled to yield
      `(1 - rate) * norm + rate * norm.clip(min_value, max_value)`.
      Effectively, this means that rate=1.0 stands for strict
      enforcement of the constraint, while rate<1.0 means that
      weights will be rescaled at each step to slowly move
      towards a value inside the desired interval.
    axis: integer, axis along which to calculate weight norms.
      For instance, in a `Dense` layer the weight matrix
      has shape `(input_dim, output_dim)`,
      set `axis` to `0` to constrain each weight vector
      of length `(input_dim,)`.
      In a `Conv2D` layer with `data_format="channels_last"`,
      the weight tensor has shape
      `(rows, cols, input_depth, output_depth)`,
      set `axis` to `[0, 1, 2]`
      to constrain the weights of each filter tensor of size
      `(rows, cols, input_depth)`.
  c                 <    || _         || _        || _        || _        y r!   	min_valuer#   rater$   )r   rF   r#   rG   r$   s        r   r%   zMinMaxNorm.__init__   s    DNDNDIDIr   c                 b   t        j                  t        j                  t        j                  |      | j
                  d            }| j                  t        j                  || j                  | j                        z  d| j                  z
  |z  z   }||t        j                         |z   z  z  S )NTr'      )r   r)   r
   r*   r+   r$   rG   r,   rF   r#   r-   r.   s       r   r   zMinMaxNorm.__call__   s    LLHOOA.TYYNPE 			GLLGG	
TYY%	   7??,u4566r   c                 `    | j                   | j                  | j                  | j                  dS )NrE   rE   r   s    r   r   zMinMaxNorm.get_config   s*     ^^^^					 r   N)r8         ?rK   r   r3   r   r   r   rC   rC      s@    < $$7 %7 $$ %r   rC   c                   :    e Zd ZdZej
                  d        Zd Zy)RadialConstraintas  Constrains `Conv2D` kernel weights to be the same for each radius.

  Also available via the shortcut function
  `tf.keras.constraints.radial_constraint`.

  For example, the desired output for the following 4-by-4 kernel:

  ```
      kernel = [[v_00, v_01, v_02, v_03],
                [v_10, v_11, v_12, v_13],
                [v_20, v_21, v_22, v_23],
                [v_30, v_31, v_32, v_33]]
  ```

  is this::

  ```
      kernel = [[v_11, v_11, v_11, v_11],
                [v_11, v_33, v_33, v_11],
                [v_11, v_33, v_33, v_11],
                [v_11, v_11, v_11, v_11]]
  ```

  This constraint can be applied to any `Conv2D` layer version, including
  `Conv2DTranspose` and `SeparableConv2D`, and with either `"channels_last"` or
  `"channels_first"` data format. The method assumes the weight tensor is of
  shape `(rows, cols, input_depth, output_depth)`.
  c           	         |j                   }|j                  |j                  dk7  rt        d|z        |\  }}}}t        j                  |||||z  f      }t        j
                  | j                  t        j                  t        j                  |d      d            }t        j                  t        j                  t        j                  |d      d      ||||f      S )N   z8The weight tensor must be of rank 4, but is of shape: %sr?   r   )
shaperank
ValueErrorr   reshapemap_fn_kernel_constraintstackr	   unstack)r   r   w_shapeheightwidthchannelskernelss          r   r   zRadialConstraint.__call__   s    ggG||w||q0
Dw
NP P (/$FE8WFE8g+=>?A 	o--ab9B	DA ??o--aa8rB	'*, ,r   c           
      V  	 t        j                  ddgddggd      t        j                        d   }t        j                  |dz  d      	t        j                  t        j                  t        j                  |d      d      	fd	fd      }t        j                  t        j                  t        j                  |d      d      d	 d
       }	fd}	fd}t        j                  ||||g|j                         t        j                  ddg      g      \  }}|S )zCRadially constraints a kernel with shape (height, width, channels).rI   int32dtyper   r2   boolc                  &     dz
  dz
  f   S )NrI   r   kernelstarts   r   <lambda>z5RadialConstraint._kernel_constraint.<locals>.<lambda>  s!    uqy	%78 r   c                  j     dz
  dz
  f   t        j                  d j                        z   S )NrI   )r2   r2   r`   )r   zerosra   rd   s   r   rg   z5RadialConstraint._kernel_constraint.<locals>.<lambda>  s:    uqy	%787==&,,<( ( r   c                  0    t        j                  dd      S )Nr   r_   r`   r   constantr   r   r   rg   z5RadialConstraint._kernel_constraint.<locals>.<lambda>        '2 r   c                  0    t        j                  dd      S )NrI   r_   r`   rk   r   r   r   rg   z5RadialConstraint._kernel_constraint.<locals>.<lambda>  rm   r   c                 0    t        j                  |       S r!   )r   less)indexargsrf   s     r   rg   z5RadialConstraint._kernel_constraint.<locals>.<lambda>  s    7<<u+E r   c           	      T    | dz   t        j                  || z   | z   f         fS )NrI   )constant_values)r   pad)iarrayre   paddingrf   s     r   body_fnz4RadialConstraint._kernel_constraint.<locals>.body_fn  s:    UIMM

 EAI!568 8 8r   N)shape_invariants)r   rl   rQ   r9   switchr
   floormodr   	get_shaper   TensorShape)
r   re   kernel_shape
kernel_newrq   while_conditionry   _rx   rf   s
    `      @@r   rV   z#RadialConstraint._kernel_constraint  s   AA/w?G==(+LLL)73EX&&|Q7@8	()J
 NNX&&|Q7@224E FO8 ))%$OO$$dD\2
MAz r   N)r   r   r   r   r   r4   r   rV   r   r   r   rM   rM      s&    : $$, %,"r   rM   c                     t        |       S r!   r   )
constraints    r   	serializer   =  s    	
	++r   Nc                 0    t        | t               |d      S )Nr   )module_objectscustom_objectsprintable_module_name)r   globals)configr   s     r   deserializer   A  s    	!Y#(	
* *r   c                     | y t        | t              rt        |       S t        | t              rt        |       i d}t        |      S t	        |       r| S t        dt        |       z         )N)
class_namer   z+Could not interpret constraint identifier: )
isinstancedictr   strcallablerS   )
identifierr   s     r   getr   I  sm    
D!z""*c"
Or:Fv

B_% & &r   r!   ) r   tensorflow.python.frameworkr   tensorflow.python.kerasr   +tensorflow.python.keras.utils.generic_utilsr   r   tensorflow.python.opsr   r	   r
   r   tensorflow.tools.docsr   r   r   r6   r=   rC   rM   max_normnon_neg	unit_normmin_max_normradial_constraintmaxnormnonnegunitnormr   r   r   r   r   r   <module>r      s   " G 4 + P N + 1 * , .0 0f%<j %<PNZ Nz D5 5pOz Oh 
	$  	,*&r   