o
    Zh                     @   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dedefdd	Zd
ejjdeeef fddZdee deeef fddZdedef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   N/var/www/auris/lib/python3.10/site-packages/torch/fx/experimental/_dynamism.pyr      s   r   modulec                 C   s   i }i |d< i |d< t | D ]-}|ds;tt| |s;t| |}t|tjjs;t|tt	tj
fr;t|tur;|||< q| jddD ]
\}}||d |< qB| jddD ]
\}}||d |< qS|  D ]\}}t||d |< qb|S )ziRecursively converts an nn.Module into a nested dictionary with explicit 'parameters' and 'modules' keys._parametersZ_modules_F)recurse)dir
startswithcallablegetattr
isinstancetorchnnModuleintfloatTensortypeboolZnamed_parametersZnamed_buffersZnamed_childrenr   )r   Z	self_dictZ	attr_nameZ
attr_valuer   parambuffer	submoduler   r   r   r      s(   
r   example_inputsc                 C   s  i }| D ]}d|v rt |d tjjrt|d |d< t|\}}|D ]j\}}t |tttjfs1q#t |tjr?t	|j
}d}n|f}d}||vrXdd tt|D |f||< n!|| \}	}
|
|krc	 t|	t|k ry|	t  t|	t|k skt|D ]\}}|| d | | q}q#qi }| D ].\}\}	}t	dd |	D }d	d
dd |D  }|d j}||vri ||< ||| |< 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>O   s    z2track_dynamism_across_examples.<locals>.<listcomp>r   c                 s   s    | ]	}t |d kV  qdS )   N)len)r(   sr   r   r   	<genexpr>[   s    z1track_dynamism_across_examples.<locals>.<genexpr>L c                 s   s    | ]}t | V  qd S )N)str)r(   kr   r   r   r-   \   s    )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valuer3   Z	is_tensorZdim_setsflagidimoutputZ
_is_tensorZ	final_dynZkey_strr:   r   r   r   r	   4   sD   
 
r	   example_inputc                 C   s   dt dt f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_fnj   s   z/clone_and_convert_to_meta.<locals>.transform_fn)r   r   )rA   rE   r   r   r   r
   d   s   
r
   )r   typingr   r   r   r   Ztorch.utils._pytreer   r   r2   ZKeyPathr   r   ZNonTensorShapeFn__all__r0   r   r   r   dictr   listr	   r
   r   r   r   r   <module>   s    

0