
    JTh                     J   S r SSKrSSKJrJr  SSKJr  SSKr " S S\5      r " S S\5      r	 " S	 S
\5      r
 " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      rS rS rS$S jrS rS$S jrS$S jrS rS rS rS rS rS  rS! rS" rS# rg)%zPruning methods.    N)ABCabstractmethod)Iterablec                   h    \ rS rSr% Sr\\S'   S r\S 5       r	S r
\SS.S	 j5       rSS
 jrS rSrg)BasePruningMethod
   zAbstract base class for creation of new pruning techniques.

Provides a skeleton for customization requiring the overriding of methods
such as :meth:`compute_mask` and :meth:`apply`.
_tensor_namec                 N    [        XR                  U R                  U5      5        g)a]  Multiply the mask into original tensor and store the result.

Multiplies the mask (stored in ``module[name + '_mask']``)
into the original tensor (stored in ``module[name + '_orig']``)
and stores the result into ``module[name]`` by using :meth:`apply_mask`.

Args:
    module (nn.Module): module containing the tensor to prune
    inputs: not used.
N)setattrr	   
apply_mask)selfmoduleinputss      L/var/www/auris/envauris/lib/python3.13/site-packages/torch/nn/utils/prune.py__call__BasePruningMethod.__call__   s     	))4??6+BC    c                     g)ao  Compute and returns a mask for the input tensor ``t``.

Starting from a base ``default_mask`` (which should be a mask of ones
if the tensor has not been pruned yet), generate a random mask to
apply on top of the ``default_mask`` according to the specific pruning
method recipe.

Args:
    t (torch.Tensor): tensor representing the importance scores of the
    parameter to prune.
    default_mask (torch.Tensor): Base mask from previous pruning
    iterations, that need to be respected after the new mask is
    applied. Same dims as ``t``.

Returns:
    mask (torch.Tensor): mask to apply to ``t``, of same dims as ``t``
N )r   tdefault_masks      r   compute_maskBasePruningMethod.compute_mask    s    r   c                     U R                   c   SU S35       e[        XR                   S-   5      n[        XR                   S-   5      nUR                  UR                  S9U-  nU$ )aY  Simply handles the multiplication between the parameter being pruned and the generated mask.

Fetches the mask and the original tensor from the module
and returns the pruned version of the tensor.

Args:
    module (nn.Module): module containing the tensor to prune

Returns:
    pruned_tensor (torch.Tensor): pruned version of the input tensor
Module z has to be pruned_mask_origdtype)r	   getattrtor   )r   r   maskorigpruned_tensors        r   r   BasePruningMethod.apply_mask4   ss     )	/VH-.	/)v007:;v007:;djj1D8r   Nimportance_scoresc                   S nU" XU/UQ70 UD6n[        X5      nUb(  UR                  UR                  :X  d   SU SU 35       eOUn[        U[        5      (       d9  UR	                  US-   U5        UR
                  U	 [        R                  " U5      n	O7[        XS-   5      R                  5       R                  [        R                  S9n	 UR                  X9S9n
UR                  US-   U
5        [        XUR                  U5      5        UR                  U5        U$ ! [          aK  n[        U[        5      (       d/  [        XS-   5      nUR	                  X(5        UR
                  US-   	 UeSnAff = f)	ar  Add pruning on the fly and reparametrization of a tensor.

Adds the forward pre-hook that enables pruning on the fly and
the reparametrization of a tensor in terms of the original tensor
and the pruning mask.

Args:
    module (nn.Module): module containing the tensor to prune
    name (str): parameter name within ``module`` on which pruning
        will act.
    args: arguments passed on to a subclass of
        :class:`BasePruningMethod`
    importance_scores (torch.Tensor): tensor of importance scores (of
        same shape as module parameter) used to compute mask for pruning.
        The values in this tensor indicate the importance of the
        corresponding elements in the parameter being pruned.
        If unspecified or None, the parameter will be used in its place.
    kwargs: keyword arguments passed on to a subclass of a
        :class:`BasePruningMethod`
c                 
   S nSn/ nUR                   R                  5        HF  u  p[        U	[        5      (       d  M  U	R                  U:X  d  M.  U	nUR                  U5        US-  nMH     US::  d   SU SU S35       eU H  nUR                   U	 M     U " U0 UD6n
X*l        Ub]  [        U[        5      (       a  UR                  U
5        Un
U
$ [        U[        5      (       a  [        U5      nUR                  U
5        Un
U
$ )Nr      zFAvoid adding multiple pruning hooks to the                same tensor z of module z. Use a PruningContainer.)_forward_pre_hooksitems
isinstancer   r	   appendPruningContaineradd_pruning_method)clsr   nameargskwargs
old_methodfoundhooks_to_removekhookmethod	containers               r   _get_composite_method6BasePruningMethod.apply.<locals>._get_composite_methoda   s2    JE !O!44::< d$5664;L;LPT;T!%J#**1-QJE = 
P!F+fX5NPP %--a0 %
 $)&)F"& % j*:;;11&9'F M  
,=>> 0 <I 008&FMr   NzJimportance_scores should have the same shape as parameter                 z of r   r   memory_formatr   )r    shaper-   r/   register_parameter_parameterstorch	ones_likedetachclonecontiguous_formatr   register_bufferr   r   register_forward_pre_hook	Exception)r1   r   r2   r'   r3   r4   r<   r:   r#   r   r"   es               r   applyBasePruningMethod.applyJ   s   .-	^ 'sDJ4J6J v$(!''4::5o[\`[aaeflemno5 !%
 &"233%%dWnd;""4( ??40L w/U%<%<= 	&&'8&TD""4'>48F&"3"3F";< ,,V4   	f&677vg~6))$5&&tg~6G	s   AD! !
E6+AE11E6c                     Ub"  UR                   UR                   :X  d   S5       eOUnUb  UO[        R                  " U5      nXR                  X2S9-  $ )aS  Compute and returns a pruned version of input tensor ``t``.

According to the pruning rule specified in :meth:`compute_mask`.

Args:
    t (torch.Tensor): tensor to prune (of same dimensions as
        ``default_mask``).
    importance_scores (torch.Tensor): tensor of importance scores (of
        same shape as ``t``) used to compute mask for pruning ``t``.
        The values in this tensor indicate the importance of the
        corresponding elements in the ``t`` that is being pruned.
        If unspecified or None, the tensor ``t`` will be used in its place.
    default_mask (torch.Tensor, optional): mask from previous pruning
        iteration, if any. To be considered when determining what
        portion of the tensor that pruning should act on. If None,
        default to a mask of ones.

Returns:
    pruned version of tensor ``t``.
z8importance_scores should have the same shape as tensor tr@   )rA   rD   rE   r   )r   r   r   r'   s       r   pruneBasePruningMethod.prune   sd    * (!''1772JIJ2 !"'3'?|U__UVEW$$%6$RRRr   c                    U R                   c   SU S35       eU R                  U5      n[        XR                   5      (       a  [        XR                   5        UR                  U R                   S-      nUR
                  Ul        UR                  U R                   S-   	 UR                  U R                   S-   	 [        XR                   U5        g)aB  Remove the pruning reparameterization from a module.

The pruned parameter named ``name`` remains permanently pruned,
and the parameter named ``name+'_orig'`` is removed from the parameter list.
Similarly, the buffer named ``name+'_mask'`` is removed from the buffers.

Note:
    Pruning itself is NOT undone or reversed!
Nr   z: has to be pruned            before pruning can be removedr   r   )r	   r   hasattrdelattrrC   data_buffersr   )r   r   weightr#   s       r   removeBasePruningMethod.remove   s     )	XVHVW	X) ( 6,,--F--.!!$"3"3g"=>KK	t007:;OOD--78))40r   r   )NN)__name__
__module____qualname____firstlineno____doc__str__annotations__r   r   r   r   classmethodrM   rP   rX   __static_attributes__r   r   r   r   r   
   sS     D  &, :> ~ ~@S<1r   r   c                   <    \ rS rSrSrS rS rS rS rS r	S r
S	rg
)r/   i  a  Container holding a sequence of pruning methods for iterative pruning.

Keeps track of the order in which pruning methods are applied and handles
combining successive pruning calls.

Accepts as argument an instance of a BasePruningMethod or an iterable of
them.
c                 &   SU l         [        U[        5      (       d#  UR                  U l        U R	                  U5        g [        U5      S:X  a)  US   R                  U l        U R	                  US   5        g U H  nU R	                  U5        M     g )Nr   r*   r   )_pruning_methodsr-   r   r	   r0   len)r   r3   r:   s      r   __init__PruningContainer.__init__  sz    ?A$)) $ 1 1D##D)Y!^ $Q 4 4D##DG,''/ r   c                 "   [        U[        5      (       d  Ub  [        [        U5       S35      eUbG  U R                  UR                  :w  a-  [        SU R                   SU  S3SUR                   S3-   5      eU =R                  U4-  sl        g)zAdd a child pruning ``method`` to the container.

Args:
    method (subclass of BasePruningMethod): child pruning method
        to be added to the container.
Nz$ is not a BasePruningMethod subclassz<Can only add pruning methods acting on the parameter named 'z' to PruningContainer .z Found '')r-   r   	TypeErrortyper	   
ValueErrorre   )r   r:   s     r   r0   #PruningContainer.add_pruning_method  s     &"3449KtF|n,PQRRD$5$59L9L$L((,(9(9'::PQUPVVWYV00134  	&*r   c                 ,    [        U R                  5      $ N)rf   re   r   s    r   __len__PruningContainer.__len__.  s    4(())r   c                 ,    [        U R                  5      $ rq   )iterre   rr   s    r   __iter__PruningContainer.__iter__1  s    D))**r   c                      U R                   U   $ rq   re   )r   idxs     r   __getitem__PruningContainer.__getitem__4  s    $$S))r   c                 <    S nU R                   S   nU" XAU5      nU$ )a  Apply the latest ``method`` by computing the new partial masks and returning its combination with the ``default_mask``.

The new partial mask should be computed on the entries or channels
that were not zeroed out by the ``default_mask``.
Which portions of the tensor ``t`` the new mask will be calculated from
depends on the ``PRUNING_TYPE`` (handled by the type handler):

* for 'unstructured', the mask will be computed from the raveled
  list of nonmasked entries;

* for 'structured', the mask will be computed from the nonmasked
  channels in the tensor;

* for 'global', the mask will be computed across all entries.

Args:
    t (torch.Tensor): tensor representing the parameter to prune
        (of same dimensions as ``default_mask``).
    default_mask (torch.Tensor): mask from previous pruning iteration.

Returns:
    mask (torch.Tensor): new mask that combines the effects
    of the ``default_mask`` and the new mask from the current
    pruning ``method`` (of same dimensions as ``default_mask`` and
    ``t``).
c                    UnUR                  UR                  S9nU R                  S:X  a  US:H  nOU R                  S:X  a  [        U S5      (       d  [	        S5      eUR                  5       nU R
                  nUS:  a  XV-   nUS:  a  [        SU 35      eUR                  [        U5       Vs/ s H  owU:w  d  M
  UPM     snS	9S:g  n[        S
5      /U-  nXU'   OMU R                  S:X  a%  [        UR                  5      n[        S
5      /U-  nO[        SU R                   35      eU R                  X   X$   S9n	U	R                  UR                  S9X4'   U$ s  snf )a	  Combine the masks from all pruning methods and returns a new mask.

Args:
    method (a BasePruningMethod subclass): pruning method
        currently being applied.
    t (torch.Tensor): tensor representing the parameter to prune
        (of same dimensions as mask).
    mask (torch.Tensor): mask from previous pruning iteration

Returns:
    new_mask (torch.Tensor): new mask that combines the effects
        of the old mask and the new mask from the current
        pruning method (of same dimensions as mask and t).
r   unstructuredr*   
structureddimzVPruning methods of PRUNING_TYPE "structured" need to have the attribute `dim` defined.r   z2Index is out of bounds for tensor with dimensions )r   NglobalzUnrecognized PRUNING_TYPE r@   )r!   r   PRUNING_TYPErS   AttributeErrorr   
IndexErrorsumrangeslicerf   rA   rn   r   )
r:   r   r"   new_maskslcn_dimsr   dkeep_channelpartial_masks
             r   _combine_masks5PruningContainer.compute_mask.<locals>._combine_masksS  sq    H{{{1H ""n4ai $$4vu--(Q  jj7 ,C7$LVHU   $xxf,R1cQ,RxSWXXT{mf,'C$$0QWWT{mf, !#=f>Q>Q=R!STT "..qvDI.NL(OO(..OAHMO! -Ss   0	E=Erz   )r   r   r   r   r:   r"   s         r   r   PruningContainer.compute_mask7  s+    8=	~ &&r*f6r   )re   r	   N)rZ   r[   r\   r]   r^   rg   r0   rs   rw   r|   r   rb   r   r   r   r/   r/     s&    
0+&*+*]r   r/   c                   @   ^  \ rS rSrSrSrS r\U 4S j5       rSr	U =r
$ )Identityi  zsUtility pruning method that does not prune any units but generates the pruning parametrization with a mask of ones.r   c                 
    UnU$ rq   r   r   r   r   r"   s       r   r   Identity.compute_mask  s    r   c                 "   > [         TU ]  X5      $ )j  Add pruning on the fly and reparametrization of a tensor.

Adds the forward pre-hook that enables pruning on the fly and
the reparametrization of a tensor in terms of the original tensor
and the pruning mask.

Args:
    module (nn.Module): module containing the tensor to prune
    name (str): parameter name within ``module`` on which pruning
        will act.
superrM   )r1   r   r2   	__class__s      r   rM   Identity.apply  s     w}V**r   r   )rZ   r[   r\   r]   r^   r   r   ra   rM   rb   __classcell__r   s   @r   r   r     s$    ~!L + +r   r   c                   F   ^  \ rS rSrSrSrS rS r\U 4S j5       r	Sr
U =r$ )RandomUnstructuredi  a  Prune (currently unpruned) units in a tensor at random.

Args:
    name (str): parameter name within ``module`` on which pruning
        will act.
    amount (int or float): quantity of parameters to prune.
        If ``float``, should be between 0.0 and 1.0 and represent the
        fraction of parameters to prune. If ``int``, it represents the
        absolute number of parameters to prune.
r   c                 &    [        U5        Xl        g rq   _validate_pruning_amount_initamountr   r   s     r   rg   RandomUnstructured.__init__      %f-r   c                 ^   UR                  5       n[        U R                  U5      n[        XC5        UR	                  [
        R                  S9nUS:w  aX  [
        R                  " U5      n[
        R                  " UR                  S5      US9nSUR                  S5      UR                  '   U$ )Nr>   r   r   r8   )nelement_compute_nparams_topruner   _validate_pruning_amountrG   rD   rH   	rand_liketopkviewindices)r   r   r   tensor_sizenparams_topruner"   probr   s           r   r   RandomUnstructured.compute_mask  s     jjl 34;;L 	!>!!0G0G!Ha??1%D::diim?D*+DIIbM$,,'r   c                     > [         TU ]  XUS9$ )ac  Add pruning on the fly and reparametrization of a tensor.

Adds the forward pre-hook that enables pruning on the fly and
the reparametrization of a tensor in terms of the original tensor
and the pruning mask.

Args:
    module (nn.Module): module containing the tensor to prune
    name (str): parameter name within ``module`` on which pruning
        will act.
    amount (int or float): quantity of parameters to prune.
        If ``float``, should be between 0.0 and 1.0 and represent the
        fraction of parameters to prune. If ``int``, it represents the
        absolute number of parameters to prune.
r   r   )r1   r   r2   r   r   s       r   rM   RandomUnstructured.apply  s    " w}V&}99r   r   rZ   r[   r\   r]   r^   r   rg   r   ra   rM   rb   r   r   s   @r   r   r     s-    	 "L
( : :r   r   c                   J   ^  \ rS rSrSrSrS rS r\SU 4S jj5       r	Sr
U =r$ )	L1Unstructuredi  a^  Prune (currently unpruned) units in a tensor by zeroing out the ones with the lowest L1-norm.

Args:
    amount (int or float): quantity of parameters to prune.
        If ``float``, should be between 0.0 and 1.0 and represent the
        fraction of parameters to prune. If ``int``, it represents the
        absolute number of parameters to prune.
r   c                 &    [        U5        Xl        g rq   r   r   s     r   rg   L1Unstructured.__init__  r   r   c                 \   UR                  5       n[        U R                  U5      n[        XC5        UR	                  [
        R                  S9nUS:w  aW  [
        R                  " [
        R                  " U5      R                  S5      USS9nSUR                  S5      UR                  '   U$ )Nr>   r   r   Fr8   largest)r   r   r   r   rG   rD   rH   r   absr   r   )r   r   r   r   r   r"   r   s          r   r   L1Unstructured.compute_mask  s     jjl 34;;L 	!>!!0G0G!Ha ::eiil//3PUVD*+DIIbM$,,'r   c                     > [         TU ]  XX4S9$ )a  Add pruning on the fly and reparametrization of a tensor.

Adds the forward pre-hook that enables pruning on the fly and
the reparametrization of a tensor in terms of the original tensor
and the pruning mask.

Args:
    module (nn.Module): module containing the tensor to prune
    name (str): parameter name within ``module`` on which pruning
        will act.
    amount (int or float): quantity of parameters to prune.
        If ``float``, should be between 0.0 and 1.0 and represent the
        fraction of parameters to prune. If ``int``, it represents the
        absolute number of parameters to prune.
    importance_scores (torch.Tensor): tensor of importance scores (of same
        shape as module parameter) used to compute mask for pruning.
        The values in this tensor indicate the importance of the corresponding
        elements in the parameter being pruned.
        If unspecified or None, the module parameter will be used in its place.
r   r'   r   )r1   r   r2   r   r'   r   s        r   rM   L1Unstructured.apply  s     , w}  
 	
r   r   rq   r   r   s   @r   r   r     s-     "L
, 
 
r   r   c                   N   ^  \ rS rSrSrSrSS jrS r\SU 4S jj5       r	Sr
U =r$ )	RandomStructuredi-  a  Prune entire (currently unpruned) channels in a tensor at random.

Args:
    amount (int or float): quantity of parameters to prune.
        If ``float``, should be between 0.0 and 1.0 and represent the
        fraction of parameters to prune. If ``int``, it represents the
        absolute number of parameters to prune.
    dim (int, optional): index of the dim along which we define
        channels to prune. Default: -1.
r   c                 2    [        U5        Xl        X l        g rq   )r   r   r   )r   r   r   s      r   rg   RandomStructured.__init__;  s    %f-r   c                 0   [        U5        [        XR                  5        UR                  U R                     n[	        U R
                  U5      n[        XC5        S nUS:X  a  UnU$ U" XR                  X45      nXbR                  UR                  S9-  nU$ )a  Compute and returns a mask for the input tensor ``t``.

Starting from a base ``default_mask`` (which should be a mask of ones
if the tensor has not been pruned yet), generate a random mask to
apply on top of the ``default_mask`` by randomly zeroing out channels
along the specified dim of the tensor.

Args:
    t (torch.Tensor): tensor representing the parameter to prune
    default_mask (torch.Tensor): Base mask from previous pruning
        iterations, that need to be respected after the new mask is
        applied. Same dims as ``t``.

Returns:
    mask (torch.Tensor): mask to apply to ``t``, of same dims as ``t``

Raises:
    IndexError: if ``self.dim >= len(t.shape)``
c                     [         R                  " U5      n[         R                  " XCS9R                  nXE:  n[         R                  " U 5      n[        S 5      /[        U R                  5      -  nXhU'   SXx'   U$ )Nr   r*   )rD   randkthvaluevalues
zeros_liker   rf   rA   )	r   r   	nchannelsnchannels_topruner   	thresholdchannel_maskr"   r   s	            r   	make_mask0RandomStructured.compute_mask.<locals>.make_maski  si    ::i(D tAHHI+L##A&D;-#agg,.C#HDIKr   r   r   )	_validate_structured_pruning_validate_pruning_dimr   rA   r   r   r   r!   r   )r   r   r   r   r   r   r"   s          r   r   RandomStructured.compute_maskA  s    , 	%Q' 	a* ggdhh' 34;;L 	!>
	 aD  Q+GDOO$**O55Dr   c                     > [         TU ]  XX4S9$ )a  Add pruning on the fly and reparametrization of a tensor.

Adds the forward pre-hook that enables pruning on the fly and
the reparametrization of a tensor in terms of the original tensor
and the pruning mask.

Args:
    module (nn.Module): module containing the tensor to prune
    name (str): parameter name within ``module`` on which pruning
        will act.
    amount (int or float): quantity of parameters to prune.
        If ``float``, should be between 0.0 and 1.0 and represent the
        fraction of parameters to prune. If ``int``, it represents the
        absolute number of parameters to prune.
    dim (int, optional): index of the dim along which we define
        channels to prune. Default: -1.
r   r   r   )r1   r   r2   r   r   r   s        r   rM   RandomStructured.apply  s    & w}V&}BBr   r   r   r   r   s   @r   r   r   -  s0    	  L=~ C Cr   r   c                   N   ^  \ rS rSrSrSrSS jrS r\S	U 4S jj5       r	Sr
U =r$ )
LnStructuredi  a=  Prune entire (currently unpruned) channels in a tensor based on their L\ ``n``-norm.

Args:
    amount (int or float): quantity of channels to prune.
        If ``float``, should be between 0.0 and 1.0 and represent the
        fraction of parameters to prune. If ``int``, it represents the
        absolute number of parameters to prune.
    n (int, float, inf, -inf, 'fro', 'nuc'): See documentation of valid
        entries for argument ``p`` in :func:`torch.norm`.
    dim (int, optional): index of the dim along which we define
        channels to prune. Default: -1.
r   c                 >    [        U5        Xl        X l        X0l        g rq   )r   r   nr   )r   r   r   r   s       r   rg   LnStructured.__init__  s    %f-r   c                    [        U5        [        XR                  5        UR                  U R                     n[	        U R
                  U5      nX4-
  n[        XC5        [        XR                  U R                  5      n[        R                  " XeSS9nS nUS:X  a  Un	U	$ U" XR                  UR                  5      n	XR                  U	R                  S9-  n	U	$ )a  Compute and returns a mask for the input tensor ``t``.

Starting from a base ``default_mask`` (which should be a mask of ones
if the tensor has not been pruned yet), generate a mask to apply on
top of the ``default_mask`` by zeroing out the channels along the
specified dim with the lowest L\ ``n``-norm.

Args:
    t (torch.Tensor): tensor representing the parameter to prune
    default_mask (torch.Tensor): Base mask from previous pruning
        iterations, that need to be respected after the new mask is
        applied.  Same dims as ``t``.

Returns:
    mask (torch.Tensor): mask to apply to ``t``, of same dims as ``t``

Raises:
    IndexError: if ``self.dim >= len(t.shape)``
Tr   c                     [         R                  " U 5      n[        S 5      /[        U R                  5      -  nX$U'   SX4'   U$ )Nr*   )rD   r   r   rf   rA   )r   r   r   r"   r   s        r   r   ,LnStructured.compute_mask.<locals>.make_mask  sA    ##A&D;-#agg,.C H DIKr   r   r   )r   r   r   rA   r   r   r   _compute_normr   rD   r   r   r!   r   )
r   r   r   r   r   nparams_tokeepnormr   r   r"   s
             r   r   LnStructured.compute_mask  s    , 	%Q'a* ggdhh' 34;;L$6 	!>
 Q1 zz$$?	 aD
  Q$,,7DOO$**O55Dr   c           	      (   > [         TU ]  UUUUUUS9$ )a  Add pruning on the fly and reparametrization of a tensor.

Adds the forward pre-hook that enables pruning on the fly and
the reparametrization of a tensor in terms of the original tensor
and the pruning mask.

Args:
    module (nn.Module): module containing the tensor to prune
    name (str): parameter name within ``module`` on which pruning
        will act.
    amount (int or float): quantity of parameters to prune.
        If ``float``, should be between 0.0 and 1.0 and represent the
        fraction of parameters to prune. If ``int``, it represents the
        absolute number of parameters to prune.
    n (int, float, inf, -inf, 'fro', 'nuc'): See documentation of valid
        entries for argument ``p`` in :func:`torch.norm`.
    dim (int): index of the dim along which we define channels to
        prune.
    importance_scores (torch.Tensor): tensor of importance scores (of same
        shape as module parameter) used to compute mask for pruning.
        The values in this tensor indicate the importance of the corresponding
        elements in the parameter being pruned.
        If unspecified or None, the module parameter will be used in its place.
)r   r   r   r'   r   )r1   r   r2   r   r   r   r'   r   s          r   rM   LnStructured.apply  s-    4 w}/  
 	
r   )r   r   r   r   rq   r   r   s   @r   r   r     s/      LDL  
  
r   r   c                   B   ^  \ rS rSrSrS rS r\U 4S j5       rSr	U =r
$ )CustomFromMaski  r   c                     Xl         g rq   r"   )r   r"   s     r   rg   CustomFromMask.__init__  s    	r   c                     UR                   U R                  R                   :X  d   eX R                  R                  UR                  S9-  nU$ )Nr   )rA   r"   r!   r   r   s       r   r   CustomFromMask.compute_mask  s@    !!TYY__444iill1C1ClDDr   c                     > [         TU ]  XUS9$ )r   r   r   )r1   r   r2   r"   r   s       r   rM   CustomFromMask.apply"  s     w}V}55r   r   )rZ   r[   r\   r]   r   rg   r   ra   rM   rb   r   r   s   @r   r   r     s&    L
 6 6r   r   c                 0    [         R                  X5        U $ )a  Apply pruning reparametrization without pruning any units.

Applies pruning reparametrization to the tensor corresponding to the
parameter called ``name`` in ``module`` without actually pruning any
units. Modifies module in place (and also return the modified module)
by:

1) adding a named buffer called ``name+'_mask'`` corresponding to the
   binary mask applied to the parameter ``name`` by the pruning method.
2) replacing the parameter ``name`` by its pruned version, while the
   original (unpruned) parameter is stored in a new parameter named
   ``name+'_orig'``.

Note:
    The mask is a tensor of ones.

Args:
    module (nn.Module): module containing the tensor to prune.
    name (str): parameter name within ``module`` on which pruning
            will act.

Returns:
    module (nn.Module): modified (i.e. pruned) version of the input module

Examples:
    >>> # xdoctest: +SKIP
    >>> m = prune.identity(nn.Linear(2, 3), 'bias')
    >>> print(m.bias_mask)
    tensor([1., 1., 1.])
)r   rM   )r   r2   s     r   identityr   2  s    > NN6 Mr   c                 2    [         R                  XU5        U $ )a  Prune tensor by removing random (currently unpruned) units.

Prunes tensor corresponding to parameter called ``name`` in ``module``
by removing the specified ``amount`` of (currently unpruned) units
selected at random.
Modifies module in place (and also return the modified module) by:

1) adding a named buffer called ``name+'_mask'`` corresponding to the
   binary mask applied to the parameter ``name`` by the pruning method.
2) replacing the parameter ``name`` by its pruned version, while the
   original (unpruned) parameter is stored in a new parameter named
   ``name+'_orig'``.

Args:
    module (nn.Module): module containing the tensor to prune
    name (str): parameter name within ``module`` on which pruning
            will act.
    amount (int or float): quantity of parameters to prune.
        If ``float``, should be between 0.0 and 1.0 and represent the
        fraction of parameters to prune. If ``int``, it represents the
        absolute number of parameters to prune.

Returns:
    module (nn.Module): modified (i.e. pruned) version of the input module

Examples:
    >>> # xdoctest: +SKIP
    >>> m = prune.random_unstructured(nn.Linear(2, 3), 'weight', amount=1)
    >>> torch.sum(m.weight_mask == 0)
    tensor(1)

)r   rM   )r   r2   r   s      r   random_unstructuredr   U  s    B V62Mr   c                 .    [         R                  XX#S9  U $ )aW  Prune tensor by removing units with the lowest L1-norm.

Prunes tensor corresponding to parameter called ``name`` in ``module``
by removing the specified `amount` of (currently unpruned) units with the
lowest L1-norm.
Modifies module in place (and also return the modified module)
by:

1) adding a named buffer called ``name+'_mask'`` corresponding to the
   binary mask applied to the parameter ``name`` by the pruning method.
2) replacing the parameter ``name`` by its pruned version, while the
   original (unpruned) parameter is stored in a new parameter named
   ``name+'_orig'``.

Args:
    module (nn.Module): module containing the tensor to prune
    name (str): parameter name within ``module`` on which pruning
            will act.
    amount (int or float): quantity of parameters to prune.
        If ``float``, should be between 0.0 and 1.0 and represent the
        fraction of parameters to prune. If ``int``, it represents the
        absolute number of parameters to prune.
    importance_scores (torch.Tensor): tensor of importance scores (of same
        shape as module parameter) used to compute mask for pruning.
        The values in this tensor indicate the importance of the corresponding
        elements in the parameter being pruned.
        If unspecified or None, the module parameter will be used in its place.

Returns:
    module (nn.Module): modified (i.e. pruned) version of the input module

Examples:
    >>> # xdoctest: +SKIP
    >>> m = prune.l1_unstructured(nn.Linear(2, 3), 'weight', amount=0.2)
    >>> m.state_dict().keys()
    odict_keys(['bias', 'weight_orig', 'weight_mask'])
r   )r   rM   )r   r2   r   r'   s       r   l1_unstructuredr   z  s$    L V   Mr   c                 2    [         R                  XX#5        U $ )a  Prune tensor by removing random channels along the specified dimension.

Prunes tensor corresponding to parameter called ``name`` in ``module``
by removing the specified ``amount`` of (currently unpruned) channels
along the specified ``dim`` selected at random.
Modifies module in place (and also return the modified module)
by:

1) adding a named buffer called ``name+'_mask'`` corresponding to the
   binary mask applied to the parameter ``name`` by the pruning method.
2) replacing the parameter ``name`` by its pruned version, while the
   original (unpruned) parameter is stored in a new parameter named
   ``name+'_orig'``.

Args:
    module (nn.Module): module containing the tensor to prune
    name (str): parameter name within ``module`` on which pruning
            will act.
    amount (int or float): quantity of parameters to prune.
        If ``float``, should be between 0.0 and 1.0 and represent the
        fraction of parameters to prune. If ``int``, it represents the
        absolute number of parameters to prune.
    dim (int): index of the dim along which we define channels to prune.

Returns:
    module (nn.Module): modified (i.e. pruned) version of the input module

Examples:
    >>> # xdoctest: +SKIP
    >>> m = prune.random_structured(
    ...     nn.Linear(5, 3), 'weight', amount=3, dim=1
    ... )
    >>> columns_pruned = int(sum(torch.sum(m.weight, dim=0) == 0))
    >>> print(columns_pruned)
    3
)r   rM   )r   r2   r   r   s       r   random_structuredr     s    J 65Mr   c           	      0    [         R                  XX#XES9  U $ )aY  Prune tensor by removing channels with the lowest L\ ``n``-norm along the specified dimension.

Prunes tensor corresponding to parameter called ``name`` in ``module``
by removing the specified ``amount`` of (currently unpruned) channels
along the specified ``dim`` with the lowest L\ ``n``-norm.
Modifies module in place (and also return the modified module)
by:

1) adding a named buffer called ``name+'_mask'`` corresponding to the
   binary mask applied to the parameter ``name`` by the pruning method.
2) replacing the parameter ``name`` by its pruned version, while the
   original (unpruned) parameter is stored in a new parameter named
   ``name+'_orig'``.

Args:
    module (nn.Module): module containing the tensor to prune
    name (str): parameter name within ``module`` on which pruning
            will act.
    amount (int or float): quantity of parameters to prune.
        If ``float``, should be between 0.0 and 1.0 and represent the
        fraction of parameters to prune. If ``int``, it represents the
        absolute number of parameters to prune.
    n (int, float, inf, -inf, 'fro', 'nuc'): See documentation of valid
        entries for argument ``p`` in :func:`torch.norm`.
    dim (int): index of the dim along which we define channels to prune.
    importance_scores (torch.Tensor): tensor of importance scores (of same
        shape as module parameter) used to compute mask for pruning.
        The values in this tensor indicate the importance of the corresponding
        elements in the parameter being pruned.
        If unspecified or None, the module parameter will be used in its place.

Returns:
    module (nn.Module): modified (i.e. pruned) version of the input module

Examples:
    >>> from torch.nn.utils import prune
    >>> m = prune.ln_structured(
    ...     nn.Conv2d(5, 3, 2), 'weight', amount=0.3, dim=1, n=float('-inf')
    ... )
r&   )r   rM   )r   r2   r   r   r   r'   s         r   ln_structuredr     s&    R f   Mr   c                    [        U [        5      (       d  [        S5      eUb  UO0 n[        U[        5      (       d  [        S5      e[        R
                  R                  R                  U  VVs/ s H!  u  pEUR                  XE4[        XE5      5      PM#     snn5      n[        R
                  R                  R                  U  VVs/ s H1  u  pE[        XES-   [        R                  " [        XE5      5      5      PM3     snn5      n[        5       nSUl        U" S0 UD6n	SU	l        U	R                  S:w  a  [        SU SU	R                   35      eUR                  U	5        UR                  Xg5      n
S	nU  HC  u  pE[        XE5      nUR!                  5       nXX-    R#                  U5      n[%        XEUS
9  X-  nME     gs  snnf s  snnf )a	  
Globally prunes tensors corresponding to all parameters in ``parameters`` by applying the specified ``pruning_method``.

Modifies modules in place by:

1) adding a named buffer called ``name+'_mask'`` corresponding to the
   binary mask applied to the parameter ``name`` by the pruning method.
2) replacing the parameter ``name`` by its pruned version, while the
   original (unpruned) parameter is stored in a new parameter named
   ``name+'_orig'``.

Args:
    parameters (Iterable of (module, name) tuples): parameters of
        the model to prune in a global fashion, i.e. by aggregating all
        weights prior to deciding which ones to prune. module must be of
        type :class:`nn.Module`, and name must be a string.
    pruning_method (function): a valid pruning function from this module,
        or a custom one implemented by the user that satisfies the
        implementation guidelines and has ``PRUNING_TYPE='unstructured'``.
    importance_scores (dict): a dictionary mapping (module, name) tuples to
        the corresponding parameter's importance scores tensor. The tensor
        should be the same shape as the parameter, and is used for computing
        mask for pruning.
        If unspecified or None, the parameter will be used in place of its
        importance scores.
    kwargs: other keyword arguments such as:
        amount (int or float): quantity of parameters to prune across the
        specified parameters.
        If ``float``, should be between 0.0 and 1.0 and represent the
        fraction of parameters to prune. If ``int``, it represents the
        absolute number of parameters to prune.

Raises:
    TypeError: if ``PRUNING_TYPE != 'unstructured'``

Note:
    Since global structured pruning doesn't make much sense unless the
    norm is normalized by the size of the parameter, we now limit the
    scope of global pruning to unstructured methods.

Examples:
    >>> from torch.nn.utils import prune
    >>> from collections import OrderedDict
    >>> net = nn.Sequential(OrderedDict([
    ...     ('first', nn.Linear(10, 4)),
    ...     ('second', nn.Linear(4, 1)),
    ... ]))
    >>> parameters_to_prune = (
    ...     (net.first, 'weight'),
    ...     (net.second, 'weight'),
    ... )
    >>> prune.global_unstructured(
    ...     parameters_to_prune,
    ...     pruning_method=prune.L1Unstructured,
    ...     amount=10,
    ... )
    >>> print(sum(torch.nn.utils.parameters_to_vector(net.buffers()) == 0))
    tensor(10)

z4global_unstructured(): parameters is not an IterableNz=global_unstructured(): importance_scores must be of type dictr   tempr   zROnly "unstructured" PRUNING_TYPE supported for the `pruning_method`. Found method z	 of type r   r   r   )r-   r   rl   dictrD   nnutilsparameters_to_vectorgetr    rE   r/   r	   r   r0   r   numelview_ascustom_from_mask)
parameterspruning_methodr'   r4   r   r2   relevant_importance_scoresr   r;   r:   
final_maskpointerparam	num_param
param_masks                  r   global_unstructuredr    s   | j(++NOO->-J)PR'..WXX "'!D!D #-	
", !!6.'&2GH",	
" 88>>66 #-	
", F7NEOOGF<Q,RS",	
L !"I#I%f%F Fn,22@1A6K^K^J_a
 	

   ( ''(BQJ G"%KKM	'*=>FFuM
 	J7 	 #E	
	
s   0(G
8G
c                 2    [         R                  XU5        U $ )a  Prune tensor corresponding to parameter called ``name`` in ``module`` by applying the pre-computed mask in ``mask``.

Modifies module in place (and also return the modified module) by:

1) adding a named buffer called ``name+'_mask'`` corresponding to the
   binary mask applied to the parameter ``name`` by the pruning method.
2) replacing the parameter ``name`` by its pruned version, while the
   original (unpruned) parameter is stored in a new parameter named
   ``name+'_orig'``.

Args:
    module (nn.Module): module containing the tensor to prune
    name (str): parameter name within ``module`` on which pruning
        will act.
    mask (Tensor): binary mask to be applied to the parameter.

Returns:
    module (nn.Module): modified (i.e. pruned) version of the input module

Examples:
    >>> from torch.nn.utils import prune
    >>> m = prune.custom_from_mask(
    ...     nn.Linear(5, 3), name='bias', mask=torch.tensor([0, 1, 0])
    ... )
    >>> print(m.bias_mask)
    tensor([0., 1., 0.])

)r   rM   )r   r2   r"   s      r   r  r  u  s    : t,Mr   c                     U R                   R                  5        HN  u  p#[        U[        5      (       d  M  UR                  U:X  d  M.  UR                  U 5        U R                   U	 U s  $    [        SU SU  S35      e)a  Remove the pruning reparameterization from a module and the pruning method from the forward hook.

The pruned parameter named ``name`` remains permanently pruned, and the parameter
named ``name+'_orig'`` is removed from the parameter list. Similarly,
the buffer named ``name+'_mask'`` is removed from the buffers.

Note:
    Pruning itself is NOT undone or reversed!

Args:
    module (nn.Module): module containing the tensor to prune
    name (str): parameter name within ``module`` on which pruning
        will act.

Examples:
    >>> m = random_unstructured(nn.Linear(5, 7), name='weight', amount=0.2)
    >>> m = remove(m, name='weight')
zParameter 'z' of module z/ has to be pruned before pruning can be removed)r+   r,   r-   r   r	   rX   rn   )r   r2   r8   r9   s       r   rX   rX     s{    & ,,224d-..43D3D3LKK))!,M	 5 
dV<x/^_ r   c                     U R                  5        H>  u  pUR                  R                  5        H  n[        U[        5      (       d  M      g   M@     g)a4  Check if a module is pruned by looking for pruning pre-hooks.

Check whether ``module`` is pruned by looking for
``forward_pre_hooks`` in its modules that inherit from the
:class:`BasePruningMethod`.

Args:
    module (nn.Module): object that is either pruned or unpruned

Returns:
    binary answer to whether ``module`` is pruned.

Examples:
    >>> from torch.nn.utils import prune
    >>> m = nn.Linear(5, 7)
    >>> print(prune.is_pruned(m))
    False
    >>> prune.random_unstructured(m, name='weight', amount=0.2)
    >>> print(prune.is_pruned(m))
    True
TF)named_modulesr+   r   r-   r   )r   _	submoduler9   s       r   	is_prunedr    sH    , ,,.00779D$ 122 : / r   c                 D   [        U [        R                  5      (       d  [        SU  S35      e[        U [        R                  5      (       a  U S:  d=  [        U [        R                  5      (       d.  [        U 5      S:  d  [        U 5      S:  a  [        SU  S35      egg)	aP  Validate helper to check the range of amount at init.

Args:
    amount (int or float): quantity of parameters to prune.
        If float, should be between 0.0 and 1.0 and represent the
        fraction of parameters to prune. If int, it represents the
        absolute number of parameters to prune.

Raises:
    ValueError: if amount is a float not in [0, 1], or if it's a negative
        integer.
    TypeError: if amount is neither a float nor an integer.

Note:
    This does not take into account the number of parameters in the
    tensor to be pruned, which is known only at prune.
zInvalid type for amount: z. Must be int or float.r   g      ?g        amount=zG should either be a float in the range [0, 1] or a non-negative integerN)r-   numbersRealrl   Integralfloatrn   r   s    r   r   r     s    $ fgll++3F8;RSTT67++,,!vw//006]S E&MC$7fXde
 	
 %8 1r   c                 p    [        U [        R                  5      (       a  X:  a  [        SU  SU 35      egg)a  Validate that the pruning amount is meaningful wrt to the size of the data.

Validation helper to check that the amount of parameters to prune
is meaningful wrt to the size of the data (`tensor_size`).

Args:
    amount (int or float): quantity of parameters to prune.
        If float, should be between 0.0 and 1.0 and represent the
        fraction of parameters to prune. If int, it represents the
        absolute number of parameters to prune.
    tensor_size (int): absolute number of parameters in the tensor
        to prune.
r  z: should be smaller than the number of parameters to prune=N)r-   r  r  rn   r   r   s     r   r   r     sE    $ &'**++0DfXWXcWde
 	
 1E+r   c                 p    U R                   n[        U5      S::  a  [        SU S[        U5       S35      eg)aM  Validate that the tensor to be pruned is at least 2-Dimensional.

Validation helper to check that the tensor to be pruned is multi-
dimensional, such that the concept of "channels" is well-defined.

Args:
    t (torch.Tensor): tensor representing the parameter to prune

Raises:
    ValueError: if the tensor `t` is not at least 2D.
r*   zZStructured pruning can only be applied to multidimensional tensors. Found tensor of shape z with z dimsN)rA   rf   rn   )r   rA   s     r   r   r     sE     GGE
5zQ?gVCJ<u.
 	
 r   c                 ^    [        U [        R                  5      (       a  U $ [        X-  5      $ )a  Convert the pruning amount from a percentage to absolute value.

Since amount can be expressed either in absolute value or as a
percentage of the number of units/channels in a tensor, this utility
function converts the percentage to absolute value to standardize
the handling of pruning.

Args:
    amount (int or float): quantity of parameters to prune.
        If float, should be between 0.0 and 1.0 and represent the
        fraction of parameters to prune. If int, it represents the
        absolute number of parameters to prune.
    tensor_size (int): absolute number of parameters in the tensor
        to prune.

Returns:
    int: the number of units to prune in the tensor
)r-   r  r  roundr   s     r   r   r     s*    ( &'**++V)**r   c                 `    XR                  5       :  a  [        SU SU R                   35      eg)zValidate that the pruning dimension is within the bounds of the tensor dimension.

Args:
    t (torch.Tensor): tensor representing the parameter to prune
    dim (int): index of the dim along which we define channels to prune
zInvalid index z for tensor of size N)r   r   rA   )r   r   s     r   r   r   6  s1     eeg~>#.B177)LMM r   c                     [        [        U R                  5       5      5      nUS:  a  X2   nUR                  U5        [        R
                  " XUS9nU$ )a"  Compute the L_n-norm of a tensor along all dimensions except for the specified dimension.

The L_n-norm will be computed across all entries in tensor `t` along all dimension
except for the one identified by dim.
Example: if `t` is of shape, say, 3x2x4 and dim=2 (the last dim),
then norm will have Size [4], and each entry will represent the
`L_n`-norm computed using the 3x2=6 entries for each of the 4 channels.

Args:
    t (torch.Tensor): tensor representing the parameter to prune
    n (int, float, inf, -inf, 'fro', 'nuc'): See documentation of valid
        entries for argument p in torch.norm
    dim (int): dim identifying the channels to prune

Returns:
    norm (torch.Tensor): L_n norm computed across all dimensions except
        for `dim`. By construction, `norm.shape = t.shape[-1]`.
r   )pr   )listr   r   rX   rD   r   )r   r   r   dimsr   s        r   r   r   A  sG    ( aeegD
QwiKK::a$'DKr   rq   )r^   r  abcr   r   collections.abcr   rD   r   r/   r   r   r   r   r   r   r   r   r   r   r   r  r  rX   r  r   r   r   r   r   r   r   r   r   <module>r+     s      # $ x1 x1vO( Od+  +28:* 8:v?
& ?
DfC( fCR~
$ ~
B6& 66 F"J)X&R,^tnB<:
<
0
*+4Nr   