
    BVh8              
          d Z ddl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   ed
g      ej                        Zh dZg dZdZd Zdej                  _          ej&                  de       edg      d%d              Zd Zd Zd Zd Zd Z ej&                  de       edg      d               Z ej&                  de       edg      d               Z ej&                  de       edg      d&d              Z edg       	 d%d ej                  d!ej                  d"ed#efd$       Zy)'z0Helpers to manipulate a tensor graph in python.
    N)	graph_pb2)node_def_pb2)_proto_comparators)dtypes)ops)deprecation)	tf_exportGraphDef)v1>
   QueueAssignVariable	AssignAdd	AssignSub
ScatterAdd
ScatterSub
VariableV2ScatterUpdateTruncatedNormal)SwitchEnterExitIdentityMergeNextIterationzThis API was designed for TensorFlow v1. See https://www.tensorflow.org/guide/migrate for instructions on how to migrate your code to TensorFlow v2.c                     | t         v S )z/Returns true if 'op' refers to a Variable node.)_VARIABLE_OPS)ops    [/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/framework/graph_util_impl.py_is_variable_opr    ;   s    	}	    a  A protobuf containing the graph of operations.

@compatibility(TF2)
This API is not available in TensorFlow 2.x.

You should not need to use `GraphDef`s directly in TF2. To load `GraphDef`s in
TF2, use SavedModel. The SavedModel contains the `GraphDef`.

Before:

```python
with tf.io.gfile.GFile('/tmp/graph.pb', 'rb') as f:
  graph_def = tf.compat.v1.GraphDef()
  graph_def.ParseFromString(f.read())
```

After:

```python
tf.saved_model.load('/tmp/saved_model')
```

If you would like to create a `GraphDef` in TF2, use `tf.function` and
`get_concrete_function`.

>>> @tf.function
>>> def f(x):
>>>   return x
>>>
>>> graph_def = f.get_concrete_function(1.).graph.as_graph_def()
>>> print(graph_def)

@end_compatibility

)dateinstructionszgraph_util.must_run_on_cpuc                 H   t        | t        j                        r| j                  }nt        | t        j
                        sJ | }|rt        |j                        ry|j                  dk(  r@|j                  d   j                  }|t        j                  k(  s|t        j                  k(  ry|j                  dv r-|j                  d   j                  }|t        j                  k(  ry|j                  dv r-|j                  d   j                  }|t        j                  k(  ryy)	ar  Returns True if the given node_def must run on CPU, otherwise False.

  Args:
    node: The node to be assigned to a device. Could be either an ops.Operation
      or NodeDef.
    pin_variables_on_cpu: If True, this function will return False if node_def
      represents a variable-related op.

  Returns:
    True if the given node must run on CPU, otherwise False.
  TConstdtype)DynamicStitchParallelDynamicStitchT)CastSrcTF)
isinstancer   	Operationnode_defr   NodeDefr    r   attrtyper   stringint32)nodepin_variables_on_cpur.   r&   s       r   must_run_on_cpur6   f   s    " cmm$}}HdL00111H ohkk: [[GMM'"''E&,,!6[[>>MM###E[[HMM&!&&E	r!   c                 V    | j                  d      r| dd  S | j                  d      d   S )N^   :r   )
startswithsplit)ns    r   
_node_namer>      s+    \\#QR5L773<?r!   c                 T    | j                  d      }|j                  d      r|dd S |S )zCDecodes colocated node name and returns it without loc:@ prepended.zutf-8zloc:@   N)decoder;   )colocated_node_namecolocated_node_decodeds     r   _get_colocated_node_namerD      s4    .55g>&&w/!!"%%	r!   c                    i }i }i }d}| j                   D ]  }t        |j                        }|||<   |j                  D cg c]  }t        |       c}||<   d|j                  v rE|j                  d   j
                  j                  D ]  }||   j                  t        |             ! |||<   |dz  } |||fS c c}w )z<Extracts useful information from the graph and returns them.r   _classr9   )	r4   r>   nameinputr0   listsappendrD   )		graph_defname_to_input_namename_to_nodename_to_seq_numseqr4   r=   xrB   s	            r   _extract_graph_summaryrR      s    , /	#nn 
d499ALO48JJ?qZ]?q499!%8!4!9!9!;!; ;
1$$$%89	;; OA1HC
 
\?	:: @s    B<c                 .    |D ]  }|| v rJ d|z          y)z+Assert that nodes are present in the graph.z%s is not in graphN )rN   nodesds      r   _assert_nodes_are_presentrW      s*     7a62Q667r!   c                     t               }t        |       }|r-|d   }|d= ||v r|j                  |       ||v r|||   z  }|r-|S )z;Breadth first search for reachable nodes from target nodes.r   )setrI   add)target_nodesrM   nodes_to_keepnext_to_visitr4   s        r   _bfs_for_reachable_nodesr^      sg    %-|$-Da}d!!)$//m 	 
r!   zgraph_util.extract_sub_graphc                 j   t        | t        j                        st        dt	        |        d      t        |t
              rt        dt	        |       d      t        |       \  }}t        ||       t        ||      }t        t        |      fd      }t        j                         }|D ]4  }|j                  j                  t        j                  ||         g       6 |j                  j!                  | j                         |j"                  j!                  | j"                         |S )aD  Extract the subgraph that can reach any of the nodes in 'dest_nodes'.

  Args:
    graph_def: A graph_pb2.GraphDef proto.
    dest_nodes: An iterable of strings specifying the destination node names.
  Returns:
    The GraphDef of the sub-graph.

  Raises:
    TypeError: If 'graph_def' is not a graph_pb2.GraphDef proto.
  z;graph_def must be a graph_pb2.GraphDef proto, but got type .z8dest_nodes must be an iterable of strings, but got type c                     |    S NrT   )r=   rO   s    r   <lambda>z#extract_sub_graph.<locals>.<lambda>   s    ); r!   )key)r,   r   r
   	TypeErrorr1   strrR   rW   r^   sortedrI   r4   extendcopydeepcopylibraryCopyFromversions)	rL   
dest_nodesrM   rN   r\   nodes_to_keep_listoutr=   rO   s	           @r   extract_sub_graphrq      s!   " 
Iy11	2
  O,A/ 0 0 
C 
  ,-Q0 1 1 7M73lOL*5*:7IJ-
=;= 	# 6aHHOOT]]<?3456++y((),,	**+	*r!   z*graph_util.tensor_shape_from_node_def_namec                 `    d|vr|dz   }n|}| j                  |      }|j                         }|S )zBConvenience function to get a shape from a NodeDef's input string.r:   z:0)get_tensor_by_name	get_shape)graph
input_namecanonical_nametensorshapes        r   tensor_shape_from_node_def_namerz     s>     	
$&NN##N3&



%	,r!   z graph_util.remove_training_nodesc                    |sg }ddi}| j                   }i }|D ]/  }|j                  |v s|j                  |vs!d||j                  <   1 g }|D ]  }|j                  |v rt        j                         }|j                  |       |j                  }|j                  dd= |D ]9  }	t        j                  dd|	      }
|
|v r|j                  j                  |	       ; |j                  |        ddd}t               }t               }t               }|D ]  }|j                  D ]C  }d|v s|j                  |j                  dd             |j                  |j                         E d|j                  v sd|j                  d   j                  j                  D ]  }|j                  t!        |               i }|D ]Z  }|j                  |v s|j                  |vs!|j                  |v r0|j                  |vs?|j                  d	   ||j                  <   \ |j#                         D ci c]  \  }}||vr|| }}}g }|D ]  }|j                  |v rt        j                         }|j                  |       |j                  }|j                  dd= |D ]Y  }	t        j                  dd|	      }
|
|v r!||
   }	t        j                  dd|	      }
|
|v r!|j                  j                  |	       [ |j                  |        t%        j&                         }|j                   j)                  |       |S c c}}w )
a  Prunes out nodes that aren't needed for inference.

  There are nodes like Identity and CheckNumerics that are only useful
  during training, and can be removed in graphs that will be used for
  nothing but inference. Here we identify and remove them, returning an
  equivalent graph. To be specific, CheckNumerics nodes are always removed, and
  Identity nodes that aren't involved in control edges are spliced out so that
  their input and outputs are directly connected.

  Args:
    input_graph: Model to analyze and prune.
    protected_nodes: An optional list of names of nodes to be kept
      unconditionally. This is for example useful to preserve Identity output
      nodes.

  Returns:
    A list of nodes with the unnecessary ones removed.
  CheckNumericsTNz^\^ )r   StopGradientr8   rF   r   )r4   r   rG   r   r/   rl   rH   resubrK   rY   rZ   replacer0   rI   rJ   rD   itemsr   r
   rh   )input_graphprotected_nodestypes_to_removeinput_nodesnames_to_remover4   nodes_after_removalnew_nodeinput_before_removalfull_input_namerv   types_to_splicecontrol_input_namesnode_names_with_control_inputnode_in_colocated
node_inputrB   names_to_splicerG   valuenodes_after_splicingoutput_graphs                         r   remove_training_nodesr     s]   . 
O$d+/  +/ (dww/!dii&F#'odii (  )dyyO###%Hd::q/ -66&"o6j		&nnO,	-
 x() "&t</"%%e! Mdjj 5
	
	
 2 23 ;<%))$))45
 499!%8!4!9!9!;!; M
67JKLMM /! 3dww/!dii&F	'	' 
7	7%)ZZ]		"3 5D4I4I4K 9[T5$77 5[ 9/ 9 ! *dyyO###%Hd::q/ -66&"o6j/))*5VVFB8
 /) nnO,- )* ##%,/0	+9s   3L?z(__internal__.graph_util.graph_defs_equalgraph_def_1graph_def_2treat_nan_as_equalreturnc                 Z   t        | t        j                        st        dt	        |        d      t        |t        j                        st        dt	        |       d      t        j                  |      }t        j                  | j                         |j                         |      S )a/  Returns True iff the graph def arguments are structurally equivalent.

  The notion of equivalence encoded here checks that the set of NodeDefs in
  the GraphDef's function library and main graph body are identical.
  Additionally, it checks that the functions in the function library are equal
  as sets.

  Example usage:

  ```
  with tf.Graph().as_default() as g1:
    tf.constant(1)

  with tf.Graph().as_default() as g2:
    tf.constant(2)

  with tf.Graph().as_default() as g3:
    tf.constant(1)

  assert tf.__internal__.graph_util.graph_defs_equal(g1.as_graph_def(),
                                                     g3.as_graph_def())

  assert not tf.__internal__.graph_util.graph_defs_equal(g1.as_graph_def(),
                                                         g2.as_graph_def())
  ```

  Args:
    graph_def_1: Instance of `graph_pb2.GraphDef` to compare.
    graph_def_2: Instance of `graph_pb2.GraphDef` to compare.
    treat_nan_as_equal: Boolean indicating whether or not to treat nan
      floating-point values as equal. This is crucial for any equivalence
      relation defined over GraphDefs, to ensure symmetry.

  Returns:
    Boolean indicating structural equivalence as described above.

  Raises:
    TypeError: If either of the GraphDefs are not instances of
      `graph_pb2.GraphDef`.
  z=graph_def_1 must be a graph_pb2.GraphDef proto, but got type r`   z=graph_def_2 must be a graph_pb2.GraphDef proto, but got type )	r,   r   r
   re   r1   r   ProtoComparisonOptionsEqualsGraphDefSerializeToString)r   r   r   optionss       r   graph_defs_equalr   {  s    X 
K!3!3	4
  -.a1 2 2	K!3!3	4
  -.a1 2 2556HI'		*	*;+H+H+J+6+H+H+J+2
4 4r!   )Frb   )__doc__ri   r   tensorflow.core.frameworkr   r   tensorflow.python.frameworkr   r   r   tensorflow.python.utilr    tensorflow.python.util.tf_exportr	   r
   r   "_CONTROL_FLOW_OP_NAMES_OR_IDENTITY_DEPRECATION_MSGr    
deprecatedr6   r>   rD   rR   rW   r^   rq   rz   r   boolr   rT   r!   r   <module>r      s    	 / 2 : . + . 6%9%i&8&89& "* 
#	   L 	!# +,-) .#)f ;.7" 	!# -./$ 0#$N 	!# ;<= ># 	!# 123] 4#]@ 5"= 1644)"4"4 44"+"4"444)-44:>44 >44r!   