o
    ?e@                     @   sL  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dejedddd						d$ddZ edg dejd%ddZ!dd Z"d d! Z#d"d# Z$dS )&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fn2Fc                 C   s  |dur|durt d|}n|du rt d|dur&|dur#t d|}n|du r.t dt|s6t dt|s>t dt rJt| ||||S tt rYt		| |||S t
|d| g t| trlt d	t| | \}}tj|d
d}	tj|dd}
tj| dd} |||	|
| fD ]
}|jj|j qtj| |	dd}z|  ||\}}|du rtd|| W |  n|  w tj| |
dd}z|  ||\}}|du rtd|| W |  n|  w |st|}t|}z
tj||dd W nL t tfyS   tt|| tt|| z
tj||dd W n' t y= } zt d| d}~w tyP } ztd| d}~ww Y nw |s[tdtj|dd}tj|dd}t ||D ]-\}}t|t!j"rt|t!j"sJ |j#j$|j#j$krtd|j#j% d|j#j% dqndd t ||D }ttj&tj|dd|}|j'|j'ksJ |j'du rt(tj)j*| t(tj)j*| tj+||dd}|st|}|W  d   S 1 sw   Y  dS )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.Zswitch_t)nameZswitch_fZ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'.c                 S   s   g | ]	}t |d  qS )r   )r   merge).0pair r   [/home/www/facesmatcher.com/pyenv/lib/python3.10/site-packages/tensorflow/python/ops/cond.py
<listcomp>   s    zcond.<locals>.<listcomp>)Z	structureZflat_sequencer   ),	TypeErrorcallabler   Zexecuting_eagerly_eager_cond_implementationutilZEnableControlFlowV2r   Zget_default_graphr
   
name_scope
isinstanceboolr   switchr	   identityopgraphZprevent_fetchingZCondContextZEnterZBuildCondBranch
ValueErrorZ
ExitResultZExit_UnpackIfSingletonr   Zassert_same_structureZmap_structure_cast_indexed_slice_indicesflattenzip
tensor_libZTensordtypeZ
base_dtyper   Z_convert_flow_to_tensorarrayZouter_contextZadd_to_collectionZ	GraphKeysZCOND_CONTEXTZpack_sequence_as)predtrue_fnfalse_fnstrictr   r   r   Zp_2Zp_1Zpivot_1Zpivot_2r   Z	context_tZ
orig_res_tZres_tZ	context_fZ
orig_res_fZres_feZ
res_t_flatZ
res_f_flatxyZmergesr   r   r    r   '   s   R



&c                 C   s   t | ||d|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
  >>> 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.
  >>> 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))
  >>> 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.
  >>> r.numpy()
  14

  T)r5   r6   r7   r   )r   )r4   r5   r6   r   r   r   r    cond_for_tf_v2   s   dr;   c                 C   s&   t | ttfrt| dkr| d S | S )Nr   r   )r'   listtuplelen)resr   r   r    r.   Z  s   r.   c              	   C   s   t | } t| }|du rMt|tjrt|tjstdt	 }|r)t
d td zt| |||W |durAt| S S |durLt| w w t |d| g |r\| }n| }|set|}|W  d   S 1 sqw   Y  dS )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   Zconvert_to_tensorr   Zconstant_valuer'   r   ZGenericFunctionr"   r   functions_run_eagerlyloggingwarningZrun_functions_eagerlyr
   r&   r.   )r4   r5   r6   r7   r   Zpred_constant_valuer@   resultr   r   r    r$   a  s8   




$r$   c                 C   s\   t | tjr(t |tjr*| jj|jjkr,t| jtj| _	t|jtj|_	dS dS dS dS )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   ZIndexedSlicesindicesr3   r   castr   Zint64Z_indices)abr   r   r    r/     s   
r/   )NNFNNN)NNN)%__doc__Ztensorflow.python.eagerr   Z,tensorflow.python.eager.polymorphic_functionr   Ztensorflow.python.frameworkr   r   r   r   r2   r   Ztensorflow.python.opsr	   r
   r   r   r%   r   Ztensorflow.python.platformr   rA   Ztensorflow.python.typesr   Ztensorflow.python.utilr   r   r   Z tensorflow.python.util.tf_exportr   Zadd_dispatch_supportZdeprecated_argsr   r;   r.   r$   r/   r   r   r   r    <module>   sN   
 
He(