
    `i5                         d dl Z d dlZd dlmZ d dlmZmZ d dlZd dlmZ d dl	m
Z
 d dlmZ ddlmZmZmZmZmZ d	gZej        hZg d
Z G d d	e j                  ZdS )    N)defaultdict)AnyOptional)nn)parametrize)type_before_parametrizations   )FakeSparsityget_arg_info_from_tensor_fqnmodule_contains_parammodule_to_fqnswap_moduleBaseSparsifier)module
module_fqntensor_namec            
       R    e Zd ZdZd"deeeef                  f fdZdeeef         fdZ	deeeeef         f         ddfdZ
d	 Zdeeef         fd
Zd#deeef         defdZefdej        deeej                          ddfdZd Zd Z	 	 d$deeedf                  deeeeedf         f                  fdZddefdej        deeeej                 eej                 f                  dedeej                 fdZd#deddfdZej        dej        d efd!            Z xZ S )%r   a'  Base class for all sparsifiers.

    Abstract methods that need to be implemented:

    - update_mask: Function to compute a new mask for all keys in the
        `groups`.

    Args:
        - model [nn.Module]: model to configure. The model itself is not saved
            but used for the state_dict saving / loading.
        - config [list]: configuration elements should be a dict map that includes
            `tensor_fqn` of tensors to sparsify
        - defaults [dict]: default configurations will be attached to the
            configuration. Only the keys that don't exist in the `config` will
            be updated.

    Example::

        >>> # xdoctest: +SKIP("Can't instantiate abstract class BaseSparsifier with abstract method update_mask")
        >>> config = [{'tensor_fqn': 'layer1.weight', 'tensor_fqn': 'linear2.weight2', 'sparsity_level': 0.5}]
        >>> defaults = {'sparsity_level': 0.7}
        >>> # model.layer1.weight will have `sparsity_level` = 0.7 (getting default)
        >>> sparsifier = BaseSparsifier(config, defaults)
    Ndefaultsc                     t                                                       |pi | _        t          t                    | _        g | _        d| _        d S )NT)super__init__r   r   dictstategroupsenable_mask_update)selfr   	__class__s     /home/jaya/work/projects/VOICE-AGENT/VIET/agent-env/lib/python3.11/site-packages/torch/ao/pruning/sparsifier/base_sparsifier.pyr   zBaseSparsifier.__init__7   sH    (0B&1$&7&7
,."&    returnc                 ,    | j         | j        | j        dS )Nr   r   r   r"   )r   s    r   __getstate__zBaseSparsifier.__getstate__?   s     Zk
 
 	
r   r   c                 :    | j                             |           d S N)__dict__update)r   r   s     r   __setstate__zBaseSparsifier.__setstate__F   s    U#####r   c                    | j         j        dz   }t          | j                  D ]a\  }}|d         }|dz  }|d| dz  }|d| dz  }t	          |                                          D ]}|dk    r	|d| d||          dz  }b|dz  }|S )	Nz (r   
z	Group z	    module: z	    z: ))r   __name__	enumerater   sortedkeys)r   format_stringisparse_argsr   keys         r   __repr__zBaseSparsifier.__repr__I   s    /$6'44 	F 	FNA{ *FT!M-----M8f8888Mk..0011 F F(??!E#!E!ES1A!E!E!EEF 	r   c                 8    d | j         D             }| j        |dS )a  Returns the state of the optimizer as a :class:`dict`.

        It contains:
        * state - current state of the sparsification.
        * groups - a list containing all sparsity configuration groups
            with the key 'tensor_fqn' specifying the path to the sparsified tensor within a model

        TODO: Need a clean way of loading the state of the "prepared" module
        c           	      n    g | ]2}t          t          d  |                                                    3S )c                      | d         t           vS )Nr   )KEYS_NOT_IN_STATE_DICT)	key_values    r   <lambda>z6BaseSparsifier.state_dict.<locals>.<listcomp>.<lambda>e   s    il:P&P r   )r   filteritems).0mgs     r   
<listcomp>z-BaseSparsifier.state_dict.<locals>.<listcomp>b   sR     (
 (
 (
  PPHHJJ  (
 (
 (
r   r   r   )r   r   )r   r   s     r   
state_dictzBaseSparsifier.state_dictW   s=    (
 (
 k(
 (
 (
 Z
 
 	
r   TrA   strictc           	         t          j        |d                   }|d         }|                                D ]\  }}t          | j        |          }|d         }|d         }	|r|t          d| d          d}
|j        |	         D ]}t          |t                    rd}
 n|
sJt          t          j
        t          ||	          j                            }t          j        ||	|           |                    d	d           |                    d	          }||_        |D ]#}|d
         |k    r|                    |           $|                     ||d           d S )Nr   r   r   r   zError loading z into the modelFTmask
tensor_fqnr@   )copydeepcopyr<   r   modelRuntimeErrorparametrizations
isinstancer
   torchonesgetattrshaper   register_parametrizationgetpoprD   r'   r(   )r   rA   rB   r   statesrE   sarg_infor   r   foundprD   r>   s                 r   load_state_dictzBaseSparsifier.load_state_dictq   s   z(344G$#\\^^ 	( 	(MJ3DJ
KKHh'F"=1K Q&."#OJ#O#O#OPPPE,[9  a..  EE  M GFK,H,H,N!O!OPP4V[!LLLuuVT"".uuV}} ( (l#z11IIh'''( 	Ff==>>>>>r   rH   SUPPORTED_MODULESc                 \   g | _         |g}|r|                                }|                                D ]r\  }}t          |          |v rGt	          ||          }t          |t                    sJ | j                             d|dz   i           ]|                    |           s|d S d S )NrE   z.weight)configrR   named_childrentyper   rK   strappend)r   rH   rY   stackr   _namechildr   s           r   make_config_from_modelz%BaseSparsifier.make_config_from_model   s    
  	(YY[[F & 5 5 7 7 ( (u;;"333!.ue!<!<J%j#66666K&&j96L'MNNNNLL''''  	( 	( 	( 	( 	(r   c                    || _         || _        | j        |                     |           | j        D ]#}t          |t                    s
J d            t          | j        t                    sJ t          j        | j                  }|                    |           |	                    dd          }|
J d            t          ||          }|                                D ]A}||v r;||         ||         k    s)|dk    rd||         z   ||         k    sJ d| d            B|                    |           | j                            |           %|                                  dS )zPrepares a model, by adding the parametrizations.

        Note::

            The model is modified inplace. If you need to preserve the original
            model, use copy.deepcopy.
        Nznconfig elements should be dicts not modules i.e.:[{`tensor_fqn`: `foo.bar.weight`}, {`tensor_fqn`: ... }, ...]rE   zttensor_fqn is a required argument in the sparsity config whichreplaces previous `module` and [module]`fqn` arguments.zGiven both `z?` and `tensor_fqn` in the config, it is expected them to agree!)rH   r[   rc   rK   r   r   rF   rG   r'   rQ   r   r/   r   r_   _prepare)r   rH   r[   module_config
local_argsrE   info_from_tensor_fqnr3   s           r   preparezBaseSparsifier.prepare   s    
 ;''... "[ "	+ "	+MmT22  P 2
 dmT22222t}55Jm,,,#d;;J))I *)) $@z#R#R  ,0022  *$$,S1Z_DD<// #&:3&? ?:c? R R R lskkk	 !S R 2333Kz****r   c           
      F   | j         D ]}|d         }|d         }|                    dt                    }|                    dt          j        t          ||                              }|| j        |d                  d<   t          j        || ||                     dS )z-Adds mask parametrization to the layer weightr   r   parametrizationrD   rE   N)	r   rQ   r
   rL   	ones_likerN   r   r   rP   )r   argskwargsr[   r   r   rl   rD   s           r   rf   zBaseSparsifier._prepare   s    k 	 	FH%F /K$jj):LIIO::feogfk6R6R&S&STTD7;DJvl+,V40__T%:%:   	 	r   params_to_keep.params_to_keep_per_layerc                 P   | j         D ]d         }d         }t          j        ||d           i }|#fd|D             }|                    |           |A|                    d         d          }	|	#fd|	D             }
|                    |
           |r||_        dS )	a3	  Squashes the sparse masks into the appropriate tensors.

        If either the `params_to_keep` or `params_to_keep_per_layer` is set,
        the module will have a `sparse_params` dict attached to it.

        Args:
            params_to_keep: List of keys to save in the module or a dict
                            representing the modules and keys that will have
                            sparsity parameters saved
            params_to_keep_per_layer: Dict to specify the params that should be
                            saved for specific layers. The keys in the dict
                            should be the module fqn, while the values should
                            be a list of strings with the names of the variables
                            to save in the `sparse_params`

        Examples:
            >>> # xdoctest: +SKIP("locals are undefined")
            >>> # Don't save any sparse params
            >>> sparsifier.squash_mask()
            >>> hasattr(model.submodule1, "sparse_params")
            False

            >>> # Keep sparse params per layer
            >>> sparsifier.squash_mask(
            ...     params_to_keep_per_layer={
            ...         "submodule1.linear1": ("foo", "bar"),
            ...         "submodule2.linear42": ("baz",),
            ...     }
            ... )
            >>> print(model.submodule1.linear1.sparse_params)
            {'foo': 42, 'bar': 24}
            >>> print(model.submodule2.linear42.sparse_params)
            {'baz': 0.1}

            >>> # Keep sparse params for all layers
            >>> sparsifier.squash_mask(params_to_keep=("foo", "bar"))
            >>> print(model.submodule1.linear1.sparse_params)
            {'foo': 42, 'bar': 24}
            >>> print(model.submodule2.linear42.sparse_params)
            {'foo': 42, 'bar': 24}

            >>> # Keep some sparse params for all layers, and specific ones for
            >>> # some other layers
            >>> sparsifier.squash_mask(
            ...     params_to_keep=("foo", "bar"),
            ...     params_to_keep_per_layer={"submodule2.linear42": ("baz",)},
            ... )
            >>> print(model.submodule1.linear1.sparse_params)
            {'foo': 42, 'bar': 24}
            >>> print(model.submodule2.linear42.sparse_params)
            {'foo': 42, 'bar': 24, 'baz': 0.1}
        r   r   T)leave_parametrizedNc                 "    i | ]}||         S  ru   r=   kr[   s     r   
<dictcomp>z.BaseSparsifier.squash_mask.<locals>.<dictcomp>!  s     F F F!F1I F F Fr   r   c                 "    i | ]}||         S ru   ru   rv   s     r   rx   z.BaseSparsifier.squash_mask.<locals>.<dictcomp>&  s    'E'E'E6!9'E'E'Er   )r   r   remove_parametrizationsr'   rQ   sparse_params)r   rp   rq   rn   ro   r   r   r{   global_paramsparamsper_layer_paramsr[   s              @r   squash_maskzBaseSparsifier.squash_mask   s    v k 	5 	5FH%F /K/    M) F F F F~ F F F$$]333'3155f\6JDQQ%'E'E'E'Ef'E'E'E$!(()9::: 5'4$#	5 	5r   Fr   mappinginplaceparameterizationc                 v   |t          d          |st          j        |          }i }|                                D ]V\  }}t	          ||          r%t          |          |v rt          ||          ||<   :|                     ||d|          ||<   W|                                D ]\  }}	|	|j	        |<   |S )a  Converts submodules in input module to a different module according to `mapping`
        by calling `from_dense` method on the target module class
        Args:
            module: input module
            mapping: a dictionary that maps from source module type to target
                module type, can be overwritten to allow swapping user defined
                Modules
            inplace: carry out model transformations in-place, the original module
                is mutated
        NzNeed to auto generate mapping T)r   r   r   )
NotImplementedErrorrF   rG   r\   r   r   r   convertr<   _modules)
r   r   r   r   r   reassignnamemodr3   values
             r   r   zBaseSparsifier.convert,  s    " ?%&FGGG 	+]6**F..00 	 	ID# &c+;<<055@@!,S'!:!: "&# %5	 ". " " #..** 	) 	)JC#(FOC  r   use_pathc                     | j         sd S t          j                    5  | j        D ]} | j        di | 	 d d d            d S # 1 swxY w Y   d S )Nru   )r   rL   no_gradr   update_mask)r   r   r[   s      r   stepzBaseSparsifier.stepX  s    & 	F]__ 	+ 	++ + +  **6****+	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+s   AA
Ar   c                     d S r%   ru   )r   r   r   ro   s       r   r   zBaseSparsifier.update_mask_  s    r   r%   )T)NN)!r,   
__module____qualname____doc__r   r   r^   r   r   r#   r(   r4   rA   boolrX   rY   r   Modulesetr]   Linearrc   rj   rf   tupler   r
   r   r   abcabstractmethodr   __classcell__)r   s   @r   r   r      s        2' '$sCx.!9 ' ' ' ' ' '
d38n 
 
 
 
$$sDcN':"; $ $ $ $ $  
DcN 
 
 
 
4? ?$sCx. ?$ ? ? ? ?< 3D( (y( tBI/( 
	( ( ( ("3 3 3j
 
 
 59IML5 L5 sCx1L5 #+4U38_0D+E"FL5 L5 L5 L5b EI,8* *	* $tBIRY?@A* 	*
 ry/* * * *X+ +T +T + + + + 	") #        r   )r   rF   collectionsr   typingr   r   rL   r   torch.nn.utilsr   torch.nn.utils.parametrizer   utilsr
   r   r   r   r   __all__r   rY   r8   ABCr   ru   r   r   <module>r      s&   



  # # # # # #                        & & & & & & C C C C C C              
YK @@@ D D D D DSW D D D D Dr   