o
    i eX7                     @   s   d Z ddlmZ ddlmZ ddlmZ dd Zdd Zd	d
 Z	dd Z
d+ddZdd Zd,ddZdd Zdd Zd,ddZdd Z						d-dd ZG d!d" d"eZd#d$ Zd%d& Zd'd( Zd)d* ZdS ).z#Tools for selecting ops in a graph.    )ops)tensor)object_identityc                 C   s,   zt j| jjd uW S  ty   Y dS w NF)r   _gradient_registrylookupop_defnameLookupErrorop r   P/var/www/myenv/lib/python3.10/site-packages/tensorflow/python/ops/op_selector.pyis_differentiable   s
   r   c                 C   s4   t | tjrdS zt| }W dS  ty   Y dS w )z&Return true if the object is iterable.FT)
isinstance
tensor_libTensoriter	Exception)obj_r   r   r   is_iterable   s   
r   c                 C   s2   t | }|D ]}||vr| | || q| 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lr   r   r   concatenate_unique(   s   

r   c                 C   s>   t | tjstdt| g }|  D ]}||j7 }q|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   r   r   r   get_tensors;   s   
r(   NFc                 C   s   t | tjr| S t| stdt| |du r tjtj	f}nt|s'|f}d}| D ]/}t ||sDtdd
dd |D t||du rL|j}q+|j|jjkrZtd|q+|du re|setd|S )	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, c                 S      g | ]}t |qS r   )str.0tr   r   r   
<listcomp>h   s
    z$get_unique_graph.<locals>.<listcomp>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   joinr&   
_graph_key
ValueError)topscheck_typesnone_if_emptygr   r   r   r   get_unique_graphM   s0   
r7   c                  G   sX   d}t | D ]#\}}|du r|jdur|j}q|jdur)|j|ur)td| dqdS )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&   r2   )argsr&   isgvr   r   r   check_graphss   s   r<   Tc                 C   sb   t | tjr|rt| S tdt| s| g} | sg S |r*|r!dntj}t| |d dd | D S )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r4   c                 S      g | ]
}t |tjr|qS r   )r   r   r   r+   r   r   r   r.          z"make_list_of_t.<locals>.<listcomp>)	r   r   r    r(   r!   r   r   r   r7   )r'   check_graphallow_graph
ignore_opsr4   r   r   r   make_list_of_t   s   rD   c                 C   s   t | dd} dd | D S )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rB   c                 S      g | ]}|j qS r   r   r+   r   r   r   r.          z&get_generating_ops.<locals>.<listcomp>)rD   )r'   r   r   r   get_generating_ops   s   
rH   c                 C   s>   t | dd} g }| D ]}| D ]}||vr|| qq
|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`.
  FrE   )rD   	consumersr   )r'   r3   r-   r   r   r   r   get_consuming_ops   s   

rJ   c                 C   sb   t | tjr|r|  S tdt| s| g} | sg S |r*|r!dntj}t| |d dd | D S )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.
  r=   Nr>   c                 S   r?   r   )r   r   r/   r,   r   r   r   r   r.      r@   z#make_list_of_op.<locals>.<listcomp>)r   r   r    r$   r!   r   r/   r7   )r3   rA   rB   	ignore_tsr4   r   r   r   make_list_of_op   s   rM   c                 C   s   | j }|rt| r|S g S |S N)inputsr   )r   only_differentiable	op_inputsr   r   r   _get_inputs   s   rR   r   c                    sp  |o| }t  s g ztt }W n ty   g  Y S w t|tjr1t dd}t| nt	 dd t
t|}t
t	  rVt	ddt
 M  fdd}	t }
t }|rt }|D ]5}t||dD ]}||v r{qt|j|
vr|	|jr||j qt|r|jD ]}||
vr|	|r|| qqlt|
| |}|sg|s fdd|
D }
|
S )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`.
  FrE   c                    s     d u s|  v od u p| S rN   r   r   )
within_opswithin_ops_fnr   r   	is_within!  s   z(get_backward_walk_ops.<locals>.is_within)rP   c                    s   g | ]}| vr|qS r   r   rK   )seed_opsr   r   r.   6  s    z)get_backward_walk_ops.<locals>.<listcomp>)r   nextr   StopIterationr   r   r   rD   rH   rM   r   ObjectIdentitySetlistr   rR   r   r   control_inputsr   )rV   	inclusiverS   rT   
stop_at_tsr[   rP   first_seed_opr'   rU   resultwavenew_waver   new_tnew_opr   )rV   rS   rT   r   get_backward_walk_ops   sR   





rd   c                   @   s   e Zd ZdZdZdS )UnliftableErrorz3Raised if a Tensor cannot be lifted from the graph.TN)__name__
__module____qualname____doc__ag_pass_throughr   r   r   r   re   :  s    re   c                 C   s   t | tjr	| jS | S rN   )r   r   r   r   )op_or_tensorr   r   r   _as_operationA  s   rl   c                 C   s   dd | j D t| j S )Nc                 S   rF   r   r   r,   xr   r   r   r.   H  rG   z graph_inputs.<locals>.<listcomp>)rO   rZ   r[   r   r   r   r   graph_inputsG  s   ro   c                 C   s   t | tjr	| j} t |ts|g}dd |D }tdd |D }t|}i }|rw| }||v r2q'|| || kr]|}|g}	||vrQ|| }|	| ||vsDd	dd t
|	D S t|D ]}
|
|vrt|
|vrt|||
< ||
 qa|s)dS )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                 S   r)   r   )rl   )r,   r   r   r   r   r.   \  s    zshow_path.<locals>.<listcomp>c                 s   s    | ]}|j V  qd S rN   r   rm   r   r   r   	<genexpr>^  s    zshow_path.<locals>.<genexpr>z <- c                 s   s     | ]}d |j |jf V  qdS )z%s (%s)N)r	   r#   rm   r   r   r   rp   l  s    z??)r   r   r   r   rZ   r   popr   r   r0   reversedro   )from_optensorssources	final_opsvisited_opsops_to_visitsome_op_outputr   path_oppathinpr   r   r   	show_pathK  s8   



r}   c                 C   s   t | g}t }|rk| }||v rq	|| d}	|dur&||v r&d}	n|jdkr9|du r3|s3d}	||j |	rLtdt	| t	|t
|| |f t|D ]}
||
 | |
|vrh|
|pa|vrh||
 qP|s|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.
  FNTPlaceholderzjUnable to lift tensor %s because it depends transitively on placeholder %s via at least one path, e.g.: %s)rl   r   rY   rq   r   r#   updater%   re   reprr}   ro   r   )init_tensorru   disallowed_placeholdersrw   
op_outputsadd_sourcesrx   extra_sourcesr   should_raiser|   r   r   r   map_subgraphw  s6   



r   r   )TTF)TNNr   FF)ri   tensorflow.python.frameworkr   r   r   tensorflow.python.utilr   r   r   r   r(   r7   r<   rD   rH   rJ   rM   rR   rd   r   re   rl   ro   r}   r   r   r   r   r   <module>   s6   
&

 	
O,