
    qi6                         d dl Z d dlZd dlmZ d dl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y)    N)defaultdict)Any)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            
       *    e Zd ZdZd!deeef   dz  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df   dz  deeeedf   f   dz  fdZddefdej                   deeej                      eej                      f   dz  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         |           |xs i | _        t        t              | _        g | _        d| _        y )NT)super__init__r   r   dictstategroupsenable_mask_update)selfr   	__class__s     q/home/ubuntu/crypto_trading_bot/.venv/lib/python3.12/site-packages/torch/ao/pruning/sparsifier/base_sparsifier.pyr   zBaseSparsifier.__init__7   s4    (0B&1$&7
,."&    returnc                 J    | j                   | j                  | j                  dS )Nr   r   r   r!   )r   s    r   __getstate__zBaseSparsifier.__getstate__?   s!    ZZkk
 	
r   r   c                 :    | j                   j                  |       y N)__dict__update)r   r   s     r   __setstate__zBaseSparsifier.__setstate__F   s    U#r   c                    | j                   j                  dz   }t        | j                        D ]T  \  }}|d   }|dz  }|d| dz  }|d| dz  }t	        |j                               D ]  }|dk(  r	|d| d||    dz  } V |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 	FNA{ *FT!Mxs"--M~fXR88Mk..01 F(?6#bS1A0B"!EEF	F 	r   c           
          | j                   D cg c]&  }t        t        d |j                                     ( }}| j                  |dS c c}w )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                     | d   t         vS )Nr   )KEYS_NOT_IN_STATE_DICT)	key_values    r   <lambda>z+BaseSparsifier.state_dict.<locals>.<lambda>e   s    il:P&P r   r   r   )r   r   filteritemsr   )r   mgr   s      r   
state_dictzBaseSparsifier.state_dictW   s[    $ kk(
  PHHJ(
 (
 ZZ
 	
(
s   +Ar=   strictc           	      |   t        j                  |d         }|d   }|j                         D ]  \  }}t        | j                  |      }|d   }|d   }	|r|t        d| d      d}
|j                  |	   D ]  }t        |t              sd}
 n |
sIt        t        j                  t        ||	      j                              }t        j                  ||	|       |j                  d	d       |j!                  d	      }|_        |D ]  }|d
   |k(  s|j%                  |         | j'                  ||d       y )Nr   r   r   r   zError loading z into the modelFTmask
tensor_fqnr9   )copydeepcopyr;   r
   modelRuntimeErrorparametrizations
isinstancer	   torchonesgetattrshaper   register_parametrizationgetpopr@   r&   r'   )r   r=   r>   r   statesrA   sarg_infor   r   foundpr@   r<   s                 r   load_state_dictzBaseSparsifier.load_state_dictq   sA   z(34G$#\\^ 	(MJ3DJJ
KHh'F"=1K&."^J<#OPPE,,[9 a. E  GFK,H,N,N!OP44V[!LuuVT".uuV} (l#z1IIh'('	(, 	Ff=>r   rD   SUPPORTED_MODULESc                 @   g | _         |g}|r|j                         }|j                         D ]k  \  }}t        |      |v rHt	        ||      }t        |t              st        d      | j                   j                  d|dz   i       [|j                  |       m |ry y )Nzmodule_fqn must be a stringrA   z.weight)	configrN   named_childrentyper   rG   strAssertionErrorappend)r   rD   rU   stackr   _namechildr   s           r   make_config_from_modelz%BaseSparsifier.make_config_from_model   s    
 YY[F & 5 5 7 (u;"33!.ue!<J%j#6,-JKKKK&&j96L'MNLL'( r   c                    || _         || _        | j                  | j                  |       | j                  D ]  }t        |t              st        d      t        | j                  t              st        d      t        j                  | j                        }|j                  |       |j                  dd      }|t        d      t        ||      }|D ]5  }||v s||   ||   k(  r|dk(  rd||   z   ||   k(  r(t        d| d       |j                  |       | j                  j                  |        | j                          y)	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`: ... }, ...]zdefaults must be a dictrA   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!)rD   rW   r`   rG   r   r[   r   rB   rC   r&   rM   r
   r   r\   _prepare)r   rD   rW   module_config
local_argsrA   info_from_tensor_fqnr2   s           r   preparezBaseSparsifier.prepare   sh    
 ;;''. "[[ &	+MmT2$T 
 dmmT2$%>??t}}5Jm,#d;J!$M  $@z#R  , *$,S1Z_D</ #&:3&? ?:c? R -*3%/no  23KKz*M&	+N 	r   c           
      (   | j                   D ]  }|d   }|d   }|j                  dt              }|j                  dt        j                  t        ||                  }|| j                  |d      d<   t        j                  || ||              y)z-Adds mask parametrization to the layer weightr   r   parametrizationr@   rA   N)	r   rM   r	   rH   	ones_likerJ   r   r   rL   )r   argskwargsrW   r   r   ri   r@   s           r   rc   zBaseSparsifier._prepare   s    kk 	FH%F /K$jj):LIO::feoogfk6R&STD7;DJJvl+,V400_T%:	r   params_to_keep.params_to_keep_per_layerc                 \   | j                   D ]  }|d   }|d   }t        j                  ||d       i }|$|D 	ci c]  }	|	||	   
 }
}	|j                  |
       |;|j	                  |d   d      }|$|D 	ci c]  }	|	||	   
 }}	|j                  |       |s||_         yc c}	w c c}	w )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_parametrizedNr   )r   r   remove_parametrizationsr&   rM   sparse_params)r   rm   rn   rk   rl   rW   r   r   rr   kglobal_paramsparamsper_layer_paramss                r   squash_maskzBaseSparsifier.squash_mask   s    v kk 	5FH%F /K// M)7E F!F1I F F$$]3'3155f\6JDQ%>D'E6!9'E$'E!(()9:'4$#	5 !G
 (Fs   B$7B)Fr   mappinginplaceparameterizationc                 R   |t        d      |st        j                  |      }i }|j                         D ]F  \  }}t	        ||      rt        |      |v rt        ||      ||<   /| j                  ||d|      ||<   H |j                         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
        zNeed to auto generate mapping T)rx   ry   rz   )
NotImplementedErrorrB   rC   rX   r   r   r   convertr;   _modules)
r   r   rx   ry   rz   reassignnamemodr2   values
             r   r}   zBaseSparsifier.convert2  s    " ?%&FGG]]6*F..0 	ID# &c+;<05@!,S'!: "&# %5	 ". "	  #..* 	)JC#(FOOC 	) r   use_pathc                     | j                   sy t        j                         5  | j                  D ]  } | j                  di |  	 d d d        y # 1 sw Y   y xY w)N )r   rH   no_gradr   update_mask)r   r   rW   s      r   stepzBaseSparsifier.step^  sR    &&]]_ 	+++ +   *6*+	+ 	+ 	+s   $AAr   c                      y r$   r   )r   r   r   rl   s       r   r   zBaseSparsifier.update_maske  s    r   r$   )T)NN) r+   
__module____qualname____doc__r   rZ   r   r   r"   r'   r3   r=   boolrT   rU   r   ModulesetrY   Linearr`   rg   rc   tuplerw   r	   r}   r   abcabstractmethodr   __classcell__)r   s   @r   r   r      s   2'c3h$!6 '
d38n 
$$sDcN':"; $ $
DcN 
4?$sCx. ?$ ?< 3D(yy( tBII/( 
	($8t
 26FJL5c3h$.L5 #'sE#s(O';"<t"CL5b BF,8*		* d299otBII67$>* 	*
 ryy/*X+T +T + 	")) #  r   )r   rB   collectionsr   typingr   rH   r   torch.nn.utilsr   torch.nn.utils.parametrizer   utilsr	   r
   r   r   r   __all__r   rU   r6   ABCr   r   r   r   <module>r      sU    
  #    & C  
YYK @ JSWW Jr   