
    6bi<                         S r SSKJs  Jr  SSKJr  SSKJr  SSK	J
r
  SSKJr  SSKJr  SSKJr  SS	KJr  SS
KJr  \" S5       " S S\5      5       rg)z8Wrapper layer to apply every temporal slice of an input.    N)backend)Layer)	InputSpec)Wrapper)generic_utils)layer_utils)tf_utils)keras_exportzkeras.layers.TimeDistributedc                   ^   ^  \ rS rSrSrU 4S jrS rS rU 4S jrS r	SS jr
SS	 jrS
rU =r$ )TimeDistributed    a"  This wrapper allows to apply a layer to every temporal slice of an input.

Every input should be at least 3D, and the dimension of index one of the
first input will be considered to be the temporal dimension.

Consider a batch of 32 video samples, where each sample is a 128x128 RGB
image with `channels_last` data format, across 10 timesteps.
The batch input shape is `(32, 10, 128, 128, 3)`.

You can then use `TimeDistributed` to apply the same `Conv2D` layer to each
of the 10 timesteps, independently:

>>> inputs = tf.keras.Input(shape=(10, 128, 128, 3))
>>> conv_2d_layer = tf.keras.layers.Conv2D(64, (3, 3))
>>> outputs = tf.keras.layers.TimeDistributed(conv_2d_layer)(inputs)
>>> outputs.shape
TensorShape([None, 10, 126, 126, 64])

Because `TimeDistributed` applies the same instance of `Conv2D` to each of
the timestamps, the same set of weights are used at each timestamp.

Args:
  layer: a `tf.keras.layers.Layer` instance.

Call arguments:
  inputs: Input tensor of shape (batch, time, ...) or nested tensors,
    and each of which has shape (batch, time, ...).
  training: Python boolean indicating whether the layer should behave in
    training mode or in inference mode. This argument is passed to the
    wrapped layer (only if the layer supports this argument).
  mask: Binary tensor of shape `(samples, timesteps)` indicating whether
    a given timestep should be masked. This argument is passed to the
    wrapped layer (only if the layer supports this argument).

Raises:
  ValueError: If not initialized with a `tf.keras.layers.Layer` instance.
c                    > [        U[        5      (       d  [        SU 35      e[        TU ]  " U40 UD6  SU l        [        R                  " U5      =(       a    [        USS5      (       + U l	        g )Nz]Please initialize `TimeDistributed` layer with a `tf.keras.layers.Layer` instance. Received: TstatefulF)

isinstancer   
ValueErrorsuper__init__supports_maskingr   is_builtin_layergetattr_always_use_reshape)selflayerkwargs	__class__s      b/home/james-whalen/.local/lib/python3.13/site-packages/tf_keras/src/layers/rnn/time_distributed.pyr   TimeDistributed.__init__H   sx    %''??DgG  	)&) $ $/#?#?$
 $4%U33 	     c                    [         R                  " U5      US n[        S U 5       5      (       d  X-   $ [         R                  " U5      n[	        U5      n[        U5       H  u  pgUb  M
  XSU-      XF'   M     U[        U5      -   $ )ab  Finds non-specific dimensions in the static shapes.

The static shapes are replaced with the corresponding dynamic shapes of
the tensor.
Args:
  init_tuple: a tuple, the first part of the output shape
  tensor: the tensor from which to get the (static and dynamic) shapes
    as the last part of the output shape
  start_idx: int, which indicate the first dimension to take from
    the static shape of the tensor
Returns:
  The new shape with the first part from `init_tuple` and the last part
  from or `tensor.shape`, where every `None` is replaced by the
  corresponding dimension from `tf.shape(tensor)`.
Nc              3   (   #    U  H  oS L v   M
     g 7fN ).0ss     r   	<genexpr>3TimeDistributed._get_shape_tuple.<locals>.<genexpr>i   s     0i9is   )r   	int_shapeanyshapelist	enumeratetuple)r   
init_tupletensor	start_idxr'   r)   ir$   s           r   _get_shape_tuple TimeDistributed._get_shape_tupleW   s    " %%f-ij9	0i000))f%O	i(DAy$]3	 ) E),,,r   c                 b    UR                  5       n[        R                  " US   /USS  -   5      $ )Nr      as_listtfTensorShape)r   dimss     r   _remove_timesteps!TimeDistributed._remove_timestepsr   s-    ||~~~tAwi$qr(233r   c                    > [         R                  " USS9n[        R                  R	                  [        R                  R                  S U5      5      n[        S U 5       5      (       a  [        SU 35      e[        R                  R                  S U5      U l        [        R                  R                  U R                  U5      n[         R                  " U5      n[        TU ]-  [        U5      5        SU l        g )NF	to_tuplesc                     U R                   $ r!   )ndimsxs    r   <lambda>'TimeDistributed.build.<locals>.<lambda>y   s    AGGr   c              3   *   #    U  H	  oS :  v   M     g7f)   Nr"   )r#   dims     r   r%   (TimeDistributed.build.<locals>.<genexpr>{   s     -*3Qw*s   za`TimeDistributed` Layer should be passed an `input_shape ` with at least 3 dimensions, received: c                 @    [        S S /U R                  5       SS  -   S9$ )Nr4   )r)   )r   r6   rA   s    r   rC   rD      s    itTlQYY[_&DEr   T)r	   convert_shapesr7   nestflattenmap_structurer(   r   
input_specr:   r   buildr,   built)r   input_shape
input_dimschild_input_shaper   s       r   rO   TimeDistributed.buildv   s    --kUKWW__GG!!"3[A

 -*---99DG 
 ''//E
 GG11""K
 %334EFe-./
r   c                   ^ [         R                  " USS9n[        R                  R	                  U R
                  U5      nU R                  R                  U5      n[         R                  " USS9n[         R                  " U5      m[        R                  R                  T5      S   mU4S jn[        R                  R	                  XC5      $ )NFr=      c                 f   > U R                  5       n [        R                  " U S   T/U SS  -   5      $ )Nr   rV   r5   )r9   	timestepss    r   insert_timesteps>TimeDistributed.compute_output_shape.<locals>.insert_timesteps   s1    <<>D>>47I"6ab"ABBr   )	r	   rJ   r7   rK   rM   r:   r   compute_output_shaperL   )r   rQ   rS   child_output_shaperY   rX   s        @r   r[   $TimeDistributed.compute_output_shape   s    --kUKGG11""K
 "ZZ<<=NO%44%
 ++K8	GGOOI.q1		C ww$$%5JJr   c           	      P  ^ ^^^^^ 0 m[         R                  " T R                  R                  S5      (       a  UTS'   [        R
                  R                  S U5      n[        R                  " U5      n[        R
                  R                  U5      S   nU(       a  T R                  (       d  [        R                  " U5      u  nmTS Lm[        R                  " U5      m[        R
                  R                  T5      S   mUU 4S jn[        R                  " UU/ T(       a  TS   OTUSS9u  pxn[        R
                  R                  UU4S jU5      n	U	$ [        R
                  R                  S	 U5      m[        R
                  R                  T5      m[        T5      (       a  [        R
                  R                  S
 U5      n
[        R
                  R                  S U5      nT R                  " U
40 TD6n	[        R
                  R                  [        R                  R                   X5      n	U	$ [#        T5      (       a  [%        SU 35      e[        R                  " U5      m[        R
                  R                  T5      S   mT(       dW  [        R
                  R                  S U5      m[         R&                  " [        R
                  R                  T5      5      S   m[        R
                  R                  U 4S jU5      n[        R(                  R
                  R+                  U[        R,                  X5      n[         R                  " T R                  R                  S5      (       a/  Ub,  T R/                  SUS5      n[        R,                  " X=5      TS'   T R                  " U40 TD6n	U(       a  UOSm[        R
                  R                  UUU 4S jU	5      n[        R(                  R
                  R+                  U	[        R,                  X5      n	U	$ )Ntrainingc                 V    [         R                  " [        R                  " U 5      5      $ r!   r7   r8   r   r'   rA   s    r   rC   &TimeDistributed.call.<locals>.<lambda>       bnnW%6%6q%9:r   r   rV   c                 2   > TR                   " U 40 TD6nU/ 4$ r!   )r   )rB   _outputr   r   s      r   step"TimeDistributed.call.<locals>.step   s     A00rz!r   F)initial_statesinput_lengthmaskunrollc                 4   > [         R                  " TU T5      $ r!   )r   maybe_convert_to_ragged)rf   is_ragged_inputrow_lengthss    r   rC   rb      s    w>>#V[ r   c                 6    [        U [        R                  5      $ r!   r   r7   RaggedTensorrA   s    r   rC   rb      s    *Q8r   c                     U R                   $ r!   )valuesrA   s    r   rC   rb      s    qxxr   c                 (    U R                  5       S   $ )Nr   )nested_row_lengthsrA   s    r   rC   rb      s    a224Q7r   zDAll inputs has to be either ragged or not, but not mixed. Received: c                 4    [         R                  " U 5      S   $ NrV   )r7   r)   rA   s    r   rC   rb      s    "((1+a.r   c                 *   > TR                  SU S5      $ Nr4   r1   )rB   r   s    r   rC   rb      s    d33E1a@r   rk   r|   r4   r}   c                 .   > TR                  TT4U S5      $ ry   r~   )r.   rj   reshape_batch_sizer   s    r   rC   rb      s    4#8#8+\:FA$r   )r   has_argr   callr7   rK   rM   r	   rJ   rL   r   r   convert_inputs_if_raggedrnnallrs   from_row_lengthsr(   r   to_list__internal__map_structure_up_toreshaper1   )r   inputsr_   rk   rQ   
batch_sizerg   re   outputsyinput_valuesinput_row_lenghtsinner_input_shapeinner_mask_shapeoutput_shaperj   ro   r   r   rp   s   `              @@@@@r   r   TimeDistributed.call   s\     *==!)F:gg++:F
 ,,[9
WW__Z03
d66")"B"B6"JFK)5O#22;?L77??<8;L" $KK!" )^!	MA %% 	AP } !gg338&O !ggooo>O?##!ww445GP$&GG$9$97%! JJ|6v6GG))OO44ah c _%% 006x9 
  (66{C!ww|<Q?##%77#8#80&$L $1#8#85$$L %'GG$9$9@&%!
 --AABJJ
 "))$**//6BB('+'<'<UD!'L$%,__T%LF6NJJv00 4>Z2"!ww44 	  OO((<<rzz1 r   c                 :  ^  [         R                  R                  S U5      n[        R                  " USS9n[        R                  " U5      n[         R                  R                  U5      S   n[         R                  R                  S U5      n[        R                  " [         R                  R                  U5      5      nU(       a  T R                  (       a  [        U5      (       a  U$ UnUb)  T R                  SUS5      n[        R                  " Xg5      n[         R                  R                  U 4S	 jU5      n[         R                  R                  R                  U[         R                  X5      n	T R                  R!                  X5      n
U
cM  Uc  gUn
[#        S[%        [        R&                  " U5      5      5       H  n[        R                  " U
S
S9n
M     U
$ [        R                  " U5      n[         R                  R                  U5      S   nU(       dC  [         R                  R                  S U5      n[         R                  R                  U5      S   nU(       a  UOS
nT R                  X4U
S5      n[        R                  " X5      n
U
$ )a6  Computes an output mask tensor for Embedding layer.

This is based on the inputs, mask, and the inner layer.
If batch size is specified:
Simply return the input `mask`. (An rnn-based implementation with
more than one rnn inputs is required but not supported in tf.keras yet.)
Otherwise we call `compute_mask` of the inner layer at each time step.
If the output mask at each time step is not `None`:
(E.g., inner layer is Masking or RNN)
Concatenate all of them and return the concatenation.
If the output mask at each time step is `None` and the input mask is not
`None`:(E.g., inner layer is Dense)
Reduce the input_mask to 2 dimensions and return it.
Otherwise (both the output mask and the input mask are `None`):
(E.g., `mask` is not used at all)
Return `None`.

Args:
  inputs: Tensor with shape [batch size, timesteps, ...] indicating the
    input to TimeDistributed. If static shape information is available
    for "batch size", `mask` is returned unmodified.
  mask: Either None (indicating no masking) or a Tensor indicating the
    input mask for TimeDistributed. The shape can be static or dynamic.

Returns:
  Either None (no masking), or a [batch size, timesteps, ...] Tensor
  with an output mask for the TimeDistributed layer with the shape
  beyond the second dimension being the value of the input mask shape(if
  the computed output mask is none), an output mask with the shape
  beyond the first dimension being the value of the mask shape(if mask
  is not None) or output mask with the shape beyond the first dimension
  being the value of the computed output shape.

c                 V    [         R                  " [        R                  " U 5      5      $ r!   ra   rA   s    r   rC   .TimeDistributed.compute_mask.<locals>.<lambda>/  rc   r   Fr=   r   c                 6    [        U [        R                  5      $ r!   rr   rA   s    r   rC   r   5  s    jBOO4r   Nr|   r4   c                 *   > TR                  SU S5      $ r{   r~   )r.   r   s    r   rC   r   D  s    400Br   r}   )axisrV   c                 4    [         R                  " U 5      S   $ ry   )r   r)   rA   s    r   rC   r   X  s    gmmA.q1r   )r7   rK   rM   r	   rJ   rL   r   r   r   r(   r1   r   r   r   r   r   compute_maskrangelenr'   )r   r   rk   rQ   r   ro   
inner_maskr   r   inner_inputsoutput_maskre   rj   r   output_mask_shapes   `              r   r   TimeDistributed.compute_mask	  s   J gg++:F
 --kUK,,[9
WW__Z03
''//4f
 (//GGOOO,
 d66#o:N:N K
!#44UD!D FJGG11BF
 ++??BJJ
 jj--lG| K1c'"3"3D"9:;%kk+B? <   $22;?L77??<8;L!ww4416   "ww|<Q?/9r $ 5 5#2K! "//+IKr   )r   rP   rN   r   )NNr!   )__name__
__module____qualname____firstlineno____doc__r   r1   r:   rO   r[   r   r   __static_attributes____classcell__)r   s   @r   r   r       s6    $L4-64,K&hTW Wr   r   )r   tensorflow.compat.v2compatv2r7   tf_keras.srcr   tf_keras.src.engine.base_layerr   tf_keras.src.engine.input_specr   $tf_keras.src.layers.rnn.base_wrapperr   tf_keras.src.utilsr   r   r	    tensorflow.python.util.tf_exportr
   r   r"   r   r   <module>r      sP    ? " !   0 4 8 , * ' : ,-g  .r   