
    ijjJ                         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	 d dl
mZ  ed       G d	 d
e             Zd Zd Zd Zd Zy)    N)tree)keras_exportKerasTensor)backend)is_nnx_enabled)	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	 Zd
 Zd Zd df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 }	| j%                  d gt'        | j                        z  |	       t)               r| j+                          y y )N)name
tensorflow_self_setattr_trackingTFc                     | S N xs    k/var/www/html/emotional.easysim.app/public_html/venv/lib/python3.12/site-packages/keras/src/ops/function.py<lambda>z#Function.__init__.<locals>.<lambda>:   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=c                 Z    d gt        t        j                  | j                              z  S r   )lenr   flattenoutput)opargskwargss      r   empty_op_outputsz+Function.__init__.<locals>.empty_op_outputsW   s!    6CRYY 7888r   )call_fn)super__init__r   getattrr   r   map_structure_inputs_struct_outputs_structr   _inputs_outputs
ValueError	map_graph_nodes_nodes_by_depth_operations_operations_by_depth_run_through_graphr   r   _setup_nnx_op_mapping)selfinputsoutputsr   r   nodesnodes_by_depth
operationsoperations_by_depthr    	__class__s             r   r#   zFunction.__init__.   s   d#9$
 &-.&" +0D'"00fE#11+wG||F+W-||  "")% 
 }}  "")%  9$*@D'CLLL$--D
@
,? -%$7!	9 	FS&&0@ 	  	

 &&( r   c                      | j                   d d  S r   )r.   r2   s    r   r7   zFunction.operationsb   s    ""r   c                     | j                   S )z1Flat list of the symbolic inputs of the Function.)r(   r;   s    r   r3   zFunction.inputsf   s     ||r   c                     | j                   S )z2Flat list of the symbolic outputs of the Function.)r)   r;   s    r   r4   zFunction.outputsk   s     }}r   c                     i | _         | j                  dd | _        | j                  D ]  }|| j                   t        |      <    y)zSetup operation mapping for NNXN)_nnx_op_mappingr.   nnx_operationsid)r2   	operations     r   r1   zFunction._setup_nnx_op_mappingp   sJ      " #..q1)) 	<I2;D  I/	<r   c                     |j                   }t        | d      r0t        |      t        | di       v r| j                  t        |         S |S )z;Get the operation for a node, using NNX mapping if enabled.r?   )rB   hasattrrA   r$   r?   )r2   noderB   s      r   _get_operation_for_nodez Function._get_operation_for_node{   sN    NN	4*+9#RB
 1
 ''966r   c                 2   | j                  |       d}t        t        j                  |      | j                        D ]"  \  }}|j
                  |j
                  k7  s d} n |r!t        j                  d | j                        S | j                  |d       S )NTFc                 D    t        | j                  | j                        S )N)shapedtype)r   rI   rJ   r   s    r   r   z.Function.compute_output_spec.<locals>.<lambda>   s    +AGG177C r   c                     | j                   S r   )compute_output_specr   s    r   r   z.Function.compute_output_spec.<locals>.<lambda>   s    B,B,B r   )operation_fn)	_assert_input_compatibilityzipr   r   r(   rI   r%   r'   r0   )r2   r3   shortcutr   x_refs        r   rL   zFunction.compute_output_spec   s    ((0 DLL0$,,? 	HAuww%++% 	 %%C$$  &&!B ' 
 	
r   c                 &   t        j                  d |      }t        t        j                  |      | j                        D ]'  \  }}|j
                  |_        |j                  |_        ) | j                  |      }t        j                  d |      S )Nc                     t        |       S )NrI   r   r   s    r   r   z/Function.compute_output_shape.<locals>.<lambda>   s    k* r   c                     | j                   S r   rU   r   s    r   r   z/Function.compute_output_shape.<locals>.<lambda>   s
    AGG r   )r   map_shape_structurerP   r   r(   rJ   _dtypesparse_sparserL   r%   )r2   input_shapeinput_shape_structr   rR   output_specs         r   compute_output_shapezFunction.compute_output_shape   s     "55*K

 DLL);<dllK 	%HAu{{AHAI	% ../AB!!"3[AAr   c                 F    | j                  |       | j                  |      S )z'Computes output tensors for new inputs.)rO   r0   )r2   r3   s     r   callzFunction.call   s!    ((0&&v..r   c                     | S r   r   rM   s    r   r   zFunction.<lambda>   s    b r   c                 6   t        j                  |      }i t        | j                  |      D ]  \  }}|t	        |      <    | j
                  }t        |j                               }|j                  d       |D ]  }||   }	|	D ]  }
|
j                  r|
j                  rt        fd|
j                  D              r;|
j                  j                        \  }}| ||
j                        } ||g|i |}n!| j                  |
      } ||      } ||i |}t        |
j                   t        j                  |            D ]  \  }}|t	        |      <      g }t#        | j                         D ]{  \  }}t	        |      vrLt        j$                  | j&                        |   d   }dj)                  d |D              }t+        d| d      |j-                  t	        |                } t        j.                  | j&                  |      S )	zExecute the graph.

        At each node we compute outputs via
        `operation_fn(node.operation)(*args, **kwargs)`.
        Treversec              3   8   K   | ]  }t        |      v  y wr   rA   ).0r   tensor_dicts     r   	<genexpr>z.Function._run_through_graph.<locals>.<genexpr>   s     LAr!uK/Ls   r   .c              3   2   K   | ]  }t        |        y wr   )str)rg   ps     r   ri   z.Function._run_through_graph.<locals>.<genexpr>   s     51A5s   zOutput with path `z` is not connected to `inputs`)r   r   rP   r3   rA   r-   listkeyssortrB   is_inputanyinput_tensors	argumentsfill_inrF   r4   	enumerateflatten_with_pathr'   joinr*   appendpack_sequence_as)r2   r3   rN   r!   r   yr6   
depth_keysdepthr5   rE   r   r   r   r4   rB   output_tensorsipathrh   s                      @r   r0   zFunction._run_through_graph   s    f% V, 	#DAq!"K1	# --.--/0
% 	+E"5)E +~~L9K9KLL#~~55kBf&%dnn5B%b:4:6:G !% < <T BI%i0B $1&1G  dll7.CD +DAq)*K1&+'+	+0 dll+ 	6DAq!uK'--d.B.BCAFqIxx555 (.LM  !!+be"45	6 $$T%9%9>JJr   c                    	 t        j                  || j                         t	        t        j
                  |      | j                        D ]  \  }}t        |j                        t        |j                        k7  rIt        | j                  j                   d|j                   d|j                   d|j                   d      t	        |j                  |j                        D ]Y  \  }}|	|||k7  st        | j                  j                   d|j                   d|j                   d|j                   d        y # t        $ r t        d| j                   d|       w xY w)NzOFunction 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 rj   )r   assert_same_structurer&   r*   rP   r   r(   r   rI   r9   __name__r   )r2   r3   r   rR   dimref_dims         r   rO   z$Function._assert_input_compatibility   sr   	&&vt/B/BC DLL0$,,? 	HAu177|s5;;// ~~../ 077<zzl C&&+kk] 333477)1>  !$AGGU[[ 9 W&3?g~(#~~667 8??Dzzl K..3kk] ;;;<77)1F 	  	--1-@-@,A B--3H6 	s    E %E)r   )r   
__module____qualname____doc__r#   propertyr7   r3   r4   r1   rF   rL   r^   r`   r0   rO   __classcell__)r9   s   @r   r   r      sx    B2)h # #    	<
,B/ $1$5Knr   r   c                 "    t        |        d| S )Nz_ib-rf   )r   
node_indexs     r   make_node_keyr      s    fXT*&&r   c                    t        | |      \  }t        |      }|D ch c];  }t        |j                  |j                  j                  j                  |            = }}i }i }t        |      D ]  }|j                  |d      }|j                  |j                  d      }	t        ||	      }|||j                  <   |||<   |j                  D ]+  }
|
|vr|j                  |
d      }	t        |dz   |	      ||
<   -  | D ]u  }|j                  d   }|s||vs|j                  j                  }|j                  |   }|j                  sLd||<   d|<   d||<   |j                  t        ||             w t        j                   t"              }|j%                         D ]  \  }}||   j'                  |        t        j                   t"              }|j%                         D ]  \  }}||   j'                  |        t#        |j)                               }|j+                  d       g }|D ]-  }||   }|j+                  fd       |j-                  |       / t#        |j)                               }|j+                  d       t               }| D ]  }|j                  |        g }|D ]  }||   D ]  }t/        j0                  |j2                        D ]K  }||vr |j                  }t5        d| d	| d
|       |j'                  |j                  j6                         M t/        j0                  |j8                        D ]  }|j                  |          |D cg c]  }|j6                   }}|D ]7  }|j;                  |      dk7  st5        d| d|j;                  |       d       ||||fS c c}w c c}w )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.
    r      Trc   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: z
The name "z
" is used z: times in the model. All operation names should be unique.)
_build_mapsetr   rB   _inbound_nodesindexreversed
setdefaultgetmaxparent_nodes_keras_historyr   rq   addcollectionsdefaultdictrn   itemsry   ro   rp   extendr   r   rs   r*   r   r4   count)r3   r4   nodes_in_decreasing_depthnodes_in_graphrE   network_nodesnodes_depthsoperations_depthsr}   previous_depthnode_depinput_tinput_operationr   r6   r8   rB   r|   r7   operations_for_depthcomputable_tensorsr   operations_with_complete_input	all_namesr   r   s                            @r   r+   r+     s>   " 4>fg3N0023N . 	dnndnn&C&C&I&I$&OPM 
 L23 D''a0 +..t~~qA
 E>*,1$..)"T )) 	DH~-)--h:N%(N%CL"		D%D6  N!0036GG //::J"11*=D }}56!/257!/2%&T"!!-"LMN !,,T2N#))+ +eu$$T*+ &11$7-335 5	5E")))45 )..01JOODO! J 0259 	!!&D!E./0 n))+,JOODO!
  "q!" &(" *"5) 	*D\\$"4"45 	K.. $I$""#OI; ?**H)IK  /55dnn6I6IJ	K \\$,,/ *"&&q)*	**$ 2<<I<I< ??4 A%TF*Y__T-B,C DL L  .*6III[L =s   A N>'O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)r3   r4   finished_nodesnodes_in_progressr   r   r   s          r   r   r     s_    , UN ",,w' 
%	

 %&777r   c           	         |j                   \  }}}|sy|j                  |   }	|	|v ryt        j                  |       }
|	j                  s||
v r|j                  |	       y|	|v rt        d| d|j                   d      ||vrt        |      ||<   |j                  |	       |	j                  s!|	j                  D ]  }t        | |||||        |j                  |	       |j                  |	       |j                  |	       y)z"Recursive helper for `_build_map`.NzTensor z from operation 'z' is part of a cycle.)r   r   r   r   rq   r   r*   r   r   rs   r   removery   )r3   tensorr   r   r   r   rB   r   _rE   flat_inputsinput_tensors               r   r   r     s0    			##J/D ~
 ,,v&K==V{24    fX.y~~.> ? 
 	
 ))'*+<'=)$ $== .. 	L!)!	 tT"$$T*r   )r   	keras.srcr   keras.src.api_exportr   keras.src.backendr   keras.src.backend.configr   r   keras.src.ops.operationr	   r   r   r+   r   r   r   r   r   <module>r      sW      - ) , 3 - qy q  qh'@JF#8L9+r   