o
    IhAp                     @   s  d dl mZ d dlZd dlm  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
 d
eZe Zeejeejdd Zdd Z dZ!e!fddZ"G dd deZ#dd Z$dd Z%eej&dd Z'dd Z(dd Z)dd Z*eej+d d! Z,d"d# Z-d$d% Z.G d&d' d'Z/G d(d) d)e/Z0G d*d+ d+e/Z1	d4d,d-Z2	d4d.d/Z3d0d1 Z4G d2d3 d3eZ5e5 Z6dS )5    )
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                       s*   e Zd Zd fddZ fddZ  ZS )!CustomFunctionHigherOrderOperatorreturnNc                       t  d d S )Ncustom_function_callsuper__init__self	__class__ V/var/www/vscode/kcb/lib/python3.10/site-packages/torch/_functorch/autograd_function.pyr   !      z*CustomFunctionHigherOrderOperator.__init__c                    s4   t j rt j|g|R i |S |j|i |S N)torch_C _are_functorch_transforms_activer   __call__apply)r   autograd_functionargskwargsr   r   r   r"   $   s   
z*CustomFunctionHigherOrderOperator.__call__r   N__name__
__module____qualname__r   r"   __classcell__r   r   r   r   r       s    r   c                 G   s@   t | |}t  |j| }W d    |S 1 sw   Y  |S r   )generate_single_level_functionr   r#   )interpreterr$   operands	Generatedflat_outr   r   r   custom_function_call_gradX   s   

r2   c                    sz      fdd} fdd} fdd} fdd} j d	}t|tjjjft|t|t|t|d
}|S )Nc               
      s   t tjfdd| }t 8 td$   t g|R  }W d    n1 s-w   Y  W d    n1 s<w   Y  W d    n1 sKw   Y  fdd}t||| |S )Nc                    
   t |  S r   )r   )xlevelr   r   <lambda>f   s   
 zAgenerate_single_level_function.<locals>.forward.<locals>.<lambda>Tc                    r3   r   )r   )outputr5   r   r   wrap_fnq   s   
z@generate_single_level_function.<locals>.forward.<locals>.wrap_fn)	pytreetree_map_onlyr   Tensorenable_gradr   lowerr   !wrap_outputs_maintaining_identity)r/   unwrapped_operandsunwrapped_outputr9   r$   r.   r6   r   r   forwardd   s$   
  z/generate_single_level_function.<locals>.forwardc                    s     | ||S r   )setup_context)ctxinputsr8   r$   r   r   rD   x   s   z5generate_single_level_function.<locals>.setup_contextc                        j | g|R  }|S r   )backward)rE   gradsresultrG   r   r   rI   |      z0generate_single_level_function.<locals>.backwardc                    rH   r   )jvp)rE   tangentsrK   rG   r   r   rM      rL   z+generate_single_level_function.<locals>.jvpr0   )rC   rI   rM   rD   )r6   r)   typer   autogradfunction_SingleLevelFunctionstaticmethod)r.   r$   rC   rD   rI   rM   namer0   r   rB   r   r-   a   s    

r-   znot specifiedc                 C   s   t j| }t j| }dd t||D }t | \}}	g }
|tk}|r?t||	}|d u r?td| dt |d  d|	 dt|D ]4\}}t|t	j
sS|
| qCt||v rc|
|t|  qC|rp|
||||  qC|
|| qCt |
|	S )Nc                 S   s   i | ]	\}}t ||qS r   )id).0	unwrappedorigr   r   r   
<dictcomp>   s    z5wrap_outputs_maintaining_identity.<locals>.<dictcomp>zoThe 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tree_flattenNO_OUT_DIMSr
   RuntimeError	enumerate
isinstancer   r<   appendrU   tree_unflatten)outputsunwrapped_inputsorig_inputsr9   out_dimsflat_unwrapped_inputsflat_orig_inputsunwrapped_input_to_orig_inputflat_outputsspecrK   out_dims_specifiedflat_out_dimsir8   r   r   r   r?      s>   



r?   c                   @   s   e Zd ZU eed< eed< dS )VmapInfo
batch_size
randomnessN)r)   r*   r+   int__annotations__strr   r   r   r   rp      s   
 rp   c                 C   s   | j tjjj uS r   )r   r   rP   FunctionrG   r   r   r   has_overriden_vmap_rule  r   rw   c                 C   sN   d}t | tst|dt|  d t| dks%t|dt|  d d S )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)ra   tupler_   rO   len)rK   base_error_msgr   r   r   +validate_vmap_returns_tuple_of_two_elements	  s   
r|   c                 O   s   t dd tjj|d D rtd| |jr0t|r'td|j	 dt
| |g|R  S t|s=td|j	 dt| |j|g|R i |S )Nc                 s   s    | ]	}t |tjV  qd S r   )ra   r   r<   )rV   valr   r   r   	<genexpr>  s
    

z,custom_function_call_vmap.<locals>.<genexpr>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_rulerw   r_   r)   'custom_function_call_vmap_generate_rule custom_function_call_vmap_helperr   )r.   r$   r/   r&   r   r   r   custom_function_call_vmap  s:   r   c                    s    t  d}t|tjjj  fdd}t	|\}}t
dd |rW|    rAt|g|R  W  d    S ||i |W  d    S 1 sRw   Y  |  |||g|R i |}	W d    n1 sqw   Y  t|	 |	\}
}fdd}t|
||||dS )	N)rq   rr   c                      s&    r  S tjtjtjjjS r   )r>   r   r    _ExcludeDispatchKeyGuardDispatchKeySetDispatchKeyFuncTorchBatchedr   )autograd_function_caser.   r   r   lower_to_nextL  s
   z7custom_function_call_vmap_helper.<locals>.lower_to_nextc                 S   s   | d u S r   r   )dimr   r   r   r7   X  s    z2custom_function_call_vmap_helper.<locals>.<lambda>c                    s   |d u r| S t | | S r   )r	   )r8   out_dim)r   r   r   r9   e  s
   
z1custom_function_call_vmap_helper.<locals>.wrap_fn)rg   )r6   rp   rq   rr   ra   r   rP   rQ   FunctionMetar   r:   tree_allr   r|   r?   )r.   vmap_functionopr/   r&   infor   r@   in_dimsrK   rA   rg   r9   r   )r   r   r.   r   r   @  s0    
r   c                 C   s6   | d }t |tr| d d } | |fS | d } | |fS )Nr   )ra   ry   )rd   rg   r   r   r   unpack_outputsq  s   
r   c                 G   s   t ||  \}}t|||  |  }|   t|g|R  }W d    n1 s+w   Y  t|ts7J t	|\}}t
|||  S r   )r   r6   vmapify_autograd_functionrq   rr   r>   r   ra   ry   r   r   )r.   r$   r/   r@   r   vmapped_functionrd   rg   r   r   r   r   z  s   
r   c                 G   s   t d)Nz0NYI: Functionalize rule for custom_function_call)r_   )r.   r$   r   r/   r   r   r   "custom_function_call_functionalize  s   r   c           	   	      s   fdd} fdd} fdd} fdd}d	j  }t|tjjft|t|t|t|d
d  S )Nc                     s:   t  j|  \}}t|tjr||fS g ||R S r   )r   rC   ra   r   r<   )r/   rd   rg   )r$   rq   r   rr   r   r   rC     s   
z*vmapify_autograd_function.<locals>.forwardc                    s`   t |\}}t fdd}t||f|| t ds&i  _ j|i d S )Nc                    sr   t t } || | tdd | D }tdsi _j|i tds.i _j|ji d S )Nc                 s   s&    | ]}t |tjr|jnd V  qd S r   )ra   r   r<   shape)rV   inpr   r   r   r~     s    
zRvmapify_autograd_function.<locals>.setup_context.<locals>.inner.<locals>.<genexpr>_pt_input_shapes_pt_saved_tensors_bdims_stack)	CtxCustomSaver   rD   ry   hasattrr   updater   _pt_saved_tensors_bdims)rF   rd   wrapped_ctxinput_shapes)r$   rE   keyr   r   inner  s   

z?vmapify_autograd_function.<locals>.setup_context.<locals>.inner_pt_out_dims)r   rU   r   r   r   r   )rE   rF   rd   rg   r   r0   r$   rq   r   rr   )rE   r   r   rD     s   
z0vmapify_autograd_function.<locals>.setup_contextc                    sz   t } fdd}t|}t| j| |f j|\}}t|| j| }t|tj	r6|d fS g |d R S )Nc                    s   t | } j|g|R  S r   )CtxWithSavedTensorsrM   )saved_tensorsrN   r   r$   rE   r   r   jvp_no_context  s   
z>vmapify_autograd_function.<locals>.jvp.<locals>.jvp_no_context)
rU   get_tangents_in_dimsr   r   r   	reductifyr   ra   r   r<   )rE   rN   r   r   tangent_in_dimsout_tangentsout_tangents_dimsrK   r   rE   r   rM     s"   
z&vmapify_autograd_function.<locals>.jvpc           	         s   t }|d d } j| }t|ts|f}tdd t||D } fdd}t| j| |ff j|f\}}t|| j	| }|S )Nr   c                 s   s$    | ]\}}|d ur|nd V  qd S r   r   )rV   grad_outputin_dimr   r   r   r~     s
    
z>vmapify_autograd_function.<locals>.backward.<locals>.<genexpr>c                    s$   | \}}t |} j|g|R  S r   )r   rI   )rF   r   grad_outputsr   r   r   r   backward_no_context  s   
zHvmapify_autograd_function.<locals>.backward.<locals>.backward_no_context)
rU   r   ra   ry   r\   r   r   r   r   r   )	rE   r   r   grad_outputs_grad_outputs_in_dimsr   grad_insgrad_ins_dimsrK   r   r   r   rI     s*   

z+vmapify_autograd_function.<locals>.backwardVmappedT)rC   rI   rM   rD   r   )r)   rO   r   rP   rv   rS   )	r$   r   rq   rr   rC   rD   rM   rI   rT   r   r   r   r     s    	)r   c                 C   s8   t | \}}t j| }dd t||D }t ||S )Nc                 S   s    g | ]\}}|d u rd n|qS r   r   )rV   r   tangentr   r   r   
<listcomp>
  s    z(get_tangents_in_dims.<locals>.<listcomp>)r:   r]   r[   r\   rc   )
input_dimsrN   flat_in_dimsrl   flat_tangentsrK   r   r   r   r     s   
r   c                   @   s:   e Zd ZU dZeedf ed< dd Zdd Zdd	 Z	d
S )
WrappedCtx)_pt_reserved_attrs_pt_inner_ctx.r   c                 C   sB   t |tst| j}|D ]}t||sqtd| d|| _d S )NzPyTorch reserves the zU field on ctx. Please name your fields on ctx something else to avoid name collision.)ra   r   rO   r   r   r_   r   )r   rE   reserved_attrsrT   r   r   r   r   I  s   




zWrappedCtx.__init__c                 C   s   t | j|S r   )getattrr   )r   rT   r   r   r   __getattr__V  s   zWrappedCtx.__getattr__c                 C   s*   |t | jv r|| j|< d S t| j||S r   )rO   r   __dict__setattrr   )r   rT   valuer   r   r   __setattr__Y  s   
zWrappedCtx.__setattr__N)
r)   r*   r+   r   ry   ru   rt   r   r   r   r   r   r   r   r   F  s
   
 r   c                       s6   e Zd ZdgejR Z fddZedd Z  ZS )r   _pt_new_saved_tensorsc                    s   t  | || _d S r   )r   r   r   )r   rE   new_saved_tensorsr   r   r   r   d  s   
zCtxWithSavedTensors.__init__c                 C   s   | j S r   )r   r   r   r   r   r   h  s   z!CtxWithSavedTensors.saved_tensors)	r)   r*   r+   r   r   r   propertyr   r,   r   r   r   r   r   a  s
    r   c                       s<   e Zd ZddgejR Z fddZdd Zdd Z  ZS )	r   r   _pt_current_levelc                    s   t  | d| _|| _d S )Nr   )r   r   r   r   )r   rE   r   r   r   r   r   t  s   
zCtxCustomSave.__init__c                 G   &   t || j\}}| jj|  || _d S r   )r   r   r   save_for_backwardr   r   tensorsunwrapped_tensorsbdimsr   r   r   r   y     
zCtxCustomSave.save_for_backwardc                 G   r   r   )r   r   r   save_for_forwardr   r   r   r   r   r   ~  r   zCtxCustomSave.save_for_forward)	r)   r*   r+   r   r   r   r   r   r,   r   r   r   r   r   m  s    r   c                    sh   t | ts| f} t |ts|f}t |ts|f}|d u r"t| d }t fddt| |||D }|S )Nr   c                 3   s(    | ]\}}}}t ||| |V  qd S r   )reductify_leaf)rV   gigi_bdimi_bdimmaybe_ishaperq   r   r   r~     s
    

zreductify.<locals>.<genexpr>)ra   ry   rz   r\   )
grad_inputgrad_input_bdim
input_bdimrq   &target_shape_without_bdim_to_reduce_torK   r   r   r   r     s"   


	r   c                 C   s   | d u rd S |d u r|d u r| S |d ur|d u r|  |S |d us#J |d u r<| |} t| j}|||< | |} |}|d urNttjj|d f|d| |S ||krX| 	||} | S )N)r   rg   )
sum	unsqueezelistr   expandr   r   r<   sum_to_sizemovedim)r   r   r   rq   r   	new_shaper   r   r   r     s0   



r   c                    s    fdd}|S )Nc                    s    |i |}| || |S r   r   )rE   r%   r&   r8   original_forwardoriginal_setup_contextr   r   new_forward  s   z8autograd_function_forward_rewritten.<locals>.new_forwardr   )r   r   r   r   r   r   #autograd_function_forward_rewritten  s   r   c                       s&   e Zd Zd fddZdd Z  ZS )AutogradFunctionApplyr   Nc                    r   )Nautograd_function_applyr   r   r   r   r   r     r   zAutogradFunctionApply.__init__c           	         sR   d |d }|d t |}d | }G  fdddtjj}|j| S )Nargs_tensor_masknon_differentiable_idxc                       s4   e Zd ZefddZe fddZdS )z5AutogradFunctionApply.__call__.<locals>.ApplyTemplatec                    sV    d gR  \}t dkr)g }t|D ]\}}|v r#|| q| j|  |S )Nr   )rz   r`   rb   mark_non_differentiable)rE   r%   r8   non_differentiable_outputro   r4   )fwdfwd_argsr   saved_valuesr   r   rC     s   

z=AutogradFunctionApply.__call__.<locals>.ApplyTemplate.forwardc                    s    d g|R  S r   r   )rE   grad)bwdr   r   r   rI     s   z>AutogradFunctionApply.__call__.<locals>.ApplyTemplate.backwardN)r)   r*   r+   rS   rC   rI   r   r   r   r   r   r   r   r   ApplyTemplate  s
    r   )r   r   rP   rv   r#   )	r   r   r   r   
fwd_kwargsr   length_of_tensor_argsnew_fwd_argsr   r   r   r   r"     s    
zAutogradFunctionApply.__call__r'   r(   r   r   r   r   r     s    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Jvpr2   r-   r^   r?   rp   rw   r|   Vmapr   r   r   r   Functionalizer   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sP   


?
Y

+1	

y?
!
;	
%