a
    h                     @   s   d dl Z d dlmZmZmZ d dlZd dlmZmZ e	edf Z
eeeef ge	edf f Zg dZeedddZejjeeef d	d
dZee eeef dddZeedddZdS )    N)AnyCallableUnion)tree_flatten_with_pathtree_map.)normalize_source_namemodule_to_nested_dicttrack_dynamism_across_examplesclone_and_convert_to_meta)namereturnc                 C   s   t dd| S )Nz\.([a-zA-Z_][a-zA-Z0-9_]*)z['\1'])resub)r    r   M/var/www/auris/lib/python3.9/site-packages/torch/fx/experimental/_dynamism.pyr      s    r   )moduler   c              	   C   s   i }i |d< i |d< t | D ]v}zZ|dsxtt| |sxt| |}t|tjjsxt|tt	tj
frxt|turx|||< W q ty   Y qY q0 q| jddD ]\}}||d |< q| jddD ]\}}||d |< q|  D ]\}}t||d |< q|S )ziRecursively converts an nn.Module into a nested dictionary with explicit 'parameters' and 'modules' keys._parametersZ_modules_F)Zrecurse)dir
startswithcallablegetattr
isinstancetorchnnModuleintfloatTensortypeboolNotImplementedErrorZnamed_parametersZnamed_buffersZnamed_childrenr   )r   Z	self_dict	attr_name
attr_valuer   parambuffer	submoduler   r   r   r      s2    

r   )example_inputsr   c                 C   s  i }| D ]}d|v r8t |d tjjr8t|d |d< t|\}}|D ]\}}t |tttjfsdqHt |tjrt	|j
}d}n
|f}d}||vrdd tt|D |f||< n2|| \}	}
|
|krt|	t|k r|	t  qt|D ]\}}|| d | | qqHqi }| D ]`\}\}	}t	dd |	D }d	d
dd |D  }|d j}||vrni ||< ||| |< q|S )a  
    This function analyzes a list of example inputs to determine the dynamism of their shapes.
    It tracks whether the dimensions of tensors or non-tensor values change across
    different examples. The function returns a dictionary where each key represents
    a path to a value in the input examples, and the corresponding value is a tuple
    indicating which dimensions are dynamic (i.e., change across examples). This
    helps in understanding how the structure of data varies across different instances.
    selfTFc                 S   s   g | ]
}t  qS r   )set).0r   r   r   r   
<listcomp>V       z2track_dynamism_across_examples.<locals>.<listcomp>r   c                 s   s   | ]}t |d kV  qdS )   N)len)r*   sr   r   r   	<genexpr>b   r,   z1track_dynamism_across_examples.<locals>.<genexpr>L c                 s   s   | ]}t | V  qd S )N)str)r*   kr   r   r   r0   c   r,   )r   r   r   r   r   r   r   r   r   tupleshaperanger.   appendr)   	enumerateadditemsjoinkey)r'   ZtrackingexZleaves_with_pathsr   Zkey_pathvaluer6   Z	is_tensorZdim_setsflagiZdimoutputZ
_is_tensorZ	final_dynZkey_strr=   r   r   r   r	   ;   s<    

 

r	   )example_inputr   c                 C   s   t t ddd}t|| S )z
    This function takes a list of example inputs and for each tensor, clones it and converts it to device=meta.
    For non-tensor values, it keeps the reference. It uses pytree to handle nested structures recursively.
    )r?   r   c                 S   s    t | tjr|  jddS | S )Nmeta)Zdevice)r   r   r   cloneto)r?   r   r   r   transform_fnq   s    z/clone_and_convert_to_meta.<locals>.transform_fn)r   r   )rC   rG   r   r   r   r
   k   s    r
   )r   typingr   r   r   r   Ztorch.utils._pytreer   r   r5   ZKeyPathr   r   ZNonTensorShapeFn__all__r3   r   r   r   dictr   listr	   r
   r   r   r   r   <module>   s   $
0