
    6bi$6              	           S r SSKrSSKrSSKrSSK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S	0r " S
 S5      r " S S\R*                  " S/ SQ5      5      rS rg)zContains the `Node` class.    N)backend)base_layer_utils)
json_utils)tf_utils_CONSTANT_VALUE_TYPE	COMPOSITEc                       \ rS rSrSrSS jr\S 5       r\S 5       rS r	S r
S	 r\S
 5       r\S 5       r\S 5       r\S 5       r\S 5       r\S 5       rSrg)Node$   aC  A `Node` describes a layer `__call__()` event.

A Functional model is a DAG with `Node` instances as nodes, and
`KerasTensor` instances as edges. Nodes aren't `Layer` instances, because a
single layer could be called multiple times, which would result in graph
cycles.

A `__call__()` event involves input tensors (and other input arguments),
the layer that was called, and the resulting output tensors.
A `Node` will include all this information.

Since a single `Layer` could be called multiple times, the `Node` instances
are stored on layers as a list. Each time a layer is called a node is added
to `layer._inbound_nodes`. Each time the output of a layer is used by
another layer, a node is added to `layer._outbound_nodes`.

Every `KerasTensor` instance has a `KerasHistory` object attached,
which tracks the `Node` that records the `__call__()` event that created
the tensor. By recursively walking through `Node` instances
via the `KerasHistory` metadata of `KerasTensor` instances, once can
retrieve the entire DAG of a Functional model.

Args:
    layer: The layer that was called in the `Layer.__call__()`
      event that this node represents.
    call_args: The positional arguments the layer was called with.
    call_kwargs: The keyword arguments the layer was called with.
    outputs: The output tensors of the `Layer.__call__()`
Nc                    Uc  / OUnUc  0 OUnUc  / OUnXl         U(       + =(       a    U(       + U l        [        R                  R	                  S U5      n[        R                  R	                  S U5      n[        R                  R	                  S U5      U l        X l        X0l        [        R                  R                  U R                  U R                  45      U l	        U R                  (       + =(       aB    [        U R                  5      S:H  =(       a#    [        R                  " U R                  S   5      U l        [        R                  R                  R                  5       (       df  U R                   HV  n[!        U[        R"                  5      (       d  M$  [$        R&                  " USS9(       d  M@  [$        R(                  " U5        MX     / U l        / U l        [/        U R                  5       Hd  u  pg[1        U5      (       d  M  U R*                  R3                  U5        [5        [7        U5      5      nUn	U R,                  R3                  X45        Mf     U R                   R8                  R3                  U 5        U R:                   H9  n
U
R<                  R                   nUc  M  UR>                  R3                  U 5        M;     [        U R                   R8                  5      S-
  n[/        [        R                  R                  U5      5       H  u  pm[A        XUS9Ul        M     U R*                   Vs/ s H  n[5        [7        U5      5      PM     snU l!        [        R                  R                  U R
                  5       Vs/ s H  n[5        [7        U5      5      PM     snU l"        g s  snf s  snf )	Nc                     U $ N ts    R/home/james-whalen/.local/lib/python3.13/site-packages/tf_keras/src/engine/node.py<lambda>Node.__init__.<locals>.<lambda>Q   s    A    c                     U $ r   r   r   s    r   r   r   R   s    ar   c                     U $ r   r   r   s    r   r   r   S   s    qr      r   T)ignore_call_contextlayer
node_indextensor_index)#r   is_inputtfnestmap_structureoutputs	call_argscall_kwargsflatten_flat_argumentslen	is_tensor _single_positional_tensor_passedcompatv1#executing_eagerly_outside_functions
isinstanceTensorr   needs_keras_historycreate_keras_history_keras_inputs_keras_inputs_ids_and_indices	enumerateis_keras_tensorappendstrid_inbound_nodeskeras_inputs_keras_history_outbound_nodesKerasHistoryflat_input_idsflat_output_ids)selfr   r$   r%   r#   objielekt_idkt_indexktinbound_layerr   tensorr   s                  r   __init__Node.__init__C   s   #+B	'/b["W
%9k/ GG))+yA	gg++KEww,,['B"&  "ww^^T--. 

     0DNN#q(0T^^A./ 	- yy||??AA++ &::T  %99#> ,  -/* 4 45FAs##""))#.BsG22995:KL 6 	

!!((.##B--33M(--44T: $ 223a7
"277??7#;<IA$0%F! = 483E3EF3Eas2a5z3EF " = 
 =1C1J = 
 G 
s   ?N7N<c                     U R                   $ )zFTensors input to this node that can be traced back to a
`keras.Input`.)r2   r@   s    r   r:   Node.keras_inputs   s     !!!r   c                     / nU R                    HR  nUR                  R                  nUR                  R                  nUc  M4  UR	                  UR
                  U   5        MT     U$ )zFReturns all the `Node`s whose output this node immediately depends
on.)r:   r;   r   r   r6   r9   )r@   	node_depsrF   r   r   s        r   parent_nodesNode.parent_nodes   sb     	##B%%++E**55J   !5!5j!AB	 $
 r   c              #      #    U R                    H9  nUR                  nUR                  nUR                  nUR                  nX4XQ4v   M;     g7f)zYields tuples representing the data inbound from other nodes.

Yields:
  tuples like: (inbound_layer, node_index, tensor_index, tensor).
N)r:   r;   r   r   r   )r@   rF   keras_historyr   r   r   s         r   iterate_inboundNode.iterate_inbound   sN      ##B--M!''E&11J(55L\55 $s   AAc                 x   U R                   (       a&  U R                  S   u  p#X   R                  5       40 4$ [        R                  " U R                  5      nU R                   H  u  p%X   R                  5       XE'   M     [
        R                  R                  U R                  U R                  4U5      u  pgXg4$ )z>Maps TF-Keras Tensors to computed Tensors using `tensor_dict`.r   )
r*   r3   popcopyr'   r    r!   pack_sequence_asr$   r%   )r@   tensor_dictrD   _flat_argumentsrE   argskwargss           r   map_argumentsNode.map_arguments   s    0099!<HE&**,.22!YYt';';<N#'#E#E+6+=+A+A+C( $F 7733!1!12NLD <r   c                   ^^^	^
 U R                   U R                  snm
U R                  R                  R	                  UT
5      u  pCm
[        [        U R                  R                  R                  SS U5      5      nUR                  T
5        Um
UU4S jm	[        R                  R                  T	T
5      m
 [        R                  " T
[        R                  S9  U	U
UU4S	 jn[        R                  R                  Xt5      n[        R                  R)                  U5      (       d  U R                  R*                  (       d  U/n[,        R.                  " U5      nU$ ! [          a\    [        R                  R                  ["        T
5      n[!        SU R                  R$                  -   S-   S-   ['        U5      -   S-   5      ef = f)
z4Serializes `Node` for Functional API's `get_config`.r   Nc                   > [        U S5      (       ai  U R                  nUR                  nT" UR                  R                  U5      nTR                  US5      nUR                  R                  XAR                  /$ [        U [        R                  5      (       a  U R                  5       $ [        U [        R                  5      (       a$  [        R                  " U 5      R                  5       $ [        U [        R                  R                   5      (       a*  ["        [$        R&                  " 5       R)                  U 5      4$ U $ )z,Serializes a single Tensor passed to `call`.r;   r   )hasattrr;   r   r   namegetr   r.   npndarraytolistr    r/   r   	get_value__internal__CompositeTensor_COMPOSITE_TYPEr   Encoderencode)r   khr   node_keynew_node_indexmake_node_keynode_conversion_maps        r   _serialize_keras_tensor/Node.serialize.<locals>._serialize_keras_tensor   s    q*++%%]]
(
C!4!8!81!E~GG!RZZ((xxz!!RYY''((+2244 !R__<<=='););)=)D)DQ)GHHHr   )defaultzLayer z- was passed non-JSON-serializable arguments. zArguments had types: z6. They cannot be serialized out when saving the model.c                 F  > [        U 5      (       ak  U R                  nUR                  nT" UR                  R                  U5      nT	R                  US5      nUR                  R                  XAR                  T/nO[        ST" U 5      T/n[        R                  " U5      $ )Nr   )
r5   r;   r   r   rd   re   r   r   r   ListWrapper)
r   ro   r   rp   rq   datart   r^   rr   rs   s
         r   serialize_first_arg_tensor2Node.serialize.<locals>.serialize_first_arg_tensor   s    q!!%%]]
(
C!4!8!81!E~O (-DQ-GP''--r   )r$   r%   r   
_call_specsplit_out_first_argdictzip	arg_namesupdater    r!   r"   jsondumpsr   get_json_type	TypeErrortyperd   r7   	is_nested#_preserve_input_structure_in_configr   convert_inner_node_data)r@   rr   rs   r]   inputs	argumentskwarg_typesr{   rz   rt   r^   s    ``      @@r   	serializeNode.serialize   s    ~~t'7'7f#zz44HH& 
f
 TZZ22<<QR@$GH	 	, &&'>G	JJvz'?'?@	. 	.  ww$$%?H!!$''JJBB6D//5I  		''//f=K**//"AB ** k"	#
 KK 		s   8#E A&Gc                 \    U R                   (       a  U R                  /$ U R                  S   $ )Nr   )r   r#   r$   rL   s    r   input_tensorsNode.input_tensors
  s$    ==LL>!~~a  r   c                 V    U R                   (       a  U R                  /$ U R                  $ r   )r   r#   rL   s    r   output_tensorsNode.output_tensors  s    ==LL>!||r   c                     [         R                  R                  [        R                  U R
                  5      n[        U5      S:X  a  U R                  (       d  US   $ U$ )Nr   r   )r    r!   r"   r   	int_shaper   r(   r   )r@   input_shapess     r   r   Node.input_shapes  sL    ww,,t11
 |!$--?"r   c                 r    [         R                  R                  [        R                  U R
                  5      $ r   )r    r!   r"   r   r   r   rL   s    r   output_shapesNode.output_shapes  s%    ww$$W%6%68K8KLLr   c                     U R                   $ r   )r   rL   s    r   outbound_layerNode.outbound_layer#  s    zzr   c                 8   U R                   (       a  / $ U R                   Vs/ s H5  n[        R                  " U5      (       d  M   [	        US5      (       d  M3  UPM7     nn[        R
                  R                  S U5      n[        U5      S:X  a  US   $ U$ s  snf )z2Return all layers that feed into the current node.r;   c                 .    U R                   R                  $ r   )r;   r   r   s    r   r   %Node.inbound_layers.<locals>.<lambda>2  s    a&&,,r   r   r   )r   r'   r    r)   rc   r!   r"   r(   )r@   xtensor_call_argsinbound_layerss       r   r   Node.inbound_layers'  s     ==I ))
)||A #*1.>#? ) 	 

 ..,.>
 ~!#!!$$
s   BBB)r'   r2   r3   r*   r$   r%   r>   r?   r   r   r#   )NNN)__name__
__module____qualname____firstlineno____doc__rI   propertyr:   rP   rT   r_   r   r   r   r   r   r   r   __static_attributes__r   r   r   r   r   $   s    <D
L " "
 	 	6  Jd ! !
  
   M M    r   r   c                       \ rS rSrSrSrSrg)r=   i9  a  Tracks the Layer call that created a Tensor, for TF-Keras Graph Networks.

During construction of TF-Keras Graph Networks, this metadata is added to
each Tensor produced as the output of a Layer, starting with an
`InputLayer`. This allows TF-Keras to track how each Tensor was produced,
and this information is later retraced by the `keras.engine.Network` class
to reconstruct the TF-Keras Graph Network.

Attributes:
  layer: The Layer that produced the Tensor.
  node_index: The specific call to the Layer that produced this Tensor.
    Layers can be called multiple times in order to share weights. A new
    node is created every time a Layer is called. The corresponding node
    that represents the call event that produced the Tensor can be found at
    `layer._inbound_nodes[node_index]`.
  tensor_index: The output index for this Tensor. Always zero if the Layer
    that produced this Tensor only has one output. Nested structures of
    Tensors are deterministically assigned an index via `nest.flatten`.
r   N)r   r   r   r   r   	__slots__r   r   r   r   r=   r=   9  s    
, Ir   r=   r   c                     [        U S5      $ )Nr;   )rc   )rA   s    r   r5   r5   W  s    3())r   )r   collectionsrX   r   numpyrf   tensorflow.compat.v2r+   v2r    tf_keras.srcr   tf_keras.src.enginer   &tf_keras.src.saving.legacy.saved_modelr   tf_keras.src.utilsr   r   rl   r   
namedtupler=   r5   r   r   r   <module>r      sg   " !     ! !   0 = '#K(R Rj?<*r   