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
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
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]
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
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)
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)
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
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
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
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
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
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