U
    ©Ê¹j8P  ã                	   @   sB  d dl Z d dlZd dlZd dlmZ d dlm  m  m  mZ	 d dl
m  m  mZ ejjZd dlmZmZmZ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 d dlmZ d dlm Z  dd	l!m"Z"m#Z# G d
d„ de j$ƒZ%eeeee&ee" f ee%e%f dœdd„Z'eeee&ee" f eeeej(e)f eej(e*f f  dœdd„Z+eeedœdd„Z,eee*dœdd„Z-eee* dœdd„Z.eee&dœdd„Z/e#e&e#dœdd„Z0e#ddœd d!„Z1d"d#„ Z2e2ej(ej(ej(d$œd%d&„ƒZ3e2ej(ej(ej(d$œd'd(„ƒZ4e2ej(ej(ej(d$œd)d*„ƒZ5ee6dœd+d,„Z7eee*ed-œd.d/„Z8dS )0é    N)ÚTupleÚCallableÚDictÚSetÚListÚOptionalÚUnion)ÚGraphModule)ÚNode)ÚObserverBaseÚFakeQuantizeBase)Úgetattr_from_fqn)Ú_is_activation_post_processé   )ÚNSNodeTargetTypeÚNSResultsTypec                   @   s4   e Zd Ze ¡ Ze ¡ Ze ¡ Ze ¡ Ze ¡ Z	dS )ÚNodeInputOrOutputTypeN)
Ú__name__Ú
__module__Ú__qualname__ÚenumÚautoÚFP32ÚINT8ÚFP16ÚUNKNOWNZFP32_OR_INT8© r   r   úS/var/www/html/bwave/python/venv/lib/python3.8/site-packages/torch/ao/ns/fx/utils.pyr      s
   r   )ÚnodeÚgmÚ
logger_clsÚnode_type_to_io_type_mapÚreturnc                    sî  |d }|d }|d }|d }|d }|d }	|d }
|d }| j d	krÚ| j|kr`tjtjfS | j|krvtjtjfS | j|krŒtjtjfS | j|krÊt| |d
ƒ}t|tƒs°t	‚t
||||ƒ\}}||fS tjtjfS �n| j dk�rÖ| j dksôt	‚t| jtƒ�st	‚t|| jƒ‰ t‡ fdd„|
D ƒƒ}tˆ |ttfƒ�s@|�rvt| |d
ƒ}t|tƒ�s\t	‚t
||||ƒ\}}||fS t‡ fdd„|D ƒƒ}t‡ fdd„|	D ƒƒ}|�r´tjtjfS |�rÆtjtjfS tjtjfS �n| j dk�rÞ| jdk�r&t| |d
ƒ}t|tƒ�s
t	‚t
||||ƒ\}}|tjfS | jdk�r�t| |d
ƒ}t|tƒ�sNt	‚t
||||ƒ\}}t| |dƒ}|tjk�s†t	|› d�ƒ‚|tjfS | j|k�rÒt| |d
ƒ}t|tƒ�s¸t	‚t
||||ƒ\}}||fS tjtjfS tjtjfS d S )NZfuns_io_type_fp32Zfuns_io_type_fp16Zfuns_io_type_int8Zfuns_io_type_fp32_or_int8Zmods_io_type_fp32Zmods_io_type_int8Úmods_io_type_fp32_or_int8Zmeths_io_type_fp32_or_int8Úcall_functionr   Úcall_modulec                 3   s   | ]}t ˆ |ƒV  qd S ©N©Ú
isinstance©Ú.0Útarget_type©Úmodr   r   Ú	<genexpr>O   s    z7get_node_first_input_and_output_type.<locals>.<genexpr>c                 3   s   | ]}t ˆ |ƒV  qd S r&   r'   r)   r,   r   r   r.   a   s    c                 3   s   | ]}t ˆ |ƒV  qd S r&   r'   r)   r,   r   r   r.   d   s    Úcall_methodÚ
dequantizeÚtor   z handling needs to be added)ÚopÚtargetr   r   r   r   Úget_normalized_nth_inputr(   r
   ÚAssertionErrorÚ$get_node_first_input_and_output_typer   Ústrr   Úanyr   r   ÚtorchZfloat16)r   r   r    r!   ZFUNS_IO_TYPE_FP32ZFUNS_IO_TYPE_FP16ZFUNS_IO_TYPE_INT8ZFUNS_IO_TYPE_FP32_OR_INT8ZMODS_IO_TYPE_FP32ZMODS_IO_TYPE_INT8ÚMODS_IO_TYPE_FP32_OR_INT8ZMETHS_IO_TYPE_FP32_OR_INT8Z	first_argZ_prev_node_input_typeZprev_node_output_typeÚ"is_known_fp32_or_int8_input_moduleZis_known_fp32_input_moduleZis_known_int8_input_moduleÚ	prev_nodeZcur_node_dtype_targetr   r,   r   r6   &   sÜ    




   ÿýÿÿþ   ÿýÿÿ   ÿý
   ÿýÿþ
   ÿýr6   )r   r   r!   r"   c                    sF  t | |dƒ}t|tƒsdS |d }dd„ }|jdkrz|jtjkrN|||ddƒS |jtjtj	tj
tjfkrv|||dd	ƒS dS |jd
k�rBt|jtƒs–t‚t||jƒ‰ tˆ tjtjtjtjtjtjtjtjtjtjtjtjtjtjtjtj tj!tj"tj#tj$tj%tjtj&tj'fƒ�rˆ j(ˆ j)fS t*‡ fdd„|D ƒƒ}|�rBt+|||ƒS dS )z{
    Returns the qparams (scale, zero_point) of the first input to `node`,
    if they can be inferred from the graph.
    r   Nr#   c                 S   sl   t | ||ƒ}t | ||ƒ}t|tƒr.t|jtƒs2t‚t|tƒrHt|jtƒsLt‚t||jƒ}t||jƒ}||fS r&   )r4   r(   r
   r3   r7   r5   r   )r   r   Zscale_arg_idxZ
zp_arg_idxZ
scale_nodeZzp_nodeZ	scale_objZzp_objr   r   r   Ú _get_scale_zp_from_function_args²   s    z@get_node_input_qparams.<locals>._get_scale_zp_from_function_argsr$   r   é   é   r%   c                 3   s   | ]}t ˆ |ƒV  qd S r&   r'   r)   ©Z
module_objr   r   r.   ë   s    z)get_node_input_qparams.<locals>.<genexpr>),r4   r(   r
   r2   r3   r9   Zquantize_per_tensorÚtoqÚaddZadd_reluÚmulZmul_relur7   r5   r   ÚnnqZLinearZConv1dZConv2dÚnniqZ
ConvReLU2dZConv3dZBatchNorm2dZBatchNorm3dZConvTranspose1dZConvTranspose2dZELUZ	GroupNormZInstanceNorm1dZInstanceNorm2dZInstanceNorm3dZ	LayerNormZ	HardswishZ	LeakyReLUZReLU6ZBNReLU2dZBNReLU3dZ
ConvReLU1dZ
ConvReLU3dZ
LinearReLUÚscaleZ
zero_pointr8   Úget_node_input_qparams)r   r   r!   r<   r:   r=   r;   r   r@   r   rG   ¢   sb    	
	
èþÿrG   )r   r   r"   c                 C   s¦   | j dkr¢t|| jƒ}t|ƒr¢t| jƒdks0t‚t| jd tƒsDt‚| jd } t| jt	ƒs^t‚t|| jƒ}t|ƒr¢t| jƒdks„t‚t| jd tƒs˜t‚| jd } | S )a‡  
    If node is not an observer, returns it.  If node is an observer,
    navigates up the graph and returns the first parent which is not an
    observer.  For example,

    graph: (node_non_obs), node = node_non_obs : returns node_non_obs
    graph: (node_non_obs -> obs0), node = obs0 : returns node_non_obs
    graph: (node_non_obs -> obs0 -> fq0), node = fq0 : returns node_non_obs
    r%   r   r   )
r2   r   r3   r   ÚlenÚargsr5   r(   r
   r7   ©r   r   Znode_objr   r   r   Úreturn_first_non_observer_nodeô   s    


rK   c                 C   s*   | j dkr&t|| jƒ}t|tjƒr&dS dS )aO  
    Assumes that all non-param args occur first. Returns the number of
    non-param args expected for a node.  For example, for

      F.linear(x, weight, bias)

    Returns 1, because x is a non-param arg and weight and bias are params.
    For

      lstm_mod(x, hid)

    Returns 2, because both x and hid are non-param args.
    r%   r>   r   )r2   r   r3   r(   ÚnnZLSTMrJ   r   r   r   Úget_number_of_non_param_args  s
    
rM   )r   r"   c                 C   sˆ   t | jƒdkrg S | jdkr‚| jtjtjjjtjfksP| jtj	tjjj	tj	fkr‚g }t
dƒD ] }t| j| ƒtkr\| |¡ q\|S dgS )a-  
    Returns the indices of args of the node which we should attach
    loggers to, if input logging is enabled.

    For example,
    * for (x + y), returns [0, 1]
    * for (1 + y), returns [1]
    * for (x + 1), returns [0]
    * for (linear(x, w, b)) returns [0]
    * by default, returns [0]
    r   r$   r>   )rH   rI   r2   r3   r9   rB   ÚopsÚ	quantizedÚoperatorrC   ÚrangeÚtyper
   Úappend)r   ÚresultÚir   r   r   Ú get_arg_indices_of_inputs_to_log+  s    
þýrV   c                 C   sP   d}| j dkrt | j¡}n0| j dkrLt| jtƒs6t‚t|| jƒ}t |¡}|S )zˆ
    Returns a string representation of the type of the function or module
    pointed to by this node, or '' for other node types.
    Ú )r$   r/   r%   )r2   r9   Útypenamer3   r(   r7   r5   r   )r   r   r+   Z
target_modr   r   r   Úget_target_type_strF  s    


rY   )ÚresultsÚ
model_namer"   c           	      C   s|   i }|   ¡ D ]j\}}d}| ¡ D ]:}|  ¡ D ],\}}||kr,t|ƒsHt‚|d d }q,q,q,q |dk	rn|||< q|||< q|S )a	  
    Rekeys the layer name of a results dictionary to use node names
    from `model_name`.

    For example, transforms

        {'base_op_1_0': {'node_output': {'model_a':
          [{'ref_node_name': 'linear1', ...}]}}}

    into

        {'linear1': {'node_output': {'model_a':
          [{'ref_node_name': 'linear1', ...}]}}}

    Note: we cannot use these node names directly because they are not
    guaranteed to be consistent across models. This is why we extract
    the results first and rekey afterwards.
    Nr   Zref_node_name)ÚitemsÚvaluesrH   r5   )	rZ   r[   Znew_resultsZold_layer_nameÚresult_type_to_resultsZnew_layer_nameÚmodel_name_to_resultsZcur_model_nameZlist_of_resultsr   r   r   Ú'rekey_logger_info_on_node_name_of_modelU  s    

r`   )rZ   r"   c           	      C   sÐ   d}|   ¡ D ]P}|  ¡ D ]>}| ¡ D ],\}}t|ƒdkr$|d d dk	r$|} qRq$ qXq q^q|rÌ|   ¡ D ]`}|  ¡ D ]R}|| }| ¡ D ]<\}}||krœqŠtt|ƒƒD ]}|| d }||| d< q¨qŠqvqjdS )ay  
    If `fqn` entries are filled in for one of the models in `results`, copies
    them over to any models which do not have them filled out.

    A common use case benefitting from this is comparing a model prepared by
    quantization to a quantized model. In this case, the model prepared by
    quantization would have `fqn` entries, and the quantized model would not.
    Nr   Úfqn)r]   r\   rH   rQ   )	rZ   Zmodel_name_with_fqnsr^   r_   r[   Zmodel_resultsZref_model_resultsrU   ra   r   r   r   Úmaybe_add_missing_fqns|  s(    rb   c                    s   ‡ ‡fdd„‰ˆS )Nc            	         sÐ   | ^}}}t |tƒrt |tƒs2t |tƒrjt |tƒrjg }t||ƒD ]$\}}||f|˜}| ˆ||Ž¡ q@|S t |tjƒržt |tjƒrž|jr�| ¡ }|jrž| ¡ }|j	tj
ks¶|j	tj
krºd S ||f|˜}ˆ ||ŽS r&   )r(   ÚtupleÚlistÚziprS   r9   ÚTensorZis_quantizedr0   ZdtypeÚfloat)	rI   ÚkwargsZa0Za1Za_otherrZ   Zel0Zel1Únew_args©ÚfÚinnerr   r   rl   Ÿ  s(    
ÿÿzGmaybe_dequantize_first_two_tensor_args_and_handle_tuples.<locals>.innerr   )rk   r   rj   r   Ú8maybe_dequantize_first_two_tensor_args_and_handle_tuplesž  s    rm   )ÚxÚyr"   c                 C   s*   t  | ¡}t  | | ¡}dt  || ¡ S )zµ
    Computes the SQNR between `x` and `y`.

    Args:
        x: Tensor or tuple of tensors
        y: Tensor or tuple of tensors

    Return:
        float or tuple of floats
    é   )r9   ZnormÚlog10)rn   ro   ZPsZPnr   r   r   Úcompute_sqnr»  s    
rr   c                 C   s"   t  | | d  ¡ | d  ¡  ¡S )zÄ
    Computes the normalized L2 error between `x` and `y`.

    Args:
        x: Tensor or tuple of tensors
        y: Tensor or tuple of tensors

    Return:
        float or tuple of floats
    r>   )r9   ÚsqrtÚsum©rn   ro   r   r   r   Úcompute_normalized_l2_errorÌ  s    rv   c                 C   s(   |   dd¡} |  dd¡}tjj | |¡S )zÂ
    Computes the cosine similarity between `x` and `y`.

    Args:
        x: Tensor or tuple of tensors
        y: Tensor or tuple of tensors

    Return:
        float or tuple of floats
    r   éÿÿÿÿ)Zreshaper9   rL   Z
functionalZcosine_similarityru   r   r   r   Úcompute_cosine_similarityÛ  s    rx   c                 C   s4   | j dkr0| jtjtjtjtjtjtjfkr0dS dS )Nr$   FT)r2   r3   r9   rB   rC   rP   ÚcatÚstack)r   r   r   r   Úop_type_supports_shadowingî  s    
"r{   )r   r   Úidxr"   c                 C   s6  z¼| j |dd�}|dk	rb|\}}t|ƒt|ƒ |ks8t‚|t|ƒk rN|| W S t| ¡ ƒ| W S nXt| jƒt| jƒ |ks~t‚|t| jƒk r˜| j| W S |t| jƒ }t| j ¡ ƒ| W S W nt tk
�r0   t| jƒt| jƒ |ksêt‚|t| jƒk �r| j|  Y S |t| jƒ }t| j ¡ ƒ|  Y S Y nX dS )zu
    Given a node, gets the n'th input to that node, normalizing
    args and kwargs to the best of its ability.
    T)Znormalize_to_only_use_kwargsN)Znormalized_argumentsrH   r5   rd   r]   rI   rh   ÚRuntimeError)r   r   r|   Znorm_args_and_kwargsZ	norm_argsZnorm_kwargsZ
kwargs_idxr   r   r   r4   õ  s,     ÿ
r4   )9r   rP   r9   Ztorch.nnrL   Ztorch.ao.nn.intrinsic.quantizedZaoZ	intrinsicrO   rE   Ztorch.ao.nn.quantizedrD   rN   rA   Útypingr   r   r   r   r   r   r   Ztorch.fxr	   Ztorch.fx.graphr
   Ztorch.ao.quantizationr   r   Ztorch.ao.quantization.utilsr   Ztorch.ao.quantization.observerr   Zns_typesr   r   ÚEnumr   r7   r6   rf   rg   ÚintrG   rK   rM   rV   rY   r`   rb   rm   rr   rv   rx   Úboolr{   r4   r   r   r   r   Ú<module>   sb   $
û}"üSýýý'"