Example #1
0
def factorized(A):
    """
    Return a function for solving a sparse linear system, with A pre-factorized.

    Parameters
    ----------
    A : (N, N) array_like
        Input. A in CSC format is most efficient. A CSR format matrix will
        be converted to CSC before factorization.

    Returns
    -------
    solve : callable
        To solve the linear system of equations given in `A`, the `solve`
        callable should be passed an ndarray of shape (N,).

    Examples
    --------
    >>> from scipy.sparse.linalg import factorized
    >>> A = np.array([[ 3. ,  2. , -1. ],
    ...               [ 2. , -2. ,  4. ],
    ...               [-1. ,  0.5, -1. ]])
    >>> solve = factorized(A) # Makes LU decomposition.
    >>> rhs1 = np.array([1, -2, 0])
    >>> solve(rhs1) # Uses the LU factors.
    array([ 1., -2., -2.])

    """
    if is_pydata_spmatrix(A):
        A = A.to_scipy_sparse().tocsc()

    if useUmfpack:
        if noScikit:
            raise RuntimeError('Scikits.umfpack not installed.')

        if not isspmatrix_csc(A):
            A = csc_matrix(A)
            warn('splu converted its input to CSC format',
                 SparseEfficiencyWarning)

        A = A.asfptype()  # upcast to a floating point format

        if A.dtype.char not in 'dD':
            raise ValueError("convert matrix data to double, please, using"
                             " .astype(), or set linsolve.useUmfpack = False")

        umf_family, A = _get_umf_family(A)
        umf = umfpack.UmfpackContext(umf_family)

        # Make LU decomposition.
        umf.numeric(A)

        def solve(b):
            return umf.solve(umfpack.UMFPACK_A, A, b, autoTranspose=True)

        return solve
    else:
        return splu(A).solve
Example #2
0
def factorized(A):
    """
    Return a fuction for solving a sparse linear system, with A pre-factorized.

    Parameters
    ----------
    A : (N, N) array_like
        Input.

    Returns
    -------
    solve : callable
        To solve the linear system of equations given in `A`, the `solve`
        callable should be passed an ndarray of shape (N,).

    Examples
    --------
    >>> A = np.array([[ 3. ,  2. , -1. ],
                      [ 2. , -2. ,  4. ],
                      [-1. ,  0.5, -1. ]])

    >>> solve = factorized( A ) # Makes LU decomposition.

    >>> rhs1 = np.array([1,-2,0])
    >>> x1 = solve( rhs1 ) # Uses the LU factors.
    array([ 1., -2., -2.])

    """
    if isUmfpack and useUmfpack:
        if noScikit:
            warn(
                'scipy.sparse.linalg.dsolve.umfpack will be removed,'
                ' install scikits.umfpack instead', DeprecationWarning)

        if not isspmatrix_csc(A):
            A = csc_matrix(A)
            warn('splu requires CSC matrix format', SparseEfficiencyWarning)

        A.sort_indices()
        A = A.asfptype()  #upcast to a floating point format

        if A.dtype.char not in 'dD':
            raise ValueError("convert matrix data to double, please, using"
                             " .astype(), or set linsolve.useUmfpack = False")

        family = {'d': 'di', 'D': 'zi'}
        umf = umfpack.UmfpackContext(family[A.dtype.char])

        # Make LU decomposition.
        umf.numeric(A)

        def solve(b):
            return umf.solve(umfpack.UMFPACK_A, A, b, autoTranspose=True)

        return solve
    else:
        return splu(A).solve
Example #3
0
def spsolve(A, b, permc_spec=2):
    """Solve the sparse linear system Ax=b
    """
    if isspmatrix(b):
        b = b.toarray()

    if b.ndim > 1:
        if max(b.shape) == b.size:
            b = b.squeeze()
        else:
            raise ValueError, "rhs must be a vector (has shape %s)" % (
                b.shape, )

    if not (isspmatrix_csc(A) or isspmatrix_csr(A)):
        A = csc_matrix(A)
        warn('spsolve requires CSC or CSR matrix format',
             SparseEfficiencyWarning)

    A.sort_indices()
    A = A.asfptype()  #upcast to a floating point format

    M, N = A.shape
    if (M != N):
        raise ValueError, "matrix must be square (has shape %s)" % (M, N)
    if M != b.size:
        raise ValueError, "matrix - rhs size mismatch (%s - %s)"\
              % (A.shape, b.size)

    if isUmfpack and useUmfpack:
        if noScikit:
            warn( 'scipy.sparse.linalg.dsolve.umfpack will be removed,'\
                    ' install scikits.umfpack instead', DeprecationWarning )
        if A.dtype.char not in 'dD':
            raise ValueError, "convert matrix data to double, please, using"\
                  " .astype(), or set linsolve.useUmfpack = False"

        b = asarray(b, dtype=A.dtype).reshape(-1)

        family = {'d': 'di', 'D': 'zi'}
        umf = umfpack.UmfpackContext(family[A.dtype.char])
        return umf.linsolve(umfpack.UMFPACK_A, A, b, autoTranspose=True)

    else:
        if isspmatrix_csc(A):
            flag = 1  # CSC format
        else:
            flag = 0  # CSR format

        ftype = superLU_transtabl[A.dtype.char]

        gssv = eval('_superlu.' + ftype + 'gssv')
        b = asarray(b, dtype=A.dtype)

        return gssv(N, A.nnz, A.data, A.indices, A.indptr, b, flag,
                    permc_spec)[0]
Example #4
0
 def __init__(self):
     # List here the functions that can be used to solve equations
     self.convergence_helpers = [
         self.solve_simple, self.solve_homotopy_gmin2,
         self.solve_homotopy_source, None
     ]
     # Allocate UmfPack context
     umfp.configure(assumeSortedIndices=True)
     self._umf = umfp.UmfpackContext(family='di', maxCond=1e20)
     # Set control options. Try to find optimum values?
     self._umf.control[5] = umfp.UMFPACK_STRATEGY_AUTO
     self._umf.control[7] = 1  # Iterative refinement steps
     self._umf.control[16] = umfp.UMFPACK_SCALE_NONE
     # print(self._umf.report_control())
     # Force Symbolic and Numeric factorization
     self.__doSymbolic = True
Example #5
0
    def test_complex_lu(self):
        # Getting factors of complex matrix
        umfpack = um.UmfpackContext("zi")

        for A in self.complex_matrices:
            umfpack.numeric(A)

            (L, U, P, Q, R, do_recip) = umfpack.lu(A)

            L = L.todense()
            U = U.todense()
            A = A.todense()
            if not do_recip:
                R = 1.0 / R
            R = matrix(diag(R))
            P = eye(A.shape[0])[P, :]
            Q = eye(A.shape[1])[:, Q]

            assert_array_almost_equal(P * R * A * Q, L * U)
Example #6
0
    def test_real_int64_lu(self):
        # Getting factors of real matrix with long indices
        umfpack = um.UmfpackContext("dl")

        for A in self.real_int64_matrices:
            umfpack.numeric(A)

            (L, U, P, Q, R, do_recip) = umfpack.lu(A)

            L = L.todense()
            U = U.todense()
            A = A.todense()
            if not do_recip:
                R = 1.0 / R
            R = matrix(diag(R))
            P = eye(A.shape[0])[P, :]
            Q = eye(A.shape[1])[:, Q]

            assert_array_almost_equal(P * R * A * Q, L * U)
Example #7
0
def factorized(A):
    """
    Return a fuction for solving a sparse linear system, with A pre-factorized.

    Examples
    --------
    solve = factorized( A ) # Makes LU decomposition.
    x1 = solve( rhs1 ) # Uses the LU factors.
    x2 = solve( rhs2 ) # Uses again the LU factors.
    """
    if isUmfpack and useUmfpack:
        if noScikit:
            warn(
                'scipy.sparse.linalg.dsolve.umfpack will be removed,'
                ' install scikits.umfpack instead', DeprecationWarning)

        if not isspmatrix_csc(A):
            A = csc_matrix(A)
            warn('splu requires CSC matrix format', SparseEfficiencyWarning)

        A.sort_indices()
        A = A.asfptype()  #upcast to a floating point format

        if A.dtype.char not in 'dD':
            raise ValueError("convert matrix data to double, please, using"
                             " .astype(), or set linsolve.useUmfpack = False")

        family = {'d': 'di', 'D': 'zi'}
        umf = umfpack.UmfpackContext(family[A.dtype.char])

        # Make LU decomposition.
        umf.numeric(A)

        def solve(b):
            return umf.solve(umfpack.UMFPACK_A, A, b, autoTranspose=True)

        return solve
    else:
        return splu(A).solve
Example #8
0
def spsolve(A, b, permc_spec=None, use_umfpack=True):
    """Solve the sparse linear system Ax=b, where b may be a vector or a matrix.

    Parameters
    ----------
    A : ndarray or sparse matrix
        The square matrix A will be converted into CSC or CSR form
    b : ndarray or sparse matrix
        The matrix or vector representing the right hand side of the equation.
        If a vector, b.shape must be (n,) or (n, 1).
    permc_spec : str, optional
        How to permute the columns of the matrix for sparsity preservation.
        (default: 'COLAMD')

        - ``NATURAL``: natural ordering.
        - ``MMD_ATA``: minimum degree ordering on the structure of A^T A.
        - ``MMD_AT_PLUS_A``: minimum degree ordering on the structure of A^T+A.
        - ``COLAMD``: approximate minimum degree column ordering
    use_umfpack : bool, optional
        if True (default) then use umfpack for the solution.  This is
        only referenced if b is a vector and ``scikit-umfpack`` is installed.

    Returns
    -------
    x : ndarray or sparse matrix
        the solution of the sparse linear equation.
        If b is a vector, then x is a vector of size A.shape[1]
        If b is a matrix, then x is a matrix of size (A.shape[1], b.shape[1])

    Notes
    -----
    For solving the matrix expression AX = B, this solver assumes the resulting
    matrix X is sparse, as is often the case for very sparse inputs.  If the
    resulting X is dense, the construction of this sparse result will be
    relatively expensive.  In that case, consider converting A to a dense
    matrix and using scipy.linalg.solve or its variants.

    Examples
    --------
    >>> from scipy.sparse import csc_matrix
    >>> from scipy.sparse.linalg import spsolve
    >>> A = csc_matrix([[3, 2, 0], [1, -1, 0], [0, 5, 1]], dtype=float)
    >>> B = csc_matrix([[2, 0], [-1, 0], [2, 0]], dtype=float)
    >>> x = spsolve(A, B)
    >>> np.allclose(A.dot(x).todense(), B.todense())
    True
    """
    if not (isspmatrix_csc(A) or isspmatrix_csr(A)):
        A = csc_matrix(A)
        warn('spsolve requires A be CSC or CSR matrix format',
             SparseEfficiencyWarning)

    # b is a vector only if b have shape (n,) or (n, 1)
    b_is_sparse = isspmatrix(b)
    if not b_is_sparse:
        b = asarray(b)
    b_is_vector = ((b.ndim == 1) or (b.ndim == 2 and b.shape[1] == 1))

    A.sort_indices()
    A = A.asfptype()  # upcast to a floating point format
    result_dtype = np.promote_types(A.dtype, b.dtype)
    if A.dtype != result_dtype:
        A = A.astype(result_dtype)
    if b.dtype != result_dtype:
        b = b.astype(result_dtype)

    # validate input shapes
    M, N = A.shape
    if (M != N):
        raise ValueError("matrix must be square (has shape %s)" % ((M, N), ))

    if M != b.shape[0]:
        raise ValueError("matrix - rhs dimension mismatch (%s - %s)" %
                         (A.shape, b.shape[0]))

    use_umfpack = use_umfpack and useUmfpack

    if b_is_vector and use_umfpack:
        if b_is_sparse:
            b_vec = b.toarray()
        else:
            b_vec = b
        b_vec = asarray(b_vec, dtype=A.dtype).ravel()

        if noScikit:
            raise RuntimeError('Scikits.umfpack not installed.')

        if A.dtype.char not in 'dD':
            raise ValueError("convert matrix data to double, please, using"
                             " .astype(), or set linsolve.useUmfpack = False")

        umf = umfpack.UmfpackContext(_get_umf_family(A))
        x = umf.linsolve(umfpack.UMFPACK_A, A, b_vec, autoTranspose=True)
    else:
        if b_is_vector and b_is_sparse:
            b = b.toarray()
            b_is_sparse = False

        if not b_is_sparse:
            if isspmatrix_csc(A):
                flag = 1  # CSC format
            else:
                flag = 0  # CSR format

            options = dict(ColPerm=permc_spec)
            x, info = _superlu.gssv(N,
                                    A.nnz,
                                    A.data,
                                    A.indices,
                                    A.indptr,
                                    b,
                                    flag,
                                    options=options)
            if info != 0:
                warn("Matrix is exactly singular", MatrixRankWarning)
                x.fill(np.nan)
            if b_is_vector:
                x = x.ravel()
        else:
            # b is sparse
            Afactsolve = factorized(A)

            if not isspmatrix_csc(b):
                warn(
                    'spsolve is more efficient when sparse b '
                    'is in the CSC matrix format', SparseEfficiencyWarning)
                b = csc_matrix(b)

            # Create a sparse output matrix by repeatedly applying
            # the sparse factorization to solve columns of b.
            data_segs = []
            row_segs = []
            col_segs = []
            for j in range(b.shape[1]):
                bj = b[:, j].A.ravel()
                xj = Afactsolve(bj)
                w = np.flatnonzero(xj)
                segment_length = w.shape[0]
                row_segs.append(w)
                col_segs.append(np.ones(segment_length, dtype=int) * j)
                data_segs.append(np.asarray(xj[w], dtype=A.dtype))
            sparse_data = np.concatenate(data_segs)
            sparse_row = np.concatenate(row_segs)
            sparse_col = np.concatenate(col_segs)
            x = A.__class__((sparse_data, (sparse_row, sparse_col)),
                            shape=b.shape,
                            dtype=A.dtype)

    return x
Example #9
0
def spsolve(A, b, permc_spec=None, use_umfpack=True):
    """Solve the sparse linear system Ax=b, where b may be a vector or a matrix.

    Parameters
    ----------
    A : ndarray or sparse matrix
        The square matrix A will be converted into CSC or CSR form
    b : ndarray or sparse matrix
        The matrix or vector representing the right hand side of the equation.
        If a vector, b.shape must be (n,) or (n, 1).
    permc_spec : str, optional
        How to permute the columns of the matrix for sparsity preservation.
        (default: 'COLAMD')

        - ``NATURAL``: natural ordering.
        - ``MMD_ATA``: minimum degree ordering on the structure of A^T A.
        - ``MMD_AT_PLUS_A``: minimum degree ordering on the structure of A^T+A.
        - ``COLAMD``: approximate minimum degree column ordering [1]_, [2]_.

    use_umfpack : bool, optional
        if True (default) then use UMFPACK for the solution [3]_, [4]_, [5]_,
        [6]_ . This is only referenced if b is a vector and
        ``scikits.umfpack`` is installed.

    Returns
    -------
    x : ndarray or sparse matrix
        the solution of the sparse linear equation.
        If b is a vector, then x is a vector of size A.shape[1]
        If b is a matrix, then x is a matrix of size (A.shape[1], b.shape[1])

    Notes
    -----
    For solving the matrix expression AX = B, this solver assumes the resulting
    matrix X is sparse, as is often the case for very sparse inputs.  If the
    resulting X is dense, the construction of this sparse result will be
    relatively expensive.  In that case, consider converting A to a dense
    matrix and using scipy.linalg.solve or its variants.

    References
    ----------
    .. [1] T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, Algorithm 836:
           COLAMD, an approximate column minimum degree ordering algorithm,
           ACM Trans. on Mathematical Software, 30(3), 2004, pp. 377--380.
           :doi:`10.1145/1024074.1024080`

    .. [2] T. A. Davis, J. R. Gilbert, S. Larimore, E. Ng, A column approximate
           minimum degree ordering algorithm, ACM Trans. on Mathematical
           Software, 30(3), 2004, pp. 353--376. :doi:`10.1145/1024074.1024079`

    .. [3] T. A. Davis, Algorithm 832:  UMFPACK - an unsymmetric-pattern
           multifrontal method with a column pre-ordering strategy, ACM
           Trans. on Mathematical Software, 30(2), 2004, pp. 196--199.
           https://dl.acm.org/doi/abs/10.1145/992200.992206

    .. [4] T. A. Davis, A column pre-ordering strategy for the
           unsymmetric-pattern multifrontal method, ACM Trans.
           on Mathematical Software, 30(2), 2004, pp. 165--195.
           https://dl.acm.org/doi/abs/10.1145/992200.992205

    .. [5] T. A. Davis and I. S. Duff, A combined unifrontal/multifrontal
           method for unsymmetric sparse matrices, ACM Trans. on
           Mathematical Software, 25(1), 1999, pp. 1--19.
           https://doi.org/10.1145/305658.287640

    .. [6] T. A. Davis and I. S. Duff, An unsymmetric-pattern multifrontal
           method for sparse LU factorization, SIAM J. Matrix Analysis and
           Computations, 18(1), 1997, pp. 140--158.
           https://doi.org/10.1137/S0895479894246905T.


    Examples
    --------
    >>> from scipy.sparse import csc_matrix
    >>> from scipy.sparse.linalg import spsolve
    >>> A = csc_matrix([[3, 2, 0], [1, -1, 0], [0, 5, 1]], dtype=float)
    >>> B = csc_matrix([[2, 0], [-1, 0], [2, 0]], dtype=float)
    >>> x = spsolve(A, B)
    >>> np.allclose(A.dot(x).toarray(), B.toarray())
    True
    """

    if is_pydata_spmatrix(A):
        A = A.to_scipy_sparse().tocsc()

    if not (isspmatrix_csc(A) or isspmatrix_csr(A)):
        A = csc_matrix(A)
        warn('spsolve requires A be CSC or CSR matrix format',
             SparseEfficiencyWarning)

    # b is a vector only if b have shape (n,) or (n, 1)
    b_is_sparse = isspmatrix(b) or is_pydata_spmatrix(b)
    if not b_is_sparse:
        b = asarray(b)
    b_is_vector = ((b.ndim == 1) or (b.ndim == 2 and b.shape[1] == 1))

    # sum duplicates for non-canonical format
    A.sum_duplicates()
    A = A.asfptype()  # upcast to a floating point format
    result_dtype = np.promote_types(A.dtype, b.dtype)
    if A.dtype != result_dtype:
        A = A.astype(result_dtype)
    if b.dtype != result_dtype:
        b = b.astype(result_dtype)

    # validate input shapes
    M, N = A.shape
    if (M != N):
        raise ValueError("matrix must be square (has shape %s)" % ((M, N), ))

    if M != b.shape[0]:
        raise ValueError("matrix - rhs dimension mismatch (%s - %s)" %
                         (A.shape, b.shape[0]))

    use_umfpack = use_umfpack and useUmfpack

    if b_is_vector and use_umfpack:
        if b_is_sparse:
            b_vec = b.toarray()
        else:
            b_vec = b
        b_vec = asarray(b_vec, dtype=A.dtype).ravel()

        if noScikit:
            raise RuntimeError('Scikits.umfpack not installed.')

        if A.dtype.char not in 'dD':
            raise ValueError("convert matrix data to double, please, using"
                             " .astype(), or set linsolve.useUmfpack = False")

        umf_family, A = _get_umf_family(A)
        umf = umfpack.UmfpackContext(umf_family)
        x = umf.linsolve(umfpack.UMFPACK_A, A, b_vec, autoTranspose=True)
    else:
        if b_is_vector and b_is_sparse:
            b = b.toarray()
            b_is_sparse = False

        if not b_is_sparse:
            if isspmatrix_csc(A):
                flag = 1  # CSC format
            else:
                flag = 0  # CSR format

            options = dict(ColPerm=permc_spec)
            x, info = _superlu.gssv(N,
                                    A.nnz,
                                    A.data,
                                    A.indices,
                                    A.indptr,
                                    b,
                                    flag,
                                    options=options)
            if info != 0:
                warn("Matrix is exactly singular", MatrixRankWarning)
                x.fill(np.nan)
            if b_is_vector:
                x = x.ravel()
        else:
            # b is sparse
            Afactsolve = factorized(A)

            if not (isspmatrix_csc(b) or is_pydata_spmatrix(b)):
                warn(
                    'spsolve is more efficient when sparse b '
                    'is in the CSC matrix format', SparseEfficiencyWarning)
                b = csc_matrix(b)

            # Create a sparse output matrix by repeatedly applying
            # the sparse factorization to solve columns of b.
            data_segs = []
            row_segs = []
            col_segs = []
            for j in range(b.shape[1]):
                # TODO: replace this with
                # bj = b[:, j].toarray().ravel()
                # once 1D sparse arrays are supported.
                # That is a slightly faster code path.
                bj = b[:, [j]].toarray().ravel()
                xj = Afactsolve(bj)
                w = np.flatnonzero(xj)
                segment_length = w.shape[0]
                row_segs.append(w)
                col_segs.append(np.full(segment_length, j, dtype=int))
                data_segs.append(np.asarray(xj[w], dtype=A.dtype))
            sparse_data = np.concatenate(data_segs)
            sparse_row = np.concatenate(row_segs)
            sparse_col = np.concatenate(col_segs)
            x = A.__class__((sparse_data, (sparse_row, sparse_col)),
                            shape=b.shape,
                            dtype=A.dtype)

            if is_pydata_spmatrix(b):
                x = b.__class__(x)

    return x
Example #10
0
def spsolve(A, b, permc_spec=None, use_umfpack=True):
    """Solve the sparse linear system Ax=b, where b may be a vector or a matrix.

    Parameters
    ----------
    A : ndarray or sparse matrix
        The square matrix A will be converted into CSC or CSR form
    b : ndarray or sparse matrix
        The matrix or vector representing the right hand side of the equation.
        If a vector, b.size must
    permc_spec : str, optional
        How to permute the columns of the matrix for sparsity preservation.
        (default: 'COLAMD')

        - ``NATURAL``: natural ordering.
        - ``MMD_ATA``: minimum degree ordering on the structure of A^T A.
        - ``MMD_AT_PLUS_A``: minimum degree ordering on the structure of A^T+A.
        - ``COLAMD``: approximate minimum degree column ordering
    use_umfpack : bool (optional)
        if True (default) then use umfpack for the solution.  This is
        only referenced if b is a vector.

    Returns
    -------
    x : ndarray or sparse matrix
        the solution of the sparse linear equation.
        If b is a vector, then x is a vector of size A.shape[1]
        If b is a matrix, then x is a matrix of size (A.shape[1], b.shape[1])

    Notes
    -----
    For solving the matrix expression AX = B, this solver assumes the resulting
    matrix X is sparse, as is often the case for very sparse inputs.  If the
    resulting X is dense, the construction of this sparse result will be
    relatively expensive.  In that case, consider converting A to a dense
    matrix and using scipy.linalg.solve or its variants.
    """
    if not (isspmatrix_csc(A) or isspmatrix_csr(A)):
        A = csc_matrix(A)
        warn('spsolve requires A be CSC or CSR matrix format',
             SparseEfficiencyWarning)

    # b.size gives a different answer for dense vs sparse:
    # use prod(b.shape)
    b_is_vector = (max(b.shape) == prod(b.shape))

    if b_is_vector:
        if isspmatrix(b):
            b = b.toarray()
        b = b.squeeze()

    else:
        if isspmatrix(b) and not (isspmatrix_csc(b) or isspmatrix_csr(b)):
            b = csc_matrix(b)
            warn('solve requires b be CSC or CSR matrix format',
                 SparseEfficiencyWarning)
        if b.ndim != 2:
            raise ValueError("b must be either a vector or a matrix")

    A.sort_indices()
    A = A.asfptype()  # upcast to a floating point format

    # validate input shapes
    M, N = A.shape
    if (M != N):
        raise ValueError("matrix must be square (has shape %s)" % ((M, N), ))

    if M != b.shape[0]:
        raise ValueError("matrix - rhs dimension mismatch (%s - %s)" %
                         (A.shape, b.shape[0]))

    use_umfpack = use_umfpack and useUmfpack

    if b_is_vector and isUmfpack and use_umfpack:
        if noScikit:
            warn(
                'scipy.sparse.linalg.dsolve.umfpack will be removed,'
                ' install scikits.umfpack instead', DeprecationWarning)
        if A.dtype.char not in 'dD':
            raise ValueError("convert matrix data to double, please, using"
                             " .astype(), or set linsolve.useUmfpack = False")

        b = asarray(b, dtype=A.dtype).reshape(-1)

        family = {'d': 'di', 'D': 'zi'}
        umf = umfpack.UmfpackContext(family[A.dtype.char])
        x = umf.linsolve(umfpack.UMFPACK_A, A, b, autoTranspose=True)

    elif b_is_vector:
        if isspmatrix_csc(A):
            flag = 1  # CSC format
        elif isspmatrix_csr(A):
            flag = 0  # CSR format
        else:
            A = csc_matrix(A)
            flag = 1

        b = asarray(b, dtype=A.dtype)
        options = dict(ColPerm=permc_spec)
        x = _superlu.gssv(N,
                          A.nnz,
                          A.data,
                          A.indices,
                          A.indptr,
                          b,
                          flag,
                          options=options)[0]
    else:
        # Cover the case where b is also a matrix
        Afactsolve = factorized(A)
        tempj = empty(M, dtype=int)
        x = A.__class__(b.shape)
        for j in range(b.shape[1]):
            xj = Afactsolve(squeeze(b[:, j].toarray()))
            w = where(xj != 0.0)[0]
            tempj.fill(j)
            x = x + A.__class__(
                (xj[w], (w, tempj[:len(w)])), shape=b.shape, dtype=A.dtype)
    return x
Example #11
0
def spsolve(A, b, permc_spec=None, use_umfpack=True):
    """Solve the sparse linear system Ax=b, where b may be a vector or a matrix.

    Parameters
    ----------
    A : ndarray or sparse matrix
        The square matrix A will be converted into CSC or CSR form
    b : ndarray or sparse matrix
        The matrix or vector representing the right hand side of the equation.
        If a vector, b.size must
    permc_spec : str, optional
        How to permute the columns of the matrix for sparsity preservation.
        (default: 'COLAMD')

        - ``NATURAL``: natural ordering.
        - ``MMD_ATA``: minimum degree ordering on the structure of A^T A.
        - ``MMD_AT_PLUS_A``: minimum degree ordering on the structure of A^T+A.
        - ``COLAMD``: approximate minimum degree column ordering
    use_umfpack : bool (optional)
        if True (default) then use umfpack for the solution.  This is
        only referenced if b is a vector.

    Returns
    -------
    x : ndarray or sparse matrix
        the solution of the sparse linear equation.
        If b is a vector, then x is a vector of size A.shape[1]
        If b is a matrix, then x is a matrix of size (A.shape[1], b.shape[1])

    Notes
    -----
    For solving the matrix expression AX = B, this solver assumes the resulting
    matrix X is sparse, as is often the case for very sparse inputs.  If the
    resulting X is dense, the construction of this sparse result will be
    relatively expensive.  In that case, consider converting A to a dense
    matrix and using scipy.linalg.solve or its variants.
    """
    if not (isspmatrix_csc(A) or isspmatrix_csr(A)):
        A = csc_matrix(A)
        warn('spsolve requires A be CSC or CSR matrix format',
                SparseEfficiencyWarning)

    # b is a vector only if b have shape (n,) or (n, 1)
    b_is_sparse = isspmatrix(b)
    if not b_is_sparse:
        b = asarray(b)
    b_is_vector = ((b.ndim == 1) or (b.ndim == 2 and b.shape[1] == 1))

    A.sort_indices()
    A = A.asfptype()  # upcast to a floating point format

    # validate input shapes
    M, N = A.shape
    if (M != N):
        raise ValueError("matrix must be square (has shape %s)" % ((M, N),))

    if M != b.shape[0]:
        raise ValueError("matrix - rhs dimension mismatch (%s - %s)"
                         % (A.shape, b.shape[0]))

    use_umfpack = use_umfpack and useUmfpack

    if b_is_vector and use_umfpack:
        if b_is_sparse:
            b_vec = b.toarray()
        else:
            b_vec = b
        b_vec = asarray(b_vec, dtype=A.dtype).ravel()

        if noScikit:
            raise RuntimeError('Scikits.umfpack not installed.')

        if A.dtype.char not in 'dD':
            raise ValueError("convert matrix data to double, please, using"
                  " .astype(), or set linsolve.useUmfpack = False")

        family = {'d': 'di', 'D': 'zi'}
        umf = umfpack.UmfpackContext(family[A.dtype.char])
        x = umf.linsolve(umfpack.UMFPACK_A, A, b_vec,
                         autoTranspose=True)
    else:
        if b_is_vector and b_is_sparse:
            b = b.toarray()
            b_is_sparse = False

        if not b_is_sparse:
            if isspmatrix_csc(A):
                flag = 1  # CSC format
            else:
                flag = 0  # CSR format

            options = dict(ColPerm=permc_spec)
            x, info = _superlu.gssv(N, A.nnz, A.data, A.indices, A.indptr,
                                    b, flag, options=options)
            if info != 0:
                warn("Matrix is exactly singular", MatrixRankWarning)
                x.fill(np.nan)
            if b_is_vector:
                x = x.ravel()
        else:
            # b is sparse
            Afactsolve = factorized(A)
            tempj = empty(M, dtype=int)
            x = A.__class__(b.shape)

            if not (isspmatrix_csr(b) or isspmatrix_csc(b)):
                warn('spsolve requires sparse b be in CSC or CSR matrix format',
                     SparseEfficiencyWarning)
                b = csc_matrix(b)

            for j in range(b.shape[1]):
                col = b[:, j].toarray()
                xj = Afactsolve(ravel(col))
                w = nonzero(xj)[0]
                tempj.fill(j)
                x = x + A.__class__((xj[w], (w, tempj[:len(w)])),
                                    shape=b.shape, dtype=A.dtype)

    return x
Example #12
0
    def solve(self):
        """ might be broken for superLU """

        if self.USE_UMFPACK:
            import scikits.umfpack as um

        umfpack = um.UmfpackContext(
        )  # Use default 'di' family of UMFPACK routines.
        umfpack.control[um.UMFPACK_STRATEGY_SYMMETRIC] = True
        umfpack.control[um.UMFPACK_PRL] = 0  # not working

        # UGLY
        c = self.standard_c
        A = self.standard_A
        b = self.standard_b

        M, N = A.shape
        converged = False
        """ Initial solution """
        x, lambda_, s = self.find_initial_solution(A, b, c)
        zero_m_m = sp.csc_matrix((M, M))

        iter = 1
        while (not converged):
            if iter > self.max_iter:
                return False, np.nan
            """ Affine-scaling directions: 14.41 general form """
            D = sp.diags(np.sqrt(1 / s)).dot(sp.diags(np.sqrt(x)))  # CORRECT
            D_ = -sp.diags(
                1.0 / np.square(D.diagonal()))  # CORRECT (octave test)

            diag = D_.diagonal()
            pos_inds = np.where(diag >= 0.0)
            neg_inds = np.where(diag < 0.0)

            new_diag = diag[:]
            new_diag[pos_inds] += self.dyn_reg_eps
            new_diag[neg_inds] -= self.dyn_reg_eps
            D_.setdiag(new_diag)

            lhs = sp.bmat([[D_, A.T], [A, zero_m_m]], format='csc')

            lhs_fact = None
            if self.USE_UMFPACK:
                if iter == 1:
                    umfpack.symbolic(lhs)
                    #umfpack.report_symbolic()
                umfpack.numeric(lhs)
                #umfpack.report_numeric()

            else:
                lhs_fact = splin.splu(
                    lhs
                )  #, permc_spec='MMD_AT_PLUS_A', diag_pivot_thresh=0.0, options=dict(SymmetricMode=True)) # superlu

            r_b = A.dot(x) - b
            r_c = A.T.dot(lambda_) + s - c
            r_xs = x * s
            rhs = np.hstack([-r_c + sp.diags(1 / x).dot(r_xs), -r_b])

            sol = None
            if self.USE_UMFPACK:
                sol = umfpack(um.UMFPACK_A, lhs, rhs, autoTranspose=True)
            else:
                sol = lhs_fact.solve(rhs)

            delta_x_aff = sol[:N]
            delta_lambda_aff = sol[N:N + M]

            delta_s_aff = -sp.diags(1 / x).dot(r_xs) - (sp.diags(1 / x).dot(
                sp.diags(s))).dot(delta_x_aff)
            """ Affine-scaling step-length: 14:32 + 14:33 """
            alpha_pri_aff = 1.0
            for i in range(N):
                if delta_x_aff[i] < 0.0 and not np.isclose(
                        delta_x_aff[i], 0.0):  # CRITICAL
                    alpha_pri_aff = min(alpha_pri_aff, -x[i] / delta_x_aff[i])

            alpha_dual_aff = 1.0
            for i in range(M):
                if delta_s_aff[i] < 0.0 and not np.isclose(
                        delta_x_aff[i], 0.0):  # CRITICAL
                    alpha_dual_aff = min(alpha_dual_aff,
                                         -s[i] / delta_s_aff[i])

            mu = 1 / N * np.dot(x, s)
            mu_aff = 1 / N * np.dot(x + alpha_pri_aff * delta_x_aff,
                                    s + alpha_dual_aff * delta_s_aff)
            """ Centering param """
            sigma = (mu_aff / mu)**3
            """ Re-solve for directions """
            r_xs_ = r_xs + delta_x_aff * delta_s_aff - sigma * mu

            # CRITICAL # TODO
            rhs = np.hstack([-r_c + sp.diags(1 / x).dot(r_xs_), -r_b])

            sol_ = None
            if self.USE_UMFPACK:
                sol_ = umfpack(um.UMFPACK_A, lhs, rhs, autoTranspose=True)
            else:
                sol_ = lhs_fact.solve(rhs)

            delta_x = sol_[:N]
            delta_lambda = sol_[N:N + M]
            delta_s = -sp.diags(1 / x).dot(r_xs_) - (sp.diags(1 / x).dot(
                sp.diags(s))).dot(delta_x)
            """ Step-lengths """
            eta = 0.9
            alpha_pri_max = np.inf
            for i in range(N):
                if delta_x[i] < 0.0:
                    alpha_pri_max = min(alpha_pri_max, -x[i] / delta_x[i])
            alpha_dual_max = np.inf
            for i in range(N):
                if delta_s[i] < 0.0:
                    alpha_dual_max = min(alpha_dual_max, -s[i] / delta_s[i])
            alpha_pri = min(1.0, eta * alpha_pri_max)
            alpha_dual = min(1.0, eta * alpha_dual_max)
            """ Update current solution """
            x += alpha_pri * delta_x
            lambda_ += alpha_dual * delta_lambda
            s += alpha_dual * delta_s

            if abs(np.dot(c, x) - np.dot(b, lambda_)) < 1e-5:
                converged = True
            else:
                iter += 1

        return True, np.dot(c, x)
import numpy as np
import matlab_ports
# from scipy.sparse.linalg import spsolve

try:
    from scikits import umfpack
    old_del = umfpack.UmfpackContext.__del__

    def new_del(self):
        try:
            old_del(self)
        except AttributeError:
            pass

    umfpack.UmfpackContext.__del__ = new_del
    UmfpackContext = umfpack.UmfpackContext()
except:
    UmfpackContext = None

try:
    from pyamg import ruge_stuben_solver
    amg_loaded = True
except ImportError:
    amg_loaded = False

try:
    from sksparse.cholmod import cholesky
    cl_loaded = True
except ImportError:
    cl_loaded = False