U
    ©Ê¹j’(  ã                   @   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/bwave/python/venv/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	r˜tdƒ‚|	}qx|	jdkrÒ|j|	j|	jd�||	< t |	j¡||	 _qx|	jd	krÞqxt|	d
ƒsìt‚‡fdd„||	jƒ||	jƒ D ƒ}
||	j ‰ ˆ ˆ|	< tdd„ |
D ƒdd�}ˆ j|k�sFt‚‡ ‡‡‡fdd„}ˆ j	 |	|¡}|	j|_|ˆ|	< ˆ ˆ|< qx|dk�r’t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�rìt(||jt)| |j*ƒƒ �qìt 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"   
	
