
    ϑiPW                       S r SSKJr  SSKrSSKrSSKrSSKJr  SSKJ	r	  SSK
JrJr  SSKr\(       a  SSKJ
r  / r " S S\5      r " S	 S
\5      rSS jrS rSS jrSS jrS rSS jr        SS jr\R6                  " 5       q0 qS rSS jr\R@                  SS4         SS jjr!\RD                  SS4         SS jjr#g)z#
Utilities of Auto SParsity (ASP).
    )annotationsN)Enum)permutations)TYPE_CHECKINGAnyc                  $    \ rS rSrSrSrSrSrSrg)MaskAlgo$   z
A collection of all mask generating algorithms.
There currently are three algorithms, `MASK_1D`, `MASK_2D_GREEDY` and `MASK_2D_BEST`
get_mask_1dget_mask_2d_greedyget_mask_2d_best N)	__name__
__module____qualname____firstlineno____doc__MASK_1DMASK_2D_GREEDYMASK_2D_BEST__static_attributes__r       Y/var/www/html/banglarbhumi/venv/lib/python3.13/site-packages/paddle/incubate/asp/utils.pyr	   r	   $   s    
 G)N%Lr   r	   c                  4    \ rS rSrSrSrSr\SS j5       rSr	g)	CheckMethod/   zn
A collection of all sparsity checking approaches.
There currently are two methods, `CHECK_1D` and `CHECK_2D`
check_mask_1dcheck_mask_2dc                    [        U [        5      (       d   S5       eU [        R                  :X  a  [        R                  $ [        R
                  $ )a}  
Get sparsity checking method by mask generating algorithm.

Args:
    mask_algo (MaskAlgo): The algorithm of mask generating.
Returns:
    CheckMethod: The corresponded sparsity checking method.
Examples:
    .. code-block:: python

        >>> import numpy as np
        >>> from paddle.incubate.asp import CheckMethod, MaskAlgo
        >>> print(CheckMethod.get_checking_method(MaskAlgo.MASK_1D))
        CheckMethod.CHECK_1D
        >>> print(CheckMethod.get_checking_method(MaskAlgo.MASK_2D_GREEDY))
        CheckMethod.CHECK_2D
        >>> print(CheckMethod.get_checking_method(MaskAlgo.MASK_2D_BEST))
        CheckMethod.CHECK_2D
z!mask_algo should be MaskAlgo type)
isinstancer	   r   r   CHECK_1DCHECK_2D)	mask_algos    r   get_checking_methodCheckMethod.get_checking_method8   sI    * )X.. 	
/	
. (((''''''r   r   N)r#   r	   returnr   )
r   r   r   r   r   r!   r"   staticmethodr$   r   r   r   r   r   r   /   s%    
 HH( (r   r   c                    U R                  5       n[        [        R                  " U5      S   R                  5      UR                  -  $ )a  

Return the density of the input tensor.

Args:
    x (nparray): The input tensor.

Returns:
    float, The density of :attr:`x`.

Examples:
    .. code-block:: python

        >>> import paddle
        >>> import numpy as np

        >>> x = np.array([[0, 1, 3, 0],
        ...             [1, 1, 0, 1]])
        >>> out = paddle.incubate.asp.calculate_density(x)
        >>> print(out)
        0.625

r   )flattenfloatnpnonzerosize)xx_flatteneds     r   calculate_densityr0   V   s9    0 ))+KK(+001K4D4DDDr   c                   [        U R                  5      S:X  d   S5       eU R                  S   U-  nU R                  S   U-  S:  an  [        R                  " U R                  S   U R                  S   X-
  -   45      nXSS2SU R                  S   24'   UR                  nUR	                  SU5      U4$ U R	                  SU5      U R                  4$ )a  
Reshape the input 2D matrix to shape (-1, m).
If the second dimension of :attr:`mat` is not a multiples of :attr:`m`,
then this function would pad the remainder with 0 before reshaping.

.. math::

    remainder = mat.shape[1] % m

Args:
    mat (nparray): The input 2D matrix.
    m (int): The second dimension of reshaped matrix.
Returns:
    tuple: A pair of the reshaped and padded matrix and the shape of padded matrix (non-reshaping).
   $The input mat should be a 2D matrix!   r   N)lenshaper+   zerosreshape)matm	remainder
mat_paddedr7   s        r   _reshape_1dr>   r   s      syy>QF FF		!q I
yy|a!XXsyy|SYYq\Q]-KLM
(+1n		!n$%  !!"a(%//{{2q!399,,r   c                   [        U R                  5      S::  a,  [        U R                  SU R                  S   5      U5      u  p4O[        X5      u  p4U H.  n[        R
                  " U5      S   R                  X!-
  :  d  M.    g   g)aj  
Check if every row of the input matrix :attr:`mat` is in 1D `n:m` sparse pattern.
This function would pad the second dimension of :attr:`mat` by zero
to be a multiples of :attr:`m` if necessary.

1D `n:m` sparse pattern: At least :attr:`n` zeros in every :math:`1 \times m` block.

Args:
    mat (nparray): The input matrix.
    n (int): n of `n:m` sparse pattern.
    m (int): m of `n:m` sparse pattern.
Returns:
    bool: True if every row of :attr:`mat` is in 1D n:m sparse pattern, else False.
Examples:
    .. code-block:: python

      >>> import numpy as np
      >>> import paddle.incubate.asp as sparsity

      >>> x = np.array([[0, 1, 3, 0],
      ...               [1, 0, 0, 1]])
      >>> y = sparsity.check_mask_1d(x, 2, 4)
      >>> print(y)
      True

      >>> x = np.array([[0, 1, 5, 4],
      ...               [1, 0, 0, 1]])
      >>> y = sparsity.check_mask_1d(x, 2, 4)
      >>> print(y)
      False

      >>> # x would be padded to shape (2, 8)
      >>> x = np.array([[0, 1, 0, 4, 6],
      ...               [1, 0, 0, 1, 7]])
      >>> y = sparsity.check_mask_1d(x, 2, 4)
      >>> print(y)
      True
r4   r   FT)r6   r7   r>   r9   r+   r,   r-   )r:   nr;   mat_flattenr7   sub_mats         r   r   r      sv    N 399~(Q		!)EqIU(0::gq!&&!%0  r   c                   [        X5      u  p4[        R                  " U5      n[        R                  " U 5      n[        UR                  S   5       HH  nX7   n[        R
                  " [        R                  " U5      5      n	SXWU	SU R                  5       4'   MJ     UR                  U5      nUSS2SU R                  S   24   USS2SS24'   U$ )ab  
Generate 1D `n:m` sparse pattern mask of the input matrix :attr:`mat`
in row-directory. This function would pad the second dimension of :attr:`mat`
by zero to be a multiples of :attr:`m` before mask generation.

1D `n:m` sparse pattern: At least :attr:`n` zeros in every :math:`1 \times m` block.

Args:
    mat (nparray): The input matrix.
    n (int): n of `n:m` sparse pattern.
    m (int): m of `n:m` sparse pattern.
Returns:
    nparray: The 1D `n:m` sparse mask of :attr:`mat`.
Examples:
    .. code-block:: python

      >>> import numpy as np
      >>> import paddle.incubate.asp as sparsity
      >>> mat = np.array([[0, 1, 5, 4],
      ...                 [2, 7, 3, 6]])
      >>> mask = sparsity.get_mask_1d(mat, 2, 4)
      >>> print(mask)
      [[0 0 1 1]
      [0 1 0 1]]
      >>> y = sparsity.check_mask_1d(mask, 2, 4)
      >>> print(y)
      True
r   Nr4   )	r>   r+   	ones_likeranger7   argsortabsolutetolistr9   )
r:   r@   r;   rA   r7   mask_flattenmaskirB   min_order_indicess
             r   r   r      s    : %S,K<<,L<<D;$$Q'(.JJr{{7';<:;)"1-44667 )  ''.La399Q</0DAJKr   c                   [        U R                  5      S:X  d   S5       eU R                  S   U-  nU R                  S   U-  nUS:X  a  U R                  S   OU R                  S   X-
  -   US:X  a  U R                  S   OU R                  S   X-
  -   4n[        R                  " U5      nXSU R                  S   2SU R                  S   24'   [        R                  " U5      R                  SX-  5      nSn[        SUR                  S   U5       Ha  nX-   n	[        SUR                  S   U5       H<  n
X-   n[        R                  " XXU	2X24   R                  S5      5      nXU'   US-  nM>     Mc     XeR                  4$ )a  
Reshape the input 2D matrix to shape (-1, :math:`m \times m`).
In each dimension of :attr:`mat`, if it is not a multiples of :attr:`m`,
then this function would pad the remainder with 0 before reshaping.

.. math::

    remainder_0 = mat.shape[0] % m \\
    remainder_1 = mat.shape[1] % m

Args:
    mat (nparray): The input 2D matrix.
    m (int): The square root of second dimension of reshaped matrix.
Returns:
    tuple: A pair of the reshaped and padded matrix and the shape of padded matrix (non-reshaping).
r2   r3   r   r4   Nr5   )r6   r7   r+   r8   emptyr9   rE   squeeze)r:   r;   remainder_0remainder_1	new_shaper=   rA   curr_idx	row_startrow_end	col_startcol_endrB   s                r   _reshape_2drX      s   " syy>QF FF))A,"K))A,"K $q(		!ciilao.N#q(		!ciilao.NI )$J14~1~~1~-.((9%--b!%8KH1j..q115	-q*"2"21"5q9ImGjjW,i.??@HHLG %,!MH : 6 ((((r   c           	     x   [        X5      u  p4U H  n[        R                  " [        R                  " UR	                  X"5      5      5      S:  n[        R
                  " [        R
                  " USS9X!-
  :  5      S:w  d  Ms  [        R
                  " [        R
                  " USS9X!-
  :  5      S:w  d  M    g   g)a  
Check if every :math:`m \times m` block of the input matrix :attr:`mat` is in 2D `n:m` sparse pattern.
This function would pad each dimension of :attr:`mat` by zero to be a multiples of
:attr:`m` if necessary.

2D `n:m` sparse pattern: At least :math:`n \times n` zeros in every :math:`m \times m` block
under the constraint of at least :attr:`n` zeros for each row and column.

Args:
    mat (nparray): The input matrix.
    n (int): n of `n:m` sparse pattern.
    m (int): m of `n:m` sparse pattern.
Returns:
    bool: True if  every :math:`m \times m` block of the input matrix :attr:`mat` is in 2D `n:m` sparse pattern, else False.
Examples:
    .. code-block:: python

      >>> import numpy as np
      >>> import paddle.incubate.asp as sparsity

      >>> x = np.array([[0, 8, 9, 0],
      ...               [9, 0, 0, 10],
      ...               [5, 0, 0, 6],
      ...               [0, 4, 6, 0]])
      >>> y = sparsity.check_mask_2d(x, 2, 4)
      >>> print(y)
      True

      >>> x = np.array([[0, 8, 0, 9],
      ...               [9, 0, 0, 10],
      ...               [0, 5, 0, 6],
      ...               [0, 4, 6, 0]])
      >>> y = sparsity.check_mask_2d(x, 2, 4)
      >>> print(y)
      True

      >>> # x would be padded to shape (8, 8)
      >>> x = np.array([[0, 8, 0, 9],
      ...               [9, 0, 7, 0],
      ...               [0, 5, 0, 6],
      ...               [3, 0, 6, 0],
      ...               [1, 1, 0, 1]])
      >>> y = sparsity.check_mask_2d(x, 2, 4)
      >>> print(y)
      True
r   r4   axisFT)rX   r+   rG   rO   r9   sum)r:   r@   r;   r=   r7   rB   sub_masks          r   r   r     s    ^ $C+J;;rzz'//!*?@AAEFF266(+qu56!;FF266(+qu56!;  r   c                   [        X5      u  p4[        R                  " U5      R                  SX"5      n[	        [        U5      5       GH  n[        R                  " [        R                  " X6   5      5      n[        R                  " XV   5      n[        R                  " U5      n	U	 V
s/ s H  n
[        X-  5      X-  4PM     nn
[        R                  " 5       n[        R                  " 5       n[	        [        U	5      S-
  SS5       HI  nX   nXS      U:X  d  XS      U:X  a  M  SXS   US   4'   XS   ==   S-  ss'   XS   ==   S-  ss'   MK     GM     [        R                  " U5      nSn[	        SUS   U5       H7  nUU-   n[	        SUS   U5       H  nUU-   nUU   UUU2UU24'   US-  nM     M9     USU R                  S   2SU R                  S   24   $ s  sn
f )a  
Greedily generate 2D `n:m` sparse pattern mask of the input matrix :attr:`mat`.
This function would pad each dimension of :attr:`mat` by zero to be a multiples of :attr:`m` before mask generation.

2D `n:m` sparse pattern: At least :math:`n \times n` zeros in every :math:`m \times m` block
under the constraint of at least :attr:`n` zeros for each row and column.
Greedily generating: For each :math:`m \times m` block, selecting values to keep in descent order.

Args:
    mat (nparray): The input matrix.
    n (int): n of `n:m` sparse pattern.
    m (int): m of `n:m` sparse pattern.
Returns:
    nparray: The 2D `n:m` sparse mask of :attr:`mat`.
Examples:
    .. code-block:: python

      >>> import numpy as np
      >>> import paddle.incubate.asp as sparsity

      >>> mat = np.array([[9, 8, 3, 7],
      ...                 [9, 2, 1, 10],
      ...                 [5, 1, 3, 6],
      ...                 [2, 4, 6, 1]])
      >>> mask = sparsity.get_mask_2d_greedy(mat, 2, 4)
      >>> print(mask)
      [[1. 1. 0. 0.]
      [1. 0. 0. 1.]
      [0. 0. 1. 1.]
      [0. 1. 1. 0.]]
      >>> y = sparsity.check_mask_2d(mask, 2, 4)
      >>> print(y)
      True
r5   r4   r   g      ?N)rX   r+   
zeros_liker9   rE   r6   rG   rO   rF   intcollectionsCounterrN   r7   )r:   r@   r;   r=   r7   mask_paddedidxrB   r]   min_order_1d_indicesr.   min_order_2d_indicesrow_countercol_counterrK   matrix_entryrJ   rS   rT   rU   rV   rW   s                         r   r   r   N  s   J $C+J--
+33B=KS_%++bjj9:::k./!zz'2)= 
)=ASZ)= 	  
 "))+!))+s/014b"=A/2LO,1O,19<H!_l1o56Q(A-(Q(A-( > &, 88E?DH1eAh*	a-q%(A.I!mG9DX9ND7"Ig$556MH / + #))A,#))A,.//3 
s   *G$c           
     t   U SU  3nU[         ;   a	  [         U   $ [        R                  " U5      nSUSU & [        [	        [        UR                  5       5      5      5      nX3-   n[        R                  " [        [	        [        X15      5      5      5      nUR                  SS9U :*  R                  SS9U:H  R                  5       S   R                  S5      n[        R                  " UR                  S   X45      nX4SS    USS& [        R                  5         U[         U'   [        R                  5         U$ )a  
Compute all valid 2D `n:m` sparse patterns.

2D `n:m` sparse pattern: At least :math:`n \times n` zeros in every :math:`m \times m` block
under the constraint of at least :attr:`n` zeros for each row and column.

Args:
    n (int): n of `n:m` sparse pattern.
    m (int): m of `n:m` sparse pattern.
Returns:
    dictionary: A dictionary with key: *m_n* (string) and value: all valid 2D `n:m` sparse patterns.
_r4   NrZ   r   r5   )_valid_2d_patternsr+   r8   listsetr   rH   asarrayr\   r,   r9   rN   r7   _valid_2d_patterns_lockacquirerelease)r@   r;   	valid_keypatternsvalidvalid_patternss         r   _compute_valid_2d_patternsrw     s     #Qqc
I&&!),,88A;!L):;<=&::d3|H'@#ABC lll"a',,!,49WYqWR[ 	
 5;;q>1"89$1X.q'')(69%'')r   c           
     <   [        X5      n[        X5      u  pE[        R                  " U5      R	                  SX"5      n[        R
                  " [        R                  " XCR	                  UR                  S   X"-  5      R                  5      SS9nX7SS    USS& [        R                  " U5      nSn	[        SUS   U5       H2  n
X-   n[        SUS   U5       H  nX-   nXi   XU2X24'   U	S-  n	M     M4     USU R                  S   2SU R                  S   24   $ )aH  
Generate 2D `n:m` sparse pattern mask of the input matrix :attr:`mat`
to form sparse matrix with maximum L1 norm .This function would pad each
dimension of :attr:`mat` by zero to be a multiples of :attr:`m` before mask generation.

2D `n:m` sparse pattern: At least :math:`n \times n` zeros in every :math:`m \times m` block
under the constraint of at least :attr:`n` zeros for each row and column.

*Note*: L1 norm of sparse matrix from `Best` API is greater than or equal to the one from `Greedy`.

Args:
    mat (nparray): The input matrix.
    n (int): n of `n:m` sparse pattern.
    m (int): m of `n:m` sparse pattern.
Returns:
    nparray: The 1D `n:m` sparse mask of :attr:`mat`.
Examples:
    .. code-block:: python

      >>> import numpy as np
      >>> import paddle.incubate.asp as sparsity

      >>> mat = np.array([[2, 8, 9, 9],
      ...                 [9, 1, 3, 9],
      ...                 [5, 6, 3, 9],
      ...                 [2, 4, 6, 9]])
      >>> mask_greedy = sparsity.get_mask_2d_greedy(mat, 2, 4)
      >>> mask_best = sparsity.get_mask_2d_best(mat, 2, 4)
      >>> print("L1 norm of `greedy` sparse matrix", np.multiply(mat, mask_greedy).sum())
      L1 norm of `greedy` sparse matrix 56.0
      >>> print("L1 norm of `best` sparse matrix", np.multiply(mat, mask_best).sum())
      L1 norm of `best` sparse matrix 61.0
r5   r   r4   rZ   N)rw   rX   r+   rD   r9   argmaxmatmulr7   TrN   rE   )r:   r@   r;   rt   rA   r7   rI   pmaxrJ   rS   rT   rU   rV   rW   s                 r   r   r     s   D *!/H$S,K<<,44R>L99
		+//q0A15IKKLD
 Aw'LO88E?DH1eAh*	-q%(A.ImG9E9OD7"I$556MH / + #))A,#))A,.//r   r2      c                   U R                   nU R                  nU R                  [        5      n[	        U[
        5      (       d   S[        U5       35       e[        [        R                  [           UR                  S5      n[        U5      S:X  a  UR                  SUS   5      nO[        U5      S:X  a  UR                  US   US   5      nO[        U5      S:X  a  UR                  US   US   -  US   5      nO[        U5      S:X  a}  UR                  / SQ5      R                  US   US   -  US   -  US   5      nU" XbUS	9nUR                  US   US   US   US   /5      R                  / SQ5      R                  U5      $ [        S
[        U5       35      eU" XbUS	9nUR                  U5      R                  U5      $ )a  
Create `n:m` sparse pattern mask of the input tensor via function given by :attr:`func_name`.
Currently only support tensor with dimension less than or equal to 4.

Args:
    tensor (nparray): The input tensor.
    func_name (MaskAlgo, optional): The function name to generate sparse mask. Default is `MaskAlgo.MASK_1D`. All options please refer to `MaskAlgo`.
    n (int, optional): n of `n:m` sparse pattern. Default is 2.
    m (int, optional): m of `n:m` sparse pattern. Default is 4.
Returns:
    nparray: The `n:m` sparse mask of :attr:`tensor` generated by :attr:`func_name`.
Examples:
    .. code-block:: python

      >>> import numpy as np
      >>> import paddle.incubate.asp as sparsity

      >>> tensor = np.array([[2, 8, 9, 9],
      ...                    [9, 1, 3, 9],
      ...                    [5, 6, 3, 9],
      ...                    [2, 4, 6, 9]])
      >>> mask_1d = sparsity.create_mask(tensor, func_name=sparsity.MaskAlgo.MASK_1D)
      >>> print(mask_1d)
      [[0 0 1 1]
      [1 0 0 1]
      [0 1 0 1]
      [0 0 1 1]]
      >>> mask_2d = sparsity.create_mask(tensor, func_name=sparsity.MaskAlgo.MASK_2D_BEST)
      >>> print(mask_2d)
      [[0 1 1 0]
      [1 0 0 1]
      [1 1 0 0]
      [0 0 1 1]]
zMfunc_name argument of create_mask is only accepted as type MaskAlgo. But got Nr4   r   r2      r}   r   r4   r   r2   r@   r;   gThe dimension of input tensor is not supported in create_mask, Only dimension < 4 is supported but got )r7   dtypeastyper*   r    r	   typegetattrsysmodulesr   valuer6   r9   	transpose
ValueError)	tensor	func_namer@   r;   r7   r   tfuncrJ   s	            r   create_maskr     s   P LLELLEeAi** 		?#	%* 3;;x()//4@D
5zQIIaq"	UqIIeAha)	UqIIeAhq)584	UqKK%--!HuQx%(*E!H
 Aa LL%(E!HeAhaABY|$VE]	
 77:5zlD
 	

 !D<<%%e,,r   c                   U R                   nU R                  [        5      n[        U5      [        :X  d   S[        U5       35       e[        [        R                  [           UR                  S5      n[        U5      S:X  a  UR                  SUS   5      nO[        U5      S:X  a  UR                  US   US   5      nO[        U5      S:X  a  UR                  US   US   -  US   5      nO][        U5      S:X  a7  UR                  / SQ5      R                  US   US   -  US   -  US   /5      nO[        S	[        U5       35      eU" XRUS
9$ )a  
Check if input tensor is in `n:m` sparse pattern via function given by :attr:`func_name`.
Currently only support tensor with dimension less than or equal to 4.

Args:
    tensor (nparray): The input tensor.
    func_name (CheckMethod, optional): The function name to generate sparse mask. Default is `CheckMethod.CHECK_1D`. All options please refer to `CheckMethod`.
    n (int, optional): n of `n:m` sparse pattern. Default is 2.
    m (int, optional): m of `n:m` sparse pattern. Default is 4.
Returns:
    bool: True if tensor pass checking of function given by :attr:`func_name`, else False.
Examples:
    .. code-block:: python

      >>> import numpy as np
      >>> import paddle.incubate.asp as sparsity

      >>> tensor = np.array([[2, 8, 9, 9],
      ...                    [9, 1, 3, 9],
      ...                    [5, 6, 3, 9],
      ...                    [2, 4, 6, 9]])
      >>> mask_1d = sparsity.create_mask(tensor, func_name=sparsity.MaskAlgo.MASK_1D)
      >>> print(mask_1d)
      [[0 0 1 1]
      [1 0 0 1]
      [0 1 0 1]
      [0 0 1 1]]
      >>> y = sparsity.check_sparsity(mask_1d, func_name=sparsity.CheckMethod.CHECK_1D)
      >>> print(y)
      True
      >>> y = sparsity.check_sparsity(mask_1d, func_name=sparsity.CheckMethod.CHECK_2D)
      >>> print(y)
      True
zSfunc_name argument of check_sparsity is only accepted as type CheckMethod. But got Nr4   r   r2   r   r}   r   r   r   )r7   r   r*   r   r   r   r   r   r   r   r6   r9   r   r   )r   r   r@   r;   r7   r   r   s          r   check_sparsityr   H  sL   P LLEeA	?k) 		?#	%) 3;;x()//4@D
5zQIIaq"	UqIIeAha)	UqIIeAhq)584	UqKK%--1Xa 58+U1X6
 77:5zlD
 	

 !r   )r.   npt.NDArray[Any]r&   r*   )r:   r   r@   r`   r;   r`   r&   bool)r:   r   r@   r`   r;   r`   r&   r   )
r   r   r   r	   r@   r`   r;   r`   r&   r   )
r   r   r   r   r@   r`   r;   r`   r&   r   )$r   
__future__r   ra   r   	threadingenumr   	itertoolsr   typingr   r   numpyr+   numpy.typingnpt__all__r	   r   r0   r>   r   r   rX   r   r   Lockrp   rl   rw   r   r   r   r!   r   r   r   r   <module>r      sL   #  
   " % 
&t &$($ $(NE8-8/d'T()V6rF0	F0!F0&)F0F0R $..*  &R50t #**	I-I-I- I- 	I-
 I-\ )11	AAA A 	A
 
Ar   