
    9j+                        d dl Z d dl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 d dlmZmZmZ d dlmZ  ed	      d
edefd       Z ed	      dedefd       Z ed	      	 dddde	d
ededeeedz  f   dz  dedee	eedf   eedf   f   fd       Z ed	      	 dde	de	deedf   deedf   dedz  de	fd       Z ed	      de	d
eddfd       Z ed	      	 	 d de	deeeedz  f      dedede	f
d       Zy)!    N)compatibility)Graph)GraphModule)Node)legalize_graphNodeListNodeSet)lift_subgraph_as_moduleF)is_backward_compatiblenodesreturnc                 L   t         j                  | d      }t        |       D ci c]  \  }}||
 }}}g }| D ]I  }|j                  D ]  }||v s||xx   dz  cc<    ||   dk(  s/t	        j
                  |||   |f       K g }|rst	        j                  |      \  }}|j                  |       |j                  D ]8  }||v s||xx   dz  cc<   ||   dk(  st	        j
                  |||   |f       : |rst        |       t        |      k7  rt        d      |S c c}}w )Nr      z@topological sorted nodes doesn't have same length as input nodes)dictfromkeys	enumerateall_input_nodesheapqheappushheappopappenduserslenAssertionError)	r   indegree_mapinodeposition
candidatesnsorted_nodes_s	            a/media/conek/DATA/Code/OCR/venv/lib/python3.12/site-packages/torch/fx/passes/utils/fuser_utils.py	topo_sortr$      sH   
 ==*L'0'78GAta8H8)+J ?%% 	(AL T"a'"	( "NN:'=>?  L
--
+4D! 	AAL Q1$?a'NN:Q/?@		A	  5zS&&N
 	
 5 9s   D 	partitionc                     t        |       g }D ])  }|j                  D ]  }|vs|j                  |        + dt        dt        ffd} ||      ryy)N
root_nodesr   c                     t               }| }|rP|j                         }|j                  |       |v ry|j                  D ]  }||v r|j	                  |        |rPy)NTF)setpopaddr   r   )r'   visitedqueuecurrent	user_nodepartition_sets        r#   bfs_find_cyclez*validate_partition.<locals>.bfs_find_cycleA   sn     5
 %iikGKK -' $]] (	'Y'(      FT)r)   r   r   r   bool)r%   outputsr   r/   r1   r0   s        @r#   validate_partitionr5   0   sl    
 	NMG * 	*I-y)	**8  4 gr2   always_return_tuplegmmodule_namepartition_lookup_tabler7   .c                   |D ]  }|j                   j                  | urt        | d| j                                |j                  rt        | d      || j                   j
                  vslt        | d| j                                 t        |      st        d      t        j                  |      t               i i dt        dt        ffd}|D ]  }j                  ||      }||<    i }|D ]   }|j                  D ]  }	|	vs|   ||<    " t        |j                               }
|rj                  |
       n$j                  t!        |
      dk(  r|
d	   n|
       j#                          t%        | d
|      \  }}t        j'                               }t        |j'                               }|||fS )a  
    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

        partition_lookup_table (Optional[Dict[Node, None]]): optional dict of nodes to speed up lookup

        always_return_tuple (bool): whether to always return a tuple, even if there is only one output

    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 cyclesxr   c                     | j                   dk(  r	 | v r|    S | vrPj                  | j                  | j                        }t	        j                  | j
                        |_        || <   |    S )Nget_attr)	type_expr)opplaceholdernametypecopymeta)r<   placeholder_nodenode_mapnode_to_placeholderr:   subgraphs     r#   remap_inputsz)fuse_as_graphmodule.<locals>.remap_inputs   s|    44: && A;'''33AFFaff3M$(IIaff$5!%5""1%%r2   r   r    )	comp_name
class_name)graphowning_moduler   	_get_name_erased_find_nodes_lookup_tabler5   r   r   r   r   	node_copyr   tuplevaluesoutputr   lintr
   keys)r8   r   r9   r:   r7   r   rJ   new_nodeoutput_mappingr/   outsfused_gmr"   original_inputsoriginal_outputsrG   rH   rI   s      `           @@@r#   fuse_as_graphmoduler_   a   s   D  
::##2- &B2<<>BRS  << D6)L!MNNrxx888 &6r||~6FG 
 e$IJJ %!%u!5wH 	  "$H& & & &*  "%%dL9!"
 (*N 6 	6I 66'/~t$	66 &&()D 	3t9>Qt< MMO)
H{KHa
 )..A.F.F.H(IO */~/B/B/D)E_&666r2   sub_gmorig_inputsorig_outputsinsertion_pointc                    |j                   j                  }| j                  ||       |9t        | j                  j
                        D ]
  }||v s|} n |t        d      | j                  j                  |      5  | j                  j                  ||d       }|j                  j                         }d d d        |rj                  }	| j                  j                  |	      5  t        |      dk(  r4t        j                  d   t              s|d   j!                  |d       nqt#        |      D ]D  \  }
}t$        j&                  j)                  |      |
   j*                  }|j!                  |d       F t        d |D              |j,                  d<   d d d        | S | S # 1 sw Y   xY w# 1 sw Y   | S xY w)	NzCannot determine insertion point: no insertion_point provided and orig_outputs is empty. Pass the last partition node as insertion_point.)argskwargsr   r   T)propagate_metac              3   T   K   | ]   }|j                   j                  d d       " yw)valN)rE   get).0orig_outputs     r#   	<genexpr>zinsert_subgm.<locals>.<genexpr>  s(      0:EK$$((50s   &(ri   )	__class____name__add_submodulereversedrN   r   r   inserting_aftercall_moduleoutput_nodenextinserting_beforer   
isinstancere   rT   replace_all_uses_withr   torchfxProxyr   rE   )r8   r`   ra   rb   rc   submodule_namer   module_nodert   	next_noder   rl   	proxy_outs                r#   insert_subgmr      s    %%..N^V, RXX^^, 	D|#"&	 " Z  
	!	!/	2 1hh**T + 
 ll..0	1 $$	XX&&y1 	< A%j9I9I!9Le.TQ55kRV5W&/&= VNA{ %{ ;A > C CI55iPT5UV
 +0 0IU0 +  '	 I2I/1 1	 Is   ?9F))B4F5)F25F?c                 Z    t        |      D ]  }| j                  j                  |        y N)rq   rN   
erase_node)r8   r   r   s      r#   erase_nodesr     s)      "
D!"r2   
partitionsprefixc           	      n   t        |      D ]Y  \  }}t        t        |            }|t        |      z   }t	        | ||||      \  }}	}
t        | ||	|
|d          t        | |       [ t        j                  j                  j                  j                  |        | j                  j                          | S )Nr6   )r   r$   liststrr_   r   r   ry   rz   passestools_commonstable_topological_sortrN   rW   )r8   r   r   r7   partition_idr%   r!   r|   r`   ra   rb   s              r#   fuse_by_partitionsr     s     $-Z#8 &i i1#l"33,? 3-
)\ 	RlL<LMB%&  
HHOO  88<HHMMOIr2   r   )fused_F)rD   r   torch.fxry   torch.fx._compatibilityr   torch.fx.graphr   torch.fx.graph_moduler   torch.fx.noder   torch.fx.passes.tools_commonr   r   r	   torch.fx.passes.utilsr
   r$   r3   r5   r   r   intrT   r_   r   r   r   r    r2   r#   <module>r      s      1   -  J J 9 e,X (  -D e,-( -t - --` e,
 =A	v7 !&v7v7v7 v7 !sTz!12T9	v7 v7 ;dCi(%c	*::;v7 -v7r e, $(/// tSy!/ c	"	/
 D[/ / -/d e,"K " "T " -" e,  %	T$d
*+,  	
  -r2   