a
    Sic
                    @   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dlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlm Z  ddl!m"Z# ddl$m%Z% G dd dej&Z'dd Z(dd Z)dd Z*dd Z+dd Z,d d! Z-d"d# Z.d,d$d%Z/d-d&d'Z0d(d) Z1G d*d+ d+ej2Z3dS ).zHA `Network` is way to compose layers: the topological form of a `Model`.    N)backend)
layout_map)
base_layer)base_layer_utils)functional_utils)input_layer)
input_spec)node)training)training_utils)
json_utils)network_serialization)generic_utils)
tf_inspect)tf_utils)
tf_logging)doc_controlsc                       s  e Zd ZdZeedejj	Z	e
jjjdC fdd	Ze
jjjdd Zed	d
 Zedd Zedd Zejdd Zedd Zedd Zdd Zedd ZdD fdd	Z fddZdd Zedd  Zd!d" ZejdEd#d$Z d%d& Z!dFd'd(Z"dGd)d*Z#d+d, Z$d-d. Z% fd/d0Z&d1d2 Z'd3d4 Z(dHd5d6Z)d7d8 Z*d9d: Z+d;d< Z,d=d> Z-ed?d@ Z.dI fdAdB	Z/  Z0S )J
Functionalak  A `Functional` model is a `Model` defined as a directed graph of layers.

    Three types of `Model` exist: subclassed `Model`, `Functional` model,
    and `Sequential` (a special case of `Functional`).
    In general, more Keras features are supported with `Functional`
    than with subclassed `Model`s, specifically:

    - Model cloning (`keras.models.clone`)
    - Serialization (`model.get_config()/from_config`, `model.to_json()`
    - Whole-model saving (`model.save()`)

    A `Functional` model can be instantiated by passing two arguments to
    `__init__`. The first argument is the `keras.Input` Tensors that represent
    the inputs to the model. The second argument specifies the output
    tensors that represent the outputs of this model. Both arguments can be a
    nested structure of tensors.

    Example:

    ```
    inputs = {'x1': keras.Input(shape=(10,)), 'x2': keras.Input(shape=(1,))}
    t = keras.layers.Dense(1, activation='relu')(inputs['x1'])
    outputs = keras.layers.Add()([t, inputs['x2'])
    model = keras.Model(inputs, outputs)
    ```

    A `Functional` model constructed using the Functional API can also include
    raw TensorFlow functions, with the exception of functions that create
    Variables or assign ops.

    Example:

    ```python
    inputs = keras.Input(shape=(10,))
    x = keras.layers.Dense(1)(inputs)
    outputs = tf.nn.relu(x)
    model = keras.Model(inputs, outputs)
    ```

    A new `Functional` model can also be created by using the
    intermediate tensors. This enables you to quickly extract sub-components
    of the model.

    Example:

    ```python
    inputs = keras.Input(shape=(None, None, 3))
    processed = keras.layers.RandomCrop(width=32, height=32)(inputs)
    conv = keras.layers.Conv2D(filters=2, kernel_size=3)(processed)
    pooling = keras.layers.GlobalAveragePooling2D()(conv)
    feature = keras.layers.Dense(10)(pooling)

    full_model = keras.Model(inputs, feature)
    backbone = keras.Model(processed, conv)
    activations = keras.Model(conv, feature)
    ```

    Note that the `backbone` and `activations` models are not
    created with `keras.Input` objects, but with the tensors that are originated
    from `keras.Input` objects. Under the hood, the layers and weights will
    be shared across these models, so that user can train the `full_model`, and
    use `backbone` or `activations` to do feature extraction.
    The inputs and outputs of the model can be nested structures of tensors as
    well, and the created models are standard `Functional` model that support
    all the existing API.

    Args:
      inputs: List of input tensors (must be created via `tf.keras.Input()` or
        originated from `tf.keras.Input()`).
      outputs: List of output tensors.
      name: String, optional. Name of the model.
      trainable: Boolean, optional. If the model's variables should be
        trainable.
    )_layer_call_argspecs_compiled_trainable_state_output_mask_cache_output_tensor_cache_output_shape_cacheNTc                    sv   | dd}|rd S t|i  t j||d tjj rft	dd tj
|D sft||\}}| || d S )N	skip_initF)name	trainablec                 S   s   g | ]}t |qS  )r   Zis_input_keras_tensor.0tr   r   S/var/www/html/django/DPS/env/lib/python3.9/site-packages/keras/engine/functional.py
<listcomp>   s   z'Functional.__init__.<locals>.<listcomp>)popr   validate_kwargssuper__init__tfcompatv1#executing_eagerly_outside_functionsallnestflattenr   Zclone_graph_nodes_init_graph_network)selfinputsoutputsr   r   kwargsr   	__class__r   r    r%      s    
zFunctional.__init__c                 C   s  t jdd d| _t|tr>ttj	
|dkr>|d }t|trdttj	
|dkrd|d }|| _|| _tj	
|| _tj	
|| _tj	| jsd| _n^t| jttfrtdd | jD sd| _n2t| jtrtdd | j D sd| _nd| _tjj s0td	d | jD r0t| j |   d| _tj	d
d || _d| _d| j_ d| j_!d| _"g | _#g | _$g | _%g | _&i | _'i | _(i | _)| jD ]0}|j*\}}}| j$+| | j&+|||f q| jD ]L}|j*\}}}|dksJ |dksJ | j#+| | j%+|||f qt,| j| j\}}}	}
|| _-|| _.|	| _/i | _0| j/D ]}t12|j3| j0|< qX| 4  g | _5g | _6g | _7g | _8| j#D ]F}| j5+|j9 |j:r| j6+|j9 | j8+|j; | j7+|j< q| =  | >| j t?@| jA | jBd urtCD| | jB d S )Nr   T   r   c                 s   s   | ]}t j|V  qd S Nr&   r+   	is_nestedr   r   r   r    	<genexpr>   s   z1Functional._init_graph_network.<locals>.<genexpr>c                 s   s   | ]}t j|V  qd S r5   r6   r   r   r   r    r8      s   Fc                 s   s   | ]}t |d  V  qdS )_keras_historyN)hasattrr   tensorr   r   r    r8      s   c                 S   s   | j S r5   )shapexr   r   r    <lambda>       z0Functional._init_graph_network.<locals>.<lambda>)Er   Zkeras_api_gaugeget_cellset_is_graph_network
isinstancelistlenr&   r+   r,   _nested_inputs_nested_outputsr/   r0   r7   _enable_dict_to_input_mappingtupleanydictvaluesr'   r(   r)   r   create_keras_history"_validate_graph_inputs_and_outputsbuiltmap_structure_build_input_shape _compute_output_and_mask_jointly
_call_specexpects_training_argexpects_mask_arg	_autocast_input_layers_output_layers_input_coordinates_output_coordinatesr   r   r   r9   append_map_graph_network_network_nodes_nodes_by_depth_self_tracked_trackablesr   r   getfullargspeccall_set_output_namesinput_names_feed_input_names_feed_inputs_feed_input_shapesr   is_placeholder_batch_input_shapeinput_compute_tensor_usage_count_set_save_specr   assert_no_legacy_layerslayersZ_layout_maplayout_map_libZ_map_functional_model_variable)r.   r/   r0   r?   layer
node_indextensor_indexnodesnodes_by_depthro   _r   r   r    r-      s    




zFunctional._init_graph_networkc                 C   s   | j S )af  Retrieves the input tensor(s) of a layer.

        Only applicable if the layer has exactly one input,
        i.e. if it is connected to one incoming layer.

        Returns:
            Input tensor or list of input tensors.

        Raises:
          RuntimeError: If called in Eager mode.
          AttributeError: If no inbound nodes are found.
        )rH   r.   r   r   r    rk   3  s    zFunctional.inputc                 C   s   t jtj| jS )a  Retrieves the input shape(s) of a layer.

        Only applicable if the layer has exactly one input,
        i.e. if it is connected to one incoming layer, or if all inputs
        have the same shape.

        Returns:
            Input shape, as an integer shape tuple
            (or list of shape tuples, one tuple per input tensor).

        Raises:
            AttributeError: if the layer has no defined input_shape.
            RuntimeError: if called in Eager mode.
        )r&   r+   rR   r   	int_shaperk   rw   r   r   r    input_shapeC  s    zFunctional.input_shapec                    sz   t  dr jS t jtttfr:t jt jkr:d S t jtrft	 j
 } fdd|D S dd  jD S d S )N_manual_input_specc                    s&   g | ]}t jt j| d |dqS T)r=   allow_last_axis_squeezer   )r   	InputSpecshape_with_no_batch_sizerH   )r   r   rw   r   r    r!   b  s   z)Functional.input_spec.<locals>.<listcomp>c                 S   s&   g | ]}t jt|d |jjjdqS r{   )r   r}   r~   r9   rq   r   r   r?   r   r   r    r!   m  s   )r:   rz   rE   rH   rM   rF   rK   rG   r/   sortedkeys)r.   namesr   rw   r    r   U  s     

zFunctional.input_specc                 C   s
   || _ d S r5   )rz   )r.   valuer   r   r    r   v  s    c                 C   s   | j S )a  Retrieves the output tensor(s) of a layer.

        Only applicable if the layer has exactly one output,
        i.e. if it is connected to one incoming layer.

        Returns:
          Output tensor or list of output tensors.

        Raises:
          AttributeError: if the layer is connected to more than one incoming
            layers.
          RuntimeError: if called in Eager mode.
        )rI   rw   r   r   r    outputz  s    zFunctional.outputc                 C   s   t jtj| jS )a  Retrieves the output shape(s) of a layer.

        Only applicable if the layer has one output,
        or if all outputs have the same shape.

        Returns:
            Output shape, as an integer shape tuple
            (or list of shape tuples, one tuple per output tensor).

        Raises:
            AttributeError: if the layer has no defined output shape.
            RuntimeError: if called in Eager mode.
        )r&   r+   rR   r   rx   r   rw   r   r   r    output_shape  s    zFunctional.output_shapec                 C   sr   g }t  }i }| jD ]R}|j}||v rR||jd}d|j|}|d ||j< q|| || q|| _dS )zAssigns unique names to the Network's outputs.

        Output layers with multiple output tensors would otherwise lead to
        duplicate names in self.output_names.
        r4   z{}_{}N)rC   rZ   r   getformataddr]   output_names)r.   
uniquifiedr   prefix_countrq   proposalexisting_countr   r   r    rd     s    

zFunctional._set_output_namesc              	   C   sb   d}t  }t| jD ]F\}}z|jr:||d| < |d7 }W n tyN   Y n0 ||d| < q|S )zBDictionary of layer dependencies to be included in the checkpoint.r   zlayer_with_weights-%dr4   zlayer-%d)collectionsOrderedDict	enumeratero   weights
ValueError)r.   weight_layer_indexdependencieslayer_indexrq   r   r   r    _layer_checkpoint_dependencies  s    z)Functional._layer_checkpoint_dependencies
checkpointc                    s$   | j }|t j|fi | |S r5   )r   updater$   _trackable_children)r.   	save_typer1   r   r2   r   r    r     s    zFunctional._trackable_childrenc                    s"   | j }||v r|| S t |S r5   )r   r$   _lookup_dependency)r.   r   layer_dependenciesr2   r   r    r     s    zFunctional._lookup_dependencyc                 C   s@   | j }dd | D }|D ]}||v r| j|| |d qdS )z@Handles layer checkpoint dependencies that are added after init.c                 S   s   i | ]\}}||qS r   r   )r   kvr   r   r    
<dictcomp>  rA   zBFunctional._handle_deferred_layer_dependencies.<locals>.<dictcomp>)r   	trackableN)r   items_handle_deferred_dependencies)r.   ro   layer_checkpoint_dependencieslayer_to_namerq   r   r   r    #_handle_deferred_layer_dependencies  s    z.Functional._handle_deferred_layer_dependenciesc                 C   s   dS )NTr   rw   r   r   r    _should_compute_mask  s    zFunctional._should_compute_maskc                 C   s    | j ||d}tjdd |S )N)maskc                 S   s   t | dd S )N_keras_mask)getattr)r   r   r   r    r@     rA   z)Functional.compute_mask.<locals>.<lambda>)_run_internal_graphr&   r+   rR   )r.   r/   r   output_tensorsr   r   r    compute_mask  s    zFunctional.compute_maskc                 C   s   | j |||dS )a  Calls the model on new inputs.

        In this case `call` just reapplies
        all ops in the graph to the new inputs
        (e.g. build a new computational graph from the provided inputs).

        Args:
            inputs: A tensor or list of tensors.
            training: Boolean or boolean scalar tensor, indicating whether to
                run the `Network` in training mode or inference mode.
            mask: A mask or list of masks. A mask can be
                either a tensor or None (no mask).

        Returns:
            A tensor if there is a single output, or
            a list of tensors if there are more than one outputs.
        )r
   r   )r   )r.   r/   r
   r   r   r   r    rc     s    zFunctional.callc                 C   sF  t j|dd}ttj|ttj| jkrLtd| dt| j dz,tt j|dd}|| j	v rv| j	| W S W n ty   Y n0 i }t
| jtj|D ]\}}|jd }|||< qt| j }|jdd t|d	krB|D ]}| j| }	|	D ]}
|
j}|| jv rqg }|
jd
 }tj|D ]2}|j}|jjd|j|jf  }|||  q0tj||}t j|dd}||}t j|dd}|j|
}ttj|D ]$\}}|jd||f  }|||< qqqg }tt| jD ]6}| j| \}}}|jd||f  }|||  qtj| j|}|| j	|< |S )NF)	to_tupleszInvalid `input_shape` argument z: the model expects z input tensors.T_0_0reverser4   r   z_%s_%s)r   convert_shapesrG   r&   r+   r,   rY   r   rK   r   zipr   rF   r`   r   sortrq   	call_argsr9   rr   rs   r]   pack_sequence_ascompute_output_shape_inbound_nodesindexr   rangerZ   r\   rI   )r.   ry   	cache_keylayers_to_output_shapesrq   r=   	shape_key
depth_keysdepthrt   r	   layer_input_shapeslayer_inputslayer_inputkhinput_layer_keylayer_output_shapesrr   joutput_shapesirs   r   r   r    r      s    






zFunctional.compute_output_shapec                 C   s<   |s2| j j}| j tkrd}tjt||d| _n|| _d S )NModel)
zero_based)r3   __name__r   r   unique_object_namer   to_snake_case_name)r.   r   r   cls_namer   r   r    _init_set_nameb  s    


zFunctional._init_set_namec                    s  |  |}|du r"dgt| }n
|  |}t||D ]\}}||_q6i  | j}t| j|D ]4\}}| j||d}tt|}	|g||	   |	< q\| j	}
t
|
 }|jdd |D ]}|
| }|D ]v}|jrqt fdd|jD rq| \}}|j|i |}t|jtj|D ]\}	}|g||	   |	< qqqg }| jD ]>}tt|}	|	 v srJ dt| | |	   qHtj| j|S )aY  Computes output tensors for new inputs.

        # Note:
            - Can be run on non-Keras tensors.

        Args:
            inputs: Tensor or nested structure of Tensors.
            training: Boolean learning phase.
            mask: (Optional) Tensor or nested structure of Tensors.

        Returns:
            output_tensors
        N)	ref_inputTr   c                 3   s   | ]}| vV  qd S r5   r   )r   t_idtensor_dictr   r    r8     rA   z1Functional._run_internal_graph.<locals>.<genexpr>zCould not compute output )_flatten_to_reference_inputsrG   r   r   _tensor_usage_countr/   _conform_to_reference_inputstridr`   rF   r   r   is_inputrL   flat_input_idsmap_argumentsrq   flat_output_idsr&   r+   r,   r0   r]   r"   r   rI   )r.   r/   r
   r   masksinput_ttensor_usage_countr?   yx_idru   r   r   rt   r	   argsr1   r0   r   r   r   r    r   o  sD    


zFunctional._run_internal_graphc                    s   | j rttr| j}tj|s*| jg}t|trBt|  ndd |D  t	t	 krt
jd fdd D dd zfdd D W S  ty   tj Y S 0 tjS )z1Maps `tensors` to their respective `keras.Input`.c                 S   s   g | ]}|j jjqS r   )r9   rq   r   )r   inpr   r   r    r!     s   z;Functional._flatten_to_reference_inputs.<locals>.<listcomp>zdInput dict contained keys {} which did not match any model input. They will be ignored by the model.c                    s   g | ]}| vr|qS r   r   r   n)ref_input_namesr   r    r!     rA      )
stacklevelc                    s   g | ]} | qS r   r   r   )tensorsr   r    r!     rA   )rJ   rE   rM   rH   r&   r+   r7   r   r   rG   warningswarnr   KeyErrorr,   )r.   r   
ref_inputsr   )r   r   r    r     s*    
z'Functional._flatten_to_reference_inputsc           
   
   C   sZ  t |tjr|j}|j}|j}|j}t|dd}|dur|dur||d krh|d dkrhtj|dd}n&||d kr|d dkrtj|dd}|dur||_t	 sz|
|j|j W n* ty   td|j||j Y n0 tj||jd}n\t|rVt|dd}t|dd}	|	durV|durV||	krV|	tjkrVtj||	d}|S )	z,Set shape and dtype based on `keras.Input`s.r9   Nr4   )axiszkModel was constructed with shape {} for input {}, but it was called on an input with incompatible shape {}.dtyper   )rE   r&   Tensorr=   rankr   squeezeexpand_dimsr9   executing_eagerly	set_shape
merge_withr   loggingwarningr   castr   r   is_extension_typevariant)
r.   r<   r   t_shapet_rank	ref_shaperef_rankkeras_historytensor_dtyperef_input_dtyper   r   r    r     sH    

	z&Functional._conform_to_reference_inputc                    s   t   }tt| |dS )N)config)r$   
get_configcopydeepcopyget_network_config)r.   r  r2   r   r    r  
  s    
zFunctional.get_configc                 C   sn   i }| j D ]^}tjj| \}}|D ]>}t|tjr(|| }ddd |D }|||j	d | < q(q
|S )N.c                 S   s   g | ]
}|j qS r   r   r   r   r   r    r!     rA   z/Functional.get_weight_paths.<locals>.<listcomp>)
ro   r&   __internal__trackingObjectGraphViewbreadth_first_traversalrE   Variablejoinr   )r.   resultrq   descendantsZobject_paths_dict
descendantZtrackable_referencesobject_pathr   r   r    get_weight_paths  s     
zFunctional.get_weight_pathsc              
   C   s*  t dd | jD t | jkr.td| j | jD ]}t|ds`| jj}td| d| d|jj}t |jdks|jr4|jd	 j	s4| jj}t
| d
| j d|j d|  q4tdd | jD }|d t |dkrt
dt|  | jD ]*}t|ds| jj}td| d| qdS )z4Validates the inputs and outputs of a Graph Network.c                 S   s   h | ]}t |qS r   )r   )r   r   r   r   r    	<setcomp>$  rA   z@Functional._validate_graph_inputs_and_outputs.<locals>.<setcomp>zThe list of inputs passed to the model contains the same input multiple times. All inputs should only appear once.Received inputs=r9   zInput tensors to a z8 model must come from `tf.keras.Input`. Received inputs=z# (missing previous layer metadata).r4   r   z model inputs must come from `tf.keras.Input` (thus holding past layer metadata). They cannot be the output of a previous non-Input layer. Here, a tensor specified as input to "z6" was not an Input tensor, it was generated by layer "zx".
Note that input tensors are instantiated via `tensor = tf.keras.Input(shape)`.
The tensor that caused the issue was: c                 S   s   g | ]}t |jjqS r   )r   get_static_batch_sizer9   rq   r   r   r   r    r!   K  s   zAFunctional._validate_graph_inputs_and_outputs.<locals>.<listcomp>NzEFound incompatible static batch sizes among the inputs. Batch sizes: zOutput tensors of a z] model must be the output of a TensorFlow `Layer` (thus holding past layer metadata). Found: )rG   r/   r   r:   r3   r   r9   rq   r   r   r   r   r   rC   discardr   r0   )r.   r?   r   rq   input_batch_sizesr   r   r    rP   !  sd    


	


z-Functional._validate_graph_inputs_and_outputsc                    s  t j|}t| i | j D ] \ } fdd|D  q$|s`t jdd |D }t|t	
  fdd}t|}d}|r|d7 }|d	krtd
|d}||  du r|| qt|jj|jj|}|| jvr |< | j| | j  | qt| j}	g }
|D ]B}||	vr.| j| |
| t|j| j|< |	| q.| |
 |   dS )a  Inserts Layers into the Network after Network creation.

        This is only valid for Keras Graph Networks.  Layers added via this
        function will be included in the `call` computation and `get_config` of
        this Network.  They will not be added to the Network's outputs.

        Args:
          layers: Arbitrary nested structure of Layers. Layers must be reachable
            from one or more of the `keras.Input` Tensors that correspond to
            this Network's inputs.
          relevant_nodes: Nodes from the Layers that should be considered part
            of this Network. If `None`, all Nodes will be considered part of
            this Network.

        Raises:
          ValueError: If the layers depend on `Input`s not found in this Model.
        c                    s   i | ]
}| qS r   r   r   r	   )r   r   r    r   v  rA   z-Functional._insert_layers.<locals>.<dictcomp>c                 S   s   g | ]
}|j qS r   )r   r   rq   r   r   r    r!   {  rA   z-Functional._insert_layers.<locals>.<listcomp>c                    sV   d}|   D ]@\}}}}|j| }|v r:t|| }q| vrFqq dS q|d S )z5Gets the minimum depth at which node can be computed.r   Nr4   )iterate_inboundr   min)r	   	min_depthrq   node_idrv   inbound_node)network_nodesnode_to_depthr   r    _get_min_depth  s    
z1Functional._insert_layers.<locals>._get_min_depthr   r4   i'  z6Layers could not be added due to missing dependencies.N)r&   r+   r,   r   rn   r`   r   r   rC   rF   r   r  r   r"   r]   _make_node_keyrq   r   r   r   r_   r   ra   r   rb   rc   r   r   rl   )r.   ro   relevant_nodesrt   r$  unprocessed_nodesr   r	   node_key	layer_setdeferred_layersrq   r   )r   r"  r#  r    _insert_layers`  sV    









zFunctional._insert_layersc           	      C   s   t  }tdd | jD }t| j }|jdd |dd }|D ]}| j| D ]x}dd tj	
|jD }||rTtj	
|jD ]}|tt|  d7  < qtj	
|jD ]}|tt| qqTqF| jD ]}|tt|  d7  < q|| _dS )	a%  Compute the #. of tensor usages for all the output tensors of layers.

        The computed tensor usage count is saved as `self._tensor_usage_count`.
        This is later used for saving memory in eager computation by releasing
        no-longer-needed tensors as early as possible.
        c                 s   s   | ]}t t|V  qd S r5   r   r   r;   r   r   r    r8     rA   z9Functional._compute_tensor_usage_count.<locals>.<genexpr>Tr   r4   Nc                 S   s   h | ]}t t|qS r   r,  r;   r   r   r    r    s   z9Functional._compute_tensor_usage_count.<locals>.<setcomp>)r   CounterrC   r/   rF   r`   r   r   r&   r+   r,   keras_inputsissubsetr   r   r0   r   r   )	r.   r   available_tensorsr   r   r	   input_tensorsr<   output_tensorr   r   r    rl     s$    

z&Functional._compute_tensor_usage_countc                 C   s   d S r5   r   rw   r   r   r    _assert_weights_created  s    z"Functional._assert_weights_createdc                 C   sP   t | j|g\}}tjd|jd}|| ||j || | || d S )NF)unconditionalr   )	_map_subgraph_networkr/   r   AddLossr   extendinbound_nodesr]   r+  )r.   symbolic_loss	new_nodes
new_layersadd_loss_layerr   r   r    _graph_network_add_loss  s    
z"Functional._graph_network_add_lossc                 C   sR   t | j|g\}}tj|||jd}|| ||j || | || d S )Nr   )	r5  r/   r   	AddMetricr   r7  r8  r]   r+  )r.   r   aggregationr   r:  r;  add_metric_layerr   r   r    _graph_network_add_metric  s    
z$Functional._graph_network_add_metricc                 C   s
   t | S r5   )r   NetworkSavedModelSaverrw   r   r   r    _trackable_saved_model_saver  s    z'Functional._trackable_saved_model_saverc                    s   t | ddrd}t ||S )N_has_explicit_input_shapeTF)r   r$   _get_save_spec)r.   dynamic_batchZinputs_onlyr2   r   r    rE    s    zFunctional._get_save_spec)NT)r   )NN)T)NN)N)TT)1r   
__module____qualname____doc__	frozenset	itertoolschaintraining_libr   _TF_MODULE_IGNORED_PROPERTIESr&   r  r   no_automatic_dependency_trackingr%   r-   propertyrk   ry   r   setterr   r   rd   r   r   r   r   r   r   r   do_not_doc_inheritablerc   r   r   r   r   r   r  r  rP   r+  rl   r3  r=  rA  rC  rE  __classcell__r   r   r2   r    r   /   sf   O
 


 





	b

<(7?
V 

r   c                 C   s   | d t | S )Nz_ib-)r   )
layer_namerr   r   r   r    r%    s    r%  c              
      s  t |\} dd |D }i }i }t|D ]d}||d}||jd}t||}|||j< |||< |jD ]"}	||	d}t|d |||	< qjq*| D ]F}
|
jd }||vrd||< d |< d||jd < |	t
|jd qtt}| D ]\}}|| | qtt}| D ]\}}|| | qt| }|jdd g }|D ],}|| }|j fdd	d
 || qRt| }|jdd t }| D ]}|	t| qg }|D ]}|| D ]}|j}|r|jstj|jD ]0}t||vrtd| d|j d| qtj|jD ]}|	t| q2||j q̐qdd |D }|D ]2}||dkrntd| d|| dqn||||fS )a5  Validates a network's topology and gather its layers and nodes.

    Args:
      inputs: List of input tensors.
      outputs: List of outputs tensors.

    Returns:
      A tuple `(nodes, nodes_by_depth, layers, layers_by_depth)`.
      - nodes: list of Node instances.
      - nodes_by_depth: dict mapping ints (depth) to lists of node instances.
      - layers: list of Layer instances.
      - layers_by_depth: dict mapping ints (depth) to lists of layer instances.

    Raises:
      ValueError: In case the network is not valid (e.g. disconnected graph).
    c                 S   s$   h | ]}t |jj|jj|qS r   )r%  rq   r   r   r   r  r   r   r    r    s   z%_map_graph_network.<locals>.<setcomp>r   r4   r   Tr   c                    s    |  S r5   r   r>   layer_indicesr   r    r@   S  rA   z$_map_graph_network.<locals>.<lambda>)keyz3Graph disconnected: cannot obtain value for tensor z at layer "z>". The following previous layers were accessed without issue: c                 S   s   g | ]
}|j qS r   r  r  r   r   r    r!   t  rA   z&_map_graph_network.<locals>.<listcomp>z
The name "z
" is used z6 times in the model. All layer names should be unique.)
_build_mapreversed
setdefaultr   rq   maxparent_nodesr9   r   r   r%  r   r   defaultdictrF   r   r]   r   r   r7  rC   r   r   r&   r+   r,   r.  r   r0   count)r/   r0   nodes_in_decreasing_depthr"  nodes_depthslayers_depthsr	   r   previous_depthnode_depr   r   ru   layers_by_depthrq   r   ro   layers_for_depthcomputable_tensorsr?   layers_with_complete_input	all_namesr   r   rU  r    r^     s    





r^   c                 C   s>   t  }t  }g }i }tj| D ]}t||||| q ||fS )a  This method topologically sorts nodes in order from inputs to outputs.

    It uses a depth-first search to topologically sort nodes that appear in the
    _keras_history connectivity metadata of `outputs`.

    Args:
      outputs: the output tensors whose _keras_history metadata should be
        walked. This may be an arbitrary nested structure.

    Returns:
      A tuple like (ordered_nodes, layer_to_first_traversal_index)
      ordered_nodes: list of nodes appearing in the keras history, topologically
        sorted from original inputs to the `outputs`.
        (If outputs have different sets of ancestors, the inputs to one output
        may appear after a different output).
      layer_to_first_traversal_index:
        A dict mapping layer to the traversal index in the DFS where it is
        seen. Note: if a layer is shared by several nodes, the dict will only
        store the index corresponding to the *first* time the layer seen.
    )rC   r&   r+   r,   _build_map_helper)r0   finished_nodesnodes_in_progressr_  rV  r   r   r   r    rX  ~  s    rX  c           	      C   s   | j \}}}|j| }||v r"dS ||v rBtd|  d|j d||vrVt|||< || |js|jD ]} t| |||| ql|| |	| |
| dS )z"Recursive helper for `_build_map`.NzTensor z from layer "z" is part of a cycle.)r9   r   r   r   rG   r   r   r.  ri  remover]   )	r<   rj  rk  r_  rV  rq   rr   rv   r	   r   r   r    ri    s6    




ri  c                 C   sF   t jj st| t| |\}}}}t jdd |	 D |fS )zReturns the nodes and layers in the topology from `inputs` to `outputs`.

    Args:
      inputs: List of input tensors.
      outputs: List of output tensors.

    Returns:
      A tuple of List{Node] and List[Layer].
    c                 S   s   g | ]}|qS r   r   )r   rt   r   r   r    r!     rA   z)_map_subgraph_network.<locals>.<listcomp>)
r&   r'   r(   r)   r   rO   r^   r+   r,   rN   )r/   r0   rv   ru   ro   r   r   r    r5    s    

r5  c                 C   s0   | j r"t| to t| j d tjS t| tS dS )zCReturns True if the first layer node should not be saved or loaded.r   N)ra   rE   r   input_layer_module
InputLayer)rq   r   r   r    _should_skip_first_node  s    
ro  c                    sD    fdd|  D }|r@tjdd |  D } ||  S )z?Adds layers that are not connected to the outputs to the model.c                    s   g | ]}| j vr|qS r   )ro   r  modelr   r    r!     s   z,connect_ancillary_layers.<locals>.<listcomp>c                 S   s(   g | ] }t |r|jd d n|jqS )r4   N)ro  r8  r  r   r   r    r!     s   )rN   r&   r+   r,   r+  )rq  created_layersancillary_layersr&  r   rp  r    connect_ancillary_layers  s    
rt  c                    s  p
t  i i t tfddfdd  fdd}fdd}| d	 D ]}|| qdr| d	 D ]P}|d
  }|v r~|}|r~|d }|||r|d q||< q~qq~qrg }	g }
tj| d dd}tj	|D ]T}|
 \}}}|v sJ | }||}|j| j}|	tj	||  qtj| d dd}tj	|D ]V}|
 \}}}|v sJ | }||}|j| j}|
tj	||  qltj||	}	tj||
}
|	|
fS )a  Reconstructs graph from config object.

    Args:
      config: Dictionary returned from Network.get_config()
      custom_objects: Optional dictionary mapping names (strings) to custom
        classes or functions to be considered during deserialization.
      created_layers: Optional dictionary mapping names to Layer objects. Any
        layer not in this dictionary will be created and added to the dict.
        This function will add new nodes to all layers (excluding InputLayers),
        instead of re-using pre-existing nodes in the layers.

    Returns:
      Tuple of (input tensors, output tensors, dictionary of created layers)
    c                    s"   t | tjrdS  | j|fdS )zBReturns node index in layer (might differ from config_node_index).r   N)rE   rm  rn  r   r   )rq   config_node_index)node_index_mapr   r    get_node_index$  s    z/reconstruct_from_config.<locals>.get_node_indexc                    s*    fdd}t j| dd} tj|| S )z-Deserializes Keras Tensors passed to `call`..c                    sj   t | tjrf|  } | d }| d }| d }| } ||}|du rJt|j| }tj|j	| S | S )z4Deserializes a single Keras Tensor passed to `call`.r   r4   r   N)
rE   r   ListWrapperas_list
IndexErrorr   r&   r+   r,   r0   )r   rT  rr   rs   rq   new_node_indexr	   )rw  	layer_mapr   r    _deserialize_keras_tensor-  s    
	
z^reconstruct_from_config.<locals>._deserialize_keras_tensors.<locals>._deserialize_keras_tensorTwrap)r   convert_inner_node_datar&   r+   rR   )r1   r|  r}  )rw  )r|  r    _deserialize_keras_tensors*  s    z;reconstruct_from_config.<locals>._deserialize_keras_tensorsc              	      s  g }t j|D ]@}| }t|dkr0i }nDt|dkrl|d }z |}W qt tyh   Y  dS 0 ntd|d tjkr|d }|d }|d }| }||}|du r dS |j	| }	|
t j|	j|  q|d d	ksJ t|dks J |d }
t|
trHt|
dkrH|
d tjkrH|
t|
d  q|
|
 qt j||}|dur| js~t|}| |fi |}t j|d jj}|| j|  f< |   d7  < d
S )al  Deserialize a node.

        Args:
            layer: layer instance.
            node_data: Nested structure of `ListWrapper`.

        Returns:
            Whether the node was processed (i.e. the layer was called on the
            inputs specified by the node data)

        Raises:
            ValueError: In case of improperly formatted `node_data`.
              Fz"Improperly formatted model config.r   r4   r   Nr   T)r&   r+   r,   ry  rG   rz  r   node_module_CONSTANT_VALUEr   r]   r0   rE   rK   Z_COMPOSITE_TYPEr   decoder   #_preserve_input_structure_in_configr   unnest_if_single_tensorr9   rr   r   )rq   	node_datar1  
input_datar1   inbound_layer_nameinbound_node_indexinbound_tensor_indexinbound_layerr!  Z	const_valr   output_index)r  rr  rw  node_count_by_layerrv  r   r    process_nodeH  sj    



z-reconstruct_from_config.<locals>.process_nodec                    s|   | d }| v r | }n ddl m} || d}| |< tt||< | d }tj|dd}|D ]}| | qddS )	zDeserializes a layer, then call it on appropriate inputs.

        Args:
            layer_data: layer config dict.

        Raises:
            ValueError: In case of improperly formatted `layer_data` dict.
        r   r   )deserialize)custom_objectsr8  Tr~  N)keras.layersr  intro  r   r  r]   )
layer_datarT  rq   deserialize_layerinbound_nodes_datar  )rr  r  r  r'  r   r    process_layer  s    	
z.reconstruct_from_config.<locals>.process_layerro   r   r   input_layersTr~  output_layers)r   r   r]  rF   r"   r   r  r&   r+   r,   ry  r   r   r]   r   )r  r  rr  r  r  r  rq   Zlayer_nodesr  r1  r   r  rT  rr   rs   layer_output_tensorsr  r   )r  rr  r  rw  r  rv  r'  r    reconstruct_from_config  sd    
Q#




r  c                 C   sb  |pt j}|pi }| j|d< i }| jD ]N}t|r6dnd}t|jD ].\}}t|j|}|| jv rD|||< |d7 }qDq&g }	t 	  | jD ]r}g }
t|jD ]:\}}t|j|}|| jv r|j
s|t|}|
| q||}|j|d< |
|d< |	| q|	|d< W d   n1 s0    Y  g }tt| jD ]R}| j| \}}}t|j|}|| jvrhq8|| }|t|j||g q8tj| j|}tj|s|g}t|}||d< g }tt| jD ]R}| j| \}}}t|j|}|| jvrq|| }|t|j||g qtj| j|}tj|sL|g}t|}||d< |S )	aQ  Builds the config, which consists of the node graph and serialized layers.

    Args:
      network: A Network object.
      serialize_layer_fn: Function used to serialize layers.
      config: A dict to append more config entries into. If None, start with a
          new dict for the config.

    Returns:
      Config dictionary.
    r   r4   r   r8  ro   Nr  r  )r   serialize_keras_objectr   ro   ro  r   r   r%  r_   SharedObjectSavingScoper   	serializer]   r   rG   rY   r[   r   rx  r&   r+   r   rH   r7   r  rZ   r\   rI   )networkserialize_layer_fnr  node_conversion_maprq   
kept_nodesoriginal_node_indexr	   r(  layer_configsfiltered_inbound_nodesr  layer_configmodel_inputsr   rr   rs   r{  model_outputsr   r   r    r	    s~    





(

r	  c                 C   s*   | j jd u rd S | j  }|r&d |d< |S )Nr   )r=   r   ry  )r?   r=   r   r   r    r~   J  s    
r~   c                       s*   e Zd ZdZd fdd	Zdd Z  ZS )ModuleWrapperzFWrapper for `tf.Module`s to support the Functional and Sequential API.Nc                    s   t  jf i | |du r8t|dr*d}nt|dr8d}|du sJt||sZtd|||| _|| _t||}t	|}d|j
v p|jdu| j_d|j
v p|jdu| j_dS )a  Initializes the wrapper Layer for this module.

        Args:
          module: The `tf.Module` instance to be wrapped.
          method_name: (Optional) str. The name of the method to use as the
            forward pass of the module. If not set, defaults to '__call__' if
            defined, or 'call'.
          **kwargs: Additional keywrod arguments. See `tf.keras.layers.Layer`.

        Raises:
          ValueError: If `method` is not defined on `module`.
        N__call__rc   z{} is not defined on object {}r
   r   )r$   r%   r:   r   r   _module_method_namer   r   rb   r   varkwrU   rV   rW   )r.   modulemethod_namer1   methodmethod_arg_specr2   r   r    r%   V  s&    





zModuleWrapper.__init__c                 O   sH   d|v r| j s|d d|v r0| js0|d t| j| j|i |S )Nr
   r   )_expects_training_argr"   _expects_mask_argr   r  r  )r.   r   r1   r   r   r    rc   |  s
    

zModuleWrapper.call)N)r   rG  rH  rI  r%   rc   rS  r   r   r2   r    r  S  s   &r  )NN)NN)4rI  r   r  rK  r   Ztensorflow.compat.v2r'   v2r&   kerasr   keras.dtensorr   rp   keras.enginer   r   r   r   rm  r   r	   r  r
   rM  r   Zkeras.saving.saved_modelr   r   keras.utilsr   r   r   tensorflow.python.platformr   r   tensorflow.tools.docsr   r   r   r%  r^   rX  ri  r5  ro  rt  r  r	  r~   Layerr  r   r   r   r    <module>   sT          W{$.
 o
W	