o
    Ďih                     @  s   d dl mZ d dlmZ d dlmZmZmZmZm	Z	m
Z
mZ er&d dlmZ 	dCdDddZ						dEdFddZ										dGdHd&d'Z	(	(	(	(	(	(	)	dIdJd7d8Z	(	(	(	(	(	(	(	)dKdLd;d<Z	)dMdNd?d@Z	)dMdOdAdBZdS )P    )annotations)TYPE_CHECKING)AttributeProto
GraphProto
ModelProtoTensorProtocheckerhelperutils)MutableMappingNg1r   g2io_maplist[tuple[str, str]] | Nonereturnlist[tuple[str, list[str]]]c                 C  s>  t | ts	tdt |tstdddd}dd dd}g }|s#g }dd |D }||| |||d}|r>|d|f |dd | jD dd |jD }|rX|d|f |dd | jD dd |jD }|rr|d|f |dd | jD dd |jD |dd | jD dd |jD  }|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	list[str]c2r   c                 S  s   t t| t|@ S N)listset)r   r    r   H/home/jeff/fluffinator/venv/lib/python3.10/site-packages/onnx/compose.py_overlapping'   s   z-check_overlapping_names.<locals>._overlappingNgraphr   excludeset[str] | Nonec                 S  sn   |d u rt  }g }| jD ](}|jD ]}|dkr ||vr || q|jD ]}|dkr3||vr3|| q$q|S )N )r   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   edgec                 S     g | ]}|j qS r   namer-   er   r   r   
<listcomp>C       z+check_overlapping_names.<locals>.<listcomp>
value_infoc                 S  r2   r   r3   r5   r   r   r   r7   I   r8   initializerc                 S     g | ]}|j jqS r   valuesr4   r5   r   r   r   r7   O   r0   c                 S  r;   r   r<   r5   r   r   r   r7   P   r0   c                 S  r;   r   indicesr4   r5   r   r   r   r7   R   r0   c                 S  r;   r   r>   r5   r   r   r   r7   S   r0   sparse_initializer)r   r   r   r   r   r   r   )r   r   r   r   r   r   )
isinstancer   	TypeErrorr#   r9   r:   r@   )r   r   r   r   r)   resultio_map_inputsoverlapr   r   r   check_overlapping_names   sF   


rF   list[tuple[str, str]]inputslist[str] | Noneoutputsprefix1
str | Noneprefix2r4   
doc_stringc	                   s  t | ts	tdt |tstdsrD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 }|sn|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rO|d \}}td| dd| d d t }|j| j t|j}|j|j t|j}d6 fd&d'  ||| |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d0d|jD  |d1ur0|nd2| j|jg|_|d1u r\d3| j d4|j d| j d5 | j d5 |j d5 |j }||_|S )7a  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 underscore 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rK   rM   r   r   r7          z merge_graphs.<locals>.<listcomp>c                 S  r*   )r   r   rS   r   r   r   r/      r0   zmerge_graphs.<locals>.<setcomp>c                 S  r*   r+   r   rS   r   r   r   r/      r0   c                 S  s   i | ]\}}||qS r   r   )r-   out_namein_namer   r   r   
<dictcomp>   s    z merge_graphs.<locals>.<dictcomp>c                 S     h | ]}|j qS r   r3   r-   r(   r   r   r   r/      r8   c                 S  rZ   r   r3   r-   r'   r   r   r   r/      r8   c                 S  r2   r   r3   r\   r   r   r   r7      r8   c                 S  r2   r   r3   r\   r   r   r   r7      r8   c                      g | ]
}|j  v r|j qS r   r3   r\   	input_setr   r   r7          c                   s&   g | ]}|j  v s|j v r|j qS r   r3   r\   )r_   io_map_g2_insr   r   r7      
    c                 S  r2   r   r3   r[   r   r   r   r7      r8   c                 S  r2   r   r3   r[   r   r   r   r7      r8   c                   s&   g | ]}|j v s|j  v r|j qS r   r3   r[   )io_map_g1_outs
output_setr   r   r7      rb   c                   r]   r   r3   r[   rd   r   r   r7      r`   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.	sub_graphr   startintendr   Nonec                   sv   t ||D ]3}| j| }|jD ]}|jtjkr" |jdt|jj qt|j	D ]\}}|v r7| |j	|< q(qd S Nr   )
ranger!   	attributetyper   GRAPHglen	enumerater"   )rh   ri   rk   node_idxr!   attrindexname_)
connect_ioreversed_io_mapr   r   ry      s   

z merge_graphs.<locals>.connect_ioc                      g | ]	}|j  v r|qS r   r3   r\   r^   r   r   r7          c                   r{   r   r3   r\   r^   r   r   r7      r|   c                      g | ]	}|j  vr|qS r   r3   r\   ra   r   r   r7      r|   c                   r{   r   r3   r[   re   r   r   r7      r|   c                   r{   r   r3   r[   re   r   r   r7      r|   c                   r}   r   r3   r[   )rc   r   r   r7      r|   c                   r}   r   r3   r-   initr~   r   r   r7      r|   c                   s   g | ]
}|j j vr|qS r   r<   r   r~   r   r   r7     s
    c                   r}   r   r3   )r-   vir~   r   r   r7   
  r|   N_zGraph combining  and z

)rh   r   ri   rj   rk   rj   r   rl   )rA   r   rB   CopyFromadd_prefix_graphr$   r"   r   rs   r
   	Extractorr	   
make_modelextract_modelr   
ValueErrorrF   joinr!   extendr:   r@   r9   r4   rN   )r   r   r   rH   rJ   rK   rM   r4   rN   g1_copyg2_copyg1_outsg2_ins	g1_inputs	g2_inputs
g1_outputs
g2_outputse1e2g1_out_name
g2_in_nameoverlapping_namescategorynamesrr   g2_nodes_beging2_nodes_endr   )ry   r_   rc   ra   rd   rK   rM   rz   r   merge_graphs[   s   
&



$&




"

r   onnx.compose.merge_models1.0r    r,   m1r   m2producer_nameproducer_versiondomainmodel_version
int | Nonec              	     s2  t | ts	tdt |tstd| j|jkr%td| j d|j d| j}i }t| jt|j }|D ]$}|j|v rT||j }|j|krStd| j d|j q6|j||j< q6 s_r rqt }|	|  |} 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 underscore 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 != z-. Both models should have the same IR versionzPCan't merge two models with different operator set ids for a given domain. Got: r   rO   c                   rQ   rR   r   rS   rU   r   r   r7   u  rV   z merge_models.<locals>.<listcomp>)rH   rJ   r4   rN   )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  rZ   r   r3   )r-   fr   r   r   r/     r8   zmerge_models.<locals>.<setcomp>zPCan't merge models with overlapping local function names. Found in both graphs: rf   )rA   r   rB   r   r   r   opset_importr   versionr   
add_prefixr   r   r	   r   metadata_propsvaluekeyset_model_props	functionsr   	MergeFromr   check_model)r   r   r   rH   rJ   rK   rM   r4   rN   r   r   r   r   r   opset_import_mapr   entryfound_versionm1_copym2_copyr   modelmodel_props
meta_entryr   function_overlapr   rU   r   merge_models  s   
1





	





r   TFr   rP   strrename_nodesbool | Nonerename_edgesrename_inputsrename_outputsrename_initializersrename_value_infosinplacename_mapdict[str, str] | Nonec
                 C  s  t | ts	td|st }
|
|  n| }
ddd}|	du r!i }	|rBd	d
 |
jD }|
jD ]}|jD ]}||vr@||||	|< q3q.|rS|
jD ]}|||j|	|j< qG|rd|
jD ]}|||j|	|j< qX|r|
jD ]}|||j|_|jD ]}|j	rt
|j	|d|	d quqi|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 ]2}t|jD ]\}}|j| |	v r|	| |j|< qt|jD ]\}}|j| |	v r|	| |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 rE|	|jj |j_|jj|	v rT|	|jj |j_q4|
jD ]}|j|	v rg|	|j |_qY|
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
        name_map: (Dict): shared name_map in subgraph

    Returns:
        GraphProto
    #graph argument is not an ONNX graphrP   r   r4   r   c                 S  s   t |dkr
| | S |S rm   )rs   )rP   r4   r   r   r   	_prefixed  s   z#add_prefix_graph.<locals>._prefixedNc                 S  rZ   r   r3   r[   r   r   r   r/     r8   z#add_prefix_graph.<locals>.<setcomp>T)r   r   )rP   r   r4   r   r   r   )rA   r   rB   r   r$   r!   r"   r4   ro   rr   r   r:   r@   r=   r?   r9   rt   )r   rP   r   r   r   r   r   r   r   r   rr   r   graph_output_namesr&   r6   r   ro   r   sparse_initr'   r$   input_in_descout_descr:   r@   r9   r   r   r   r     s   
"
















r   r   rename_functionsc
                 C  s   t | ts	td|	st }
|
|  |
} t| j|||||||dd	 |rci }| jD ]}||j }|||j< ||_q*| jD ]}|jD ]}|j	|v rO||j	 |_	qBq=| jjD ]}|j	|v rb||j	 |_	qU| 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   )
rA   r   rB   r   r   r   r   r4   r!   op_type)r   rP   r   r   r   r   r   r   r   r   m
f_name_mapr   
new_f_namer&   r   r   r   r   )  sD   
"







r   dim_idxrj   c                 C  s  t | ts	td|st }||  n| }dd |jD }|jD ]2}t|jD ]\}}||v r:|d|  |j|< q(t|jD ]\}}||v rR|d|  |j|< q@q!|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  r2   r   r3   )r-   r$   r   r   r   r7     r8   z(expand_out_dim_graph.<locals>.<listcomp>_collapsed_dim__expand_out_dim_idxConstantz	-constantz-valuer,   )r4   	data_typedimsvals)rH   rJ   r4   r   r   	Unsqueezez
unsqueeze-)rH   rJ   r4   c                 S  r2   r   )	dim_value)r-   dr   r   r   r7     r8   )rA   r   rB   r   r$   r!   rt   r"   r4   r#   r	   	make_nodemake_tensorr   INT64rn   rs   poprp   tensor_typeshapediminsertmake_tensor_value_info	elem_type)r   r   r   rr   orig_out_namesr&   r'   outinpexpand_dim_kr   r(   prev_output	new_shaper   r   r   expand_out_dim_graphs  sj   



r   c                 C  s>   t | ts	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   )rA   r   rB   r   r   r   )r   r   r   r   r   r   r   expand_out_dim  s   

r   r   )r   r   r   r   r   r   r   r   )NNNNNN)r   r   r   r   r   rG   rH   rI   rJ   rI   rK   rL   rM   rL   r4   rL   rN   rL   r   r   )
NNNNNNr   r   r    r,   )r   r   r   r   r   rG   rH   rI   rJ   rI   rK   rL   rM   rL   r4   rL   rN   rL   r   rL   r   rL   r   rL   r   r   r   r   )TTTTTTFN)r   r   rP   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )TTTTTTTF)r   r   rP   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )F)r   r   r   rj   r   r   r   r   )r   r   r   rj   r   r   r   r   )
__future__r   typingr   onnxr   r   r   r   r   r	   r
   collections.abcr   rF   r   r   r   r   r   r   r   r   r   r   <module>   sb   $
I H |MS