
    _-Ph2                     z    d Z ddlZddlmZmZ ddlmZ ddlm	Z	 ddl
mZ ddZd	 ZddZddZd ZddZddZdS )a  Functions to compute C/F splittings for use in Classical AMG.

Overview
--------
A C/F splitting is a partitioning of the nodes in the graph of as connection
matrix (denoted S for strength) into sets of C (coarse) and F (fine) nodes.
The C-nodes are promoted to the coarser grid while the F-nodes are retained
on the finer grid.  Ideally, the C-nodes, which represent the coarse-level
unknowns, should be far fewer in number than the F-nodes.  Furthermore,
algebraically smooth error must be well-approximated by the coarse level
degrees of freedom.


Representation
--------------
C/F splitting is represented by an array with ones for all the C-nodes
and zeros for the F-nodes.


C/F Splitting Methods
---------------------
RS : Original Ruge-Stuben method
    - Produces good C/F splittings.
    - May produce AMG hierarchies with relatively high operator complexities.
    - See References [1] and [4]

PMIS: Parallel Modified Independent Set
    - Very fast construction with low operator complexity.
    - Convergence can deteriorate with increasing problem
      size on structured meshes.
    - Uses method similar to Luby's Maximal Independent Set algorithm.
    - See References [1] and [3]

PMISc: Parallel Modified Independent Set in Color
    - Fast construction with low operator complexity.
    - Better scalability than PMIS on structured meshes.
    - Augments random weights with a (graph) vertex coloring
    - See References [1]

CLJP: Cleary-Luby-Jones-Plassmann
    - Parallel method with cost and complexity comparable to Ruge-Stuben.
    - Convergence can deteriorate with increasing problem
      size on structured meshes.
    - See References [1] and [2]

CLJP-c: Cleary-Luby-Jones-Plassmann in Color
    - Parallel method with cost and complexity comparable to Ruge-Stuben.
    - Better scalability than CLJP on structured meshes.
    - See References [1]


Summary
-------
In general, methods that use a graph coloring perform better on structured
meshes [1].  Unstructured meshes do not appear to benefit substantially
from coloring.

    ========  ========  ========  ==========
     method   parallel  in color     cost
    ========  ========  ========  ==========
       RS        no        no      moderate
      PMIS      yes        no      very low
      PMISc     yes       yes        low
      CLJP      yes        no      moderate
      CLJPc     yes       yes      moderate
    ========  ========  ========  ==========


References
----------
..  [1] Cleary AJ, Falgout RD, Henson VE, Jones JE.
    "Coarse-grid selection for parallel algebraic multigrid"
    Proceedings of the 5th International Symposium on Solving Irregularly
    Structured Problems in Parallel. Springer: Berlin, 1998; 104-115.

..  [2] David M. Alber and Luke N. Olson
    "Parallel coarse-grid selection"
    Numerical Linear Algebra with Applications 2007; 14:611-643.

..  [3] Hans De Sterck, Ulrike M Yang, and Jeffrey J Heys
    "Reducing complexity in parallel algebraic multigrid preconditioners"
    SIAM Journal on Matrix Analysis and Applications 2006; 27:1019-1039.

..  [4] Ruge JW, Stuben K.
    "Algebraic multigrid (AMG)"
    In Multigrid Methods, McCormick SF (ed.),
    Frontiers in Applied Mathematics, vol. 3.
    SIAM: Philadelphia, PA, 1987; 73-130.

    N)
csr_matrixisspmatrix_csr)vertex_coloring)amg_core)remove_diagonalFc           	         t          |           st          d          t          |           } | j                                        }t          j        | j        d         d          }t          j        | j        d         fd          }t          j
        | j        d         | j        | j        |j        |j        ||           |r,t          j        | j        d         | j        | j        |           |S )a  Compute a C/F splitting using Ruge-Stuben coarsening.

    Parameters
    ----------
    S : csr_matrix
        Strength of connection matrix indicating the strength between nodes i
        and j (S_ij)
    second_pass : bool, default False
        Perform second pass of classical AMG coarsening. Can be important for
        classical AMG interpolation. Typically not done in parallel (e.g. Hypre).

    Returns
    -------
    splitting : ndarray
        Array of length of S of ones (coarse) and zeros (fine)

    Examples
    --------
    >>> from pyamg.gallery import poisson
    >>> from pyamg.classical.split import RS
    >>> S = poisson((7,), format='csr') # 1D mesh with 7 vertices
    >>> splitting = RS(S)

    See Also
    --------
    amg_core.rs_cf_splitting

    References
    ----------
    .. [1] Ruge JW, Stuben K.  "Algebraic multigrid (AMG)"
       In Multigrid Methods, McCormick SF (ed.),
       Frontiers in Applied Mathematics, vol. 3.
       SIAM: Philadelphia, PA, 1987; 73-130.

    expected csr_matrixr   intcdtype)r   	TypeErrorr   Ttocsrnpemptyshapezerosr   rs_cf_splittingindptrindicesrs_cf_splitting_pass2)Ssecond_passr   	splitting	influences        U/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/pyamg/classical/split.pyRSr   c   s    H ! /-...A			A6222I!'!*f555IQWQZXqyXqy&&	( ( (
  =&qwqz18'(y)	= 	= 	=     c                 l    t          |           } t          |           \  }}} }~ ~t          ||          S )a6  C/F splitting using the Parallel Modified Independent Set method.

    Parameters
    ----------
    S : csr_matrix
        Strength of connection matrix indicating the strength between nodes i
        and j (S_ij)

    Returns
    -------
    splitting : ndarray
        Array of length of S of ones (coarse) and zeros (fine)

    Examples
    --------
    >>> from pyamg.gallery import poisson
    >>> from pyamg.classical.split import PMIS
    >>> S = poisson((7,), format='csr') # 1D mesh with 7 vertices
    >>> splitting = PMIS(S)

    See Also
    --------
    MIS

    References
    ----------
    .. [6] Hans De Sterck, Ulrike M Yang, and Jeffrey J Heys
       "Reducing complexity in parallel algebraic multigrid preconditioners"
       SIAM Journal on Matrix Analysis and Applications 2006; 27:1019-1039.

    r   _preprocessMIS)r   weightsGr   s       r   PMISr%      s9    @ 	A"1~~GQ1	1q'??r   JPc                 p    t          |           } t          | |          \  }}} }~ ~t          ||          S )ah  C/F splitting using Parallel Modified Independent Set (in color).

    PMIS-c, or PMIS in color, improves PMIS by perturbing the initial
    random weights with weights determined by a vertex coloring.

    Parameters
    ----------
    S : csr_matrix
        Strength of connection matrix indicating the strength between nodes i
        and j (S_ij)
    method : string
        Algorithm used to compute the initial vertex coloring:
            * 'MIS' - Maximal Independent Set
            * 'JP'  - Jones-Plassmann (parallel)
            * 'LDF' - Largest-Degree-First (parallel)

    Returns
    -------
    splitting : array
        Array of length of S of ones (coarse) and zeros (fine)

    Examples
    --------
    >>> from pyamg.gallery import poisson
    >>> from pyamg.classical.split import PMISc
    >>> S = poisson((7,), format='csr') # 1D mesh with 7 vertices
    >>> splitting = PMISc(S)

    See Also
    --------
    MIS

    References
    ----------
    .. [7] David M. Alber and Luke N. Olson
       "Parallel coarse-grid selection"
       Numerical Linear Algebra with Applications 2007; 14:611-643.

    )coloring_methodr    )r   methodr#   r$   r   s        r   PMIScr*      s@    P 	A"1f===GQ1	1q'??r   c           	      R   t          |           st          d          t          |           } d}|rd}| j                                        }t          j        | j        d         d          }t          j	        | j        d         | j
        | j        |j
        |j        ||           |S )a4  Compute a C/F splitting using the parallel CLJP algorithm.

    Parameters
    ----------
    S : csr_matrix
        Strength of connection matrix indicating the strength between nodes i
        and j (S_ij)
    color : bool
        use the CLJP coloring approach

    Returns
    -------
    splitting : array
        Array of length of S of ones (coarse) and zeros (fine)

    Examples
    --------
    >>> from pyamg.gallery import poisson
    >>> from pyamg.classical.split import CLJP
    >>> S = poisson((7,), format='csr') # 1D mesh with 7 vertices
    >>> splitting = CLJP(S)

    See Also
    --------
    MIS, PMIS, CLJPc

    References
    ----------
    .. [8] David M. Alber and Luke N. Olson
       "Parallel coarse-grid selection"
       Numerical Linear Algebra with Applications 2007; 14:611-643.

    r	   r      r
   r   )r   r   r   r   r   r   r   r   r   cljp_naive_splittingr   r   )r   colorcoloridr   r   s        r   CLJPr0      s    D ! /-...AG 			A6222I!!'!*"#(AI"#(AI"+")	+ + + r   c                 B    t          |           } t          | d          S )a  Compute a C/F splitting using the parallel CLJP-c algorithm.

    CLJP-c, or CLJP in color, improves CLJP by perturbing the initial
    random weights with weights determined by a vertex coloring.

    Parameters
    ----------
    S : csr_matrix
        Strength of connection matrix indicating the strength between nodes i
        and j (S_ij)

    Returns
    -------
    splitting : array
        Array of length of S of ones (coarse) and zeros (fine)

    Examples
    --------
    >>> from pyamg.gallery import poisson
    >>> from pyamg.classical.split import CLJPc
    >>> S = poisson((7,), format='csr') # 1D mesh with 7 vertices
    >>> splitting = CLJPc(S)

    See Also
    --------
    MIS, PMIS, CLJP

    References
    ----------
    .. [1] David M. Alber and Luke N. Olson
       "Parallel coarse-grid selection"
       Numerical Linear Algebra with Applications 2007; 14:611-643.

    T)r.   )r   r0   )r   s    r   CLJPcr2   %  s%    F 	Ar   c                    t          |           st          d          t          |           } t          j        | j        d         d          }d|dd<   t          j        }|) || j        d         | j        | j	        ddd||d	  	         n=|dk     rt          d           || j        d         | j        | j	        ddd|||	  	         |S )	a  Compute a maximal independent set of a graph in parallel.

    Parameters
    ----------
    G : csr_matrix
        Matrix graph, G[i,j] != 0 indicates an edge
    weights : ndarray
        Array of weights for each vertex in the graph G
    maxiter : int
        Maximum number of iterations (default: None)

    Returns
    -------
    mis : array
        Array of length of G of zeros/ones indicating the independent set

    Examples
    --------
    >>> from pyamg.gallery import poisson
    >>> from pyamg.classical.split import MIS
    >>> import numpy as np
    >>> G = poisson((7,), format='csr') # 1D mesh with 7 vertices
    >>> w = np.ones((G.shape[0],1)).ravel()
    >>> mis = MIS(G,w)

    See Also
    --------
    fn = amg_core.maximal_independent_set_parallel

    r	   r   r
   r   Nr,   zmaxiter must be >= 0)r   r   r   r   r   r   r    maximal_independent_set_parallelr   r   
ValueError)r$   r#   maxitermisfns        r   r"   r"   L  s    > ! /-...A
(171:V
,
,
,CCF		2B
171:qxB1c7BGGGGQ;;3444
171:qxB1c7GLLLJr   c                    t          |           st          d          | j        d         | j        d         k    rt          d| j                   | j        d         }t	          t          j        | j        d          | j        | j	        f||f          } | j
                                        }| |z   }d|j        dd<   t          j        |                    d	                    }|0|t
          j                            t#          |                    z   }n\t%          ||          }|                                dz   }|t
          j                            t#          |                    |z   |z  z   }||| |fS )
a  Preprocess splitting functions.

    Parameters
    ----------
    S : csr_matrix
        Strength of connection matrix
    method : string
        Algorithm used to compute the vertex coloring:
            * 'MIS' - Maximal Independent Set
            * 'JP'  - Jones-Plassmann (parallel)
            * 'LDF' - Largest-Degree-First (parallel)

    Returns
    -------
    weights: ndarray
        Weights from a graph coloring of G
    S : csr_matrix
        Strength matrix with ones
    T : csr_matrix
        transpose of S
    G : csr_matrix
        union of S and T

    Notes
    -----
    Performs the following operations:
        - Checks input strength of connection matrix S
        - Replaces S.data with ones
        - Creates T = S.T in CSR format
        - Creates G = S union T in CSR format
        - Creates random weights
        - Augments weights with graph coloring (if use_color == True)

    r	   r   r,   zexpected square matrix, shape=int8r   )r   N)axis)r   r   r   r6   r   r   onesnnzr   r   r   r   dataravelsumrandomrandlenr   max)r   r(   Nr   r$   r#   coloring
num_colorss           r   r!   r!     sa   F ! /-...wqzQWQZC!'CCDDD	
ABGAE000!)QXFQ	! 	! 	!A			A	AAAF111Ihquu!u}}%%G BINN3w<<888"1o66\\^^a'
binnS\\::XE    Q1r   )F)r&   )N)__doc__numpyr   scipy.sparser   r   pyamg.graphr   pyamgr   pyamg.util.utilsr   r   r%   r*   r0   r2   r"   r!    r   r   <module>rP      s   Y Yt     3 3 3 3 3 3 3 3 ' ' ' ' ' '       , , , , , ,5 5 5 5p# # #L+ + + +\3 3 3 3l$ $ $N0 0 0 0h< < < < < <r   