o
    i e+                     @   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)nodezFound 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   P/var/www/myenv/lib/python3.10/site-packages/keras/src/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
 q4|r|d}	t|	|v rKq=|t|	 |	|	 |	jD ]"}
t|
|v rj t|
 qZ|
j
}|jrwtd|
|	| qZ|s?| 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   s    z4find_nodes_by_inputs_and_outputs.<locals>.<listcomp>r   zFound 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   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outputsstart_keras_tensorsend_keras_tensorstend_idsnodes_to_visitnodes_in_graphnode_id_visitedr   r   inbound_nodeunvisited_inputsr   r   r    find_nodes_by_inputs_and_outputs4   sP   




r,   c                 C   s  t | |}g }g }i }tj| D ]'}|jjr#|| ||t|< qt|}t	j
|d}|| ||t|< qtj| |}tj|D ]}	t|	}|	j|_|| ||t|	< qFtj||}|D ]}
t|
j|}t|
j|}t|
j|}tj|
j|||d qe||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"   nodes_to_clonecloned_inputscloned_outputskt_id_mappingkt_inputcpycloned_input	kt_outputr   output_copycall_args_copycall_kwargs_copyr   r   r   clone_graph_nodes   s<   



rC   c                 C   sz   g }t j| D ]-}t|r0t||v r|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/   r3   r   r2   )argskeras_tensor_mappingresultobjr=   r   r   r   r4      s   
r4   c              	   C   sx   t  .}|  t| }t|W  d   W  d   S 1 s%w   Y  W d   dS 1 s5w   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   	keras.srcr   keras.src.enginer   r0   r   r   r   r	   r   r,   rC   r4   r/   r   r   r   r   <module>   s   TK!