我似乎无法从scipy的CG和稀疏矩阵算法中获益。
当我试图解决这个带状矩阵方程时
import time
import scipy.sparse.linalg as ssla
import scipy.sparse as ss
import numpy as np
size = 3000
x = np.ones(size)
A = ss.diags([1, -2, 1], [-1, 0, 1], shape=[size, size]).toarray()
print 'cond. nr.:{}'.format(np.linalg.cond(A))
b = np.dot(A, x)
start_time = time.clock()
sol = np.linalg.solve(A, b)
elapsed_time = time.clock() - start_time
error = np.sum(np.abs(sol - x))
print 'LU time, error:', elapsed_time, error
start_time = time.clock()
sol, info = ssla.bicg(A, b, tol=1e-12)
elapsed_time = time.clock() - start_time
error = np.sum(np.abs(sol - x))
print 'CG time, ret code, error:', elapsed_time, info, error
它大约需要LU解算器的20倍。根据我的理解,CG并不比LU贵得多,即使它必须使用所有N次迭代来达到结果。所以我预计它至少会快,但实际上要快得多,因为先前有关带状的知识。这与条件数有关吗?
在密集矩阵的情况下
import time
import scipy.sparse.linalg as ssla
import numpy as np
import matplotlib.pyplot as plt
size = 1000
x = np.ones(size)
np.random.seed(1)
A = np.random.random_integers(-size, size,
size=(size, size))
print 'cond. nr.:{}'.format(np.linalg.cond(A))
b = np.dot(A, x)
start_time = time.clock()
sol = np.linalg.solve(A, b)
elapsed_time = time.clock() - start_time
error = np.sum(np.abs(sol - x))
print 'LU time, error:', elapsed_time, error
start_time = time.clock()
sol, info = ssla.bicg(A, b, tol=1e-12)
elapsed_time = time.clock() - start_time
error = np.sum(np.abs(sol - x))
print 'CG time, ret code, error:', elapsed_time, info, error
我根本没有收敛。在这种情况下,A的条件数似乎不大,但是我没有这方面的经验。
答案 0 :(得分:2)
您使用
创建A
A = ss.diags([1, -2, 1], [-1, 0, 1], shape=[size, size]).toarray()
对.toarray()
的调用将稀疏矩阵转换为常规numpy数组。因此,您将常规数组传递给稀疏求解器,这意味着稀疏求解器无法利用任何稀疏性结构。
如果将原始稀疏矩阵传递给求解器,则速度要快得多。
对于解决带状系统,快速替代方案是scipy.linalg.solve_banded
。 (Hermitian系统也有scipy.linalg.solveh_banded
。)
这是你的例子,但稀疏矩阵传递给稀疏求解器。还包括使用scipy.linalg.solve_banded
计算的解决方案,其结果比其他两种方法更快 。
import time
import scipy.sparse.linalg as ssla
import scipy.sparse as ss
from scipy.linalg import solve_banded
import numpy as np
size = 3000
x = np.ones(size)
S = ss.diags([1, -2, 1], [-1, 0, 1], shape=[size, size])
A = S.toarray()
print 'cond. nr.:{}'.format(np.linalg.cond(A))
b = np.dot(A, x)
start_time = time.clock()
sol = np.linalg.solve(A, b)
elapsed_time = time.clock() - start_time
error = np.sum(np.abs(sol - x))
print 'LU time, error : %9.6f %g' % (elapsed_time, error)
start_time = time.clock()
sol, info = ssla.bicg(S, b, tol=1e-12)
elapsed_time = time.clock() - start_time
error = np.sum(np.abs(sol - x))
print 'CG time, ret code, error: %9.6f %2d %g' % (elapsed_time, info, error)
B = np.empty((3, size))
B[0, :] = 1
B[1, :] = -2
B[2, :] = 1
start_time = time.clock()
sol = solve_banded((1, 1), B, b)
elapsed_time = time.clock() - start_time
error = np.sum(np.abs(sol - x))
print 'solve_banded time, error: %9.6f %g' % (elapsed_time, error)
输出:
cond. nr.:3649994.05818
LU time, error : 0.858295 4.05262e-09
CG time, ret code, error: 0.552952 0 6.7263e-11
solve_banded time, error: 0.000750 4.05262e-09