
    &Vf<                         d dl 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
  ed           G d d	e
                      Zd
 Zd Zd Zd ZdS )    N)tree)keras_export)KerasTensor)backend)	Operationzkeras.Functionc                        e Zd ZdZd fd	Zed             Zed             Zed             Zd Z	d Z
dd	Zd
 Z xZS )Functiona  Class that encapsulates a computation graph of Keras operations.

    You can use a `Function` to capture the computation graph linking
    some input tensors to some output tensors, and reapply the same
    computation on new inputs.

    A `Function` is similar to a Functional Model, with the difference
    that it is stateless (it does not track state variables)
    and does not implement the `Layer` API.

    Example:

    ```python
    input_1 = keras.KerasTensor(shape=(None, 2, 3))
    input_2 = keras.KerasTensor(shape=(None, 2, 3))
    x = input_1 + input_2
    output = keras.ops.sigmoid(x)
    fn = keras.Function(inputs=[input_1, input_2], outputs=output)

    input_1_val = np.random.random((4, 2, 3))
    input_2_val = np.random.random((4, 2, 3))
    output_val = fn([input_1_val, input_2_val])
    ```

    Args:
        inputs: `KerasTensor` instance or nested structured of
            `KerasTensor` instances.
        outputs: `KerasTensor` instance or nested structured of
            `KerasTensor` instances. They should be computable
            given only the values of `inputs`.
        name: String. The name of the function.
    Nc                    t                                          |           t                      dk    rt          | dd          }d| _        t          j        d |          | _        t          j        d |          | _        t          j	        |          | _
        t          j	        |          | _        | j
        st          d| d	|           | j        st          d
| d	|           t                      dk    r|| _        t          | j
        | j                  \  }}}}|| _        || _        || _        || _        d S )Nname
tensorflow_self_setattr_trackingTFc                     | S N xs    S/var/www/html/software/conda/lib/python3.11/site-packages/keras/src/ops/function.py<lambda>z#Function.__init__.<locals>.<lambda>9   s    1     c                     | S r   r   r   s    r   r   z#Function.__init__.<locals>.<lambda>:   s    A r   z4`inputs` argument cannot be empty. Received:
inputs=z	
outputs=z5`outputs` argument cannot be empty. Received:
inputs=)super__init__r   getattrr   r   map_structure_inputs_struct_outputs_structflatten_inputs_outputs
ValueError	map_graph_nodes_nodes_by_depth_operations_operations_by_depth)
selfinputsoutputsr   r   nodesnodes_by_depth
operationsoperations_by_depth	__class__s
            r   r   zFunction.__init__-   s}   d###99$$
 &-.& &" +0D'"0fEE#1++wGG|F++W--| 	% % %"% %  
 } 	% % %"% %   99$$*@D'CLL$-D
 D
@
,? -%$7!!!r   c                      | j         d d          S r   )r%   r'   s    r   r,   zFunction.operationsU   s    ""r   c                     | j         S r   )r   r0   s    r   r(   zFunction.inputsY   s
    |r   c                     | j         S r   )r    r0   s    r   r)   zFunction.outputs]   s
    }r   c                    |                      |           d}t          t          j        |          | j                  D ]\  }}|j        |j        k    rd} n|rt          j        d | j                  S |                     |d           S )NTFc                 8    t          | j        | j                  S )N)shapedtype)r   r5   r6   r   s    r   r   z.Function.compute_output_spec.<locals>.<lambda>l   s    +AG17CCC r   c                     | j         S r   )compute_output_specops    r   r   z.Function.compute_output_spec.<locals>.<lambda>t   s	    B,B r   operation_fn)	_assert_input_compatibilityzipr   r   r   r5   r   r   _run_through_graph)r'   r(   shortcutr   x_refs        r   r8   zFunction.compute_output_speca   s    ((000 DL00$,?? 	 	HAuw%+%%  &  	%CC$   &&!B!B ' 
 
 	
r   c                 \    |                      |           |                     |d           S )z'Computes output tensors for new inputs.c                     | S r   r   r9   s    r   r   zFunction.call.<locals>.<lambda>z   s    r r   r;   )r=   r?   )r'   r(   s     r   callzFunction.callw   s1    ((000&&vMM&JJJr   c                 ,   t          j        |          }i t          | j        |          D ]\  }}|t	          |          <   | j        }t          |                                          }|                    d           |D ]}||         }	|	D ]}
|
j	        r|
j
        rt          fd|
j        D                       r2|
j                                      \  }} ||
j	                  }| ||g|R i |}n ||i |}t          |
j        t          j        |                    D ]\  }}|t	          |          <   g }| j        D ]*}|                    t	          |                              +t          j        | j        |          S )zExecute the graph.

        At each node we compute outputs via
        `operation_fn(node.operation)(*args, **kwargs)`.
        Treversec              3   :   K   | ]}t          |          vV  d S r   )id).0r   tensor_dicts     r   	<genexpr>z.Function._run_through_graph.<locals>.<genexpr>   s.      LLAr!uuK/LLLLLLr   )r   r   r>   r(   rI   r$   listkeyssort	operationis_inputanyinput_tensors	argumentsfill_inr)   appendpack_sequence_asr   )r'   r(   r<   call_fnr   yr+   
depth_keysdepthr*   nodeargskwargsr:   r)   output_tensorsrK   s                   @r   r?   zFunction._run_through_graph|   s    f%% V,, 	# 	#DAq!"K1-.--//00
%%% 	+ 	+E"5)E + +~  LLLL9KLLLLL #~55kBBf!\$.11&%gb:4:::6::GG b$1&11G  dl7.C.CDD + +DAq)*K1&&++$  	6 	6A!!+bee"45555$T%9>JJJr   c                 d   	 t          j        || j        d           n(# t          $ r t          d| j         d|           w xY wt	          t          j        |          | j                  D ]\  }}t          |j                  t          |j                  k    r4t          | j	        j
         d|j         d|j         d|j         d          t	          |j        |j                  D ]C\  }}|<|:||k    r4t          | j	        j
         d|j         d|j         d|j         d          Dd S )	NF)check_typeszOFunction was called with an invalid input structure. Expected input structure: z
Received input structure: z, was passed incompatible inputs. For input 'z', expected shape z+, but received instead a tensor with shape .)r   assert_same_structurer   r!   r>   r   r   lenr5   r.   __name__r   )r'   r(   r   rA   dimref_dims         r   r=   z$Function._assert_input_compatibility   s   		&+      	 	 	6-1-@6 6-36 6  	 DL00$,?? 	 	HAu17||s5;//// ~. > >7<z> >&+k> > 457> > >   !$AGU[ 9 9  W&3?g~~(#~6 F F?DzF F.3kF F <=7F F F  	 	s	    %Ar   )re   
__module____qualname____doc__r   propertyr,   r(   r)   r8   rD   r?   r=   __classcell__)r.   s   @r   r	   r	   
   s         B&8 &8 &8 &8 &8 &8P # # X#   X   X
 
 
,K K K
)K )K )K )KV      r   r	   c                 `    t          t          |                     dz   t          |          z   S )Nz_ib-)strrI   )r:   
node_indexs     r   make_node_keyrp      s$    r"vv;;#j//11r   c                    t          | |          \  }d |D             }i }i }t          |          D ]}|                    |d          }|                    |j        d          }t          ||          }|||j        <   |||<   |j        D ].}	|                    |	d          }t          |dz   |          ||	<   /| D ]R}
|
j        d         }|rA||vr=d||<   d|<   d||j        d         <   |	                    t          |d                     St          j        t                    }|                                D ] \  }}||                             |           !t          j        t                    }|                                D ] \  }}||                             |           !t          |                                          }|                    d           g }|D ]8}||         }|                    fd           |                    |           9t          |                                          }|                    d           t'                      }| D ]}|	                    |           g }|D ]}||         D ]}t)          j        |j                  D ]?}||vr|j        }t/          d	| d
| d|           |                    |j                   @t)          j        |j                  D ]}|	                    |           d |D             }|D ]D}|                    |          dk    r)t/          d| d|                    |           d          E||||fS )a  Validates a graph's topology and gather its operations and nodes.

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

    Returns:
        A tuple `(nodes, nodes_by_depth, operations, operations_by_depth)`.
        - nodes: set of Node instances
        - nodes_by_depth: dict mapping ints (depth) to lists of node instances.
        - operations: list of Operation instances.
        - operations_by_depth: dict mapping ints (depth) to lists of Operation
            instances.
    c                 r    h | ]4}t          |j        |j        j                            |                    5S r   )rp   rP   _inbound_nodesindex)rJ   r\   s     r   	<setcomp>zmap_graph.<locals>.<setcomp>   sG        	dndn&C&I&I$&O&OPP  r   r      TrF   c                     |          S r   r   )r   operation_indicess    r   r   zmap_graph.<locals>.<lambda>  s    0A!0D r   )keyz2Graph disconnected: cannot find parent for tensor z at operation 'zB'. The following previous operations were accessed without issue: c                     g | ]	}|j         
S r   r   )rJ   rP   s     r   
<listcomp>zmap_graph.<locals>.<listcomp>8  s    <<<I<<<r   z
The name "z
" is used z: times in the model. All operation names should be unique.)
_build_mapreversed
setdefaultgetrP   maxparent_nodes_keras_historyrs   addrp   collectionsdefaultdictrM   itemsrV   rN   rO   extendsetr   r   rS   r!   r   r)   count)r(   r)   nodes_in_decreasing_depthnetwork_nodesnodes_depthsoperations_depthsr\   r[   previous_depthnode_depinput_tinput_operationr+   r-   rP   rZ   r,   operations_for_depthcomputable_tensorsr   operations_with_complete_input	all_namesr   ry   s                          @r   r"   r"      s   " 4>fg3N3N00 -  M
 L233 D D''a00 +..t~qAA
 E>**,1$.)"T
 ) 	D 	DH)--h::N%(N%C%CL""	D  A A!03 	A6GGG12o.13o.>?L7:;mOQ??@@@ !,T22N#))++ + +eu$$T**** &1$77-3355 5 5	5E")))4444 )..0011JOODO!!! J 0 0259 	!!&D&D&D&D!EEE.//// n))++,,JOODO!!!
  " "q!!!!%'" * *"5) 	* 	*D\$"455 	F 	F... $I$K"#K K4=K K +IK K   /55inEEEE\$,// * *"&&q))))*	*" =<<<<I  ??4  A%%LT L LY__T-B-B L L L   &
 .*6IIIr   c           	          t                      }t                      }g }i }t          j        |          D ]}t          | |||||           ||fS )a  Topologically sort 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, operation_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).
        operation_to_first_traversal_index:
            A dict mapping operation to the traversal index in the DFS where it
            is seen. Note: if a operation is shared by several nodes, the dict
            will onlystore the index corresponding to the *first* time the
            operation seen.
    )r   r   r   _build_map_helper)r(   r)   finished_nodesnodes_in_progressr   ry   outputs          r   r}   r}   B  ss    , UUN ",w'' 
 
%	
 	
 	
 	
 %&777r   c           	         |j         \  }}}|sdS |j        |         }	|	|v rdS |	|v rt          d| d|j         d          ||vrt	          |          ||<   |                    |	           |	j        s4|t          j        |           vr|	j	        D ]}t          | |||||           |                    |	           |                    |	           |                    |	           dS )z"Recursive helper for `_build_map`.NzTensor z from operation 'z' is part of a cycle.)r   rs   r!   r   rd   r   rQ   r   r   rS   r   removerV   )
r(   tensorr   r   r   ry   rP   ro   _r\   s
             r   r   r   h  s]    			 #J/D ~    f  y~   
 
 	
 )))'*+<'='=)$ $= 	V4<+?+???( 	 	F!)!    tT"""$$T*****r   )r   	keras.srcr   keras.src.api_exportr   keras.src.backendr   keras.src.backend.configr   keras.src.ops.operationr   r	   rp   r"   r}   r   r   r   r   <module>r      s             - - - - - - ) ) ) ) ) ) , , , , , , - - - - - - w w w w wy w w  wt2 2 2vJ vJ vJr#8 #8 #8L1+ 1+ 1+ 1+ 1+r   