Commit 140afd9d by Stephan Rave

### fix linter issues

parent 05a935a5
Pipeline #140364 failed with stages
in 48 minutes and 57 seconds
 ... ... @@ -11,10 +11,8 @@ from scipy.special import erfinv from pymor.algorithms.gram_schmidt import gram_schmidt from pymor.core.defaults import defaults from pymor.operators.interface import Operator from pymor.algorithms.eigs import eigs from pymor.core.logger import getLogger from pymor.vectorarrays.interface import VectorArray from pymor.operators.constructions import VectorArrayOperator, InverseOperator, IdentityOperator from pymor.operators.constructions import InverseOperator, IdentityOperator @defaults('tol', 'failure_tolerance', 'num_testvecs') ... ... @@ -106,7 +104,7 @@ def rrf(A, source_product=None, range_product=None, q=2, l=8, return_rand=False, Given the |Operator| `A`, the return value of this method is the |VectorArray| `Q` whose vectors form an approximate orthonormal basis for the range of `A`. This method is based on algorithm 2 in :cite:`SBH21`. This method is based on algorithm 2 in :cite:`SBH21`. Parameters ---------- ... ... @@ -121,7 +119,7 @@ def rrf(A, source_product=None, range_product=None, q=2, l=8, return_rand=False, l The block size of the normalized power iterations. return_rand If `True`, the randomly sampled |VectorArray| R is returned. If `True`, the randomly sampled |VectorArray| R is returned. iscomplex If `True`, the random vectors are chosen complex. ... ... @@ -133,12 +131,12 @@ def rrf(A, source_product=None, range_product=None, q=2, l=8, return_rand=False, The randomly sampled |VectorArray| (if `return_rand` is `True`). """ assert isinstance(A, Operator) if range_product is None: range_product = IdentityOperator(A.range) else: assert isinstance(range_product, Operator) if source_product is None: source_product = IdentityOperator(A.source) else: ... ... @@ -146,7 +144,7 @@ def rrf(A, source_product=None, range_product=None, q=2, l=8, return_rand=False, assert 0 <= l <= min(A.source.dim, A.range.dim) and isinstance(l, int) assert q >= 0 and isinstance(q, int) R = A.source.random(l, distribution='normal') if iscomplex: ... ... @@ -170,7 +168,7 @@ def rrf(A, source_product=None, range_product=None, q=2, l=8, return_rand=False, @defaults('p', 'q', 'modes') def random_generalized_svd(A, range_product=None, source_product=None, modes=6, p=20, q=2): r"""Randomized SVD of an |Operator|. r"""Randomized SVD of an |Operator|. Viewing the `A` as a `A.dim x len(A)` matrix, the return value of this method is the randomized singular value decomposition of `A`, where the ... ... @@ -178,23 +176,23 @@ def random_generalized_svd(A, range_product=None, source_product=None, modes=6, the inner product on :math:`\mathbb{R}^{\mathtt{len(A)}}` is given by `source_product`. .. math:: A = U \Sigma V^H \mathtt{source_product} This method is based on :cite:`SHB21`. Parameters ---------- A The |Operator| for which the randomized SVD is to be computed. The |Operator| for which the randomized SVD is to be computed. range_product Range product |Operator| w.r.t which the randomized SVD is computed. source_product Source product |Operator| w.r.t which the randomized SVD is computed. modes The first `modes` approximated singular values and vectors are returned. The first `modes` approximated singular values and vectors are returned. p If not `0`, adds `p` columns to the randomly sampled matrix (oversampling parameter). If not `0`, adds `p` columns to the randomly sampled matrix (oversampling parameter). q If not `0`, performs `q` so-called power iterations to increase the relative weight of the first singular values. ... ... @@ -209,9 +207,9 @@ def random_generalized_svd(A, range_product=None, source_product=None, modes=6, |VectorArray| of the approximated right singular vectors. """ logger = getLogger('pymor.algorithms.rand_la') assert isinstance(A, Operator) assert 0 <= modes <= max(A.source.dim, A.range.dim) and isinstance(modes, int) assert 0 <= p <= max(A.source.dim, A.range.dim) - modes and isinstance(p, int) assert q >= 0 and isinstance(q, int) ... ... @@ -221,28 +219,28 @@ def random_generalized_svd(A, range_product=None, source_product=None, modes=6, else: assert isinstance(range_product, Operator) assert range_product.source == range_product.range == A.range if source_product is None: source_product = IdentityOperator(A.source) else: assert isinstance(source_product, Operator) assert source_product.source == source_product.range == A.source if A.source.dim == 0 or A.range.dim == 0: return A.source.empty(), np.array([]), A.range.empty() Q = rrf(A, source_product=source_product, range_product=range_product, q=q, l=modes+p) B = A.apply_adjoint(range_product.apply(Q)) Q_B, R_B = gram_schmidt(source_product.apply_inverse(B), product=source_product, return_R=True) U_b, s, Vh_b = sp.linalg.svd(R_B.T, full_matrices=False) U_b, s, Vh_b = sp.linalg.svd(R_B.T, full_matrices=False) with logger.block(f'Computing generalized left-singular vectors ({modes} vectors) ...'): U = Q.lincomb(U_b.T) with logger.block(f'Computung generalized right-singular vector ({modes} vectors) ...'): Vh = Q_B.lincomb(Vh_b) return U[:modes], s[:modes], Vh[:modes] return U[:modes], s[:modes], Vh[:modes] @defaults('modes', 'p', 'q') ... ... @@ -251,7 +249,7 @@ def random_ghep(A, E=None, modes=6, p=20, q=2, single_pass=False): Approximates `modes` eigenvalues `w` with corresponding eigenvectors `v` which solve the eigenvalue problem .. math:: A v_i = w_i v_i ... ... @@ -262,7 +260,7 @@ def random_ghep(A, E=None, modes=6, p=20, q=2, single_pass=False): if `E` is not `None`. This method is an implementation of algorithm 6 and 7 in :cite:`SJK16`. This method is an implementation of algorithm 6 and 7 in :cite:`SJK16`. Parameters ---------- ... ... @@ -279,7 +277,8 @@ def random_ghep(A, E=None, modes=6, p=20, q=2, single_pass=False): If not `0`, performs `q` power iterations to increase the relative weight of the larger singular values. Ignored when `single_pass` is `True`. single_pass If `True`, computes the GHEP where only one set of matvecs Ax is required, but at the expense of lower numerical accuracy. If `True`, computes the GHEP where only one set of matvecs Ax is required, but at the expense of lower numerical accuracy. If `False`, the methods require two sets of matvecs Ax. Returns ... ... @@ -297,7 +296,7 @@ def random_ghep(A, E=None, modes=6, p=20, q=2, single_pass=False): assert 0 <= modes <= max(A.source.dim, A.range.dim) and isinstance(modes, int) assert 0 <= p <= max(A.source.dim, A.range.dim) - modes and isinstance(p, int) assert q >= 0 and isinstance(q, int) if E is None: E = IdentityOperator(A.source) else: ... ... @@ -305,19 +304,19 @@ def random_ghep(A, E=None, modes=6, p=20, q=2, single_pass=False): assert not E.parametric assert E.source == E.range assert E.source == A.source if A.source.dim == 0 or A.range.dim == 0: return A.source.empty(), np.array([]), A.range.empty() if single_pass: Omega = A.source.random(modes+p, distribution='normal') Y_bar = A.apply(Omega) Y = E.apply_inverse(Y_bar) Q, R = gram_schmidt(Y, product=E, return_R=True) X = E.apply2(Omega,Q) X = E.apply2(Omega, Q) X_lu = lu_factor(X) T = lu_solve(X_lu, lu_solve(X_lu, Omega.inner(Y_bar)).T).T else: else: C = InverseOperator(E) @ A Y, Omega = rrf(C, q=q, l=modes+p, return_rand=True) Q = gram_schmidt(Y, product=E) ... ... @@ -325,9 +324,9 @@ def random_ghep(A, E=None, modes=6, p=20, q=2, single_pass=False): w, S = sp.linalg.eigh(T) w = w[::-1] S = S[:,::-1] S = S[:, ::-1] with logger.block(f'Computing eigenvectors ({modes} vectors) ...'): V = Q.lincomb(S) V = Q.lincomb(S) return w[:modes], V[:modes]
 ... ... @@ -66,5 +66,3 @@ def test_not_too_many_modes(method): if __name__ == "__main__": runmodule(filename=__file__)
 ... ... @@ -44,7 +44,7 @@ def test_rrf(): np.random.seed(3) B = uniform(low=-1.0, high=1.0, size=(10, 10)) B = B @B.T B = B @ B.T source_product = NumpyMatrixOperator(B) C = range_product.range.random(10, seed=10) ... ... @@ -65,15 +65,15 @@ def test_rrf(): def test_random_generalized_svd(): np.random.seed(4) E = uniform(low=-1.0, high=1.0, size=(5, 5)) E = uniform(low=-1.0, high=1.0, size=(5, 5)) E_op = NumpyMatrixOperator(E) modes = 3 U, s, Vh = random_generalized_svd(E_op, modes=modes, p=1) U_real, s_real, Vh_real = sp.linalg.svd(E) assert abs(np.linalg.norm(s-s_real[:modes])) <= 1e-2 assert len(U) == modes assert len(U) == modes assert len(Vh) == modes assert len(s) == modes assert U in E_op.range ... ... @@ -82,7 +82,7 @@ def test_random_generalized_svd(): def test_random_ghep(): np.random.seed(5) D = uniform(low=-1.0, high=1.0, size=(5, 5)) D = uniform(low=-1.0, high=1.0, size=(5, 5)) D = D @ D.T D_op = NumpyMatrixOperator(D) ... ... @@ -91,16 +91,16 @@ def test_random_ghep(): w2, V2 = random_ghep(D_op, modes=modes, p=1, single_pass=True) w_real, V_real = sp.linalg.eigh(D) w_real = w_real[::-1] V_real = V_real[:,::-1] V_real = V_real[:, ::-1] assert abs(np.linalg.norm(w1-w_real[:modes])) <= 1e-2 assert abs(np.linalg.norm(w2-w_real[:modes])) <= 1 for i in range(0,modes): assert np.linalg.norm(abs(V1.to_numpy()[i,:]) - abs(V_real[:,i])) <= 1 for i in range(0,modes): assert np.linalg.norm(abs(V2.to_numpy()[i,:]) - abs(V_real[:,i])) <= 1 for i in range(0, modes): assert np.linalg.norm(abs(V1.to_numpy()[i, :]) - abs(V_real[:, i])) <= 1 for i in range(0, modes): assert np.linalg.norm(abs(V2.to_numpy()[i, :]) - abs(V_real[:, i])) <= 1 assert len(w1) == modes assert len(V1) == modes assert len(V1) == modes assert V1.dim == D_op.source.dim
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment