o
    "i[                     @   sD  d dl Z d dlZd dlZd dlZ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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mZ d dlmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z& ej'd	ej(d
ej)dej*dej+dej,diZ-deej.j/ fddZ0		dIddddddee dee dee& dee1 dee$ dee de2ddfddZ3dedej.j/de2fd d!Z4dedej.j/deej5j fd"d#Z6dedej.j/de2fd$d%Z7dedej.j/deej8 fd&d'Z9dedej.j/de2fd(d)Z:dedej.j/deej8 fd*d+Z;d,ej.j<dej.j<fd-d.Z=d/eej.j/ deej.j/ fd0d1Z>	dJd/eej.j/ deej.j/ fd2d3Z?d/eej.j/ de@fd4d5ZAd/eej.j/ deej.j/ fd6d7ZB	dKd8ej.j/d9ej.j/d:e2ddfd;d<ZCd=ej.j/ddfd>d?ZDd@ej5jEfdAdBZFdCdD ZGd,ej.j<dEejHjId@ej5jEdFe	e1ef ddf
dGdHZJdS )L    N)	Parameter)AnyDictIterableListOptionalTupleType)
FakeTensor)ExportedProgram)_name_hoo_subgraph_placeholders_rename_without_collisions)	InputKind
OutputKind)_register_pytree_nodeContextFlattenFuncFromDumpableContextFn
GetAttrKeyKeyPathkeystr
MappingKeySequenceKeyToDumpableContextFntree_flatten_with_pathUnflattenFunc p_b_c_obj_tokeninput_placeholdersc                 C   s(  dt dtfdd}dd l}ddlm} ddlm} t|t| kr0tdt|  d	t| d
i }t	|| D ]Y\\}}	}
|
j
d}t|trkt|	tjs^td|| dt|	 t|jt|	jkrztd|| d|j d	|	j d
tt	|	j|jD ]\}\}}t|tjrJt|jjjdkrJtt|jjj}||v r|jj|}||krtd|| d| d| d| n:t|tjr|jjjsn.|||jj||}|d u rtd|
j d| d| d|jj d| dt|d ||< |jj|v rI|||jj \}}|dkr,||k r,td|| d| d| d| |tjk rI||krItd|| d| d| d| q||krit|tjrWqtd|| d| d| d| qq7t|tt tfrt|	t|ks|	|krtd|| d| d|	 q7d S )Nkey_pathreturnc                 S   st   | d }t |tsJ |jdkrdt| dd  S | d }t |ts&J t|dd }| t| dd  S )zFor a given index into the flat_args, return a human readable string
        describing how to access it, e.g. "*args["foo"][0].bar"
        r   z*args   N   )
isinstancer   idxr   r   str)r#   args_kwargs_key_path	kwarg_keyname r.   Q/home/ubuntu/SoloSpeech/.venv/lib/python3.10/site-packages/torch/_export/utils.py
get_keystr1   s   
z6_check_input_constraints_for_graph.<locals>.get_keystrr   )_convert_range_to_int)	try_solvez&Unexpected number of inputs (expected z, got )valzExpected input at z to be a tensor, but got z,Unexpected number of dimensions in input at z.shape (expected r%   z.shape[z] to be equal to z
, but got zExpected input z] = z to be of the form z, where z is an integerr'   z] to be >= z] to be <= z to be equal to )!r   r*   sympy@torch._export.passes.add_runtime_assertions_for_constraints_passr1   torch.utils._sympy.solver2   lenRuntimeErrorzipmetagetr(   r
   torchTensortypeshape	enumerateSymIntnodeexprfree_symbolsnextitersubs	is_numberEqr-   intmathinffloat)r"   flat_args_with_pathrange_constraintsr0   r5   r1   r2   unification_mapr#   argrC   node_valjarg_dimnode_dimsymbolexisting_dimsolutionmin_valmax_valr.   r.   r/   "_check_input_constraints_for_graph.   s   






?r\   F)serialized_type_nameto_dumpable_contextfrom_dumpable_contextreturn_none_fieldscls
flatten_fnunflatten_fnr]   r^   r_   r`   r$   c          
   	      s   t  sJ d  dtdttt tf ffdd}dtt dtdtf fdd	}dtdttt tf ffd
d}	d urCn||d urK|n|}|d u |d u A r]td  dt |||	||d d S )Nz7Only dataclasses can be registered with this function: objr$   c                    sh   g }g }g }t | D ]"}|jt| |j}}|d us r(|| || q|| q|||gfS N)dataclassesfieldsr-   getattrappend)rd   	flattened
flat_names
none_namesfr-   r4   )r`   r.   r/   default_flatten_fn   s   
z=register_dataclass_as_pytree_node.<locals>.default_flatten_fnvaluescontextc                    s*   |\}} di t t|| t |S )Nr.   )dictr:   fromkeys)ro   rp   rk   rl   )ra   r.   r/   default_unflatten_fn   s   "z?register_dataclass_as_pytree_node.<locals>.default_unflatten_fnc                    s(    | \}\}}dd t ||D |fS )Nc                 S   s   g | ]
\}}t ||fqS r.   )r   ).0kvr.   r.   r/   
<listcomp>   s    z[register_dataclass_as_pytree_node.<locals>.default_flatten_fn_with_keys.<locals>.<listcomp>)r:   )rd   rj   rk   rl   )rb   r.   r/   default_flatten_fn_with_keys   s   zGregister_dataclass_as_pytree_node.<locals>.default_flatten_fn_with_keysz7Both to_dumpable_context and from_dumpable_context for z must be None or registered.)r]   flatten_with_keys_fnr^   r_   )	rf   is_dataclassr   r   r   r   r   
ValueErrorr   )
ra   rb   rc   r]   r^   r_   r`   rn   rs   rx   r.   )ra   rb   r`   r/   !register_dataclass_as_pytree_node   s.   
""

r|   programrC   c                 C      |j | jjv S )zM
    Checks if the given node is a parameter within the exported program
    )r-   graph_signatureinputs_to_parametersr}   rC   r.   r.   r/   is_param      r   c                 C   &   t | |r| jj|j }| j| S dS )z
    Returns the parameter associated with the given node in the exported program.
    Returns None if the node is not a parameter within the exported program
    N)r   r   r   r-   
state_dict)r}   rC   parameter_namer.   r.   r/   	get_param   s   
	
r   c                 C   r~   )zJ
    Checks if the given node is a buffer within the exported program
    )r-   r   inputs_to_buffersr   r.   r.   r/   	is_buffer   r   r   c                 C   s<   t | |r| jj|j }|| jjv r| j| S | j| S dS )z
    Returns the buffer associated with the given node in the exported program.
    Returns None if the node is not a buffer within the exported program
    N)r   r   r   r-   non_persistent_buffers	constantsr   )r}   rC   buffer_namer.   r.   r/   
get_buffer   s   
	

r   c                 C   r~   )zZ
    Checks if the given node is a lifted tensor constant within the exported program
    )r-   r   !inputs_to_lifted_tensor_constantsr   r.   r.   r/   is_lifted_tensor_constant  s   r   c                 C   r   )z
    Returns the lifted tensor constant associated with the given node in the exported program.
    Returns None if the node is not a lifted tensor constant within the exported program
    N)r   r   r   r-   r   )r}   rC   lifted_tensor_namer.   r.   r/   get_lifted_tensor_constant  s   
	
r   gmc                    sl   ddl m} i  d}| jjD ]}||r|d7 }| |< q|| |  fddddd}| jj|j_|  |S )z
    Splits the graph module into multiple submodules based on the node_call_back.
    The node_call_back should return True if the node is a delimiter. Delimiter will be
    the first node in the next submodule.
    r   )split_moduler%   c                    s    |  S re   r.   rC   	split_mapr.   r/   <lambda>?  s    z"sequential_split.<locals>.<lambda>T)keep_original_orderkeep_original_node_name)torch.fx.passes.split_moduler   graphnodes_codegen	recompile)r   node_call_backr   split_idrC   new_gmr.   r   r/   sequential_split-  s"   

r   r   c                    s    fdd| D S )z:Returns the nodes that match the node_call_back as a list.c                    s   g | ]} |r|qS r.   r.   rt   rC   r   r.   r/   rw   K  s    z nodes_filter.<locals>.<listcomp>r.   r   r   r.   r   r/   nodes_filterI  s   r   c                 C   s.   t | |r|ndd }t|dkr|d S dS )z
    Returns the first node that matches the node_call_back. If no node matches, returns None.
    When node_call_back is None, returns the first node in the node list.
    c                 S   s   dS )NTr.   r   r.   r.   r/   r   U  s    znodes_first.<locals>.<lambda>r   N)r   r8   )r   r   retr.   r.   r/   nodes_firstN  s   r   c                 C   s   t t| |S )z:Returns the number of nodes that match the node_call_back.)r8   r   r   r.   r.   r/   nodes_count[  s   r   c                 C   s   | D ]}|| q| S )z
    Sequentially visit the nodes list and invoke node_call_back on each element.
    Returns the nodes list after the node_call_back is invoked on each element.
    r.   )r   r   rC   r.   r.   r/   	nodes_map`  s   
r   old_nodenew_node
delete_oldc                 C   s,   |  | |r| j  | j|  dS dS )z5
    Replace all uses of old_node with new_node.
    N)replace_all_uses_withusersclearr   
erase_node)r   r   r   r.   r.   r/   node_replace_j  s
   

r   call_mod_nodec                    s  | j dksJ | jj}t| jtsJ t|| j}dd |jjD }dd |jjD }dd |jjD }t|| j	D ]\}}t|t
jjsGJ t||dd q:|j| z |D ]}|j|}	t||	dd qXt|d	krt|d
kr}t|d	 j	d
ksJ |d	 j	d	  t t
jjrt|  dd n3t ttfrtt| j dd }
t|
 fdd | j|  ntdt  d| j|  W d   n1 sw   Y  |  |  |S )z
    Inline the submodule of the given node into the parent module.
    Note: we only support the case where submodule takes tensors inputs.
    call_modulec                 s   s    | ]
}|j d kr|V  qdS )placeholderNopr   r.   r.   r/   	<genexpr>  s    znode_inline_.<locals>.<genexpr>c                 s   s    | ]
}|j d vr|V  qdS ))r   outputNr   r   r.   r.   r/   r     s    c                 S   s   g | ]	}|j d kr|qS )r   r   r   r.   r.   r/   rw     s    z node_inline_.<locals>.<listcomp>Tr   r   r%   c                 S   s   | j dko
| jtjkS )Ncall_function)r   targetoperatorgetitemr   r.   r.   r/   r     s   
 znode_inline_.<locals>.<lambda>c                    s   t |  | jd  ddS )Nr%   Tr   )r   args)get_item_node
new_outputr.   r/   r     s
    zUnsupported output type z2. Expect it to be a Node or a list/tuple of Nodes.N)r   r   owning_moduler(   r   r*   rh   r   r:   r   r=   fxNoder   inserting_before	node_copyr8   listtupler   r   keysr   r   NotImplementedErrorr?   delete_all_unused_submodulesr   )r   r   sub_gmphsbodyr   phrR   rC   r   get_item_usersr.   r   r/   node_inline_v  sP   "
#r   modc           	      C   s~   t | j}|jd }dtji}g }| D ]"\}}dd t|j|D }|D ]}|dkr.q'|	t
|| q'qt
j|dS )z
    Get source code and parse argument names using AST. The function returns
    a signature of the forward() function.

    # TODO: Directly provide inspect.signature compatible TS-d module.
    r   r   c                 S   s   g | ]}|j qS r.   )rR   )rt   ar.   r.   r/   rw     s    z:_get_torch_jit_trace_forward_signature.<locals>.<listcomp>self)
parameters)astparsecoder   r   POSITIONAL_OR_KEYWORDitemsrh   r   ri   inspect	Signature)	r   ast_modast_func_defarg_type_map
param_listarg_type
param_typearg_name_listarg_namer.   r.   r/   &_get_torch_jit_trace_forward_signature  s   

r   c                 C   s`   t | tjjtjjfr!t| }t|jt|t| ks J dnt	| j
}|j|i |jS )NzyArguments other than POSITIONAL_OR_KEYWORD kinds in forward() are not supported in _get_torch_jit_trace_forward_signature)r(   r=   jitScriptModuleTracedModuler   r8   r   r   	signatureforwardbind	arguments)r   	fake_argsfake_kwargssigr.   r.   r/   _bind_signature_to_inputs  s   r   export_graph_signaturer   c              
      s  dd }dd  i }t |||}	t|	\}
}dd |jD }t|
|D ]\\}}}|rBt||ttj d fdd	|D  d
d q#|jD ]/}|j	tjkrOqF|j	tj
krXd}n||j }tdd|}t||jjt|j	 | d
d qF| jjD ]}|jdkrqzt||j|j qz| jjD ]#}|jdkr|j|v sJ ||j  |_|_q|j|v r||j |_qt|  |   |jD ]'}|jj|v sJ ||jj |j_|j	tjkr|j|v r||j dd |_q|jD ]#}|jj|v r||jj |j_|j	tjkr|j|v r||j |_qt| D ]4}|| }||v rFt|tjsF|| }||krFtd|rF|ttj | krF|||< ||= qdS )aQ  
    This pass is run at the end of _export_non_strict() to assign better placeholder node names:
        - User inputs:
            These follow the signature of mod.forward(), e.g. forward(x, y) produces nodes x, y.
            For nested inputs from dictionaries, lists, tuples, or dataclasses,
            the names are a concatenation of the path to the tensor.
                e.g. x = {
                    'a': torch.randn(),
                    'b': [torch.randn(), torch.randn()]
                }
            produces nodes x_a, x_b_0, x_b_1.
        - Parameters/buffers/constants/custom objects:
            These follow the FQN of the object, prefixed by "p", "b", "c", "obj" respectively.
                e.g. self.bar.l0.weight produces "p_bar_l0_weight".
        - Effect tokens:
            These are named token, token_1, ...
    c                 S   s,   |  dr| tdd  } tdd| } | S )N
L__self___[^a-zA-Z0-9]_)
startswithr8   resubxr.   r.   r/   _strip_name  s   
z,placeholder_naming_pass.<locals>._strip_namec                 S   s^   t | trtddt| j} | S t | trt| jS t | tr#| j	S t
dt|  d|  )Nr   r   zPytree key of type z not handled for )r(   r   r   r   r*   keyr   r)   r   r-   r9   r?   r   r.   r.   r/   _extract_pytree_key  s   



z4placeholder_naming_pass.<locals>._extract_pytree_keyc                 S   s    g | ]}|j tjkr|jjqS r.   )kindr   
USER_INPUTrR   r-   )rt   specr.   r.   r/   rw     s
    z+placeholder_naming_pass.<locals>.<listcomp>r   c                 3   s    | ]	} |  V  qd S re   )lower)rt   r   r   r.   r/   r     s    z*placeholder_naming_pass.<locals>.<genexpr>T)is_placeholderr   r   r      Nz
arg(\d+)_1) r   r   input_specsr:   r   placeholder_prefixesr   r   joinr   TOKENr   r  r   r   rR   r-   r   r   r   r   r   
CUSTOM_OBJoutput_specsr   USER_INPUT_MUTATIONr   r   r(   r=   r>   match)r   r   r   r   r   fake_params_buffersr   r   name_mapcombined_argsrO   r   user_input_namesarg_pathrR   user_input_namer   	base_namerC   r-   constantnew_namer.   r  r/   placeholder_naming_pass  s   








r  )NNre   )F)Kr   rf   r   rL   r   r   r   typingr   r   r   r   r   r   r	   r=   torch._subclasses.fake_tensorr
   torch.exportr   torch.export.exported_programr   r   torch.export.graph_signaturer   r   torch.utils._pytreer   r   r   r   r   r   r   r   r   r   r   r   r   	PARAMETERBUFFERCONSTANT_TENSORr	  r  r  r   r   r\   r*   boolr|   r   nnr   r   r>   r   r   r   GraphModuler   r   r   rK   r   r   r   r   Moduler   r   exportExportGraphSignaturer  r.   r.   r.   r/   <module>   s   $8


z	
7




"


"
=
