o
    i ec                     @   s:  d Z ddlmZ ddlmZ ddlmZ ddlZddlZddlm  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Zdd Zdd ZG dd deZedgdedgdG dd deZedgdedgdG dd deZedgdedgdG dd deZd d! ZdS )"z8Module implementing the V1 version of RNN cell wrappers.    )absolute_import)division)print_functionN)_enumerated_map_structure_up_to)_parse_config_to_function)_serialize_function_to_config)RNNCell)keras_export)	tf_exportzis not an RNNCellc                 C   s&   zt | | W dS  ty   Y dS w )NFT)getattrAttributeError)obj	attr_name r   X/var/www/myenv/lib/python3.10/site-packages/keras/src/layers/rnn/legacy_cell_wrappers.py_hasattr(   s   r   c                 C   sl   t |dt |dt |dpt |dt|g}g d}t|s4dd t||D }td| |d	|d
S )a  Raises a TypeError if cell is not like an RNNCell.

    NOTE: Do not rely on the error message (in particular in tests) which can be
    subject to change to increase readability. Use
    ASSERT_LIKE_RNNCELL_ERROR_REGEXP.

    Args:
      cell_name: A string to give a meaningful error referencing to the name of
        the functionargument.
      cell: The object which should behave like an RNNCell.

    Raises:
      TypeError: A human-friendly exception.
    output_size
state_sizeget_initial_state
zero_state)z!'output_size' property is missingz 'state_size' property is missingz=either 'zero_state' or 'get_initial_state' method is requiredzis not callablec                 S   s   g | ]\}}|s|qS r   r   ).0errorcondr   r   r   
<listcomp>O   s    z'assert_like_rnncell.<locals>.<listcomp>z-The argument {!r} ({}) is not an RNNCell: {}.z, N)r   callableallzip	TypeErrorformatjoin)	cell_namecell
conditionserrorsr   r   r   assert_like_rnncell1   s   r$   c                       sl   e Zd ZdZ fddZdd ZdddZed	d
 Zedd Z	dd Z
 fddZedddZ  ZS )_RNNCellWrapperV1zBase class for cells wrappers V1 compatibility.

    This class along with `_RNNCellWrapperV2` allows to define cells wrappers
    that are compatible with V1 and V2, and defines helper methods for this
    purpose.
    c                    sJ   t  j|i | td| || _t|tjjjr#| j	| jdd d S d S )Nr!   )name)
super__init__r$   r!   
isinstancetf__internal__tracking	Trackable_track_trackable)selfr!   argskwargs	__class__r   r   r(   _   s   
z_RNNCellWrapperV1.__init__c                 K   s   t )a  Calls the wrapped cell and performs the wrapping logic.

        This method is called from the wrapper's `call` or `__call__` methods.

        Args:
          inputs: A tensor with wrapped cell's input.
          state: A tensor or tuple of tensors with wrapped cell's state.
          cell_call_fn: Wrapped cell's method to use for step computation
            (cell's `__call__` or 'call' method).
          **kwargs: Additional arguments.

        Returns:
          A pair containing:
          - Output: A tensor with cell's output.
          - New state: A tensor or tuple of tensors with new wrapped cell's
            state.
        )NotImplementedErrorr/   inputsstatecell_call_fnr1   r   r   r   _call_wrapped_cellf   s   z$_RNNCellWrapperV1._call_wrapped_cellNc                 C   s   | j ||| jj|dS )a  Runs the RNN cell step computation.

        We assume that the wrapped RNNCell is being built within its `__call__`
        method. We directly use the wrapped cell's `__call__` in the overridden
        wrapper `__call__` method.

        This allows to use the wrapped cell and the non-wrapped cell
        equivalently when using `__call__`.

        Args:
          inputs: A tensor with wrapped cell's input.
          state: A tensor or tuple of tensors with wrapped cell's state.
          scope: VariableScope for the subgraph created in the wrapped cells'
            `__call__`.

        Returns:
          A pair containing:

          - Output: A tensor with cell's output.
          - New state: A tensor or tuple of tensors with new wrapped cell's
            state.
        )r8   scope)r9   r!   __call__)r/   r6   r7   r:   r   r   r   r;   z   s   z_RNNCellWrapperV1.__call__c                 C      | j jS N)r!   r   r/   r   r   r   r         z_RNNCellWrapperV1.state_sizec                 C   r<   r=   )r!   r   r>   r   r   r   r      r?   z_RNNCellWrapperV1.output_sizec                 C   sF   t t| jd  | j||W  d    S 1 sw   Y  d S N	ZeroState)r*   
name_scopetype__name__r!   r   r/   
batch_sizedtyper   r   r   r      s   $z_RNNCellWrapperV1.zero_statec                    s@   d| j jj| j  di}t  }tt| t|  S )Nr!   )
class_nameconfig)r!   r3   rD   
get_configr'   dictlistitemsr/   rI   base_configr2   r   r   rJ      s   
z_RNNCellWrapperV1.get_configc                 C   sF   |  }|d}ztd| | |fi |W S  ty"   tdw )Nr!   ztRNNCellWrapper cannot reconstruct the wrapped cell. Please overwrite the cell in the config with a RNNCell instance.)copypopr$   r   
ValueError)clsrI   custom_objectsr!   r   r   r   from_config   s   

z_RNNCellWrapperV1.from_configr=   )rD   
__module____qualname____doc__r(   r9   r;   propertyr   r   r   rJ   classmethodrU   __classcell__r   r   r2   r   r%   W   s    



r%   z1keras.__internal__.legacy.rnn_cell.DropoutWrapper)v1znn.rnn_cell.DropoutWrapperc                       s   e Zd ZdZ								d fdd	Zdd Zed	d
 Zdd Zdd Z		dddZ
dd Z fddZed fdd	Z  ZS )DropoutWrapperz@Operator adding dropout to inputs and outputs of the given cell.      ?FNc
                    s  t  j|fdi|
 |	durt|	std|	 |	pt_tdM dd }|df|df|d	ffD ]5\}}||\}}|dura|d
k sK|dkrUtd| d| t	d| t
| q5t	d| | q5W d   n1 suw   Y  |_|_|_d_d_d_|r߈du rtddd fdd tjtjrjdk r|du rtdt| fdd|_t|j fdd|j_t|j fdd|j_dS dS )a}  Create a cell with added input, state, and/or output dropout.

        If `variational_recurrent` is set to `True` (**NOT** the default
        behavior), then the same dropout mask is applied at every step, as
        described in: [A Theoretically Grounded Application of Dropout in
        Recurrent Neural Networks. Y. Gal, Z.
        Ghahramani](https://arxiv.org/abs/1512.05287).

        Otherwise a different dropout mask is applied at every time step.

        Note, by default (unless a custom `dropout_state_filter` is provided),
        the memory state (`c` component of any `LSTMStateTuple`) passing through
        a `DropoutWrapper` is never modified.  This behavior is described in the
        above article.

        Args:
          cell: an RNNCell, a projection to output_size is added to it.
          input_keep_prob: unit Tensor or float between 0 and 1, input keep
            probability; if it is constant and 1, no input dropout will be
            added.
          output_keep_prob: unit Tensor or float between 0 and 1, output keep
            probability; if it is constant and 1, no output dropout will be
            added.
          state_keep_prob: unit Tensor or float between 0 and 1, output keep
            probability; if it is constant and 1, no output dropout will be
            added. State dropout is performed on the outgoing states of the
            cell. **Note** the state components to which dropout is applied when
            `state_keep_prob` is in `(0, 1)` are also determined by the argument
            `dropout_state_filter_visitor` (e.g. by default dropout is never
            applied to the `c` component of an `LSTMStateTuple`).
          variational_recurrent: Python bool.  If `True`, then the same dropout
            pattern is applied across all time steps per run call. If this
            parameter is set, `input_size` **must** be provided.
          input_size: (optional) (possibly nested tuple of) `TensorShape`
            objects containing the depth(s) of the input tensors expected to be
            passed in to the `DropoutWrapper`.  Required and used **iff**
            `variational_recurrent = True` and `input_keep_prob < 1`.
          dtype: (optional) The `dtype` of the input, state, and output tensors.
            Required and used **iff** `variational_recurrent = True`.
          seed: (optional) integer, the randomness seed.
          dropout_state_filter_visitor: (optional), default: (see below).
            Function that takes any hierarchical level of the state and returns
            a scalar or depth=1 structure of Python booleans describing which
            terms in the state should be dropped out.  In addition, if the
            function returns `True`, dropout is applied across this sublevel.
            If the function returns `False`, dropout is not applied across this
            entire sublevel.  Default behavior: perform dropout on all terms
            except the memory (`c`) state of `LSTMCellState` objects, and don't
            try to apply dropout to `TensorArray` objects:
            ```
            def dropout_state_filter_visitor(s):
              # Never perform dropout on the c state.
              if isinstance(s, LSTMCellState):
                return LSTMCellState(c=False, h=True)
              elif isinstance(s, TensorArray):
                return False
              return True
            ```
          **kwargs: dict of keyword arguments for base layer.

        Raises:
          TypeError: if `cell` is not an `RNNCell`, or `keep_state_fn` is
            provided but not `callable`.
          ValueError: if any of the keep_probs are not between 0 and 1.
        rG   Nz9dropout_state_filter_visitor must be callable. Received: DropoutWrapperInitc                 S   s   t | }t |}||fS r=   )r*   convert_to_tensorget_static_value)vtensor_valueconst_valuer   r   r   tensor_and_const_value  s   

z7DropoutWrapper.__init__.<locals>.tensor_and_const_valueinput_keep_probstate_keep_proboutput_keep_probr      z
Parameter z# must be between 0 and 1. Received _z7When variational_recurrent=True, dtype must be providedc                 S   s   t dgt |  fdS )Nri   r   )r*   concatTensorShapeas_list)sr   r   r   convert_to_batch_shape@  s   z7DropoutWrapper.__init__.<locals>.convert_to_batch_shapec                    s    | }t jj||dS )N)seedrG   )r*   randomuniform)rn   
inner_seedshape)ro   rG   r   r   batch_noiseF  s   z,DropoutWrapper.__init__.<locals>.batch_noiser^   zdWhen variational_recurrent=True and input_keep_prob < 1.0 or is unknown, input_size must be providedc                        | d| dS )Ninputrs   	_gen_seedirn   ru   r/   r   r   <lambda>U      z)DropoutWrapper.__init__.<locals>.<lambda>c                    rv   )Nr7   rx   ry   r{   r}   r   r   r~   \  r   c                    rv   )Noutputrx   ry   r{   r}   r   r   r~   c  r   )r'   r(   r   r   %_default_dropout_state_filter_visitor_dropout_state_filterr*   rB   rR   setattrfloat_variational_recurrent_input_size_seed_recurrent_input_noise_recurrent_state_noise_recurrent_output_noiser)   _input_keep_probnumbersRealr   r   r   )r/   r!   rf   rh   rg   variational_recurrent
input_sizerG   rp   dropout_state_filter_visitorr1   re   probattrtensor_prob
const_probr2   )ru   ro   rG   r/   r   r(      s   N


zDropoutWrapper.__init__c                 C   sN   | j d u rd S d||f }t| j | d}tt| d d dd@ S )Nz%s_%dzutf-8      i)r   strencodeinthashlibmd5	hexdigest)r/   salt_prefixindexsaltstringr   r   r   rz   i  s
   
 zDropoutWrapper._gen_seedc                 C   s   | j S r=   )r!   r>   r   r   r   wrapped_cellp  s   zDropoutWrapper.wrapped_cellc                 C   s   | j | d| _d S )NT)r!   buildbuilt)r/   inputs_shaper   r   r   r   t  s   
zDropoutWrapper.buildc                 C   s4   || }t |}t ||| }||  |S )z7Performs dropout given the pre-calculated noise tensor.)r*   floordivide	set_shape	get_shape)r/   unused_indexvaluenoise	keep_probrandom_tensorbinary_tensorretr   r   r   $_variational_recurrent_dropout_valuex  s
   
z3DropoutWrapper._variational_recurrent_dropout_valuec                    s^   |du r|}j s fdd}t||g||gR  S  fdd}t||g|||gR  S )zADecides whether to perform standard dropout or recurrent dropout.Nc                    s0   t |tr|rtjj|d  | dS |S )Nr^   )raterp   )r)   boolr*   nndropoutrz   )r|   
do_dropoutrb   r   r   r/   r   r   r     s   
z(DropoutWrapper._dropout.<locals>.dropoutc                    s"   t |tr|r| || S |S r=   )r)   r   r   )r|   r   rb   n)r   r/   r   r   r     s
   )r   r   )r/   valuesr   recurrent_noiser   shallow_filtered_substructurer   r   r   r   _dropout  s"   

zDropoutWrapper._dropoutc           	      K   s   dd }|| j r| |d| j| j }|||fi |\}}|| jr7tjj| j|}| |d| j	| j|}|| j
rF| |d| j| j
}||fS )a'  Runs the wrapped cell and applies dropout.

        Args:
          inputs: A tensor with wrapped cell's input.
          state: A tensor or tuple of tensors with wrapped cell's state.
          cell_call_fn: Wrapped cell's method to use for step computation
            (cell's `__call__` or 'call' method).
          **kwargs: Additional arguments.

        Returns:
          A pair containing:

          - Output: A tensor with cell's output.
          - New state: A tensor or tuple of tensors with new wrapped cell's
            state.
        c                 S   s   t | t p	| dk S )Nri   )r)   r   )pr   r   r   _should_dropout  s   z:DropoutWrapper._call_wrapped_cell.<locals>._should_dropoutrw   r7   r   )r   r   r   _state_keep_probr*   r+   nestget_traverse_shallow_structurer   r   _output_keep_probr   )	r/   r6   r7   r8   r1   r   r   	new_stater   r   r   r   r9     s:   


z!DropoutWrapper._call_wrapped_cellc                    sp   | j | j| j| j| j| jd}| jtkr%t| j\}}}|	|||d t
  }tt| t|  S )z*Returns the config of the dropout wrapper.)rf   rh   rg   r   r   rp   )
dropout_fndropout_fn_typedropout_fn_module)r   r   r   r   r   r   r   r   r   updater'   rJ   rK   rL   rM   )r/   rI   functionfunction_typefunction_modulerO   r2   r   r   rJ     s*   

zDropoutWrapper.get_configc                    sF   d|v r|  }t||ddd}|d ||d< tt| j||dS )Nr   r   r   r   rT   )rP   r   rQ   r'   r]   rU   )rS   rI   rT   dropout_state_filterr2   r   r   rU     s   

zDropoutWrapper.from_config)r^   r^   r^   FNNNNr=   )rD   rV   rW   rX   r(   rz   rY   r   r   r   r   r9   rJ   rZ   rU   r[   r   r   r2   r   r]      s.     +

05r]   z2keras.__internal__.legacy.rnn_cell.ResidualWrapperznn.rnn_cell.ResidualWrapperc                       sH   e Zd ZdZd fdd	Zdd Z fddZed fd	d
	Z  Z	S )ResidualWrapperzBRNNCell wrapper that ensures cell inputs are added to the outputs.Nc                       t  j|fi | || _dS )a  Constructs a `ResidualWrapper` for `cell`.

        Args:
          cell: An instance of `RNNCell`.
          residual_fn: (Optional) The function to map raw cell inputs and raw
            cell outputs to the actual cell outputs of the residual network.
            Defaults to calling nest.map_structure on (lambda i, o: i + o),
            inputs and outputs.
          **kwargs: dict of keyword arguments for base layer.
        N)r'   r(   _residual_fn)r/   r!   residual_fnr1   r2   r   r   r(     s   
zResidualWrapper.__init__c           	         sB   |||fi |\}}dd   fdd}| j p|||}||fS )aG  Run the cell and apply the residual_fn.

        Args:
          inputs: cell inputs.
          state: cell state.
          cell_call_fn: Wrapped cell's method to use for step computation
            (cell's `__call__` or 'call' method).
          **kwargs: Additional arguments passed to the wrapped cell's `call`.

        Returns:
          Tuple of cell outputs and new state.

        Raises:
          TypeError: If cell inputs and outputs have different structure (type).
          ValueError: If cell inputs and outputs have different structure
            (value).
        c                 S   s   |   |   d S r=   )r   assert_is_compatible_withinpoutr   r   r   assert_shape_match>  s   z>ResidualWrapper._call_wrapped_cell.<locals>.assert_shape_matchc                    s2   t j| | t j | | t jdd | |S )Nc                 S   s   | | S r=   r   r   r   r   r   r~   E  s    zQResidualWrapper._call_wrapped_cell.<locals>.default_residual_fn.<locals>.<lambda>)r*   r   assert_same_structuremap_structure)r6   outputsr   r   r   default_residual_fnA  s
   
z?ResidualWrapper._call_wrapped_cell.<locals>.default_residual_fn)r   )	r/   r6   r7   r8   r1   r   r   r   res_outputsr   r   r   r9   )  s   z"ResidualWrapper._call_wrapped_cellc                    sR   | j durt| j \}}}|||d}ni }t  }tt| t|  S )z+Returns the config of the residual wrapper.N)r   residual_fn_typeresidual_fn_module)r   r   r'   rJ   rK   rL   rM   )r/   r   r   r   rI   rO   r2   r   r   rJ   M  s   

zResidualWrapper.get_configc                    s<   d|v r|  }t||ddd}||d< tt| j||dS )Nr   r   r   r   )rP   r   r'   r   rU   )rS   rI   rT   residual_functionr2   r   r   rU   _  s   
zResidualWrapper.from_configr=   )
rD   rV   rW   rX   r(   r9   rJ   rZ   rU   r[   r   r   r2   r   r     s    $r   z0keras.__internal__.legacy.rnn_cell.DeviceWrapperznn.rnn_cell.DeviceWrapperc                       s<   e Zd ZdZ fddZdd Zdd Z fdd	Z  ZS )
DeviceWrapperz=Operator that ensures an RNNCell runs on a particular device.c                    r   )aO  Construct a `DeviceWrapper` for `cell` with device `device`.

        Ensures the wrapped `cell` is called with `tf.device(device)`.

        Args:
          cell: An instance of `RNNCell`.
          device: A device string or function, for passing to `tf.device`.
          **kwargs: dict of keyword arguments for base layer.
        N)r'   r(   _device)r/   r!   devicer1   r2   r   r   r(   u  s   

zDeviceWrapper.__init__c              	   C   s   t t| jd / t jj| j | j	||W  d    W  d    S 1 s,w   Y  W d    d S 1 s<w   Y  d S r@   )
r*   rB   rC   rD   compatr\   r   r   r!   r   rE   r   r   r   r     s   "zDeviceWrapper.zero_statec                 K   sF   t jj| j |||fi |W  d   S 1 sw   Y  dS )z!Run the cell on specified device.N)r*   r   r\   r   r   r5   r   r   r   r9     s   $z DeviceWrapper._call_wrapped_cellc                    s0   d| j i}t  }tt| t|  S )Nr   )r   r'   rJ   rK   rL   rM   rN   r2   r   r   rJ     s   

zDeviceWrapper.get_config)	rD   rV   rW   rX   r(   r   r9   rJ   r[   r   r   r2   r   r   p  s    r   c                 C   s6   ddl m} t| |r|dddS t| tjrdS dS )Nr   )LSTMStateTupleFT)ch)!keras.src.layers.rnn.legacy_cellsr   r)   r*   TensorArray)substater   r   r   r   r     s   
r   )rX   
__future__r   r   r   r   r   tensorflow.compat.v2r   v2r*   "keras.src.layers.rnn.cell_wrappersr   r   r   r   r    tensorflow.python.util.tf_exportr	   r
    ASSERT_LIKE_RNNCELL_ERROR_REGEXPr   r$   r%   r]   r   r   r   r   r   r   r   <module>   s:   	&
c
  
\

X
 