
    VhAp                        d dl mZ d dlZd dlmc 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mZmZmZmZ d dlmZ d dlmZ  G d	 d
e      Z e       Zej9                  ej:                        ej9                  ej<                        d               Zd Z dZ!e!fdZ" G d de      Z#d Z$d Z%ej9                  ejL                        d        Z'd Z(d Z)d Z*ej9                  ejV                        d        Z,d Z-d Z. G d d      Z/ G d de/      Z0 G d de/      Z1	 d%d Z2	 d%d!Z3d" Z4 G d# d$e      Z5 e5       Z6y)&    )
NamedTupleN)_unwrap_for_grad_wrap_for_gradcurrent_levelTransformType)vmap)%enable_single_level_autograd_function)_add_batch_dim_broadcast_to_and_flattenrestore_vmapunwrap_batchedwrap_batched)HigherOrderOperator)_set_fwd_grad_enabledc                   *     e Zd Zd fdZ fdZ xZS )!CustomFunctionHigherOrderOperatorc                 $    t         |   d       y )Ncustom_function_callsuper__init__self	__class__s    R/home/dcms/DCMS/lib/python3.12/site-packages/torch/_functorch/autograd_function.pyr   z*CustomFunctionHigherOrderOperator.__init__!   s    /0    c                     t         j                  j                         rt        |   |g|i |S  |j
                  |i |S N)torch_C _are_functorch_transforms_activer   __call__apply)r   autograd_functionargskwargsr   s       r   r"   z*CustomFunctionHigherOrderOperator.__call__$   sI     884467#$5GGGG& &&777r   returnN__name__
__module____qualname__r   r"   __classcell__r   s   @r   r   r       s    18 8r   r   c                 |    t        | |      }t               5   |j                  | }d d d        |S # 1 sw Y   S xY wr   )generate_single_level_functionr	   r#   )interpreterr$   operands	Generatedflat_outs        r   custom_function_call_gradr5   X   sA     /{<MNI	.	0 ."9??H-.O.Os   1;c           
      (     j                          fd}fd}fd}fd}j                   d}t        |t        j                  j
                  j                  ft        |      t        |      t        |      t        |      d      }|S )Nc                  n   t        j                  t        j                  fd|       }t        j                         5  t        d      5  j                         5  t        g| }d d d        d d d        d d d        fd}t        || |      S # 1 sw Y   ,xY w# 1 sw Y   0xY w# 1 sw Y   4xY w)Nc                     t        |       S r   )r   )xlevels    r   <lambda>zAgenerate_single_level_function.<locals>.forward.<locals>.<lambda>f   s    $4Q$> r   Tc                     t        |       S r   )r   )outputr:   s    r   wrap_fnz@generate_single_level_function.<locals>.forward.<locals>.wrap_fnq   s    !&%00r   )	pytreetree_map_onlyr   Tensorenable_gradr   lowerr   !wrap_outputs_maintaining_identity)r2   unwrapped_operandsunwrapped_outputr>   r$   r1   r:   s       r   forwardz/generate_single_level_function.<locals>.forwardd   s    #11LL>
   	"7"= 	{?P?P?R 	3! $6 	 	 		1 10(G
 	
	 	 	 	 	 	s;   B+
BB(B0B+BBB(	$B++B4c                 *    j                  | ||      S r   )setup_context)ctxinputsr=   r$   s      r   rI   z5generate_single_level_function.<locals>.setup_contextx   s     ..sFFCCr   c                 .     j                   | g| }|S r   )backward)rJ   gradsresultr$   s      r   rM   z0generate_single_level_function.<locals>.backward|   s     +"++C8%8r   c                 .     j                   | g| }|S r   )jvp)rJ   tangentsrO   r$   s      r   rQ   z+generate_single_level_function.<locals>.jvp   s     &"&&s6X6r   r3   )rG   rM   rQ   rI   )r:   r*   typer   autogradfunction_SingleLevelFunctionstaticmethod)	r1   r$   rG   rI   rM   rQ   namer3   r:   s	   ``      @r   r0   r0   a   s    E
(D
  (()3D		 	 	5	57#G,$X.$)-8		
	I r   znot specifiedc           	         t        j                  | }t        j                  | }t        ||      D ci c]  \  }}t        |      | }	}}t        j                  |       \  }
}g }|t
        k7  }|r9t        ||      }|+t        d| dt        j                  |      d    d| d      t        |
      D ]  \  }}t        |t        j                        s|j                  |       2t        |      |	v r|j                  |	t        |                ]|r|j                   |||                {|j                   ||              t        j                  ||      S c c}}w )NzoThe autograd.Function's vmap staticmethod returned an incompatible (output, out_dims) tuple. Expected out_dims=zI to be compatible with the structure of `output`. out_dims has structure    z but output has structure zV. For more details, please see https://pytorch.org/docs/main/notes/extending.func.html)r?   arg_tree_leaveszipidtree_flattenNO_OUT_DIMSr   RuntimeError	enumerate
isinstancer   rA   appendtree_unflatten)outputsunwrapped_inputsorig_inputsr>   out_dimsflat_unwrapped_inputsflat_orig_inputs	unwrappedorigunwrapped_input_to_orig_inputflat_outputsspecrO   out_dims_specifiedflat_out_dimsir=   s                    r   rD   rD      s    #224DE--{;  ##8:JK%It 	9t%! %
  ,,W5L$F![01(DA  %%-J /**0*=*=h*G*J)K L,,06 2JK	 	 |, 
+	6&%,,/MM&!f:66MM76
CDMM'&-*:;<MM'&/*
+   ..M%s   E c                   "    e Zd ZU eed<   eed<   y)VmapInfo
batch_size
randomnessN)r*   r+   r,   int__annotations__str r   r   rt   rt      s    OOr   rt   c                 b    | j                   t        j                  j                  j                   uS r   )r   r   rT   Function)r$   s    r   has_overriden_vmap_ruler}     s#    !!)@)@)E)EEEr   c                     d}t        | t              st        |dt        |        dz         t	        |       dk(  st        |dt	        |        dz         y )Nz}Expected the vmap staticmethod to have two returns, an output and out_dims with pytree structure compatible with the output. zGot a z instead   zGot z returns instead)rb   tupler`   rS   len)rO   base_error_msgs     r   +validate_vmap_returns_tuple_of_two_elementsr   	  se    	J  fe$>fT&\N(,KKLLv;!>d3v;-?O,PPQQ r   c                    t        d t        j                  j                  j	                  |      d   D              rt        d|       |j                  r1t        |      rt        d|j                   d      t        | |g| S t        |      st        d|j                   d      t        | |j                  |g|i |S )Nc              3   P   K   | ]  }t        |t        j                           y wr   )rb   r   rA   ).0vals     r   	<genexpr>z,custom_function_call_vmap.<locals>.<genexpr>  s#       	3%s   $&r   z|Run vmap on autograd.Function with kwarg-only Tensor args. Please do not pass kwarg-only Tensors to autograd.Function. Got: zYou tried to vmap over a  , but it has both generate_vmap_rule=True and an overriden vmap staticmethod. Please set generate_vmap_rule=False or delete the overriden vmap staticmethod to avoid ambiguity. For more details, please see https://pytorch.org/docs/main/notes/extending.func.htmlz, but it does not have vmap support. Please override and implement the vmap staticmethod or set generate_vmap_rule=True. For more details, please see https://pytorch.org/docs/main/notes/extending.func.html)anyr   utils_pytreer^   NotImplementedErrorgenerate_vmap_ruler}   r`   r*   'custom_function_call_vmap_generate_rule custom_function_call_vmap_helperr   )r1   r$   r2   r&   s       r   custom_function_call_vmapr     s   
 ;;&&33F;A>  "8
 	
 ++"#45 )*;*D*D)E FJ K  7*
-5
 	
 ##45 %&7&@&@%A BF G
 	
 ,&++->AIMS r   c                 B     j                         t         j                          j                               }t	        |t
        j                  j                  j                         fd}t        |      \  }}t        j                  d |      r0 |       5  rt        |g| cd d d        S  ||i |cd d d        S  |       5   |||g|i |}	d d d        t        	       |	\  }
}fd}t        |
||||      S # 1 sw Y   KxY w# 1 sw Y   :xY w)N)ru   rv   c                       rj                         S t        j                  j                  t        j                  j	                  t        j                  j
                  j                              S r   )rC   r   r    _ExcludeDispatchKeyGuardDispatchKeySetDispatchKeyFuncTorchBatched)autograd_function_caser1   s   r   lower_to_nextz7custom_function_call_vmap_helper.<locals>.lower_to_nextL  sN    !$$&&8844''(<(<(M(MN r   c                 
    | d u S r   rz   )dims    r   r;   z2custom_function_call_vmap_helper.<locals>.<lambda>X  s
    3$; r   c                 &    || S t        | |      S r   )r
   )r=   out_dimr   s     r   r>   z1custom_function_call_vmap_helper.<locals>.wrap_fne  s'      	
  ?	
r   )rh   )r:   rt   ru   rv   rb   r   rT   rU   FunctionMetar   r?   tree_allr   r   rD   )r1   vmap_functionopr2   r&   infor   rE   in_dimsrO   rF   rh   r>   r   r   s   `            @@r   r   r   @  s0     %%'M))+))+D (ENN,C,C,P,PQ #1="I .8_ 	/%+B::	/ 	/ 8.v.		/ 	/ 
 MtWL/ALVLM/7!'h
 -,h( '	/ 	/M Ms   D	6D	D	DDc                 P    | d   }t        |t              r	| d d } | |fS | d   } | |fS )Nr   )rb   r   )re   rh   s     r   unpack_outputsr   q  sC    r{H(E"#2, H !*Hr   c                 h   t        || j                               \  }}t        ||| j                         | j	                               }| j                         5  t        |g| }d d d        t        t              sJ t        |      \  }}t        ||| j                               S # 1 sw Y   DxY wr   )r   r:   vmapify_autograd_functionru   rv   rC   r   rb   r   r   r   )r1   r$   r2   rE   r   vmapped_functionre   rh   s           r   r   r   z  s    "0;;L;L;N"O07K$:$:$<k>T>T>V 
			 N&'7M:LMN gu%%%&w/GX;+<+<+>??N Ns   B((B1c                     t        d      )Nz0NYI: Functionalize rule for custom_function_call)r`   )r1   r$   r   r2   s       r   "custom_function_call_functionalizer     s     I
JJr   c           
         	  fd}	 fd}	 fd}	 fd}d j                    }t        |t        j                  j                  ft        |      t        |      t        |      t        |      dd      		S )Nc                       t        j                        |  \  }}t        |t        j                        r||fS g ||S r   )r   rG   rb   r   rA   )r2   re   rh   r$   ru   r   rv   s      r   rG   z*vmapify_autograd_function.<locals>.forward  sX    
L%%w
J
 gu||,H$$%G%X%%r   c                      t        |      \  }}t               fd} t        |	|f
      ||       t         d      si  _         j                  j                  |i       y )Nc                 L   t        t                     }j                  || |       t        d | D              }t	        d      si _        j
                  j                  |i       t	        d      si _        j                  j                  |j                  i       y )Nc              3   l   K   | ],  }t        |t        j                        r|j                  nd  . y wr   )rb   r   rA   shape)r   inps     r   r   zRvmapify_autograd_function.<locals>.setup_context.<locals>.inner.<locals>.<genexpr>  s+      !ILZU\\:		D!s   24_pt_input_shapes_pt_saved_tensors_bdims_stack)	CtxCustomSaver   rI   r   hasattrr   updater   _pt_saved_tensors_bdims)rK   re   wrapped_ctxinput_shapesr$   rJ   keys       r   innerz?vmapify_autograd_function.<locals>.setup_context.<locals>.inner  s    
 (]_=K++KI ! !PV! L 3 23')$  ''l(;<3 ?@461--44{::<r   _pt_out_dims)r   r]   r   r   r   r   )rJ   rK   re   rh   r   r   r3   r$   ru   r   rv   s   `    @r   rI   z0vmapify_autograd_function.<locals>.setup_context  su    *73m	4	
h		

 '	 sN+!Ch0r   c                 "    t              }	 fd}t        |      } t        | j                  |   |f
       j                  |      \  }}t        || j                  |   
      }t        |t        j                        r|d fS g |d S )Nc                 B    t        |       } j                  |g| S r   )CtxWithSavedTensorsrQ   )saved_tensorsrR   r   r$   rJ   s      r   jvp_no_contextz>vmapify_autograd_function.<locals>.jvp.<locals>.jvp_no_context  s(    -c=AK($((@x@@r   )
r]   get_tangents_in_dimsr   r   r   	reductifyr   rb   r   rA   )rJ   rR   r   r   tangent_in_dimsout_tangentsout_tangents_dimsrO   r3   r$   ru   r   rv   s   `       r   rQ   z&vmapify_autograd_function.<locals>.jvp  s    m	A /wA+
,..s3_E	+

 

X+''' +S-=-=c-BJ
 fell+4< F=D= r   c                 P    t        	      }|d d } j                  |   }t        |t              s|f}t        d t	        ||      D              }
 fd} t        | j                  |   |ff       j                  |f      \  }}t        || j                  |         }|S )Nr   c              3   .   K   | ]  \  }}||nd   y wr   rz   )r   grad_outputin_dims      r   r   z>vmapify_autograd_function.<locals>.backward.<locals>.<genexpr>  s&      %
#V "-F47%
s   c                 L    | \  }}t        |      } j                  |g| S r   )r   rM   )rK   r   grad_outputsr   r$   rJ   s       r   backward_no_contextzHvmapify_autograd_function.<locals>.backward.<locals>.backward_no_context  s2    *0'M<-c=AK-$--kILIIr   )
r]   r   rb   r   r\   r   r   r   r   r   )rJ   r   r   grad_outputs_grad_outputs_in_dimsr   grad_insgrad_ins_dimsrO   r3   r$   ru   r   rv   s   `        r   rM   z+vmapify_autograd_function.<locals>.backward  s    m$Sb)"//4.6$8#: $ %
'*=:N'O%
  

	J
#
,//46JKM	#

 m
,#.- mWj#:N:Ns:S
 r   VmappedT)rG   rM   rQ   rI   r   )r*   rS   r   rT   r|   rW   )
r$   r   ru   rv   rG   rI   rQ   rM   rX   r3   s
   ````     @r   r   r     s    &'1 '1R! !. : &//01D		 	 "#G,$X.$)-8"&	

I r   c                     t        j                  |       \  }}t        j                  | }t        ||      D cg c]  \  }}|d n| }}}t        j                  ||      S c c}}w r   )r?   r^   r[   r\   rd   )
input_dimsrR   flat_in_dimsro   flat_tangentsr   tangentrO   s           r   r   r     st    ,,Z8L$**H5M  #<?FG V+F    ..	s   A#c                   8    e Zd ZU dZeedf   ed<   d Zd Zd Z	y)
WrappedCtx)_pt_reserved_attrs_pt_inner_ctx.r   c                     t        |t              s7t        |       j                  }|D ]  }t	        ||      st        d| d       || _        y )NzPyTorch reserves the zU field on ctx. Please name your fields on ctx something else to avoid name collision.)rb   r   rS   r   r   r`   r   )r   rJ   reserved_attrsrX   s       r   r   zWrappedCtx.__init__I  s`    #z*!$Z::N& sD)"+N+; <! !  !r   c                 .    t        | j                  |      S r   )getattrr   )r   rX   s     r   __getattr__zWrappedCtx.__getattr__V  s    t))400r   c                 ~    |t        |       j                  v r|| j                  |<   y t        | j                  ||      S r   )rS   r   __dict__setattrr   )r   rX   values      r   __setattr__zWrappedCtx.__setattr__Y  s:    4:000"'DMM$t))477r   N)
r*   r+   r,   r   r   ry   rx   r   r   r   rz   r   r   r   r   F  s$    *Qc3hQ!18r   r   c                   N     e Zd Zdgej                  Z fdZed        Z xZS )r   _pt_new_saved_tensorsc                 2    t         |   |       || _        y r   )r   r   r   )r   rJ   new_saved_tensorsr   s      r   r   zCtxWithSavedTensors.__init__d  s    %6"r   c                     | j                   S r   )r   )r   s    r   r   z!CtxWithSavedTensors.saved_tensorsh  s    )))r   )	r*   r+   r,   r   r   r   propertyr   r-   r.   s   @r   r   r   a  s0    1RJ4Q4QR7 * *r   r   c                   L     e Zd Zddgej                  Z fdZd Zd Z xZS )r   r   _pt_current_levelc                 @    t         |   |       d| _        || _        y )Nrz   )r   r   r   r   )r   rJ   r   r   s      r   r   zCtxCustomSave.__init__t  s     ')$!.r   c                 v    t        || j                        \  }} | j                  j                  |  || _        y r   )r   r   r   save_for_backwardr   r   tensorsunwrapped_tensorsbdimss       r   r   zCtxCustomSave.save_for_backwardy  s9    #1'4;Q;Q#R 5,,,.?@',$r   c                 v    t        || j                        \  }} | j                  j                  |  || _        y r   )r   r   r   save_for_forwardr   r   s       r   r   zCtxCustomSave.save_for_forward~  s9    #1'4;Q;Q#R 5+++->?',$r   )	r*   r+   r,   r   r   r   r   r   r-   r.   s   @r   r   r   m  s0    ! 
	&	&/
-
-r   r   c           	          t        | t              s| f} t        |t              s|f}t        |t              s|f}|t        |       dz  }t        fdt        | |||      D              }|S )Nr   c              3   F   K   | ]  \  }}}}t        ||||        y wr   )reductify_leaf)r   gigi_bdimi_bdimmaybe_ishaperu   s        r   r   zreductify.<locals>.<genexpr>  s.      -B 	r7FJEs   !)rb   r   r   r\   )
grad_inputgrad_input_bdim
input_bdimru   &target_shape_without_bdim_to_reduce_torO   s      `  r   r   r     s}     j%( ]
ou-*,j%( ]
-514Z71J. 142	2
 F Mr   c                 Z   | y ||| S ||| j                  |      S |J |>| j                  |      } t        | j                        }|||<   | j	                  |      } |}|/ t        t        j                  j                  |d f|      | |      S ||k7  r| j                  ||      } | S )N)r   rh   )
sum	unsqueezelistr   expandr   r   rA   sum_to_sizemovedim)r   r   r   ru   r  	new_shapes         r   r   r     s     :#5"z'9~~o..0 !!!))*5
))*	 *	*&&y1
$-9
tLL$$$d+
 <	> 	> _$''D
r   c                       fd}|S )Nc                 ,     |i |} | ||       |S r   rz   )rJ   r%   r&   r=   original_forwardoriginal_setup_contexts       r   new_forwardz8autograd_function_forward_rewritten.<locals>.new_forward  s#    !4262sD&1r   rz   )r  r  r  s   `` r   #autograd_function_forward_rewrittenr    s    
 r   c                   &     e Zd Zd fdZd Z xZS )AutogradFunctionApplyc                 $    t         |   d       y )Nautograd_function_applyr   r   s    r   r   zAutogradFunctionApply.__init__  s    23r   c                    	
 d 
|d   }|d   	t        |      }d | } G 	
fddt        j                  j                        } |j                  | S )Nargs_tensor_masknon_differentiable_idxc                   >    e Zd Zefd       Ze fd       Zy)5AutogradFunctionApply.__call__.<locals>.ApplyTemplatec                      d g \  }	t              dkD  r:g }t        |      D ]  \  }}|v s|j                  |         | j                  |  |S )Nr   )r   ra   rc   mark_non_differentiable)
rJ   r%   r=   non_differentiable_outputrr   r9   fwdfwd_argsr  saved_valuess
         r   rG   z=AutogradFunctionApply.__call__.<locals>.ApplyTemplate.forward  sx     (+4';(';$ -.202- )& 1 @1 665<<Q?@ 0C//1JKr   c                      d g| S r   rz   )rJ   gradbwdr  s     r   rM   z>AutogradFunctionApply.__call__.<locals>.ApplyTemplate.backward  s    46$666r   N)r*   r+   r,   rW   rG   rM   )r!  r  r  r  r  s   r   ApplyTemplater    s)      7 7r   r"  )r  r   rT   r|   r#   )r   r  r!  r  
fwd_kwargsr  length_of_tensor_argsnew_fwd_argsr"  r  r  s    ```     @@r   r"   zAutogradFunctionApply.__call__  sl    %&89!+,D!E #$4 5   6!67	7 	7ENN33 	7( #}""L11r   r'   r)   r.   s   @r   r  r    s    42r   r  r   )7typingr   r   torch.utils._pytreer   r   r?   torch._C._functorchr   r   r   r   torch._functorch.apisr   torch._functorch.utilsr	   torch._functorch.vmapr
   r   r   r   r   
torch._opsr   torch.autograd.forward_adr   r   r   py_implGradJvpr5   r0   r_   rD   rt   r}   r   Vmapr   r   r   r   Functionalizer   r   r   r   r   r   r   r   r  r  r  rz   r   r   <module>r3     s}     $ $  ' H  + ;8(; 84 9: < m001m//0 1 23~  ?J,/rz 
FR m001( 2(V.b
@ m99:K ;Ktr/~8 86	** 	*-J -8 ,0B ,08v"2/ "2J 01 r   