
    ~Wh+                     n    d Z ddlmc 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 Zd	 Zd
 Zd Z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                     t          j        |           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tensors    c/var/www/html/movieo_spanner_bot/venv/lib/python3.11/site-packages/keras/engine/functional_utils.pyis_input_keras_tensorr      s@      &v.. L;BB6JJKKK;    c                    t           j                            |          }t           j                            |           }||z   D ]=}t          j        |          s't          t                              |                    >t          d |D                       }t                      g }g }t                      }|D ]}|	                    |j
                   |r|                    d          }	t          |	          |v r)|                    t          |	                     |	                    |	           |	j        D ]{}
t          |
          |v r#                    t          |
                     6|
j
        }|j        r"t          d                    |
                    |	                    |           |||k    r0f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                 ,    g | ]}t          |          S  id).0kts     r   
<listcomp>z4find_nodes_by_inputs_and_outputs.<locals>.<listcomp>T   s    666b2b66666r   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                 6    g | ]}t          |          v|S r   r   )r   r   end_ids_founds     r   r   z4find_nodes_by_inputs_and_outputs.<locals>.<listcomp>~   s0     
 
 
bffM.I.IB.I.I.Ir   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   s                @r    find_nodes_by_inputs_and_outputsr0   4   s;   4 '//'22// #44 K K*1-- 	K?FFqIIJJJ	K66$566677G EEMNNeeO  & &af%%%%
 0!!!$$d88&&BtHH%%%d#### 	0 	0B"vv  !!"R&&)))7L
 $  ( )/r

	   !!,////3  0: -
 
 
 
*
 
 
 $f%566
 
 	
 r   c                    t          | |          }g }g }i }t          j                            |           D ]}|j        j        r(|                    |           ||t          |          <   6t          |          }t          j
        |          }|                    |           ||t          |          <   t          j                            | |          }t          j                            |          D ]D}	t          |	          }|	j        |_        |                    |           ||t          |	          <   Et          j                            ||          }|D ]^}
t          |
j        |          }t          |
j        |          }t          |
j        |          }t#          j        |
j        |||           _||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&   )r0   r   r   r   r   r   r!   r   _clone_keras_tensorinput_layer_moduleInputpack_sequence_as_keras_historyclone_keras_tensorsoutput_tensorsr2   r3   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_copys                 r   clone_graph_nodesrH      s   & 6fgFFNMN MGOOF++ 7 7=! 	7   ****2M"X,,'' &h//C-33???L  ...*6M"X,,''G,,V]CCMW__W-- + +	!),,
 '5c"""'*bmm$$W--g~FFN 
 
 *$*=}MM,T^]KK.t/?OO 	J$(		
 	
 	
 	
 	
 .((r   c                    g }t           j                            |           D ]}t          j        |          rjt          |          |v r|t          |                   }n-t          |          }|j        |_        ||t          |          <   |                    |           |                    |           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   r4   r8   r!   r7   )argskeras_tensor_mappingresultobjrB   s        r   r9   r9      s    " Fwt$$  &s++ 
	#ww...*2c773 *#..%(%7"03$RWW-MM#MM#7##D&111r   c                     t          j                    5 }|                                5  t          j        |           }t          j        |          cddd           cddd           S # 1 swxY w Y   	 ddd           dS # 1 swxY w 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placeholders      r   r4   r4      sS    
		!	! F]%%'' 	F 	F&B2FFK8EE	F 	F 	F 	F 	F 	F 	FF F F F F F F F	F 	F 	F 	F 	F 	F 	F 	F 	FF F F F F F F F F F F F F F F F F Fs4   B(A*B*A.	.B1A.	2BB
B)__doc__tensorflow.compat.v2compatv2r   kerasr   keras.enginer   r5   r   r   r   r   r   r0   rH   r9   r4   r   r   r   <module>r[      s    , + ! ! ! ! ! ! ! ! !       : : : : : : % % % % % % , , , , , ,1 #     *Q Q QhH) H) H)V2 2 2BF F F F Fr   