def spilu(A, drop_tol=None, fill_factor=None, drop_rule=None, permc_spec=None, diag_pivot_thresh=None, relax=None, panel_size=None, options={}): """Computes the incomplete LU decomposition of a sparse square matrix. Args: A (cupyx.scipy.sparse.spmatrix): Sparse matrix to factorize. drop_tol (float): (For further augments, see :func:`scipy.sparse.linalg.spilu`) fill_factor (float): drop_rule (str): permc_spec (str): diag_pivot_thresh (float): relax (int): panel_size (int): options (dict): Returns: cupyx.scipy.sparse.linalg.SuperLU: Object which has a ``solve`` method. Note: This function computes incomplete LU decomposition of a sparse matrix on the CPU using `scipy.sparse.linalg.spilu` (unless you set ``fill_factor`` to ``1``). Therefore, incomplete LU decomposition is not accelerated on the GPU. On the other hand, the computation of solving linear equations using the ``solve`` method, which this function returns, is performed on the GPU. If you set ``fill_factor`` to ``1``, this function computes incomplete LU decomposition on the GPU, but without fill-in or pivoting. .. seealso:: :func:`scipy.sparse.linalg.spilu` """ if not scipy_available: raise RuntimeError('scipy is not available') if not sparse.isspmatrix(A): raise TypeError('A must be cupyx.scipy.sparse.spmatrix') if A.shape[0] != A.shape[1]: raise ValueError('A must be a square matrix (A.shape: {})' .format(A.shape)) if A.dtype.char not in 'fdFD': raise TypeError('Invalid dtype (actual: {})'.format(A.dtype)) if fill_factor == 1: # Computes ILU(0) on the GPU using cuSparse functions if not sparse.isspmatrix_csr(A): a = A.tocsr() else: a = A.copy() cusparse.csrilu02(a) return CusparseLU(a) a = A.get().tocsc() a_inv = scipy.sparse.linalg.spilu( a, fill_factor=fill_factor, drop_tol=drop_tol, drop_rule=drop_rule, permc_spec=permc_spec, diag_pivot_thresh=diag_pivot_thresh, relax=relax, panel_size=panel_size, options=options) return SuperLU(a_inv)
def aslinearoperator(A): """Return `A` as a LinearOperator. Args: A (array-like): The input array to be converted to a `LinearOperator` object. It may be any of the following types: * :class:`cupy.ndarray` * sparse matrix (e.g. ``csr_matrix``, ``coo_matrix``, etc.) * :class:`cupyx.scipy.sparse.linalg.LinearOperator` * object with ``.shape`` and ``.matvec`` attributes Returns: cupyx.scipy.sparse.linalg.LinearOperator: `LinearOperator` object .. seealso:: :func:`scipy.sparse.aslinearoperator`` """ if isinstance(A, LinearOperator): return A elif isinstance(A, cupy.ndarray): if A.ndim > 2: raise ValueError('array must have ndim <= 2') A = cupy.atleast_2d(A) return MatrixLinearOperator(A) elif sparse.isspmatrix(A): return MatrixLinearOperator(A) else: if hasattr(A, 'shape') and hasattr(A, 'matvec'): rmatvec = None rmatmat = None dtype = None if hasattr(A, 'rmatvec'): rmatvec = A.rmatvec if hasattr(A, 'rmatmat'): rmatmat = A.rmatmat if hasattr(A, 'dtype'): dtype = A.dtype return LinearOperator(A.shape, A.matvec, rmatvec=rmatvec, rmatmat=rmatmat, dtype=dtype) else: raise TypeError('type not understood')
def splu(A, permc_spec=None, diag_pivot_thresh=None, relax=None, panel_size=None, options={}): """Computes the LU decomposition of a sparse square matrix. Args: A (cupyx.scipy.sparse.spmatrix): Sparse matrix to factorize. permc_spec (str): (For further augments, see :func:`scipy.sparse.linalg.splu`) diag_pivot_thresh (float): relax (int): panel_size (int): options (dict): Returns: cupyx.scipy.sparse.linalg.SuperLU: Object which has a ``solve`` method. Note: This function LU-decomposes a sparse matrix on the CPU using `scipy.sparse.linalg.splu`. Therefore, LU decomposition is not accelerated on the GPU. On the other hand, the computation of solving linear equations using the ``solve`` method, which this function returns, is performed on the GPU. .. seealso:: :func:`scipy.sparse.linalg.splu` """ if not scipy_available: raise RuntimeError('scipy is not available') if not sparse.isspmatrix(A): raise TypeError('A must be cupyx.scipy.sparse.spmatrix') if A.shape[0] != A.shape[1]: raise ValueError('A must be a square matrix (A.shape: {})'.format( A.shape)) if A.dtype.char not in 'fdFD': raise TypeError('Invalid dtype (actual: {})'.format(A.dtype)) a = A.get().tocsc() a_inv = scipy.sparse.linalg.splu(a, permc_spec=permc_spec, diag_pivot_thresh=diag_pivot_thresh, relax=relax, panel_size=panel_size, options=options) return SuperLU(a_inv)
def _run(self, maj, min=None, flip_for_csc=True, compare_dense=False): a = sparse.random(self.n_rows, self.n_cols, format=self.format, density=self.density) if self.format == 'csc' and flip_for_csc: tmp = maj maj = min min = tmp # None is not valid for major when minor is not None maj = slice(None) if maj is None else maj # sparse.random doesn't support complex types # so we need to cast a = a.astype(self.dtype) expected = a.get() maj_h = maj.get() if isinstance(maj, cupy.ndarray) else maj min_h = min.get() if isinstance(min, cupy.ndarray) else min if min is not None: actual = a[maj, min] expected = expected[maj_h, min_h] else: actual = a[maj] expected = expected[maj_h] if compare_dense: actual = actual.toarray() expected = expected.toarray() if sparse.isspmatrix(actual): actual.sort_indices() expected.sort_indices() testing.assert_array_equal(actual.indptr, expected.indptr) testing.assert_array_equal(actual.indices, expected.indices) testing.assert_array_equal(actual.data, expected.data) actual = actual.toarray() expected = expected.toarray() testing.assert_array_equal(actual, expected)
def spsolve(A, b): """Solves a sparse linear system ``A x = b`` Args: A (cupyx.scipy.sparse.spmatrix): Sparse matrix with dimension ``(M, M)``. b (cupy.ndarray): Dense vector or matrix with dimension ``(M)`` or ``(M, 1)``. Returns: cupy.ndarray: Solution to the system ``A x = b``. """ if not cupy.cusolver.check_availability('csrlsvqr'): raise NotImplementedError if not sparse.isspmatrix(A): raise TypeError('A must be cupyx.scipy.sparse.spmatrix') if not isinstance(b, cupy.ndarray): raise TypeError('b must be cupy.ndarray') if A.shape[0] != A.shape[1]: raise ValueError('A must be a square matrix (A.shape: {})'.format( A.shape)) if not (b.ndim == 1 or (b.ndim == 2 and b.shape[1] == 1)): raise ValueError('Invalid b.shape (b.shape: {})'.format(b.shape)) if A.shape[0] != b.shape[0]: raise ValueError( 'matrix dimension mismatch (A.shape: {}, b.shape: {})'.format( A.shape, b.shape)) if not sparse.isspmatrix_csr(A): warnings.warn('CSR format is required. Converting to CSR format.', sparse.SparseEfficiencyWarning) A = A.tocsr() A.sum_duplicates() b = b.astype(A.dtype, copy=False).ravel() return cupy.cusolver.csrlsvqr(A, b)
def spsolve_triangular(A, b, lower=True, overwrite_A=False, overwrite_b=False, unit_diagonal=False): """Solves a sparse triangular system ``A x = b``. Args: A (cupyx.scipy.sparse.spmatrix): Sparse matrix with dimension ``(M, M)``. b (cupy.ndarray): Dense vector or matrix with dimension ``(M)`` or ``(M, K)``. lower (bool): Whether ``A`` is a lower or upper trinagular matrix. If True, it is lower triangular, otherwise, upper triangular. overwrite_A (bool): (not supported) overwrite_b (bool): Allows overwriting data in ``b``. unit_diagonal (bool): If True, diagonal elements of ``A`` are assumed to be 1 and will not be referencec. Returns: cupy.ndarray: Solution to the system ``A x = b``. The shape is the same as ``b``. """ if not cusparse.check_availability('csrsm2'): raise NotImplementedError if not sparse.isspmatrix(A): raise TypeError('A must be cupyx.scipy.sparse.spmatrix') if not isinstance(b, cupy.ndarray): raise TypeError('b must be cupy.ndarray') if A.shape[0] != A.shape[1]: raise ValueError('A must be a square matrix (A.shape: {})'. format(A.shape)) if b.ndim not in [1, 2]: raise ValueError('b must be 1D or 2D array (b.shape: {})'. format(b.shape)) if A.shape[0] != b.shape[0]: raise ValueError('The size of dimensions of A must be equal to the ' 'size of the first dimension of b ' '(A.shape: {}, b.shape: {})'.format(A.shape, b.shape)) if A.dtype.char not in 'fdFD': raise TypeError('unsupported dtype (actual: {})'.format(A.dtype)) if not (sparse.isspmatrix_csr(A) or sparse.isspmatrix_csc(A)): warnings.warn('CSR or CSC format is required. Converting to CSR ' 'format.', sparse.SparseEfficiencyWarning) A = A.tocsr() A.sum_duplicates() if (overwrite_b and A.dtype == b.dtype and (b._c_contiguous or b._f_contiguous)): x = b else: x = b.astype(A.dtype, copy=True) cusparse.csrsm2(A, x, lower=lower, unit_diag=unit_diagonal) if x.dtype.char in 'fF': # Note: This is for compatibility with SciPy. dtype = numpy.promote_types(x.dtype, 'float64') x = x.astype(dtype) return x