U
    9%e(                     @   s   d dl Z d dlmZ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mZ ddlmZ d	d
ddgZedddd	 Zedddd
 ZeddeG dd dZedde	jjee e	jjdddZdS )    N)	dataclassfield)DictListOptional)compatibility)map_arg)HolderModulelift_subgraph_as_module   )NodeListgetattr_recursivesetattr_recursive	Componentsplit_by_tagsF)Zis_backward_compatiblec                 C   s0   | dD ] }t| |r$t| |} q
 d S q
| S )N.)splithasattrgetattr)objnamelayer r   Z/var/www/html/Darija-Ai-API/env/lib/python3.8/site-packages/torch/fx/passes/split_utils.pyr      s
    
c                 C   sH   d|krt | || n.|d}tt| |d d|dd  | d S )Nr   r   r   )setattrr   r   r   join)r   attrvaluer   r   r   r   r      s    
c                   @   s   e Zd ZU dZejjed< eed< e	ed< e
edZeed< e
edZeed< e
edZeed< e
edZeejjejjf ed	< e
edZee	 ed
< dZeejj ed< dS )r   zX
    A component serves as a container for a subgraph we want to create afterwards.
    graphorderr   )default_factoryinput_placeholdersorig_inputsorig_outputsgetattr_mapsconstructor_argsNgm)__name__
__module____qualname____doc__torchfxGraph__annotations__intstrr   listr!   r   r"   r#   dictr$   r   Noder%   r&   r   GraphModuler   r   r   r   r   !   s   
")r&   tagsreturnc                    s$  t jjjtddd}i i i }g }i t j }i }d}|D ].}tt j t||  |   ||< q@| j	j
D ]}	|	jdkr|dk	rtd|	}qx|	jdkr|j|	j|	jd||	< t|	j||	 _qx|	jd	krqxt|	d
stfdd||	j||	j D }
||	j   |	< tdd |
D dd} j|ksFt fdd} j	|	|}|	j|_||	<  |< qx|dkrtd||jd D ]2}|jd	kr|j|j|jd||< nd|< qD ]"}|jdkr؈| j| q|D ] ttj j} j	t|dkr2|d n| t |  j	 _!|j" jtt|j j#dd}t|dkr|| jd < n,t$ jD ] \}}t j%|| j||< qq |t&|jd |j t'dd |D }||jd D ](}|jd	krt(||jt)| |j* qt j+||S )a~  
    Splits a GraphModule using tags on its graph nodes. We honor the order of
    tags. For example, we have tags = ["a", "b", "c"], the function will create
    the initial submodules in the order of "a_0", "b_1", "c_2".

    To set a tag:
    gm.graph.nodes[idx].tag = "mytag"

    This will result in all nodes with the same tag being extracted and placed in their
    own submodule. For placeholder, output and get_attr node, the tag is ignored. placeholder
    and output nodes are created when needed while get_attr nodes get copied to submodules
    where they are used.

    Given the following module def:

    class SimpleModule(torch.nn.Module):
        def __init__(self):
            super().__init__()
            self.linear1 = torch.nn.Linear(...)
            self.linear2 = torch.nn.Linear(...)
            self.linear3 = torch.nn.Linear(...)

        def forward(self, in1, in2):
            r1 = self.linear1(in1)
            r2 = self.linear2(in2)
            r3 = torch.cat([r1, r2])
            return self.linear3(r3)

    Marking the node corresponding to in1 with the tag sc.REQUEST_ONLY.lower() results in the following split:

    ro_0:
    def forward(self, in1):
        self = self.root
        linear1 = self.linear1(in1)
        return linear1

    main_1:
    def forward(self, in2, linear1):
        self = self.root
        linear2 = self.linear2(in2)
        cat_1 = torch.cat([linear1, linear2])
        linear3 = self.linear3(cat_1)
        return linear3

    main_0:
    def forward(self, in1, in2):
        self = self.root
        ro_0 = self.ro_0(in1)
        main_1 = self.main_1(in2, ro_0)
        return main_1
    )xr6   c                 S   s   g }t | |j |S )zC
        Stores nodes in x to a list and returns the list.
        )r   append)r7   rr   r   r   flattenq   s    zsplit_by_tags.<locals>.flattenNoutputzMultiple output nodes in graph!placeholderZ	type_exprget_attrtagc                    s   g | ]}|j d kr | qS )>   r<   r>   )op).0r7   )node_to_componentr   r   
<listcomp>   s   
z!split_by_tags.<locals>.<listcomp>c                 s   s   | ]}|j V  qd S )N)r   )rA   cr   r   r   	<genexpr>   s     z split_by_tags.<locals>.<genexpr>r   )defaultc                    s   | j dkr8|  jkr. jj| j| jd j| <  j|  S | j dkrV|   krV|  S |  jkr j|   jj| j	| jd}t

| j|_ j| d | <  j j|  S )Nr>   r=   r<   )r@   r$   r   r>   targettyper"   r8   r<   r   copymetar!   index)r7   r<   compZnode_remappingrB   Zused_in_mainr   r   
remap_func   s$    

 

z!split_by_tags.<locals>.remap_funczGraph had no output node!r   )argskwargsc                 S   s   i | ]}|j |jqS r   )r   r&   )rA   rM   r   r   r   
<dictcomp>  s      z!split_by_tags.<locals>.<dictcomp>),r+   r,   nodeZArgumentr   r-   r   lenr8   r   Znodesr@   RuntimeErrorr<   r   rH   rI   rJ   r   AssertionErrorrO   rP   r?   maxr   Z	node_copyr>   r#   tuplemap__getitem__r;   r
   r&   Zcall_moduler"   	enumerateZProxyr   r	   r   r   rG   r4   )r&   r5   r:   Ztag_to_componentZall_componentsZmain_gZmain_remappingZoutput_noder?   rR   Zupstream_componentsZmxrN   nr7   ZoutsZ	main_nodeioZ	main_rootr   rL   r   r   ;   s    6	









")rI   dataclassesr   r   typingr   r   r   Ztorch.fxr+   Ztorch.fx._compatibilityr   Ztorch.fx.graphr   Ztorch.fx.passes.utilsr	   r
   Ztools_commonr   __all__r   r   r   r,   r4   r0   r   r   r   r   r   <module>   s"   
	
