B
    d5              	   @   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dddgZdd ZdS )zContains the `Node` class.    N)backend)base_layer_utils)
json_utils)tf_utils_CONSTANT_VALUEZ_TYPEZ	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 krg n|}|d kri n|}|d kr,g n|}|| _ | o@| | _tjdd |}tjdd |}tjdd || _|| _|| _tj| j| jf| _	| j ot
| jdkot| jd | _tjj sx2| j	D ](}t|tjrtj|ddrt| qW g | _g | _xNt| j	D ]@\}}t|r | j| tt|}|}	| j||	f q W | j j|  x.| jD ]$}
|
jj }|d k	rz|j|  qzW t
| j jd }x.ttj|D ]\}}t |||d	|_qW d
d | jD | _!dd tj| jD | _"d S )Nc             S   s   | S )N )tr   r   C/var/www/html/venv/lib/python3.7/site-packages/keras/engine/node.py<lambda>Q       zNode.__init__.<locals>.<lambda>c             S   s   | S )Nr   )r	   r   r   r
   r   R   r   c             S   s   | S )Nr   )r	   r   r   r
   r   S   r      r   T)Zignore_call_context)layer
node_indextensor_indexc             S   s   g | ]}t t|qS r   )strid).0r	   r   r   r
   
<listcomp>   s    z!Node.__init__.<locals>.<listcomp>c             S   s   g | ]}t t|qS r   )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compatZv1Z#executing_eagerly_outside_functions
isinstanceTensorr   Zneeds_keras_historyZcreate_keras_history_keras_inputs_keras_inputs_ids_and_indices	enumerateis_keras_tensorappendr   r   _inbound_nodeskeras_inputs_keras_historyZ_outbound_nodesKerasHistoryZflat_input_idsZflat_output_ids)selfr   r   r   r   objiZelekt_idkt_indexktZinbound_layerr   Ztensorr   r   r
   __init__C   sR    



zNode.__init__c             C   s   | j S )zNTensors input to this node that can be traced back to a
        `keras.Input`.)r$   )r-   r   r   r
   r*      s    zNode.keras_inputsc             C   s@   g }x6| j D ],}|jj}|jj}|dk	r||j|  qW |S )zNReturns all the `Node`s whose output this node immediately depends
        on.N)r*   r+   r   r   r(   r)   )r-   Z	node_depsr2   r   r   r   r   r
   parent_nodes   s    zNode.parent_nodesc             c   s:   x4| j D ]*}|j}|j}|j}|j}||||fV  qW dS )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-   r2   Zkeras_historyr   r   r   r   r   r
   iterate_inbound   s    zNode.iterate_inboundc             C   s|   | j r&| jd \}}||  fi fS t| j}x"| jD ]\}}||  ||< q:W tj| j| j	f|\}}||fS dS )z;Maps Keras Tensors to computed Tensors using `tensor_dict`.r   N)
r    r%   popcopyr   r   r   Zpack_sequence_asr   r   )r-   Ztensor_dictr0   _Zflat_argumentsr1   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
 ytjtjd W nF tk
r   t	j
t}td| jj d d t| d	 Y nX  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	rT| 
 S t| tjrnt| 
 S t| tjjrtt | fS | S )z,Serializes a single Tensor passed to `call`.r+   r   )hasattrr+   r   r   namegetr   r"   npZndarraytolistr   r#   r   	get_valueZ__internal__ZCompositeTensor_COMPOSITE_TYPEr   Z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 | rB| j}|j}|jj|}|d}|jj||jg}ntd | g}t	|S )Nr   )
r'   r+   r   r   r=   r>   r   r   r   ZListWrapper)r	   rD   r   rE   rF   data)rI   r:   rG   rH   r   r
   serialize_first_arg_tensor   s    z2Node.serialize.<locals>.serialize_first_arg_tensor)r   r   r   Z
_call_specZsplit_out_first_argdictzip	arg_namesupdater   r   r   jsondumpsr   Zget_json_type	TypeErrortyper=   r   Z	is_nestedZ#_preserve_input_structure_in_configr   Zconvert_inner_node_data)	r-   rG   rH   r9   inputs	argumentsZkwarg_typesrM   rL   r   )rI   r:   rG   rH   r
   	serialize   s*    
(

zNode.serializec             C   s   | j r| jgS | jd S )Nr   )r   r   r   )r-   r   r   r
   input_tensors
  s    zNode.input_tensorsc             C   s   | j r| jgS | jS )N)r   r   )r-   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_shaperY   r   r   )r-   input_shapesr   r   r
   r\     s
    zNode.input_shapesc             C   s   t jtj| jS )N)r   r   r   r   r[   rZ   )r-   r   r   r
   output_shapes  s    zNode.output_shapesc             C   s   | j S )N)r   )r-   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 )r+   )r   r   r<   )r   xr   r   r
   r   -  s   z'Node.inbound_layers.<locals>.<listcomp>c             S   s   | j jS )N)r+   r   )r	   r   r   r
   r   2  r   z%Node.inbound_layers.<locals>.<lambda>r   r   )r   r   r   r   r   r   )r-   Ztensor_call_argsinbound_layersr   r   r
   r`   '  s    
zNode.inbound_layers)NNN)__name__
__module____qualname____doc__r3   propertyr*   r4   r5   r;   rX   rY   rZ   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)ra   rb   rc   rd   	__slots__r   r   r   r
   r,   9  s   r,   r   r   r   c             C   s
   t | dS )Nr+   )r<   )r.   r   r   r
   r'   W  s    r'   )rd   collectionsr7   rR   numpyr?   Ztensorflow.compat.v2r!   Zv2r   Zkerasr   Zkeras.enginer   Zkeras.saving.legacy.saved_modelr   Zkeras.utilsr   r   rB   r   
namedtupler,   r'   r   r   r   r
   <module>   s$     
