o
    ZhAp                     @   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__ Q/var/www/auris/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_CZ _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	GeneratedZflat_outr   r   r   custom_function_call_gradX   s   

r0   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                    r1   r   )r   )outputr3   r   r   wrap_fnq   s   
z@generate_single_level_function.<locals>.forward.<locals>.wrap_fn)	pytreeZtree_map_onlyr   TensorZenable_gradr   lowerr   !wrap_outputs_maintaining_identity)r.   unwrapped_operandsunwrapped_outputr7   r#   r-   r4   r   r   forwardd   s$   
  z/generate_single_level_function.<locals>.forwardc                    s     | ||S r   )setup_context)ctxinputsr6   r#   r   r   r@   x   s   z5generate_single_level_function.<locals>.setup_contextc                        j | g|R  }|S r   )backward)rA   ZgradsresultrC   r   r   rE   |      z0generate_single_level_function.<locals>.backwardc                    rD   r   )jvp)rA   tangentsrF   rC   r   r   rH      rG   z+generate_single_level_function.<locals>.jvpr/   )r?   rE   rH   r@   )r4   r(   typer   autogradfunctionZ_SingleLevelFunctionstaticmethod)r-   r#   r?   r@   rE   rH   namer/   r   r>   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).0Z	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)r8   arg_tree_leavesziptree_flattenNO_OUT_DIMSr
   RuntimeError	enumerate
isinstancer   r9   appendrO   tree_unflatten)outputsZunwrapped_inputsZorig_inputsr7   out_dimsZflat_unwrapped_inputsZflat_orig_inputsZunwrapped_input_to_orig_inputZflat_outputsspecrF   Zout_dims_specifiedZflat_out_dimsir6   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   ra      s   
 ra   c                 C   s   | j tjjj uS r   )r   r   rK   FunctionrC   r   r   r   has_overriden_vmap_rule  r   rh   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)rZ   tuplerX   rJ   len)rF   Zbase_error_msgr   r   r   +validate_vmap_returns_tuple_of_two_elements	  s   
rl   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   )rZ   r   r9   )rP   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_pytreerV   NotImplementedErrorgenerate_vmap_rulerh   rX   r(   'custom_function_call_vmap_generate_rule custom_function_call_vmap_helperr   )r-   r#   r.   r%   r   r   r   custom_function_call_vmap  s:   rv   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)rb   rc   c                      s&    r  S tjtjtjjjS r   )r:   r   r    Z_ExcludeDispatchKeyGuardZDispatchKeySetZDispatchKeyZ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   r5   X  s    z2custom_function_call_vmap_helper.<locals>.<lambda>c                    s   |d u r| S t | | S r   )r	   )r6   Zout_dim)r   r   r   r7   e  s
   
z1custom_function_call_vmap_helper.<locals>.wrap_fn)r^   )r4   ra   rb   rc   rZ   r   rK   rL   ZFunctionMetar   r8   Ztree_allr   rl   r;   )r-   Zvmap_functionopr.   r%   inforx   r<   in_dimsrF   r=   r^   r7   r   )rw   r   r-   r   ru   @  s0    
ru   c                 C   s6   | d }t |tr| d d } | |fS | d } | |fS )Nr   )rZ   rj   )r]   r^   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   r4   vmapify_autograd_functionrb   rc   r:   r   rZ   rj   r~   r   )r-   r#   r.   r<   r|   Zvmapped_functionr]   r^   r   r   r   rt   z  s   
rt   c                 G   s   t d)Nz0NYI: Functionalize rule for custom_function_call)rX   )r-   r#   rs   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   r?   rZ   r   r9   )r.   r]   r^   )r#   rb   r|   rc   r   r   r?     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   )rZ   r   r9   shape)rP   inpr   r   r   rn     s    
zRvmapify_autograd_function.<locals>.setup_context.<locals>.inner.<locals>.<genexpr>_pt_input_shapes_pt_saved_tensors_bdims_stack)	CtxCustomSaver   r@   rj   hasattrr   updater   _pt_saved_tensors_bdims)rB   r]   wrapped_ctxZinput_shapes)r#   rA   keyr   r   inner  s   

z?vmapify_autograd_function.<locals>.setup_context.<locals>.inner_pt_out_dims)r~   rO   r   r   r   r   )rA   rB   r]   r^   r   r/   r#   rb   r|   rc   )rA   r   r   r@     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   )CtxWithSavedTensorsrH   )saved_tensorsrI   r   r#   rA   r   r   jvp_no_context  s   
z>vmapify_autograd_function.<locals>.jvp.<locals>.jvp_no_context)
rO   get_tangents_in_dimsr   r   r   	reductifyr   rZ   r   r9   )rA   rI   r   r   Ztangent_in_dimsZout_tangentsZout_tangents_dimsrF   r   rA   r   rH     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   )rP   Zgrad_outputin_dimr   r   r   rn     s
    
z>vmapify_autograd_function.<locals>.backward.<locals>.<genexpr>c                    s$   | \}}t |} j|g|R  S r   )r   rE   )rB   r   grad_outputsr   r   r   r   backward_no_context  s   
zHvmapify_autograd_function.<locals>.backward.<locals>.backward_no_context)
rO   r   rZ   rj   rU   r   r   r   r   r   )	rA   r   r   Zgrad_outputs_Zgrad_outputs_in_dimsr   Zgrad_insZgrad_ins_dimsrF   r   r   r   rE     s*   

z+vmapify_autograd_function.<locals>.backwardZVmappedT)r?   rE   rH   r@   rs   )r(   rJ   r   rK   rg   rM   )	r#   r|   rb   rc   r?   r@   rH   rE   rN   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   )rP   r   Ztangentr   r   r   
<listcomp>
  s    z(get_tangents_in_dims.<locals>.<listcomp>)r8   rV   rT   rU   r\   )Z
input_dimsrI   Zflat_in_dimsr_   Zflat_tangentsrF   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.)rZ   r   rJ   r   r   rX   r   )r   rA   Zreserved_attrsrN   r   r   r   r   I  s   




zWrappedCtx.__init__c                 C   s   t | j|S r   )getattrr   )r   rN   r   r   r   __getattr__V  s   zWrappedCtx.__getattr__c                 C   s*   |t | jv r|| j|< d S t| j||S r   )rJ   r   __dict__setattrr   )r   rN   valuer   r   r   __setattr__Y  s   
zWrappedCtx.__setattr__N)
r(   r)   r*   r   rj   rf   re   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   rA   Z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   rA   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   ZtensorsZunwrapped_tensorsZ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)rP   giZgi_bdimZi_bdimZmaybe_ishaperb   r   r   rn     s
    

zreductify.<locals>.<genexpr>)rZ   rj   rk   rU   )
grad_inputgrad_input_bdim
input_bdimrb   &target_shape_without_bdim_to_reduce_torF   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|   r^   )
sumZ	unsqueezelistr   expandr   r   r9   Zsum_to_sizeZmovedim)r   r   r   rb   r   Z	new_shaper   r   r   r     s0   



r   c                    s    fdd}|S )Nc                    s    |i |}| || |S r   r   )rA   r$   r%   r6   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   )rk   rY   r[   Zmark_non_differentiable)rA   r$   r6   Znon_differentiable_outputr`   r2   )fwdfwd_argsr   saved_valuesr   r   r?     s   

z=AutogradFunctionApply.__call__.<locals>.ApplyTemplate.forwardc                    s    d g|R  S r   r   )rA   Zgrad)bwdr   r   r   rE     s   z>AutogradFunctionApply.__call__.<locals>.ApplyTemplate.backwardN)r(   r)   r*   rM   r?   rE   r   r   r   r   r   r   r   r   ApplyTemplate  s
    r   )r   r   rK   rg   r"   )	r   r   r   r   Z
fwd_kwargsr   Zlength_of_tensor_argsZnew_fwd_argsr   r   r   r   r!     s    
zAutogradFunctionApply.__call__r&   r'   r   r   r   r   r     s    r   r   )7typingr   r   Ztorch.utils._pytreerp   rq   r8   Ztorch._C._functorchr   r   r   r   Ztorch._functorch.apisr   Ztorch._functorch.utilsr   Ztorch._functorch.vmapr	   r
   r   r   r   Z
torch._opsr   Ztorch.autograd.forward_adr   r   r   Zpy_implZGradZJvpr0   r,   rW   r;   ra   rh   rl   ZVmaprv   ru   r~   rt   ZFunctionalizer   r   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sP   


?
Y

+1	

y?
!
;	
%