
    BVh                     &   d Z ddlZddlmZmZmZmZ 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 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( 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j^                  j`                  ej^                  jb                  ej^                  jd                  e jf                  e jh                  gZ5 G d  d!e6      Z7	 	 d3d"Z8 e.d#g $       G d% d&ejr                               Z:e)jv                  d'e:d(eejr                     fd)       Z<	 	 	 	 	 	 	 	 d4d*Z=d+ Z>d, Z?d- Z@d. ZAd/ ZBd5d0ZCd1 ZDd2 ZEy)6z$FuncGraph and related functionality.    N)AnyCallableContextManagerHashable)
trace_type)capture_container)context)execute)composite_tensor_utils)auto_control_deps)composite_tensor)constant_op)dtypes)errors)indexed_slices)ops)tensor)	type_spec)	array_ops)resource_variable_ops)tensor_array_ops)variable_scope)save_context)core)compat)nest)object_identity)tf_contextlib)tf_decorator)
tf_inspect)variable_utils)	tf_exportc                       e Zd ZdZy)UnknownArgumentz5Signifies an argument which is not currently handled.N)__name__
__module____qualname____doc__     V/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/framework/func_graph.pyr$   r$   <   s    =r*   r$   c                 F   fd}t        j                  |       }|rHt        |      t        |       k7  rt        d|z        |D cg c]  \  }}||d      f|dd z   |f }}}|D cg c]  \  }} |||       }}}t        j                  | |      S c c}}w c c}}w )a?  Convert a potentially nested structure to a signature.

  Args:
    structure: Structure to convert, where top level collection is a list or a
      tuple.
    arg_names: Optional list of arguments that has equal number of elements as
      `structure` and is used for naming corresponding TensorSpecs.
    signature_context: TraceType InternalTracingContext to generate alias_ids
      for mutable objects, like ResourceVariables.

  Returns:
    Identical structure that has TensorSpec objects instead of Tensors and
    UnknownArgument instead of any unsupported types.
  c                    t        | t        j                        rd}	 t        j                  | j
                  j                  d            }|r|r||d   k7  r|}n+t        j                  dj                  d |D                    }t        j                  | j                  | j                  |      S t        | t        j                        rt!        j"                  |       S t        | t$        j&                        r| j(                  S t        | t*        t,        t.        t0        t3        d      t4        j6                  t        j                  t8        j:                  f      r| S t=               S # t        t        f$ r Y 0w xY w)zCA representation for this argument, for converting into signatures.N_user_specified_namer   _c              3   2   K   | ]  }t        |        y wN)str).0ps     r+   	<genexpr>zEconvert_structure_to_signature.<locals>.encode_arg.<locals>.<genexpr>`   s     5Kc!f5Ks   )
isinstance
tensor_libTensorr   as_stropget_attr
ValueErrorAttributeErrorsanitize_spec_namejoin
TensorSpecshapedtyper   ResourceVariabler   
from_valuer   CompositeTensor
_type_specintfloatboolr2   typer   DTyper   TypeSpecr$   )argpathuser_specified_namenamesignature_contexts       r+   
encode_argz2convert_structure_to_signature.<locals>.encode_argQ   s9   #z(() $mmFFOO235
 
%*=a*H #,,SXX5Kd5K-KL""399cii>>#,==>""3(9::#'778^^#T
	 	 j5 .) s   .E+ +E>=E>z6Passed in arg_names don't match actual signature (%s).r      N)r   flatten_with_tuple_pathslenr<   pack_sequence_as)	structure	arg_namesrQ   rR   	flattenedrN   rM   mappeds     `     r+   convert_structure_to_signaturer[   @   s    "!J ++I6)
9~Y'
BY
NP P
 BK4=D#)DG
	ab	)3/I  4==idCJsD!=&=			y&	11 >s   B+Bz__internal__.FuncGraph)v1c                        e Zd ZdZ	 	 	 	 d' fd	Zd Zd Z	 	 	 d(dZ fdZ fdZ	e
d        Zej                  d	        Ze
d
        Ze
d        Ze
d        Ze
d        Zej                  d        Z	 	 	 	 	 d)dZ	 	 	 	 	 	 d* fd	Zd+dZd Zd Zdedeg ef   ddfdZe
d        Zd Zd Z	 d,dZe
d        Ze
d        Ze
d        Z e
d         Z!e
d!        Z"e
d"        Z#d# Z$e
d$        Z%e
d%        Z&d& Z' xZ(S )-	FuncGrapha  Graph representing a function body.

  Attributes:
    name: The name of the function.
    inputs: Placeholder tensors representing the inputs to this function. The
      tensors are in this FuncGraph. This represents "regular" inputs as well as
      captured inputs (i.e. the values of self.captures), with the regular
      inputs coming first.
    outputs: Tensors that will be returned by this function. The tensors are in
      this FuncGraph.
    control_outputs: Operations that must be executed before the function
      represented by this graph can be said to have been executed.
    structured_input_signature: A tuple of (args, kwargs), which are both
      possibly-nested python objects that were received by this function. Note
      that these structures might contain Python `None`s.
    structured_outputs: A possibly-nested python object which will be returned
      by this function. The Tensors in this structure are the same as those of
      self.outputs. Note that this structure might contain Python `None`s.
    variables: Variables that should be watched during function execution.
    outer_graph: The graph this function is defined in. May be another FuncGraph
      or the global default Graph.
    captures: Maps external tensor -> internal tensor (i.e. input placeholder).
      The entries are in the order they were captured.
    seed: The graph-level random seed.
    capture_by_value: If True, the func graph will capture Variables by value
      instead of reference.
  c                    t         	|           || _        g | _        g | _        g | _        || _        || _        t        j                         | _
        g | _        t        j                         | _        d| _        t        j                          | _        t%        j&                         }t)        j*                  |      | _        |j.                  r|j0                  }|j.                  r|| _        d| _        ||| _        nI| j0                  6t9        | j0                  t:              r| j0                  j6                  | _        nd| _        d| _        | j0                  }t?        j@                         r!t?        jB                         | _"        d| _#        n7|jD                  | _"        d| _#        |jH                  jK                         | _$        |f|jM                         D ])  }|tN        vs|jQ                  |      | jR                  |<   + tN        D ]   }|jU                  |      | jR                  |<   " n|| _)        d| _+        tY               | _-        d| _.        y)a  Construct a new FuncGraph.

    The graph will inherit its graph key, collections, seed, and distribution
    strategy stack from the current context or graph.

    Args:
      name: the name of the function.
      collections: a dictionary of collections this FuncGraph should start with.
        If not specified (None), the FuncGraph will read (but not write to) the
        outer graph's collections that are not allowlisted, and both read and
        write to the outer graph's collections that are allowlisted. The current
        allowlisted collections are the global variables, the local variables,
        and the trainable variables. Defaults to None.
      capture_by_value: An optional boolean. If True, the func graph will
        capture Variables by value instead of reference. By default inherit from
        outer graphs, and failing that will default to False.
      structured_input_signature: Optional. The structured input signature to
        use for initializing the FuncGraph. See the docstring for FuncGraph for
        more information.
      structured_outputs: Optional. The structured outputs to use for
        initializing the FuncGraph. See the docstring for FuncGraph for more
        information.
    FNT)/super__init__rP   inputsoutputscontrol_outputsstructured_input_signaturestructured_outputsr   ObjectIdentitySet_resource_tensor_inputs_weak_variablesObjectIdentityWeakSet_watched_variablesis_control_flow_graphr   FunctionCaptures_function_capturesr   get_default_graphweakrefref_weak_outer_graphbuilding_functionouter_graph_fallback_outer_graph_output_namescapture_by_valuer6   r^   _building_functionr	   executing_eagerlyglobal_seedseed
_seed_used_colocation_stackcopyget_all_collection_keysALLOWLIST_COLLECTIONSget_collection_collectionsget_collection_ref	_saveableset_saving_errors_scope_exit_callbacks)
selfrP   collectionsrw   re   rf   rt   graphcollection_name	__class__s
            r+   ra   zFuncGraph.__init__   s   : 
GDIDKDLD&@D#0D#2#D#D#FD D-CCED!&D/@@BD'')K$[[5D

'
'++k 
'
' "-D D#.d				%*T5E5E5>+@"..??d#d"DE  "%%'di do**dido  %66;;=d"::< /"77/4/C/C0$

O
, 3 /-2-E-E./* &d
 DN%D "&Dr*   c                 :    d| j                   dt        |       dS )NzFuncGraph(name=z, id=))rP   idr   s    r+   __str__zFuncGraph.__str__  s    *.))RX>>r*   c                    t        |t        j                        r|j                  | j                  v ry| Mt        | t
              r<| j                  j                  |       | j                  } | t        | t
              r:yyyy)z;Marks the variable v as accessed while building this graph.N)	r6   r   rC   handlerh   r^   rk   addrt   )r   vs     r+   watch_variablezFuncGraph.watch_variable
  sr     	1+<<=	D000

z$	:
!!!$d 
z$	:
:
r*   c                    
t               | j                  j                  vrt        j                  d      }t        j
                  |      |&t        j                  |       }j                  |      }fd}|_        | j                  j                  ||d       | j                  j                     S )aG	  Returns a placeholder which at call time has the value closure().

    The `tf.function` supports the notion of captures, that is, it allows Python
    functions to have closure variables, which bind over some value outside the
    function. However, this name binding is "early binding" performed before the
    program is run, i.e.,
    ```
    @tf.function
    def f():
      return x

    x = tf.constant(1)
    f()  # returns 1

    x = tf.constant(2)
    f()  # still returns 1!
    ```
    while in Python, name binding is performed as the program is running.
    ```
    def f():
      return x

    x = 1
    f()  # returns 1

    x = 2
    f()  # returns 2
    ```
    `capture_call_time_value` allows tf.function to mimic late binding as a
    Python function does, by passing in a `closure` callable argument to be
    executed when the tf.function is invoked eagerly.  E.g.
    ```
    @tf.function
    def f():
      return ops.get_default_graph.capture_call_time_value(lambda: x)

    x = tf.constant(1)
    f()  # returns 1

    x = tf.constant(2)
    f()  # returns 2
    ```
    Note that a `capture_call_time_value` function itself does not work well in
    the saving process (since the tf.function in which it's called is not
    invoked eagerly) unless passed a `default_value` argument. At saving time,
    the `default_value` argument is returned instead.

    Args:
      closure: function which takes no arguments, to be evaluated at function
        call time, returning a nest of tensors compatible with `spec`.
      spec: nest of TypeSpec for the value to capture.
      key: optional. If not None, multiple calls to lazy_capture with the same
        key in the same graph will return the same placeholder, and the first
        closure will be used at function call time.
      default_value: optional value to return in environments that cannot safely
        evaluate closure.
      placeholder: optional. If not None, the graph will take the passed-in
        `placeholder` as the internal capture instead of creating a new one.
        This is useful when loading from a SavedModel.

    Returns:
      Nest of placeholders which, at function call time, will be fed with the
      result of calling closure().

    Raises:
      ValueError: at function call time, if the return value of closure() is
       not compatible with `spec`.
    Tc                     t        j                         rS t        j                         sZt	        j
                         } t        | t              sJ d       | j                         5  | j                        }d d d        n        }j                  t        j                        }j                  |      S # 1 sw Y   :xY w)Nz/This API should only be used in TF2 enviroment.)keydefault_value)r   in_save_contextr	   ry   r   ro   r6   r^   
as_defaultcapture_call_time_valuecastr   InternalCastContext
to_tensors)r   ret_nestclosurer   r   specs     r+   wrapped_closurez:FuncGraph.capture_call_time_value.<locals>.wrapped_closurei  s     '')m.G
 ((*'')% LKL  ! E443m 5 EHE E Y(99Xz'E'EFx((E Es   )C  C	)r   externalinternal	tracetype	is_by_ref)
objectrn   by_ref_internalr   InternalTracingContextrD   InternalPlaceholderContextplaceholder_valueoutput_specadd_or_replace)	r   r   r   r   r   placeholder	trace_ctxplaceholder_ctxr   s	    ````    r+   r   z!FuncGraph.capture_call_time_value  s    T {Hc
$))99933D9i""43d		$??E,,_=)@ %)o!
,," -  ""22377r*   c                    |t         |   |      S g }|D ]  }t        |t        j                        st        |d      rt        |d      r|j                  }t        j                  |      }||}|5t        |dd      | ur&| j                  j                  j                  |       |j                  |        t         |   |      S )a
  Handles control dependencies.

    FuncGraph wraps Graph's control_dependencies logic by first filtering out
    any external tensors / operations and storing them in the graph's
    control_captures member. Any consumers of this function graph must then
    decide how to handle the control captures.

    Args:
      control_inputs: A list of `Operation` or `Tensor` objects which must be
        executed or computed before running the operations defined in the
        context.  Can also be `None` to clear the control dependencies.

    Returns:
     A context manager that specifies control dependencies for all
     operations constructed within the context.

    Raises:
      TypeError: If `control_inputs` is not a list of `Operation` or
        `Tensor` objects.
    N_handler:   r   )r`   control_dependenciesr6   r   IndexedSliceshasattrr:   r   _as_graph_elementgetattrrn   controlr   append)r   control_inputsfiltered_control_inputscgraph_elementr   s        r+   r   zFuncGraph.control_dependencies  s    * W).99  6
Q44
51i WQ%5DD++A.m				"w}g/3(5<@(A''++M:&&}56 7'(?@@r*   c                 8    t         |          }t        | |      S r1   )r`   r   _func_graph_as_default_inner_cm)r   outer_cmr   s     r+   r   zFuncGraph.as_default  s    w!#H*4::r*   c                 B    | j                         }|| j                  S |S )a  The Graph this FuncGraph is nested in.

    Functions may capture Tensors from graphs they are nested in (transitive).

    Returns:
      A Graph object. Initially set to the current default graph when the
      FuncGraph was created. If the previous `outer_graph` was deleted because
      the function that owns it was deleted, `outer_graph` is reset to the
      outermost default graph active when the FuncGraph was created. This
      FuncGraph won't have captured anything from the new `outer_graph` (and
      likely not from the previous setting, since that would have created a
      strong reference), but it is returned so that FuncGraphs always have a
      parent.
    )rr   ru   )r   currents     r+   rt   zFuncGraph.outer_graph  s(      $$&G'''Nr*   c                 8    t        j                  |      | _        y)z(Sets `outer_graph` to `new_outer_graph`.N)rp   rq   rr   )r   new_outer_graphs     r+   rt   zFuncGraph.outer_graph  s     %[[9Dr*   c                 T    | j                   D cg c]  }|j                   c}S c c}w r1   )rc   rB   r   ts     r+   output_typeszFuncGraph.output_types      !\\*AGG***   %c                 T    | j                   D cg c]  }|j                   c}S c c}w r1   )rc   rA   r   s     r+   output_shapeszFuncGraph.output_shapes  r   r   c                 :    t        d | j                  D              S )a   A sequence of trainable variables accessed by this FuncGraph.

    Note that functions keep only weak references to variables. Calling the
    function after a variable it accesses has been deleted is an error.

    Returns:
      Sequence of trainable variables for this func graph.
    c              3   :   K   | ]  }|j                   s|  y wr1   )	trainable)r3   r   s     r+   r5   z0FuncGraph.trainable_variables.<locals>.<genexpr>  s     :qakk:s   )tuple	variablesr   s    r+   trainable_variableszFuncGraph.trainable_variables  s     :DNN:::r*   c                 F    d t        fd| j                  D              S )a  A sequence of variables accessed by this FuncGraph.

    Note that functions keep only weak references to variables. Calling the
    function after a variable it accesses has been deleted is an error.

    Returns:
      Sequence of variables for this func graph.
    c                 .     |        }|t        d      |S )Na  Called a function referencing variables which have been deleted. This likely means that function-local variables were created and not referenced elsewhere in the program. This is generally a mistake; consider storing variables in an object attribute on first call.)AssertionError)weak_vr   s     r+   derefz"FuncGraph.variables.<locals>.deref  s'    
(a	
 	 hr*   c              3   .   K   | ]  } |        y wr1   r)   )r3   r   r   s     r+   r5   z&FuncGraph.variables.<locals>.<genexpr>  s     8aq8s   )r   ri   )r   r   s    @r+   r   zFuncGraph.variables  s!    	 84#7#7888r*   c                 ^    |D cg c]  }t        j                  |       c}| _        y c c}w r1   )rp   rq   ri   )r   var_listr   s      r+   r   zFuncGraph.variables  s     4<=qGKKN=D=s   *c	                 p   t        d | j                  D              }	|D 
cg c]  }
|	j                  t        |
      |
       }}
t	        j
                         5  t        j                         r[dt        |d   j                        f}t        j                  t        j                  |      d||t        j                               \  }n9t	        j                         j                  ||||||||      }|j                  d   }d d d        | j!                        }|j"                  S c c}
w # 1 sw Y   +xY w)Nc              3   <   K   | ]  \  }}t        |      |f  y wr1   )r   )r3   kr   s      r+   r5   z.FuncGraph._capture_by_value.<locals>.<genexpr>  s     A41aRUAJAs   rB   rS   r   )dictcapturesgetr   r   
init_scoper	   ry   rG   rJ   r
   r   as_bytesro   _create_op_internalrc   capturer:   )r   op_typerb   r   input_typesrP   attrsop_defcompute_devicereverse_capturesr   uncaptured_inputs	attr_listvaluer:   captured_values                   r+   _capture_by_valuezFuncGraph._capture_by_value	  s    A4==AAAGHA)--beQ7HH		 
		"	"	$c%."5"567	OOG$a):IOO ""$88&T5N$ 

1
 \\%(N I
 
s   "D'B)D,,D5c	           
         | j                   r|dv r| j                  ||||||||      S |dk(  rY|d   j                  j                  dk(  r=|d   j                  j	                  d      |d   j
                  k(  r|d   j                  S t        j                         j                  }	g }
|D ]C  }|	t        |	d      r|	j                  |      }| j                  |      }|
j                  |       E t        | 9  ||
||||||      S )a3  Like Graph.create_op, except handles external input tensors.

    This overload adds functionality to create_op to "capture" any external
    input tensors, i.e. tensors from the eager context or outer function graphs
    if this is a nested function. See `capture` for more information.

    Args:
      op_type: The `Operation` type to create. This corresponds to the
        `OpDef.name` field for the proto that defines the operation.
      inputs: A list of `Tensor` objects that will be inputs to the `Operation`.
      dtypes: (Optional) A list of `DType` objects that will be the types of the
        tensors that the operation produces.
      input_types: (Optional.) A list of `DType`s that will be the types of the
        tensors that the operation consumes. By default, uses the base `DType`
        of each input in `inputs`. Operations that expect reference-typed inputs
        must specify `input_types` explicitly.
      name: (Optional.) A string name for the operation. If not specified, a
        name is generated based on `op_type`.
      attrs: (Optional.) A dictionary where the key is the attribute name (a
        string) and the value is the respective `attr` attribute of the
        `NodeDef` proto that will represent the operation (an `AttrValue`
        proto).
      op_def: (Optional.) The `OpDef` proto that describes the `op_type` that
        the operation will have.
      compute_device: (Optional.) If True, device functions will be executed to
        compute the device property of the Operation.

    Returns:
      An `Operation` object.
    )ReadVariableOpResourceGatherEnterr   
frame_nameAddValue)rw   r   r:   rJ   r;   sr   ro   _control_flow_contextr   r   r   r   r`   r   )r   r   rb   r   r   rP   r   r   r   ctxtcaptured_inputsinpr   s               r+   r   zFuncGraph._create_op_internal$  s   P  - " ##GVV[$$)6>C C 'fQill//7:			|	,l0C0E0E	Eay||   "88DO "		gdJ7mmC LLcS!" 7&&+tUF r*   c                 <    | j                   j                  | ||      S r1   )rn   rw   )r   r   rP   rA   s       r+   r   zFuncGraph.capturej  s    ""33D&$GGr*   c                 B   |j                   }|t        |t              r|| u r	 |j                  j                  }g }t	        j
                  |j                               D ]D  }|j                  |j                  d      D cg c]  }|j                         sd|  c}       F dj                  |      }t        j                  |d|d| d|d|  d|j                    d	      |j                  }|t        |t              ry y y y c c}w # t        $ r d}Y fw xY w)
N
z  z	<unknown>z is out of scope and cannot be used here. Use return values, explicit Python locals or TensorFlow collections to access it.
Please see https://www.tensorflow.org/guide/function#all_outputs_of_a_tffunction_must_be_return_values for more information.

z was defined here:
z

The tensor z cannot be accessed from z, because it was defined in z, which is out of scope.)r   r6   r^   r:   	tracebackformat_listget_user_framesextendsplitstripr?   r=   r   InaccessibleTensorErrorrt   )r   r   inner_graphtbtensor_traceback_listframelinetensor_tracebacks           r+   _validate_in_scopezFuncGraph._validate_in_scopem  sG   ,,K

!ji&H				>yy""" #%
 ,,R-?-?-AB Me!(().T):Kdjjl2dVKMM "YY'<=
 ,,j (
 j,-=,> ? #<TF C!!'.FHI 	I  ++k/ 
!ji&H
!&H
! L  	)(
	)s   D  D
D
DDc                 <    | j                   j                  | ||      S r1   )rn   _create_placeholder_helper)r   r   rP   s      r+   _capture_helperzFuncGraph._capture_helper  s"    ""==fd r*   
identifierfuncreturn.c                     t        j                         r        S fd}| j                  j                  | ||      }|S )a  Implement capturing side input by reference for tf.function.

    Note that this API will only register the capture in the func_graph where
    it is called. In the case of nested graph, like nested tf.function or
    tf.while, the outer graph is not aware of this capture in the inner graph.
    Thus, the outer tf.function will not retrace when the by-ref capture
    changes. It's the user's responsibility to call this API in the outer
    func_graph as well if proper retracing is needed.

    For example:

    ```
    x = 1

    # Correct usage
    @tf.function
    def f_1():
      graph = tf.compat.v1.get_default_graph()
      # Capture the same x for the outer tf.function
      graph._experimental_capture_side_input_by_ref("x", lambda: x)

      @tf.function
      def g():
        graph = tf.compat.v1.get_default_graph()
        cap_x = graph._experimental_capture_side_input_by_ref("x", lambda: x)
        return cap_x + 1

      return g()

    # Incorrect usage
    @tf.function
    def f_2():

      @tf.function
      def g():
        graph = tf.compat.v1.get_default_graph()
        cap_x = graph._experimental_capture_side_input_by_ref("x", lambda: x)
        return cap_x + 1

      return g()

    assert f_1() == 2
    assert f_2() == 2
    x = 2
    assert f_1() == 3
    assert f_2() == 2  # This is incorrect
    ```

    Args:
      identifier: A hashable object as the key for the capture.
      func: A Python function that takes no arguments and returns the value of
        side input. The function is evaluated at function call time.

    Returns:
      A nested structure with the same structure as the side input. Tensors
        are replaced with placehoders, and non-tensors remain the same.

    c                              } t        | t        j                        s/t        | t        j                        st	        j
                  |       } | S r1   )r6   r   ValueSymbolr   constant)r   r  s    r+   maybe_convert_to_tensorzRFuncGraph._experimental_capture_side_input_by_ref.<locals>.maybe_convert_to_tensor  s:    fe

+z%/M$$U+lr*   )r	   ry   rn   _capture_by_ref)r   r  r  r  r   s     `  r+   '_experimental_capture_side_input_by_refz1FuncGraph._experimental_capture_side_input_by_ref  sD    x   "Vm ))99%z3Kr*   c                 .    | j                   j                  S )z?Order list of tuples containing external and internal captures.)rn   by_val_capture_tuplesr   s    r+   r   zFuncGraph.captures  s     ""888r*   c                     | j                   j                  t        |      ||d       | j                  j	                  |       y)zCapture a specific tensor and utilize the provided placeholder.

    Args:
      tensor: Tensor to captures.
      placeholder: Provided placeholder for the tensor.
    Fr   r   r   r   N)rn   r   r   rb   r   r   r   r   s      r+   add_capturezFuncGraph.add_capture  sA     	**vJ	 + 
 	KK{#r*   c                 T    | j                   j                  t        |      ||d       y)z!Replace already existing capture.Fr  N)rn   r   r   r   s      r+   replace_capturezFuncGraph.replace_capture  s+    **vJ	 + r*   c                     | j                   j                  t        |      d       | j                  ||t        |      ||       y)ar  Replaces existing capture `tensor` with a deferred capture `closure`.

    Caution: It is the caller's responsibility to make sure that, after calling
    this function, the TypeSpec of the `inputs` (i.e. internal placeholders) and
    the `_captured_inputs` (i.e. external captures) of a concrete function that
    wraps this function graph are still compatible. Thus user should pairing
    usage of this function with `ConcreteFunction.set_external_captures` to make
    sure the order still matches. For example,
    ```
    # concrete_fn._captured_inputs == [tensor1, tensor2, tensor3]
    # concrete_fn.inputs == [placeholder1, placeholder2, placeholder3]
    # replace external capture `tensor2` with a deferred_capture, i.e., a
    # closure, `closure2`
    concrete_fn.graph.replace_capture_with_deferred_capture(tensor2,
                                                            closure2,
                                                            placeholder2,
                                                            some_spec,
                                                            some_default)
    concrete_fn.set_external_captures([tensor1, closure2, tensor3])
    ```

    Args:
      tensor: Tensor already captured.
      closure: function which takes no arguments, to be evaluated at function
        call time, returning a nest of tensors compatible with `spec`.
      spec: nest of TypeSpec for the value to capture.
      placeholder: the internal placeholder corresponding to the captured
        `tensor`.
      default_value: optional value to use in environments that cannot safely
        evaluate closure.
    F)r   )r   r   r   N)rn   popr   r   )r   r   r   r   r   r   s         r+   %replace_capture_with_deferred_capturez/FuncGraph.replace_capture_with_deferred_capture  sH    J 	6
e<  vJ# ! !r*   c                 \    t        | j                  j                  j                               S )z+External tensors captured by this function.)listrn   by_val_externalvaluesr   s    r+   external_captureszFuncGraph.external_captures  $     ''77>>@AAr*   c                 \    t        | j                  j                  j                               S )z=Placeholders in this function corresponding captured tensors.)r(  rn   by_val_internalr*  r   s    r+   internal_captureszFuncGraph.internal_captures#  r,  r*   c                 \    t        | j                  j                  j                               S )zDOrdered nest of tensors whose placeholders will be fed at call time.)r(  rn   by_ref_externalr*  r   s    r+   deferred_external_capturesz$FuncGraph.deferred_external_captures(  r,  r*   c                 \    t        | j                  j                  j                               S )z<List of nest of placeholders which at call time will be fed.)r(  rn   r   r*  r   s    r+   deferred_internal_capturesz$FuncGraph.deferred_internal_captures-  r,  r*   c                     | j                   S )zFMap of python object ids of variables to variables which are captured.)r   r   s    r+   variable_captureszFuncGraph.variable_captures2       >>r*   c                     | j                   S r1   )rn   r   s    r+   function_captureszFuncGraph.function_captures7  s    """r*   c                 n    d| _         t        |t              r|g}| j                  j	                  |       y)a  Marks this FuncGraph as unsaveable.

    Any attempts to export this FuncGraph will raise an error with the specified
    message.

    Args:
      error_message: List or string containing the error message to be raised
        when saving this FuncGraph to SavedModel.
    FN)r   r6   r2   r   update)r   error_messages     r+   mark_as_unsaveablezFuncGraph.mark_as_unsaveable;  s0     DN-%$om}-r*   c                     | j                   S )z+Returns whether this FuncGraph is saveable.)r   r   s    r+   saveablezFuncGraph.saveableJ  r7  r*   c                     | j                   S )zAReturns set of errors preventing this FuncGraph from being saved.)r   r   s    r+   saving_errorszFuncGraph.saving_errorsO  s     r*   c                     t        |      st        dj                  |            | j                  t	        d      | j                  j                  |       y)z?Add a function to call when this graph exits the default scope.zfn is not callable: {}NzAttempting to add a scope exit callback, but the default graph is not the context scope graph.  Did you forget to call 'with graph.as_default(): ...'?)callable	TypeErrorformatr   RuntimeErrorr   )r   fns     r+   _add_scope_exit_callbackz"FuncGraph._add_scope_exit_callbackT  sT    B<.55b9::!!),- - 	%%b)r*   )NNNN)NNN)NNNNT)NNNNNTNNr1   ))r%   r&   r'   r(   ra   r   r   r   r   r   propertyrt   setterr   r   r   r   r   r   r   r  r  r   r   r   r  r   r!  r#  r&  r+  r/  r2  r4  r6  r9  r=  r?  rA  rH  __classcell__)r   s   @r+   r^   r^      s#   <   $*."&b&H?	 #',0*.{8z&AP;
  ( : : + + + + 	; 	; 9 9. > > > DLH,8G G4<RW4EGILGR 9 9$ ;?+!Z B B B B B B B B   # #.    	*r*   r^   
func_graphr   c              #     K   t        j                         }| j                  }t        |j                        | _        | j                  }t        j                         sTt        |j                        s | j                  r3t        j                         s|j                  j                         | _        | j                  }|j                  | _
        | j                  }|j                  | _        | j                  }g | _        |5 }	 | 	 | j                  D ]	  }	 |	         	 || _        || _        || _        || _
        || _        	 ddd       y# || _        || _        || _        || _
        || _        w xY w# 	 | j                  D ]	  }	 |	         	 || _        || _        || _        || _
        || _        w # || _        || _        || _        || _
        || _        w xY wxY w# 1 sw Y   yxY ww)zBContext manager for copying distribute.Strategy scope information.N)r   ro   _distribution_strategy_stackr(  _device_function_stackr	   ry   device_stack_has_callable#executing_eagerly_outside_functionsr~   _variable_creator_stack
_graph_keyr   )
rM  r   r   old_strategy_stackold_device_stackold_creator_stackold_graph_keyold_scope_exit_callbacksgrG  s
             r+   r   r   `  s     


!%!>>,0((-**)  66

#
#
% !=!=>//335(-(D(D(I(I(KJ% 88','D'D*$ ''-***'==%'*" .1.g.22 	B
$	 ,D
(2D
/,<
)->
* -
. . ,D
(2D
/,<
)->
* -
.22 	B
$	 ,D
(2D
/,<
)->
* -
	 ,D
(2D
/,<
)->
* -
. .s`   C>G+ GE5E #G	G+%E22G5G7F4$G4%G	GGG($G+c           	         !t        t        j                        sJ        t        | |	|
      t        t              sJ rt	        j
                         }nt        j                         }j                         5  |5 t        j                         }|j                  }|j                  d       ||}i }|rt        |||      \  }}n||}}t        j                  ||g      }|j!                  ||g      _        t%        j&                         _        j"                  D ];  }|j*                  t,        j.                  k(  s!j0                  j3                  |       = t        j4                         }t7        |||      t7        ||      f_        t;        j<                  |t;        j>                  |d      d      }t;        j<                  |t;        j>                  |d      d      }fd}tA        jB                        \  }} |i |}tE        jF                  |      }t;        jH                  ||d      }t;        j<                  |t;        j>                  |d      d      }t;        j<                  |t;        j>                  |d      d      }tK        |||||       |j                  |       g }tM        jN                  ||g      D ]  }t        |tP        jR                        rYjT                  jW                  tY        |jZ                        d      }t]        |      dk\  sJ |d	   }|d|j_                  |       vt        |t        j                        s|j_                  |        |j`                  z   t;        j>                  jb                  d      z   _        |_2        jf                  ji                  fd
t?        jd                        D               j(                  _5        ddd       ddd       r6jl                  ji                  |jn                         |jp                  _8        S # 1 sw Y   KxY w# 1 sw Y   OxY w)aG	  Returns a `FuncGraph` generated from `python_func`.

  Args:
    name: an identifier for the function.
    python_func: the Python function to trace.
    args: the positional args with which the Python function should be called;
      ignored if a signature is provided.
    kwargs: the keyword args with which the Python function should be called;
      ignored if a signature is provided.
    signature: a possibly nested sequence of `TensorSpecs` specifying the shapes
      and dtypes of the arguments. When a signature is provided, `args` and
      `kwargs` are ignored, and `python_func` is traced with Tensors conforming
      to `signature`. If `None`, the shapes and dtypes are inferred from the
      inputs.
    func_graph: Optional. An instance of FuncGraph. If provided, we will use
      this graph else a new one is built and returned.
    add_control_dependencies: If True, automatically adds control dependencies
      to ensure program order matches execution order and stateful ops always
      execute.
    arg_names: Optional list of argument names, used to give input placeholders
      recognizable names.
    op_return_value: Optional. A Tensor. If set and `python_func` returns
      Operations, those return values will be replaced with this value. If not
      set, returning an Operation triggers an error.
    collections: a dictionary of collections this FuncGraph should start with.
      If not specified (None), the FuncGraph will read (but not write to) the
      outer graph's collections that are not allowlisted, and both read and
      write to the outer graph's collections that are allowlisted. The current
      allowlisted collections are the global variables, the local variables, and
      the trainable variables. Defaults to None.
    capture_by_value: An optional boolean. If True, the func graph will capture
      Variables by value instead of reference. By default inherit from outer
      graphs, and failing that will default to False.
    create_placeholders: An optional boolean. If True, then func graph will
      create placeholders for the inputs as graph ops. If False, the input args
      and kwargs will be treated as the input placeholders.

  Returns:
    A FuncGraph.

  Raises:
    TypeError: If any of `python_func`'s return values is neither `None`, a
      `Tensor` or a `tf.experimental.ExtensionType`.
  N)r   rw   T)rQ   expand_compositesc           	         | yOt        | t        j                        r5t        j                  | g      5  t	        j
                        } ddd       n0t        | t        j                        s	 t        j                  |       } rj                  |       } | S # 1 sw Y   xY w# t        t        f$ r/ t        dt               dt        |       j                   d      w xY w)z'Converts a function output to a Tensor.NzTo be compatible with tf.function, Python functions must return zero or more Tensors or ExtensionTypes or None values; in compilation of z, found return value of type z), which is not a Tensor or ExtensionType.)r6   r   	Operationr   r   identityr   TensorArrayconvert_to_tensor_or_compositer<   rD  r2   rJ   r%   mark_as_return)xadd_control_dependenciesdeps_ctxop_return_valuepython_funcs    r+   convertz(func_graph_from_py_func.<locals>.convert  s    	
		$As}})E %%qc* 	2  1!	2 	2!-99:	 003! 
"##A&h	2 	2
 I& 	 ++.{+;*< =#Aw//0 1   	 s   B1B' B$'>C%F   rS   c              3   D   K   | ]  }|j                  |        y wr1   )r   )r3   rd  rM  s     r+   r5   z*func_graph_from_py_func.<locals>.<genexpr>N  s)      = 	1s    )9r6   r7   r8   r^   r   AutomaticControlDependenciesr   NullContextmanagerr   r   get_variable_scopeuse_resourceset_use_resource_create_placeholdersr   rD   r   rb   r   rj   rk   rB   r   resourcerh   r   r   r[   re   r   rV   flattenr   unwrapr!   convert_variables_to_tensorsmap_structurecheck_func_mutationr   flatten_with_variablesr   BaseResourceVariablern   r%  r   r   rU   r   r/  r4  rf   rc   r  r   rd   ops_which_must_runcollective_manager_ids_used)rP   rh  argskwargs	signaturerM  re  rX   rg  r   rw   create_placeholdersdeps_control_managercurrent_scopedefault_use_resource	func_argsfunc_kwargsinput_trace_typesrM   rQ   func_args_beforefunc_kwargs_beforeri  r/   original_funcfunc_outputsrb   r   resource_placeholderrf  s    `   `` `                    @r+   func_graph_from_py_funcr    s8   p  oz'8'89J?J9+8HJJ	J		**	*,IIK113 w9 4 w9"557M(55""4(df3D&)Li#Vi"--y+.FG)44i5MNJ %4$I$I$KJ!   4	foo	%**..s34 #99; 	'y4E	G&+<	>-?J) ,,Y$7  ..[D9 
0 $**;7A}	9[9L ">>|LL%%7L
 %%Y$7 I ''[D9 K (*<i#]4""#78F%<<i>I>K L 	C.CC	D //33BszzNEJ7|q   &qz'
*+c:,,-c 	---11T1K 	K  %1J! 667 
 &88Jow9 w9r %%&:&M&MN88 * 
}w9 w9 w9 w9s3   Q	CQH#Q1BQ	QQ	QQ(c                 B    t        d | j                         D              S )z2Checks whether a device stack contains a callable.c              3   F   K   | ]  }t        |j                          y wr1   )rC  _device_name_or_function)r3   r   s     r+   r5   z,device_stack_has_callable.<locals>.<genexpr>_  s#      ,
 t,,-,s   !)any	peek_objs)device_stacks    r+   rQ  rQ  ]  s%    	 ,((*, 
, ,r*   c                     	 t        j                  | |d       t        t        j                  | d      t        j                  |d            D ]  \  }}||us y y# t        $ r Y yw xY w)zGReturns true if n1 and n2 are different (using `is` to compare leaves).Tr\  F)r   assert_same_structurer<   ziprs  )n1n2arg1arg2s       r+   has_mutationr  d  su    r2> 
ll2.
ll2.0 jdD 4	 
 
 s   A 	A+*A+c           	         t        | |f||f      syt        |dt        |d|            }t        j                  |      }	  |j                  | i |j
                  } |j                  |i |j
                  }t        |      t        |      k(  sJ |D 
cg c]  }
t        ||
   ||
         r|
 }}
dj                  |      }t        | | d|       # t        $ r}	t        | | d      |	d}	~	ww xY wc c}
w )z9Checks that the arguments to a function are not modified.Nr'   r%   z should not modify its Python input arguments. Check if it modifies any lists or dicts passed as arguments. Modifying a copy is allowed.z, zv should not modify its Python input arguments. Modifying a copy is allowed. The following parameter(s) were modified: )
r  r   r    r~  bind	argumentsrD  r<   r   r?   )old_args
old_kwargsnew_args
new_kwargsr  	func_namer~  	old_bound	new_boundearg_namemodified_argschangess                r+   rw  rw  t  s:   	x,x.D	E
 dNGD*d,KL)""4()
;	7J7AAI	7J7AAI 
Y3y>	))	)(	i)9X+>	? -  IIm$'i[ ,<<C9F 	G G 
 ; +i[ !2 	34 :;;	;s    8C C7	C4C//C4c                     t        j                  | d      }|D cg c]*  }t        |t        j                        r|j
                  n|, c}S c c}w )zLike nest.flatten w/ expand_composites, but returns flow for TensorArrays.

  Args:
    sequence: A nested structure of Tensors, CompositeTensors, and TensorArrays.

  Returns:
    A list of tensors.
  Tr\  )r   rs  r6   r   ra  flow)sequenceflat_sequenceitems      r+   rs  rs    sO     ,,x4@-  

 d$4$@$@AdiitK
  
s   /Ac                 h   t        |      }t        j                  | d      }t        |      t        |      k7  rt	        d      t        t        |            D ]@  }t        ||   t        j                        s!t        j                  ||   ||         ||<   B t        j                  | |d      S )af  Like `nest.pack_sequence_as` but also builds TensorArrays from flows.

  Args:
    structure: The structure to pack into. May contain Tensors,
      CompositeTensors, or TensorArrays.
    flat_sequence: An iterable containing tensors.

  Returns:
    A nested structure.

  Raises:
    AssertionError if `structure` and `flat_sequence` are not compatible.
  Tr\  zMismatch in element count)old_tar  )r(  r   rs  rU   r<   ranger6   r   ra  build_ta_with_new_flowrV   )rW   r  flattened_structureis       r+   rV   rV     s     }%-Y$G	]!33
0
11]#$ @a%a(*:*F*FG)@@$Q'mA.>@mA@ 
		y-4	PPr*   c                    t        j                  d      }t        j                  t        |       |      }t        j                  ||      }|j	                         }t        j
                  t        j                         |      }|dgt        |j                        z  }g }t        ||j                        D ]8  \  }	}
|j                  |	       |
j                  |      }|j                  |       : i }t        t        |j                  j!                                D ],  \  }	}|j                  |	       |j                  |      }|||	<   . t        |      |fS )z;Create placeholders given positional args and keyword args.T)is_legacy_signatureN)r   r   rD   r   get_placeholder_mappingr   r   ro   rU   
componentsr  update_naming_scoper   r   sortedmappingitems)r|  r}  rX   rQ   arg_trace_typeskwarg_trace_typesplaceholder_mappingplaceholder_contextr  rP   trace_type_argr   r  trace_type_kwargs                 r+   rq  rq    sU    77 ))%+7HI/ ++F4EF)AAC"==	24 _7788I )!)_-G-GH "dN++D1 223FGK[!"
 + #V,=,E,E,K,K,M%N O $d++D1"445HIK#K$
 
y	;	&&r*   c                 b    | j                   j                          t        j                  |        y)ay  Removes reference cycles in `func_graph` FuncGraph.

  Helpful for making sure the garbage collector doesn't need to run when
  the FuncGraph goes out of scope, e.g. in tests using defun with
  @test_util.run_in_graph_and_eager_modes(assert_no_eager_garbage=True).

  Args:
    func_graph: A `FuncGraph` object to destroy. `func_graph` is unusable after
      this function.
  N)rn   clearr   dismantle_graph)rM  s    r+   dismantle_func_graphr    s$     %%'j!r*   c                     || _         y r1   )_name_stack)rM  
name_scopes     r+   override_func_graph_name_scoper    s
    %*r*   rI  )NNTNNNNTr1   )Fr(   r   typingr   r   r   r   rp   tensorflow.core.functionr    tensorflow.core.function.capturer   tensorflow.python.eagerr	   r
   ,tensorflow.python.eager.polymorphic_functionr   tensorflow.python.frameworkr   r   r   r   r   r   r   r   r7   r   tensorflow.python.opsr   r   r   r   tensorflow.python.saved_modelr   tensorflow.python.typesr   tensorflow.python.utilr   r   r   r   r   r    r!    tensorflow.python.util.tf_exportr"   	GraphKeysGLOBAL_VARIABLESLOCAL_VARIABLESTRAINABLE_VARIABLES_VARSTORE_KEY_VARSCOPESTORE_KEYr   r   r$   r[   Graphr^   contextmanagerr   r  rQ  r  rw  rs  rV   rq  r  r  r)   r*   r+   <module>r     ss   +  : :  / > + + O 9 8 3 . . 6 + < 1 + 7 2 0 6 ( ) ' 2 0 / - 1 6 MM""MM!!MM%%  %% >f > 9=59B2J #+W*		 W* ,W*t 5.5.%3CII%>5. 5.x '+'+59&*,0(,-104AH, G@"Q2'<"&r*   