
    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 Z	 ddZ edg       dd       Z ed      dd       Zy)z(Switch case for Control Flow Operations.    )context)ops)tensor)	array_ops)cond_v2)control_flow_util)gen_functional_ops)math_ops)	tf_exportc                    t        |t        j                        s#t        dj	                  t        |                  |j                  j                  s$t        dj	                  |j                              | st        d      t        | t        t        t        f      st        d      t        | t              r| j                         } t        d | D              rt        t        |             } | D ]  }t        |t              rt        |      dk7  rt        d| d      |\  }}t        |t               s#t        d	j	                  t        |                  t#        |      rtt        d
j	                  |             | D cg c]  }|d   	 }}t%        |      dk  s7t'        |      t        |      k\  s t        t)        |            t        |      k7  rJt        dj	                  t        |      dj+                  t-        t.        t1        |                              t1        |       D cg c]  }|d   	 }}||j3                  |       |S c c}w c c}w )a  Verifies input arguments for the case function.

  Args:
    branch_fns: Dict or list of pairs of an `int` and a callable which returns a
      list of tensors.
    default: Optional callable that returns a list of tensors.
    branch_index: Optional int `Tensor`, which selects for the corresponding
      pred_fn_pair.

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

  Returns:
    branch_fns: validated list of callables for each branch (default last).
  z''branch_index' must be a Tensor, got {}z0'branch_index' must be an integer Tensor, got {}z.Must provide at least one item in 'branch_fns'z+'branch_fns' must be a list, tuple, or dictc              3   2   K   | ]  }t        |        y wN)callable).0fns     ^/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/ops/control_flow_switch_case.py	<genexpr>z=_indexed_case_verify_and_canonicalize_args.<locals>.<genexpr>@   s     +""+s      z7Each entry in 'branch_fns' must be a 2-tuple. Received .z"key must be a Python `int`, got {}zfn for key {} must be callable.r   zNbranch indices (keys) must form contiguous range of [0 to {}) but found {{{}}},   )
isinstancer   Tensor	TypeErrorformattypedtype
is_integer
ValueErrorlisttupledictitemsall	enumeratelenintr   minmaxsetjoinmapstrsortedappend)	
branch_fnsdefaultbranch_indexkey_fn_pairkey	branch_fnpkeysactionss	            r   *_indexed_case_verify_and_canonicalize_argsr9      s   * 
L&--	0
=DD\  				&	&
FMM   

E
FF	Jud 3	4
A
BB
D!!!#J+
++i
+,J 
Ekk5)S-=-B ""-a1 2 2 NCc3:AA$s)LMMI7>>sCDD
E #	#1!A$	#$	#Y]c$i3t9,CI#d)0K
	vc$i#c6$<2H)IJL L "*-.aQqT.'.NN7	. 
$
 /s   I0INc           
         t        | ||      } t        j                  |d|g      5  t        j                         rt        |d      sst        j                  t        j                  |d      t        j                  |t        |             z  t        |       dz
  |      } | t        |                cddd       S t        j                  || |      cddd       S # 1 sw Y   yxY w)al  Implementation of case that emits the n-way indexed Case op.

  Args:
    branch_fns: 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.
    branch_index: Optional int `Tensor`, which selects for the corresponding
      pred_fn_pair.
    name: A name for this operation (optional).
    lower_using_switch_merge: Lower this op using switch merge ops (optional).

  Returns:
    The tensors returned by the pair whose key matched branch_index, or
    those returned by `default` if none does.

  Raises:
    TypeError: If `branch_fns` is not a list/dictionary.
    TypeError: If `branch_fns` is a list but does not contain 2-tuples or
               callables.
    TypeError: If `fns[i]` is not callable for any i, or `default` is not
               callable.
  casegraphr   r   Nlower_using_switch_merge)r9   r   
name_scoper   executing_eagerlyhasattrr   wherer
   lessgreater_equalr&   r'   r   indexed_case)r0   r1   r2   namer>   s        r   _indexed_case_helperrG   Z   s    6 :'<)*
~~dF\N3 
;  "7<+I__
--a
(""<ZAB
j/A
|-l +ZL)*,
; 
; !9;
; 
; 
;s   B
C:CC$z"__internal__.execute_fn_for_device)v1c                    t        j                  t        j                               }|r |       S | j	                         D ci c]  \  }}|j                         | }}}t        |j                               }t        |j                               }t        j                  |      }	t        |||	|d      S c c}}w )a  Executes one of the provided callables based on the device placement.

  This API is used when the implementations for high level function depend on
  the underlying device placement. It takes a dictionary of device type to
  callables. The device type includes "CPU", "GPU", "TPU", etc. When the type of
  the device where to run this op matches the key in 'device_branch_fns',
  the corresponding callable is executed, falling back to 'default_fn' if none
  matches.

  **Example:**
  ```python
  def f1(): return tf.constant(1)
  def f2(): return tf.constant(2)
  r = tf.execute_fn_for_device({"CPU": f1, "GPU": f2}, default_fn=f1)
  ```
  'r' is evaluated as 1 when it runs on CPU, 2 running on GPU, 1 running on
  any other device types.


  Args:
    device_branch_fns: a dictionary of device types to the callables. Each
      callable must return a matching structure of tensors.
    default_fn: fallback callable when the underlying device does not match any
      key in the 'device_branch_fns'.
    name: A name for this operation (optional).

  Returns:
    The tensors returned by the callable identified by device type during
    execution, or those returned by 'default_fn' if no key matches.
  )device_namesFr=   )utilGraphOrParentsInXlaContextr   get_default_graphr#   upperr    valuesr7   r	   device_indexrG   )
device_branch_fns
default_fnrF   	is_in_xlakvdevice_branch_fns_upperr0   devicesrP   s
             r   execute_fn_for_devicerX      s    D --c.C.C.EF)<6G6M6M6OPdaQWWY\PP+2245*(--/0'#00gF,	
$
& &	 Qs   B:switch_casec                     t        ||| |      S )a	  Create a switch/case operation, i.e.

  an integer-indexed conditional.

  See also `tf.case`.

  This op can be substantially more efficient than `tf.case` when exactly one
  branch will be selected. `tf.switch_case` is more like a C++ switch/case
  statement than `tf.case`, which is more like an if/elif/elif/else chain.

  The `branch_fns` parameter is either a dict from `int` to callables, or list
  of (`int`, callable) pairs, or simply a list of callables (in which case the
  index is implicitly the key). The `branch_index` `Tensor` is used to select an
  element in `branch_fns` with matching `int` key, falling back to `default`
  if none match, or `max(keys)` if no `default` is provided. The keys must form
  a contiguous set from `0` to `len(branch_fns) - 1`.

  `tf.switch_case` supports nested structures as implemented in `tf.nest`. All
  callables must return the same (possibly nested) value structure of lists,
  tuples, and/or named tuples.

  **Example:**

  Pseudocode:

  ```c++
  switch (branch_index) {  // c-style switch
    case 0: return 17;
    case 1: return 31;
    default: return -1;
  }
  ```
  or
  ```python
  branches = {0: lambda: 17, 1: lambda: 31}
  branches.get(branch_index, lambda: -1)()
  ```

  Expressions:

  ```python
  def f1(): return tf.constant(17)
  def f2(): return tf.constant(31)
  def f3(): return tf.constant(-1)
  r = tf.switch_case(branch_index, branch_fns={0: f1, 1: f2}, default=f3)
  # Equivalent: tf.switch_case(branch_index, branch_fns={0: f1, 1: f2, 2: f3})
  ```

  Args:
    branch_index: An int Tensor specifying which of `branch_fns` should be
      executed.
    branch_fns: A `dict` mapping `int`s to callables, or a `list` of (`int`,
      callable) pairs, or simply a list of callables (in which case the index
      serves as the key). Each callable must return a matching structure of
      tensors.
    default: Optional callable that returns a structure of tensors.
    name: A name for this operation (optional).

  Returns:
    The tensors returned by the callable identified by `branch_index`, or those
    returned by `default` if no key matches and `default` was provided, or those
    returned by the max-keyed `branch_fn` if no `default` is provided.

  Raises:
    TypeError: If `branch_fns` is not a list/dictionary.
    TypeError: If `branch_fns` is a list but does not contain 2-tuples or
               callables.
    TypeError: If `fns[i]` is not callable for any i, or `default` is not
               callable.
  )rG   )r2   r0   r1   rF   s       r   rY   rY      s    P 
j'<	FF    r   )
execute_fn)NrY   )__doc__tensorflow.python.eagerr   tensorflow.python.frameworkr   r   tensorflow.python.opsr   r   r   rK   r	   r
    tensorflow.python.util.tf_exportr   r9   rG   rX   rY    r[   r   <module>rc      sp    / + + . + ) ; 4 * 6;D 37	';T /B7-& 8-&` =GG GGr[   