o
    I&id                     @   s  d dl Z d dlZd dl mZ d dlmZmZmZmZmZ d dl	Z	d dl
m  mZ d dlm  mZ d dlmZ d dlmZmZmZmZ d dlmZ ddlmZ d	e	jd
e	jjdedefddZ G dd de	jjZ!dede!fddZ"de	jj#ddfddZ$dd Z%dededefddZ&de	jjde	jjfd d!Z'd"e	jjdefd#d$Z(d"e	jjde	jj)fd%d&Z*d"e	jjde	jj)fd'd(Z+G d)d* d*Z,d+e	jj#d,e	jjfd-d.Z-ded/eeef d0ee fd1d2Z.d3d4 Z/dS )5    N)deepcopy)castDictListOptionalUnion)ExportedProgram)ConstantArgumentModuleCallSignatureSymIntArgumentTensorArgument)GraphModule   )!_check_input_constraints_pre_hookfrom_obj	to_moduletargetis_parameterc                 C   s   | d^ }}|D ]}t||d }|d u r!tj }t||| |}q
t| tjs1tdt	| |r?|
|tj|  d S |||  d S )N.z)Expected only parameters or buffers, got:)splitgetattrtorchnnModulesetattr
isinstanceTensor
ValueErrortypeZregister_parameter	ParameterZregister_buffer)r   r   r   r   prefixfielditemt r$   BC:\wamp64\www\opt\env\Lib\site-packages\torch/_export/unflatten.py_assign_attr   s   
r&   c                       s.   e Zd Zdef fddZ fddZ  ZS )_UnflattenedModuleexport_modulec           	         s6  |j jd ur
tdt i tj d t|j	}t|j | _ t|j
| _
t|| j  t||  |j| _|j| _|j}| j jD ]}||  }t|| |dd q@| j jD ]}||  }t|| |dd qUi | j j| j j}t| |g  |  D ]}t|tjjsqz|j	jD ]}|jdkrq|j|vsJ qqzd S )Nz%Unflattening on JointExportModule NYIr'   T)r   Fplaceholder)graph_signatureZbackward_signaturer   super__init__r   fxGraphr   graphmodule_call_graph_inplace_buffer_mutations_outline_submodulesZrange_constraintsZequality_constraints
state_dict
parameterscloner&   buffersZinputs_to_parametersinputs_to_buffers_sink_paramsmodulesr   r   nodesopname)	selfr(   Zexport_graphr3   r<   Zclonedinputs_to_statemodulenode	__class__r$   r%   r,   1   sT   


z_UnflattenedModule.__init__c                    sp   t ||f\}}| jd jdksJ | jd j}||jkr+td| dd|j t j| }t 	||j
S )Nr    zInput treespec does not match with exported module's. Are you sure you are calling this with the right arguments? Input treespec: z. zExported module treespec: )pytreeZtree_flattenr0   fqn	signaturein_spec	TypeErrorr+   __call__tree_unflattenout_spec)r=   argskwargs	flat_argsrG   rF   Ztree_outrA   r$   r%   rI   `   s   

z_UnflattenedModule.__call__)__name__
__module____qualname__r   r,   rI   __classcell__r$   r$   rA   r%   r'   0   s    /r'   r?   returnc                 C   s   t | } | t | S )zvUnflatten an ExportedProgram, producing a module with the same module
    hierarchy as the original eager module.
    )r'   Zregister_forward_pre_hookr   )r?   r$   r$   r%   	unflattenq   s   
rT   r/   c              	      s*  t tt| j}|jdkrt|jdksJ |jd }|j}|dt| }dd |j	 D }dd | jD }|D ]I}||j
 }	||	 }
||
 }| |# | dtjjj||f |j	 D ]	\}}| j|< qaW d   n1 suw   Y  |  fd	d
 q;t|t|d }|f|_dS )a  Transform buffer mutations from their functionalized form into a copy_
    node in the graph.

    Functionalization represents buffer mutation by passing the buffer as an input and output. So for example, the eager code:
        def forward(self, x):
            self.buffer += x
            return x * x

    Will become a graph that looks like:
        def forward(self, buffer, x):
            mutated_buffer = aten.add(buffer, x)
            mul = aten.mul(x, x)
            return (mutated_buffer, mul)

    We want to inplace this into something that looks like the original eager code:
        def forward(self, buffer, x):
            mutated_buffer = aten.add(buffer, x)
            buffer.copy_(mutated_buffer)
            mul = aten.mul(x, x)
            return (mul,)
    outputr   r   Nc                 S   s   i | ]\}}||qS r$   r$   ).0kvr$   r$   r%   
<dictcomp>   s    z-_inplace_buffer_mutations.<locals>.<dictcomp>c                 S   s   i | ]}|j d kr|j|qS )r)   )r;   r<   )rV   r@   r$   r$   r%   rY      s    call_functionc                    s   |  uS Nr$   )xnew_noder$   r%   <lambda>   s    z+_inplace_buffer_mutations.<locals>.<lambda>)nextiterreversedr:   r;   lenrL   Zbuffers_to_mutater7   itemsr<   inserting_aftercreate_noder   opsZatenZcopy_metareplace_all_uses_withtuple)r/   r*   Zoutput_nodeZreturn_argsZmutation_node_to_bufferZ	mutationsZbuffers_to_inputsZinput_name_to_nodeZmutationZbuffer_nameZ
input_nameZ
input_noderW   rX   Zuser_outputsr$   r]   r%   r1   z   s4   

r1   c                 C   s$   t | t |k o|dt |  | kS )z2Check whether `candidate` is a prefix of `target`.N)rc   )	candidater   r$   r$   r%   	is_prefix   s   $rl   
parent_fqn	child_fqnc                 C   s`   | dkr|S |  d}| d}|d t| |ks%J d| d|  dd|t|d  S )NrC   r   zChild module 'z(' is not a descendant of parent module '')r   rc   join)rm   rn   Zparent_splitZchild_splitr$   r$   r%   compute_accessor   s   

rq   r\   yc                 C   s2   dt jjdtfdd}|| j||jksJ d S )Nr/   rS   c                    s   g }i  dt f fdd}t| jD ]E\}}dd t||jD }|dd t||j D 7 }|jdkr:|j	nd}|
| d	|j d
| dd| d | t|< qd|S )NrS   c                    s*   t | tjjrdt t|   S t| S )N%)r   r   r-   Nodestrid)argZ	nodes_idxr$   r%   arg_dump   s   z?_verify_graph_equivalence.<locals>.graph_dump.<locals>.arg_dumpc                 S   s   g | ]}t |qS r$   )ru   )rV   rw   r$   r$   r%   
<listcomp>       zA_verify_graph_equivalence.<locals>.graph_dump.<locals>.<listcomp>c                 S   s   g | ]\}}| d | qS )=r$   )rV   keyvaluer$   r$   r%   rz      s    rZ   rC   z: [z](z, )
)ru   	enumerater:   rD   Ztree_maprL   rM   rd   r;   r   appendrp   rv   )r/   retry   ir@   Z	args_dumpr   r$   rx   r%   
graph_dump   s   *
z-_verify_graph_equivalence.<locals>.graph_dump)r   r-   r.   ru   r/   )r\   rr   r   r$   r$   r%   _verify_graph_equivalence   s   r   gmc                 C   sF   d}t | d| r|d7 }t | d| s
d| }t| || |S )Nr   Z_spec_r   )hasattrr   )r   specr   r<   r$   r$   r%   	_add_spec   s   
r   c                 C   *   t | |}| j|}| jtj||fS r[   )r   r/   get_attrrZ   	fx_pytreeZtree_flatten_spec)r   r@   r   r<   	spec_noder$   r$   r%   _generate_flatten      
r   c                 C   r   r[   )r   r/   r   rZ   rD   rJ   )r   r:   r   r<   r   r$   r$   r%   _generate_unflatten   r   r   c                   @   s^   e Zd Z	ddeeef fddZdd Zdd Zd	d
 Z	dd Z
dd Zdd Zdd ZdS )ModuleFrameNr0   c	              	      s  |_ |_|_|_|_|_|_d_jd _|d ur&|_	nt
ji t
j j_	|jj	jd< jjv rKjj _n
d _j	jj< tj j_j	j_i _i _d _|d urt|jj}	|j	|	jd u rj	nj |j|	_|j}
|
d urjd urt|
jjdksJ |
jjd }|
jjd }|jd u sJ |jd usJ j	jd  g }tt|jD ]}| j	j!d|  qi }|jD ]}j	j!|||< qt"j	t#||f|
j}t$|
j%D ];\}}j	jj&dt'j(||ft)|t*s|j+nd	| d
}t)|t*r*qt,,j|j+ j|_|jj|j+ < qW d    n	1 sKw   Y  jj-jt g }|
j%D ]-}t)|t*rs|j.d u rs| d  q^t)|t/t0fs}J | j1j|j+  q^t2jj	||
j}jj3t'j(|df jj3t'j(|df fddtt|jD }fdd|jD }W d    n	1 sw   Y  jd usJ t#|j_4|j_5d S d S d S )NFZmodule_call_signature   r   r   Z_positional_arg_rZ   Z
_constant_)r;   r   rL   r<   c                    s"   g | ]}j jtj |fqS r$   parentr/   rZ   operatorgetitem)rV   r   )	args_noder=   r$   r%   rz   n  s    z(ModuleFrame.__init__.<locals>.<listcomp>c                    s$   i | ]}|j jtj |fqS r$   r   )rV   rW   )kwargs_noder=   r$   r%   rY   r  s    

z(ModuleFrame.__init__.<locals>.<dictcomp>)6
flat_graph
seen_nodesseen_modulesr   module_stack	module_idr0   verboserE   graph_moduler   r-   r   r.   getrh   cached_graph_modulelistr:   r/   node_mapnode_to_placeholderparent_call_modulerq   Zadd_submodulecall_modulerc   rG   Zchildren_specscontextre   ranger   r)   r   rj   r   inputsrf   r   r   r   r	   r<   copyinserting_beforer~   r   r   remap_inputr   rZ   rL   rM   )r=   r   r   r   r   r   r   r0   r   accessorrF   Z	args_specZkwargs_specZ	arg_nodesidxZkwarg_nodesr<   rN   rw   Zflat_arg_noder:   inputZinputs_noder$   )r   r   r=   r%   r,      s   







!zModuleFrame.__init__c                 C   sl   |j | ju sJ | j d  | j j|j|jd}W d    n1 s#w   Y  t|j|_|| j|< d S )N)Z	type_expr)	r/   r   r   r)   r<   r   r   rh   r   )r=   r\   Zplaceholder_noder$   r$   r%   add_placeholder|  s   zModuleFrame.add_placeholderc                 C   sb   |j | ju sJ || jv r| j| S || jvr,| | | jd ur,| jd| j| | j| S )Nr   )	r/   r   r   r   r   r   Z
insert_argr   r   )r=   r\   r$   r$   r%   r     s   





zModuleFrame.remap_inputc                    s  g } j  j}|d urM jd urM|jD ]}t|ttfr(| j	|j
  qtd| t jt fdd|D |j}t jj j|j}|}n2g } j D ]}|jD ]}|j
 j	vrp|| | j|   nqYqT j}t|dkr|d }t|ttjjfsJ  j|  j   j  |d u rd S t|dkr|d u r| jj|d < nt|D ]\}	}
tj||	 j }| jj|
< q j!d urt" j! j d S d S )Nz'Unsupported data type for output node: c                 3   s"    | ]} j  j|j  V  qd S r[   )r   r   r<   )rV   rU   r=   r$   r%   	<genexpr>  s
    
z/ModuleFrame.finalize_outputs.<locals>.<genexpr>r   r   )#r0   r   rE   r   Zoutputsr   r   r   r   r   r<   RuntimeErrorr   r   rj   rK   r   r   r   keysusersrc   r   r   r-   rt   r/   rU   Zlint	recompiler   ZProxyr@   r   r   )r=   Zorig_outputsrF   rU   Ztree_out_nodeZ
parent_outZgraph_outputsZ	orig_nodeZ	user_noder   Zorig_outputZ	proxy_outr$   r   r%   finalize_outputs  s\   





zModuleFrame.finalize_outputsc                 C   s6   |  d|  | j|| j| j|< || j|j< d S )NZcopying)printformat_noder/   Z	node_copyr   r   r   r<   )r=   r@   r$   r$   r%   	copy_node  s   zModuleFrame.copy_nodec                 C   s   d}| j jD ]}| ||jd|  |d7 }qd}| j| }|jdkr9| | |d7 }| j| }|jdks&| | | j jD ]}|jdkrN| | qBd S )Nr   nn_module_stackr   r)   rU   )	r   r:   r   rh   r   r   r;   r   run_from)r=   r   r@   node_idxr$   r$   r%   	run_outer  s"   








zModuleFrame.run_outerc                 O   s   | j rt|i | d S d S r[   )r   r   )r=   rL   rM   r$   r$   r%   r     s   zModuleFrame.printc              	   C   s  d}|t | jk r| j| }|jdksJ |   | d||  | | j |jdkr<t | jdkr6|S |   |S d|jv rMdd |jd  D n| j}|d t | j | jkro|   | d	| j	 | | j
 |S |d usuJ t| j|r|t | j }| d
| t| j| j| j| | j|g t|jd  t | j | j|}|d7 }q|| jksJ | | |d7 }|t | jk s	d S d S )Nr   r)   ZSTEPrU   r   r   c                 S   s   g | ]\}}|qS r$   r$   )rV   pathtyr$   r$   r%   rz     r{   z(ModuleFrame.run_from.<locals>.<listcomp>Z	outliningzCreating new stack frame for)rc   r:   r;   r   r   r   r   rh   valuesrE   r/   rl   r   r   r   r   r   r   r0   r   r   )r=   r   Z
module_idxr@   Znode_module_stackZnext_moduler$   r$   r%   r     sT   



	
zModuleFrame.run_fromr[   )rO   rP   rQ   r   ru   r
   r,   r   r   r   r   r   r   r   r$   r$   r$   r%   r      s    


 

?r   
orig_graphroot_modulec              
   C   s6   i }i }t | ||d dgddd |jD |d  d S )NrC   c                 S   s   i | ]
}|j r|j|j qS r$   )rF   rE   )rV   entryr$   r$   r%   rY   :  s    z'_outline_submodules.<locals>.<dictcomp>)r   )r   r0   r   )r   r   r   r   r$   r$   r%   r2   0  s   
r2   r>   scopec              	      sX  | j  D ]\}}ttt| ||g  qt| tsdS | j}tdd |j}tdd |j}|D ]}t	t fdd|j
|_
q2|D ]a}|j vrLqDt|jdkr |j d}	|	dt| |krfqD|	t|d }
t| |
}t|tjs{J || |dd|
}W d   n1 sw   Y  |j|d	d
 || qD|   dS )aH  Sink params and buffers from graph inputs into get_attr nodes.

    Exported modules are purely functional, so they pass their parameters and
    buffers in as inputs to the graph.

    To replicate eager's semantics, we need to get them from the module state
    via get_attr instead.

    module: GraphModule, potentially containining nested submodules.
    inputs_to_state: mapping graph input names to the corresponding key in the state_dict.
    scope: tracks where we are in the module hierarchy, so that we can emit the
        right `getattr(self, "foo.bar")` calls, etc.
    Nc                 S   
   | j dkS )Nr)   r;   nr$   r$   r%   r_   \     
 z_sink_params.<locals>.<lambda>c                 S   r   )Nr   r   r   r$   r$   r%   r_   _  r   c                    s
   | j  vS r[   )r<   r   r>   r$   r%   r_   a  r   r   r   r   T)Zpropagate_meta)Z_modulesrd   r8   r   r   r   r/   filterr:   rj   rL   r<   rc   r   r   _recursive_getattrr   r   re   rf   rp   ri   Z
erase_noder   )r?   r>   r   r<   	submoduler/   r   Zcall_module_nodesr@   Z
state_name	attr_pathZ
state_attrr^   r$   r   r%   r8   C  s2   


r8   c                 C   s   |D ]}t | |} q| S r[   )r   )objr   attrr$   r$   r%   r   ~  s   r   )0r   r   r   typingr   r   r   r   r   r   Ztorch.fx._pytreer-   Z_pytreer   Ztorch.utils._pytreeutilsrD   Ztorch.exportr   Ztorch.export.exported_programr	   r
   r   r   Ztorch.fxr   r   r   r   r   ru   boolr&   r'   rT   r.   r1   rl   rq   r   r   rt   r   r   r   r2   r8   r   r$   r$   r$   r%   <module>   sR    
A	8	  @

;