o
    ee                     @   s  d dl mZmZmZmZmZ d dlmZmZm	Z	m
Z
 d dlmZ d dlmZ 	d6dededeeeeef   d	eeeee f  fd
dZ						d7dededeeeef  deee  deee  dee dee dee dee d	efddZ										d8dededeeeef  deee  deee  dee dee dee dee dee dee dee dee d	efddZ	 	 	 	 	 	 	!d9d"ed#ed$ee d%ee d&ee d'ee d(ee d)ee d*ee d	efd+d,Z	 	 	 	 	 	 	 	!d:d-ed#ed$ee d%ee d&ee d'ee d(ee d)ee d.ee d*ee d	efd/d0Z	!d;d"ed1ed*ee d	efd2d3Z	!d;d-ed1ed*ee d	efd4d5ZdS )<    )ListSetTupleOptionalMutableMapping)
ModelProto
GraphProtohelperchecker)TensorProto)utilsNg1g2io_mapreturnc                 C   s  t | tur
tdt |turtddtt dtt dtt fdd}t fdtd	tt dtt fd
d}g }|s=g }dd |D }||| |||d}t|dkr\|d|f |dd | j	D dd |j	D }t|dkrz|d|f |dd | j
D dd |j
D }t|dkr|d|f |dd | jD dd |jD |dd | jD dd |jD  }t|dkr|d|f |S )a  Checks whether there are name collisions between two graphs

    Returns a list of tuples where the first element represents the member containing overlapping names
    (One of: "node", "edge", "value_info", "initializer", "sparse_initializer"), and the
    second element contains a list of names that appear in both graphs on that category.

    Optionally, it takes an io_map, representing the output/inputs to be connected. It provided, overlapping
    present in the io_map argument will be ignored.
     g1 argument is not an ONNX graph g2 argument is not an ONNX graphc1c2r   c                 S   s   t t| t|@ S N)listset)r   r    r   <D:\Projects\ConvertPro\env\Lib\site-packages\onnx/compose.py_overlapping   s   z-check_overlapping_names.<locals>._overlappinggraphexcludec                 S   s`   g }| j D ](}|jD ]}|dkr||vr|| q
|jD ]}|dkr,||vr,|| qq|S )N )nodeinputappendoutput)r   r   edgesnior   r   r   _edge_names   s   




z,check_overlapping_names.<locals>._edge_namesc                 S      h | ]}|d  qS    r   ).0elemr   r   r   	<setcomp>.       z*check_overlapping_names.<locals>.<setcomp>)r   r   edgec                 S      g | ]}|j qS r   namer*   er   r   r   
<listcomp>7       z+check_overlapping_names.<locals>.<listcomp>
value_infoc                 S   r/   r   r0   r2   r   r   r   r4   ;   r5   initializerc                 S      g | ]}|j jqS r   valuesr1   r2   r   r   r   r4   ?   r-   c                 S   r8   r   r9   r2   r   r   r   r4   @   r-   c                 S   r8   r   indicesr1   r2   r   r   r   r4   A   r-   c                 S   r8   r   r;   r2   r   r   r   r4   B   r-   sparse_initializer)typer   
ValueErrorr   strr   r   lenr    r6   r7   r=   )r   r   r   r   r&   resultZio_map_inputsoverlapr   r   r   check_overlapping_names	   s>   "$""rD   inputsoutputsprefix1prefix2r1   
doc_stringc	                    s  t | tur
tdt |turtdsrFr*t }	|	|  |	} t| d} r<t }
|
| |
}t|d}fdd|D }dd |D dd |D d	d
 |D }dd | jD }dd |jD }|sp|r|sdd | jD }dd |jD }nt|  fdd| jD } fdd|jD }|sdd | jD }dd |jD }nt|fdd| jD }fdd|jD }t|t| jk st|t| jk rt	
t| }|||j} t|t|jk st|t|jk rt	
t|}|||j}|D ]\}}||vrtd| d||vr+td| dqt| ||}t|dkrQ|d \}}td| dd| d d t }|j| j t|j}|j|j t|j}t||D ]}|j| }t|jD ]\}}||v r|| |j|< q}qq|rt| |j fdd| jD  |j fd d|jD  n|j| j |jfd!d|jD  |rt||jfd"d| jD  |jfd#d|jD  n|jfd$d| jD  |j|j |j| j |jfd%d|jD  |j| j |jfd&d|jD  |j| j |jfd'd|jD  |d(urI|nd)| j|jg|_|d(u rud*| j d+|j d| j d, | j d, |j d, |j }||_|S )-a  Combines two ONNX graphs into a single one.

    The combined graph is defined by connecting the specified set of outputs/inputs. Those inputs/outputs
    not specified in the io_map argument will remain as inputs/outputs of the combined graph.

    Arguments:
        g1 (GraphProto): First graph
        g2 (GraphProto): Second graph
        io_map (list of pairs of string): The pairs of names [(out0, in0), (out1, in1), ...]
                                          representing outputs of the first graph and inputs of the second
                                          to be connected
        inputs (list of string): Optional list of inputs to be included in the combined graph
                                 By default, all inputs not present in the ``io_map`` argument will be
                                 included in the combined model
        outputs (list of string): Optional list of outputs to be included in the combined graph
                                  By default, all outputs not present in the ``io_map`` argument will be
                                  included in the combined model
        prefix1 (string): Optional prefix to be added to all names in g1
        prefix2 (string): Optional prefix to be added to all names in g2
        name (string): Optional name for the combined graph
                       By default, the name is g1.name and g2.name concatenated with an undescore delimiter
        doc_string (string): Optional docstring for the combined graph
                             If not provided, a default docstring with the concatenation of g1 and g2 docstrings is used

    Returns:
        GraphProto
    r   r   prefixc                    <   g | ]} r |d   n|d  r|d  n|d fqS r   r)   r   r*   iorG   rH   r   r   r4          z merge_graphs.<locals>.<listcomp>c                 S   r'   )r   r   rN   r   r   r   r,      r-   zmerge_graphs.<locals>.<setcomp>c                 S   r'   r(   r   rN   r   r   r   r,      r-   c                 S   s   i | ]\}}||qS r   r   )r*   Zout_nameZin_namer   r   r   
<dictcomp>   s    z merge_graphs.<locals>.<dictcomp>c                 S      h | ]}|j qS r   r0   r*   r%   r   r   r   r,      r5   c                 S   rS   r   r0   r*   r$   r   r   r   r,      r5   c                 S   r/   r   r0   rU   r   r   r   r4      r5   c                 S   r/   r   r0   rU   r   r   r   r4      r5   c                       g | ]
}|j  v r|j qS r   r0   rU   	input_setr   r   r4          c                    s&   g | ]}|j  v s|j v r|j qS r   r0   rU   )rX   io_map_g2_insr   r   r4         & c                 S   r/   r   r0   rT   r   r   r   r4      r5   c                 S   r/   r   r0   rT   r   r   r   r4      r5   c                    s&   g | ]}|j v s|j  v r|j qS r   r0   rT   )io_map_g1_outs
output_setr   r   r4      r[   c                    rV   r   r0   rT   r]   r   r   r4      rY   zOutput z is not present in g1zInput z is not present in g2r   z=Cant merge two graphs with overlapping names. Found repeated z names: , 
zYConsider using ``onnx.compose.add_prefix`` to add a prefix to names in one of the graphs.c                       g | ]	}|j  v r|qS r   r0   rU   rW   r   r   r4          c                    ra   r   r0   rU   rW   r   r   r4      rb   c                       g | ]	}|j  vr|qS r   r0   rU   rZ   r   r   r4      rb   c                    ra   r   r0   rT   r^   r   r   r4      rb   c                    ra   r   r0   rT   r^   r   r   r4      rb   c                    rc   r   r0   rT   )r\   r   r   r4      rb   c                    rc   r   r0   r*   initrd   r   r   r4      rb   c                    s   g | ]
}|j j vr|qS r   r9   re   rd   r   r   r4      rY   c                    rc   r   r0   )r*   vird   r   r   r4      rb   N_zGraph combining  and z

)r>   r   r?   CopyFromadd_prefix_graphr!   r   r   rA   r   Z	Extractorr	   
make_modelZextract_modelr   rD   joinr   extendrange	enumerater7   r=   r6   r1   rI   )r   r   r   rE   rF   rG   rH   r1   rI   Zg1_copyZg2_copyZreversed_io_mapZg1_outsZg2_insZ	g1_inputsZ	g2_inputsZ
g1_outputsZ
g2_outputse1e2Zg1_out_nameZ
g2_in_nameZoverlapping_namescategorynamesgZg2_nodes_beginZg2_nodes_endZnode_idxr   indexr   )rX   r\   rZ   r]   rG   rH   r   merge_graphsI   s   &


$&





"
rw   onnx.compose.merge_models1.0r   r)   m1m2producer_nameproducer_versiondomainmodel_versionc              	      sB  t | tur
tdt |turtd| j|jkr'td| j d|j d| j}i }dd | jD dd |jD  }|D ]$}|j|v r\||j }|j|kr[td	| j d
|j q>|j||j< q> sgr ryt }||  |} t|  d} rt }|| |}t|d} fdd|D }t	| j
|j
|||||d}tj||	|
||||d}i }| jD ]}|j||j< q|jD ](}|j|v r||j }||jkrtd|j d| d
|j dq|j||j< qt|| tdd | jD dd |jD @ }|rtdd| |j| j |j|j t| |S )a=  Combines two ONNX models into a single one.

    The combined model is defined by connecting the specified set of outputs/inputs.
    Those inputs/outputs not specified in the io_map argument will remain as
    inputs/outputs of the combined model.

    Both models should have the same IR version, and same operator sets imported.

    Arguments:
        m1 (ModelProto): First model
        m2 (ModelProto): Second model
        io_map (list of pairs of string): The pairs of names [(out0, in0), (out1, in1), ...]
                                          representing outputs of the first graph and inputs of the second
                                          to be connected
        inputs (list of string): Optional list of inputs to be included in the combined graph
                                 By default, all inputs not present in the ``io_map`` argument will be
                                 included in the combined model
        outputs (list of string): Optional list of outputs to be included in the combined graph
                                  By default, all outputs not present in the ``io_map`` argument will be
                                  included in the combined model
        prefix1 (string): Optional prefix to be added to all names in m1
        prefix2 (string): Optional prefix to be added to all names in m2
        name (string): Optional name for the combined graph
                       By default, the name is g1.name and g2.name concatenated with an undescore delimiter
        doc_string (string): Optional docstring for the combined graph
                             If not provided, a default docstring with the concatenation of g1 and g2 docstrings is used
        producer_name (string): Optional producer name for the combined model. Default: 'onnx.compose'
        producer_version (string): Optional producer version for the combined model. Default: "1.0"
        domain (string): Optional domain of the combined model. Default: ""
        model_version (int): Optional version of the graph encoded. Default: 1

    Returns:
        ModelProto
    z m1 argument is not an ONNX modelz m2 argument is not an ONNX modelzIR version mismatch z != z2. Both models should have have the same IR versionc                 S      g | ]}|qS r   r   r*   entryr   r   r   r4   '      z merge_models.<locals>.<listcomp>c                 S   r   r   r   r   r   r   r   r4   (  r   zPCan't merge two models with different operator set ids for a given domain. Got: ri   rJ   c                    rL   rM   r   rN   rP   r   r   r4   @  rQ   )rE   rF   r1   rI   )r|   r}   r~   r   opset_imports
ir_versionzaCan't merge models with different values for the same model metadata property. Found: property = z, with values .c                 S   rS   r   r0   )r*   fr   r   r   r,   a  r5   zmerge_models.<locals>.<setcomp>zPCan't merge models with overlapping local function names. Found in both graphs: r_   )r>   r   r?   r   Zopset_importr~   versionrj   
add_prefixrw   r   r	   rl   Zmetadata_propsvaluekeyZset_model_propsr   	functionsrm   Z	MergeFromr
   Zcheck_model)rz   r{   r   rE   rF   rG   rH   r1   rI   r|   r}   r~   r   r   Zopset_import_mapr   r   Zfound_versionZm1_copyZm2_copyr   modelZmodel_propsZ
meta_entryr   Zfunction_overlapr   rP   r   merge_models   s   1




	




$
r   TFr   rK   rename_nodesrename_edgesrename_inputsrename_outputsrename_initializersrename_value_infosinplacec	                 C   s  t | tur
td|st }	|	|  n| }	dtdtdtfdd}
i }|rG|	jD ]}|jD ]	}|
||||< q.|jD ]	}|
||||< q;q)n"|rX|	jD ]}|
||j||j< qL|ri|	jD ]}|
||j||j< q]|rx|	jD ]	}|
||j|_qn|r|	j	D ]}|
||j||j< q}|	j
D ]}|
||jj||jj< |
||jj||jj< q|r|	jD ]}|
||j||j< q|	jD ]8}tt|jD ]}|j| |v r||j|  |j|< qtt|jD ]}|j| |v r||j|  |j|< qq|	jD ]}|j|v r||j |_q|	jD ]}|j|v r||j |_q|	j	D ]}|j|v r(||j |_q|	j
D ]!}|jj|v r>||jj |j_|jj|v rM||jj |j_q-|	jD ]}|j|v r`||j |_qR|	S )a  Adds a prefix to names of elements in a graph: nodes, edges, inputs, outputs,
    initializers, sparse initializer, value infos.

    It can be used as a utility before merging graphs that have overlapping names.
    Empty names are not prefixed.

    Arguments:
        graph (GraphProto): Graph
        prefix (str): Prefix to be added to each name in the graph
        rename_nodes (bool): Whether to prefix node names
        rename_edges (bool): Whether to prefix node edge names
        rename_inputs (bool): Whether to prefix input names
        rename_outputs (bool): Whether to prefix output names
        rename_initializers (bool): Whether to prefix initializer and sparse initializer names
        rename_value_infos (bool): Whether to prefix value info names
        inplace (bool): If True, mutates the graph directly.
                        Otherwise, a copy will be created

    Returns:
        GraphProto
    #graph argument is not an ONNX graphrK   r1   r   c                 S   s   t |dkr
| | S |S )Nr   )rA   )rK   r1   r   r   r   	_prefixed  s   z#add_prefix_graph.<locals>._prefixed)r>   r   r?   rj   r@   r   r   r!   r1   r7   r=   r:   r<   r6   ro   rA   )r   rK   r   r   r   r   r   r   r   ru   r   Zname_mapr#   r3   r   rf   Zsparse_initr$   Zin_descZout_descr7   r=   r6   r   r   r   rk   n  s    














rk   r   rename_functionsc
                 C   s   t | tur
td|	st }
|
|  |
} t| j|||||||dd	 |rdi }| jD ]}||j }|||j< ||_q+| jD ]}|jD ]}|j	|v rP||j	 |_	qCq>| jjD ]}|j	|v rc||j	 |_	qV| S )a  Adds a prefix to names of elements in a graph: nodes, edges, inputs, outputs,
    initializers, sparse initializer, value infos, and local functions.

    It can be used as a utility before merging graphs that have overlapping names.
    Empty names are not _prefixed.

    Arguments:
        model (ModelProto): Model
        prefix (str): Prefix to be added to each name in the graph
        rename_nodes (bool): Whether to prefix node names
        rename_edges (bool): Whether to prefix node edge names
        rename_inputs (bool): Whether to prefix input names
        rename_outputs (bool): Whether to prefix output names
        rename_initializers (bool): Whether to prefix initializer and sparse initializer names
        rename_value_infos (bool): Whether to prefix value info nanes
        rename_functions (bool): Whether to prefix local function names
        inplace (bool): If True, mutates the model directly.
                        Otherwise, a copy will be created

    Returns:
        ModelProto
    #model argument is not an ONNX modelT)r   r   r   r   r   r   r   )
r>   r   r?   rj   rk   r   r   r1   r   Zop_type)r   rK   r   r   r   r   r   r   r   r   mZ
f_name_mapr   Z
new_f_namer#   r   r   r   r     sB   "







r   dim_idxc                 C   s  t | tur
td|st }||  n| }dd |jD }|jD ]>}tt|jD ]}|j| |v rA|j| d|  |j|< q+tt|jD ]}|j| |v r_|j| d|  |j|< qIq"|j	d }|j
tjdg |g| dtj| dtjd	g|gd
d tt|jD ]E}|jd}	|	j	d|  }
|j
tjd|
|g|	j	gd|	j	 d dd |	j jjjD }||d	 |j
t|	j	|	j jj| q|S )aE  Inserts an extra dimension with extent 1 to each output in the graph.

    Inserts an Unsqueeze node for each output. It can be used as a utility before merging graphs,
    for example when the second one expects a batch dimension.

    Arguments:
        graph (GraphProto): Graph
        dim_idx (int): Index of the dimension to be inserted.
                       A negative value means counting dimensions from the back.
        inplace (bool): If True, mutates the model directly.
                        Otherwise, a copy will be created

    Returns:
        GraphProto
    r   c                 S   r/   r   r0   )r*   r!   r   r   r   r4   =  r5   z(expand_out_dim_graph.<locals>.<listcomp>Z_collapsed_dim_Z_expand_out_dim_idxConstantz	-constantz-valuer)   )r1   Z	data_typedimsvals)rE   rF   r1   r   r   Z	Unsqueezez
unsqueeze-)rE   rF   r1   c                 S   r/   r   )Z	dim_value)r*   dr   r   r   r4   V  r5   )r>   r   r?   rj   r!   r   ro   rA   r   r1   r    r	   Z	make_nodeZmake_tensortpZINT64popZtensor_typeshapediminsertZmake_tensor_value_infoZ	elem_type)r   r   r   ru   Zorig_out_namesr#   r$   Zexpand_dim_krh   r%   Zprev_outputZ	new_shaper   r   r   expand_out_dim_graph   sP   

r   c                 C   s@   t | tur
td|st }||  |} t| j|dd | S )aE  Inserts an extra dimension with extent 1 to each output in the graph.

    Inserts an Unsqueeze node for each output. It can be used as a utility before merging graphs,
    for example when the second one expects a batch dimension.

    Arguments:
        model (ModelProto): Model
        dim_idx (int): Index of the dimension to be inserted.
                       A negative value means counting dimensions from the back.
        inplace (bool): If True, mutates the model directly.
                        Otherwise, a copy will be created

    Returns:
        ModelProto
    r   T)r   )r>   r   r?   rj   r   r   )r   r   r   r   r   r   r   expand_out_dim]  s   
r   r   )NNNNNN)
NNNNNNrx   ry   r   r)   )TTTTTTF)TTTTTTTF)F)typingr   r   r   r   r   Zonnxr   r   r	   r
   r   r   r   r@   rD   rw   intr   boolrk   r   r   r   r   r   r   r   <module>   sB  
D

	

 %

	

 		

l	

L
@