
    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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 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"d      e jF                  dId              Z$ e jJ                  ejL                        dIdejN                  fd       Z&dId Z(dId!Z) e jJ                  ejT                        dIdejN                  fd"       Z+ e jJ                  ejV                        	 	 	 dJdejN                  fd#       Z, e jJ                  ejZ                        ej\                  dfdejN                  fd$       Z/ e jJ                  ej^                        dej\                  fdejN                  fd%       Z0 e jJ                  ejb                        dIdejN                  fd&       Z1 e jJ                  ejd                        	 	 	 	 	 dKd'ejN                  fd(       Z3 e"d)      e jF                  dId*              Z4 e jJ                  ejj                        dId+ejN                  fd,       Z5 e"d-      e jF                  dId.              Z6 e"d/      e jF                  dLd0              Z7d1Z8	 	 	 	 dMd2Z9dId3Z: ejv                  d4      d5        Z< e jJ                  ejz                        	 dId6ej|                  d7ej|                  fd8       Z= e jJ                  ej~                        	 	 	 dLd9ejN                  fd:       Z? e jJ                  ej                        d+ej|                  d;ej                  d<eej                  e	j                  f   fd=       ZD e jJ                  ej                        dej|                  d;ej                  d<eej                  e	j                  f   fd>       ZE e jJ                  ej                        dej\                  fdejN                  d?eeH   d<ej                  fd@       ZI e jJ                  ej                        dAej                  dBej                  d<ej                  fdC       ZJ e jJ                  ej                        ej                  ddfd;ej                  d<ej|                  fdD       ZK e jJ                  ej                        ej                  ddfd;ej                  d<ej|                  fdE       ZM e jJ                  ej                        	 	 dNdFej                  d9ej                  d?eeH   d<ej|                  fdG       ZN e jJ                  ej                        	 dIdej|                  d<ej|                  fdH       ZPy)Oz#Array operations for RaggedTensors.    )Optional)Union)dtypes)ops)sparse_tensor)tensor)tensor_shape)tensor_util)	array_ops)array_ops_stack)	check_ops)control_flow_ops)data_flow_ops)gen_ragged_array_ops)math_ops)sort_ops)dynamic_ragged_shape)ragged_functional_ops)ragged_math_ops)ragged_tensor)ragged_util)segment_id_ops)core)dispatch)	tf_exportzragged.boolean_maskNc           	      
   t        j                  |d| |g      5  t        j                  | d      } t        j                  |t        j
                  d      }t        j                  | |d      \  }\  } }|j                  j                  t        d      |j                  j                  d	k(  rt        d
      t        j                  |      rt        j                  |       s@t        j                  j                  | |j                  |j                  j                        } |j                   | j                   d|j                   g}t        j"                  t%        j&                  |            5  g }t        j                  |      r|j                  j                  dkD  r|j)                  |j                         nat+        j,                  t.        j0                  ||      }t3        j4                  |d      }|j)                  t%        j6                  |             |j8                  }| j8                  } t        j                  |      rt;        | |      }t        j                  j=                  ||d      }|cddd       cddd       S t        j                  |       r|j                  j                  dk(  r| j?                         }	tA        j:                  |	|      }
t%        j6                  |
      }tC        jD                  | j                        }tA        jF                  ||      }t;        | j8                  |      }t        j                  jI                  ||d      cddd       S t        j                  |       rvt        j                  j                  |tK        | j                  |j                  j                  dz
        | j                  j                        }t;        | |      cddd       S tA        j:                  | |      }|j                  j                  dk\  rt/        jL                  |d|      }
tA        jN                  |
dg      }t        j                  jQ                  ||d      }|j                  j                  dkD  rtA        j                  ||      }t/        jR                  |      dz   }tU        |j                  j                  dz
  dd      D ]G  }||dz      }t/        jT                  ||         |z  }t        j                  jI                  ||d      }I |cddd       S # 1 sw Y   xY w# 1 sw Y   yxY w)a  Applies a boolean mask to `data` without flattening the mask dimensions.

  Returns a potentially ragged tensor that is formed by retaining the elements
  in `data` where the corresponding value in `mask` is `True`.

  * `output[a1...aA, i, b1...bB] = data[a1...aA, j, b1...bB]`

     Where `j` is the `i`th `True` entry of `mask[a1...aA]`.

  Note that `output` preserves the mask dimensions `a1...aA`; this differs
  from `tf.boolean_mask`, which flattens those dimensions.

  Args:
    data: A potentially ragged tensor.
    mask: A potentially ragged boolean tensor.  `mask`'s shape must be a prefix
      of `data`'s shape.  `rank(mask)` must be known statically.
    name: A name prefix for the returned tensor (optional).

  Returns:
    A potentially ragged tensor that is formed by retaining the elements in
    `data` where the corresponding value in `mask` is `True`.

    * `rank(output) = rank(data)`.
    * `output.ragged_rank = max(data.ragged_rank, rank(mask) - 1)`.

  Raises:
    ValueError: if `rank(mask)` is not known statically; or if `mask.shape` is
      not a prefix of `data.shape`.

  #### Examples:

  >>> # Aliases for True & False so data and mask line up.
  >>> T, F = (True, False)

  >>> tf.ragged.boolean_mask(  # Mask a 2D Tensor.
  ...     data=[[1, 2, 3], [4, 5, 6], [7, 8, 9]],
  ...     mask=[[T, F, T], [F, F, F], [T, F, F]]).to_list()
  [[1, 3], [], [7]]

  >>> tf.ragged.boolean_mask(  # Mask a 2D RaggedTensor.
  ...     tf.ragged.constant([[1, 2, 3], [4], [5, 6]]),
  ...     tf.ragged.constant([[F, F, T], [F], [T, T]])).to_list()
  [[3], [], [5, 6]]

  >>> tf.ragged.boolean_mask(  # Mask rows of a 2D RaggedTensor.
  ...     tf.ragged.constant([[1, 2, 3], [4], [5, 6]]),
  ...     tf.ragged.constant([True, False, True])).to_list()
  [[1, 2, 3], [5, 6]]
  
RaggedMaskdatanamemaskT)return_dtypeNz*mask.shape.ndims must be known statically.r   zmask cannot be scalar.)ragged_rankrow_splits_dtype   dtype   axisFvalidate)r*   r'   )out_type   )+r   
name_scoper   "convert_to_tensor_or_ragged_tensorr   boolmatch_row_splits_dtypesshapendims
ValueError	is_raggedRaggedTensorfrom_tensorr#   
row_splitsr'   nested_row_splitscontrol_dependenciesr   assert_splits_matchappendr   map_flat_valuesr   castr   
reduce_sumlengths_to_splitsvaluesboolean_maskfrom_nested_row_splitsrow_lengthsr   r   row_splits_to_segment_idsgatherfrom_row_splitsmincount_nonzeroreshapefrom_row_lengthscumprodrange)r   r!   r    r$   splits_listsplitsint_maskmasked_row_lengthsmasked_valueslengthsmasked_lengthsmasked_splitssegment_idssegment_maskflattened_masked_lengths
mask_shape
split_sizedimelt_sizes                      ]/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/ops/ragged/ragged_array_ops.pyrD   rD   1   s   h ~~dL4,7 n;;DvND;;fkk(D%2%J%Jd&'"ltT zzCDD			Q	/00 t$$$T*))55((!__22 6 4 
 
 $"8"89J$:J:J"Kk ##

)
)+
68 
 %%d+ZZ!MM$//* -<<t+;=H!0!;!;H1!MMM+778JKL$$ %%d+ %T40 &22II6E J 3 5 5n np 
	 	 	&4::+;+;q+@   "g --gt<n!33NCm #<<T__Mk%%dK8l"4;;=m''77
 8 8Qn nZ t$''33
$**DJJ,<,<q,@A??00 4 2d $%en nn  ,,T48m			Q	
 "//r!13#,#4#4^bT#J %22CC3e D E ::a t6FG*''
3a7*4::++a/R8 >c!#'*H$NN:c?;hFM)66FF}u G >M> ]n n4 5n ns@   EU
3CT=/T=>	U
CU
0BU
;D8U
=U	U

Uinputc           	          t        j                  |d| |g      5  t        j                  | d      } t        j                  |       s t        j                  | ||      cddd       S t        j                  |d| j                  j                        }|j                  j                  d       t        j                  |      }t        j                  j!                  t#        | ||      t%        | ||      d	      cddd       S # 1 sw Y   yxY w)
a#  Constructs a `RaggedTensor` by tiling a given `RaggedTensor`.

  The values of `input` are replicated `multiples[i]` times along the
  `i`th dimension (for each dimension `i`).  For every dimension `axis` in
  `input`, the length of each output element in that dimension is the
  length of corresponding input element multiplied by `multiples[axis]`.

  Args:
    input: A `RaggedTensor`.
    multiples: A 1-D integer `Tensor`.  Length must be the same as the number of
      dimensions in `input`.
    name: A name for the operation (optional).

  Returns:
    A `RaggedTensor` with the same type, rank, and ragged_rank as `input`.

  #### Example:

  >>> rt = tf.ragged.constant([[1, 2], [3]])
  >>> tf.tile(rt, [3, 2]).to_list()
  [[1, 2, 1, 2], [3, 3], [1, 2, 1, 2], [3, 3], [1, 2, 1, 2], [3, 3]]
  
RaggedTiler`   r   N	multiples)r    r'   r(   Fr+   )r   r0   r   r1   r7   r   tiler   convert_to_int_tensorr:   r'   r4   assert_has_rankr
   constant_valuer8   rE   _tile_ragged_values_tile_ragged_splits)r`   rc   r    const_multipless       r_   rd   rd      s    0 ~~dL5)*<= <<GE""5)^^E9d3	 
 115+;+;+A+ACIOO##A& "00;O%%<<E9o>E9o> =   s   AD'BDDc                    | j                   }| j                  }t        j                  |d   d         }d}t        |dd      D ]Q  }||dz
     }|t	        j
                  |||dz      z  |      }|||   dk7  rt        j                  ||||         }|}S t	        j
                  | j                  |      }	t	        j                  |dd ||dz   d gd      }
t	        j                  |	|
      S )a5  Builds flat_values tensor for a tiled `RaggedTensor`.

  Returns a tensor that repeats the values in
  `rt_input.flat_values` in the
  appropriate pattern to construct a `RaggedTensor` that tiles `rt_input` as
  specified by `multiples`.

  Args:
    rt_input: The `RaggedTensor` whose values should be repeated.
    multiples: A 1-D integer `tensor`, indicating how many times each dimension
      should be repeated.
    const_multiples: Optional constant value for multiples.  Used to skip tiling
      dimensions where `multiples=1`.

  Returns:
    A `Tensor` with the same type and rank as `rt_input.flat_values`.

  #### Example:

  >>> rt = tf.ragged.constant([[1, 2], [3]])
  >>> _tile_ragged_values(rt, tf.constant([3, 2])).numpy()
  array([1, 2, 1, 2, 3, 3, 1, 2, 1, 2, 3, 3, 1, 2, 1, 2, 3, 3], dtype=int32)
  r-   Nr   r(   r)   )r#   r;   r   rO   r   rH   r   repeat_rangesflat_valuesconcatrd   )rt_inputrc   rj   r#   nested_splitsinner_value_idsprev_splitsr*   rQ   ragged_tiled_valuesinner_repeatss              r_   rh   rh     s   0 $$+,,- NN=#4R#89/ +KB' d4!8$F iq.A A6Jf /$"71"<#11/62;D/Co K" "(()=)=O ""IbqM9[1_=M3N#O()+-	+]	;;    c           	         | j                   }| j                  }t        |      D cg c]	  }|||   i }}t        |      D ]A  }t        |dz   |dz
        D ]*  }t        j                  ||   ||   |dz
           ||   |<   , C g }	t        |      D ]  }
||
   dd ||
   dd z
  }|||
dz      z  }d}t        |
dz
  dd      D ]E  }|||dz      dk7  r+||   |
dz
     |z  }t        j                  ||||dz            }|||dz      z  }G t        j                  ||dd       }|	j                  t        j                  |              |	S c c}w )a  Builds nested_split tensors for a tiled `RaggedTensor`.

  Returns a list of split tensors that can be used to construct the
  `RaggedTensor` that tiles `rt_input` as specified by `multiples`.

  Args:
    rt_input: The `RaggedTensor` that is being tiled.
    multiples: A 1-D integer `tensor`, indicating how many times each dimension
      should be repeated.
    const_multiples: Optional constant value for multiples.  Used to skip tiling
      dimensions where `multiples=1`.

  Returns:
    A list of 1-D integer `Tensor`s (one for each ragged dimension in
    `rt_input`).

  #### Example:

  >>> rt = tf.ragged.constant([[1, 2], [3]])
  >>> _tile_ragged_splits(rt, [3, 2])
  [<tf.Tensor: shape=(7,), dtype=int64,
  numpy=array([ 0,  4,  6, 10, 12, 16, 18])>]
  r(   Nr-   )
r#   r;   rO   r   rH   r   rl   rd   r>   rB   )ro   rc   rj   r#   rp   iprojected_splitssrc_axisdst_axisresult_splitsr*   input_lengthsoutput_lengthsrepeatsdrQ   s                   r_   ri   ri   ?  s   0 $$+,,- 6;;5GHq-*+HH$ Mh(Q,a8 M-6-=-=

!#3H#=hl#K.Mx *MM -K  Hd!$'+mD.A#2.FFM #Ytax%88N
 G4!8R$ "		 OAE$:a$?!!$TAX.8$22>63<QU3CE1q5!!g" ^^NIbqMBN 66~FG/H2 
C Is   Ec                    t        j                  |d| g      5  t        j                  | d      } t        j                  |       st        j                  | |      cddd       S | j                  j                  dn| j                  j                  dz   }t        j                  ||d      }|dk(  r:t        j                  j                  | | j                         dd	
      cddd       S |dk(  r:t        j                  j                  | d| j                         d	
      cddd       S t        j                  | j                        r1| j                  t        | j                  |dz
              cddd       S | j                  t        j                  | j                  |dz
              cddd       S # 1 sw Y   yxY w)a  Inserts a dimension with shape 1 into a potentially ragged tensor's shape.

  Given a potentially ragged tenor `input`, this operation inserts a
  dimension with size 1 at the dimension `axis` of `input`'s shape.

  The following table gives some examples showing how `ragged.expand_dims`
  impacts the shapes of different input tensors.  Ragged dimensions are
  indicated by enclosing them in parentheses.

  input.shape             | axis | result.shape
  ----------------------- | ---- | -----------------------------
  `[D1, D2]`              |  `0` | `[1, D1, D2]`
  `[D1, D2]`              |  `1` | `[D1, 1, D2]`
  `[D1, D2]`              |  `2` | `[D1, D2, 1]`
  `[D1, (D2), (D3), D4]`  |  `0` | `[1, D1, (D2), (D3), D4]`
  `[D1, (D2), (D3), D4]`  |  `1` | `[D1, 1, (D2), (D3), D4]`
  `[D1, (D2), (D3), D4]`  |  `2` | `[D1, (D2), 1, (D3), D4]`
  `[D1, (D2), (D3), D4]`  |  `3` | `[D1, (D2), (D3), 1, D4]`
  `[D1, (D2), (D3), D4]`  |  `4` | `[D1, (D2), (D3), D4, 1]`

  Args:
    input: The potentially tensor that should be expanded with a new dimension.
    axis: An integer constant indicating where the new dimension should be
      inserted.
    name: A name for the operation (optional).

  Returns:
    A tensor with the same values as `input`, with an added dimension of
    size 1 at `axis`.

  #### Examples:

  >>> rt = tf.ragged.constant([[1, 2], [3]])
  >>> print(rt.shape)
  (2, None)

  >>> expanded = tf.expand_dims(rt, axis=0)
  >>> print(expanded.shape, expanded)
  (1, 2, None) <tf.RaggedTensor [[[1, 2], [3]]]>

  >>> expanded = tf.expand_dims(rt, axis=1)
  >>> print(expanded.shape, expanded)
  (2, 1, None) <tf.RaggedTensor [[[1, 2]], [[3]]]>

  >>> expanded = tf.expand_dims(rt, axis=2)
  >>> print(expanded.shape, expanded)
  (2, None, 1) <tf.RaggedTensor [[[1], [2]], [[3]]]>
  RaggedExpandDimsr`   r   Nr(   zrank(input))
ndims_namer   F)uniform_row_lengthnrowsr,   )r   r0   r   r1   r7   r   expand_dimsr4   r5   get_positive_axisr8   from_uniform_row_lengthr   rC   with_values)r`   r*   r    r5   s       r_   r   r     s   d ~~d.8 P<<GE ""5)""5$/P P KK%%-D5;;3D3Dq3HE&&tU}MDqy''??
EKKMU @ LP P 
''??
AU[[]U @ LP P" 
	 	 	.  U\\4!8!DE%P P(   !6!6u||TAX!NO)P P Ps&   AF7%A>F7-5F7,AF7<1F77G c                 &    ||}t        | ||      S )N)r`   r*   r    )r   )r`   r*   r    r]   s       r_   _ragged_expand_dims_v1r     s     	_D	5t$	77ru   c                     t        j                  |       r"t        j                  | j                  ||      S t        j                  | ||      S )a  Returns the size of a potentially ragged tensor.

  The size of a ragged tensor is the size of its inner values.

  #### Example:

  >>> tf.size(tf.ragged.constant([[1, 2], [3]])).numpy().item()
  3

  Args:
    input: A potentially ragged `Tensor`.
    out_type: The numeric output type for the operation.
    name: A name for the operation (optional).

  Returns:
    A Tensor of type `out_type`.
  )r.   r    )r   r7   r   sizerm   r`   r.   r    s      r_   r   r     s>    & U#>>%++hTJJ>>%(>>ru   c                     t        | ||      S )Nr   )r   r`   r    r.   s      r_   _ragged_size_v1r     s    
 
EH4	88ru   c                    t        j                  |d| g      5 }t        j                  |       st	        j
                  | |      cddd       S | j                  t	        j
                  | j                        z   cddd       S # 1 sw Y   yxY w)a  Returns the rank of a RaggedTensor.

  Returns a 0-D `int32` `Tensor` representing the rank of `input`.

  #### Example:

  >>> # shape of tensor 't' is [2, None, None]
  >>> t = tf.ragged.constant([[[1], [2, 2]], [[3, 3, 3], [4, 4, 4, 4]]])
  >>> tf.rank(t).numpy().item()
  3

  Args:
    input: A `RaggedTensor`
    name: A name for the operation (optional).

  Returns:
    A `Tensor` of type `int32`.
  
RaggedRankN)r   r0   r   r7   r   rankr#   rm   )r`   r    s     r_   r   r     sx    ( ~~dL5'2 Ad""5)^^E4(A A y~~e.?.?@@	A A As   +B+BBindicesc                    t        |t              r=|dk\  r8|| j                  k  rt        d|| j                  fz        || j                  z  }t	        j
                  |d| ||||g      5  t        j                  | d      } | j                  t        j                  | j                  ||||||            cddd       S # 1 sw Y   yxY w)z6Applies tf.one_hot along the values of a RaggedTensor.r   z8axis (%d) must be greater than indices.ragged_rank (%d).RaggedOneHotr   r   N)
isinstanceintr#   r6   r   r0   r   r1   with_flat_valuesr   one_hotrm   )r   depthon_value	off_valuer*   r'   r    s          r_   ragged_one_hotr   "  s     ctqyw""" "&(;(;!<= > >GD
~~dNxDAC (>>i!G##'--uh	4	'(	( ( (s   *AB??Czragged.stack_dynamic_partitionsc           
      B   t        j                  |d| ||g      5  t        j                  | d      } t	        | t        j
                        r| j                  j                  nd}t        j                  |d|      }t        j                  |d|j                        }|t        j                  ||      }t        j                  ||j                        }|j                  j                  }|t        d      |j                  j                  d	       |j                  j                  | j                  d|        |d	k(  rTt        j
                  j!                  t#        j$                  | g      t#        j$                  |g      |d
      cddd       S |dk(  rt'        j(                  |d      }t+        j,                  ||      }t+        j,                  | |      }t/        j0                  |dd |d      t/        j2                  |d      g}	t        j4                  |	      5  t        j
                  j!                  |||d
      cddd       cddd       S t	        | t        j
                        s,t        j
                  j7                  | |j                  d      } t	        |t        j
                        sCt        j
                  j7                  ||j                  t9        | j:                  |dz
              }t/        j<                  | j                  |j                  d      }
t        j4                  |
g      5  t?        | j@                  |j@                  |      cddd       cddd       S # 1 sw Y   nxY w# 1 sw Y   nxY wddd       y# 1 sw Y   yxY w)a  Stacks dynamic partitions of a Tensor or RaggedTensor.

  Returns a RaggedTensor `output` with `num_partitions` rows, where the row
  `output[i]` is formed by stacking all slices `data[j1...jN]` such that
  `partitions[j1...jN] = i`.  Slices of `data` are stacked in row-major
  order.

  If `num_partitions` is an `int` (not a `Tensor`), then this is equivalent to
  `tf.ragged.stack(tf.dynamic_partition(data, partitions, num_partitions))`.

  #### Example:

  >>> data           = ['a', 'b', 'c', 'd', 'e']
  >>> partitions     = [  3,   0,   2,   2,   3]
  >>> num_partitions = 5
  >>> tf.ragged.stack_dynamic_partitions(data, partitions, num_partitions)
  <tf.RaggedTensor [[b'b'], [], [b'c', b'd'], [b'a', b'e'], []]>

  Args:
    data: A `Tensor` or `RaggedTensor` containing the values to stack.
    partitions: An `int32` or `int64` `Tensor` or `RaggedTensor` specifying the
      partition that each slice of `data` should be added to. `partitions.shape`
      must be a prefix of `data.shape`.  Values must be greater than or equal to
      zero, and less than `num_partitions`. `partitions` is not required to be
      sorted.
    num_partitions: An `int32` or `int64` scalar specifying the number of
      partitions to output.  This determines the number of rows in `output`.
    name: A name prefix for the returned tensor (optional).

  Returns:
    A `RaggedTensor` containing the stacked partitions.  The returned tensor
    has the same dtype as `data`, and its shape is
    `[num_partitions, (D)] + data.shape[partitions.rank:]`, where `(D)` is a
    ragged dimension whose length is the number of data slices stacked for
    each `partition`.
  SegmentStackr   r   N
partitions)r    preferred_dtypenum_partitionsz partitions must have known rank.r   F)rC   value_rowidsr   r,   r(   T)stabler-   z+partitions must be less than num_partitionsmessagez partitions must be non-negative.)r   r,   )r$   r#   z3data and partitions have incompatible ragged shapes)!r   r0   r   r1   r   r8   r:   r'   convert_to_tensorr   r@   r4   r5   r6   rf   assert_is_compatible_withfrom_value_rowidsr   stackr   argsortr   rH   r   assert_lessassert_non_negativer<   r9   maxr#   assert_equalstack_dynamic_partitionsrC   )r   r   r   r    r$   partitions_rankpermutationr   rC   checkschecks              r_   r   r   ?  se   N ~~dNT:~,NO @8;;DvND dM667 	=A  AA7GIJ**-z?O?OQN#==-=>j]]>:3C3CDN !&&,,O9::((+..tzz:J?/KL! ''99 &&v.&,,j\:	 : 1@8 @8< 
A	 $$Z=k%%j+>lk2f


23CE 
'
'"DF	f ##F+ H));;L < HH HY@8 @8d m889))55:#3#3 6 D
M$>$>?"//;;'--D,,o.AB < D
 $$
//


GIe ##UG, 8'Z5F5F(688 8}@8 @8XH H$8 8}@8 @8 @8sJ   E1NBN%#M4	NC%N !N !	N4M=	9N N		NNr   c                    d}t        j                  |d| |g      5  t        |t        j                        r"t        j                  |      }|>t        |      t        |t        t        f      rt        d |D              st        |      t        j                  | d      } t        |      D cg c]4  \  }}t        j                  || j                   j"                  d|z  d      6 }}}t%        d      g|rt'        |      d	z   nd
z  }|D ]  }t%        ddd      ||<    | t        |         cddd       S c c}}w # 1 sw Y   yxY w)a  Reverses a RaggedTensor along the specified axes.

  #### Example:

  >>> data = tf.ragged.constant([
  ...   [[1, 2], [3, 4]], [[5, 6]], [[7, 8], [9, 10], [11, 12]]])
  >>> tf.reverse(data, axis=[0, 2])
  <tf.RaggedTensor [[[8, 7], [10, 9], [12, 11]], [[6, 5]], [[2, 1], [4, 3]]]>

  Args:
    tensor: A 'RaggedTensor' to reverse.
    axis: A list or tuple of 'int' or a constant 1D 'tf.Tensor'. The indices of
      the axes to reverse.
    name: A name prefix for the returned tensor (optional).

  Returns:
    A 'RaggedTensor'.
  zW`axis` must be a list of int or a constant tensorwhen reversing axes in a ragged tensorReverseNc              3   <   K   | ]  }t        |t                y wN)r   r   ).0r]   s     r_   	<genexpr>zreverse.<locals>.<genexpr>  s     73*S#&7s   r   r   zaxis[%d]zrank(tensor)r(   r   r-   )r   r0   r   
tensor_libTensorr
   rg   	TypeErrorlisttupleallr   r1   	enumerater   r   r4   r   slicer   )r   r*   r    type_error_msgrw   r]   slicess          r_   reverser     sB   (=. ~~dI~6 !$
))*''-d	''e}-7$77n%%==XF  o As 	##C):):JN$2	4D  Dk]tc$i!m;F *$b)fSk* %- 5! !! !s   BE 19D:*AE :E  E	zragged.crossc                     t        | d|      S )aX  Generates feature cross from a list of tensors.

  The input tensors must have `rank=2`, and must all have the same number of
  rows.  The result is a `RaggedTensor` with the same number of rows as the
  inputs, where `result[row]` contains a list of all combinations of values
  formed by taking a single value from each input's corresponding row
  (`inputs[i][row]`).  Values are combined by joining their strings with '_X_'.
  E.g.:

  >>> tf.ragged.cross([tf.ragged.constant([['a'], ['b', 'c']]),
  ...                  tf.ragged.constant([['d'], ['e']]),
  ...                  tf.ragged.constant([['f'], ['g']])])
  <tf.RaggedTensor [[b'a_X_d_X_f'], [b'b_X_e_X_g', b'c_X_e_X_g']]>

  Args:
    inputs: A list of `RaggedTensor` or `Tensor` or `SparseTensor`.
    name: Optional name for the op.

  Returns:
    A 2D `RaggedTensor` of type `string`.
  F)inputshashed_outputr    _cross_internal)r   r    s     r_   crossr     s    0 
e$	GGru   zragged.cross_hashedc                 "    t        | d|||      S )a  Generates hashed feature cross from a list of tensors.

  The input tensors must have `rank=2`, and must all have the same number of
  rows.  The result is a `RaggedTensor` with the same number of rows as the
  inputs, where `result[row]` contains a list of all combinations of values
  formed by taking a single value from each input's corresponding row
  (`inputs[i][row]`).  Values are combined by hashing together their
  fingerprints. E.g.:

  >>> tf.ragged.cross_hashed([tf.ragged.constant([['a'], ['b', 'c']]),
  ...                         tf.ragged.constant([['d'], ['e']]),
  ...                         tf.ragged.constant([['f'], ['g']])],
  ...                        num_buckets=100)
  <tf.RaggedTensor [[78], [66, 74]]>

  Args:
    inputs: A list of `RaggedTensor` or `Tensor` or `SparseTensor`.
    num_buckets: A non-negative `int` that used to bucket the hashed values. If
      `num_buckets != 0`, then `output = hashed_value % num_buckets`.
    hash_key: Integer hash_key that will be used by the `FingerprintCat64`
      function. If not given, a default key is used.
    name: Optional name for the op.

  Returns:
    A 2D `RaggedTensor` of type `int64`.
  T)r   r   num_bucketshash_keyr    r   )r   r   r   r    s       r_   cross_hashedr      s     : 

 ru   l   /{c                    t        | t        t        f      st        d      |t        }g }g }g }g }t        j                  |d|       5  t        |       D ]z  \  }	}
t        j                  |
      r t        j                  j                  |
      }
nt        j                  |
      }
|
j                  j                  r%t!        j"                  |
t$        j&                        }
n7|
j                  t$        j(                  k7  rt+        d|	|
j                  fz        t        |
t        j,                        r>|
j.                  dk7  rt+        d      |j1                  |
       |j1                  d       t        |
t        j                        r$|j1                  |
       |j1                  d       Y|j1                  |
       |j1                  d	       } |rt$        j&                  nt$        j(                  }|r#t3        d
 |D              rt$        j4                  }nt$        j&                  }|dkD  r|dz  }t7        j8                  |D cg c]  }|j:                   c}|D cg c]  }|j<                   c}|D cg c]  }|j>                   c}|D cg c]  }|j:                   c}|D cg c]  }|j@                   c}|djC                  |      ||||jD                  |jD                  |      \  }}t        j,                  jG                  ||d      cddd       S c c}w c c}w c c}w c c}w c c}w # 1 sw Y   yxY w)z@Generates feature cross from a list of ragged and dense tensors.zInputs must be a listNRaggedCrossz#Unexpected dtype for inputs[%d]: %sr(   z0tf.ragged.cross only supports inputs with rank=2RSDc              3   j   K   | ]+  }|j                   j                  t        j                  k(   - y wr   )r:   r'   r   int32)r   ts     r_   r   z"_cross_internal.<locals>.<genexpr>O  s*      C/0fll*Cs   13l            l             )ragged_valuesragged_row_splitssparse_indicessparse_valuessparse_shapedense_inputsinput_orderr   r   r   out_values_typeout_row_splits_typer    Fr+   )$r   r   r   r   _DEFAULT_CROSS_HASH_KEYr   r0   r   r   	is_sparseSparseTensor
from_valuer   r1   r'   
is_integerr   r@   r   int64stringr6   r8   r#   r>   r   r   r   ragged_crossrC   r:   r   dense_shapejoinas_datatype_enumrI   )r   r   r   r   r    ragged_inputssparse_inputsr   r   rw   r   r   r   rtst
values_out
splits_outs                    r_   r   r   (  s    
FUDM	*
+
,,&H--,+
~~dM62 20&!  1		 	 	#&&11!4<<Q?	
		MM!V\\*77fmm#>!QWWMNN	A}11	2==AMN
NQ3a334Q3A3' * '4fllO C4AC C"LL"LL %%h1>>+89Rryy93@AR2==A-:;r

;+89Rryy9/<=bnn=!GGK(#'88/@@J
 %%55J 6 0c20 20F :A;9=O20 20sP   	G>L8L
L8 L$3L89L)L8L.%L8+L3>AL8L88Mc                    t        j                  |d| g      5  t        | t        j                        st        dt        |              t        j                  || j                        }t        j                  | j                         | j                  | j                         |      \  }}}}t        j                  j                  ||d      |fcddd       S # 1 sw Y   yxY w)a*  Fills empty rows in the input `RaggedTensor` with rank 2 with a default

  value.

  This op adds entries with the specified `default_value` for any row in the
  input that does not already have a value.

  The op also returns an indicator vector such that

      empty_row_indicator[i] = True iff row i was an empty row.

  Args:
    ragged_input: A `RaggedTensor` with rank 2.
    default_value: The value to fill for empty rows, with the same type as
      `ragged_input.`
    name: A name prefix for the returned tensors (optional)

  Returns:
    ragged_ordered_output: A `RaggedTensor`with all empty rows filled in with
      `default_value`.
    empty_row_indicator: A bool vector indicating whether each input row was
      empty.

  Raises:
    TypeError: If `ragged_input` is not a `RaggedTensor`.
  RaggedFillEmptyRowsz3ragged_input must be RaggedTensor,             got r&   )r   rC   r   default_valueF)rC   r   r,   N)r   r0   r   r   r8   r   typer   r'   r   ragged_fill_empty_rowsr   rC   r   r   )ragged_inputr   r    output_value_rowidsoutput_valuesempty_row_indicatorunused_reverse_index_maps          r_   fill_empty_rowsr   m  s    6 ~~d1L>B lM$>$>?< !#  ))\//M 	33!..0""  "#		  	""44 , 	5 	

 	)  s   B:CC&r   c                 `    | j                   d   }t        j                  ||      \  }}d|d|gS )z"Gradients for RaggedFillEmptyRows.r/   )reverse_index_mapgrad_valuesN)outputsr   ragged_fill_empty_rows_grad)opunused_grad_output_indicesoutput_grad_valuesunused_grad_empty_row_indicatorunused_grad_reverse_index_mapr   d_valuesd_default_values           r_   _ragged_fill_empty_rows_gradr    s>     jjm2NN)7I(O
 $	00ru   r   r   c                     t        |t              r|dk  rt        d      t        | |||      }t	        |      D cg c]  }||   	 c}S c c}w )z8RaggedTensor dispatch override for tf.dynamic_partition.r   z-num_partitions must be a non-negative integer)r   r   r   r   rO   )r   r   r   r    resultrw   s         r_   dynamic_partitionr    sN     
NC	(NQ,>
C
DD#D*ndK&">2	3&)	33	3s   Avaluec           	      N   t        j                  |d      5  t        j                  | d      } t	        |t
              r|dk(  r| gcddd       S t        j                  |d       t        j                  j                  |       }t        j                  ||j                        }	 ||   }t	        |t
              rC|}|dk  rt        d| d
      t        j                   ||      }t        j"                  ||      }	nd}t        j$                  |      }	|	j&                  j(                  J|	j&                  j(                  dk7  rt+        d| d
      t-        j.                  |	j&                  d         }||t        d| d| d
      |}n|||k7  rt        d| d| d
      t        j0                  dgt        j2                  |	      gd      }
g }|j5                  t        j6                  |d             |j5                  t        j8                  |t        j&                  |	      d   d             |j5                  t        j8                  t        j:                  ||
j<                        |
d   d             t?        j@                  ||
      }
g }tC        d      g|dz   z  }tE        |      D ]7  }tC        |
|   |
|dz            |d<   |j5                  | tG        |                9 |cddd       S # t        $ r t        d| d	| d
      w xY w# 1 sw Y   yxY w)a  Splits a RaggedTensor `value` into a list of sub RaggedTensors.

  If `num_or_size_splits` is an `int`,  then it splits `value` along the
  dimension `axis` into `num_or_size_splits` smaller RaggedTensors. This
  requires that `value.shape[axis]` is divisible by `num_or_size_splits`.

  If `num_or_size_splits` is a 1-D Tensor (or list), then `value` is split into
  `len(num_or_size_splits)` elements. The shape of the `i`-th element has the
  same size as the `value` except along dimension `axis` where the size is
  `num_or_size_splits[i]`.

  Splits along a ragged dimension is not allowed.

  For example:

  >>> rt = tf.RaggedTensor.from_row_lengths(
  ...      np.arange(6 * 3).reshape(6, 3), row_lengths=[1, 2, 2, 1])
  >>> rt.shape
  TensorShape([4, None, 3])
  >>>
  >>> rt1, rt2 = tf.split(rt, 2)  # uniform splits
  >>> rt1.shape
  TensorShape([2, None, 3])
  >>> rt2.shape
  TensorShape([2, None, 3])
  >>>
  >>> rt3, rt4, rt5 = tf.split(rt, [1, 2, 1])  # ragged splits
  >>> rt3.shape
  TensorShape([1, None, 3])
  >>> rt4.shape
  TensorShape([2, None, 3])
  >>> rt5.shape
  TensorShape([1, None, 3])
  >>>
  >>> rt6, rt7 = tf.split(rt, [1, 2], axis=2)  # splits along axis 2
  >>> rt6.shape
  TensorShape([4, None, 1])
  >>> rt7.shape
  TensorShape([4, None, 2])

  Args:
    value: The `RaggedTensor` to split.
    num_or_size_splits: Either an `int` indicating the number of splits
      along `axis` or a 1-D integer `Tensor` or Python list containing the sizes
      of each output tensor along `axis`. If a Python int, then it must evenly
      divide `value.shape[axis]`; otherwise the sum of sizes along the split
      axis must match that of the `value`.
    axis: An `int` or scalar `int32` `Tensor`. The dimension along which
      to split. Must be in the range `[-rank(value), rank(value))`. Defaults to
      0.
    num: An `int` used to specify the number of outputs when
      `num_or_size_splits` is a 1-D list or `Tensor` and its length is
      statically unknown, e.g., specifying `tf.TensorSepc(None)` with
      the `input_signature` argument of `tf.function` (optional).
    name: A name for the operation (optional).

  Returns:
    if `num_or_size_splits` is an `int` returns a list of `num_or_size_splits`
    `RaggedTensor` objects; if `num_or_size_splits` is a 1-D Tensor returns
    `num_or_size_splits.get_shape[0]` `RaggedTensor` objects resulting from
    splitting `value`.

  Raises:
    ValueError: If the dimension `axis` of `value` is a ragged dimension.
    ValueError: If `num` is unspecified and cannot be inferred.
    ValueError: If `num` is specified but doesn't match the length of
      `num_or_size_splits`.
    ValueError: If `num_or_size_splits` is an `int` and less than 1.
    TypeError: If `num_or_size_splits` is not an `int` or 1-D
      list or 1-D `Tensor`.
    InvalidArgumentError: If the `axis` of `value` cannot be exactly splitted
      by `num_or_size_splits`.
    InvalidArgumentError: If `num_or_size_splits` is contains negative integers.
    InvalidArgumentError: If `num_or_size_splits`'s static shape is unknown and
      its dynamic shape is inconsistent `num`.
    InvalidArgumentError: If `num_or_size_splits`'s static rank is unknown and
      `axis` is a negative integer.
  RaggedSplitr  r   r(   NzJ`num_or_size_splits` must be an `int` or 1-D list or `Tensor` of integers.r   z8Cannot split a ragged dimension. Got `value` with shape z and `axis` .z<`num_or_size_splits` must be >=1 if it is an `int`.Received zH`num_or_size_splits` must be an `int` or 1-D list or `Tensor`. Received r   zp`num` must be specified as an `int` when the size of `num_or_size_split` is statically unknown. Received `num`: z and `num_or_size_split`: zF`num` does not match the size of `num_or_size_split`. Received `num`: z" and size of `num_or_size_split`: r)   z*`num_or_size_splits` must be non-negative.z8`num` is inconsistent with `num_or_size_split.shape[0]`.r-   zXCannot exactly split the `axis` dimension of `value` with the given `num_or_size_split`.)$r   r0   r   r1   r   r   r   assert_integer_v2r   DynamicRaggedShaper9   r   r   r   r6   r   floordivrepeatr   r4   r5   r   r	   dimension_valuern   cumsumr>   assert_non_negative_v2assert_equal_v2r@   r'   r   with_dependenciesr   rO   r   )r  num_or_size_splitsr*   numr    value_shapedim_size
num_splitssplit_lengthsplit_lengthsrQ   r   splited_rtsr   rw   s                  r_   splitr$    s   h ~~dM* H<<GE$c*/AQ/FW	H H )+ '99EEeLK&&t[-=-=>DBT"h $c*%j	a %%7$8; < 	<&&x<l&&|Z@m j++,>?m				"	"	.$$) 33E2FaI J J!11-2E2Ea2HI
		; 77:e <33E2FaI J J 
?sj0 CCF% H;;E,aI J J sHOOM$BC!LFF
MM((@	BC MM!!OOM*1-N	PQ
 MM!!MM(FLL12J;	=> //?FKDk]dQh'F: /F1q5M2fRjuV}-./ QH H  B   +}LaA B BBH Hs+   /LAL'K<,IL<LLL$r4   returnc                    t        j                  | d      } t        | t         j                        r| j                  } t        |t
        j                        rLt        j                  | |j                        }t         j                  j                  ||j                  d      S t        j                  |d      }t        j                  | |      S )z#Reshapes a tensor or ragged tensor.r   r   Fr+   r4   )r   r1   r   r8   rC   r   r  r   rL   inner_shape_from_nested_row_partitionsrow_partitionsr   r   )r   r4   rm   s      r_   ragged_reshaper*  o  s     ;;8&223]]F+>>?##FE,=,=>K%%AA B  
 !!%g6EVU++ru   c                 .    t        j                  | |      S )a  Broadcasts a potentially ragged tensor to a ragged shape.

  Tiles `input` as necessary to match the given shape.

  Behavior is undefined if `input` is not broadcast-compatible with `shape`.

  Args:
    input: The potentially ragged tensor to broadcast.
    shape: A `DynamicRaggedShape`

  Returns:
    A potentially ragged tensor whose values are taken from
    `input`, and whose shape matches `shape`.
  )r   broadcast_to)r`   r4   s     r_   r,  r,    s    & 
	*	*5%	88ru   r    c                     t        j                  |d| g      5  t        j                  j	                  | |      cddd       S # 1 sw Y   yxY w)zReturns the shape of a RaggedTensor.

  Args:
    input: A `RaggedTensor`
    name: A name for the operation (optional).
    out_type: dtype used to encode the shape.

  Returns:
    A `tf.experimental.DynamicRaggedShape`
  RaggedShapeN)r   r0   r   r  r9   r   s      r_   ragged_shaper/    sE     ~~dME73 P22>>uhOP P Ps    AAshape_xshape_yc                     t        | t        j                        st        j                  g |       } t        |t        j                        st        j                  g |      }t        j                  | |      S )a  Returns the shape formed by broadcasting two shapes to be compatible.

  1. If shape_x and shape_y both have row_partitions, then fail if their dtypes
     don't match.
  2. If neither has row_partitions and they have different dtypes,
     go with int64.
  3. If one has row_partitions, go with that dtype.

  Args:
    shape_x: A `DynamicRaggedShape`
    shape_y: A `DynamicRaggedShape`

  Returns:
    A `DynamicRaggedShape`.
  Raises:
    ValueError: If `shape_x` and `shape_y` are not broadcast-compatible.
  )r   r   r  broadcast_dynamic_shape)r0  r1  s     r_   r3  r3    s]    , 
G1DD	E"55b'BG	G1DD	E"55b'BG		5	5gw	GGru   c                     ||j                         st        d|       t        j                  | j                  |||      }| j                  |      S zReturns ones shaped like x.0RaggedTensor only allows replicated layout. got )r'   r    layout)is_fully_replicatedr6   r   onesr'  _add_row_partitionsr4   r'   r    r7  rm   s        r_   r9  r9    s^      : : <

:6(C  u4+ 
	"	";	//ru   c                     ||j                         st        d|       t        j                  | j                  |||      }| j                  |      S r5  )r8  r6   r   zerosr'  r:  r;  s        r_   r=  r=    s^      : : <

:6(C  u4+ 
	"	";	//ru   dimsc                     ||j                         st        d|       t        j                  | j                  |||      }| j                  |      S )z=Creates a tensor with shape `dims` and fills it with `value`.r6  )r    r7  )r8  r6   r   fillr'  r:  )r>  r  r    r7  rm   s        r_   r@  r@    s^      : : <

:6(C  
D+ 
	!	!+	..ru   c                    t        j                  |      }t        j                  |d| g      5  t	        j
                  | d      } | j                  j                  |j                  k  rO| j                  j                  j                  dk  r,t        d| j                  j                  j                         | j                  t        j                  | j                  |            cddd       S # 1 sw Y   yxY w)z.RaggedTensor dispatch override for tf.bitcast.Bitcastr`   r   r%   zb`input.flat_values` is required to have rank >= 2 when input.dtype.size < type.size. Actual rank: N)r   as_dtyper   r0   r   r1   r'   r   rm   r4   r   r6   r   r   bitcast)r`   r   r    s      r_   rD  rD    s     
	$
~~dIw/ N<<GE499$):):)@)@)E)E)I E++116679 : : !!)"3"3E4E4Et"LMN N Ns   B8C00C9r   )NNN)NNNNN)r   NN)Fr   NN)NN)Q__doc__typingr   r   tensorflow.python.frameworkr   r   r   r   r   r	   r
   tensorflow.python.opsr   r   r   r   r   r   r   r   tensorflow.python.ops.raggedr   r   r   r   r   r   tensorflow.python.typesr   
core_typestensorflow.python.utilr    tensorflow.python.util.tf_exportr   add_dispatch_supportrD   dispatch_for_apird   Raggedrh   ri   expand_dims_v2r   r   size_v2r   r   r   r   r   r   r   r   r   r   r   r   r   RegisterGradientr  r  RaggedOrDenser$  rL   DenseOrRaggedShaper8   r   r*  r,  r  r4   strr/  r3  r9  float32r=  r@  
TensorLikerD   ru   r_   <module>rZ     s   *   . + 5 < 4 3 + 1 + 2 / 6 * * = > 8 6 4 7 6 + 6  !	`  "`L 9>>*'$$ ' +'T8<v@P 9334EP}++ EP 5EPP 9001 
		88 28 9,,-/5||$ ?$$ ? .?0 9>>* 
\\99 +9 9>>*A$$ A +A: 9,,- !!(M00 ( .(8 ,-	e8  .e8V 9,,-0!M(( 0! .0!p >	H  H2  !	   " F '  #( !!	B0J6r +,1 -1* =::;  4M77 4"/"="=4 <4 9??+ 	[%% [ ,[F 9,,-,'',22, =%%z'8'889, .,* 91129&&9229 =%%z'8'8899 39. 9??+ \\PP
3-P 3EEP ,P$ 9<<=H!44H!44H ,,H >H8 9>>* ..		0220
   0 +0" 9??+ ..		0220
   0 ,0" 9>>* 	/

1
1/  / 3-/
   / +/( 9,,- 
N&&N  --N .Nru   