
    BVhܵ                     .   d Z ddlZddlZddlZddlZddlmZ ddlmZ ddl	m
Z
 ddl	mZ ddl	mZ ddl	mZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlm Z  ddl!m"Z" ddl!m#Z# dZ$dZ%dZ&dZ' ejP                         Z)d Z*d Z+	 d;d Z,d! Z-d" Z.	 d<d#Z/d$ Z0d% Z1d& Z2d' Z3d( Z4d) Z5d* Z6d+ Z7d, Z8d- Z9d. Z: G d/ d0e;      Z<d1 Z=d2 Z>d3Z?d=d4Z@d5 ZAd6 ZBd7 ZCd8 ZDd9 ZEd: ZFy)>a  Control flow statements: loops, conditionals, etc.

Note: most of these operators accept pairs of get_state/set_state functions, to
capture mutations that the corresponding code blocks might make. These
mutations only need to be captured when staging the control flow, and they just
work when reverting to Python behavior.

__Examples__

```
while cond:
  self.x += i
```

When the functionalized version is executed as a Python loop, it just works:

```
def loop_body():
  self.x += i     # works as expected for Python loops
```

But it won't work for TF loops:

```
def loop_body():
  self.x += i     # self.x has the wrong value!
```

get_state/set_state allow piping the mutations through the loop variables as
well, in effect changing the loop body:

```
def loop_body(self_x):
  self.x = self_x  # self.x now has the proper value
  self.x += i      # the original block
  self_x = self.x  # write self.x back into the loop vars
  return self_x

self_x = tf.while_loop(...)
self.x = self_x    # the result is not properly captured
```
    N)py_builtins)	variables)
ag_logging)misc)tensors)type_registry)dtypes)errors_impl)
func_graph)ops)tensor_conversion)tensor_shape)tensor_util)	array_ops)cond)control_flow_assert)control_flow_util)math_ops)tensor_array_ops)
while_loop)
distribute)nest)variable_utilsi TiP     c                 z    | du xs6 t        | t        j                        xs t        | t        j                        S )zTests whether a value is None or undefined.

  AutoGraph represents undefined symbols using special objects of type Undefined
  or UndefinedReturnValue.

  Args:
    value: value to test

  Returns:
    Boolean
  N)
isinstancer   UndefinedReturnValue	Undefined)values    b/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/autograph/operators/control_flow.py_is_none_or_undefr!   f   s:     D= 4y==>4y2235    c                 >   d}t        j                  |       } | j                  t        j                  k7  rt        dj                  || |            | j                  | j                  j                  t        j                  | d      } | S | j                  j                  dkD  rt| j                  j                         D cg c]  }||	 }}t        j                  |      dkD  rt        dj                  || |            t        j                  | d      } | S c c}w )z<Ensures that the condition can be used in a TF control flow.z$to check for None, use `is not None`zdcondition of {} expected to be `tf.bool` scalar, got {}; to use as boolean Tensor, use `tf.cast`; {} r   r   z;condition of {} expected to be `tf.bool` scalar, got {}; {})r   convert_to_tensor_v2dtyper	   bool
ValueErrorformatshapendimsr   reshapeas_listnpprod)r   tag
extra_hintd
known_dimss        r    _verify_tf_conditionr4   w   s   5*		/	/	5$	ZZ6;;
	vc4,. .
 
ZZ4::++3T2&D 
+ zz!!ZZ//1CQ]!CJC	wwzQT:.0 0 tR(d	+ Ds    DDc           	         |sy|dt        |      z  }t        |      t        |       k(  sJ t        |      t        |      k(  sJ t        || |      D ]  \  }}}t        |t        j                        r5|r(t        dj                  t        t        |                  t        d      d}|dj                  |      }n5t        |t        j                        rdj                  |      }|r|d|z   z  }|t        |       y)a  Ensures that all values in the state are valid to use in a TF loop.

  The init_vars may contain placeholder values derived from first_iter_vars.

  Args:
    init_vars: initial loop variables (as taken before entering the loop)
    symbol_names: corresponding names of the initial loop variables
    first_iter_vars: loop variables after one iteration of the loop
    extra_message: an extra string to append to the error message, in case of
      "undefined variable" errors (see variables.Undefined)
  NNz@the return value from a TensorFlow loop may only be a {}; got {}za return statement cannot be placed inside this TensorFlow loop; this may happen if a return statement depends on a static Python condition such as a hyperparameterz.'{}' is not allowed to be None before the loopz$'{}' must be defined before the loop
)lenzipr   r   r   r(   r)   LEGAL_LOOP_TYPEStypeNotImplementedErrorr   )	init_varssymbol_namesfirst_iter_varsextra_messagenamevalfi_val	error_msgs           r    verify_loop_init_varsrE      s    

L 11O	\	c)n	,,	,	\	c/2	22	2|YH "dC#y556	NV$d6l35 	5
 "@A 	A
 I
{BII$Oi	C,,	-8??Ei	TM))	y!!-"r"   c                     |j                   y| j                  |j                  k7  ryt        | j                   |j                         D ]-  \  }}|j                  |j                  |j                  k7  s- y y)zBReturns True if left shape is at least as specific as right shape.TF)dimsr+   r9   r   )leftrightldimrdims       r    _is_subshaperL      sg     ZZ	ZZ5;;		5::. jdDzz$**

": 
r"   c                    |J dj                  |              |t        dj                  |             t        |t        t        t
        t        t        j                  f      rt        j                  |      }t        |t        t        t
        t        t        j                  f      rt        j                  |      }t        |t        t        t
        t        t        j                  f      rt        j                  |      }t        j                  |      rt        j                  |      syt        |d      rt        |d      syt        |d      rt        |d      sy|j                  |j                  k7  rDt        dj                  | |j                  j                   |j                  j                               |r|j"                  }|5|j"                  }t%        ||      st        dj                  | ||            y|j"                  }t%        ||      st        dj                  | ||            t%        ||      st        d	j                  | ||            yy)
zCVerifies whether the initial, entry and exit values are consistent.Nz!no TF op should set '{}' to None?z)'{}' is None at the end of the iteration.r&   r*   zC'{}' has dtype {} before the loop, but dtype {} after one iterationz'{}' has shape {} before the loop, but shape {} after one iteration. Use tf.autograph.experimental.set_loop_options to set shape invariants.zV'{}' has shape {} before the loop, which does not conform with the shape invariant {}.zZ'{}' has shape {} after one iteration, which does not conform with the shape invariant {}.)r)   r(   r   r'   intfloatstrr.   ndarrayr   r%   r   
is_tf_typehasattrr&   	TypeErrorrA   r*   rL   )	rA   check_shapeinitentryexit_shape_invariant
exit_shapeentry_shape
init_shapes	            r    _verify_single_loop_varr]      s    
	L?FFtLL	
]
@GGM
NNtS%bjj9:11$7Dc5#rzz:;2259Ec5#rzz:;2259E

 
 
'

 
 
'
 %
!
%
!

%
!
%
!

[[EKK
	VKKKK
  JKKk*k2!!'k:!FH 	H 3 ::j*o6''-vdJ.=(?@ 	@ *o6''-vdJ'P
 	
 7! r"   c           	      .   |r
d|v r|d   }nt        j                  d |      }t        |      t        |      k(  sJ t        |      t        |       k(  sJ t        |      t        |      k(  sJ t        |      t        |      k(  sJ t        t        |            D ]  }||   }| |   }	||   }
||   }||   }	 t        j                  |	|
d       	 t        j                  |
|d       |	 t        j                  |	|d       t        j                  t        j                  t        ||      |	|
||        y# t
        t        f$ re 	 t        j                  |	      }t        j                  ||
d       n3# t
        t        f$ r!}t        dj                  ||            |d}~ww xY wY w xY w# t
        t        f$ r!}t        dj                  ||            |d}~ww xY w# t
        t        f$ r!}t        dj                  ||            |d}~ww xY w)	z(Verifies loop variables for consistency.shape_invariantsc                      y r6   r$   _s    r    <lambda>z%verify_tf_loop_vars.<locals>.<lambda>      r"   Texpand_compositeszE'{}' does not have the same nested structure after one iteration.

{}NFzV'{}' does not have the same nested structure as its corresponding shape invariant.

{})r   map_structurer8   rangeassert_same_structurer(   rT   r   convert_variables_to_tensorsr)   	functoolspartialr]   )r=   iter_entry_varsiter_exit_varsr>   optscheck_shapesr_   irA   rV   rW   rX   	invariantinit_tensorses                  r    verify_tf_loop_varsru   
  sF    (D0./))./J	\	c"23	33	3	\	c)n	,,	,	\	c/2	22	2	\	c.1	11	1\"# $!a?DQ<DAE1E #ID
  uEB
  F -""4eL 	14Fui!E$! 	" 
D
D%BB4H""<$O)$ D ,,2F4O=BC	DD 	P
D 	" B **0&q/;@ABB )$ - @@F !A%&+,	--sf   9D:F1-G$:F.
-E87F.8F(F##F((F.-F.1G! GG!$H3HHc                    |t        dj                  |             |t        dj                  |             t        |t        t        t
        t        t        j                  f      rt        j                  |      }t        |t        t        t
        t        t        j                  f      rt        j                  |      }t        j                  |      rt        j                  |      syt        |d      rt        |d      sy|j                  |j                  k7  rDt        dj                  | |j                  j                   |j                  j                               y)z8Verifies whether body_var and orelse_var are consistent.Nz+'{}' is None at the end of the main branch.z+'{}' is None at the end of the else branch.r&   zE'{}' has dtype {} in the main branch, but dtype {} in the else branch)r(   r)   r   r'   rN   rO   rP   r.   rQ   r   r%   r   rR   rS   r&   rT   rA   )rA   body_var
orelse_vars      r    verify_single_cond_varry   D  s   
BII$O
PP
5<<TBD D 4eS"**=> 55h?H
T3sBJJ?@"77
CJ

 
 
*

 
 
,
 (G
$
*g
&
^^z'''
	&x~~22#))..01 1 (r"   c                     t        ||       D ]n  \  }}t        |t        j                        rt	        dj                  ||            t        |t        j                        sVt	        dj                  |             y)zBVerifies variables output by a conditional branch for consistency.z.'{}' must also be initialized in the {} branchz0the {} branch must also have a return statement.N)r9   r   r   r   r(   r)   r   )vars_r>   branch_namerA   var_s        r    _verify_tf_cond_branch_varsr~   b  s|    e, jdD$	++,
:
A
AK!" " $	667
<
C
C r"   c                    t        || |      }|D ]N  \  }}}	 t        j                  ||d       t        j                  t        j                  t        |      ||       P y# t        t        f$ r 	 t        j                  |      }t        j                  |      }t        j                  ||d       n<# t        t        f$ r*}	t	        dj                  |t        |	                  |	d}	~	ww xY wY w xY w)z@Verifies variables manipulated by a conditional for consistency.Tre   zK'{}' must have the same nested structure in the main and else branches:

{}N)r9   r   ri   r(   rT   r   rj   r)   rP   rg   rk   rl   ry   )
	body_varsorelse_varsr>   
named_varsrA   rw   rx   body_var_tensorsorelse_var_tensorsrt   s
             r    _verify_tf_cond_varsr   o  s    <K8*$. O dHj<
  :N 	0$7:O#O 	" <	<)FFxP+HH""#35G59	;)$ <%vdCF35:;	<<	;<s6   A""C42AB54C45C.%C))C..C43C4c           	      h   	 t         j                  |       } || ||||||       y# t        $ r t        }t	        j
                  |       r#t        j                  |       rt        }nHt        }nAt        | t        j                        rt        }n t        | t        j                        rt        }Y w xY w)a  Functional form of a for statement.

  The loop operates on a state, which includes all symbols that are
  variant across loop iterations, excluding the variables local to the loop.

  For example, given the loop below that calculates the geometric and
  arithmetic means or some numbers:

  ```
    geo_mean = 1
    arith_mean = 0
    for i in range(n):
      a = numbers[i]
      geo_mean *= a
      arith_mean += a
  ```

  The state is represented by the variables named geo_mean and arith_mean. The
  `extra_test`, `body`, `get_state` and `set_state` functions must bind to the
  original `geo_mean` and `arith_mean` symbols, using `nonlocal`.

  The inputs and outputs of the callables representing the loop blocks are not
  explicit - instead, these functions must use nonlocal/global for side effects.
  The inputs and outputs are instead controlled by the set_state/get_state
  functions.

  Args:
    iter_: The entity being iterated over.
    extra_test: Callable with boolean return type. An additional loop condition.
    body: Callable representing the actual loop body.
    get_state: Additional callable which can capture additional state (such as
      the values of composite symbols). This is only useful when staging the
      loop.
    set_state: Additional callable which save values captured by get_state back
      into the Python environment. This is only useful when staging the loop.
    symbol_names: Tuple containing names of the loop variables returned by
      get_state.
    opts: Optional dict of extra loop parameters.
  N)for_loop_registrylookupLookupError_py_for_stmtr   rR   r   is_range_tensor_tf_range_for_stmt_known_len_tf_for_stmtr   r   Iterator_tf_iterator_for_stmtIterable!_tf_distributed_iterable_for_stmt)iter_
extra_testbody	get_state	set_stater>   ro   for_fns           r    for_stmtr     s    R1%%e,F 	
D)YdK 
 1Fe$		 	 	'#'	E:..	/$f	E:..	/0f1s   & BB10B1c                     ~~~~	 t               }|j                  |j                           |fd}|}&fd}	 |	       r| D ]  }
 ||
        |	       r y yy| D ]
  }
 ||
        y)z5Overload of for_stmt that executes a Python for loop.c                 2     |                          y r6   r$   )protected_iterafter_iterationbefore_iterationoriginal_bodys    r    protected_bodyz$_py_for_stmt.<locals>.protected_body  s    N#r"   Nc                              } 	 t        |       S # t        j                  $ r)}t        j                  ddd       t        d      |d }~ww xY w)Nr   z1Caught error while evaluating loop stop conditionTexc_infoa+  break and return statements which depend on a TF condition are not supported in Python for loops. Did you intend to make it a TF loop?
See https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/autograph/g3doc/reference/limitations.md#consistency-of-control-flow-types for more info.r'   r
   OperatorNotAllowedInGraphErrorr   logr<   )extra_test_resultrt   r   s     r    guarded_extra_testz(_py_for_stmt.<locals>.guarded_extra_test  sj    $,H %&&77 H?	
 "@A GH	HH   
 A$AA_PythonLoopCheckerr   r   )r   r   r   r   r   r>   ro   checkerr   r   targetr   r   r   s    `         @@@r    r   r     s     L$ "G//--OM DH(  &V!#
   
6lr"   c                 ^    t        j                  t        j                               r|| d<   y y )Nmaximum_iterations)r   GraphOrParentsInXlaContextr   get_default_graph)ro   ns     r    _add_max_iterations_hintr     s*    11#2G2G2IJ!"D	 Kr"   c                     t        j                         t        j                   j                        }|j                          dfd}fd}	 fd}
fd}t        |       t        ||
||	d|z   |       y)	zHOverload of for_stmt that iterates over TF entities that admit a length.)sizer   c                      f         z   S r6   r$   )r   iterate_indexs   r    aug_get_statez-_known_len_tf_for_stmt.<locals>.aug_get_state
  s    ik))r"   c                     | ^} |       y r6   r$   )aug_loop_vars	loop_varsr   r   s     r    aug_set_statez-_known_len_tf_for_stmt.<locals>.aug_set_state  s     !.MI ir"   c                  >      j                               dz  y Nr   )read)r   r   r   s   r    aug_bodyz(_known_len_tf_for_stmt.<locals>.aug_body  s    M	"#QMr"   c                  F    k  } t        j                  | d       S | S )Nc                       yNFr$   r$   r"   r    rc   z:_known_len_tf_for_stmt.<locals>.aug_test.<locals>.<lambda>  rd   r"   tf_condr   )	main_testr   r   r   s    r    aug_testz(_known_len_tf_for_stmt.<locals>.aug_test  s,    !I\\)Z??r"   z<internal iterate>N)r   len_r   TensorArrayr&   unstackr   _tf_while_stmt)r   r   r   r   r   r>   ro   tar   r   r   r   r   r   s   `````       @@r    r   r     s     u!
 ##EKKa8"
**U
%-*
 4#,
r"   c           
      @   | j                   j                  \  }|fdfd}fd}	fd}
fd}t        t        j                  t        j                  |      t        j                               t        ||
||	dz          y)zCOverload of for_stmt that iterates over a TF range (and elides it).c                 P    | d   k(  rt        |t        j                        r|S |S )Niterate_names)r   r   r   )rA   vardefaultro   s      r    	_value_orz%_tf_range_for_stmt.<locals>._value_or3  s)    _%%*S):M:M*NnJr"   c                  \            } t        fdt        |       D              } f| z   S )Nc              3   8   K   | ]  \  }} ||        y wr6   r$   ).0rA   r   r   iterates      r    	<genexpr>z<_tf_range_for_stmt.<locals>.aug_get_state.<locals>.<genexpr>:  s&      8D# 	$W%8s   )tupler9   )
state_varsr   r   r   r>   s    r    r   z)_tf_range_for_stmt.<locals>.aug_get_state8  s7    J 8\:68 8J :
""r"   c                     | ^} |       y r6   r$   )r   r   r   r   s     r    r   z)_tf_range_for_stmt.<locals>.aug_set_state?  s     (Gi ir"   c                                z  y r6   r$   )r   deltar   s   r    r   z$_tf_range_for_stmt.<locals>.aug_bodyG  s    MuGr"   c                      t        j                        } | | dk\  rk  }nPkD  }nJt        j                  t        j                  dk\  k        t        j                  dk  kD              }t        j                  |d       }|S )Nr   c                       yr   r$   r$   r"   r    rc   z6_tf_range_for_stmt.<locals>.aug_test.<locals>.<lambda>Z  rd   r"   )r   constant_valuer   
logical_orlogical_andr   r   )const_deltar   r   r   r   limits     r    r   z$_tf_range_for_stmt.<locals>.aug_testL  s    ,,U3K		eO	eO	%%


uz7U?
;


uqy'E/
:<i ,,y*mDir"   r   N)
opinputsr   r   castr   get_range_lenr	   int32r   )r   r   r   r   r   r>   ro   startr   r   r   r   r   r   r   r   s    ``````     @@@@r    r   r   ,  s     %'
#
" 
mmD&&ueU;V\\JL ,
r"   c                     	
 dz   dfd	fd
 	       t               	
 fd}fd}t        ||	
       y)zCOverload of for_stmt that iterates over TF Iterators. See for_loop.)z<internal has_next>Tc                      f         z   S r6   r$   )r   has_nexts   r    r   z,_tf_iterator_for_stmt.<locals>.aug_get_statep  s    ;$$r"   c                     | ^} |       y r6   r$   )r   r   r   r   s     r    r   z,_tf_iterator_for_stmt.<locals>.aug_set_states  s     )Hyir"   c                      	j                         j                                 
fd} fd} t        j                  | |             y)z#Main body passed to _tf_while_stmt.c                  `     j                                        } t        |        | S r6   )	get_valueru   )new_loop_varsr   r   r=   r   opt_iteratero   r>   s    r    	main_pathz:_tf_iterator_for_stmt.<locals>.aug_body.<locals>.main_path  s7    
;  "##om 
Y|TCr"   c                       S r6   r$   )r   s   r    	noop_pathz:_tf_iterator_for_stmt.<locals>.aug_body.<locals>.noop_path  s	    r"   N)get_next_as_optional	has_valuer   r   )r   r   r   r   r   r   r   r   r=   r   ro   r>   s     @@r    r   z'_tf_iterator_for_stmt.<locals>.aug_body|  sQ     ,,.K$$&HI  Xy)46r"   c                  @    } t        j                  | d       S | S )Nc                       yr   r$   r$   r"   r    rc   z9_tf_iterator_for_stmt.<locals>.aug_test.<locals>.<lambda>  rd   r"   r   )r   r   r   s    r    r   z'_tf_iterator_for_stmt.<locals>.aug_test  s)     I\\)Z??r"   N)rE   r   )r   r   r   r   r   r>   ro   r   r   r   r   r   r=   s   ```````  @@@@r    r   r   j  s]     *L8,(% o)	<06 64 
r"   c                     |t        d              t               dv rt        d         d<   fd} | j                  |             y)z@Overload of for_stmt that iterates over TF distributed datasets.NzXbreak and return statements are not yet supported in for ... in distributed input loops.r_   c                 T     |         |               }t        | |       |S r6   ru   )	r   r   r   r   r   r=   ro   r   r>   s	      r    reduce_bodyz6_tf_distributed_iterable_for_stmt.<locals>.reduce_body  s3    iMKM9m\4Ar"   )r<   rE   ,_shape_invariants_mapping_to_positional_listreduce)	r   r   r   r   r   r>   ro   r   r=   s	     ````` @r    r   r     sr     
	./ / k)	<04K ) -D	  ELLK01r"   c                     t        j                  d      j                         5   |        }ddd       t        j                        rt        | |||||       y|sy |        t        | ||||       y# 1 sw Y   IxY w)a  Functional form of a while statement.

  The loop operates on a so-called state, which includes all symbols that are
  variant across loop iterations. In what follows we refer to state as either
  a tuple of entities that represent an actual state, or a list of arguments
  of the corresponding types.

  The inputs and outputs of the callables representing the loop blocks are not
  explicit - instead, these functions must use nonlocal/global for side effects.
  The inputs and outputs are instead controlled by the set_state/get_state
  functions.

  Args:
    test: Callable with boolean return type. The loop condition.
    body: Callable representing the actual loop body.
    get_state: Additional callable which can capture additional state (such as
      the values of composite symbols). This is only useful when staging the
      loop.
    set_state: Additional callable which save values captured by get_state back
      into the Python environment. This is only useful when staging the loop.
    symbol_names: Tuple containing the names of all loop variables.
    opts: Optional dict of extra loop parameters.

  Returns:
    Tuple containing the final state.
  tmpN)r   	FuncGraph
as_defaultr   is_dense_tensorr   _py_while_stmt)testr   r   r   r>   ro   	init_tests          r    
while_stmtr    sy    > E"--/ I
 Y'4y)\4H

 

&tY	48! s   A44A=c                   >    e Zd ZdZdZd Zd Zd Zd Zd Z	d Z
d	 Zy
)r   z-Verifies Python loops for TF-specific limits.)
iterationscheck_inefficient_unrollcheck_op_count_after_iterationops_before_iterationc                 6    d| _         t        | _        d| _        y )Nr   F)r
  WARN_INEFFICIENT_UNROLLr  r  selfs    r    __init__z_PythonLoopChecker.__init__  s    DO$;D! +0D'r"   c                 X    t        t        j                         j                               S r6   )setr   r   get_operationsr  s    r    _get_opsz_PythonLoopChecker._get_ops  s    s$$&55788r"   c                 @    | j                   t        kD  rt        d      y )Nziteration limit exceeded)r
  PYTHON_MAX_ITERATIONSr(   r  s    r    _check_unroll_limitsz'_PythonLoopChecker._check_unroll_limits	  s     ..122 /r"   c                 .    d| _         d| _        d | _        y r   )r  r  r  r  s    r    !_stop_checking_inefficient_unrollz4_PythonLoopChecker._stop_checking_inefficient_unroll  s    $)D!*/D' $Dr"   c           	           j                   J  j                         }t         fd|D              }t        |      t        k  ryt        j                  d j                  |dj                  t        j                                      y)zAChecks for possibly-inefficient creation of ops in a Python loop.c              3   @   K   | ]  }|j                   vs|  y wr6   )r  )r   r   r  s     r    r   z@_PythonLoopChecker._verify_inefficient_unroll.<locals>.<genexpr>  s%      QBd6O6O,OQs   Fa  Large unrolled loop detected. Did you mean to use a TF loop? The following ops were created after iteration %s: %s
See https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/autograph/g3doc/reference/common_errors.md#warning-large-unrolled-loop-detected
Location:
%sr7   T)r  r  r   r8   INEFFICIENT_UNROLL_MIN_OPSr   warningr
  join	tracebackformat_stack)r  ops_after_iterationnew_opss   `  r    _verify_inefficient_unrollz-_PythonLoopChecker._verify_inefficient_unroll  s    $$000--/ Q(Q QG 7|00		 OOWdii	0F0F0H&I
K r"   c                 ~    | j                   r1| j                  t        kD  r| j                         | _        d| _        yyy)z.Called before each iteration in a Python loop.TN)r  r
  !INEFFICIENT_UNROLL_MIN_ITERATIONSr  r  r  r  s    r    r   z#_PythonLoopChecker.before_iteration)  s8    %%;;"&--/d,0d) 	< 	&r"   c                     | xj                   dz  c_         | j                          | j                  rK| j                         }|r| j	                          y| j                   t
        dz   kD  r| j	                          yyy)z-Called after each iteration in a Python loop.r      N)r
  r  r  r%  r  r'  )r  did_warns     r    r   z"_PythonLoopChecker.after_iteration0  sk    OOqO**002h	..0??>BB..0 C	 +r"   N)__name__
__module____qualname____doc__	__slots__r  r  r  r  r%  r   r   r$   r"   r    r   r     s/    5)093%
.11r"   r   c                     	
 ~~~	 t               }|j                  	|j                   	        |
	
fd}|} fd} |       r |         |       ryy)z9Overload of while_stmt that executes a Python while loop.c                  0                                y r6   r$   )r   r   r   s   r    r   z&_py_while_stmt.<locals>.protected_bodyJ  s    or"   c                              } 	 t        |       S # t        j                  $ r)}t        j                  ddd       t        d      |d }~ww xY w)Nr   z2Caught error while evaluating while loop conditionTr   a  The condition of while loop started as non-Tensor, then changed to Tensor. This may happen either because variables changed type, or when a break or return statement inside the loop depends on a Tensor condition. In both cases, changing to a TF loop should remove the error.
See https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/autograph/g3doc/reference/limitations.md#consistency-of-control-flow-types for more info.r   )test_resultrt   r  s     r    guarded_testz$_py_while_stmt.<locals>.guarded_testP  sf    &KF +55 Fnn

>
  >? EFFFr   Nr   )r  r   r   r   ro   r   r   r4  r   r   r   s   `       @@@r    r  r  ?  s\    
Iy "G//--OM DF* 	F 	r"   c                 
   | D ci c]  \  }}t        |      ||f } }}g }|D ]L  }| j                  t        |      d      \  }}|j                  ||u r|nt        j                  d |             N t        |      S c c}}w )NNNc                      y r6   r$   ra   s    r    rc   z>_shape_invariants_mapping_to_positional_list.<locals>.<lambda>p  rd   r"   )idgetappendr   rg   r   )mappingkeyskvresultmap_keymap_vals          r    r   r   i  s    './tq!RUQF]/'/& La{{2a5,7GW
MMa<T%7%7%JLL 
v 0s   A?z9Tensor, int, float, bool or a list, tuple or dict thereofc                 X   | |dfS t        | t        j                  t        j                  f      r|dfS t        | t        t
        t        f      r t        |       d      dfS t        j                  |       rE||n| j                  }||j                  "t        j                  d| j                        |fS g }d}t        | j                  |      D ]  \  }}|d}n8t        |t         j"                        r|j$                  d}n|j$                  }n|}||j'                  |       d}Yt        |t         j"                        r<|j$                  |j'                  |       d}|j'                  |j$                         |j'                  |        |r|}	nd}	t        j                  || j                        |	fS t        | t(        t*        t,        f      r|+t/        j0                  d t/        j2                  |             }
nAt/        j0                  t4        t/        j2                  |       t/        j2                  |            }
t        |
 \  }}t/        j6                  | |      t/        j6                  | |      fS t9        dj;                  t        |       j<                  |             )a  Constructs a (dummy) placeholder value for a loop-initialized variable.

  Args:
    like: Any object. The value created by the first iteration of the loop. If a
      Python scalar, the placeholder will be the zero value of that type. If a
      Tensor, the placeholder will be a zero tensor of matching shape and dtype.
      If a list, dict or tuple, the placeholder will be an identical structure
      of placeholders.
    shape_invariant: The shape invariant specified by the user (or None, if
      nothing was specified) for the respective variable.
    original: Any object. The value of the variable prior to entering the loop.
      Typically, this is one of the special "Undefined" value, because that's
      when a placeholder is needed.

  Returns:
    Either a zero value of structure, shape and dtype matching 'like', or
    'original', if no such zero value could be created.
  Nr   r$   FTc                     t        | d       S r6   _placeholder_valuer>  s    r    rc   z$_placeholder_value.<locals>.<lambda>  s    ,>q$,G r"   zFound an unsupported type '{}' while creating placeholder for {}. Supported types include Tensor, int, float, bool, list, tuple or dict.)r   r   r   r   rN   rO   r'   r;   r   rR   r*   rankr   zerosr&   r9   r   	Dimensionr   r:  listr   dictr   rg   flattenrE  pack_sequence_asrT   r)   r+  )likerY   original
like_shapeplaceholder_shapehas_dynamic_dimssrq   like_dimrr   zippedvalsinvarss                r    rE  rE  z  sa   & 
\T>$,,i.L.LMNT>$eT*+4:a=$d#$3$?TZZJZ__4__R,j88 DJJ
+ $1	
a//077?(WW(	
  *a//077?

"
"8
,!


"
"177
+  #+$. ii??,djj99DD$ud+,!!"G"&,,t"46f !!"4dll46H"&,,"?Af<LD&!!$"&()-)>)>tV)LN N 	Pvd4j!!4(	* *r"   c           	      p   d}d}d}		 t        j                  d      j                         5  d }
t        j                  |
|      } ||       d} |          |       }ddd       t        d t        ||||      D              }t        | \  }}d}|r	 ||       	 t#        ||||	       |fS # 1 sw Y   SxY w# t        t        t        t        f$ rQ t        j                  ddd	       t        j                         }d
j                  |d   j                   |d         }	Y w xY w# |r	 ||       w w xY w)ap  Makes a best-effort attempt to substitute undefineds with placeholders.

  Note: this substitution requires two things to happen:
   1. the types of loop variables could be inferred (usually by staging one
       iteration)
   2. these types could be replaced by placeholders (e.g. zero values, for
       tensors).

  Args:
    body: a function representing the loop body. See while_stmt.
    get_state: state getter for the loop statement. See while_stmt.
    set_state: state getter for the loop statement. See while_stmt.
    init_vars: loop variables before entering the loop. See while_stmt.
    nulls: list of boolean flags indicating whether the corresponding loop var
      is None or undefined.
    shape_invariants: user-specified shape invariant for each loop variable.
    symbol_names: list of loop variable names. See while_stmt.

  Returns:
    A tuple (success, new_init_vars, extra_shape_invariants, failure_message):
     * success is a boolean flag indicating
       whether types could be successfully inferred (step 1 above)
     * new_init_vars contains the loop vars, with None or undefined values
       replaced by default values, where possible (step 2 above)
     * extra_shape_invariants contains shape invariants that would be needed
       by while_stmt, for instance if the placeholder values had a shape
       different from the corresponding loop outputs
  FNr  c                    t        | t        t        t        t        t
        t        t        j                  t        j                  f      r?t        j                  |       }t        j                  |j                  |j                        S | S r6   )r   rN   rO   r'   rP   rJ  r   r.   rQ   genericr   r%   r   placeholderr&   r*   )r>  init_vals     r    autocast_to_tensorz4_try_handling_undefineds.<locals>.autocast_to_tensor  sY    UD#tUBJJ

KM&;;A>(&&x~~x~~F
Fr"   Tc              3   L   K   | ]  \  }}}}|rt        |||      n|d f  y wr6   rD  )r   r>  r   ivrq   s        r    r   z+_try_handling_undefineds.<locals>.<genexpr>
  s5      !2Aq"a *+	B1	%D		9!2s   "$r   z$Caught error while staging loop bodyr   zGNote: AutoGraph tried to define it automatically, but ran into a {}: {}r   )r@   )r   r  r  r   rg   r   r9   UnboundLocalErrorrT   r(   KeyErrorr   r   sysr   r)   r+  rE   )r   r   r   r=   nullsr_   r>   state_modifiedr?   failure_messager]  autocast_init_varsinits_and_invariantsextra_shape_invariantssuccessexcs                   r    _try_handling_undefinedsrk    sW   < .//*			e	$	/	/	1 $  --.@)L"#n
f!o#$, ! !2y%/1!2 2 ),-A(B%I%G 	 oO 
)3	33]$ $: Y
H	= 3NN1<tL ,,.C	&Q#a&1 3 	 s;   #B; 2B/3B; /B84B; ;A'D%"D( $D%%D( (D5c                     g }t        | ||      D ]F  \  }}}|s
t        |t        j                        r|j	                  d       6|j	                  |       H dj                  |      }dj                  |      S )zFCreates an error message asking for the loop to iterate at least once.zthe function return valuez, z0loop must iterate at least once to initialize {})r9   r   r   r   r:  r   r)   )r>   rc  r=   	var_namessnr   r>  s          r    _runtime_zero_iterations_errmsgro  %  sy    )lE95 hb!Q!Y33423r ii	")	;	B	B9	MMr"   c           
                  }t        d D              }t        |      rYj                  dd      D 	ci c]  \  }}	t        |      |	 c}	}t        fd|D              }
t	        ||
      \  }ndrst              t        |      D ]2  \  }}}j                  t        |      |      }|%|t        |      <   4 t        fdD              rt        di d<    fd}fd	}dv rt        d         d<   t              }|j                  d
d       d|d<   rdz   }d|v rd|d   z   |d<   n}t        j                  |||fi |}r\t        j                  t        j                  |d   t        ||      g      g      5  t        j                   d |dd       }ddd        |       yc c}	}w # 1 sw Y   xY w)z3Overload of while_stmt that stages a TF while_stmt.c              3   2   K   | ]  }t        |        y wr6   )r!   )r   r>  s     r    r   z!_tf_while_stmt.<locals>.<genexpr>8  s     8!!$8s   r_   r$   c              3   T   K   | ]  }j                  t        |      d        ! y wr6   )r9  r8  )r   r>  shape_invars_by_init_valss     r    r   z!_tf_while_stmt.<locals>.<genexpr>=  s*      L78!%%beT2Ls   %(FNc              3   X   K   | ]!  }t        |      v r|t        |         f # y wr6   )r8  )r   nvmerged_shape_invariantss     r    r   z!_tf_while_stmt.<locals>.<genexpr>Q  s7      $J(*')"v1H'H &()@B)H$I $Js   '*c                  D    r| dd  }  |        t                d      S )Nr   z
while loop)r4   )r   require_one_iterationr   r  s    r    r   z _tf_while_stmt.<locals>.aug_testX  s(    AB-ii55r"   c                  n    r| dd  }  |                         }t        | |       rd|z   }|S )Nr   Tr   )	r   r   r   r   r=   ro   rx  r   r>   s	     r    r   z _tf_while_stmt.<locals>.aug_body_  sN    AB-iiFKM9m\4A -mr"   r   Treturn_same_structure)Fr6   r   c                 Z    t        j                  |       rt        j                  |       S | S r6   )r   rR   r   identityrF  s    r    rc   z _tf_while_stmt.<locals>.<lambda>  s"    k.D.DQ.GY''* Q r"   r   )r   anyr9  r8  rk  rK  r9   r   popr   r   control_dependenciesr   Assertro  r   rg   )r  r   r   r   r>   ro   orig_init_varsrc  r>  rq   r_   rh  ru  nimerged_invariantr   r   while_loop_optsaug_init_varsfinal_loop_varsr=   rv  rx  rs  s   ``````              @@@@r    r   r   3  sj   k).
8i8
8%Z!XX&8"=!Q1q!  L<JL L  8i8A98=?O8D FI
 ""#<=
 4JK ;	2r044RUB?		%*:2'; $ $J.7$J J \D\d!8d6  4K ) -D	 J/ot, .2/)*y(M_,
O$67
7 () M))(Hm =,;=/ 		!	!""?1#5+L%P8
 	# 
 
 **
O
!"
o Ok!V s   G#7G))G2c           	      l    t        j                  |       rt        | ||||||       yt        | ||       y)a  Functional form of an if statement.

  The conditional operates on a state, which includes all symbols whose values
  are a function of the branch taken.

  For example, given the code below that calculates the abs function:

  ```
    x = 1
    if x > 0:
      x = -x
  ```

  The state is represented by the variable `x`. The `body, `orelse` and
  `set_state` functions must bind to the original `x` symbol, using `nonlocal`.

  The inputs and outputs of the callables representing the loop blocks are not
  explicit - instead, these functions must use nonlocal/global for side effects.
  The inputs and outputs are instead controlled by the set_state/get_state
  functions.

  Args:
    cond: Boolean.
    body: Callable representing the main block of the conditional.
    orelse: Callable representing the else block of the conditional.
    get_state: Function that returns a tuple containing the values of all
      composite symbols modified within the conditional. This allows access to
      state that branches may mutate through side effects. This function is not
      needed and should not be called when dispatching to code matching Python's
      default semantics. This is useful for checkpointing to avoid unintended
      side-effects when staging requires evaluating all code-paths.
    set_state: Function to set the values of all composite symbols modified
      within the conditional. This is the complement to get_state, used to
      restore checkpointed values. The single argument a tuple containing values
      for each composite symbol that may be modified in a branch of the
      conditional. The is usually the result of a call to get_state.
    symbol_names: Tuple containing basic loop var names.
    nouts: Number of variables output by the statement. Vars which are not
      outputs will not be passed through staged control flow such as tf.cond.
      This includes variables that are defined before the conditional, but are
      not used after it.
  N)r   r  _tf_if_stmt_py_if_stmt)r   r   orelser   r   r>   noutss          r    if_stmtr    s3    X T"dFIy,NdF#r"   c                    
 t        | d      } scfdfddz  d        
dgdg
fd}
fd}t        j                  | ||d	
      }	|	
d z   }	 |	       y)z*Overload of if_stmt that stages a TF cond.zif statementc                      d         z   S )N)r   r$   )prev_get_states   r    rc   z_tf_if_stmt.<locals>.<lambda>  s    ~// r"   c                      | dd        S r   r$   )r>  prev_set_states    r    rc   z_tf_if_stmt.<locals>.<lambda>  s    .12/ r"   )z<unused dummy>r   Nc                                               } | d  } | d<   t        | d       d   t        | d          | S )Nr   mainr~   r   )	new_body_varsr   r   r=   new_body_vars_new_orelse_vars_r  r   r>   s	    r    r   z_tf_if_stmt.<locals>.aug_body  s\    iFKM!&5)M%N1|VD&=*:1*=|Lr"   c                                               } | d  } | d<   t        | d       d   t        d   |        | S )Nr   elser  )	new_orelse_varsr   r=   r  r  r  r  r   r>   s	    r    
aug_orelsez_tf_if_stmt.<locals>.aug_orelse  s\    i
HkO%fu-O)QvFa$>!,o|Lr"   T)strict)r4   r   r   )r   r   r  r   r   r>   r  r   r  final_cond_varsr=   r  r  r  r  s    ``````   @@@@@r    r  r    s     
dN	3$	%.	"NN/I/I''LEk) 6.V	 		 	 LL
Hj//#i&77/Or"   c                 "    | r |       S  |       S )z8Overload of if_stmt that executes a Python if statement.r$   )r   r   r  s      r    r  r    s    %VX%r"   r6  rz  r6   )Gr.  rk   rb  r!  numpyr.   %tensorflow.python.autograph.operatorsr   r   !tensorflow.python.autograph.utilsr   r   r   r   tensorflow.python.frameworkr	   r
   r   r   r   r   r   tensorflow.python.opsr   r   r   r   r   r   r   r   tensorflow.python.typesr   tensorflow.python.utilr   r   r  r  r'  r  TypeRegistryr   r!   r4   rE   rL   r]   ru   ry   r~   r   r   r   r   r   r   r   r   r  objectr   r  r   r:   rE  rk  ro  r   r  r  r  r$   r"   r    <module>r     sF  )V  
   = ; 8 2 5 ; . 3 2 + 9 4 3 + 1 5 3 * 2 , . ' 1 "  $) !  /M..0 5"8 BF+"\"6
~ 7!t1<
O29Lx0f#,^;|;|26/9dG1 G1T'T O S*lR4jN\~/$d-`&r"   