U
    ªÊ¹j.  ã                   @   s�   d dl Z d dlm  mZ d dlmZ d dlZdd„ Zdd„ Z	dd„ Z
d	d
„ Zdd„ Zejdd„ ƒZdd„ Zdd„ Zdd„ Zdd„ Zdd„ ZdS )é    N)Ú
namedtuplec                    s   t ˆƒ‰ ‡ ‡fdd„}|S )Nc               
      sŽ   ˆ  d¡r ˆ d¡j}|| |ŽS ˆ  d¡s4ˆ  d¡r„ˆ  d¡rBdnd}|dkrRdnd}ˆ |¡j}td|› dˆ› d|› d|› d�	ƒ‚ˆ | |ŽS )	NÚautogradÚsave_for_backwardÚbackwardzWe found a 'z' registration for ú at z but were unable to find a 'zÔ' registration. To use the CustomOp API to register a backward formula, please provide us both a backward function and a 'save for backward' function via `impl_backward` and `impl_save_for_backward` respectively.)Z	_has_implÚ	_get_implÚfuncÚlocationÚRuntimeError)ÚargsÚkwargsÚkernelÚmissingÚfoundÚloc©Zautograd_fallbackÚ	custom_op© úX/var/www/html/bwave/python/venv/lib/python3.8/site-packages/torch/_custom_op/autograd.pyÚinner   s    

þÿz*autograd_kernel_indirection.<locals>.inner)Úautograd_not_implemented)r   r   r   r   r   Úautograd_kernel_indirection   s    r   c                    s   ‡ fdd„}|S )Nc               
      sP   t  ¡ r$t dd„ | |f¡r$tdƒ‚t j ¡ � ˆ | |ŽW  5 Q R £ S Q R X d S )Nc                 S   s   t | tjƒo| jS ©N)Ú
isinstanceÚtorchÚTensorZrequires_grad©Úxr   r   r   Ú<lambda>3   ó    z:autograd_not_implemented.<locals>.kernel.<locals>.<lambda>z.Autograd has not been implemented for operator)r   Zis_grad_enabledÚpytreeZtree_anyr
   Ú_CÚ_AutoDispatchBelowAutograd)r   r   ©r   r   r   r   1   s     ÿz(autograd_not_implemented.<locals>.kernelr   )r   r   r   r#   r   r   0   s    r   c              	   C   s¾   |d k	rºt |tƒs|f}n|}t|ƒt|ƒks2t‚g }tt||ƒƒD ]f\}\}}t |tjƒrl|sD| |¡ qDt |t	ƒr†|sD| 
|¡ qD|rDtd|› d|› dt|ƒ› d�ƒ‚qD|rº| j|Ž  d S )NzWith output_differentiability=z	. At idx z , we received an object of type za that is not a Tensor, so it cannot have be marked as differentiable in output_differentiability.)r   ÚtupleÚlenÚAssertionErrorÚ	enumerateÚzipr   r   ÚappendÚlistÚextendr
   ÚtypeÚmark_non_differentiable)ÚctxÚoutputÚoutput_differentiabilityZtuple_outputZnon_differentiable_tensorsÚidxZdifferentiableÚoutr   r   r   r-   ;   s*    



ÿr-   c                    s   ‡ ‡‡‡‡‡fdd„}|S )Nc                     sp   t  | ¡\}‰d ‰ ‡‡ ‡‡‡‡fdd„}‡‡‡ fdd„}tˆjd ||ƒ}|j|Ž }ˆ d k	s`t‚t  t|ƒˆ ¡S )Nc              	      s’   |   d¡ t t|ƒˆ¡}tj ¡ � ˆ |Ž }W 5 Q R X tˆt dd„ |¡ƒ}tˆ|ƒ}ˆ||ƒ}t	| ||fƒ t
| |ˆƒ t |¡\}‰t|ƒS )NTc                 S   s   t | ƒS r   )r,   )Úargr   r   r   r   o   r   zKconstruct_autograd_kernel.<locals>.apply.<locals>.forward.<locals>.<lambda>)Zset_materialize_gradsr    Útree_unflattenr*   r   r!   r"   Únamedtuple_argsÚtree_mapÚsave_pytree_for_backwardr-   Útree_flattenr$   )r.   Ú	flat_argsr   r/   Ú	args_infoZsave_for_backward_fn_inputsZto_saveÚflat_output)Úop_overloadÚout_specr0   Úsave_for_backward_fnÚschemaÚspecr   r   Úforwardg   s    
 ÿ

z9construct_autograd_kernel.<locals>.apply.<locals>.forwardc                    sd   ˆd k	st ‚t t|ƒˆ¡}t| ƒ\}}tƒ }t|tƒs>|f}ˆ ||f|žŽ }t|ˆ|ƒ t	||ƒS r   )
r&   r    r4   r*   Úunpack_savedÚobjectr   r$   Úvalidate_grad_inputs_dictÚgrad_inputs_dict_to_flat_tuple)r.   Zflat_grad_outputZgradsZsavedr:   Z	inner_ctxÚgrad_inputs_dict)Úbackward_fnr   r=   r   r   r   {   s    
z:construct_autograd_kernel.<locals>.apply.<locals>.backwardZ	_customop)r    r8   Úgen_autograd_functionZ_opnameÚapplyr&   r4   r*   )r   r9   rA   r   Úgenerated_clsr;   ©rG   r   r<   r0   r>   r?   )r=   r@   r   rI   c   s      ÿ
z(construct_autograd_kernel.<locals>.applyr   )r?   r0   r   r<   r>   rG   rI   r   rK   r   Úconstruct_autograd_kernel[   s    .rL   c                 C   s$   t | tjjft|ƒt|ƒdœƒ}|S )N)rA   r   )r,   r   r   ÚFunctionÚstaticmethod)ÚnamerA   r   rJ   r   r   r   rH   ”   s    þýrH   c                 C   s.   dd„ | j jD ƒ}t| jƒd }t||ƒ}|S )Nc                 S   s   g | ]
}|j ‘qS r   )rO   ©Ú.0r3   r   r   r   Ú
<listcomp>¢   s     z'namedtuple_args_cls.<locals>.<listcomp>Ú_args)Ú	argumentsÚflat_allÚstrrO   r   )r?   ÚattribsrO   Ú	tuple_clsr   r   r   Únamedtuple_args_cls    s    
rY   c                 C   s   t |tƒst‚t| ƒ}||Ž S r   )r   r$   r&   rY   )r?   r   rX   r   r   r   r5   ©   s    r5   c                    sÄ  ‡ fdd„}t | tƒs(|dt| ƒ› �ƒ dd„ ˆ jjjD ƒ}|  ¡ }||krb|d|› d|› d�ƒ |  ¡ D �]R\}}t||ƒ}t |t	ƒ�rdt |t
t	fƒs²|d	|› d
t|ƒ› d�ƒ t|ƒt|ƒksä|d	|› dt|ƒ› dt|ƒ› �ƒ tt||ƒƒD ]n\}	\}
}|
d k�r
qòt |
tjƒ�s6|d	|› dt|
ƒ› d|	› �ƒ |tjkrò|d	|› d|	› d|	› d|› �ƒ qòqj|d k�rpqjt |tjƒ�s˜|dt|ƒ› d|› d�ƒ |tjkrj|d|› d|› d|› d�ƒ qjd S )Nc                    s*   ˆ   d¡}tdˆ › d|j› d| › �ƒ‚d S )Nr   z%In the backward function defined for r   z using the CustomOp API, )r   r
   r	   )Úwhatr   ©Ú
forward_opr   r   Úerror°   s    
ÿz(validate_grad_inputs_dict.<locals>.errorzBexpected the output of the backward function to be a dict but got c                 S   s   h | ]}|j  ¡ r|j’qS r   )r,   Zis_tensor_likerO   rP   r   r   r   Ú	<setcomp>º   s    
ÿz,validate_grad_inputs_dict.<locals>.<setcomp>z3expected the returned grad_input dict to have keys z	 but got zÖ. The backward function must return a gradient (can be None) for each arg to the CustomOp that may be a Tensor or Sequence[Tensor]. Args declared to be non-Tensor-like types should not appear in the grad_input dictzfor input 'zR' expected the grad_input dict to hold a list of gradients but got object of type Ú.z1' expected the grad_input dict to hold a list of z gradients but got z\' expected the grad_input dict to hold a list of None or Tensor gradients but got object of z
 at index z(', got a Tensor as the gradient for the z(-th value but expected None because the z(-th value was not a Tensor (it was type zgot object of type z as the gradient for input 'z:', but expected the gradient to be either None or a Tensorz(got a Tensor as the gradient for input 'z3' but expected None as the gradient because input 'z ' was not a Tensor (it was type z).)r   Údictr,   Z_schemarT   rU   ÚkeysÚitemsÚgetattrr*   r$   r%   r'   r(   r   r   )rF   r\   r:   r]   Zexpected_keysZactual_keysrO   ZgradÚarg_infor1   ÚgÚinfor   r[   r   rD   ¯   s8    

"

"

rD   c                 C   sZ   g }|  ¡  ¡ D ]6\}}|| kr8| t dd„ |¡¡ q| | | ¡ qtt |¡d ƒS )Nc                 S   s   d S r   r   r   r   r   r   r   î   r   z0grad_inputs_dict_to_flat_tuple.<locals>.<lambda>r   )Ú_asdictrb   r)   r    r6   r$   r8   )rF   r:   ÚresultrO   rd   r   r   r   rE   ê   s    rE   c           	      C   s‚   t  |¡\}}t|ƒ}dd„ t|ƒD ƒ}dd„ t|ƒD ƒ}dd„ |D ƒ}dd„ |D ƒ}|| _|| _| j|Ž  || _|| _|| _	d S )Nc                 S   s    g | ]\}}t |tjƒr|‘qS r   ©r   r   r   ©rQ   r1   Úthingr   r   r   rR   ú   s    ÿz,save_pytree_for_backward.<locals>.<listcomp>c                 S   s    g | ]\}}t |tjƒs|‘qS r   ri   rj   r   r   r   rR   ü   s    ÿc                 S   s   g | ]}t |tjƒr|‘qS r   ri   ©rQ   rk   r   r   r   rR   þ   s      c                 S   s   g | ]}t |tjƒs|‘qS r   ri   rl   r   r   r   rR   ÿ   s      )
r    r8   r%   r'   r@   Únum_eltsr   Útensor_idxsÚsaved_non_tensorsÚnon_tensor_idxs)	r.   ÚstuffÚ
flat_stuffr@   rm   rn   rp   ZtensorsZnon_tensorsr   r   r   r7   ÷   s    
r7   c                 C   s^   d g| j  }t| j| jƒD ]\}}|||< qt| j| jƒD ]\}}|||< q:t || j¡}|S r   )	rm   r(   Zsaved_tensorsrn   ro   rp   r    r4   r@   )r.   rr   Ztensorr1   Z
non_tensorrq   r   r   r   rB   
  s    

rB   )r   Ztorch.utils._pytreeÚutilsZ_pytreer    Úcollectionsr   Ú	functoolsr   r   r-   rL   rH   Ú	lru_cacherY   r5   rD   rE   r7   rB   r   r   r   r   Ú<module>   s    9
;