U
    yha"                  
   @   s\  d dl Z d dlmZ d dlmZmZ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mZ d dlmZ d d	lmZ ed
deedddZed
deedddZed
de
eeee
eedf eedf f dddZed
de
e
eedf eedf dddZed
de
edddZed
dd e
ee ee
dddZdS )!    N)SimpleQueue)ListDictTuple)GraphModule)Graph)Node)NodeListNodeSetlegalize_graph)lift_subgraph_as_module)compatibilityF)Zis_backward_compatible)nodesreturnc                 C   s   t | d}t }| D ]>}|jD ]}||kr ||  d7  < q || dkr|| qt }| s| }|| |j	D ]2}||kr|||  d8  < || dkr||| q|q\t
| t
|kstd|S )Nr      z@topological sorted nodes doesn't have same length as input nodes)dictfromkeysr   Zall_input_nodesputlistemptygetappenduserslenAssertionError)r   Zindegree_map
candidatesnodensorted_nodes r   S/var/www/html/venv/lib/python3.8/site-packages/torch/fx/passes/utils/fuser_utils.py	topo_sort   s&    


r!   )	partitionr   c                    sZ   t |  t } D ]"}|jD ]}| kr|| qqttd fdd}||rVdS dS )N)
root_nodesr   c                    sR   t  }| }|rN| }|| | kr,dS |jD ]}||kr@q2|| q2q
dS )NTF)setpopaddr   r   )r#   visitedqueuecurrent	user_nodeZpartition_setr   r    bfs_find_cycle<   s    

z*validate_partition.<locals>.bfs_find_cycleFT)r$   r   r   r   r	   bool)r"   outputsr   r*   r,   r   r+   r    validate_partition+   s    
r/   .)gmr   module_namer   c                    sH  D ]\}|j j| ks*t| d|   |jr>t| d|| j jkst| d|   qtsrtdt i i   fdd}D ]}||}| |< qi }D ]$}|j	D ]}|kr | ||< qqt
| }t|dkr|d n|   t| d	|d
\}	}
t
 }t
| }|	||fS )a1  
    Fuse nodes in graph_module into a GraphModule.

    Args:
        gm (GraphModule): target graph_module

        nodes (List[Node]): list of nodes in `gm` to fuse, where the node must be topologically sorted

        module_name: class name for the fused GraphModule

    Returns:
        fused_gm (GraphModule): fused graph module, where its node is a copy of `nodes` in `gm`

        original_inputs (Tuple[Node, ...]): input nodes to `nodes` in original `gm`

        original_outputs (Tuple[Node, ...]): consumer nodes of `nodes` in original `gm`

    z* doesn't belong to passed in graph module z# has been removed from owning graphz is not found in graph module z*Invalid partition, found dependency cyclesc                    sR   | j dkr
| kr |  S | krJj| j| jd}t| j|_|| < |  S )NZget_attr)Z	type_expr)opplaceholdernametypecopymeta)xZplaceholder_nodeZnode_mapZnode_to_placeholderr   Zsubgraphr   r    remap_inputs   s    
z)fuse_as_graphmodule.<locals>.remap_inputsr   r    )Z	comp_name
class_name)graphZowning_moduler   Z	_get_nameZ_erasedr   r/   r   Z	node_copyr   tuplevaluesoutputr   Zlintr   keys)r0   r   r1   r   r:   new_nodeZoutput_mappingr*   ZoutsZfused_gm_Zoriginal_inputsZoriginal_outputsr   r9   r    fuse_as_graphmodule\   s0    "$

 rD   )r0   sub_gmorig_inputsorig_outputsc           	      C   s   |j j}| || | jj||d d}t|dkrF|d j|dd nJt|D ](\}}tj	
|| j}|j|dd qNtdd |D |jd< | S )	N)argskwargsr   r   T)Zpropagate_metac                 s   s   | ]}|j d dV  qdS )valN)r7   r   ).0orig_outputr   r   r    	<genexpr>   s     zinsert_subgm.<locals>.<genexpr>rJ   )	__class____name__Zadd_submoduler=   Zcall_moduler   Zreplace_all_uses_with	enumeratetorchZfxZProxyr   r>   r7   )	r0   rE   rF   rG   submodule_nameZmodule_nodeirL   Z	proxy_outr   r   r    insert_subgm   s    rT   )r0   r   c                 C   s   t |D ]}| j| qd S N)reversedr=   Z
erase_node)r0   r   r   r   r   r    erase_nodes   s    rW   fused_)r0   
partitionsprefixr   c           
      C   s\   t |D ]F\}}t|}|t| }t| ||\}}}	t| |||	 t| | qt|  | S rU   )rP   r!   strrD   rT   rW   r   )
r0   rY   rZ   Zpartition_idr   r   rR   rE   rF   rG   r   r   r    fuse_by_partitions   s    r\   )rX   )r6   r(   r   typingr   r   r   Ztorch.fxrQ   Ztorch.fx.graph_moduler   Ztorch.fx.graphr   Ztorch.fx.noder   Ztorch.fx.passes.tools_commonr	   r
   r   Ztorch.fx.passes.utilsr   Ztorch.fx._compatibilityr   r!   r-   r/   r[   rD   rT   rW   r\   r   r   r   r    <module>   s2   0 `&