U
    U?hEZ                     @   sb   d dl mZ d dlZd dlmZ d dlmZ d dl	m
Z
 ddlmZmZ dd ZG dd	 d	ZdS )
    )PathN)
ModelProto   )attribute_to_kwargfind_by_namec              	   C   s.  t  }|dd | jD  |dd | jD  g }| jD ]}|}dd |jD }|r"i }|jD ]}i }	|jtjjkrt	|j
|\}
}|j|
i}	|| nT|jtjjkrg }|jD ]&}t	||\}
}||
 || q|j|i}	nt|}	||	 qdtj|j|j|jfd|ji|}|| q<| d | j| |dd | jD  g }| jD ]*}|j|kr||j n
|| qdd	d
 | jD }|D ]j}| j| |j|krz| j||j  W n4 tk
r
   |jdk rtd|j d Y nX q|dd | jD  | |fS )zClean unused initializers from graph.

    Returns:
        A cleaned graph without unused initializers
        A list of tensor names, which are not produced by this graph and its subgraphes
    c                 s   s"   | ]}|j D ]}|r|V  qqd S N)input).0node
input_name r   U/var/www/html/venv/lib/python3.8/site-packages/onnxruntime/quantization/onnx_model.py	<genexpr>   s
        z-_clean_initializers_helper.<locals>.<genexpr>c                 s   s   | ]}|j r|j V  qd S r   name)r	   Zg_outr   r   r   r      s      c                 S   s,   g | ]$}|j tjjks$|j tjjkr|qS r   )typeonnxAttributeProtoGRAPHGRAPHSr	   attrr   r   r   
<listcomp>   s    z._clean_initializers_helper.<locals>.<listcomp>r   r
   c                 s   s   | ]}|j D ]
}|V  qqd S r   )output)r	   r
   r   r   r   r   r   @   s       c                 S   s   i | ]}|j |qS r   r   r	   r   r   r   r   
<dictcomp>J   s      z._clean_initializers_helper.<locals>.<dictcomp>   zWarning: invalid weight name z' found in the graph (not a graph input)c                 s   s   | ]}|j V  qd S r   r   r   r   r   r   r   T   s     )setupdater
   r   	attributer   r   r   r   _clean_initializers_helpergr   r   graphsappendr   onnx_helper	make_nodeop_typer   
ClearFieldextenddifference_updateinitializerremoveStopIteration
ir_versionprint)graphmodelZrequesting_tensor_names	new_nodesr
   new_nodegraph_attrskwargsr   Znew_attributeZcleaned_sub_graphZsub_requesting_tensor_namesZcleaned_graphessubgraphZunused_initializerr*   Zname_to_inputr   r   r   r       sj    





"

r    c                   @   s  e Zd ZedddZdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zed"d#d$Zd%d& Zd'd( Zd)d* Zd+d, Zd-d. Zd/d0 Zd1d2 Zddd4d5Zded6d7Zdfd8d9Zd:d; Z d<d= Z!d>d? Z"e#d@dA Z$e#dBdC Z%dDdE Z&dgdGdHZ'e#dIdJ Z(dKdL Z)dMdN Z*e#dOdP Z+dQdR Z,dSdT Z-dUdV Z.dWdX Z/ee0dYdZd[Z1d\d] Z2d^d_ Z3dhd`daZ4dbdc Z5d3S )i	ONNXModelr0   c                 C   s
   || _ d S r   r7   )selfr0   r   r   r   __init__Z   s    zONNXModel.__init__c                 C   s
   | j jjS r   )r0   r/   r
   r8   r   r   r   nodes]   s    zONNXModel.nodesc                 C   s
   | j jjS r   r0   r/   r*   r:   r   r   r   r*   `   s    zONNXModel.initializerc                 C   sV   t |dkrtd|  D ]}| |d q|D ]}| | | jjj| q2d S )Nr   zCan add an empty list.Zgain)len
ValueErrorr*   _check_initr0   r/   r#   )r8   Zinitsinitr   r   r   initializer_extendc   s    
zONNXModel.initializer_extendc                 C   s   | j jS r   )r0   r/   r:   r   r   r   r/   l   s    zONNXModel.graphc                 C   s   | j jS r   )r0   r-   r:   r   r   r   r-   o   s    zONNXModel.ir_versionc                 C   s   | j jS r   )r0   opset_importr:   r   r   r   rB   r   s    zONNXModel.opset_importc                 C   s@   | j jD ]}|j|kr||_ d S q| j jt||g d S r   )r0   rB   domainversionr(   r$   Zmake_opsetid)r8   rC   rD   Zopsetr   r   r   set_opset_importu   s
    
zONNXModel.set_opset_importc                 C   s"   || j jjkr| j jj| d S r   )r0   r/   r
   r+   r8   r
   r   r   r   remove_node}   s    zONNXModel.remove_nodec                 C   s   |D ]}|  | qd S r   )rG   )r8   Znodes_to_remover
   r   r   r   remove_nodes   s    zONNXModel.remove_nodesc                 C   s   | j jj| |g d S r   )r0   r/   r
   r(   _check_noderF   r   r   r   add_node   s    zONNXModel.add_nodec                 C   s   |D ]}|  | qd S r   )rJ   )r8   Znodes_to_addr
   r   r   r   	add_nodes   s    zONNXModel.add_nodesc                 C   s6   t |j| jjjd kr2| | | jjj|g d S r   )r   r   r0   r/   r*   r?   r(   )r8   tensorr   r   r   add_initializer   s    
zONNXModel.add_initializerc                 C   s&   | j jjD ]}|j|kr
|  S q
d S r   )r0   r/   r*   r   )r8   r   rL   r   r   r   get_initializer   s    

zONNXModel.get_initializerc                 C   s&   | j jjD ]}|j|kr
|  S q
d S r   )r0   r/   r   r   )r8   r   r   r   r   r   find_graph_input   s    

zONNXModel.find_graph_inputc                 C   s&   | j jjD ]}|j|kr
|  S q
d S r   )r0   r/   r   r   )r8   output_namer   r   r   r   find_graph_output   s    

zONNXModel.find_graph_outputtensor_namec                 C   sV   dd | j jjD }||kr&|| jS | |}|r<|jjS | |}|rR|jjS d S )Nc                 S   s   i | ]}|j |jqS r   )r   r   )r	   objr   r   r   r      s      z-ONNXModel.get_tensor_type.<locals>.<dictcomp>)r0   r/   Z
value_infoZtensor_typerO   r   rQ   )r8   rS   Ztensor_type_mapZg_inputZg_outputr   r   r   get_tensor_type   s    


zONNXModel.get_tensor_typec                 C   sr   | j jjD ]F}|jdkr
|jd |kr
|jD ]"}|jdkr,t|j	    S q,q
| 
|}|d k	rnt|S d S )NConstantr   value)r0   r/   r
   r&   r   r   r   onnx_numpy_helperto_arraytrN   )r8   rP   r
   r   r*   r   r   r   get_constant_value   s    




zONNXModel.get_constant_valuec                 C   s   dd | j jjD S )Nc                 S   s   h | ]
}|j qS r   r   )r	   r*   r   r   r   	<setcomp>   s     z5ONNXModel.get_initializer_name_set.<locals>.<setcomp>r<   r:   r   r   r   get_initializer_name_set   s    z"ONNXModel.get_initializer_name_setc                 C   sR   || j jjkrN| j jj| | j jjD ]$}|j|jkr(| j jj|  qNq(d S r   )r0   r/   r*   r+   r   r   )r8   rL   r   r   r   r   remove_initializer   s    zONNXModel.remove_initializerc                 C   s   |D ]}|  | qd S r   )r^   )r8   Zinit_to_remover*   r   r   r   remove_initializers   s    zONNXModel.remove_initializersc                 C   s8   |   }t }| jjjD ]}|j|kr||j q|S r   )r]   r   r0   r/   r   r   add)r8   initializer_namesZnon_initializer_inputsr   r   r   r   get_non_initializer_inputs   s    
z$ONNXModel.get_non_initializer_inputsc                 C   sJ   i }| j jjD ]6}|jD ]*}|r||kr4|g||< q|| | qq|S r   )r0   r/   r
   r   r#   )r8   input_name_to_nodesr
   r   r   r   r   rc      s    
zONNXModel.input_name_to_nodesc                 C   s0   i }| j jjD ]}|jD ]}|r|||< qq|S r   )r0   r/   r
   r   )r8   output_name_to_noder
   rP   r   r   r   rd      s    
zONNXModel.output_name_to_nodeNc                 C   sD   |d kr|   }g }|jD ]$}||kr|| D ]}|| q.q|S r   )rc   r   r#   )r8   r
   rc   childrenr   r   r   r   get_children   s    
zONNXModel.get_childrenc                 C   s:   |d kr|   }g }|jD ]}||kr|||  q|S r   )rd   r   r#   )r8   r
   rd   parentsr   r   r   r   get_parents   s    
zONNXModel.get_parentsc                 C   s@   |d kr|   }t|j|kr"d S |j| }||kr8d S || S r   )rd   r=   r   )r8   r
   idxrd   r   r   r   r   
get_parent  s    
zONNXModel.get_parentc                 C   s"   t |j}|| t||}|S )zFind out if a node exists in a graph or a node is in the
        new set of nodes created during quantization.

        Returns:
            The node found or None.
        )listr
   r(   r   )r8   Z	node_nameZnew_nodes_listr/   Zgraph_nodes_listr
   r   r   r   find_node_by_name  s    


zONNXModel.find_node_by_namec              	   C   sh   d}| j jjD ]T}|jr|j|rz$t|jt|d }t||}W q tk
r`   Y qY qX q|S )z
        Gets the largest node name (int) suffix for all node names that begin with `node_name_prefix`.
        Example: for nodes my_prefix_0 and my_prefix_3, this method returns 3.
        N)	r0   r/   r
   r   
startswithintr=   maxr>   )r8   Znode_name_prefixsuffixr
   indexr   r   r   get_largest_node_name_suffix  s    z&ONNXModel.get_largest_node_name_suffixc                 C   s4   g }|j D ]$}|jD ]}||jkr|| qq
|S )zD
        Find all nodes with given initializer as an input.
        )r
   r   r   r#   )r8   r/   r*   r;   r
   Z
node_inputr   r   r   find_nodes_by_initializer+  s    


z#ONNXModel.find_nodes_by_initializerc                 C   sL   t t|d ddD ]2}|| }|jD ]}|j| kr&||f    S q&qdS )Nr   rm   )NN)ranger=   r*   r   )r   
graph_pathgidr/   rL   r   r   r   Z__get_initializer6  s    

zONNXModel.__get_initializerc                 C   sB  g }| d }|j D ]
}dd |jD }t|ri }|jD ]}|jdkrf| |j |jt| i}nJ|jdkrg }|j	D ] }	| |	 |
t| g qz|j|i}nt|}|| q:tj|j|j|jfd|ji|}|jdkrd}
d}d	}d	}|jD ]d}|jd
krt|}
nF|jdkr4t|}n.|jdkrLt|}n|jdkr t|}q |
dkr|dkr|d	kr|jd }|dkrZt|jd | \}}|rt|}t|j}|j|_|j| |jD ]$}|j|kr|j|  q
q|j
|g n@|d7 }tjd|jd g|g|jrH|jd ndd}|| tjd|jd	 |g|jd	 t|jdkrdnd g|jr|jd ndd}|| t|jdkrtjd|jd	 d |jd g|j|jr|jd ndd}|| n
|| q|| q|d |j 
| |   |S )Nrm   c                 S   s$   g | ]}|j d ks|j dkr|qS )   
   )r   r   r   r   r   r   D  s     
 
 z8ONNXModel.__replace_gemm_with_matmul.<locals>.<listcomp>rx   ry   r   ZGemmg      ?r   alphabetatransAtransBr   Z_TransposedZ	TransposeZ
_Transpose )inputsoutputsr   ZMatMul   Z_MatMulAddZ_Addr
   )r
   r   r=   r   r#   r!   r   r6   $_ONNXModel__replace_gemm_with_matmulr"   r(   r   r   r$   r%   r&   r   r   Zget_attribute_value_ONNXModel__get_initializerrX   rY   Z
from_arrayTr*   r+   r'   pop)rv   r1   r/   r
   r3   r4   r   kvrW   r5   rz   r{   r|   r}   ZinputBBZBs_graphZB_arrayZB_transr   Ztranspose_nodeZmatmul_noderJ   r   r   r   Z__replace_gemm_with_matmul?  s    




  







"

z$ONNXModel.__replace_gemm_with_matmulc                 C   s   |   g}t| d S r   )r/   r6   r   )r8   rv   r   r   r   replace_gemm_with_matmul  s    
z"ONNXModel.replace_gemm_with_matmulFc                 C   sZ   |    |r,tjj| jdt|jd dd | jjjD ]}| 	|d q6t
| j| dS )zS
        Save model to external data, which is needed for model size > 2GB
        Tz.data)Zall_tensors_to_one_filelocationZconvert_attributeendN)topological_sortr   Zexternal_data_helperZconvert_model_to_external_datar0   r   r   r/   r*   r?   Z
save_model)r8   Zoutput_pathZuse_external_data_formatr@   r   r   r   save_model_to_file  s    zONNXModel.save_model_to_filec                 C   sH   t |trt |tsttt| jD ]}| j| |kr&|| j|< q&d S r   )
isinstancestrAssertionErrorru   r=   r   )r
   old_input_namenew_input_namejr   r   r   replace_node_input  s    zONNXModel.replace_node_inputc                 C   s"   | j jjD ]}t||| q
d S r   )r0   r/   r
   r6   r   )r8   r   r   r
   r   r   r   replace_input_of_all_nodes  s    z$ONNXModel.replace_input_of_all_nodesc                 C   s,   | j jjD ]}|j|kr
t||| q
d S r   )r0   r/   r
   r   r6   r   )r8   r   r   node_names_setr
   r   r   r   replace_input_of_nodes  s    
z ONNXModel.replace_input_of_nodesc                 C   sH   t |trt |tsttt| jD ]}| j| |kr&|| j|< q&d S r   )r   r   r   ru   r=   r   )r
   old_output_namenew_output_namer   r   r   r   replace_node_output  s    zONNXModel.replace_node_outputc                 C   s"   | j jjD ]}t||| q
d S r   )r0   r/   r
   r6   r   )r8   r   r   r
   r   r   r   replace_output_of_all_nodes  s    z%ONNXModel.replace_output_of_all_nodesc                 C   s,   | j jjD ]}|j|kr
t||| q
d S r   )r0   r/   r
   r   r6   r   )r8   r   r   r   r
   r   r   r   replace_output_of_nodes  s    
z!ONNXModel.replace_output_of_nodesc                 C   s   |   }g }|  }|D ]6}|jdkr| |jd s|jd |kr|| q| | g }|  D ]P}|j|krf| |jsf|| | 	 j
D ] }|j|jkr| 	 j
| qqf| | d S )NrV   r   )rc   r;   r&   is_graph_outputr   r#   rH   r*   r   r/   r   r+   r_   )r8   rc   Zunused_nodesr;   r
   Zununsed_weightswZgraph_inputr   r   r   remove_unused_constant  s(    

z ONNXModel.remove_unused_constantc                    s   t  fdd| jjjD S )Nc                 3   s   | ]}|j  kV  qd S r   r   )r	   r   rP   r   r   r     s     z,ONNXModel.is_graph_output.<locals>.<genexpr>)anyr0   r/   r   )r8   rP   r   r   r   r     s    zONNXModel.is_graph_output)rS   returnc                    s   t  fdd| jjjD S )Nc                 3   s   | ]}|j  kV  qd S r   r   r   rR   r   r   r     s     z+ONNXModel.is_graph_input.<locals>.<genexpr>)r   r0   r/   r   )r8   rS   r   rR   r   is_graph_input  s    zONNXModel.is_graph_inputc                 C   s  dgt |   }i }g }t|  D ]t\}}tdd |jD ||< || dkrf||  |  q&|jD ],}|svql||kr|g||< ql|| | qlq&dd |  D }dd | jjjD }|| }	|		  d }
|	D ]V}|
|krq|}
||kr|| D ]2}|| d ||< || dkr||  |  qqd}t |}||k r|| j
D ]X}||krR|| D ]>}|| d ||< || dkrh||  |  |d }qhqR|d }q>|t |  jkstd|  d	 |  j| d S )
Nr   c                 s   s   | ]}|rd V  qdS )r   Nr   )r	   _r   r   r   r     s      z-ONNXModel.topological_sort.<locals>.<genexpr>c                 S   s   g | ]
}|j qS r   r   )r	   r@   r   r   r   r     s     z.ONNXModel.topological_sort.<locals>.<listcomp>c                 S   s   g | ]
}|j qS r   r   r   r   r   r   r     s     r   zGraph is not a DAGr
   )r=   r;   	enumeratesumr   r#   r*   r0   r/   sortr   r
   r   r'   r(   )r8   Z
deps_countZdeps_to_nodesZsorted_nodesZnode_idxr
   r   ra   Zgraph_input_namesZinput_namesZprev_input_namestartr   r   r   r   r   r     sT    


zONNXModel.topological_sortc                 C   s   t |  | jS r   )r    r/   r0   r:   r   r   r   clean_initializers(  s    zONNXModel.clean_initializersc                 C   sJ   |j tjjkrF|drFt|j}ttdd |rFt	d|j
d|S )Nraw_datac                 S   s   | d@ dkS )N   r   )ir   r   r   <lambda>/      z'ONNXModel._check_init.<locals>.<lambda>zInitializer z	 has nan.)	data_typer   TensorProtoZFLOAT8E4M3FNZHasFieldrk   r   r   mapr>   r   )r8   r@   testbr   r   r   r?   +  s    

zONNXModel._check_initc                 C   sX   |j dkrT|jd }| |}|j}|tjjtjjtjjtjj	hkrTt
d| d|S )z
        A quantization to float 8 does not use quantized bias but float 16 bias.
        This function checks that DequantizeLinear is not used to
        dequantize from float 16.
        ZDequantizeLinearr   z;Unsupported DequantizeLinear operator, dequantization from .)r&   r   rN   r   r   r   ZFLOAT16FLOATDOUBLEZBFLOAT16RuntimeError)r8   r
   Z
zero_pointr@   Zdtyper   r   r   rI   3  s    


zONNXModel._check_node)N)N)N)F)N)6__name__
__module____qualname__r   r9   r;   r*   rA   r/   r-   rB   rE   rG   rH   rJ   rK   rM   rN   rO   rQ   r   rU   r[   r]   r^   r_   rb   rc   rd   rf   rh   rj   rl   rs   rt   staticmethodr   r   r   r   r   r   r   r   r   r   r   r   boolr   r   r   r?   rI   r   r   r   r   r6   Y   sf   	





]


4
r6   )pathlibr   r   Zonnx.helperhelperr$   Zonnx.numpy_helperZnumpy_helperrX   Zonnx.onnx_pbr   Zquant_utilsr   r   r    r6   r   r   r   r   <module>   s   J