
    AVh;                     T   d 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  edg       ej,                  	 	 	 	 dd              Z edg      ej,                  	 	 	 	 dd              Zd Zd Z	 ddZd Zy)z+Case functions for Control Flow Operations.    N)context)constant_op)dtypes)ops)tensor)array_ops_stack)cond)control_flow_assert)math_ops)
tf_logging)dispatch)	tf_exportcase)v1c           	      B    t        t        j                  | |||d|      S )ap  Create a case operation.

  See also `tf.switch_case`.

  The `pred_fn_pairs` parameter is a list of pairs of size N.
  Each pair contains a boolean scalar tensor and a python callable that
  creates the tensors to be returned if the boolean evaluates to True.
  `default` is a callable generating a list of tensors. All the callables
  in `pred_fn_pairs` as well as `default` (if provided) should return the same
  number and types of tensors.

  If `exclusive==True`, all predicates are evaluated, and an exception is
  thrown if more than one of the predicates evaluates to `True`.
  If `exclusive==False`, execution stops at the first predicate which
  evaluates to True, and the tensors generated by the corresponding function
  are returned immediately. If none of the predicates evaluate to True, this
  operation returns the tensors generated by `default`.

  `tf.case` supports nested structures as implemented in
  `tf.nest`. All of the callables 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 a callable, they are
  implicitly unpacked to single values. This behavior is disabled by passing
  `strict=True`.

  @compatibility(v2)
  `pred_fn_pairs` could be a dictionary in v1. However, tf.Tensor and
  tf.Variable are no longer hashable in v2, so cannot be used as a key for a
  dictionary.  Please use a list or a tuple instead.
  @end_compatibility


  **Example 1:**

  Pseudocode:

  ```
  if (x < y) return 17;
  else return 23;
  ```

  Expressions:

  ```python
  f1 = lambda: tf.constant(17)
  f2 = lambda: tf.constant(23)
  r = tf.case([(tf.less(x, y), f1)], default=f2)
  ```

  **Example 2:**

  Pseudocode:

  ```
  if (x < y && x > z) raise OpError("Only one predicate may evaluate to True");
  if (x < y) return 17;
  else if (x > z) return 23;
  else return -1;
  ```

  Expressions:

  ```python
  def f1(): return tf.constant(17)
  def f2(): return tf.constant(23)
  def f3(): return tf.constant(-1)
  r = tf.case([(tf.less(x, y), f1), (tf.greater(x, z), f2)],
           default=f3, exclusive=True)
  ```

  Args:
    pred_fn_pairs: List of pairs of a boolean scalar tensor and a callable which
      returns a list of tensors.
    default: Optional callable that returns a list of tensors.
    exclusive: True iff at most one predicate is allowed to evaluate to `True`.
    strict: A boolean that enables/disables 'strict' mode; see above.
    name: A name for this operation (optional).

  Returns:
    The tensors returned by the first pair whose predicate evaluated to True, or
    those returned by `default` if none does.

  Raises:
    TypeError: If `pred_fn_pairs` is not a list/tuple.
    TypeError: If `pred_fn_pairs` is a list but does not contain 2-tuples.
    TypeError: If `fns[i]` is not callable for any i, or `default` is not
               callable.
  Fallow_python_predsstrict_case_helperr	   pred_fn_pairsdefault	exclusiver   names        W/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/ops/control_flow_case.pycase_v2r   !   s+    ~ 

ii

     c           	      B    t        t        j                  | |||d|      S )a4  Create a case operation.

  See also `tf.switch_case`.

  The `pred_fn_pairs` parameter is a dict or list of pairs of size N.
  Each pair contains a boolean scalar tensor and a python callable that
  creates the tensors to be returned if the boolean evaluates to True.
  `default` is a callable generating a list of tensors. All the callables
  in `pred_fn_pairs` as well as `default` (if provided) should return the same
  number and types of tensors.

  If `exclusive==True`, all predicates are evaluated, and an exception is
  thrown if more than one of the predicates evaluates to `True`.
  If `exclusive==False`, execution stops at the first predicate which
  evaluates to True, and the tensors generated by the corresponding function
  are returned immediately. If none of the predicates evaluate to True, this
  operation returns the tensors generated by `default`.

  `tf.case` supports nested structures as implemented in
  `tf.nest`. All of the callables 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 a callable, they are
  implicitly unpacked to single values. This behavior is disabled by passing
  `strict=True`.

  If an unordered dictionary is used for `pred_fn_pairs`, the order of the
  conditional tests is not guaranteed. However, the order is guaranteed to be
  deterministic, so that variables created in conditional branches are created
  in fixed order across runs.

  @compatibility(eager)
  Unordered dictionaries are not supported in eager mode when `exclusive=False`.
  Use a list of tuples instead.
  @end_compatibility


  **Example 1:**

  Pseudocode:

  ```
  if (x < y) return 17;
  else return 23;
  ```

  Expressions:

  ```python
  f1 = lambda: tf.constant(17)
  f2 = lambda: tf.constant(23)
  r = tf.case([(tf.less(x, y), f1)], default=f2)
  ```

  **Example 2:**

  Pseudocode:

  ```
  if (x < y && x > z) raise OpError("Only one predicate may evaluate to True");
  if (x < y) return 17;
  else if (x > z) return 23;
  else return -1;
  ```

  Expressions:

  ```python
  def f1(): return tf.constant(17)
  def f2(): return tf.constant(23)
  def f3(): return tf.constant(-1)
  r = tf.case({tf.less(x, y): f1, tf.greater(x, z): f2},
           default=f3, exclusive=True)
  ```

  Args:
    pred_fn_pairs: Dict or list of pairs of a boolean scalar tensor and a
      callable which returns a list of tensors.
    default: Optional callable that returns a list of tensors.
    exclusive: True iff at most one predicate is allowed to evaluate to `True`.
    strict: A boolean that enables/disables 'strict' mode; see above.
    name: A name for this operation (optional).

  Returns:
    The tensors returned by the first pair whose predicate evaluated to True, or
    those returned by `default` if none does.

  Raises:
    TypeError: If `pred_fn_pairs` is not a list/dictionary.
    TypeError: If `pred_fn_pairs` is a list but does not contain 2-tuples.
    TypeError: If `fns[i]` is not callable for any i, or `default` is not
               callable.
  Fr   r   r   s        r   r   r      s+    F 

ii

 r   c                 ~   t        j                  | d      }t        j                  t        j                  |t
        j                        d      }t        j                  |t        j                  |d            }dj                  d | D              }d|||fz  |g}t        j                  ||t        |             S )	zReturns an Assert op that checks that at most n predicates are True.

  Args:
    predicates: list of bool scalar tensors.
    n: maximum number of true predicates allowed.
    msg: Error message.
  preds_cr   num_true_condsn_true_condsz, c              3   6   K   | ]  }t        |d d        yw)r   ?N)getattr).0ps     r   	<genexpr>z)_assert_at_most_n_true.<locals>.<genexpr>  s     Fa'!VS1Fs   z3%s: more than %d conditions (%s) evaluated as True:)data	summarize)r   stackr   
reduce_sumcastr   int32
less_equalr   constantjoinr
   Assertlen)
predicatesnmsgr!   num_true_conditions	conditionpreds_names	error_msgs           r   _assert_at_most_n_truer=      s     !!*9=' ++mmGV\\*1AC!!"5"-"6"6q~"NP)		F:FF+;
A{$) 
	#	#i3z?
< <r   c                 p     t               dz
      |   c d |d c} fd}||fS )aV  Creates default action for a list of actions and their predicates.

  It uses the input actions to select an arbitrary as default and makes sure
  that corresponding predicates have valid values.

  Args:
    predicates: a list of bool scalar tensors
    actions: a list of callable objects which return tensors.

  Returns:
    a callable
     Nc                      dz  } dt        j                  d      f}t        j                  t	        d|       t        j                  |      g      5          cd d d        S # 1 sw Y   y xY w)NzeImplementation error: selected default action #%d was called, but some of other predicates are True: z2Input error: None of conditions evaluated as True:r!   r"   r   r7   r8   )r+   )r   r-   r   control_dependenciesr=   r
   r4   )
others_msgdefault_msgactionkother_predicates	predicater6   s     r   default_actionz3_case_create_default_action.<locals>.default_action  s    *,-.J;"(()DFK 
	!	!z	3""9;?# 
 
 X  s   A))A2)r5   )r6   actionsother_actionsrI   rE   rF   rG   rH   s   `   @@@@r   _case_create_default_actionrL     sZ     
*o! mWQZ)V$.rNGBQK!M  
)=	88r   c           	         t        ||||      \  }}t        j                  |d|g      5  |t        ||      \  }}}|}	t	        t        t        ||                  D ]  \  }
}t        j                  | |
f||	d|}	! |r<t        j                  t        |dd      g      5   |	       cddd       cddd       S  |	       cddd       S # 1 sw Y   nxY w	 ddd       y# 1 sw Y   yxY w)a   Implementation of case that allows for different cond functions.

  Args:
    cond_fn: method that has signature and semantics of `cond` above.
    pred_fn_pairs: Dict or list of pairs of a boolean scalar tensor, and a
      callable which returns a list of tensors.
    default: Optional callable that returns a list of tensors.
    exclusive: True iff at most one predicate is allowed to evaluate to `True`.
    name: A name for this operation (optional).
    allow_python_preds: if true, pred_fn_pairs may contain Python bools in
      addition to boolean Tensors
    **cond_kwargs: keyword arguments that will be passed to `cond_fn`.

  Returns:
    The tensors returned by the first pair whose predicate evaluated to True, or
    those returned by `default` if none does.

  Raises:
    TypeError: If `pred_fn_pairs` is not a list/dictionary.
    TypeError: If `pred_fn_pairs` is a list but does not contain 2-tuples.
    TypeError: If `fns[i]` is not callable for any i, or `default` is not
               callable.
  r   N)true_fnfalse_fnr?   zInput error: exclusive=TruerA   )"_case_verify_and_canonicalize_argsr   
name_scoperL   reversedlistzip	functoolspartialrB   r=   )cond_fnr   r   r   r   r   cond_kwargsr6   rJ   fnrH   rE   s               r   r   r   /  s!   < ;Y&8:*g
~~dFZL1 %@
g&"gz7	B &d3z7+C&DE J	6
9J&,rJ=HJbJ ##
 A#@B% 	  t	  " T#     s*   A9C##C*	C#=C#C	C##C,c                    t        | t        t        t        f      st	        dt        |              t        | t        j                        r| j                         } nt        | t              rot        j                         r'|st        d      t        | j                               } n4t        | j                         d       } |st        j                  d|       | D ]  }t        |t              rt        |      dk7  rt	        d| d      |\  }}t        |t         j"                        r5|j$                  t&        j(                  k7  rFt	        d	|j*                  z        |st	        d
|z        t        |t(              st	        d|z        t-        |      rt	        d|j*                  z         t/        |  \  }}||fS )a  Verifies input arguments for the case function.

  Args:
    pred_fn_pairs: Dict or list of pairs of a boolean scalar tensor, and a
      callable which returns a list of tensors.
    exclusive: True iff at most one predicate is allowed to evaluate to `True`.
    name: A name for the case operation.
    allow_python_preds: if true, pred_fn_pairs may contain Python bools in
      addition to boolean Tensors

  Raises:
    TypeError: If `pred_fn_pairs` is not a list/dictionary.
    TypeError: If `pred_fn_pairs` is a list but does not contain 2-tuples.
    TypeError: If `fns[i]` is not callable for any i, or `default` is not
               callable.

  Returns:
    a tuple <list of scalar bool tensors, list of callables>.
  z:'pred_fn_pairs' must be a list, tuple, or dict. Received: z{Unordered dictionaries are not supported for the 'pred_fn_pairs' argument when `exclusive=False` and eager mode is enabled.c                      | d   j                   S )Nr   r"   )items    r   <lambda>z4_case_verify_and_canonicalize_args.<locals>.<lambda>  s    $q',, r   )keyz%s: An unordered dictionary of predicate/fn pairs was provided, but exclusive=False. The order of conditional tests is deterministic but not guaranteed.   z:Each entry in 'pred_fn_pairs' must be a 2-tuple. Received .z$pred must be Tensor of type bool: %szpred must be a Tensor, got: %sz&pred must be a Tensor or bool, got: %sz fn for pred %s must be callable.)
isinstancerS   tupledict	TypeErrortypecollectionsOrderedDictitemsr   executing_eagerly
ValueErrorsortedloggingwarnr5   r   Tensordtyper   boolr   callablerT   )	r   r   r   r   pred_fn_pairpredrY   r6   rJ   s	            r   rP   rP   c  s   * 
MD%#6	7
 !!%m!4 57 8 8 {667!'')M-&  "  2 3 	3 =..01m



%>@m9:>	@ $ FllE*c,.?1.D "".q2 3 3HD"$&	v{{	">JKK6=>>d#>EFFB<8499DEEF" ]+*g	W	r   )NFFr   )F)__doc__rf   rU   tensorflow.python.eagerr   tensorflow.python.frameworkr   r   r   r   tensorflow.python.opsr   r	   r
   r   tensorflow.python.platformr   rl   tensorflow.python.utilr    tensorflow.python.util.tf_exportr   add_dispatch_supportr   r   r=   rL   r   rP    r   r   <module>r}      s    2   + 3 . + . 1 & 5 * < + 6 6b		d  dN vh		h  hV<,9N %*1h>r   