
    2Vh`c                         d dl Zd dlZd dlmZ d dlmZ d dlmZ 	 	 	 	 	 	 	 	 ddZd Z	d Z
d Zd	 Zd
 Zd Z	 ddZ	 	 	 	 ddZd Zd Zy)    N)tree)convert_to_tensor)
get_devicec           	      P   	
./01234567 xs j                   d   d }|st        j                  |      t        j                        }|d   j                   d   }|}|t|j                  t
        j                  k7  r|j                  t
        j                        }t        |j                         dk(  rt        j                  |d      }|s ||      }g dd.|r|st        d      t              }g }g }fd}t        j                        rt        j                  |      6n	 |      f66fd	}|t        j                  |      }r!t        j                  ||j                   
      }t        |      D ]  } ||      }||   3  |t        |      t              z         \  }} .3|      }|st        j                   |      }n|d   }t        j"                  |||      }t        j                  |      }t        j                  |      }t        .3fd|D              }t        d t%        |||      D              }t        j&                  ||      }
r$|j)                  |       |j)                  |       |g}|g} |d   }|d   }t        j*                  |      }	rt        j"                   .|d   |      |t        j                   |            }t        j"                   .||d      |t        j                   |            }n^t        |      D ]V  } ||      }  |t        |      t              z         \  }}
r#|j)                  |       |j)                  |       Q|g}|g}X |d   }|d   }t        j*                  |      }nt              }t        fd|D              2t        j&                  |D cg c]  }|d   	 c}      }   | t              t              z         \  }!}"
r|nd}#g }$t        j                  |!      D ]M  }%t-        |%      }&t        |%      |#k  r!|&j/                  g g|#t        |%      z
  z         |$j)                  |&       O t        j0                  dt
        j2                        }'|}(n/t5        d      r!t7              t        j8                        }(n}(|Brt        j                  |dg      }t-        t        j                  |            44fd5.fd0n]t;        t
        j<                        rAr6t        j8                  d      })t        j>                  |)dz
        77fd5nfd5d 0nd 55nt        d t        j                  |!      D              10125
 	f	d}*d}+|$|1}}},|'|k  rp|+|(k  rk |*|'|,|g| }-|-d d \  }'},}|-dd  }|+dz  }+|'|k  rH|+|(k  r)nA2
 fd}*d}+|$},|}|'|k  r,|+|(k  r' |*|'|,g| }-|-d d \  }'},|-dd  }|+dz  }+|'|k  r|+|(k  r'd /-d   }$t        /fd|$D              }t        d |D              }t        j&                  |!|      }t        j&                  |!|      }|st        j                  ||      }|||fS c c}w )N   c                     t        t        t        | j                                    }d\  |d<   |d<   t	        j
                  | |      S )Nr   r   r   r   )listrangelenshapetorchpermute)input_taxess     K/home/dcms/DCMS/lib/python3.12/site-packages/keras/src/backend/torch/rnn.pyswap_batch_timestepz rnn.<locals>.swap_batch_timestep   s=    E#gmm,-.Qa}}Wd++    r      c                    t        j                  |       rt        d|        t        j                  |      rt        d|       t        |j                        t        | j                        z
  }t        |      D ]  }t        j                  | d      }  dg|z  t        |j                  |d        z   }t        j                  | |      S )Nz:mask_t is expected to be tensor,                  but got z;input_t is expected to be tensor,                  but got r   r   )
r   	is_nested
ValueErrorr   r   r   r   	unsqueezer
   tile)mask_tr   	fixed_dim	rank_diff_	multipless         r   _expand_maskzrnn.<locals>._expand_mask0   s    >>&!!($  >>'"")%  &V\\)::	y! 	1A__VR0F	1C)Od7==+D&EE	zz&),,r   z/Unrolling requires a fixed number of timesteps.c                 F    t        j                  |       } r| d d d   } | S )Nr   )r   unbind)r   go_backwardss    r   _process_single_input_tz$rnn.<locals>._process_single_input_tM   s&    ll7+G!$B$-Nr   c                 ^    D cg c]  }||    	 }}t        j                  |      S c c}w N)r   pack_sequence_as)timet_inpinputsprocessed_inputs      r   _get_input_tensorzrnn.<locals>._get_input_tensorZ   s2    &562d86C6((55 7s   *dimsc              3   0   K   | ]  } |        y wr'    ).0sr!   r   s     r   	<genexpr>zrnn.<locals>.<genexpr>t   s      %01L+%s   c              3   R   K   | ]  \  }}}t        j                  |||       ! y wr'   r   where)r3   mr4   pss       r   r5   zrnn.<locals>.<genexpr>w   s+      * 1b KK1b)*   %'r   c           	   3      K   | ]W  }st        t        j                  |            n2t        t        j                  t        j                  |d g                   Y yw)r   N)r
   r   r#   flip)r3   input_r$   s     r   r5   zrnn.<locals>.<genexpr>   sR      
  $ U\\&)*%,,uzz&1#'>?@A
s   AA dtype__len__c                     |    S r'   r2   )r)   mask_tas    r   
masking_fnzrnn.<locals>.masking_fn   s    t}$r   c                 j     t         fd|D              }t        d t        |||      D              S )Nc              3   Z   K   | ]"  } |t        j                                $ yw)r<   N)r   r   )r3   or!   r   s     r   r5   z5rnn.<locals>.compute_masked_output.<locals>.<genexpr>   s.      % !c&,,6GHH%s   (+c              3   R   K   | ]  \  }}}t        j                  |||       ! y wr'   r7   )r3   r9   rH   fms       r   r5   z5rnn.<locals>.compute_masked_output.<locals>.<genexpr>   s+       1b KK1b)r;   tuplezip)r   flat_out	flat_masktiled_mask_tr!   s   `   r   compute_masked_outputz"rnn.<locals>.compute_masked_output   s?    $ %%%    $'h	$J  r   dimc                 0    t        j                  |       S r'   )r   less)r)   rev_input_lengths    r   rE   zrnn.<locals>.masking_fn   s     ::&6==r   c                 0    t        j                  |       S r'   )r   greater)r)   input_lengths    r   rE   zrnn.<locals>.masking_fn   s     ==t<<r   c                 @     t         fdt        ||      D              S )Nc              3   R   K   | ]  \  }}t        j                  ||         y wr'   r7   )r3   rH   zor   s      r   r5   z5rnn.<locals>.compute_masked_output.<locals>.<genexpr>   s*      B KK2.s   $'rK   )r   rN   rO   s   `  r   rQ   z"rnn.<locals>.compute_masked_output   s$     #&x#;  r   c              3   F   K   | ]  }t        j                  |        y wr'   )r   
zeros_liker3   rH   s     r   r5   zrnn.<locals>.<genexpr>   s       %()  #%s   !c                 (  	  t         fdD              }t        j                  |      }        } |t        |      t              z         \  }}t        j                  |      }rnt        j                  |      }	 |||	      }
t        j                  |      }t        j                  |      } |||      }t        j                  ||      }r nd}t	        ||
      D ]
  \  }}|||<     dz   |t        |
      ft        |      z   S )as  RNN step function.

                Args:
                    time: Current timestep value.
                    output_ta_t: TensorArray.
                    prev_output: tuple of outputs from time - 1.
                    *states: List of states.

                Returns:
                    Tuple: `(time + 1, output_ta_t, output) + tuple(new_states)`
                c              3   (   K   | ]	  }|     y wr'   r2   r3   tar)   s     r   r5   z%rnn.<locals>._step.<locals>.<genexpr>       %B2bh%B   r   r   rL   r   r(   flattenrM   )r)   output_ta_tprev_outputstatescurrent_inputr   output
new_statesflat_outputflat_mask_outputflat_new_output
flat_stateflat_new_stateflat_final_stateta_index_to_writerc   outrQ   	constantsflat_zero_outputinput_tar,   rE   return_all_outputsstep_functionzero_output_for_masks   `                r   _stepzrnn.<locals>._step  s0    !&%B%B B $ 5 5fm L#D)%2!5=53C#C&"
 #ll62 , %k2 !
 #8K)9#
 "\\&1
!%j!9#8NJ$  "22:?OP
,>DA!";@ 0GB,/B()0 q+u_/EFJ  r      c                     t         fdD              }t        j                  |      } |t        |      t              z         \  }}t        j                  |      }t        j                  |      }r nd}t	        ||      D ]
  \  }	}
|
|	|<    t        j                  |      } dz   |ft        |      z   S )a)  RNN step function.

                Args:
                    time: Current timestep value.
                    output_ta_t: TensorArray.
                    *states: List of states.

                Returns:
                    Tuple: `(time + 1,output_ta_t) + tuple(new_states)`
                c              3   (   K   | ]	  }|     y wr'   r2   rb   s     r   r5   z%rnn.<locals>._step.<locals>.<genexpr>J  rd   re   r   r   rf   )r)   rh   rj   rk   rl   rm   rr   rn   rt   rc   ru   rv   initial_statesrx   r,   ry   rz   s   `          r   r|   zrnn.<locals>._step?  s     !&%B%B B $ 5 5fm L%2!5=53C#C&"
 "&j!9"ll62,>DA!";< 0GB,/B()0 "22"N
 q+.z1BBBr   c                     t        | D cg c]  }|j                   c}      }g }t        |       D ]&  \  }}|j                  |k(  s|j                  |       ( t	        j
                  |      S c c}w r'   )maxndim	enumerateappendr   stack)tensor_listt	max_ndimsmax_listis        r   _stackzrnn.<locals>._stackd  sf    [9QVV9:IH!+. '166Y&OOA&' ;;x(( :s   A/c              3   .   K   | ]  } |        y wr'   r2   )r3   rH   r   s     r   r5   zrnn.<locals>.<genexpr>n  s     5aq	5s   c              3   &   K   | ]	  }|d      yw)r   Nr2   r_   s     r   r5   zrnn.<locals>.<genexpr>o  s     3aAbE3s   )r   ) r   r   map_structurerg   rA   r   booltyper   r   r   rL   r   r#   r>   r   r^   r8   rM   r(   r   r   r
   extendtensorint32hasattrr   r   
isinstanceTensorsubtract)8rz   r,   r   r$   maskrv   unrollrY   
time_majorr{   ry   r   flattened_inputs
time_stepstime_steps_trj   successive_statessuccessive_outputsr%   r.   	mask_listr   r+   rl   rm   rP   ri   flat_statesflat_new_statesflat_final_stateslast_outputoutputsinput_time_zerooutput_time_zeror   output_ta_size	output_taru   out_listr)   max_iterationsmax_lenr|   itrh   final_outputsr!   r   rQ   rw   rx   r   rD   rE   r-   rV   s8   ```` ` ` ``                                   @@@@@@@@@@r   rnnr   	   s     26<<?L, ##$7@||F+!!$**1-JL::#99UZZ(Dtzz?a??4,D&t,D	-" NOO~&	 >>&!"00'O  7v>@O	6 T*I!JJyyG	:& !1'*"1%2vy)99&"
  ,FF;)"'"2"26":K"4R"8K\6;G"ll62"&,,z":$ %5@%   %* *$'$o{%* %! ..v7HI%&--f5%,,V4*0&)/%C!1D -R0K*2.Jkk"45G##kk 2<$$[1
  ++ w!<$$W- :& 
1'*!.vy)99" &&--f5%,,V4*0&)/%
1 -R0K*2.Jkk"45G ~&  
 +
 
 //'78SV8
 ,U>2U95EE
! *<	<< 01 	'CCyH3x.(S(A BCX&		' ||AU[[1)N|Y/0>!&<!8!-zz$,5<<-.G% ell3))La8#(>>'A+|#L >
= J!  % %-1\\:J-K%  , ,\ B  &1K
 %"~*= %+{!5?! 2?r1B.k;*12.
a %"~*=C C8 B#KJ%"~*= %dK E* E$1"1$5!k*12.
a	 %"~*=	) "!$	59553733''(8'B++,<kJ$$%8'B++A 9s    Z#
c                 &   | j                   d   }t        j                  | d      }| j                   d   }t        j                  || j                        j                  |d      }||j                  d      k  }t        j                  | |k(        S )aJ  Check the mask tensor and see if it right padded.

    cuDNN uses the sequence length param to skip the tailing
    timestep. If the data is left padded, or not a strict right padding (has
    masked value in the middle of the sequence), then cuDNN won't work
    properly in those cases.

    Left padded data: [[False, False, True, True, True]].
    Right padded data: [[True, True, True, False, False]].
    Mixture of mask/unmasked data: [[True, False, True, False, False]].

    Note that for the mixed data example above, the actually data RNN should see
    are those 2 Trues (index 0 and 2), the index 1 False should be ignored and
    not pollute the internal states.

    Args:
        mask: the Boolean tensor with shape [batch, timestep]

    Returns:
        boolean scalar tensor, whether the mask is strictly right padded.
    r   rR   r   device)r   r   sumaranger   repeatr   all)r   max_seq_lengthcount_of_true
batch_sizeindicesright_padded_masks         r   _is_sequence_right_paddedr   z  s    . ZZ]NIId*MAJll>$++>EEAG  -"9"9!"<<99T..//r   c                 X    t        j                  t        j                  |  d            S )Nr   rR   )r   anyr   )r   s    r   _has_fully_masked_sequencer     s      99UYYu!,--r   c                 v    t        |        }t        |       }||z  }|j                         sd}t        |      y )Na  You are passing a RNN mask that does not correspond to right-padded sequences, while using cuDNN, which is not supported. With cuDNN, RNN masks can only be used for right-padding, e.g. `[[True, True, False, False]]` would be a valid mask, but any mask that isn't just contiguous `True`'s on the left and contiguous `False`'s on the right would be invalid. You can pass `use_cudnn=False` to your RNN layer to stop using cuDNN (this may be slower).)r   r   itemr   )r   no_fully_maskedis_right_paddedvaliderror_messages        r   _assert_valid_maskr     sI    1$77O/5Oo-E::<B 	 '' r   c                 X    |sdnd}t        j                  | j                         |      S )a]  Calculate the sequence length tensor (1-D) based on the masking tensor.

    The masking tensor is a 2D boolean tensor with shape [batch, timestep]. For
    any timestep that should be masked, the corresponding field will be False.
    Consider the following example:
      a = [[True, True, False, False]
           [True, True, True, False]]
    It is a (2, 4) tensor, and the corresponding sequence length result should
    be 1D tensor with value [2, 3]. Note that the masking tensor must be right
    padded that could be checked by, e.g., `is_sequence_right_padded()`.

    Args:
        mask: Boolean tensor with shape [batch, timestep] or [timestep, batch]
            if time_major=True.
        time_major: Boolean, which indicates whether the mask is time major or
            batch major.

    Returns:
        sequence_length: 1D int32 tensor.
    r   r   rR   )r   r   int)r   batch_firsttimestep_indexs      r   "_compute_sequence_length_from_maskr     s$    * *QqN99TXXZ^44r   c                 ,   | j                  |      } | j                  }t        j                  |dd      \  }}}}	t        j                  ||||	gd      j
                  }
t        j                  |dd      \  }}}}t        j                  ||||gd      j
                  }|#t        |d      }t        j                  |      }n4t        j                  d|z  |      }t        j                  d|z  |      }t        |
d      j                         }t        |d      j                         }t        |d      j                         }t        |d      j                         }|j                  |      }|j                  |      }|j                  |      }|j                  |      }t        j                         5  | j                  j                  |       | j                  j                  |       | j                  j                  |       | j                   j                  |       ddd       | j#                          | j%                         D ]2  }|j&                  |k7  s|j(                  j                  |      |_        4 y# 1 sw Y   _xY w)aV  Copies kernel and recurrent kernel weights in the Pytorch format
    We split the kernel and recurrent kernel weights, create associated
    torch tensors adapted to be in line with the Cudnn optimization.
    After we have copied the weights, we ensure the paramters are on
    the same device and memory layout is optimized for Cudnn.

       r   )axisNfloat32r@   r   )tohidden_sizenpsplitconcatenateTr   r   r^   zeros
contiguousno_gradweight_ih_l0copy_weight_hh_l0
bias_ih_l0
bias_hh_l0flatten_parameters
parametersr   data)lstmkernelrecurrent_kernelbiasr   r   i_kf_kc_ko_kweight_ih_datai_rf_rc_ro_rweight_hh_databias_ih_databias_hh_data	weight_ih	weight_hhbias_ihbias_hhparams                          r   prepare_lstm_weightsr     s!    776?D""K &!!4Cc3^^S#sC$8qACCN"2AA>Cc3^^S#sC$8qACCN(Y?''5 {{1{?6B{{1{?6B ".	BMMOI!.	BMMOII>IIKGI>IIKG V$IV$Ijj Gjj G 
 '	*	*g&g&	' 	 " /<<6!v.EJ/' 's   ?A-J

Jc                      t         j                  j                         xr( t         j                  j                  j                         S r'   )r   cudais_availablebackendscudnnr2   r   r   _is_cuda_cudnn_availabler     s-    ::""$L)=)=)J)J)LLr   c                     ddl m} ddl m} | |j                  t        j                  |j                  fv xr> ||j
                  t        j
                  |j
                  fv xr | xr |xr
 t               S )Nr   )activations)ops)	keras.srcr   r   tanhr   sigmoidr   )
activationrecurrent_activationr   use_biasr   r   s         r   cudnn_okr    sv     & 	{''SXX>> 	' <=	' J	' 		'
 %&r   c                    t        ||||d u      }|st        t               }ddlm} t        ||      r|j                  }t        ||      r|j                  }t        ||      r|j                  }t        | d      } t        |d      }t        |d      }|t        |d      }|
r8|rdnd}t        j                  | |g      } |t        j                  ||g      }| j                  |      } |j                  |      }|j                  |      }||j                  |      }	 t        | ||||||||
|	|      S # t        $ r t        w xY w)	N)r  r   )Variabler   r@   r   r   r/   )r  NotImplementedErrorr   keras.src.backend.torchr	  r   valuer   r   r>   r   _cudnn_lstm	Exception)r,   initial_state_hinitial_state_cr   r   r   r   r  r  return_sequencesr$   r   r   cudnn_supportedr   r	  seq_dims                    r   r   r   $  sp    T!	O !! \F0&(#"H-+11$!zz vY7F'yIO'yIO V4 "!F'3::d'3D YYvF%((0O%((0Owwv"
 	
  "!!"s   )D> >Ec                    |t        |       t        ||      }|s| j                  ddd      } |sdnd\  }}|j                         dk(  r#|j	                  d      }|j	                  d      }nK|j                         dk(  r8|j
                  d   dk(  r&|j                  ddd      }|j                  ddd      }|j
                  d   }|j
                  d   }t        j                  j                  ||d|d      }t        |||||
       |t        j                  d	
      \  }}| |   }|d d |f   }|d d |f   }t        j                  j                  j                  j                  ||j                         |      } ||||f      \  }\  }}t        j                  j                  j                  j                  ||      \  }}n || ||f      \  }\  }}|j!                         j#                         j                         }|j!                         j#                         j                         }|j!                         j#                         j                         }|j%                  |      }|j%                  |      }||}n|r	|d d df   n|d   }|	s$|r|j	                  d      n|j	                  d      }|r|	rt        j&                  ||g      }||||gfS )Nr   r   r   )r   r   r	   r}   F)
input_sizer   
num_layersr   bidirectionalT)
descendingr   r/   )r   r   r   rS   r   r   r   nnLSTMr   sortutilsr   pack_padded_sequencecpupad_packed_sequencedetachclonesqueezer>   )r,   r  r  r   r   r   r   r   r$   r  r   sequence_lengthsseq_axis
batch_axisr  r   r   sorted_lengthssorted_indicessorted_inputssorted_initial_hsorted_initial_cpacked_inputspacked_outputsh_nc_nr   r   r   s                                r   r  r  p  s    4 =dKP 1a()46&Hj !)33A6)33A6				!	#(=(=a(@A(E)11!Q:)11!Q:aJ"((+K 88==  D v'7vF).*
& ~.*1n+<=*1n+<= **??>--/

 &*,.>?&
"
c
 XX^^'';;K

 #6O_+MN#snn$$&**,G
**,



"
"
$C
**,



"
"
$C
++j
!C
++j
!C (3gaen  !!!$&&q) 	 (**WH:6#s++r   c                      t         r'   )r
  )argskwargss     r   grur2    s    
r   )FNNFNFFT)T)FFFT)numpyr   r   r  r   keras.src.backend.torch.corer   r   r   r   r   r   r   r   r   r  r   r  r2  r2   r   r   <module>r5     s       : 3 	n,b 0F.((526/rM 	: I"Xb,Jr   