def _spectral(self, X_i: LazyTensor): ''' Helper function to compute eigendecomposition of K_q. Written using LinearOperators which are lazy representations of sparse and/or structured data. Args: X_i[numpy LazyTensor] Returns S[np.array] eigenvalues, U[np.array] eigenvectors ''' K_linear = aslinearoperator(X_i) # K <- K + eps K_linear = K_linear + IdentityOperator(K_linear.shape, dtype=self.dtype) * self.inv_eps k = K_linear.shape[0] - 1 S, U = eigsh(K_linear, k=k, which='LM') return S, U
def make_system(A, M, x0, b, xtype=None): """Make a linear system Ax=b Parameters ---------- A : LinearOperator sparse or dense matrix (or any valid input to aslinearoperator) M : {LinearOperator, Nones} preconditioner sparse or dense matrix (or any valid input to aslinearoperator) x0 : {array_like, None} initial guess to iterative method b : array_like right hand side xtype : {'f', 'd', 'F', 'D', None} dtype of the x vector Returns ------- (A, M, x, b, postprocess) A : LinearOperator matrix of the linear system M : LinearOperator preconditioner x : rank 1 ndarray initial guess b : rank 1 ndarray right hand side postprocess : function converts the solution vector to the appropriate type and dimensions (e.g. (N,1) matrix) """ A_ = A A = aslinearoperator(A) if A.shape[0] != A.shape[1]: raise ValueError('expected square matrix, but got shape=%s' % (A.shape, )) N = A.shape[0] b = asanyarray(b) if not (b.shape == (N, 1) or b.shape == (N, )): raise ValueError('A and b have incompatible dimensions') if b.dtype.char not in 'fdFD': b = b.astype('d') # upcast non-FP types to double def postprocess(x): if isinstance(b, matrix): x = asmatrix(x) return x.reshape(b.shape) if xtype is None: if hasattr(A, 'dtype'): xtype = A.dtype.char else: xtype = A.matvec(b).dtype.char xtype = coerce(xtype, b.dtype.char) else: warn( 'Use of xtype argument is deprecated. ' 'Use LinearOperator( ... , dtype=xtype) instead.', DeprecationWarning) if xtype == 0: xtype = b.dtype.char else: if xtype not in 'fdFD': raise ValueError("xtype must be 'f', 'd', 'F', or 'D'") b = asarray(b, dtype=xtype) # make b the same type as x b = b.ravel() if x0 is None: x = zeros(N, dtype=xtype) else: x = array(x0, dtype=xtype) if not (x.shape == (N, 1) or x.shape == (N, )): raise ValueError('A and x have incompatible dimensions') x = x.ravel() # process preconditioner if M is None: if hasattr(A_, 'psolve'): psolve = A_.psolve else: psolve = id if hasattr(A_, 'rpsolve'): rpsolve = A_.rpsolve else: rpsolve = id if psolve is id and rpsolve is id: M = IdentityOperator(shape=A.shape, dtype=A.dtype) else: M = LinearOperator(A.shape, matvec=psolve, rmatvec=rpsolve, dtype=A.dtype) else: M = aslinearoperator(M) if A.shape != M.shape: raise ValueError('matrix and preconditioner have different shapes') return A, M, x, b, postprocess
from scipy.sparse import diags L = aslinearoperator(diags(D)) - K L.dtype = np.dtype( dtype) # Scipy Bugfix: by default, "-" removes the dtype information... ################################################## # Alternatively, we can also use a **symmetric, normalized Laplacian matrix** defined through: # # .. math:: # L_{\text{norm}}= \text{Id} - \text{diag}(D^{-1/2}) K \text{diag}(D^{-1/2}). from scipy.sparse.linalg.interface import IdentityOperator D_2 = aslinearoperator(diags(1 / np.sqrt(D))) L_norm = IdentityOperator((N, N)) - D_2 @ K @ D_2 L_norm.dtype = np.dtype( dtype) # Scipy Bugfix: by default, "-" removes the dtype information... ################################################## # Then, computing spectral coordinates on **x** is as simple # as typing: # from time import time start = time() # Compute the 7 smallest eigenvalues/vectors of our graph Laplacian eigenvalues, coordinates = eigsh(L, k=7, which="SM")
def make_system(A, M, x0, b): """Make a linear system Ax=b Parameters ---------- A : LinearOperator sparse or dense matrix (or any valid input to aslinearoperator) M : {LinearOperator, Nones} preconditioner sparse or dense matrix (or any valid input to aslinearoperator) x0 : {array_like, str, None} initial guess to iterative method. ``x0 = 'Mb'`` means using the nonzero initial guess ``M @ b``. Default is `None`, which means using the zero initial guess. b : array_like right hand side Returns ------- (A, M, x, b, postprocess) A : LinearOperator matrix of the linear system M : LinearOperator preconditioner x : rank 1 ndarray initial guess b : rank 1 ndarray right hand side postprocess : function converts the solution vector to the appropriate type and dimensions (e.g. (N,1) matrix) """ A_ = A A = aslinearoperator(A) if A.shape[0] != A.shape[1]: raise ValueError('expected square matrix, but got shape=%s' % (A.shape, )) N = A.shape[0] b = asanyarray(b) if not (b.shape == (N, 1) or b.shape == (N, )): raise ValueError('shapes of A {} and b {} are incompatible'.format( A.shape, b.shape)) if b.dtype.char not in 'fdFD': b = b.astype('d') # upcast non-FP types to double def postprocess(x): if isinstance(b, matrix): x = asmatrix(x) return x.reshape(b.shape) if hasattr(A, 'dtype'): xtype = A.dtype.char else: xtype = A.matvec(b).dtype.char xtype = coerce(xtype, b.dtype.char) b = asarray(b, dtype=xtype) # make b the same type as x b = b.ravel() # process preconditioner if M is None: if hasattr(A_, 'psolve'): psolve = A_.psolve else: psolve = id if hasattr(A_, 'rpsolve'): rpsolve = A_.rpsolve else: rpsolve = id if psolve is id and rpsolve is id: M = IdentityOperator(shape=A.shape, dtype=A.dtype) else: M = LinearOperator(A.shape, matvec=psolve, rmatvec=rpsolve, dtype=A.dtype) else: M = aslinearoperator(M) if A.shape != M.shape: raise ValueError('matrix and preconditioner have different shapes') # set initial guess if x0 is None: x = zeros(N, dtype=xtype) elif isinstance(x0, str): if x0 == 'Mb': # use nonzero initial guess ``M @ b`` bCopy = b.copy() x = M.matvec(bCopy) else: x = array(x0, dtype=xtype) if not (x.shape == (N, 1) or x.shape == (N, )): raise ValueError(f'shapes of A {A.shape} and ' f'x0 {x.shape} are incompatible') x = x.ravel() return A, M, x, b, postprocess
def make_system(A, M, x0, b): A_ = A A = aslinearoperator(A) if A.shape[0] != A.shape[1]: raise ValueError( 'expected square matrix, but got shape=%s' % (A.shape,)) N = A.shape[0] b = asanyarray(b) if not (b.shape == (N, 1) or b.shape == (N,)): raise ValueError('A and b have incompatible dimensions') if b.dtype.char not in 'fdFD': b = b.astype('d') # upcast non-FP types to double def postprocess(x): if isinstance(b, matrix): x = asmatrix(x) return x.reshape(b.shape) if hasattr(A, 'dtype'): xtype = A.dtype.char else: xtype = A.matvec(b).dtype.char xtype = coerce(xtype, b.dtype.char) b = asarray(b, dtype=xtype) # make b the same type as x b = b.ravel() if x0 is None: x = zeros(N, dtype=xtype) else: x = array(x0, dtype=xtype) if not (x.shape == (N, 1) or x.shape == (N,)): raise ValueError('A and x have incompatible dimensions') x = x.ravel() # process preconditioner if M is None: if hasattr(A_, 'psolve'): psolve = A_.psolve else: psolve = id if hasattr(A_, 'rpsolve'): rpsolve = A_.rpsolve else: rpsolve = id if psolve is id and rpsolve is id: M = IdentityOperator(shape=A.shape, dtype=A.dtype) else: M = LinearOperator(A.shape, matvec=psolve, rmatvec=rpsolve, dtype=A.dtype) else: M = aslinearoperator(M) if A.shape != M.shape: raise ValueError('matrix and preconditioner have different shapes') return A, M, x, b, postprocess