o
    i e	6                     @   s   d Z ddlZddlZddlZddl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	iZG d
d dZG dd dedg dZdd ZdS )zContains the `Node` class.    N)backend)base_layer_utils)
json_utils)tf_utils_CONSTANT_VALUE_TYPE	COMPOSITEc                   @   s   e Zd ZdZdddZedd Zedd Zd	d
 Zdd Z	dd Z
edd Zedd Zedd Zedd Zedd Zedd ZdS )Nodea  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                 C   s  |d u rg n|}|d u ri n|}|d u rg n|}|| _ | o | | _tjdd |}tjdd |}tjdd || _|| _|| _tj| j| jf| _	| j oat
| jdkoat| jd | _tjj s| j	D ]}t|tjrtj|ddrt| qlg | _g | _t| j	D ]\}}t|r| j| tt|}|}	| j||	f q| j j|  | jD ]}
|
jj }|d ur|j|  qt
| j jd }ttj|D ]\}}t |||d	|_qd
d | jD | _!dd tj| jD | _"d S )Nc                 S      | S N tr   r   D/var/www/myenv/lib/python3.10/site-packages/keras/src/engine/node.py<lambda>Q       zNode.__init__.<locals>.<lambda>c                 S   r
   r   r   r   r   r   r   r   R   r   c                 S   r
   r   r   r   r   r   r   r   S   r      r   T)ignore_call_contextlayer
node_indextensor_indexc                 S      g | ]}t t|qS r   strid.0r   r   r   r   
<listcomp>   s    z!Node.__init__.<locals>.<listcomp>c                 S   r   r   r   r   r   r   r   r      s    )#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appendr   r   _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   r   r   __init__C   sj   




zNode.__init__c                 C      | j S )zNTensors input to this node that can be traced back to a
        `keras.Input`.)r2   r>   r   r   r   r8      s   zNode.keras_inputsc                 C   s<   g }| j D ]}|jj}|jj}|dur||j|  q|S )zNReturns all the `Node`s whose output this node immediately depends
        on.N)r8   r9   r   r   r6   r7   )r>   	node_depsrD   r   r   r   r   r   parent_nodes   s   
zNode.parent_nodesc                 c   s8    | j D ]}|j}|j}|j}|j}||||fV  qdS )zYields tuples representing the data inbound from other nodes.

        Yields:
          tuples like: (inbound_layer, node_index, tensor_index, tensor).
        N)r8   r9   r   r   r   )r>   rD   keras_historyr   r   r   r   r   r   iterate_inbound   s   
zNode.iterate_inboundc                 C   st   | j r| jd \}}||  fi fS t| j}| jD ]\}}||  ||< qtj| j| j	f|\}}||fS )z;Maps Keras Tensors to computed Tensors using `tensor_dict`.r   )
r*   r3   popcopyr'   r    r!   pack_sequence_asr$   r%   )r>   tensor_dictrB   _flat_argumentsrC   argskwargsr   r   r   map_arguments   s   zNode.map_argumentsc           	         s  | j | j}| jj|\}}tt| jjjdd |}| |fdd t	j
 z
tjtjd W n  ty_   t	j
t}td| jj d d t| d	 w  fd
d}t	j
||}t	j
|s}| jjs}|g}t|}|S )z4Serializes `Node` for Functional API's `get_config`.r   Nc                    s   t | dr | j}|j} |jj|}|d}|jj||jgS t| tj	r*| 
 S t| tjr7t| 
 S t| tjjrGtt | fS | S )z,Serializes a single Tensor passed to `call`.r9   r   )hasattrr9   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_mapr   r   _serialize_keras_tensor   s   
z/Node.serialize.<locals>._serialize_keras_tensor)defaultzLayer z- was passed non-JSON-serializable arguments. zArguments had types: z6. They cannot be serialized out when saving the model.c                    s\   t | r!| j}|j}|jj|}|d}|jj||jg}ntd | g}t	|S )Nr   )
r5   r9   r   r   rX   rY   r   r   r   ListWrapper)r   rc   r   rd   re   datarh   rU   rf   rg   r   r   serialize_first_arg_tensor   s   
z2Node.serialize.<locals>.serialize_first_arg_tensor)r$   r%   r   
_call_specsplit_out_first_argdictzip	arg_namesupdater    r!   r"   jsondumpsr   get_json_type	TypeErrortyperX   r   	is_nested#_preserve_input_structure_in_configr   convert_inner_node_data)	r>   rf   rg   rT   inputs	argumentskwarg_typesrn   rl   r   rm   r   	serialize   sH   



zNode.serializec                 C   s   | j r| jgS | jd S )Nr   )r   r#   r$   rI   r   r   r   input_tensors
  s   
zNode.input_tensorsc                 C   s   | j r| jgS | jS r   )r   r#   rI   r   r   r   output_tensors  s   zNode.output_tensorsc                 C   s0   t jtj| j}t|dkr| js|d S |S )Nr   r   )r    r!   r"   r   	int_shaper   r(   r   )r>   input_shapesr   r   r   r     s   zNode.input_shapesc                 C   s   t jtj| jS r   )r    r!   r"   r   r   r   rI   r   r   r   output_shapes  s   zNode.output_shapesc                 C   rH   r   )r   rI   r   r   r   outbound_layer#  s   zNode.outbound_layerc                 C   sD   | j rg S dd | jD }tjdd |}t|dkr |d S |S )z2Return all layers that feed into the current node.c                 S   s$   g | ]}t |rt|d r|qS )r9   )r    r)   rW   )r   xr   r   r   r   ,  s    z'Node.inbound_layers.<locals>.<listcomp>c                 S   s   | j jS r   )r9   r   r   r   r   r   r   2  s    z%Node.inbound_layers.<locals>.<lambda>r   r   )r   r'   r    r!   r"   r(   )r>   tensor_call_argsinbound_layersr   r   r   r   '  s   zNode.inbound_layers)NNN)__name__
__module____qualname____doc__rG   propertyr8   rK   rM   rV   r   r   r   r   r   r   r   r   r   r   r   r	   $   s,    
F

R




r	   c                   @   s   e Zd ZdZdZdS )r;   a,  Tracks the Layer call that created a Tensor, for Keras Graph Networks.

    During construction of Keras Graph Networks, this metadata is added to
    each Tensor produced as the output of a Layer, starting with an
    `InputLayer`. This allows Keras to track how each Tensor was produced, and
    this information is later retraced by the `keras.engine.Network` class to
    reconstruct the 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   	__slots__r   r   r   r   r;   9  s    r;   r   c                 C   s
   t | dS )Nr9   )rW   )r?   r   r   r   r5   W  s   
r5   )r   collectionsrO   ru   numpyrZ   tensorflow.compat.v2r+   v2r    	keras.srcr   keras.src.enginer   #keras.src.saving.legacy.saved_modelr   keras.src.utilsr   r   r`   r	   
namedtupler;   r5   r   r   r   r   <module>   s*     
