o
    ?e1                     @   sX  d Z ddlZddlZddlmZ ddlmZ e r!e	ddkp@e	dddkp@e	dddkp@e	dddkp@e	d	ddka
d
d Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% Zd&d' Zd(d) Zd*d+ Zd,d- Zd>d.d/Zd0d1 Zd2d3 Zd4d5 Z d6d7 Z!d8d9 Z"d:d; Z#d<d= Z$dS )?zUtility functions for control flow.

This file is necessary to avoid cyclic dependencies between ops.py and
control_flow_ops.py.
    N)tf2)
tf_loggingZTF_ENABLE_CONTROL_FLOW_V20ZTF_ENABLE_COND_V2ZTF_ENABLE_WHILE_V2ZTF_ENABLE_TENSOR_ARRAY_V2c                   C   s   da dS )zHUse control flow v2.

  Do not use this symbol. This will be removed.
  TN)ENABLE_CONTROL_FLOW_V2 r   r   h/home/www/facesmatcher.com/pyenv/lib/python3.10/site-packages/tensorflow/python/ops/control_flow_util.pyenable_control_flow_v2%   s   r   c                 C   s   t p
| jo
t| d S )z:Returns whether control flow v2 should be used in `graph`.Z	_captured)r   Zbuilding_functionhasattrgraphr   r   r   EnableControlFlowV2.   s   r   c                 C   s@   z|  d}|rW dS W n	 ty   Y nw |  }t|d uS )NZ_XlaCompileT)get_attr
ValueError_get_control_flow_contextGetContainingXLAContext)opZxla_compilectxtr   r   r   IsInXLAContext6   s   
r   c                 C      |   }t|d uS N)r   r   )r   r   r   r   r   InXlaContext@      r   c                 C   s0   	 t | rdS z| j} W n
 ty   Y dS w q)NTF)r   Zouter_graphAttributeErrorr
   r   r   r   GraphOrParentsInXlaContextE   s   
r   c                 C   r   r   )r   GetContainingWhileContextr   r   r   r   r   IsInWhileLoopN   r   r   c                 C   r   r   )r   GetContainingCondContextr   r   r   r   IsInCondS   r   r   c                 C      | j dkp	| j dkS )z Return true if `op` is a Switch.Switch	RefSwitchtyper   r   r   r   IsSwitchX      r%   c                 C   r   )zReturn true if `op` is a Merge.ZMergeZRefMerger"   r$   r   r   r   IsMerge]   r&   r'   c                 C   r   )z!Returns true if `op` is an Enter.ZEnterZRefEnterr"   r$   r   r   r   IsLoopEnterb   r&   r(   c                 C   r   )zReturn true if `op` is an Exit.ZExitZRefExitr"   r$   r   r   r   
IsLoopExitg   r&   r)   c                 C   sb   t | sdS | jsdS d}| jD ]}| D ]}| }t|r#|j}|o,|duo,| }qq|S )z4Return true if `op` is the Switch for a conditional.FTN)r%   ZoutputsZ	consumersr   r(   outer_contextIsCondContext)r   Zis_cond_switchocr   r   r   r   IsCondSwitchl   s   
r.   c                 C   sH   t | sdS | jsdS d}| jD ]}t|j}|o |duo | }q|S )z3Return true if `op` is the Merge for a conditional.FTN)r'   inputsGetOutputContextr   r+   )r   Zis_cond_mergeir   r   r   r   IsCondMerge   s   

r2   c                 C   .   t | r|  }|duo| ot|  S dS )z3Return true if `op` is the Switch for a while loop.NF)r%   r   IsWhileContextr.   r   r   r   r   IsLoopSwitch      r5   c                 C   r3   )z2Return true if `op` is the Merge for a while loop.NF)r'   r   r4   r2   r   r   r   r   IsLoopMerge   r6   r7   c                 C   s   t | o| dS )z'Return true iff op is a loop invariant.is_constant)r(   r   r$   r   r   r   IsLoopConstantEnter   s   r9   c                 C   s>   h d}| j }|j|v r|jd j }|j|v st|r|S dS )zCReturn the enter op if we can infer `value` to be a loop invariant.>   ZIdentityZRefIdentityr    r!   r   N)r   r#   r/   r9   )valueZid_opsr   r   r   r   GetLoopConstantEnter   s   

r;   c                 C   s"   |   }|durt| r|j}|S )z8Return the control flow context for the output of an op.N)r   r)   r*   r   r   r   r   r0      s   r0   c                 C   s&   | r|   s
| |kr| S | j} | sdS )a  Returns the first ancestor WhileContext of `ctxt`.

  Returns `ctxt` if `ctxt` is a WhileContext, or None if `ctxt` is not in a
  while loop.

  Args:
    ctxt: ControlFlowContext
    stop_ctxt: ControlFlowContext, optional. If provided, the search will end
      if it sees stop_ctxt.

  Returns:
    `ctxt` if `ctxt` is a WhileContext, the most nested WhileContext containing
    `ctxt`, or None if `ctxt` is not in a while loop.  If `stop_ctxt` is not
    `None`, this returns `ctxt` if it matches `stop_ctxt` in its traversal.
  N)r4   r*   )r   Z	stop_ctxtr   r   r   r      s
   r   c                 C      | r|   r| S | j} | sdS )a@  Returns the first ancestor XLAContext of `ctxt`.

  Returns `ctxt` if `ctxt` is a XLAContext, or None if `ctxt` is not in a
  while loop.

  Args:
    ctxt: ControlFlowContext

  Returns:
    `ctxt` if `ctxt` is a XLAContext, the most nested XLAContext containing
    `ctxt`, or None if `ctxt` is not in a while loop.
  N)ZIsXLAContextr*   r   r   r   r   r      s
   r   c                 C   r<   )a6  Returns the first ancestor CondContext of `ctxt`.

  Returns `ctxt` if `ctxt` is a CondContext, or None if `ctxt` is not in a cond.

  Args:
    ctxt: ControlFlowContext

  Returns:
    `ctxt` if `ctxt` is a CondContext, the most nested CondContext containing
    `ctxt`, or None if `ctxt` is not in a cond.
  N)r+   r*   r=   r   r   r   r      s
   r   c                 C   s&   | |ur| du r
dS | j } | |usdS )z>Returns true if `maybe_containing_ctxt` is or contains `ctxt`.NFT)r*   )r   Zmaybe_containing_ctxtr   r   r   IsContainingContext   s
   r>   c                 C   s   t |  |S r   )r>   r   r   r   r   r   OpInContext   s   r?   c                 C   s   t | j|S r   )r?   r   )Ztensorr   r   r   r   TensorInContext  s   r@   c           	   
   C   s  |   }t|}d}|sd}nf||u rd}n_t|}t|}|du r5|du r(d}t| r.d}t| r4d}n@t||r=d}n8|jrJt|jj|rJd}n+|jrW|jj|ju rWd}n|jrc|jj|u rcd}n|jru|jjjru|jjjj|u rud}|s|rd|j	 d| j	 d}nd|j	 d| j	 d|j	 d}|}|d	| j	|f 7 }|d
|j	|f 7 }|d| j	d
t| j|j	d
t|jf 7 }t| t|d dS )an  Returns whether `input_op` can be used from `op`s context.

  Conceptually, only inputs from op's while context or any ancestor while
  context (including outside of any context) are valid. In practice, there are
  many other edge cases as well.

  Args:
    op: Operation
    input_op: Operation

  Raises:
    ValueError: if input_op is from an invalid context.
  FTNzCannot use 'z' as input to 'z,' because they are in different while loops.z' because 'z' is in a while loop.z

%s while context: %sz
%s while context: %sz,

Traceback for %s:
%s
Traceback for %s:
%s
 z See info log for more details.)r   r0   r   r(   r%   r>   Z
grad_stateZforward_contextZ_outer_contextnamejoin	tracebackformat_listlogginginfor   )	r   Zinput_opZop_ctxtZ
input_ctxtZvalidZ
while_ctxtZinput_while_ctxt	error_msgZlog_msgr   r   r   CheckInputFromValidContext  sz   
	


rI   c                 C   s   |   }|r
| }|S )z.Get the WhileContext to which this op belongs.)r   GetWhileContextr   r   r   r   rJ   j  s   rJ   r   )%__doc__osrD   Ztensorflow.pythonr   Ztensorflow.python.platformr   rF   enabledgetenvr   r   r   r   r   r   r   r   r%   r'   r(   r)   r.   r2   r5   r7   r9   r;   r0   r   r   r   r>   r?   r@   rI   rJ   r   r   r   r   <module>   sT   		
		
d