
    AVh@                        d 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  edg      ej<                   ej>                  dddd      	 	 	 	 	 	 dd                     Z  edg       ej<                  d d              Z!d Z"d Z#d Z$y)!z*Cond function for Control Flow Operations.    )context)eager_function_run)dtypes)indexed_slices)ops)tensor)tensor_util)	array_ops)cond_v2)control_flow_ops)control_flow_util)math_ops)
tf_logging)core)deprecation)dispatch)nest)	tf_exportcond)v1NzBfn1/fn2 are deprecated in favor of the true_fn/false_fn arguments.fn1fn2c           	         ||t        d      |}n|t        d      ||t        d      |}n|t        d      t        |      st        d      t        |      st        d      t        j                         rt	        | ||||      S t        j                  t        j                               rt        j                  | |||      S t        j                  |d| g      5  t        | t              rt        d	      t        j                  | |       \  }}t        j                   |d
      }	t        j                   |d      }
t        j                   | d      } |||	|
| fD ]1  }|j"                  j$                  j'                  |j"                         3 t        j(                  | |	d      }	 |j+                          |j-                  |      \  }}|t/        d      |j1                  |       |j3                          t        j(                  | |
d      }	 |j+                          |j-                  |      \  }}|t/        d      |j1                  |       |j3                          |st5        |      }t5        |      }	 t7        j8                  ||d       |st/        d      t7        j>                  |d      }t7        j>                  |d      }tA        ||      D ]  \  }}t        |tB        jD                        rt        |tB        jD                        sJ |jF                  jH                  |jF                  jH                  k7  sjt/        d|jF                  jJ                   d|jF                  jJ                   d       tA        ||      D cg c]  }t        jL                  |      d    }}t7        j:                  t        jN                  t7        j>                  |d      |      }|jP                  |jP                  k(  sJ |jP                  \t        jR                  t        jT                  jV                  |       t        jR                  t        jT                  jV                  |       t7        jX                  ||d      }|st5        |      }|cddd       S # |j3                          w xY w# |j3                          w xY w# t         t.        f$ r t7        j:                  t<        ||       t7        j:                  t<        ||       	 t7        j8                  ||d       n9# t         $ r}t        d|       d}~wt.        $ r}t/        d|       d}~ww xY wY w xY wc c}w # 1 sw Y   yxY w)ah
  Return `true_fn()` if the predicate `pred` is true else `false_fn()`.

  `true_fn` and `false_fn` both return lists of output tensors. `true_fn` and
  `false_fn` must have the same non-zero number and type of outputs.

  **WARNING**: Any Tensors or Operations created outside of `true_fn` and
  `false_fn` will be executed regardless of which branch is selected at runtime.

  Although this behavior is consistent with the dataflow model of TensorFlow,
  it has frequently surprised users who expected a lazier semantics.
  Consider the following simple program:

  ```python
  z = tf.multiply(a, b)
  result = tf.cond(x < y, lambda: tf.add(x, z), lambda: tf.square(y))
  ```

  If `x < y`, the `tf.add` operation will be executed and `tf.square`
  operation will not be executed. Since `z` is needed for at least one
  branch of the `cond`, the `tf.multiply` operation is always executed,
  unconditionally.

  Note that `cond` calls `true_fn` and `false_fn` *exactly once* (inside the
  call to `cond`, and not at all during `Session.run()`). `cond`
  stitches together the graph fragments created during the `true_fn` and
  `false_fn` calls with some additional graph nodes to ensure that the right
  branch gets executed depending on the value of `pred`.

  `tf.cond` supports nested structures as implemented in
  `tensorflow.python.util.nest`. Both `true_fn` and `false_fn` must return the
  same (possibly nested) value structure of lists, tuples, and/or named tuples.
  Singleton lists and tuples form the only exceptions to this: when returned by
  `true_fn` and/or `false_fn`, they are implicitly unpacked to single values.
  This behavior is disabled by passing `strict=True`.

  Args:
    pred: A scalar determining whether to return the result of `true_fn` or
      `false_fn`.
    true_fn: The callable to be performed if pred is true.
    false_fn: The callable to be performed if pred is false.
    strict: A boolean that enables/disables 'strict' mode; see above.
    name: Optional name prefix for the returned tensors.

  Returns:
    Tensors returned by the call to either `true_fn` or `false_fn`. If the
    callables return a singleton list, the element is extracted from the list.

  Raises:
    TypeError: if `true_fn` or `false_fn` is not callable.
    ValueError: if `true_fn` and `false_fn` do not return the same number of
      tensors, or return tensors of different types.

  Example:

  ```python
  x = tf.constant(2)
  y = tf.constant(5)
  def f1(): return tf.multiply(x, 17)
  def f2(): return tf.add(y, 23)
  r = tf.cond(tf.less(x, y), f1, f2)
  # r is set to f1().
  # Operations in f2 (e.g., tf.add) are not executed.
  ```

  Nz:cond(): 'true_fn' and 'fn1' may not be set simultaneously.z#cond(): 'true_fn' argument requiredz;cond(): 'false_fn' and 'fn2' may not be set simultaneously.z$cond(): 'false_fn' argument requiredz'true_fn' must be callable.z'false_fn' must be callable.r   z!'pred' must not be a Python bool.switch_t)nameswitch_fpred_id   )branchz#'true_fn' must have a return value.r   z$'false_fn' must have a return value.T)expand_compositesz7Incompatible return types of 'true_fn' and 'false_fn': z8Incompatible return values of 'true_fn' and 'false_fn': z9'true_fn' and 'false_fn' must return at least one result.zIOutputs of 'true_fn' and 'false_fn' must have the same type(s). Received z from 'true_fn' and z from 'false_fn'.)	structureflat_sequencer    )-	TypeErrorcallabler   executing_eagerly_eager_cond_implementationutilEnableControlFlowV2r   get_default_graphr   
name_scope
isinstanceboolr   switchr
   identityopgraphprevent_fetchingCondContextEnterBuildCondBranch
ValueError
ExitResultExit_UnpackIfSingletonr   assert_same_structuremap_structure_cast_indexed_slice_indicesflattenzip
tensor_libTensordtype
base_dtyper   merge_convert_flow_to_tensorarrayouter_contextadd_to_collection	GraphKeysCOND_CONTEXTpack_sequence_as)predtrue_fnfalse_fnstrictr   r   r   p_2p_1pivot_1pivot_2r   	context_t
orig_res_tres_t	context_f
orig_res_fres_fe
res_t_flat
res_f_flatxypairmergess                            J/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/ops/cond.pyr   r   '   s%   d 	_
FH HG
9
::_
GI IH
:
;;	'	
1
22	(	
2
33 %dGXvtLL 
c3356??4(D99
~~dFTF+ \$9::&&tT2HC  :6G  :6Gd3DWgt4 2iioo&&vyy12 !,,T71EIoo#33G<j%		>??5!nn !,,T71EIoo#33H=j%		?@@5!nn%j1j%j1jL
  Z4P 
EG G et<Jet<Jj*- 4A
Q
))
*J--.0/	
		qww11	1~ &77<<. 134 	44 58
J4OQ,0t$Q'QF Q55Z48F ""i&=&====&	CMM66	B	CMM66	B""FdLF !&)fy\ \* nn nn z" L
4j*M
4eUCL"":z59	; KEaSIK 	K LFqcJL 	LL	;	L>QQ\ \s   %CU73AR)5(U7AR> (U7	S!B0U7A	U7U2:C%U7)R;;U7>SU7AU/T21U/2	U(;U		U(U##U((U/+U7.U//U77V c                 "    t        | ||d|      S )a   Return `true_fn()` if the predicate `pred` is true else `false_fn()`.

  Note: This op is automatically used in a `tf.function` to convert Python
  if-statements when the predicate is a `tf.Tensor`, unless `autograph=False` is
  explicitly specified in `tf.function` args. For example, the following are
  equivalent:

  >>> @tf.function
  ... def fun1(x,y):
  ...   if x > 0:  # AutoGraph converts if-statement to tf.cond().
  ...     z = y+1
  ...   else:
  ...     z = y-1
  ...   return z
  >>> print(fun1(tf.constant(7), tf.constant(3)).numpy())
  4

  >>> @tf.function
  ... def fun2(x,y):
  ...   pred = x > 0
  ...   true_fn =  lambda: y+1
  ...   false_fn = lambda: y-1
  ...   return tf.cond(pred, true_fn, false_fn)  # Use tf.cond() explicitly.
  >>> print(fun1(tf.constant(7), tf.constant(3)).numpy())
  4

  For more information, see [tf.function and AutoGraph guide](
  https://www.tensorflow.org/guide/function#autograph_transformations).

  `true_fn` and `false_fn` both return lists of output tensors. `true_fn` and
  `false_fn` must have the same non-zero number and type of outputs.

  **WARNING**: Any Tensors or Operations created outside of `true_fn` and
  `false_fn` will be executed regardless of which branch is selected at runtime.

  Although this behavior is consistent with the dataflow model of TensorFlow,
  it has frequently surprised users who expected a lazier semantics.
  Consider the following simple program:

  >>> x, y = tf.constant(2, dtype=tf.int32), tf.constant(4, dtype=tf.int32)
  >>> z = tf.multiply(x, y)
  >>> r = tf.cond(x < y, lambda: tf.add(x, z), lambda: tf.square(y))
  >>> print(r.numpy())
  10

  If `x < y`, the `tf.add` operation will be executed and `tf.square`
  operation will not be executed. Since `z` is needed for at least one
  branch of the `cond`, the `tf.multiply` operation is always executed,
  unconditionally.

  Note that `cond` calls `true_fn` and `false_fn` *exactly once* (inside the
  call to `cond`, and not at all during `Session.run()`). `cond`
  stitches together the graph fragments created during the `true_fn` and
  `false_fn` calls with some additional graph nodes to ensure that the right
  branch gets executed depending on the value of `pred`.

  `tf.cond` supports nested structures as implemented in
  `tensorflow.python.util.nest`. Both `true_fn` and `false_fn` must return the
  same (possibly nested) value structure of lists, tuples, and/or named tuples.
  Singleton lists and tuples form the only exceptions to this: when returned by
  `true_fn` and/or `false_fn`, they are implicitly unpacked to single values.

  Note: It is illegal to "directly" use tensors created inside a cond branch
  outside it, e.g. by storing a reference to a branch tensor in the python
  state. If you need to use a tensor created in a branch function you should
  return it as an output of the branch function and use the output from
  `tf.cond` instead.

  Args:
    pred: A scalar determining whether to return the result of `true_fn` or
      `false_fn`.
    true_fn: The callable to be performed if pred is true.
    false_fn: The callable to be performed if pred is false.
    name: Optional name prefix for the returned tensors.

  Returns:
    Tensors returned by the call to either `true_fn` or `false_fn`. If the
    callables return a singleton list, the element is extracted from the list.

  Raises:
    TypeError: if `true_fn` or `false_fn` is not callable.
    ValueError: if `true_fn` and `false_fn` do not return the same number of
      tensors, or return tensors of different types.

  Example:

  >>> x = tf.constant(2)
  >>> y = tf.constant(5)
  >>> def f1(): return tf.multiply(x, 7)
  >>> def f2(): return tf.add(y, 3)
  >>> r = tf.cond(tf.less(x, y), f1, f2)
  >>> # r is set to f1().
  >>> # Operations in f2 (e.g., tf.add) are not executed.
  >>> print(r.numpy())
  14

  T)rJ   rK   rL   r   )r   )rI   rJ   rK   r   s       r^   cond_for_tf_v2r`      s    H 
dGht$	OO    c                 X    t        | t        t        f      rt        |       dk(  r| d   S | S )Nr   r   )r+   listtuplelen)ress    r^   r8   r8   Z  s(    dE]#CAq6MJra   c                    t        j                  |       } t        j                  |       }|t	        |t
        j                        rt	        |t
        j                        st        d      t        j                         }|rt        j                  d       t        j                  d       	 t        j                  | |||      |t        j                  |       S S t        j                  |d| g      5  |r |       }n |       }|st        |      }|cddd       S # |t        j                  |       w w xY w# 1 sw Y   yxY w)z0Special cases for `cond` when executing eagerly.NziWhen running tf.cond on a parallel device, 'true_fn' and 'false_fn' must be decorated with `tf.function`.zIt looks like tf.function behavior was disabled, perhaps using tf.config.run_functions_eagerly. Parallelized tf.cond requires tf.function to work. This primitive will override the disable.Fr   )r   convert_to_tensorr	   constant_valuer+   r   PolymorphicFunctionr#   r   functions_run_eagerlyloggingwarningrun_functions_eagerlyr   r*   r8   )rI   rJ   rK   rL   r   pred_constant_valuerk   results           r^   r&   r&   a  s6   			t	$$#2248  w 8 89(D$<$<= M N N.DDF ooKL ,,U3H__T7Hd;		*001FG 
+
 
ftf	- 	#F+  
	*001FG 
+
 s   -D 5 D<D9<Ec                    t        | t        j                        rt        |t        j                        r| j                  j                  |j                  j                  k7  rgt        j                  | j                  t        j                        | _	        t        j                  |j                  t        j                        |_	        yyyy)aa  Cast IndexedSlice.indices from int32 to int64 where necessary.

  If `a` and `b` are both IndexedSlices, and their indices have different
  dtypes, then cast both their dtypes to `int64` (modifies `a` and `b`
  in-place).  Otherwise, does nothing.

  Args:
    a: A value, which may be an IndexedSlices.
    b: A value, which may be an IndexedSlices.
  N)
r+   r   IndexedSlicesindicesr@   r   castr   int64_indices)abs     r^   r;   r;     s     N001N001iioo(qyy&,,7AJqyy&,,7AJ ) 2 2ra   )NNFNNN)NNN)%__doc__tensorflow.python.eagerr   ,tensorflow.python.eager.polymorphic_functionr   tensorflow.python.frameworkr   r   r   r   r>   r	   tensorflow.python.opsr
   r   r   r   r'   r   tensorflow.python.platformr   rl   tensorflow.python.typesr   tensorflow.python.utilr   r   r    tensorflow.python.util.tf_exportr   add_dispatch_supportdeprecated_argsr   r`   r8   r&   r;    ra   r^   <module>r      s    1 + K . 6 + < 3 + ) 2 ; * < ( . + ' 6
 vh	
N	5 D  
DN 6b	bP  bPJ%P8ra   