def test_callback(self): def store_residual(r, rvec): rvec[rvec.nonzero()[0].max()+1] = r # Define, A,b A = csr_matrix(array([[-2,1,0,0,0,0],[1,-2,1,0,0,0],[0,1,-2,1,0,0],[0,0,1,-2,1,0],[0,0,0,1,-2,1],[0,0,0,0,1,-2]])) b = ones((A.shape[0],)) maxiter = 1 rvec = zeros(maxiter+1) rvec[0] = 1.0 callback = lambda r:store_residual(r, rvec) with suppress_warnings() as sup: sup.filter(DeprecationWarning, ".*called without specifying.*") x,flag = gmres(A, b, x0=zeros(A.shape[0]), tol=1e-16, maxiter=maxiter, callback=callback) # Expected output from SciPy 1.0.0 assert_allclose(rvec, array([1.0, 0.81649658092772603]), rtol=1e-10) # Test preconditioned callback M = 1e-3 * np.eye(A.shape[0]) rvec = zeros(maxiter+1) rvec[0] = 1.0 with suppress_warnings() as sup: sup.filter(DeprecationWarning, ".*called without specifying.*") x, flag = gmres(A, b, M=M, tol=1e-16, maxiter=maxiter, callback=callback) # Expected output from SciPy 1.0.0 (callback has preconditioned residual!) assert_allclose(rvec, array([1.0, 1e-3 * 0.81649658092772603]), rtol=1e-10)
def test_atol_legacy(self): with suppress_warnings() as sup: sup.filter(DeprecationWarning, ".*called without specifying.*") # Check the strange legacy behavior: the tolerance is interpreted # as atol, but only for the initial residual A = eye(2) b = 1e-6 * ones(2) x, info = gmres(A, b, tol=1e-5) assert_array_equal(x, np.zeros(2)) A = eye(2) b = ones(2) x, info = gmres(A, b, tol=1e-5) assert_(np.linalg.norm(A.dot(x) - b) <= 1e-5*np.linalg.norm(b)) assert_allclose(x, b, atol=0, rtol=1e-8) rndm = np.random.RandomState(12345) A = rndm.rand(30, 30) b = 1e-6 * ones(30) x, info = gmres(A, b, tol=1e-7, restart=20) assert_(np.linalg.norm(A.dot(x) - b) > 1e-7) A = eye(2) b = 1e-10 * ones(2) x, info = gmres(A, b, tol=1e-8, atol=0) assert_(np.linalg.norm(A.dot(x) - b) <= 1e-8*np.linalg.norm(b))
def test_abi(self): # Check we don't segfault on gmres with complex argument A = eye(2) b = ones(2) with suppress_warnings() as sup: sup.filter(DeprecationWarning, ".*called without specifying.*") r_x, r_info = gmres(A, b) r_x = r_x.astype(complex) x, info = gmres(A.astype(complex), b.astype(complex)) assert_(iscomplexobj(x)) assert_allclose(r_x, x) assert_(r_info == info)
def test_callback_x_monotonic(self): # Check that callback_type='x' gives monotonic norm decrease np.random.seed(1) A = np.random.rand(20, 20) + np.eye(20) b = np.random.rand(20) prev_r = [np.inf] count = [0] def x_cb(x): r = np.linalg.norm(A.dot(x) - b) assert r <= prev_r[0] prev_r[0] = r count[0] += 1 x, info = gmres(A, b, tol=1e-6, atol=0, callback=x_cb, maxiter=20, restart=10, callback_type='x') assert info == 20 assert count[0] == 21 x_cb(x)
def test_arnoldi(self): np.random.seed(1) A = eye(2000) + rand(2000, 2000, density=5e-4) b = np.random.rand(2000) # The inner arnoldi should be equivalent to gmres with suppress_warnings() as sup: sup.filter(DeprecationWarning, ".*called without specifying.*") x0, flag0 = gcrotmk(A, b, x0=zeros(A.shape[0]), m=15, k=0, maxiter=1) x1, flag1 = gmres(A, b, x0=zeros(A.shape[0]), restart=15, maxiter=1) assert_equal(flag0, 1) assert_equal(flag1, 1) assert np.linalg.norm(A.dot(x0) - b) > 1e-3 assert_allclose(x0, x1)
def test_callback_type(self): # The legacy callback type changes meaning of 'maxiter' np.random.seed(1) A = np.random.rand(20, 20) b = np.random.rand(20) cb_count = [0] def pr_norm_cb(r): cb_count[0] += 1 assert_(isinstance(r, float)) def x_cb(x): cb_count[0] += 1 assert_(isinstance(x, np.ndarray)) with suppress_warnings() as sup: sup.filter(DeprecationWarning, ".*called without specifying.*") # 2 iterations is not enough to solve the problem cb_count = [0] x, info = gmres(A, b, tol=1e-6, atol=0, callback=pr_norm_cb, maxiter=2, restart=50) assert info == 2 assert cb_count[0] == 2 # With `callback_type` specified, no warning should be raised cb_count = [0] x, info = gmres(A, b, tol=1e-6, atol=0, callback=pr_norm_cb, maxiter=2, restart=50, callback_type='legacy') assert info == 2 assert cb_count[0] == 2 # 2 restart cycles is enough to solve the problem cb_count = [0] x, info = gmres(A, b, tol=1e-6, atol=0, callback=pr_norm_cb, maxiter=2, restart=50, callback_type='pr_norm') assert info == 0 assert cb_count[0] > 2 # 2 restart cycles is enough to solve the problem cb_count = [0] x, info = gmres(A, b, tol=1e-6, atol=0, callback=x_cb, maxiter=2, restart=50, callback_type='x') assert info == 0 assert cb_count[0] == 2
def test_basic(self): A = np.vander(np.arange(10) + 1)[:, ::-1] b = np.zeros(10) b[0] = 1 with suppress_warnings() as sup: sup.filter(DeprecationWarning, ".*called without specifying.*") x_gm, err = gmres(A, b, restart=5, maxiter=1) assert_allclose(x_gm[0], 0.359, rtol=1e-2)
def test_defective_matrix_breakdown(self): # Breakdown due to defective matrix A = np.array([[0, 1, 0], [1, 0, 0], [0, 0, 0]]) b = np.array([1, 0, 1]) x, info = gmres(A, b, tol=1e-8, atol=0) # Should not return nans, nor terminate with false success assert_(not np.isnan(x).any()) if info == 0: assert_(np.linalg.norm(A.dot(x) - b) <= 1e-8*np.linalg.norm(b)) # The solution should be OK outside null space of A assert_allclose(A.dot(A.dot(x)), A.dot(b))
def test_defective_precond_breakdown(self): # Breakdown due to defective preconditioner M = np.eye(3) M[2,2] = 0 b = np.array([0, 1, 1]) x = np.array([1, 0, 0]) A = np.diag([2, 3, 4]) x, info = gmres(A, b, x0=x, M=M, tol=1e-15, atol=0) # Should not return nans, nor terminate with false success assert_(not np.isnan(x).any()) if info == 0: assert_(np.linalg.norm(A.dot(x) - b) <= 1e-15*np.linalg.norm(b)) # The solution should be OK outside null space of M assert_allclose(M.dot(A.dot(x)), M.dot(b))
def test_restrt_dep(self): with pytest.warns(DeprecationWarning, match="'gmres' keyword argument 'restrt'"): gmres(np.array([1]), np.array([1]), restrt=10)