
    AVhX7                         d Z ddlmZ ddlmZ ddlmZ d Zd Zd Z	d Z
dd
Zd ZddZd Zd ZddZd Z	 	 	 	 	 	 ddZ G d de      Zd Zd Zd Zd Zy	)z#Tools for selecting ops in a graph.    )ops)tensor)object_identityc                     	 t         j                  j                  | j                  j                        d uS # t
        $ r Y yw xY wNF)r   _gradient_registrylookupop_defnameLookupErrorops    Q/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/ops/op_selector.pyis_differentiabler      s=    !!((8DD	 s   47 	AAc                 p    t        | t        j                        ry	 t        |       }y# t        $ r Y yw xY w)z&Return true if the object is iterable.FT)
isinstance
tensor_libTensoriter	Exception)obj_s     r   is_iterabler      s<    Z&&'S	A 
 
 s   ) 	55c                 x    t        |       }|D ])  }||vs| j                  |       |j                  |       + | S )a  Add all the elements of `lb` to `la` if they are not there already.

  The elements added to `la` maintain ordering with respect to `lb`.

  Args:
    la: List of Python objects.
    lb: List of Python objects.
  Returns:
    `la`: The list `la` with missing elements from `lb`.
  )setappendadd)lalbla_setls       r   concatenate_uniquer"   (   s@     r7& aiiljjm 
)    c                     t        | t        j                        s#t        dj	                  t        |                   g }| j                         D ]  }||j                  z  } |S )zget all the tensors which are input or output of an op in the graph.

  Args:
    graph: a `tf.Graph`.
  Returns:
    A list of `tf.Tensor`.
  Raises:
    TypeError: if graph is not a `tf.Graph`.
  zExpected a graph, got: {})r   r   Graph	TypeErrorformattypeget_operationsoutputs)graphtsr   s      r   get_tensorsr-   ;   s]     
E399	%
/66tE{C
DD	"  " b"**B	)r#   Nc                 z   t        | t        j                        r| S t        |       s#t	        dj                  t        |                   |!t        j                  t        j                  f}nt        |      s|f}d}| D ]  }t        ||      sJt	        dj                  dj                  |D cg c]  }t        |       c}      t        |                  ||j                  }h|j                  |j                  j                  k7  st        dj                  |             ||st        d      |S c c}w )a<  Return the unique graph used by the all the elements in tops.

  Args:
    tops: iterable of elements to check (usually a list of tf.Operation and/or
      tf.Tensor). Or a tf.Graph.
    check_types: check that the element in tops are of given type(s). If None,
      the types (tf.Operation, tf.Tensor) are used.
    none_if_empty: don't raise an error if tops is an empty list, just return
      None.
  Returns:
    The unique graph used by all the tops.
  Raises:
    TypeError: if tops is not a iterable of tf.Operation.
    ValueError: if the graph is not unique.
  z{} is not iterableNz Expected a type in ({}), got: {}z, z+Operation {} does not belong to given graphz,Can't find the unique graph of an empty list)r   r   r%   r   r&   r'   r(   	Operationr   r   joinstrr+   
_graph_key
ValueError)topscheck_typesnone_if_emptygr   ts         r   get_unique_graphr9   M   s/     cii K	T	
(//T
;
<<==*"3"34K{#.K
! Qbb+&8??		!K# LO
L K# A$%)"X/ 0 0y
((a	
,,	,DKKBOPPQ Y}
C
DD	
(K#s   .D8c                      d}t        |       D ]J  \  }}||j                  |j                  }!|j                  .|j                  |us=t        d| d       y)zCheck that all the element in args belong to the same graph.

  Args:
    *args: a list of object with a obj.graph property.
  Raises:
    ValueError: if all the elements do not belong to the same graph.
  Nzargs[z7] does not belong to the same graph as other arguments.)	enumerater+   r3   )argsr+   isgvs       r   check_graphsr?   s   si     %$ +fa}.iie		399E#9qc "* * + +	+r#   c                 0   t        | t        j                        r|rt        |       S t	        d      t        |       s| g} | sg S |r!|rdnt        j                  }t        | |       | D cg c]  }t        |t        j                        s|! c}S c c}w )a  Convert ts to a list of `tf.Tensor`.

  Args:
    ts: can be an iterable of `tf.Tensor`, a `tf.Graph` or a single tensor.
    check_graph: if `True` check if all the tensors belong to the same graph.
    allow_graph: if `False` a `tf.Graph` cannot be converted.
    ignore_ops: if `True`, silently ignore `tf.Operation`.
  Returns:
    A newly created list of `tf.Tensor`.
  Raises:
    TypeError: if `ts` cannot be converted to a list of `tf.Tensor` or,
     if `check_graph` is `True`, if all the ops do not belong to the same graph.
  0allow_graph is False: cannot convert a tf.Graph.Nr5   )	r   r   r%   r-   r&   r   r   r   r9   )r,   check_graphallow_graph
ignore_opsr5   r8   s         r   make_list_of_trF      s     CII_HIIr?4bi&DJ,=,=kr{3>!Z:+<+<=A>>>s   ,BBc                 Z    t        | d      } | D cg c]  }|j                   c}S c c}w )a  Return all the generating ops of the tensors in `ts`.

  Args:
    ts: a list of `tf.Tensor`
  Returns:
    A list of all the generating `tf.Operation` of the tensors in `ts`.
  Raises:
    TypeError: if `ts` cannot be converted to a list of `tf.Tensor`.
  FrD   )rF   r   )r,   r8   s     r   get_generating_opsrI      s(     be,"	1!$$		s   (c                     t        | d      } g }| D ]-  }|j                         D ]  }||vs|j                  |        / |S )zReturn all the consuming ops of the tensors in ts.

  Args:
    ts: a list of `tf.Tensor`
  Returns:
    A list of all the consuming `tf.Operation` of the tensors in `ts`.
  Raises:
    TypeError: if ts cannot be converted to a list of `tf.Tensor`.
  FrH   )rF   	consumersr   )r,   r4   r8   r   s       r   get_consuming_opsrL      sR     be,"	$ akkm 	4B 
+r#   c                 :   t        | t        j                        r|r| j                         S t	        d      t        |       s| g} | sg S |r!|rdnt        j                  }t        | |       | D cg c]  }t        |t        j                        s|! c}S c c}w )a4  Convert ops to a list of `tf.Operation`.

  Args:
    tops: can be an iterable of `tf.Operation`, a `tf.Graph` or a single
      operation.
    check_graph: if `True` check if all the operations belong to the same graph.
    allow_graph: if `False` a `tf.Graph` cannot be converted.
    ignore_ts: if True, silently ignore `tf.Tensor`.
  Returns:
    A newly created list of `tf.Operation`.
  Raises:
    TypeError: if tops cannot be converted to a list of `tf.Operation` or,
     if `check_graph` is `True`, if all the ops do not belong to the
     same graph.
  rA   NrB   )r   r   r%   r)   r&   r   r/   r9   )r4   rC   rD   	ignore_tsr5   r   s         r   make_list_of_oprO      s      cii   ""HIItVdi%D3==kt5?2B!>B???s   1BBc                 @    | j                   }|rt        |       r|S g S |S N)inputsr   )r   only_differentiable	op_inputss      r   _get_inputsrU      s&    ii))"-9525r#   c                    |xr | }t        |       s| g} 	 t        t        |             }t	        |t
        j                        rt        | d      }t        |      } nt        | d      } t        j                  t        |            }t        j                  t        |             } r't        d      t        j                        | z  } fd}	t        |       }
t        |       }|rt               }|D ]  }t        ||      D ]D  }||v r|j                  |
vs |	|j                        s*|j!                  |j                         F |sZ|j"                  D ]!  }||
vs |	|      s|j!                  |       #  t%        |
|       |}|r|s|
D cg c]	  }|| vs| }
}|
S # t        $ r g cY S w xY wc c}w )a  Do a backward graph walk and return all the visited ops.

  Args:
    seed_ops: an iterable of operations from which the backward graph
      walk starts. If a list of tensors is given instead, the seed_ops are set
      to be the generators of those tensors.
    inclusive: if True the given seed_ops are also part of the resulting set.
    within_ops: an iterable of `tf.Operation` within which the search is
      restricted. If `within_ops` is `None`, the search is performed within
      the whole graph.
    within_ops_fn: if provided, a function on ops that should return True iff
      the op is within the graph traversal. This can be used along within_ops,
      in which case an op is within if it is also in within_ops.
    stop_at_ts: an iterable of tensors at which the graph walk stops.
    control_inputs: if True, control inputs will be used while moving backward.
    only_differentiable: if True, only traverse ops which are differentiable.
      This includes natively differentiable ops, or ops with custom gradients.
  Returns:
    A Python set of all the `tf.Operation` behind `seed_ops`.
  Raises:
    TypeError: if `seed_ops` or `within_ops` cannot be converted to a list of
      `tf.Operation`.
  FrH   c                 8    d u xs | v xr d u xs  |       S rQ    )r   
within_opswithin_ops_fns    r   	is_withinz(get_backward_walk_ops.<locals>.is_within!  s1    $2"
"2 42r!24r#   )rS   )r   nextr   StopIterationr   r   r   rF   rI   rO   r   ObjectIdentitySetlistr   rU   r   r   control_inputsr"   )seed_ops	inclusiverY   rZ   
stop_at_tsr`   rS   first_seed_opr,   r[   resultwavenew_waver   new_tnew_ops     ``            r   get_backward_walk_opsrj      s   < "?+>'>.	X	zHh(M
 z001	e	4B!"%HxU;H00
1KL*..x/HI( ?J 22:>J
H4 >&	X$uH 	!r7JK !%J
886!i&9
,,uxx
 	!
 
'' 	!F6!i&7LL 	!	! vx(D 	 
!8RRx%7b8F8	-O 
 IL 9s   F1 	G)G1F?>F?c                       e Zd ZdZdZy)UnliftableErrorz3Raised if a Tensor cannot be lifted from the graph.TN)__name__
__module____qualname____doc__ag_pass_throughrX   r#   r   rl   rl   :  s    ; /r#   rl   c                 R    t        | t        j                        r| j                  S | S rQ   )r   r   r   r   )op_or_tensors    r   _as_operationrt   A  s"    j//0??	r#   c                     | j                   D cg c]  }|j                   c}t        | j                        z   S c c}w rQ   )rR   r   r_   r`   )r   xs     r   graph_inputsrw   G  s.    			"1!$$	"T"*;*;%<	<<	"s   ;c                 8   t        | t        j                        r| j                  } t        |t              s|g}|D cg c]  }t        |       }}t        d |D              }t	        |      }i }|r|j                         }||v r|j                  |       || k(  rE|}	|	g}
|	|vr||	   }	|
j                  |	       |	|vrdj                  d t        |
      D              S t        |      D ]"  }||vs||vs|||<   |j                  |       $ |ryc c}w )a$  Find one path from `from_op` to any of `tensors`, ignoring `sources`.

  Args:
    from_op: A `tf.Operation`.
    tensors: A `tf.Operation`, a `tf.Tensor`, or a list thereof.
    sources: A list of `tf.Tensor`.

  Returns:
    A python string containing the path, or "??" if none is found.
  c              3   4   K   | ]  }|j                     y wrQ   r   .0rv   s     r   	<genexpr>zshow_path.<locals>.<genexpr>^  s     *QADD*s   z <- c              3   T   K   | ]   }|j                   d |j                  d " yw)z ()N)r   r(   rz   s     r   r|   zshow_path.<locals>.<genexpr>l  s     N!affaff5Ns   &(z??)r   r   r   r   r_   rt   r   popr   r   r0   reversedrw   )from_optensorssourcesr   	final_opsvisited_opsops_to_visitsome_op_outputr   path_oppathinps               r   	show_pathr   K  s,    **+jjG	GT	"iG3:;}V$;);*'**+i,.				B	[OOB	W}gYd9$ )G 9$ [[Nx~NNNb! ##k!c&8 ".



c
"# 	" 
- <s   Dc                    t        |       g}t        j                         }|r|j                         }||v r|j	                  |       d}	|||v rd}	n0|j
                  dk(  r!||sd}	|j                  |j                         |	r1t        dt        |       dt        |      dt        || |            t        |      D ]5  }
||
   j	                  |       |
|vs|
|xs |vs%|j                  |
       7 |r|S )a  Walk a Graph and capture the subgraph between init_tensor and sources.

  Note: This function mutates visited_ops and op_outputs.

  Args:
    init_tensor:  A Tensor or Operation where the subgraph terminates.
    sources:  A set of Tensors where subgraph extraction should stop.
    disallowed_placeholders: An optional set of ops which may not appear in the
      lifted graph. Defaults to all placeholders.
    visited_ops: A set of operations which were visited in a prior pass.
    op_outputs: A defaultdict containing the outputs of an op which are to be
      copied into the new subgraph.
    add_sources: A boolean indicating whether placeholders which are not in
      sources should be allowed.

  Returns:
    The set of placeholders upon which init_tensor depends and are not in
    sources.

  Raises:
    UnliftableError: if init_tensor depends on a placeholder which is not in
      sources and add_sources is False.
  FTPlaceholderzUnable to lift tensor z0 because it depends transitively on placeholder z via at least one path, e.g.: )rt   r   r^   r   r   r(   updater*   rl   reprr   rw   r   )init_tensorr   disallowed_placeholdersr   
op_outputsadd_sourcesr   extra_sourcesr   should_raiser   s              r   map_subgraphr   w  s   2  ,-,!335-				B	[OOBL*r5L/Ll	M	!	 	(2::& d2h	"k7(KMN N B !o"	K	C0H=$IC !' 	0 
r#   r   )TTF)TNNrX   FF)rp   tensorflow.python.frameworkr   r   r   tensorflow.python.utilr   r   r   r"   r-   r9   r?   rF   rI   rL   rO   rU   rj   r   rl   rt   rw   r   r   rX   r#   r   <module>r      s    * + < 2&$#L+"?<&@@ %)%)(,%')..3L^i ='X3r#   