o
    wi9                     @  s   d dl mZ d dlZd dlmZmZmZmZm	Z	m
Z
mZ d dlmZmZmZmZmZmZmZmZmZ d dlmZ d ddZd!ddZd"ddZ				d#d$ddZdS )%    )annotationsN)AttributeProtoFunctionProto
GraphProto
ModelProto	NodeProtoSparseTensorProtoTensorProto)	make_attributemake_function
make_graph
make_model	make_nodemake_tensormake_tensor_value_infoset_model_propstensor_dtype_to_np_dtype)
from_arraynoder   	thresholdintvalue_constant_of_shapefloatreturnlist[NodeProto]c              
   C  s   | j dkrtd| j d| jD ]j}|jdkr!td| jd|jdkrt|j}|j d}|j}t|}||kr@| g  S t	tj
t|tjd	|d
}t|j}	tdg |g|d}
td|g| jt	tj
|g|	d	d}|
|g  S td|j| gS )zReplaces a Constant node with a large tensor (with more than threshold elements) by a sequence of nodes that produces a dummy constant of same shape as original tensor.Constantz!Node type must be 'Constant' not .sparse_valuezEThis feature is not yet implemented for a sparse constant (node name=).value__SHAPEdtypenamer   ConstantOfShapez'Replacement of constant with attribute )op_type	TypeError	attributer$   NotImplementedErrortdimsnpprodr   arraylistint64r   	data_typer   output)r   r   r   attr   new_namer,   sizeinitr"   
node_shapenew_node r:   Y/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/onnx/tools/replace_constants.py_replace_constant   sF   







r<   onxGraphProto | FunctionProtoc                   s  t | trt| j}nt | trt| j}n
tdt|  dt  |D ]} t|jO   t|j	O  q% fdd}t
dg |dgdd}t
dg |d	gd
d}i }t|D ]\}}|jdkrbqX|jd }t
d|g|| dg}	t
d|j	d |	j	d |j	d g|| dg}
t|jd
kr|jd jj}ntj}t
d|
j	d g|| dg|d}t
d|	j	d g|| dg|d}t
d|j	d |j	d g|| dg}t
d|j	d |g|j	}|	|
||||g||< qXt| ddD ]\}}||||d
 < q|d| |d
| t | tr%t|| j| j| j	| j| jd}|S t | tr<t| j| j| j| j	|| jd}|S tdt|  d)zReplaces all *ConstantOfShape* by node *Range* to avoid constant tensors.

    The function is not recursive. The recursivity is done by
    *replace_initializer_by_constant_of_shape*.
    Not implemented for type r   c                   sJ   |  vr  |  | S d}	 |  d| }| vr   | |S |d7 }q)N   T_   )addRuntimeError)prefixir$   existing_namesr:   r;   
_find_name[   s   

z9_replace_constant_of_shape_with_range.<locals>._find_namer   zeror   )	value_intonerB   r&   
ReduceProd_NRange_RANGECast_RANGEf)to_NfDiv_FLATReshapeT)reverseinitializersparse_initializeropset_imports)
isinstancer   r0   r   r   r(   typesetinputr3   r   	enumerater'   lenr)   r+   r2   r	   FLOATsorteditemsinsertr   r$   rZ   r[   r   domainopset_import)r=   nodesr   rI   cst0cst1updateinodeshapenarS   accldreshupgraphnew_onxr:   rG   r;   %_replace_constant_of_shape_with_rangeG   st   



$$"ry   c                 C  sn  t | trt| j}nt | trt| j}n
tdt|  dt }|D ]}|t|jO }|t|j	O }q%i }t
|D ]7\}}|jdkrFq<|jd j}t|j|jdg|g}td|j|j	}	t|jd j|d}
|	j|
 |	||< q<| D ]\}}|||< qxt | trt|| j| j| j	| j| jd}|S t | trt| j| j| j| j	|| jd}|S tdt|  d)	z7Replaces all fill value of all nodes *ConstantOfShape*.r?   r   r&   r   rB   r%   rY   r\   )r^   r   r0   r   r   r(   r_   r`   ra   r3   rb   r'   r)   r+   r   r$   r2   r   r
   appendrf   r   rZ   r[   r   rh   ri   )r=   r   rj   rH   r   rm   rn   tensor
new_tensorr9   r4   rv   rw   rx   r:   r:   r;    _replace_constant_of_shape_value   sX   






r}      F      ?'FunctionProto | GraphProto | ModelProto
ir_version
int | None	use_rangeboolc               
     s  t tr`d}g }jD ] }|jdkr't|}t|dkr!d}|| q|| q|rOtj	j
jj|jd}	rDt|	S dkrMt|	S |	S rUtS dkr^tS S t trtj pljd}
 fdd	jD }t|
|jj pjjj	jd
}tjdkrdd jD }t|| |jdd= jD ]7}|j }|j	dkr|jdk r͈rtd|j d|j	dkr|jdk rtd|j d|j	|_	|j|_q|S t tst dt! dd}g }t" g }g }j#D ]n}t$|j%}t&'|}|kr || q|d7 }|j
 d}|t(t&j)t*|t&j+d|d t,|j-}t.d|g|j
gt(t&j)dg|dd}|| |j
  duru dkru|t/|t0j1t|g qg }j2D ]&}t$|j%}t&'|}|kr|| q|t3d|j4j
d|j5j
djD ]}|jdkrt|}t|dkr|d7 }|| qd}g }|j6D ]7}|j!t7j8krt9|d r|j:durt|j: d!}t;|t;|j:krd}t<|j
|}|| q|r"t.|j|j|j}|j6| || |d7 }q|| q|dkrWt=|j
fd"d	jD | j||d#}rKt|S dkrUt|S |S r^tS dkrhtS S )$a  Replace initializers or constant node by nodes *ConstantOfShape* to reduce the size.

    This reduce the cost to write a unit test about a specific graph structure.

    Args:
        onx: ModelProto
        threshold: every initializer under this threshold is not
            impacted
        ir_version: initializer must be specified as input for
            `ir_version <= 3`, this must be specified if onx is
            :class:`FunctionProto` or :class:`GraphProto`
        use_range: if uses operator *Range* instead of *ConstantOfShape*
            to avoid constant tensors
        value_constant_of_shape: value to use as a value for all nodes
            *ConstantOfShape*, a high value may produce nan or inf
            predictions

    Returns:
        onx, modified ModelProto

    The function is designed so that the function can be reapplied on a modified model
    and either replace *ConstantOfShape* with *Range* operators, either replace the fill value
    for every *ConstantOfShape*.
    Fr   r@   Tr\   rB   )r   r   r   r   c              	     s$   g | ]}t | pjd qS )r   r   r   r   )(replace_initializer_by_constant_of_shaper   ).0f)r   r=   r   r   r   r:   r;   
<listcomp>  s    z<replace_initializer_by_constant_of_shape.<locals>.<listcomp>)	functionsproducer_nameproducer_versionr   
doc_stringrh   model_versionr   c                 S  s   i | ]}|j |jqS r:   )keyr   )r   pr:   r:   r;   
<dictcomp>3  s    z<replace_initializer_by_constant_of_shape.<locals>.<dictcomp>N    z.Range was introduced in opset 11 but opset is r   	   z7ConstantOfShape was introduced in opset 9 but opset is z-onx should be a GraphProto at this stage not r    r!   r#   r&   r   r%      zKThis feature is not yet implemented for a sparse initializer (indices.name=z, values.name=r   gr   c                   s   g | ]	}|j  vr|qS r:   r#   )r   rF   )removedr:   r;   r     s    rY   )>r^   r   r   r'   r<   rc   extendrz   r   rh   r$   ra   r3   ri   ry   r}   r   r   rw   r   r   r   r   r   r   r   metadata_propsr   rC   versionrD   r   r(   r_   r`   rZ   tupler,   r-   r.   r   r/   r0   r1   r   r2   r   r   r	   INT64r[   r*   indicesvaluesr)   r   GRAPHhasattrr   idr
   r   ) r=   r   r   r   r   modified	new_nodesr   	cst_nodesrx   	new_graphnew_functionsmodelr   oimpop_setn_modificationsadditional_inputs	new_initsr7   r,   r6   r5   r"   new_sparse_initssp_initshape_nodesattsr4   r   r9   rw   r:   )r   r=   r   r   r   r   r;   r      sP  

































r   )r   r   r   r   r   r   r   r   )r=   r>   r   r>   )r=   r>   r   r   r   r>   )r~   NFr   )
r=   r   r   r   r   r   r   r   r   r   )
__future__r   numpyr-   onnxr   r   r   r   r   r   r	   onnx.helperr
   r   r   r   r   r   r   r   r   onnx.numpy_helperr   r<   ry   r}   r   r:   r:   r:   r;   <module>   s   $,	

(
X9