
    Ph=                     R   d dl mZ d dlmZ d dlZd dlZd dlmc mZ	 d dl
mc 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mZmZmZ d d
lmZ d dlm Z  d dl!m"Z" ed        Z#e G d de$             Z% ed      d        Z&	  ed      Z'd Z(d Z)e'jU                  ejV                        d        Z, e'jU                  ejZ                         ee'd             e'jU                  e      d        Z.e'jU                  e      d        Z/d Z0d Z1e'jd                  d        Z3y)    )contextmanager)	dataclassN)DispatchKey)
exposed_in)autograd_not_implemented)HigherOrderOperator)FakeTensorMode)disable_proxy_modes_tracingmake_fxProxyTorchDispatchModetrack_tensor_tree)_extract_tensor_metadata)StorageWeakRef_get_current_dispatch_modec               #   "  K   t         j                  j                  j                  } 	 dt         j                  j                  _        d  | t         j                  j                  _        y # | t         j                  j                  _        w xY ww)NF)torchfx_symbolic_trace_is_fx_tracing_flag)_old_is_tracings    gC:\Users\daisl\Desktop\realtime-object-detection\venv\Lib\site-packages\torch/_higher_order_ops/cond.py_set_compilation_envr      s\     hh..BBOG 8=  47F  4  4s   %B#A+  B+!BBc                       e Zd ZU eed<   y)!UnsupportedAliasMutationExceptionreasonN)__name__
__module____qualname__str__annotations__     r   r   r   '   s    Kr#   r   r   c                    t         j                  j                         rt        | |||      S d } || |||       t         j                  j	                         st        d      t               5  t         j                  j                  j                         5   t        j                  t        dd      | |||      cddd       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^  
    Conditionally applies `true_fn` or `false_fn`.

    .. warning::
        `torch.cond` is a prototype feature in PyTorch. It has limited support for input and output types and
        doesn't support training currently. Please look forward to a more stable implementation in a future version of PyTorch.
        Read more about feature classification at: https://pytorch.org/blog/pytorch-feature-classification-changes/#prototype

    `cond` is structured control flow operator. That is, it is like a Python if-statement,
    but has restrictions on `true_fn`, `false_fn`, and `operands` that enable it to be
    capturable using torch.compile and torch.export.

    Assuming the constraints on `cond`'s arguments are met, `cond` is equivalent to the following::

        def cond(pred, true_branch, false_branch, operands):
            if pred:
                return true_branch(*operands)
            else:
                return false_branch(*operands)

    Args:
        pred (Union[bool, torch.Tensor]): A boolean expression or a tensor with one element,
          indicating which branch function to apply.

        true_fn (Callable): A callable function (a -> b) that is within the
          scope that is being traced.

        false_fn (Callable): A callable function (a -> b) that is within the
          scope that is being traced. The true branch and false branch must
          have consistent input and outputs, meaning the inputs have to be
          the same, and the outputs have to be the same type and shape.

        operands (Tuple of possibly nested dict/list/tuple of torch.Tensor): A tuple of inputs to the true/false functions.

    Example::

        def true_fn(x: torch.Tensor):
            return x.cos()
        def false_fn(x: torch.Tensor):
            return x.sin()
        return cond(x.shape[0] > 4, true_fn, false_fn, (x,))

    Restrictions:
        - The conditional statement (aka `pred`) must meet one of the following constraints:

          - It's a `torch.Tensor` with only one element, and torch.bool dtype

          - It's a boolean expression, e.g. `x.shape[0] > 10` or `x.dim() > 1 and x.shape[1] > 10`

        - The branch function (aka `true_fn`/`false_fn`) must meet all of the following constraints:

          - The function signature must match with operands.

          - The function must return a tensor with the same metadata, e.g. shape,
            dtype, etc.

          - The function cannot have in-place mutations on inputs or global variables.
            (Note: in-place tensor operations such as `add_` for intermediate results
            are allowed in a branch)

    .. warning::
        Temporal Limitations:

        - `cond` only supports **inference** right now. Autograd will be supported in the future.

        - The **output** of branches must be a **single Tensor**. Pytree of tensors will be supported in the future.

    c                    t        | t        t        j                  t        j                  f      st        d|  d      t        | t        j                        r"| j                         dk7  rt        d|  d      t        |      rt        |      st        d      t        |t        t        f      rt        j                  d |      rt        d| d      y )Nz,Expected pred to be bool or tensor, but got .   z;Expected pred to be bool or single-element tensor, but got z$Expect both branches to be callbale.c                 8    t        | t        j                         S N
isinstancer   Tensor)ts    r   <lambda>z/cond.<locals>._validate_input.<locals>.<lambda>   s    *Q55r#   zmExpect operands to be a tuple of possibly nested dict/list/tuple that onlyconsists of tensor leaves, but got )r+   boolr   r,   SymBoolRuntimeErrornumelcallabletuplelistpytreetree_any)predtrue_fnfalse_fnoperandss       r   _validate_inputzcond.<locals>._validate_inputv   s    $u||U]] CD!MdVSTUVVdELL)djjla.?MdVSTU   (:EFF(UDM2foo5x7
 66>ZqB 7
r#   z#torch.cond requires dynamo support.eagerT)backend	fullgraphN)
r   _dynamois_compilingcond_opis_dynamo_supportedr1   r   utilsdisable_cache_limitcompile)r8   r9   r:   r;   r<   s        r   condrG   ,   s    N }}!!#tWh99( D'8X6==,,.@AA		]]  446J5=='TJgx 76 
 	666 
 		s$   .)C%%C<	C%C	C%%C.rG   c                       }t         t        j                  j                        rt	        j
                         r fd}|}|S )Nc                      t        j                         5  t        j                  j	                        j
                  |  cd d d        S # 1 sw Y   y xY wr)   )fx_tracebackpreserve_node_metar   r   Interpreterrun)argsfns    r   graph_with_interpreterz;_maybe_run_with_interpreter.<locals>.graph_with_interpreter   s8    002xx++B/33T: 322s   +AA)r+   r   r   GraphModulerJ   has_preserved_node_meta)rO   maybe_interpreted_fnrP   s   `  r   _maybe_run_with_interpreterrT      s;    "ehh**+0T0T0V	;  6r#   c                    t        |t        t        f      sJ d       t        d |D              sJ d       t	        | dd      }t               5   t        t        |      |      | } t        t        |      |      | }d d d        g }	g }
j                  j                  D ]-  }|j                  dk(  s|	j                  |j                         / j                  j                  D ]-  }|j                  dk(  s|
j                  |j                         / t        j                  |	 }t        j                  |
 }t        |      t        |      k7  r\t         j"                  j$                  j'                  d|j(                   d	t        |       d
|j(                   d	t        |       d	      t+        dt        |            D ]  }||   }||   }|j,                  d   |j,                  d   k7  s-t         j"                  j$                  j'                  d|j(                   d	|j,                  d    d|j(                   d	|j,                  d           d }d}|s0d| }t/        | j0                  j2                  |      r|dz  }n|}|s0|}d| }t/        | j0                  j2                  |      rJ | j0                  j2                  j5                  ||       | j0                  j2                  j5                  ||       ||||f}t        j6                  | j0                  j8                  |      }| j0                  j;                  d||i d      } || }t=        ||d | j0                        S # 1 sw Y   xY w)Nz0Cond operands must be a list or tuple of tensorsc              3   P   K   | ]  }t        |t        j                           y wr)   r*   ).0os     r   	<genexpr>ztrace_cond.<locals>.<genexpr>   s      -5
1ell#Xs   $&z'Cond operands must be a list of tensorspre_dispatchF)rZ   outputz5Expected to return same number of outputs but got:
  	 returns z item(s)
  z item(s)r   tensor_meta6Expected each tensor to have same metadata but got:
  
  true_graph_r'   false_graph_call_functionconditional)name)constanttracer)r+   r5   r4   allgetattrr
   r   rT   graphnodesopextendrN   r6   arg_tree_leaveslenr   r@   excCondOpArgsMismatchErrorr   rangemetahasattrrf   rootregister_moduletree_mapunwrap_proxycreate_proxyr   )
proxy_modefunc_overloadr8   r9   r:   r;   rZ   
true_graphfalse_graph	true_outs
false_outsnodeflat_true_outsflat_false_outsitrue_out	false_out	next_name	candidate	true_name
false_namerN   
proxy_args	out_proxyouts                            r   
trace_condr      s   4- :9:   -5  101  :~u=L	$	&
W'0|


g'1
	 
' IJ  &&77hTYY' ' !!''77hdii( ( ++Y7N,,j9O
>c/22mm77##$Ic..A-B C$$%Ys?/C.DHN
 	
 1c.)*!!$#A&	=='9>>-+HH--##;;''(	(--2N1Ox(()9>>-3P2QS 	 + I	A!!%	:$$))95FA!I  Is#Jz((--z:::**9jA**:{C*k84D!2!2!?!?FJ!!..
B] / I H
CS)d:CTCTUUW 
'	&s   3M//M9c                 @    t               }|J d       | r || S  || S )Nz-Mode should never be enabled for CPU/CUDA keyr   )r8   r9   r:   r;   modes        r   cond_op_denser     s3    %'D<HHH<!!""r#   T)deferred_errorc                 ^    | j                   rt        | t        ||||      S t        ||||      S r)   )enable_tracingr   rB   )r   r8   r9   r:   r;   s        r   innerr     s1    $w(KKtWh99r#   c                    | 5   || }t        j                  |      }t        j                   ||       }d d d        t              t              k7  rt        d      t	        ||      D ]i  \  }}	t        |      }
t        |	      }|
|k7  s"t        j                  j                  j                  d|j                   d|
 d|j                   d|        S # 1 sw Y   xY w)Nz1Unmatched number of outputs from cond() branches.r^   r\   r_   )r6   tree_leavesrn   r1   zipr   r   r@   ro   rp   r   )r   r8   r9   r:   r;   r}   r   r   r   r   	true_meta
false_metas               r   cond_fake_tensor_moder     s    	X&	++I6 ,,Xx-@A 
 >c/22NOO">?C),X6	-i8

"--##;;''(	)x(():,@ 	  D ! 
s   3CC#c                 v    	  t        |       | }fd |      S # t        $ r Y yt        $ r}|d}~ww xY w)z
    Dispatch-trace the branch with inputs and check if
    producing graph has mutable op on the input. This is
    bit restrictive as the branch must be traceable.
    TNc                    t               }| j                  j                  D ]  }|j                  dk(  r|j	                  |       |j                  dk(  s3|j
                  }t        |t        j                  j                        sd|j                  j                  s{|j                  D ]	  }||v s  y  | j                         D ]4  \  }}t        |t        j                  j                        s+ |      s4 y y)Nplaceholderrb   TF)setri   rj   rk   addtargetr+   r   _ops
OpOverload_schema
is_mutablerN   named_childrenr   rQ   )gminput_nodesr   r   arg_module_detect_input_mutations          r   r   zD_has_potential_branch_input_mutation.<locals>._detect_input_mutation<  s    eHHNNDww-'%ww/)vuzz'<'<=11#yy+-#'  ) # **,IAv&%(("6"67)&1 -
 r#   r   r   	Exception)branchinputsr   er   s       @r   $_has_potential_branch_input_mutationr   -  sN    WV_f%, ""%%; -       	8838c                 v    	  t        |       | }fd |      S # t        $ r Y yt        $ r}|d}~ww xY w)z
    Dispatch-trace the branch with inputs and check if
    producing graph has output aliasing the branch input. This is
    bit restrictive as the branch must be traceable.
    TNc           	      *   t               | j                  j                  D ]  }|j                  dk(  rCd|j                  v r5j                  t        |j                  d   j                                      |j                  dk(  sefd}t        t        j                  t        j                  ||j                                    s y | j                         D ]4  \  }}t        |t        j                   j"                        s+ |      s4 y y)Nr   valr[   c                 z    | 8d| j                   v r*t        | j                   d   j                               }|v S y)Nr   F)rr   r   _typed_storage)r   out_storageinput_storagess     r   check_aliaszS_has_potential_branch_input_alias.<locals>._detect_input_alias.<locals>.check_aliaso  s<    5CHH+<&4SXXe_5S5S5U&V*n<< r#   TF)r   ri   rj   rk   rr   r   r   r   anyr6   r   rv   rN   r   r+   r   r   rQ   )r   r   r   r   r   r   _detect_input_aliass        @r   r   z>_has_potential_branch_input_alias.<locals>._detect_input_aliase  s    HHNND ww-'ETYY,>"">$))E2B2Q2Q2S#TUww("! v))&//+tyy*QRS #" **,IAv&%(("6"67<OPV<W - r#   r   )r   r   r   r   r   s       @r   !_has_potential_branch_input_aliasr   U  sO    WV_f%2 r""A -   r   c                    | j                  |      }| j                  |      }| j                         5  | j                  |      }| j                  |      }||fD ]  }	t        |	|      st	        d       ||fD ]  }	t        |	|      st	        d       t        ||||      }
| j                  |
      cd d d        S # 1 sw Y   y xY w)Nz6One of torch.cond branch might be modifying the input!z5One of torch.cond branch might be aliasing the input!)unwrap_tensorsredispatch_to_nextfunctionalizer   r   r   rB   wrap_tensors)ctxr8   r9   r:   r   unwrapped_inputsunwrapped_predfunctional_truefunctional_falser   cond_returns              r   	cond_funcr     s    ))&1''-N				!++G4,,X6&(89F3F<LM7L  :
 )F09IJ7K  * O-=?O
 ,# 
"	!	!s   6B>*B>
*B>>C)4
contextlibr   dataclassesr   r   #torch._subclasses.functional_tensortorch.fx.tracebackr   	tracebackrJ   torch.utils._pytreerD   _pytreer6   torch._Cr   torch._functorch.utilsr   torch._higher_order_ops.utilsr   
torch._opsr   torch._subclasses.fake_tensorr	   "torch.fx.experimental.proxy_tensorr
   r   r   r   torch.fx.passes.shape_propr    torch.multiprocessing.reductionsr   torch.utils._python_dispatchr   r   r1   r   rG   rB   rT   r   py_implCompositeExplicitAutogradr   Autogradr   r   r   r   py_functionalize_implr   r"   r#   r   <module>r      sV   % !  * ) ) $ $   - B * 8  @ ; C G G    Gf fR f
%	 UVp 	667# 8# &$$ %WT:
 	'(: ): 	  !(%&P)#X 	- -r#   