o
    i 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_loggingTF_ENABLE_CONTROL_FLOW_V20TF_ENABLE_COND_V2TF_ENABLE_WHILE_V2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
   V/var/www/myenv/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`.	_captured)r	   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 )N_XlaCompileT)get_attr
ValueError_get_control_flow_contextGetContainingXLAContext)op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   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.MergeRefMerger+   r-   r
   r
   r   IsMerge]   r/   r2   c                 C   r(   )z!Returns true if `op` is an Enter.EnterRefEnterr+   r-   r
   r
   r   IsLoopEnterb   r/   r5   c                 C   r(   )zReturn true if `op` is an Exit.ExitRefExitr+   r-   r
   r
   r   
IsLoopExitg   r/   r8   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.   outputs	consumersr   r5   outer_contextIsCondContext)r   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)r2   inputsGetOutputContextr   r<   )r   is_cond_mergeir   r
   r
   r   IsCondMerge   s   

rE   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      rH   c                 C   rF   )z2Return true if `op` is the Merge for a while loop.NF)r2   r   rG   rE   r$   r
   r
   r   IsLoopMerge   rI   rJ   c                 C   s   t | o| dS )z'Return true iff op is a loop invariant.is_constant)r5   r   r-   r
   r
   r   IsLoopConstantEnter   s   rL   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.>   r)   Identityr*   RefIdentityr   N)r   r,   rA   rL   )valueid_opsr   r
   r
   r   GetLoopConstantEnter   s   

rQ   c                 C   s"   |   }|durt| r|j}|S )z8Return the control flow context for the output of an op.N)r   r8   r;   r$   r
   r
   r   rB      s   rB   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)rG   r;   )r   	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)IsXLAContextr;   r   r
   r
   r   r      s
   r   c                 C   rS   )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;   rU   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   maybe_containing_ctxtr
   r
   r   IsContainingContext   s
   rW   c                 C   s   t |  |S r   )rW   r   r$   r
   r
   r   OpInContext   s   rX   c                 C   s   t | j|S r   )rX   r   )tensorr   r
   r
   r   TensorInContext  s   rZ   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   rB   r#   r5   r.   rW   
grad_stateforward_context_outer_contextnamejoin	tracebackformat_listlogginginfor   )	r   input_opop_ctxt
input_ctxtvalid
while_ctxtinput_while_ctxt	error_msglog_msgr
   r
   r   CheckInputFromValidContext  st   
	

rm   c                 C   s   |   }|r
| }|S )z.Get the WhileContext to which this op belongs.)r   GetWhileContextr$   r
   r
   r   rn   j  s   rn   r   )%__doc__osra   tensorflow.pythonr   tensorflow.python.platformr   rc   enabledgetenvr	   r   r   r   r   r"   r%   r'   r.   r2   r5   r8   r@   rE   rH   rJ   rL   rQ   rB   r#   r   r&   rW   rX   rZ   rm   rn   r
   r
   r
   r   <module>   sT   		
		
d