
    AVhA@                        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lmZ  ej"                  ej$                        dddej&                  dddfdej(                  fd       Z ej"                  ej*                        	 	 	 	 	 	 ddej(                  fd       ZddZy)zbincount ops for RaggedTensors.    )dtypes)ops)sparse_tensor)	array_ops)bincount_ops)	check_ops)gen_count_ops)gen_math_ops)math_ops)
sparse_ops)ragged_tensor)dispatchNFarrc                    |dn|}t        j                  |      5  t        j                  | d      } |1t	        |t
        j                        st        j                  |d      }||rt        d      | j                  j                  s$t        j                  | t        j                        } |d}|dvrt        d	| d
      t        j                  |       dkD  }t        j                  || j                        t        j                   |       dz   z  }	|8t        j"                  |d| j                        }t%        j&                  ||	      }	|8t        j"                  |d| j                        }t%        j(                  ||	      }	|dk(  rPt	        | t        j*                        r6|t-        | ||      }| j.                  } t	        | t        j*                        r6t	        | t        j*                        rDt-        | ||      }t%        j0                  | j2                  | j.                  |	||      cddd       S t5        j6                  | ||      }t%        j8                  | |	||      cddd       S # 1 sw Y   yxY w)a$  Counts the number of occurrences of each value in an integer array.

  If `minlength` and `maxlength` are not given, returns a vector with length
  `tf.reduce_max(arr) + 1` if `arr` is non-empty, and length 0 otherwise.

  >>> data = tf.ragged.constant([[1, 1], [2, 3, 2, 4, 4, 5]])
  >>> tf.math.bincount(data)
  <tf.Tensor: ... numpy=array([0, 2, 2, 1, 2, 1], dtype=int32)>

  Vector length = Maximum element in vector `values` is 5. Adding 1, which is 6
                  will be the vector length.

  Each bin value in the output indicates number of occurrences of the particular
  index. Here, index 1 in output has a value 2. This indicates value 1 occurs
  two times in `values`.

  **Bin-counting with weights**

  >>> data = tf.ragged.constant([[1, 1], [2, 3, 2, 4, 4, 5]])
  >>> weights = tf.ragged.constant([[1, 5], [0, 1, 0, 5, 4, 5]])
  >>> tf.math.bincount(data, weights=weights)
  <tf.Tensor: ... numpy=array([0, 6, 0, 1, 9, 5], dtype=int32)>

  When `weights` is specified, bins will be incremented by the corresponding
  weight instead of 1. Here, index 1 in output has a value 6. This is the
  summation of `weights` corresponding to the value in `arr` (i.e. for index
  1, the first two values `arr` are 1 so the first two weights, 1 and 5, are
  summed).

  There is an equivilance between bin-counting with weights and
  `unsorted_segement_sum` where `data` is the weights and `segment_ids` are the
  values.

  >>> data = tf.ragged.constant([[1, 1], [2, 3, 2, 4, 4, 5]])
  >>> weights = tf.ragged.constant([[1, 5], [0, 1, 0, 5, 4, 5]])
  >>> tf.math.unsorted_segment_sum(weights, data, num_segments=6).numpy()
  array([0, 6, 0, 1, 9, 5], dtype=int32)

  On GPU, `bincount` with weights is only supported when XLA is enabled
  (typically when a function decorated with `@tf.function(jit_compile=True)`).
  `unsorted_segment_sum` can be used as a workaround for the non-XLA case on
  GPU.

  **Bin-counting matrix rows independently**

  This example uses `axis=-1` with a 2 dimensional input and returns a
  `Tensor` with bincounting where axis 0 is **not** flattened, i.e. an
  independent bincount for each matrix row.

  >>> data = tf.ragged.constant([[1, 2], [3, 0, 0, 0, 1, 2]], dtype=np.int32)
  >>> tf.math.bincount(data, axis=-1)
  <tf.Tensor: shape=(2, 4), dtype=int32, numpy=
    array([[0, 1, 1, 0],
           [3, 1, 1, 1]], dtype=int32)>

  **Bin-counting with binary_output**

  This example gives binary output instead of counting the occurrence.

  >>> data = tf.ragged.constant([[1, 2], [3, 0, 0, 0, 1, 2]], dtype=np.int32)
  >>> tf.math.bincount(data, axis=-1, binary_output=True)
  <tf.Tensor: shape=(2, 4), dtype=int32, numpy=
    array([[0, 1, 1, 0],
           [1, 1, 1, 1]], dtype=int32)>

  Args:
    arr: A RaggedTensor whose values should be counted.
      These tensors must have a rank of 2 if `axis=-1`.
    weights: If non-None, must be a RaggedTensor with the same row splits as
      `arr`. For each value in `arr`, the bin will be incremented by the
      corresponding weight instead of 1. If non-None, `binary_output` must be
      False.
    minlength: If given, ensures the output has length at least `minlength`,
      padding with zeros at the end if necessary.
    maxlength: If given, skips values in `arr` that are equal or greater than
      `maxlength`, ensuring that the output has length at most `maxlength`.
    dtype: If `weights` is None, determines the type of the output bins.
    name: A name scope for the associated operations (optional).
    axis: The axis to slice over. Axes at and below `axis` will be flattened
      before bin counting. Currently, only `0`, and `-1` are supported. If None,
      all axes will be flattened (identical to passing `0`).
    binary_output: If True, this op will output 1 instead of the number of times
      a token appears (equivalent to one_hot + reduce_any instead of one_hot +
      reduce_add). Defaults to False.

  Returns:
    A vector with the same dtype as `weights` or the given `dtype` containing
    the bincount values.

  Raises:
    `InvalidArgumentError` if negative values are provided as an input.

  Nbincountr   nameweightsXArguments `binary_output` and `weights` are mutually exclusive. Please specify only one.r   r   $Unsupported value for argument axis=(. Only 0 and -1 are currently supported.   	minlength)r   dtype	maxlength)splitsvaluessizer   binary_output)inputr    r   r!   )r   
name_scoper   "convert_to_tensor_or_ragged_tensor
isinstancer   SparseTensor
ValueErrorr   
is_integerr   castr   int32r   r    
reduce_maxconvert_to_tensorr
   maximumminimumRaggedTensorvalidate_ragged_weightsr   ragged_bincount
row_splitsr   validate_dense_weightsdense_bincount)
r   r   r   r   r   r   axisr!   array_is_nonemptyoutput_sizes
             `/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/ops/ragged/ragged_bincount_ops.pyr   r      sQ   L |$
~~d 6'

:
:3U
KC!;!;<BB)% } = > > 99MM#v||,c|d7=dV D6 6 7 7 "s+a/-- 1399=C 1$&K''
+SYY8i ((K@k''
+SYY8i ((K@kqy sM667+C%@'jj sM667
 #}112'We<g))%'U6' 6'b 33C%Hg((%	'e6' 6' 6's   GI8!AI8?/I88Jr   c           	         t        j                  |d| |g      5  t        j                  | d      } |1t	        |t
        j                        st        j                  |d      }||rt        d      |d}|dvrt        d	| d
      ||nd}||nd}|dk(  r|t        | |      }| j                  } t	        | t        j                        r@t        | |      }t        j                  | j                  | j                  ||||      \  }	}
}n4t        j                  | |      }t        j                   | ||||      \  }	}
}t        j                  |	|
|      cddd       S # 1 sw Y   yxY w)a^  Count the number of times an integer value appears in a tensor.

  This op takes an N-dimensional `Tensor`, `RaggedTensor`, or `SparseTensor`,
  and returns an N-dimensional int64 SparseTensor where element
  `[i0...i[axis], j]` contains the number of times the value `j` appears in
  slice `[i0...i[axis], :]` of the input tensor.  Currently, only N=0 and
  N=-1 are supported.

  Args:
    values: A RaggedTensor whose values should be
      counted. These tensors must have a rank of 2 if `axis=-1`.
    weights: If non-None, must be a RaggedTensor with the same row splits as
      `values`. For each value in `value`, the bin will be incremented by the
      corresponding weight instead of 1.
    axis: The axis to slice over. Axes at and below `axis` will be flattened
      before bin counting. Currently, only `0`, and `-1` are supported. If None,
      all axes will be flattened (identical to passing `0`).
    minlength: If given, ensures the output has length at least `minlength`,
      padding with zeros at the end if necessary.
    maxlength: If given, skips values in `values` that are equal or greater than
      `maxlength`, ensuring that the output has length at most `maxlength`.
    binary_output: If True, this op will output 1 instead of the number of times
      a token appears (equivalent to one_hot + reduce_any instead of one_hot +
      reduce_add). Defaults to False.
    name: A name for this op.

  Returns:
    A SparseTensor with `output.shape = values.shape[:axis] + [N]`, where `N` is
      * `maxlength` (if set);
      * `minlength` (if set, and `minlength > reduce_max(values)`);
      * `0` (if `values` is empty);
      * `reduce_max(values) + 1` otherwise.

  Raises:
    `InvalidArgumentError` if negative values are provided as an input.

  Examples:

  **Bin-counting every item in individual batches**

  This example takes an input (which could be a Tensor, RaggedTensor, or
  SparseTensor) and returns a SparseTensor where the value of (i,j) is the
  number of times value j appears in batch i.

  >>> data = tf.ragged.constant(
  ...     [[10, 20], [30, 20, 11, 101, 11, 10001]], dtype=np.int64)
  >>> tf.sparse.bincount(data, axis=-1)
  SparseTensor(indices=tf.Tensor(
    [[    0    10]
     [    0    20]
     [    1    11]
     [    1    20]
     [    1    30]
     [    1   101]
     [    1 10001]], shape=(7, 2), dtype=int64),
     values=tf.Tensor([1 1 2 1 1 1 1], shape=(7,), dtype=int64),
     dense_shape=tf.Tensor([    2 10002], shape=(2,), dtype=int64))

  **Bin-counting with defined output shape**

  This example takes an input (which could be a Tensor, RaggedTensor, or
  SparseTensor) and returns a SparseTensor where the value of (i,j) is the
  number of times value j appears in batch i. However, all values of j
  above 'maxlength' are ignored. The dense_shape of the output sparse tensor
  is set to 'minlength'. Note that, while the input is identical to the
  example above, the value '10001' in batch item 2 is dropped, and the
  dense shape is [2, 500] instead of [2,10002] or [2, 102].

  >>> minlength = maxlength = 500
  >>> data = tf.ragged.constant(
  ...     [[10, 20], [30, 20, 11, 101, 11, 10001]], dtype=np.int64)
  >>> tf.sparse.bincount(
  ...    data, axis=-1, minlength=minlength, maxlength=maxlength)
  SparseTensor(indices=tf.Tensor(
  [[  0  10]
   [  0  20]
   [  1  11]
   [  1  20]
   [  1  30]
   [  1 101]], shape=(6, 2), dtype=int64),
   values=tf.Tensor([1 1 2 1 1 1], shape=(6,), dtype=int64),
   dense_shape=tf.Tensor([  2 500], shape=(2,), dtype=int64))

  **Binary bin-counting**

  This example takes an input (which could be a Tensor, RaggedTensor, or
  SparseTensor) and returns a SparseTensor where (i,j) is 1 if the value j
  appears in batch i at least once and is 0 otherwise. Note that, even though
  some values (like 20 in batch 1 and 11 in batch 2) appear more than once,
  the 'values' tensor is all 1s.

  >>> data = tf.ragged.constant(
  ...     [[10, 20], [30, 20, 11, 101, 11, 10001]], dtype=np.int64)
  >>> tf.sparse.bincount(data, binary_output=True, axis=-1)
  SparseTensor(indices=tf.Tensor(
  [[  0  10]
   [  0  20]
   [  1  11]
   [  1  20]
   [  1  30]
   [  1 101]
   [  1 10001]], shape=(7, 2), dtype=int64),
   values=tf.Tensor([1 1 1 1 1 1 1], shape=(7,), dtype=int64),
   dense_shape=tf.Tensor([  2 10002], shape=(2,), dtype=int64))

  **Weighted bin-counting**

  This example takes two inputs - a values tensor and a weights tensor. These
  tensors must be identically shaped, and have the same row splits or indices
  in the case of RaggedTensors or SparseTensors. When performing a weighted
  count, the op will output a SparseTensor where the value of (i, j) is the
  sum of the values in the weight tensor's batch i in the locations where
  the values tensor has the value j. In this case, the output dtype is the
  same as the dtype of the weights tensor.

  >>> data = tf.ragged.constant(
  ...    [[10, 20], [30, 20, 11, 101, 11, 10001]], dtype=np.int64)
  >>> weights = tf.ragged.constant(
  ...    [[2, 0.25], [15, 0.5, 2, 17, 3, 0.9]])
  >>> tf.sparse.bincount(data, weights=weights, axis=-1)
  SparseTensor(indices=tf.Tensor(
  [[    0    10]
   [    0    20]
   [    1    11]
   [    1    20]
   [    1    30]
   [    1   101]
   [    1 10001]], shape=(7, 2), dtype=int64),
   values=tf.Tensor([ 2. 0.25  5. 0.5 15. 17. 0.9 ], shape=(7,), dtype=float32),
   dense_shape=tf.Tensor([    2 10002], shape=(2,), dtype=int64))

  countr   r   Nr   r   r   r   r   r   r   )r   r   r!   )r   r   r   r!   )r   r#   r   r$   r%   r   r&   r'   r0   r   r/   r	   ragged_count_sparse_outputr2   r   r3   dense_count_sparse_output)r   r   r5   r   r   r!   r   minlength_valuemaxlength_valuec_indc_valc_shapes               r8   sparse_bincountrB      s   X ~~dGfg%67 -===XF!;!;<BB)% } = > > |d7=dV D6 6 7 7 $-#8ibO#,#8ibOqy		)&':}}f&-445'8g+FF



--
##%'eUG 33FGDg+EE
##%'eUG %%eUG<[-= -= -=s   E E$$E-c                 n   |D|rt        j                  g |      S t        j                  g | j                  j                        S t	        |t
        j                        s%t        d| dt        |      j                   d      g }|j                  | j                  ur;|j                  t        j                  |j                  | j                  d             |r?t        j                  |      5  t        j                   |j                        }ddd       |S |j                  }|S # 1 sw Y   |S xY w)z;Validates the passed weight tensor or creates an empty one.N)r   zZ`weights` must be a RaggedTensor if `values` is a RaggedTensor. Received argument weights=z
 of type: .z5'weights' and 'values' must have the same row splits.)message)r   constantr   r   r%   r   r/   r'   type__name__r2   appendr   assert_equalr   control_dependenciesidentity)r   r   r   checkss       r8   r0   r0   {  s   _%00b(;(;<<	G]77	8
	%%,IZ=!!
"!	%& &
 &v000
MMK	MN
 		!	!&	) 3""7>>2g3
 
. nnG	.3
 
.s   2 D**D4)Nr   NNFN)N)__doc__tensorflow.python.frameworkr   r   r   tensorflow.python.opsr   r   r   r	   r
   r   r   tensorflow.python.ops.raggedr   tensorflow.python.utilr   dispatch_for_apir   r*   r/   rB   r0        r8   <module>rV      s    & . + 5 + . + / . * , 6 + <001<< \'-,, \' 2\'~ :556 """'x=M66 x= 7x=vrU   