o
    ix]                     @   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 ]w}|}dd |jD }|ri }|jD ]M}i }	|jtjjkrOt	|j
|\}
}|j|
i}	|| n*|jtjjkrug }|jD ]}t	||\}
}||
 || q[|j|i}	nt|}	||	 q1tj|j|j|jfd|ji|}|| q| d | j| |dd | jD  g }| jD ]}|j|v r||j q|| qd	d
 | jD }|D ]0}| j| |j|v rz| j||j  W q ty   |jdk rtd|j d Y qw 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   ]/home/kim/smarthome/.venv/lib/python3.10/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          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!      sp   





"




r!   c                   @   s  e Zd Zdef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d"efd#d$Zd%d& Zd'd( Zd)d* Zd+d, Zd-d. Zd/d0 Zd1d2 Zdfd4d5Zdfd6d7Zdfd8d9Zd:d; Z d<d= Z!d>d? Z"d@dA Z#e$dBdC Z%e$dDdE Z&dFdG Z'dgdIdJZ(e$dKdL Z)dMdN Z*dOdP Z+e$dQdR Z,dSdT Z-dUdV Z.dWdX Z/dYdZ Z0d"ed[e1fd\d]Z2d^d_ Z3d`da Z4dfdbdcZ5ddde Z6d3S )h	ONNXModelr1   c                 C   s
   || _ d S r   )r1   )selfr1   r   r   r   __init__Z      
zONNXModel.__init__c                 C   
   | j jjS r   )r1   r0   r
   r8   r   r   r   nodes]   r:   zONNXModel.nodesc                 C   r;   r   r1   r0   r+   r<   r   r   r   r+   `   r:   zONNXModel.initializerc                 C   sV   t |dkr
td|  D ]}| |d q|D ]}| | | jjj| qd S )Nr   zCan add an empty list.Zgain)len
ValueErrorr+   _check_initr1   r0   r$   )r8   Zinitsinitr   r   r   initializer_extendc   s   
zONNXModel.initializer_extendc                 C      | j jS r   )r1   r0   r<   r   r   r   r0   l      zONNXModel.graphc                 C   rD   r   )r1   r.   r<   r   r   r   r.   o   rE   zONNXModel.ir_versionc                 C   rD   r   )r1   opset_importr<   r   r   r   rF   r   rE   zONNXModel.opset_importc                 C   s@   | j jD ]}|j|kr||_ d S q| j jt||g d S r   )r1   rF   domainversionr)   r%   Zmake_opsetid)r8   rG   rH   Zopsetr   r   r   set_opset_importu   s   
zONNXModel.set_opset_importc                 C   s&   || j jjv r| j jj| d S d S r   )r1   r0   r
   r,   r8   r
   r   r   r   remove_node}   s   zONNXModel.remove_nodec                 C      |D ]}|  | qd S r   )rK   )r8   Znodes_to_remover
   r   r   r   remove_nodes      zONNXModel.remove_nodesc                 C   s   | j jj| |g d S r   )r1   r0   r
   r)   _check_noderJ   r   r   r   add_node      zONNXModel.add_nodec                 C   rL   r   )rP   )r8   Znodes_to_addr
   r   r   r   	add_nodes   rN   zONNXModel.add_nodesc                 C   s:   t |j| jjjd u r| | | jjj|g d S d S r   )r   r   r1   r0   r+   rA   r)   )r8   tensorr   r   r   add_initializer   s   
zONNXModel.add_initializerc                 C   &   | j jjD ]}|j|kr|  S qd S r   )r1   r0   r+   r   )r8   r   rS   r   r   r   get_initializer   
   
zONNXModel.get_initializerc                 C   rU   r   )r1   r0   r   r   )r8   r   r   r   r   r   find_graph_input   rW   zONNXModel.find_graph_inputc                 C   rU   r   )r1   r0   r   r   )r8   output_namer   r   r   r   find_graph_output   rW   zONNXModel.find_graph_outputtensor_namec                 C   sV   dd | j jjD }||v r|| jS | |}|r|jjS | |}|r)|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>)r1   r0   Z
value_infoZtensor_typerX   r   rZ   )r8   r[   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 ]#}|jdkr(|jd |kr(|jD ]}|jdkr't|j	    S qq| 
|}|d ur7t|S d S )NConstantr   value)r1   r0   r
   r'   r   r    r   onnx_numpy_helperto_arraytrV   )r8   rY   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>       z5ONNXModel.get_initializer_name_set.<locals>.<setcomp>r>   r<   r   r   r   get_initializer_name_set   s   z"ONNXModel.get_initializer_name_setc                 C   sX   || j jjv r(| j jj| | j jjD ]}|j|jkr'| j jj|  d S qd S d S r   )r1   r0   r+   r,   r   r   )r8   rS   r   r   r   r   remove_initializer   s   zONNXModel.remove_initializerc                 C   rL   r   )rg   )r8   Zinit_to_remover+   r   r   r   remove_initializers   rN   zONNXModel.remove_initializersc                 C   s8   |   }t }| jjjD ]}|j|vr||j q|S r   )rf   r   r1   r0   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 ]}|jD ]}|r!||vr|g||< q|| | qq|S r   )r1   r0   r
   r   r$   )r8   input_name_to_nodesr
   r   r   r   r   rl      s   
zONNXModel.input_name_to_nodesc                 C   s0   i }| j jjD ]}|jD ]}|r|||< qq|S r   )r1   r0   r
   r   )r8   output_name_to_noder
   rY   r   r   r   rm      s   
zONNXModel.output_name_to_nodeNc                 C   sD   |d u r|   }g }|jD ]}||v r|| D ]}|| qq|S r   )rl   r   r$   )r8   r
   rl   childrenr   r   r   r   get_children   s   
zONNXModel.get_childrenc                 C   s:   |d u r|   }g }|jD ]}||v r|||  q|S r   )rm   r   r$   )r8   r
   rm   parentsr   r   r   r   get_parents   s   
zONNXModel.get_parentsc                 C   s@   |d u r|   }t|j|krd S |j| }||vrd S || S r   )rm   r?   r   )r8   r
   idxrm   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_listr0   Zgraph_nodes_listr
   r   r   r   find_node_by_name  s   


zONNXModel.find_node_by_namec              	   C   sb   d}| j jjD ]'}|jr.|j|r.zt|jt|d }t||}W q ty-   Y qw 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)	r1   r0   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   s\   d}| j jjD ]$}|j|r+zt|jt|d }t||}W q ty*   Y qw q|S )ab  
        Gets the largest initializer name integer suffix for all initializer names that begin
        with `initializer_name_prefix`. This can be used to create unique initializer names.

        Example: for initializer names 'my_weight_0' and 'my_weight_3', this method returns 3 if
                 `initializer_name_prefix` is 'my_weight_'.
        rv   N)	r1   r0   r+   r   rw   rx   r?   ry   r@   )r8   Zinitializer_name_prefixrz   r+   r{   r   r   r   #get_largest_initializer_name_suffix+  s   z-ONNXModel.get_largest_initializer_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   r0   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 ]}|| }|jD ]}|j| kr"||f    S qq
dS )Nr   rv   )NN)ranger?   r+   r   )r   
graph_pathgidr0   rS   r   r   r   Z__get_initializerJ  s   

zONNXModel.__get_initializerc                 C   s.  g }| d }|j D ]{}dd |jD }|rmi }|jD ]@}|jdkr1| |j |jt| i}n%|jdkrRg }|jD ]}	| |	 |	t| g q;|j|i}nt
|}|| qtj|j|j|jfd|ji|}|jdkrd}
d}d	}d	}|jD ]-}|jd
krt|}
q~|jdkrt|}q~|jdkrt|}q~|jdkrt|}q~|
dkrz|dkrz|d	krz|jd }|dkr#t|jd | \}}|rt|}t|j}|j|_|j| |jD ]}|j|kr|j|  nq|j	|g n |d7 }tjd|jd g|g|jr|jd ndd}|| tjd|jd	 |g|jd	 t|jdkr:dnd g|jrF|jd ndd}|| t|jdkrytjd|jd	 d |jd g|j|jrp|jd ndd}|| q	|| q	|| q	|d |j 	| |   |S )Nrv   c                 S   s$   g | ]}|j d ks|j dkr|qS )   
   )r   r   r   r   r   r   X  s   $ z8ONNXModel.__replace_gemm_with_matmul.<locals>.<listcomp>r   r   r   ZGemmg      ?r   alphabetatransAtransBr   Z_TransposedZ	TransposeZ
_Transpose )ZinputsZoutputsr   ZMatMul   Z_MatMulAddZ_Addr
   )r
   r    r   r$   r"   r   r7   $_ONNXModel__replace_gemm_with_matmulr#   r)   r   r   r%   r&   r'   r   r   Zget_attribute_value_ONNXModel__get_initializerr`   ra   Z
from_arrayTr+   r,   r?   r(   pop)r   r2   r0   r
   r4   r5   r   kvr_   r6   r   r   r   r   ZinputBBZBs_graphZB_arrayZB_transr   Ztranspose_nodeZmatmul_noderP   r   r   r   Z__replace_gemm_with_matmulS  s   

















"


z$ONNXModel.__replace_gemm_with_matmulc                 C   s   |   g}t| d S r   )r0   r7   r   )r8   r   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 qt
| 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_datar1   r   r   r0   r+   rA   Z
save_model)r8   Zoutput_pathZuse_external_data_formatrB   r   r   r   save_model_to_file  s   zONNXModel.save_model_to_filec                 C   H   t |tr
t |tsJ tt| jD ]}| j| |kr!|| j|< qd S r   )
isinstancestrr   r?   r   )r
   old_input_namenew_input_namejr   r   r   replace_node_input     
zONNXModel.replace_node_inputc                 C   "   | j jjD ]	}t||| qd S r   )r1   r0   r
   r7   r   )r8   r   r   r
   r   r   r   replace_input_of_all_nodes     z$ONNXModel.replace_input_of_all_nodesc                 C   ,   | j jjD ]}|j|v rt||| qd S r   )r1   r0   r
   r   r7   r   )r8   r   r   node_names_setr
   r   r   r   replace_input_of_nodes  
   
z ONNXModel.replace_input_of_nodesc                 C   r   r   )r   r   r   r?   r   )r
   old_output_namenew_output_namer   r   r   r   replace_node_output  r   zONNXModel.replace_node_outputc                 C   r   r   )r1   r0   r
   r7   r   )r8   r   r   r
   r   r   r   replace_output_of_all_nodes  r   z%ONNXModel.replace_output_of_all_nodesc                 C   r   r   )r1   r0   r
   r   r7   r   )r8   r   r   r   r
   r   r   r   replace_output_of_nodes  r   z!ONNXModel.replace_output_of_nodesc                 C   s   |   }g }|  }|D ]}|jdkr'| |jd s'|jd |vr'|| q| | g }|  D ](}|j|vr[| |js[|| | 	 j
D ]}|j|jkrZ| 	 j
| qJq3| | d S )Nr^   r   )rl   r=   r'   is_graph_outputr   r$   rM   r+   r   r0   r   r,   rh   )r8   rl   Zunused_nodesr=   r
   Zununsed_weightswZgraph_inputr   r   r   remove_unused_constant  s(   



z ONNXModel.remove_unused_constantc                       t  fdd| jjjD S )Nc                 3       | ]}|j  kV  qd S r   r   )r	   r   rY   r   r   r         z,ONNXModel.is_graph_output.<locals>.<genexpr>)anyr1   r0   r   )r8   rY   r   r   r   r      rQ   zONNXModel.is_graph_outputreturnc                    r   )Nc                 3   r   r   r   r   r[   r   r   r     r   z+ONNXModel.is_graph_input.<locals>.<genexpr>)r   r1   r0   r   )r8   r[   r   r   r   is_graph_input  rQ   zONNXModel.is_graph_inputc                 C   s  dgt |   }i }g }t|  D ]:\}}tdd |jD ||< || dkr3||  |  q|jD ]}|s;q6||vrE|g||< q6|| | q6qdd |  D }dd | jjjD }|| }	|		  d }
|	D ]+}|
|krtqm|}
||v r|| D ]}|| d ||< || dkr||  |  q~qmd}t |}||k r|| j
D ](}||v r|| D ]}|| d ||< || dkr||  |  |d }qq|d }||k s|t |  jksJ 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      g | ]}|j qS r   r   )r	   rB   r   r   r   r     re   z.ONNXModel.topological_sort.<locals>.<listcomp>c                 S   r   r   r   r   r   r   r   r     re   r   zGraph is not a DAGr
   )r?   r=   	enumeratesumr   r$   r+   r1   r0   sortr   r
   r(   r)   )r8   Z
deps_countZdeps_to_nodesZsorted_nodesZnode_idxr
   r   rj   Zgraph_input_namesZinput_namesZprev_input_namestartr   r   r   r   r   r     s\   

zONNXModel.topological_sortc                 C   s   t |  | jS r   )r!   r0   r1   r<   r   r   r   clean_initializers<  s   zONNXModel.clean_initializersc                 C   sJ   |j tjjkr#|dr#t|j}tdd |D r#td|j	d|S )Nraw_datac                 s   s    | ]	}|d @ d kV  qdS )   Nr   )r	   ir   r   r   r   C  r   z(ONNXModel._check_init.<locals>.<genexpr>zInitializer z	 has nan.)
	data_typer   TensorProtoZFLOAT8E4M3FNZHasFieldrt   r   r   r@   r   )r8   rB   testbr   r   r   rA   ?  s   

zONNXModel._check_initc                 C   sX   |j dkr*|jd }| |}|j}|tjjtjjtjjtjj	hv r*t
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   rV   r   r   r   ZFLOAT16FLOATDOUBLEZBFLOAT16RuntimeError)r8   r
   Z
zero_pointrB   Zdtyper   r   r   rO   G  s   


zONNXModel._check_noder   )F)7__name__
__module____qualname__r   r9   r=   r+   rC   r0   r.   rF   rI   rK   rM   rP   rR   rT   rV   rX   rZ   r   r]   rc   rf   rg   rh   rk   rl   rm   ro   rq   rs   ru   r|   r}   r~   staticmethodr   r   r   r   r   r   r   r   r   r   r   r   boolr   r   r   rA   rO   r   r   r   r   r7   Y   sj    	





]


4
r7   )pathlibr   r   Zonnx.helperhelperr%   Zonnx.numpy_helperZnumpy_helperr`   Zonnx.onnx_pbr   Zquant_utilsr   r   r!   r7   r   r   r   r   <module>   s   J