a
    Sic+  ã                   @   sv   d 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Zdd	„ Zd
d„ Zdd„ Zdd„ Zdd„ ZdS )z%Utilities for keras functional model.é    N)Úbackend)Úinput_layer)Úkeras_tensor)Únodez´Found unexpected instance while processing input tensors for keras functional model. Expecting KerasTensor which is from tf.keras.Input() or output from keras layer call(). Got: {}c                 C   s    t  | ¡stt | ¡ƒ‚| jjS )aà  Check if tensor is directly generated from `tf.keras.Input`.

    This check is useful when constructing the functional model, since we will
    need to clone Nodes and KerasTensors if the model is building from non input
    tensor.

    Args:
      tensor: A `KerasTensor` as inputs to the functional model.

    Returns:
      bool. Whether the tensor is directly generated from `tf.keras.Input`.

    Raises:
      ValueError: if the tensor is not a KerasTensor instance.
    )Únode_moduleÚis_keras_tensorÚ
ValueErrorÚ"_KERAS_TENSOR_TYPE_CHECK_ERROR_MSGÚformatr   Úis_input©Útensor© r   úY/var/www/html/django/DPS/env/lib/python3.9/site-packages/keras/engine/functional_utils.pyÚis_input_keras_tensor   s    
r   c                    s*  t j |¡}t j | ¡}|| D ]}t |¡s tt |¡ƒ‚q tdd„ |D ƒƒ}tƒ ‰ g }g }tƒ }|D ]}| 	|j
¡ qh|rü| d¡}	t|	ƒ|v r–qz| t|	ƒ¡ | 	|	¡ |	jD ]D}
t|
ƒ|v rÔˆ  t|
ƒ¡ q´|
j
}|jrîtd |
¡ƒ‚| 	|¡ q´qz|ˆ kr&‡ fdd„|D ƒ}td |¡ƒ‚|S )a6  Fetch all Nodes in the graph defined by "inputs" and "outputs".

    This method is used to find and then clone Nodes when creating a new
    sub-model from an existing functional model.

    Args:
      inputs: A nested structure of KerasTensor to use as model inputs.
      outputs: A nested structure of KerasTensor to use as model outputs.

    Returns:
      A list of Nodes that are connected to the inputs and outputs.

    Raises:
      ValueError: when inputs and outputs are disconnected or in case of
        unexpected objects in the inputs/outputs.
    c                 S   s   g | ]}t |ƒ‘qS r   ©Úid©Ú.0Úktr   r   r   Ú
<listcomp>T   ó    z4find_nodes_by_inputs_and_outputs.<locals>.<listcomp>r   z¢Found input tensor cannot be reached given provided output tensors. Please make sure the tensor {} is included in the model inputs when building functional model.c                    s   g | ]}t |ƒˆ vr|‘qS r   r   r   ©Zend_ids_foundr   r   r   ~   s   zHFound unvisited input tensors that are disconnected from the outputs: {})ÚtfÚnestÚflattenr   r   r   r	   r
   ÚsetÚappendr   Úpopr   ÚaddÚkeras_inputsr   )ÚinputsÚoutputsZstart_keras_tensorsZend_keras_tensorsÚtZend_idsÚnodes_to_visitZnodes_in_graphZnode_id_visitedr   r   Úinbound_nodeZunvisited_inputsr   r   r   Ú find_nodes_by_inputs_and_outputs4   sP    



ýÿ

ÿÿÿr&   c                 C   s  t | |ƒ}g }g }i }tj | ¡D ]N}|jjrF| |¡ ||t|ƒ< q"t|ƒ}t	j
|d}| |¡ ||t|ƒ< q"tj | |¡}tj |¡D ]*}	t|	ƒ}|	j|_| |¡ ||t|	ƒ< qŒtj ||¡}|D ]<}
t|
j|ƒ}t|
j|ƒ}t|
j|ƒ}tj|
j|||d qÊ||fS )a¬  Clone the `Node` between the inputs and output tensors.

    This function is used to create a new functional model from any intermediate
    keras tensors. The clone of the nodes mimic the behavior of reconstructing
    the functional graph network by re-executing all the __call__ methods. The
    cloned nodes will be appended to the layers.

    Note that a new tf.keras.Inputs will be created for any items in the
    `inputs`

    Args:
      inputs: A nested structure of keras_tensors.
      outputs: A nested structure of keras_tensors.

    Returns:
      A pair of inputs and outputs, with cloned keras_tensors. They can be used
      to create a new functional model.
    r   )Ú	call_argsÚcall_kwargsr"   )r&   r   r   r   r   r   r   r   Ú_clone_keras_tensorÚinput_layer_moduleÚInputÚpack_sequence_asÚ_keras_historyÚclone_keras_tensorsÚoutput_tensorsr'   r(   r   ÚNodeÚlayer)r!   r"   Znodes_to_cloneZcloned_inputsZcloned_outputsZkt_id_mappingZkt_inputÚcpyZcloned_inputZ	kt_outputr   Zoutput_copyZcall_args_copyZcall_kwargs_copyr   r   r   Úclone_graph_nodesˆ   s<    



ür3   c                 C   sz   g }t j | ¡D ]Z}t |¡r`t|ƒ|v r8|t|ƒ }nt|ƒ}|j|_||t|ƒ< | |¡ q| |¡ qt j 	| |¡S )aë  Clone the keras tensors from the inputs.

    For any KerasTensor instance in the `args`, a new copy of KerasTensor will
    be created if it has not been cloned yet (by checking the
    `keras_tensor_mapping`). For any other types, the instance will be
    unchanged. This function is useful for cloning the Nodes since KerasTensor
    can't be reused across the models.

    Args:
      args: A nested structure of objects, which could contain KerasTensor.
      keras_tensor_mapping: A dict contains the ID of original KerasTensor, and
        the cloned KerasTensor instance. The dict will be updated with newly
        copied KerasTensor instances within this method.
    Returns:
      Same structure as inputs, with KerasTensor cloned.
    )
r   r   r   r   r   r   r)   r-   r   r,   )ÚargsZkeras_tensor_mappingÚresultÚobjr2   r   r   r   r.   Ó   s    
r.   c              	   C   sv   t  ¡ Z}| ¡ 2 t | ¡}t |¡W  d  ƒ W  d  ƒ S 1 sJ0    Y  W d  ƒ n1 sh0    Y  dS )a(  Create an identical keras_tensor based on the input.

    We use keras_tensor_to_placeholder and keras_tensor_from_tensor to make sure
    inferred shape are not lost during the copy.

    Args:
      kt: the input KerasTensor.

    Returns:
      An identical copy of the input KerasTensor.
    N)r   Ú_scratch_graphÚ
as_defaultr   Úkeras_tensor_to_placeholderÚkeras_tensor_from_tensor)r   Úscratch_graphÚplaceholderr   r   r   r)   ô   s    


r)   )Ú__doc__Útensorflow.compat.v2ÚcompatÚv2r   Úkerasr   Úkeras.enginer   r*   r   r   r   r	   r   r&   r3   r.   r)   r   r   r   r   Ú<module>   s   ÿTK!