o
    i e8                     @   s   d 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 e	jZdd Zdd Zedg dZedddgZdd Zdd Zedg d						dddZdS )zUtility to lift subgraphs.    N)
func_graph)ops)tensor)	array_ops)op_selector)resource_variable_ops)compat)object_identity)	tf_exportc                 C   s   t | tjr	| jS | S N)
isinstance
tensor_libTensoropop_or_tensor r   T/var/www/myenv/lib/python3.10/site-packages/tensorflow/python/eager/lift_to_graph.py_as_operation"   s   r   c                 C   s   t dd tt| D S )Nc                 s   s*    | ]}t |jd kot |j V  qdS )ConstN)r   typecontrol_inputs).0ir   r   r   	<genexpr>)   s    

z#_constant_inputs.<locals>.<genexpr>)allr   graph_inputsr   r   r   r   r   _constant_inputs(   s   r   _InputMutation	copied_opinput_indexold_graph_tensor_ControlMutationr    old_graph_opc              	      s  g }g }g }t | jD ]'\}}||d}	|	du r-tjd|j|jd}	|td||d ||	 qg }
| j	D ]}||d}|du rN|t
d|d q8|
| q8t|
S t| j= |j| jd}|dur{t|j|jvr{|| |j| j|dd | jD dd	 | jj D | jd
 W d   n1 sw   Y  W d   n1 sw   Y   || < t | jD ]\}} j| ||< q fdd|D  fdd|D fS )a  Copy an op directly to a given graph.

  Generally `op`'s inputs should already have been copied. If this is not the
  case, for example with v1 while_loops, then `_copy_non_source` inserts
  placeholders for the unavailable Tensors and returns a list of required
  mutations.

  Args:
    op: The op to be copied.
    graph: The destination graph.
    op_map: A dict mapping ops and tensors in the old graph to the new one.
    base_graph: The graph we're copying from, for any necessary functions.
  Returns:
    A tuple of (required_inputs, required_control_inputs):
      required_inputs:
        A list of `_InputMutation` tuples containing inputs to `copied_op` which
        must be updated once `old_graph_tensor` has been copied.
      required_control_inputs:
        A list of `_ControlMutation` tuples containing control inputs to
        `copied_op` which must be added once `old_graph_op` has been copied.
  Nunused_control_flow_input)nameshapedtyper   )r    r$   c                 S   s   g | ]}|j qS r   )r(   r   xr   r   r   
<listcomp>~       z$_copy_non_source.<locals>.<listcomp>c                 S   s*   i | ]\}}| d s| ds||qS )_class_tpu_replicate)
startswith)r   keyvaluer   r   r   
<dictcomp>   s    z$_copy_non_source.<locals>.<dictcomp>)op_typeinputsdtypesattrsr&   c                       g | ]}|j  d qS r    _replacer   mutationr9   r   r   r+          c                    r7   r8   r:   r<   r9   r   r   r+      r>   )	enumerater4   getr   placeholderr'   r(   appendr   r   r#   r   control_dependenciesdevice
_functionsr   r   as_strr&   add_to_graph	create_opoutputsnode_defattritems)r   graphop_map
base_graphinput_mutationscontrol_mutationscopied_inputsr!   original_inputcopied_inputcopied_control_inputsoriginal_control_inputcopied_control_inputfr   or   r9   r   _copy_non_source<   sl   


 

rZ   c                 C   s8  |r| |v r|j ||  | jjd}nn| jjdkr]t| r]| jjd }t|j|||d\}}	|s1|	r8td|t	
| jj
 tj|| | j| jjd}W d   n1 sWw   Y  n#t	
| jj
 tj| j| j| jjd}W d   n1 s{w   Y  t| }
|
jrtj||
d	d
 ||| < |j|| j< dS )a  Create a source in a graph based on a Tensor from a different graph.

  This function creates a placeholder analog of `s` in a graph with the
  following behavior:

  1) If s is a captured Tensor or Variable and handle_captures is set to True,
     simply capture it in the new graph as well.

  2) If s is a PlaceholderWithDefault whose default is a constant, preserve
     said default in the new graph.

  3) When applicable, copy resource variable metadata from `s` to the newly
     created placeholder.

  Args:
    s: The source of interest.
    graph: The destination graph.
    op_map: A dict mapping ops and tensors in the old graph to the new one.
    handle_captures: A boolean indicating whether to re-capture s in the new
      graph or simply create a vanilla placeholder.
    inverse_captures: A dict mapping s back to the Tensor or Variable that it
      captures.
    base_graph: The graph being copied from.
  )r&   PlaceholderWithDefaultr   r   rM   rN   rO   z4Could not copy source node {} because it has inputs.)inputr'   r&   N)r(   r'   r&   T)
graph_mode)capturer   r&   r   r   r4   rZ   AssertionErrorformatr   rD   r   placeholder_with_defaultr'   rA   r(   r   get_resource_handle_datashape_and_type_set_handle_shapes_and_types)srM   rN   handle_capturesinverse_capturesrO   copied_placeholderdefault_valueunavailable_inputsunavailable_control_inputsbase_handler   r   r   _copy_source   sB   

rn   z__internal__.lift_to_graph)v1Fc                    sN  g }g }	| D ]}
t |
tjr||
 q|	|
 q|p |	d j}|p&t }t|p,g }tdd |D }t	
t|	D ]}|tj|||||d q>g }tg  fdd|	D }t|}|r|r| }| v roqd | || t|D ]#}|jdkrq~|| t fdd| D r||vr|| q~|sf|  |r|tt| |sd|jd	d
 d g }t }g }t |tjrt |tjr|j}|D ]\}}|||< q|j}|  |D ]}|||< qt }|D ]}||v r|| ||j t||||||d q|D ]}||j t||||||d qg }g }t|D ]#}||v s=||v r?q1t ||||d\}}|!| |!| q1|" 1 |D ]}|j#$|j%||j&  q\|D ]}|j'jdkrxqm|j#(||j'  qmW d   n	1 sw   Y  |W  d   S 1 sw   Y  dS )a  Copies the tensor and all its inputs recursively to the outer graph.

  Args:
    tensors: The Tensors to lift.
    graph: The graph to lift to.
    sources: Optional sequence of nodes to start from. If omitted the whole
      subgraph which feeds into `init_tensor` is lifted.
    disallowed_placeholders: An optional set of ops which may not appear in the
      lifted graph. Defaults to all placeholders.
    add_sources: A boolean indicating whether placeholders which are not in
      sources should be allowed.
    handle_captures: A boolean indicating whether to re-capture s in the new
      graph or simply create a vanilla placeholder.
    base_graph: The graph from which to lift ops. This will be inferred if not
      specified.
    op_map: A map contains all the existing nodes that have been lifted to the
      destination graph, so they won't be lifted and copied again.

  Returns:
    A mapping from ops in the current default graph to ops in `graph`.

  Raises:
    UnliftableError: If a placeholder blocks lifting.
  r   c                 s   s    | ]}|j V  qd S r   r   r)   r   r   r   r      s    z lift_to_graph.<locals>.<genexpr>)init_tensorsourcesdisallowed_placeholdersvisited_ops
op_outputsadd_sourcesc                    s    g | ]} t | st |qS r   )r   )r   t)ru   r   r   r+   	  s    
z!lift_to_graph.<locals>.<listcomp>TPUReplicateMetadatac                 3   s    | ]}| v V  qd S r   r   r)   )
marked_opsr   r   r     s    c                 S   s   t t| dkS )Nr   )lenr   r   rp   r   r   r   <lambda>(  r,   zlift_to_graph.<locals>.<lambda>)r0   )rf   rM   rN   rg   rh   rO   r\   N))r   r   ResourceVariablerB   rM   r	   ObjectIdentityDictionaryObjectIdentitySetsetcollectionsdefaultdictupdater   map_subgraphpopaddr   r   r   difference_updatenextitersortr   	FuncGraphcapturesinternal_captures
as_defaultremover   rn   reversedrZ   extend_mutation_lockr    _update_inputr!   r"   r$   _add_control_input)tensorsrM   rr   rs   rv   rg   rO   rN   variable_init_tensorsinit_tensorsr   rt   rq   ops_to_copyops_to_visitunvisited_opsr   inpr   rh   r   external_captureinternal_capturer   
source_opsrf   rP   rQ   new_input_mutationsnew_control_mutationsr=   r   )ry   ru   r   lift_to_graph   s   !


















&r   )NNFFNN)__doc__r   tensorflow.python.frameworkr   r   r   r   tensorflow.python.opsr   r   r   tensorflow.python.utilr   r	    tensorflow.python.util.tf_exportr
   UnliftableErrorr   r   
namedtupler   r#   rZ   rn   r   r   r   r   r   <module>   s@   S
<