o
    eiX                     @   sX  d dl Z d dlZd dlmZ d dlZd dlm  m  m  m	Z
 d dlm  m  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 d dlmZ dd	lmZmZ ejj	ZG d
d de jZdededede e!e"e f de#eef f
ddZ$dedede e!e"e f de#ej%e&B ej%e'B f dB fddZ(dededefddZ)dedede'fddZ*dede+e' fddZ,dedede!fddZ-dede!defdd Z.deddfd!d"Z/d#d$ Z0e0d%ej%d&ej%dej%fd'd(Z1e0d%ej%d&ej%dej%fd)d*Z2e0d%ej%d&ej%dej%fd+d,Z3dede4fd-d.Z5deded/e'defd0d1Z6dS )2    N)Callable)FakeQuantizeBaseObserverBase)_is_activation_post_process)getattr_from_fqn)GraphModule)Node   )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UNKNOWNFP32_OR_INT8 r   r   ^/var/www/addictedbytheproject.nl/epg/venv/lib/python3.10/site-packages/torch/ao/ns/fx/utils.pyr      s    r   nodegm
logger_clsnode_type_to_io_type_mapreturnc                    s8  |d }|d }|d }|d }|d }|d }	|d }
|d }| j d	krr| j|v r0tjtjfS | j|v r;tjtjfS | j|v rFtjtjfS | j|v rlt| |d
}t|ts_t	dt
| t||||\}}||fS tjtjfS | j dkr| j dkrt	d| j  dt| jtst	dt
| j t|| j t fdd|
D }t |ttfs|rt| |d
}t|tst	dt
| t||||\}}||fS t fdd|D }t fdd|	D }|rtjtjfS |rtjtjfS tjtjfS | j dkr| jdkr,t| |d
}t|tst	dt
| t||||\}}|tjfS | jdkrht| |d
}t|tsGt	dt
| t||||\}}t| |d}|tjurct	| d|tjfS | j|v rt| |d
}t|tst	dt
| t||||\}}||fS tjtjfS tjtjfS )Nfuns_io_type_fp32funs_io_type_fp16funs_io_type_int8funs_io_type_fp32_or_int8mods_io_type_fp32mods_io_type_int8mods_io_type_fp32_or_int8meths_io_type_fp32_or_int8call_functionr   Expected Node, got call_modulezExpected call_module, got ''zExpected str, but got c                 3       | ]}t  |V  qd S N
isinstance.0target_typemodr   r   	<genexpr>R   
    
z7get_node_first_input_and_output_type.<locals>.<genexpr>c                 3   r*   r+   r,   r.   r1   r   r   r3   f   r4   c                 3   r*   r+   r,   r.   r1   r   r   r3   j   r4   call_method
dequantizetor	   z handling needs to be added)optargetr   r   r   r   get_normalized_nth_inputr-   r   AssertionErrortype$get_node_first_input_and_output_typer   strr   anyr   r   torchfloat16)r   r   r   r   FUNS_IO_TYPE_FP32FUNS_IO_TYPE_FP16FUNS_IO_TYPE_INT8FUNS_IO_TYPE_FP32_OR_INT8MODS_IO_TYPE_FP32MODS_IO_TYPE_INT8MODS_IO_TYPE_FP32_OR_INT8METHS_IO_TYPE_FP32_OR_INT8	first_arg_prev_node_input_typeprev_node_output_type"is_known_fp32_or_int8_input_moduleis_known_fp32_input_moduleis_known_int8_input_module	prev_nodecur_node_dtype_targetr   r1   r   r=   &   s   










r=   c                    sP  t | |d}t|tsdS |d }dd }|jdkr=|jtju r'|||ddS |jtjtj	tj
tjfv r;|||dd	S dS |jd
krt|jtsRtdt|j 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 }|rt,|||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   s   t | ||}t | ||}t|tstdt| t|jts*tdt|j t|ts8tdt| t|jtsHtdt|j t||j}t||j}||fS )Nr'   Expected str, got )r:   r-   r   r;   r<   r9   r>   r   )r   r   scale_arg_idx
zp_arg_idx
scale_nodezp_node	scale_obj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(   rR   c                 3   r*   r+   r,   r.   
module_objr   r   r3      r4   z)get_node_input_qparams.<locals>.<genexpr>)-r:   r-   r   r8   r9   r@   quantize_per_tensortoqaddadd_relumulmul_relur>   r;   r<   r   nnqLinearConv1dConv2dnniq
ConvReLU2dConv3dBatchNorm2dBatchNorm3dConvTranspose1dConvTranspose2dELU	GroupNormInstanceNorm1dInstanceNorm2dInstanceNorm3d	LayerNorm	Hardswish	LeakyReLUReLU6BNReLU2dBNReLU3d
ConvReLU1d
ConvReLU3d
LinearReLUscale
zero_pointr?   get_node_input_qparams)r   r   r   rP   rH   rY   rM   r   r\   r   r      sd   	


r   c                 C   s   | j dkr}t|| j}t|r}t| jdkr tdt| j t| jd ts4tdt	| jd  | jd } t| jt
sItdt	| j t|| j}t|r}t| jdkrdtdt| j t| jd tsxtdt	| jd  | 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	   z)Expected node.args to have length 1, got r   r'   rR   )r8   r   r9   r   lenargsr;   r-   r   r<   r>   r   r   node_objr   r   r   return_first_non_observer_node  s,   


r   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(   rZ   r	   )r8   r   r9   r-   nnLSTMr   r   r   r   get_number_of_non_param_args+  s
   
r   c                    sp   t  jdkr	g S  jdkr5 jtjtjjjtjfv s( jtj	tjjj	tj	fv r5 fddt
dD }|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&   c                    s"   g | ]}t  j| tu r|qS r   )r<   r   r   )r/   ir   r   r   
<listcomp>X  s   " z4get_arg_indices_of_inputs_to_log.<locals>.<listcomp>rZ   )r   r   r8   r9   r@   r`   ops	quantizedoperatorrb   range)r   resultr   r   r    get_arg_indices_of_inputs_to_logE  s   
r   c                 C   sb   d}| j dv rt| j}|S | j dkr/t| jts$tdt| j 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&   r5   r(   rR   )	r8   r@   typenamer9   r-   r>   r;   r<   r   )r   r   r0   
target_modr   r   r   get_target_type_str]  s   


r   results
model_namec           	      C   s   i }|   D ]8\}}d}| D ] }|  D ]\}}||kr/t|dkr(td|d d }qqq|dur:|||< 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(Expected list_of_results to be not emptyref_node_name)itemsvaluesr   r;   )	r   r   new_resultsold_layer_nameresult_type_to_resultsnew_layer_namemodel_name_to_resultscur_model_namelist_of_resultsr   r   r   'rekey_logger_info_on_node_name_of_modelm  s   

r   c           	      C   s   d}|   D ]$}|  D ]}| D ]\}}t|dkr(|d d dur(|} nq  |rb|   D ]2}|  D ])}|| }| D ]\}}||krJqAtt|D ]}|| d }||| d< qPqAq7q1dS d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   r   r   )	r   model_name_with_fqnsr   r   r   model_resultsref_model_resultsr   r   r   r   r   maybe_add_missing_fqns  s4   r   c                    s    fddS )Nc            	         s   | ^}}}t |trt |tst |tr8t |tr8g }t||D ]\}}||g|R }||i | q |S t |tjrRt |tjrR|jrK| }|jrR| }|j	tj
ks^|j	tj
kr`d S ||g|R } |i |S r+   )r-   tuplelistzipappendr@   Tensoris_quantizedr6   dtypefloat)	r   kwargsa0a1a_otherr   el0el1new_argsfinnerr   r   r     s(   
zGmaybe_dequantize_first_two_tensor_args_and_handle_tuples.<locals>.innerr   )r   r   r   r   8maybe_dequantize_first_two_tensor_args_and_handle_tuples  s   r   xyc                 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
       )r@   normlog10)r   r   PsPnr   r   r   compute_sqnr  s   
r   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
    rZ   )r@   sqrtsumr   r   r   r   r   compute_normalized_l2_error  s   "r   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	   )reshaper@   r   
functionalcosine_similarityr   r   r   r   compute_cosine_similarity  s   r   c                 C   s4   | j dkr| jtjtjtjtjtjtjfv rdS dS )Nr&   FT)r8   r9   r@   r`   rb   r   catstackr   r   r   r   op_type_supports_shadowing
  s   
	r   idxc              
   C   s  zy| j |dd}|dur>|\}}t|t| |kr*td| dt|t|  |t|k r5|| W S t| | W S t| jt| j |kr\td| dt| jt| j  |t| jk ri| j| W S |t| j }t| j | W S  ty   t| jt| j |krtd| dt| jt| j  d|t| jk r| j|  Y S |t| j }t| j |  Y S w )zu
    Given a node, gets the n'th input to that node, normalizing
    args and kwargs to the best of its ability.
    T)normalize_to_only_use_kwargsNzIndex z out of range: total = )normalized_argumentsr   r;   r   r   r   r   RuntimeError)r   r   r   norm_args_and_kwargs	norm_argsnorm_kwargs
kwargs_idxr   r   r   r:     sB   
r:   )7r   r   collections.abcr   r@   torch.ao.nn.intrinsic.quantizedaor   	intrinsicr   rh   torch.ao.nn.quantizedrd   torch.nntorch.ao.quantizationr   r   torch.ao.quantization.observerr   torch.ao.quantization.utilsr   torch.fxr   torch.fx.graphr   ns_typesr
   r   r   r_   Enumr   dictr>   setr   r=   r   r   intr   r   r   r   r   r   r   r   r   r   r   r   boolr   r:   r   r   r   r   <module>   s   

 
X
&

(#