
    6bi(+                     l    S r SSKJs  Jr  SSKJr  SSKJr	  SSKJ
r
  SSKJr  SrS rS	 rS
 rS rS rg)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                     [         R                  " U 5      (       d  [        [        R	                  U 5      5      eU R
                  R                  $ )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    ^/home/james-whalen/.local/lib/python3.13/site-packages/tf_keras/src/engine/functional_utils.pyis_input_keras_tensorr      s<      &&v..;BB6JKK;;    c                 *   [         R                  R                  U5      n[         R                  R                  U 5      nX#-    H<  n[        R                  " U5      (       a  M   [        [        R                  U5      5      e   [        U Vs/ s H  n[        U5      PM     sn5      n[        5       n/ n/ n	[        5       n
U H  nUR                  UR                  5        M      U(       a  UR                  S5      n[        U5      U
;   a  M)  U
R                  [        U5      5        U	R                  U5        UR                   Hv  n[        U5      U;   a  UR                  [        U5      5        M.  UR                  nUR                  (       a  [        SR                  U5      5      eUR                  U5        Mx     U(       a  M  Xg:w  a=  U Vs/ s H  n[        U5      U;  d  M  UPM     nn[        SR                  U5      5      eU	$ s  snf s  snf )a
  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.
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.zHFound unvisited input tensors that are disconnected from the outputs: {})tfnestflattenr   r	   r
   r   r   setidappendr   popaddkeras_inputsr   )inputsoutputsstart_keras_tensorsend_keras_tensorstktend_idsend_ids_foundnodes_to_visitnodes_in_graphnode_id_visitedr   inbound_nodeunvisited_inputss                 r    find_nodes_by_inputs_and_outputsr*   4   s   4 ''//'2/ 4**1--?FFqIJJ 5 $56$5b2b6$567G EMNNeO aff% ! !!!$d8&BtH%d###B"v !!"R&)77L
 $$ ( )/r
	  !!,/% $ .: *
*2bfM.IB* 	 
 $f%56
 	
 c 7T
s   HH'Hc                 z   [        X5      n/ n/ n0 n[        R                  R                  U 5       H{  nUR                  R
                  (       a   UR                  U5        Xe[        U5      '   M>  [        U5      n[        R                  " US9nUR                  U5        X[        U5      '   M}     [        R                  R                  X5      n[        R                  R                  U5       H=  n	[        U	5      nU	R                  Ul        UR                  U5        Xu[        U	5      '   M?     [        R                  R                  X5      nU Hf  n
[        U
R                  U5      n[        U
R                  U5      n[        U
R                   U5      n["        R$                  " U
R&                  UUUS9  Mh     X44$ )ax  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_copys                 r   clone_graph_nodesrB      sx   & 6fFNMN MGGOOF+==!!   **2"X,' &h/C-333?L  .*6"X,' , GG,,VCMWW__W-	!),
 '55c"'*bm$ . WW--gFN *$*=*=}M,T^^]K.t/?/?O 	JJ$(		
 " ((r   c                    / n[         R                  R                  U 5       H  n[        R                  " U5      (       aZ  [        U5      U;   a  U[        U5         nO)[        U5      nUR                  Ul        XA[        U5      '   UR                  U5        Mx  UR                  U5        M     [         R                  R                  X5      $ )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.   r2   r   r1   )argskeras_tensor_mappingresultobjr<   s        r   r3   r3      s    " Fwwt$&&s++#w..*2c73 *#.%(%7%7"03RW-MM#MM# % 77##D11r   c                 $   [         R                  " 5        nUR                  5          [        R                  " U 5      n[        R
                  " U5      sSSS5        sSSS5        $ ! , (       d  f       O= f SSS5        g! , (       d  f       g= f)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   r.   r.      sb     
			!]%%'&BB2FK88E (' 
"	!''' 
"	!	!s"   B,A&	B&
A4	0B
B)__doc__tensorflow.compat.v2compatv2r   tf_keras.srcr   tf_keras.src.enginer   r/   r   r   r   r   r   r*   rB   r3   r.    r   r   <module>rV      sE    , ! !   A , 31 # *QhH)V2BFr   