U
    yhp$                     @   s   d dl Z d dlZd dlZd dlmZmZmZ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 d dlmZmZ dejjeedf ee ee ee ee ee ee ejjjjd	d	d
Zdejjjjee ejjjjdddZdS )    N)AnyCallableOptionalTuple)default_weight_observerdefault_weight_fake_quantFakeQuantizeBaseQConfigQConfigMapping)BackendConfig)_PartialWrapper)convert_to_reference_fx
prepare_fx.)	
float_lstmexample_inputsbackend_configlinear_output_obs_ctrsigmoid_obs_ctrtanh_obs_ctrcell_state_obs_ctrhidden_state_obs_ctrreturnc                 C   s  t tddd}tjjj| j| j| j	| j
| j| j| j}	| j|	_t| j	D ]*}
tjjjjjjj| |
| jdd|	j|
< qLt | j}|dk	r|d|| |d|| |d	|| |dk	r|d
|| |	jD ]}|jj}t||||d}tjdf|tjdf|tjdf|tjdf|tjdf|i}d}d}|jjD ]}d}|jtjkrjtj|f}|d7 }n&|jtjkr@tj|f}|d7 }nq@||krq@t |j!dkst"t#t$|j!% j&}|| }|dk	r@t'|||  q@||j_q|	S )aO  
    Return an observed `torch.ao.nn.quantizable.LSTM` created from a `torch.nn.LSTM`
    with specific observers or fake quantizes assigned to the inner ops or submodules.

    In both eager and FX graph mode quantization, `torch.ao.nn.quantizable.LSTM` is
    used as an observed custom module, which is responsible for inserting its own
    observers. By default, all inner ops inherit the parent custom module's QConfig.
    Users who wish to override this behavior may extend `torch.ao.nn.quantizable.LSTM`
    and use this helper function to customize the observer insertion logic.

    This is meant to be used to convert a float module to an observed module in the
    custom module flow.

    Args:
        `float_lstm`: The float LSTM module
        `example_inputs`: example inputs for the forward function of the LSTM module
        `backend_config`: BackendConfig to use to observe the LSTM module
        `linear_output_obs_ctr`: observer or fake quantize for linear outputs Wx + b,
            where W is the weight matrix, b is the bias, and x is either the inputs
            or the hidden state from the previous layer (if any)
        `sigmoid_obs_ctr`: observer or fake quantize for sigmoid activations
        `tanh_obs_ctr`: observer or fake quantize for tanh activations
        `cell_state_obs_ctr`: observer or fake quantize for the cell state
        `hidden_state_obs_ctr`: observer or fake quantize for the hidden state and
            the output

    Return:
        A `torch.ao.nn.quantizable.LSTM` with the specified observers or fake quantizes
        assigned to the inner ops.
    )obs_ctrr   c                 S   s"   t |  trt}nt}t| |dS )zP
        Make a QConfig with fixed qparams observers or fake quantizes.
        )Z
activationweight)
isinstancer   r   r   r	   )r   r    r   U/var/www/html/venv/lib/python3.8/site-packages/torch/ao/quantization/fx/lstm_utils.pymake_qconfig<   s    z@_get_lstm_with_individually_observed_parts.<locals>.make_qconfigF)batch_firstNZ
input_gateZforget_gateZoutput_gateZ	cell_gater   r         )(r   r	   torchaonnquantizableLSTM
input_sizehidden_size
num_layersbiasr   dropoutbidirectionalZqconfigrangemodulesZrnnZ
_LSTMLayer
from_floatlayersr
   Z
set_globalZset_module_namelayer_fwcellr   addmulgraphnodestargetlenZusersAssertionErrornextiterkeysnamesetattr)r   r   r   r   r   r   r   r   r   Zquantizable_lstmidxZcell_qmlayerr2   Z'op_index_to_activation_post_process_ctrZ	add_countZ	mul_countnodeZop_indexZactivation_post_process_nameZactivation_post_process_ctrr   r   r   *_get_lstm_with_individually_observed_parts   st    (

          






rB   )observed_lstmr   r   c                 C   sT  t jjj| j| j| j| j| j	| j
| j}t|jD ]\}}t| jt|jj}t||d}t|t jjsvt|jjD ]}|jt jkr|jd }|jdks|jtjkr|jd jdkr|j | |!| |j"| W 5 Q R X |jdkr~|jd D ]0}|j | |#||jd  W 5 Q R X q q~|j$  |%  ||j_q4|S )aO  
    Return a `torch.ao.nn.quantized.LSTM` created from a `torch.ao.nn.quantizable.LSTM`
    with observers or fake quantizes inserted through `prepare_fx`, e.g. from
    `_get_lstm_with_individually_observed_parts`.

    This is meant to be used to convert an observed module to a quantized module in the
    custom module flow.

    Args:
        `observed_lstm`: a `torch.ao.nn.quantizable.LSTM` observed through `prepare_fx`
        `backend_config`: BackendConfig to use to produce the reference quantized model

    Return:
        A reference `torch.ao.nn.quantized.LSTM` module.
    r   r   xZhiddenoutput)&r"   r#   r$   	quantizedr&   r'   r(   r)   r*   r   r+   r,   	enumerater0   copydeepcopyZget_submodulestrr1   r2   r   r   ZfxZGraphModuler9   r5   r6   r7   Zquantize_per_tensorargsoperatorgetitemZinserting_beforeZreplace_all_uses_withZ
erase_nodeZreplace_input_withZeliminate_dead_codeZ	recompile)rC   r   Zquantized_lstmir@   r2   rA   argr   r   r   $_get_reference_quantized_lstm_module   s8    
    	
&

"

rP   )NNNNNN)N)rH   rL   r"   typingr   r   r   r   Ztorch.ao.quantizationr   r   r   r	   r
   Z$torch.ao.quantization.backend_configr   Ztorch.ao.quantization.observerr   Z!torch.ao.quantization.quantize_fxr   r   r$   r&   r#   r%   rB   rF   rP   r   r   r   r   <module>   s<   	      

q 

