o
    ?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   Z_gradient_registrylookupZop_defnameLookupErrorop r   b/home/www/facesmatcher.com/pyenv/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)ZlaZlbZ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!   Z
_graph_key
ValueError)topscheck_typesZnone_if_emptygr
   r   r   r   get_unique_graphM   s0   
r0   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!   r,   )argsr!   iZsgvr   r   r   check_graphss   s   r4   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r.   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   r0   )r"   check_graphallow_graphZ
ignore_opsr.   r   r   r   make_list_of_t   s   r;   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r:   c                 S      g | ]}|j qS r   r	   r&   r   r   r   r)          z&get_generating_ops.<locals>.<listcomp>)r;   )r"   r   r   r   get_generating_ops   s   
r?   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`.
  Fr<   )r;   Z	consumersr   )r"   r-   r(   r
   r   r   r   get_consuming_ops   s   

r@   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.
  r5   Nr6   c                 S   r7   r   )r   r   r*   r'   r
   r   r   r   r)      r8   z#make_list_of_op.<locals>.<listcomp>)r   r   r   r   r   r   r*   r0   )r-   r9   r:   Z	ignore_tsr.   r   r   r   make_list_of_op   s   rB   c                 C   s   | j }|rt| r|S g S |S N)inputsr   )r
   only_differentiableZ	op_inputsr   r   r   _get_inputs   s   rF   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`.
  Fr<   c                    s     d u s|  v od u p| S rC   r   r	   )
within_opswithin_ops_fnr   r   	is_within!  s   z(get_backward_walk_ops.<locals>.is_within)rE   c                    s   g | ]}| vr|qS r   r   rA   )seed_opsr   r   r)   6  s    z)get_backward_walk_ops.<locals>.<listcomp>)r   nextr   StopIterationr   r   r   r;   r?   rB   r   ObjectIdentitySetlistr   rF   r
   r   control_inputsr   )rJ   Z	inclusiverG   rH   Z
stop_at_tsrO   rE   Zfirst_seed_opr"   rI   resultwaveZnew_waver
   Znew_tZnew_opr   )rJ   rG   rH   r   get_backward_walk_ops   sR   





rR   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__Zag_pass_throughr   r   r   r   rS   :  s    rS   c                 C   s   t | tjr	| jS | S rC   )r   r   r   r
   )Zop_or_tensorr   r   r   _as_operationA  s   rX   c                 C   s   dd | j D t| j S )Nc                 S   r=   r   r	   r'   xr   r   r   r)   H  r>   z graph_inputs.<locals>.<listcomp>)rD   rN   rO   r	   r   r   r   graph_inputsG  s   r[   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   )rX   )r'   r   r   r   r   r)   \  s    zshow_path.<locals>.<listcomp>c                 s   s    | ]}|j V  qd S rC   r	   rY   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   rY   r   r   r   r\   l  s    z??)r   r   r   r
   rN   r   popr   r   r+   reversedr[   )Zfrom_opZtensorssourcesZ	final_opsvisited_opsops_to_visitZsome_op_outputr
   Zpath_oppathinpr   r   r   	show_pathK  s8   



rd   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.
  FNTZPlaceholderzjUnable to lift tensor %s because it depends transitively on placeholder %s via at least one path, e.g.: %s)rX   r   rM   r]   r   r   updater    rS   reprrd   r[   r   )Zinit_tensorr_   Zdisallowed_placeholdersr`   Z
op_outputsZadd_sourcesra   Zextra_sourcesr
   Zshould_raiserc   r   r   r   map_subgraphw  s6   



rg   r   )TTF)TNNr   FF)rW   Ztensorflow.python.frameworkr   r   r   Ztensorflow.python.utilr   r   r   r   r#   r0   r4   r;   r?   r@   rB   rF   rR   r   rS   rX   r[   rd   rg   r   r   r   r   <module>   s6   
&

 	
O,