
    AVh                        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
 dd
lmZ ddlmZ ddlmZ 	 	 d4dZd5dZd6dZd7dZ edg      d8d       Z edg      d8d       Z edg      d9d       Z edg       edd      d7d              Z edg      d:d       Z edg      d:d       Z ed g      d;d!       Z ed"g      d;d#       Z ed$g      d;d%       Z ed&g      d;d'       Z ed(g      d;d)       Z ed*g      d;d+       Z  ed,g      d;d-       Z! ed.g      d;d/       Z" ed0g       ej                  d1d2      d:d3              Z#y)<zSVariables.

See the [Variables](https://www.tensorflow.org/guide/variables) guide.
    )ops)tensor_shape)	array_ops)gen_math_ops)gen_resource_variable_ops)gen_state_ops)
state_grad)*)deprecation)
deprecated)	tf_exportc                     |st        j                         } t        j                  | ||||      }|r|j	                  |        |S )z(Deprecated. Used variable_op_v2 instead.shapedtypename	containershared_name)r   unknown_shaper   variable	set_shape)r   r   r   r   r   r   rets          O/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/ops/state_ops.pyvariable_opr   &   sG     
&&(EU%d)2	M# MM%	*    c                 6    t        j                  | ||||      S )ap  Create a variable Operation.

  See also variables.Variable.

  Args:
    shape: The shape of the tensor managed by this variable
    dtype: The underlying type of the tensor values.
    name: optional name to use for the variable op.
    container: An optional string. Defaults to "".
      If non-empty, this variable is placed in the given container.
      Otherwise, a default container is used.
    shared_name: An optional string. Defaults to "".
      If non-empty, this variable is named in the given bucket
      with this shared_name. Otherwise, the node name is used instead.

  Returns:
    A variable tensor.
  r   )r   variable_v2r   s        r   variable_op_v2r   4   s&    & 
	"	"
 r   c                 $   t        j                  d| j                  j                  dz   | |g      5  t        j                  |      5 }t        j                  |       5  t        |      r| j                         j                         sJ d        || j                         j                         | j                  j                        }t        j                  |d      }t        j                  | ||      cddd       cddd       cddd       S t        j                  |d      }t        j                  | ||      cddd       cddd       cddd       S # 1 sw Y   nxY w	 ddd       n# 1 sw Y   nxY wddd       y# 1 sw Y   yxY w)aE  Initializes variable with "init".

  This op does the following:
  if init is a Tensor, v = init
  if callable(init): v = init(VariableShape(v), v.dtype)

  Args:
    v: Variable to initialize
    init: Tensor to assign to v,
      Or an object convertible to Tensor e.g. nparray,
      Or an Initializer that generates a tensor given the shape and type of v.
      An "Initializer" is a callable that returns a tensor that "v" should be
      set to. It will be called as init(shape, dtype).
    name: Optional name for the op.

  Returns:
    The operation that initializes v.
  N/zVariable shape unknown.valuer   init)r   
name_scopeopr   colocate_withcallable	get_shapeis_fully_definedas_listr   
base_dtypeconvert_to_tensorr   assign)vr#   r   scoper!   s        r   init_variabler0   O   sQ   & ~~dADDIIOaY7 ;		 ;Q ;D>//1
L3L
L1 q{{},,.0B0BC%''G<%%%aU;; ;; ;; ; &&t&9$%%aE:; ;; ;; ;; ; ;; ; ;; ; ;sT   FE1BE5	E1>	F.E?	E1	FE$ E1(	F1E:	6FFNc                     | j                   j                  rt        j                  | |      S | j	                  |      S )a<  Checks whether a tensor has been initialized.

  Outputs boolean scalar indicating whether the tensor has been initialized.

  Args:
    ref: A mutable `Tensor`.
      Should be from a `Variable` node. May be uninitialized.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` of type `bool`.
  refr   r"   )r   _is_ref_dtyper   is_variable_initializedis_initializedr2   s     r   r5   r5   r   s8     	YY00StDD					&&r   
assign_sub)v1c                     | j                   j                  rt        j                  | |||      S | j                  |      S )a;	  Update `ref` by subtracting `value` from it.

  This operation outputs `ref` after the update is done.
  This makes it easier to chain operations that need to use the reset value.
  Unlike `tf.math.subtract`, this op does not broadcast. `ref` and `value`
  must have the same shape.

  Args:
    ref: A mutable `Tensor`. Must be one of the following types: `float32`,
      `float64`, `int64`, `int32`, `uint8`, `uint16`, `int16`, `int8`,
      `complex64`, `complex128`, `qint8`, `quint8`, `qint32`, `half`. Should be
      from a `Variable` node.
    value: A `Tensor`. Must have the same shape and dtype as `ref`. The value to
      be subtracted to the variable.
    use_locking: An optional `bool`. Defaults to `False`. If True, the
      subtraction will be protected by a lock; otherwise the behavior is
      undefined, but may exhibit less contention.
    name: A name for the operation (optional).

  Returns:
    Same as `ref`.  Returned as a convenience for operations that want
    to use the new value after the variable has been updated.

  @compatibility(TF2)
  `tf.compat.v1.assign_sub` is mostly compatible with eager
  execution and `tf.function`.

  To switch to the native TF2 style, one could use method 'assign_sub' of
  `tf.Variable`:

  #### How to Map Arguments

  | TF1 Arg Name          | TF2 Arg Name    | Note                       |
  | :-------------------- | :-------------- | :------------------------- |
  | `ref`                 | `self`          | In `assign_sub()` method   |
  | `value`               | `value`         | In `assign_sub()` method   |
  | `use_locking`         | `use_locking`   | In `assign_sub()` method   |
  | `name`                | `name`          | In `assign_sub()` method   |
  | -                     | `read_value`    | Set to True to replicate   |
  :                       :                 : behavior (True is default) :


  #### Before & After Usage Example

  Before:

  >>> with tf.Graph().as_default():
  ...   with tf.compat.v1.Session() as sess:
  ...     a = tf.compat.v1.Variable(1, dtype=tf.int64)
  ...     sess.run(a.initializer)
  ...     update_op = tf.compat.v1.assign_sub(a, 1)
  ...     res_a = sess.run(update_op)
  ...     print(res_a)
  0

  After:

  >>> b = tf.Variable(1, dtype=tf.int64)
  >>> res_b = b.assign_sub(1)
  >>> res_b.numpy().item()
  0

  @end_compatibility
  use_lockingr   )r   r4   r   r7   r3   r!   r;   r   s       r   r7   r7      =    D 	YY##U$8 8		r   
assign_addc                     | j                   j                  rt        j                  | |||      S | j                  |      S )a'	  Update `ref` by adding `value` to it.

  This operation outputs `ref` after the update is done.
  This makes it easier to chain operations that need to use the reset value.
  Unlike `tf.math.add`, this op does not broadcast. `ref` and `value` must have
  the same shape.

  Args:
    ref: A mutable `Tensor`. Must be one of the following types: `float32`,
      `float64`, `int64`, `int32`, `uint8`, `uint16`, `int16`, `int8`,
      `complex64`, `complex128`, `qint8`, `quint8`, `qint32`, `half`. Should be
      from a `Variable` node.
    value: A `Tensor`. Must have the same shape and dtype as `ref`. The value to
      be added to the variable.
    use_locking: An optional `bool`. Defaults to `False`. If True, the addition
      will be protected by a lock; otherwise the behavior is undefined, but may
      exhibit less contention.
    name: A name for the operation (optional).

  Returns:
    Same as `ref`.  Returned as a convenience for operations that want
    to use the new value after the variable has been updated.

  @compatibility(TF2)
  `tf.compat.v1.assign_add` is mostly compatible with eager
  execution and `tf.function`.

  To switch to the native TF2 style, one could use method 'assign_add' of
  `tf.Variable`:

  #### How to Map Arguments

  | TF1 Arg Name          | TF2 Arg Name    | Note                       |
  | :-------------------- | :-------------- | :------------------------- |
  | `ref`                 | `self`          | In `assign_add()` method   |
  | `value`               | `value`         | In `assign_add()` method   |
  | `use_locking`         | `use_locking`   | In `assign_add()` method   |
  | `name`                | `name`          | In `assign_add()` method   |
  | -                     | `read_value`    | Set to True to replicate   |
  :                       :                 : behavior (True is default) :


  #### Before & After Usage Example

  Before:

  >>> with tf.Graph().as_default():
  ...   with tf.compat.v1.Session() as sess:
  ...     a = tf.compat.v1.Variable(0, dtype=tf.int64)
  ...     sess.run(a.initializer)
  ...     update_op = tf.compat.v1.assign_add(a, 1)
  ...     res_a = sess.run(update_op)
  ...     print(res_a)
  1

  After:

  >>> b = tf.Variable(0, dtype=tf.int64)
  >>> res_b = b.assign_add(1)
  >>> res_b.numpy().item()
  1

  @end_compatibility
  r:   )r   r4   r   r>   r<   s       r   r>   r>      r=   r   r-   c                     | j                   j                  rt        j                  | ||||      S | j                  ||      S )a  Update `ref` by assigning `value` to it.

  This operation outputs a Tensor that holds the new value of `ref` after
  the value has been assigned. This makes it easier to chain operations that
  need to use the reset value.

  Args:
    ref: A mutable `Tensor`. Should be from a `Variable` node. May be
      uninitialized.
    value: A `Tensor`. Must have the same shape and dtype as `ref`. The value to
      be assigned to the variable.
    validate_shape: An optional `bool`. Defaults to `True`. If true, the
      operation will validate that the shape of 'value' matches the shape of the
      Tensor being assigned to.  If false, 'ref' will take on the shape of
      'value'.
    use_locking: An optional `bool`. Defaults to `True`. If True, the assignment
      will be protected by a lock; otherwise the behavior is undefined, but may
      exhibit less contention.
    name: A name for the operation (optional).

  Returns:
    A `Tensor` that will hold the new value of `ref` after
      the assignment has completed.

  @compatibility(TF2)
  `tf.compat.v1.assign` is mostly compatible with eager
  execution and `tf.function`. However, argument 'validate_shape' will be
  ignored. To avoid shape validation, set 'shape' to tf.TensorShape(None) when
  constructing the variable:

  >>> import tensorflow as tf
  >>> a = tf.Variable([1], shape=tf.TensorShape(None))
  >>> tf.compat.v1.assign(a, [2,3])

  To switch to the native TF2 style, one could use method 'assign' of
  `tf.Variable`:

  #### How to Map Arguments

  | TF1 Arg Name          | TF2 Arg Name    | Note                       |
  | :-------------------- | :-------------- | :------------------------- |
  | `ref`                 | `self`          | In `assign()` method       |
  | `value`               | `value`         | In `assign()` method       |
  | `validate_shape`      | Not supported   | Specify `shape` in the     |
  :                       :                 : constructor to replicate   :
  :                       :                 : behavior                   :
  | `use_locking`         | `use_locking`   | In `assign()` method       |
  | `name`                | `name`          | In `assign()` method       |
  | -                     | `read_value`    | Set to True to replicate   |
  :                       :                 : behavior (True is default) :
  @end_compatibility


  #### Before & After Usage Example

  Before:

  >>> with tf.Graph().as_default():
  ...   with tf.compat.v1.Session() as sess:
  ...     a = tf.compat.v1.Variable(0, dtype=tf.int64)
  ...     sess.run(a.initializer)
  ...     update_op = tf.compat.v1.assign(a, 2)
  ...     res_a = sess.run(update_op)
  ...     print(res_a)
  2

  After:

  >>> b = tf.Variable(0, dtype=tf.int64)
  >>> res_b = b.assign(2)
  >>> res_b.numpy().item()
  2
  )r;   r   validate_shaper"   )r   r4   r   r-   )r3   r!   rA   r;   r   s        r   r-   r-     sF    V 	YYU$%' ' 
E	%%r   count_up_tozPrefer Dataset.range instead.c                     | j                   j                  rt        j                  | ||      S t        j                  | j
                  || j                   |      S )a  Increments 'ref' until it reaches 'limit'.

  Args:
    ref: A Variable. Must be one of the following types: `int32`, `int64`.
      Should be from a scalar `Variable` node.
    limit: An `int`.
      If incrementing ref would bring it above limit, instead generates an
      'OutOfRange' error.
    name: A name for the operation (optional).

  Returns:
    A `Tensor`. Has the same type as `ref`.
    A copy of the input before increment. If nothing else modifies the
    input, the values produced will all be distinct.
  )limitr   )Tr   )r   r4   r   rB   resource_count_up_tohandle)r3   rD   r   s      r   rB   rB   g  sJ    $ 	YY$$SDAA		+	+	jj%3994
1 1r   scatter_updatec           
         | j                   j                  rt        j                  | ||||      S | j	                  t        j                  | j                  |t        j                  || j                         |            S )a  Applies sparse updates to a variable reference.

  This operation computes

  ```python
      # Scalar indices
      ref[indices, ...] = updates[...]

      # Vector indices (for each i)
      ref[indices[i], ...] = updates[i, ...]

      # High rank indices (for each i, ..., j)
      ref[indices[i, ..., j], ...] = updates[i, ..., j, ...]
  ```

  This operation outputs `ref` after the update is done.
  This makes it easier to chain operations that need to use the reset value.

  If values in `ref` is to be updated more than once, because there are
  duplicate entries in `indices`, the order at which the updates happen
  for each value is undefined.

  Requires `updates.shape = indices.shape + ref.shape[1:]`.

  <div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;">
  <img style="width:100%" src="https://www.tensorflow.org/images/ScatterUpdate.png" alt>
  </div>

  Args:
    ref: A `Variable`.
    indices: A `Tensor`. Must be one of the following types: `int32`, `int64`.
      A tensor of indices into the first dimension of `ref`.
    updates: A `Tensor`. Must have the same type as `ref`.
      A tensor of updated values to store in `ref`.
    use_locking: An optional `bool`. Defaults to `True`.
      If True, the assignment will be protected by a lock;
      otherwise the behavior is undefined, but may exhibit less contention.
    name: A name for the operation (optional).

  Returns:
    Same as `ref`.  Returned as a convenience for operations that want
    to use the updated values after the update is done.
  r:   r"   )
r   r4   r   rH   
_lazy_readr   resource_scatter_updaterG   r   r,   r3   indicesupdatesr;   r   s        r   rH   rH     sp    \ 	YY''Wg4?dL L	1II	jj'300#))D 
 r   scatter_nd_updatec           
          | j                   j                  rt        j                  | ||||      S | j	                  t        j
                  | j                  |t        j                  || j                         |            S )a+  Applies sparse `updates` to individual values or slices in a Variable.

  `ref` is a `Tensor` with rank `P` and `indices` is a `Tensor` of rank `Q`.

  `indices` must be integer tensor, containing indices into `ref`.
  It must be shape `[d_0, ..., d_{Q-2}, K]` where `0 < K <= P`.

  The innermost dimension of `indices` (with length `K`) corresponds to
  indices into elements (if `K = P`) or slices (if `K < P`) along the `K`th
  dimension of `ref`.

  `updates` is `Tensor` of rank `Q-1+P-K` with shape:

  ```
  [d_0, ..., d_{Q-2}, ref.shape[K], ..., ref.shape[P-1]].
  ```

  For example, say we want to update 4 scattered elements to a rank-1 tensor to
  8 elements. In Python, that update would look like this:

  ```python
      ref = tf.Variable([1, 2, 3, 4, 5, 6, 7, 8])
      indices = tf.constant([[4], [3], [1] ,[7]])
      updates = tf.constant([9, 10, 11, 12])
      update = tf.compat.v1.scatter_nd_update(ref, indices, updates)
      with tf.compat.v1.Session() as sess:
        print sess.run(update)
  ```

  The resulting update to ref would look like this:

      [1, 11, 3, 10, 9, 6, 7, 12]

  See `tf.scatter_nd` for more details about how to make updates to
  slices.

  Args:
    ref: A Variable.
    indices: A `Tensor`. Must be one of the following types: `int32`, `int64`.
      A tensor of indices into ref.
    updates: A `Tensor`. Must have the same type as `ref`.
      A Tensor. Must have the same type as ref. A tensor of updated
      values to add to ref.
    use_locking: An optional `bool`. Defaults to `True`.
      An optional bool. Defaults to True. If True, the assignment will
      be protected by a lock; otherwise the behavior is undefined,
      but may exhibit less contention.
    name: A name for the operation (optional).

  Returns:
    The value of the variable after the update.
  r"   )	r   r4   r   rO   rJ   resource_scatter_nd_updaterG   r   r,   rL   s        r   rO   rO     sm    l 	YY**Wg{D2 2	@@	jj'300#))D 
 r   scatter_addc           
         | j                   j                  rt        j                  | ||||      S | j	                  t        j                  | j                  |t        j                  || j                         |            S )a  Adds sparse updates to the variable referenced by `resource`.

  This operation computes

  ```python
      # Scalar indices
      ref[indices, ...] += updates[...]

      # Vector indices (for each i)
      ref[indices[i], ...] += updates[i, ...]

      # High rank indices (for each i, ..., j)
      ref[indices[i, ..., j], ...] += updates[i, ..., j, ...]
  ```

  This operation outputs `ref` after the update is done.
  This makes it easier to chain operations that need to use the updated value.
  Duplicate entries are handled correctly: if multiple `indices` reference
  the same location, their contributions add.

  Requires `updates.shape = indices.shape + ref.shape[1:]`.

  <div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;">
  <img style="width:100%" src='https://www.tensorflow.org/images/ScatterAdd.png' alt>
  </div>

  Args:
    ref: A `Variable`.
    indices: A `Tensor`. Must be one of the following types: `int32`, `int64`.
      A tensor of indices into the first dimension of `ref`.
    updates: A `Tensor`. Must have the same type as `ref`.
      A tensor of updated values to store in `ref`.
    use_locking: An optional `bool`. Defaults to `False`.
      If True, the assignment will be protected by a lock;
      otherwise the behavior is undefined, but may exhibit less contention.
    name: A name for the operation (optional).

  Returns:
    Same as `ref`.  Returned as a convenience for operations that want
    to use the updated values after the update is done.
  r:   r"   )
r   r4   r   rR   rJ   r   resource_scatter_addrG   r   r,   rL   s        r   rR   rR     p    X 	YY$$S'71<4I I	1FF	jj'300#))D 
 r   scatter_nd_addc           
          | j                   j                  rt        j                  | ||||      S | j	                  t        j
                  | j                  |t        j                  || j                         |            S )a  Applies sparse addition to individual values or slices in a Variable.

  `ref` is a `Tensor` with rank `P` and `indices` is a `Tensor` of rank `Q`.

  `indices` must be integer tensor, containing indices into `ref`.
  It must be shape `[d_0, ..., d_{Q-2}, K]` where `0 < K <= P`.

  The innermost dimension of `indices` (with length `K`) corresponds to
  indices into elements (if `K = P`) or slices (if `K < P`) along the `K`th
  dimension of `ref`.

  `updates` is `Tensor` of rank `Q-1+P-K` with shape:

  ```
  [d_0, ..., d_{Q-2}, ref.shape[K], ..., ref.shape[P-1]]
  ```

  For example, say we want to add 4 scattered elements to a rank-1 tensor to
  8 elements. In Python, that addition would look like this:

  ```python
  ref = tf.Variable([1, 2, 3, 4, 5, 6, 7, 8])
  indices = tf.constant([[4], [3], [1], [7]])
  updates = tf.constant([9, 10, 11, 12])
  add = tf.compat.v1.scatter_nd_add(ref, indices, updates)
  with tf.compat.v1.Session() as sess:
    print sess.run(add)
  ```

  The resulting update to ref would look like this:

      [1, 13, 3, 14, 14, 6, 7, 20]

  See `tf.scatter_nd` for more details about how to make updates to
  slices.

  Args:
    ref: A mutable `Tensor`. Must be one of the following types: `float32`,
      `float64`, `int32`, `uint8`, `int16`, `int8`, `complex64`, `int64`,
      `qint8`, `quint8`, `qint32`, `bfloat16`, `uint16`, `complex128`, `half`,
      `uint32`, `uint64`. A mutable Tensor. Should be from a Variable node.
    indices: A `Tensor`. Must be one of the following types: `int32`, `int64`.
      A tensor of indices into ref.
    updates: A `Tensor`. Must have the same type as `ref`.
      A tensor of updated values to add to ref.
    use_locking: An optional `bool`. Defaults to `False`.
      If True, the assignment will be protected by a lock;
      otherwise the behavior is undefined, but may exhibit less contention.
    name: A name for the operation (optional).

  Returns:
    A mutable `Tensor`. Has the same type as `ref`.
  r"   )	r   r4   r   rV   rJ   resource_scatter_nd_addrG   r   r,   rL   s        r   rV   rV   '  sm    n 	YY''Wg{D2 2	==	jj'300#))D 
 r   scatter_subc           
         | j                   j                  rt        j                  | ||||      S | j	                  t        j                  | j                  |t        j                  || j                         |            S )a  Subtracts sparse updates to a variable reference.

  ```python
      # Scalar indices
      ref[indices, ...] -= updates[...]

      # Vector indices (for each i)
      ref[indices[i], ...] -= updates[i, ...]

      # High rank indices (for each i, ..., j)
      ref[indices[i, ..., j], ...] -= updates[i, ..., j, ...]
  ```

  This operation outputs `ref` after the update is done.
  This makes it easier to chain operations that need to use the reset value.

  Duplicate entries are handled correctly: if multiple `indices` reference
  the same location, their (negated) contributions add.

  Requires `updates.shape = indices.shape + ref.shape[1:]` or
  `updates.shape = []`.

  <div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;">
  <img style="width:100%"
       src="https://www.tensorflow.org/images/ScatterSub.png" alt>
  </div>

  Args:
    ref: A mutable `Tensor`. Must be one of the following types: `float32`,
      `float64`, `int32`, `uint8`, `int16`, `int8`, `complex64`, `int64`,
      `qint8`, `quint8`, `qint32`, `bfloat16`, `uint16`, `complex128`, `half`,
      `uint32`, `uint64`. Should be from a `Variable` node.
    indices: A `Tensor`. Must be one of the following types: `int32`, `int64`.
      A tensor of indices into the first dimension of `ref`.
    updates: A `Tensor`. Must have the same type as `ref`.
      A tensor of updated values to subtract from `ref`.
    use_locking: An optional `bool`. Defaults to `False`.
      If True, the subtraction will be protected by a lock;
      otherwise the behavior is undefined, but may exhibit less contention.
    name: A name for the operation (optional).

  Returns:
    A mutable `Tensor`. Has the same type as `ref`.
  r:   r"   )
r   r4   r   rY   rJ   r   resource_scatter_subrG   r   r,   rL   s        r   rY   rY   f  sp    \ 	YY$$S'71<4I I	1FF	jj'300#))D 
 r   scatter_nd_subc           
          | j                   j                  rt        j                  | ||||      S | j	                  t        j
                  | j                  |t        j                  || j                         |            S )a  Applies sparse subtraction to individual values or slices in a Variable.

  `ref` is a `Tensor` with rank `P` and `indices` is a `Tensor` of rank `Q`.

  `indices` must be integer tensor, containing indices into `ref`.
  It must be shape `[d_0, ..., d_{Q-2}, K]` where `0 < K <= P`.

  The innermost dimension of `indices` (with length `K`) corresponds to
  indices into elements (if `K = P`) or slices (if `K < P`) along the `K`th
  dimension of `ref`.

  `updates` is `Tensor` of rank `Q-1+P-K` with shape:

  ```
  [d_0, ..., d_{Q-2}, ref.shape[K], ..., ref.shape[P-1]]
  ```

  For example, say we want to subtract 4 scattered elements from a rank-1 tensor
  with 8 elements. In Python, that update would look like this:

  ```python
  ref = tf.Variable([1, 2, 3, 4, 5, 6, 7, 8])
  indices = tf.constant([[4], [3], [1] ,[7]])
  updates = tf.constant([9, 10, 11, 12])
  op = tf.compat.v1.scatter_nd_sub(ref, indices, updates)
  with tf.compat.v1.Session() as sess:
    print sess.run(op)
  ```

  The resulting update to ref would look like this:

      [1, -9, 3, -6, -6, 6, 7, -4]

  See `tf.scatter_nd` for more details about how to make updates to
  slices.

  Args:
    ref: A mutable `Tensor`. Must be one of the following types: `float32`,
      `float64`, `int32`, `uint8`, `int16`, `int8`, `complex64`, `int64`,
      `qint8`, `quint8`, `qint32`, `bfloat16`, `uint16`, `complex128`, `half`,
      `uint32`, `uint64`. A mutable Tensor. Should be from a Variable node.
    indices: A `Tensor`. Must be one of the following types: `int32`, `int64`.
      A tensor of indices into ref.
    updates: A `Tensor`. Must have the same type as `ref`.
      A tensor of updated values to add to ref.
    use_locking: An optional `bool`. Defaults to `False`.
      An optional bool. Defaults to True. If True, the assignment will
      be protected by a lock; otherwise the behavior is undefined,
      but may exhibit less contention.
    name: A name for the operation (optional).

  Returns:
    A mutable `Tensor`. Has the same type as `ref`.
  r"   )	r   r4   r   r\   rJ   resource_scatter_nd_subrG   r   r,   rL   s        r   r\   r\     sm    p 	YY''Wg{D2 2	==	jj'300#))D 
 r   scatter_mulc           
         | j                   j                  rt        j                  | ||||      S | j	                  t        j                  | j                  |t        j                  || j                         |            S )a  Multiplies sparse updates into a variable reference.

  This operation computes

  ```python
      # Scalar indices
      ref[indices, ...] *= updates[...]

      # Vector indices (for each i)
      ref[indices[i], ...] *= updates[i, ...]

      # High rank indices (for each i, ..., j)
      ref[indices[i, ..., j], ...] *= updates[i, ..., j, ...]
  ```

  This operation outputs `ref` after the update is done.
  This makes it easier to chain operations that need to use the reset value.

  Duplicate entries are handled correctly: if multiple `indices` reference
  the same location, their contributions multiply.

  Requires `updates.shape = indices.shape + ref.shape[1:]` or `updates.shape =
  []`.

  Args:
    ref: A mutable `Tensor`. Must be one of the following types: `float32`,
      `float64`, `int32`, `uint8`, `int16`, `int8`, `complex64`, `int64`,
      `qint8`, `quint8`, `qint32`, `bfloat16`, `uint16`, `complex128`, `half`,
      `uint32`, `uint64`. Should be from a `Variable` node.
    indices: A `Tensor`. Must be one of the following types: `int32`, `int64`. A
      tensor of indices into the first dimension of `ref`.
    updates: A `Tensor`. Must have the same type as `ref`. A tensor of updated
      values to multiply to `ref`.
    use_locking: An optional `bool`. Defaults to `False`. If True, the operation
      will be protected by a lock; otherwise the behavior is undefined, but may
      exhibit less contention.
    name: A name for the operation (optional).

  Returns:
    A mutable `Tensor`. Has the same type as `ref`.
  r:   r"   )
r   r4   r   r_   rJ   r   resource_scatter_mulrG   r   r,   rL   s        r   r_   r_     rU   r   scatter_divc           
         | j                   j                  rt        j                  | ||||      S | j	                  t        j                  | j                  |t        j                  || j                         |            S )a  Divides a variable reference by sparse updates.

  This operation computes

  ```python
      # Scalar indices
      ref[indices, ...] /= updates[...]

      # Vector indices (for each i)
      ref[indices[i], ...] /= updates[i, ...]

      # High rank indices (for each i, ..., j)
      ref[indices[i, ..., j], ...] /= updates[i, ..., j, ...]
  ```

  This operation outputs `ref` after the update is done.
  This makes it easier to chain operations that need to use the reset value.

  Duplicate entries are handled correctly: if multiple `indices` reference
  the same location, their contributions divide.

  Requires `updates.shape = indices.shape + ref.shape[1:]` or `updates.shape =
  []`.

  Args:
    ref: A mutable `Tensor`. Must be one of the following types: `float32`,
      `float64`, `int32`, `uint8`, `int16`, `int8`, `complex64`, `int64`,
      `qint8`, `quint8`, `qint32`, `bfloat16`, `uint16`, `complex128`, `half`,
      `uint32`, `uint64`. Should be from a `Variable` node.
    indices: A `Tensor`. Must be one of the following types: `int32`, `int64`. A
      tensor of indices into the first dimension of `ref`.
    updates: A `Tensor`. Must have the same type as `ref`. A tensor of values
      that `ref` is divided by.
    use_locking: An optional `bool`. Defaults to `False`. If True, the operation
      will be protected by a lock; otherwise the behavior is undefined, but may
      exhibit less contention.
    name: A name for the operation (optional).

  Returns:
    A mutable `Tensor`. Has the same type as `ref`.
  r:   r"   )
r   r4   r   rb   rJ   r   resource_scatter_divrG   r   r,   rL   s        r   rb   rb     rU   r   scatter_maxc           
         | j                   j                  rt        j                  | ||||      S | j	                  t        j                  | j                  |t        j                  || j                         |            S )a  Reduces sparse updates into a variable reference using the `max` operation.

  This operation computes

      # Scalar indices
      ref[indices, ...] = max(ref[indices, ...], updates[...])

      # Vector indices (for each i)
      ref[indices[i], ...] = max(ref[indices[i], ...], updates[i, ...])

      # High rank indices (for each i, ..., j)
      ref[indices[i, ..., j], ...] = max(ref[indices[i, ..., j], ...],
      updates[i, ..., j, ...])

  This operation outputs `ref` after the update is done.
  This makes it easier to chain operations that need to use the reset value.

  Duplicate entries are handled correctly: if multiple `indices` reference
  the same location, their contributions combine.

  Requires `updates.shape = indices.shape + ref.shape[1:]` or `updates.shape =
  []`.

  <div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;">
  <img style="width:100%" src="https://www.tensorflow.org/images/ScatterAdd.png"
  alt>
  </div>

  Args:
    ref: A mutable `Tensor`. Must be one of the following types: `half`,
      `bfloat16`, `float32`, `float64`, `int32`, `int64`. Should be from a
      `Variable` node.
    indices: A `Tensor`. Must be one of the following types: `int32`, `int64`. A
      tensor of indices into the first dimension of `ref`.
    updates: A `Tensor`. Must have the same type as `ref`. A tensor of updated
      values to reduce into `ref`.
    use_locking: An optional `bool`. Defaults to `False`. If True, the update
      will be protected by a lock; otherwise the behavior is undefined, but may
      exhibit less contention.
    name: A name for the operation (optional).

  Returns:
    A mutable `Tensor`. Has the same type as `ref`.
  r:   r"   )
r   r4   r   re   rJ   r   resource_scatter_maxrG   r   r,   rL   s        r   re   re   D  p    ^ 	YY$$S'71<4I I	1FF	jj'300#))D 
 r   scatter_minc           
         | j                   j                  rt        j                  | ||||      S | j	                  t        j                  | j                  |t        j                  || j                         |            S )a  Reduces sparse updates into a variable reference using the `min` operation.

  This operation computes

      # Scalar indices
      ref[indices, ...] = min(ref[indices, ...], updates[...])

      # Vector indices (for each i)
      ref[indices[i], ...] = min(ref[indices[i], ...], updates[i, ...])

      # High rank indices (for each i, ..., j)
      ref[indices[i, ..., j], ...] = min(ref[indices[i, ..., j], ...],
      updates[i, ..., j, ...])

  This operation outputs `ref` after the update is done.
  This makes it easier to chain operations that need to use the reset value.

  Duplicate entries are handled correctly: if multiple `indices` reference
  the same location, their contributions combine.

  Requires `updates.shape = indices.shape + ref.shape[1:]` or `updates.shape =
  []`.

  <div style="width:70%; margin:auto; margin-bottom:10px; margin-top:20px;">
  <img style="width:100%" src="https://www.tensorflow.org/images/ScatterAdd.png"
  alt>
  </div>

  Args:
    ref: A mutable `Tensor`. Must be one of the following types: `half`,
      `bfloat16`, `float32`, `float64`, `int32`, `int64`. Should be from a
      `Variable` node.
    indices: A `Tensor`. Must be one of the following types: `int32`, `int64`. A
      tensor of indices into the first dimension of `ref`.
    updates: A `Tensor`. Must have the same type as `ref`. A tensor of updated
      values to reduce into `ref`.
    use_locking: An optional `bool`. Defaults to `False`. If True, the update
      will be protected by a lock; otherwise the behavior is undefined, but may
      exhibit less contention.
    name: A name for the operation (optional).

  Returns:
    A mutable `Tensor`. Has the same type as `ref`.
  r:   r"   )
r   r4   r   ri   rJ   r   resource_scatter_minrG   r   r,   rL   s        r   ri   ri   {  rh   r   batch_scatter_updatez
2018-11-29z8Use the batch_scatter_update method of Variable instead.c           	         t        j                  |      5  t        j                  |d      }t        j                  |      }|j                         j                  }|t        d      t        j                  |d      }g }t        |dz
        D ]  }	||	   }
dg|dz   z  }|
||	<   t        j                  t        j                  d|
d      |      }|j                  j                  |j                  k7  r t        j                  ||j                        }|j!                  |t        j"                  |      z          |j!                  |       t        j$                  |d      }t'        | |||	      cddd       S # 1 sw Y   yxY w)
aU  Generalization of `tf.compat.v1.scatter_update` to axis different than 0.

  Analogous to `batch_gather`. This assumes that `ref`, `indices` and `updates`
  have a series of leading dimensions that are the same for all of them, and the
  updates are performed on the last dimension of indices. In other words, the
  dimensions should be the following:

  `num_prefix_dims = indices.ndims - 1`
  `batch_dim = num_prefix_dims + 1`
  `updates.shape = indices.shape + var.shape[batch_dim:]`

  where

  `updates.shape[:num_prefix_dims]`
  `== indices.shape[:num_prefix_dims]`
  `== var.shape[:num_prefix_dims]`

  And the operation performed can be expressed as:

  `var[i_1, ..., i_n, indices[i_1, ..., i_n, j]] = updates[i_1, ..., i_n, j]`

  When indices is a 1D tensor, this operation is equivalent to
  `tf.compat.v1.scatter_update`.

  To avoid this operation there would be 2 alternatives:
  1) Reshaping the variable by merging the first `ndims` dimensions. However,
     this is not possible because `tf.reshape` returns a Tensor, which we
     cannot use `tf.compat.v1.scatter_update` on.
  2) Looping over the first `ndims` of the variable and using
     `tf.compat.v1.scatter_update` on the subtensors that result of slicing the
     first
     dimension. This is a valid option for `ndims = 1`, but less efficient than
     this implementation.

  See also `tf.compat.v1.scatter_update` and `tf.compat.v1.scatter_nd_update`.

  Args:
    ref: `Variable` to scatter onto.
    indices: Tensor containing indices as described above.
    updates: Tensor of updates to apply to `ref`.
    use_locking: Boolean indicating whether to lock the writing operation.
    name: Optional scope name string.

  Returns:
    Ref to `variable` after it has been modified.

  Raises:
    ValueError: If the initial `ndims` of `ref`, `indices`, and `updates` are
        not the same.
  rM   r"   Nz7batch_gather does not allow indices with unknown shape.)axis   r   )r;   )r   r$   r,   r   r   r(   ndims
ValueErrorexpand_dimsrangereshaper   _ranger   r+   castappend	ones_likeconcatrO   )r3   rM   rN   r;   r   indices_shapeindices_dimensions
nd_indicesnd_indices_list	dimensiondimension_sizeshape_to_broadcastdimension_rangefinal_indicess                 r   rl   rl     s   l ~~d +>##G)<GOOG,M **,22!   ! ! &&wR8JO -12 =	 %Y/n3"4q"89&4#!))


a
35GIo				)	)Z-=-=	=&++OZ=M=MN
I//
;
;==" :&$$_2>M]G>U+> +> +>s   EE>>F)VariableT r   )r   r   r   )r#   )N)NN)NNN)TN)FN)$__doc__tensorflow.python.frameworkr   r   tensorflow.python.opsr   r   r   r   r	   #tensorflow.python.ops.gen_state_opstensorflow.python.utilr   "tensorflow.python.util.deprecationr    tensorflow.python.util.tf_exportr   r   r   r0   r5   r7   r>   r-   rB   rH   rO   rR   rV   rY   r\   r_   rb   re   ri   rl    r   r   <module>r      s/   
 , 4 + . ; / , 2 . 9 6 JL6 ;F'& |nD DN |nD DN xjN& N&b }oD121 3 1,  !2 "2j "#$: %:z }o0 0f  !; ";| }o2 2j  !< "<~ }o0 0f }o0 0f }o3 3l }o3 3l %&'LN^>N (^>r   