注意:我在最初发布的代码中犯了一个愚蠢的错误,正如Warren Weckesser所说。纠正后,一些求解器给出了正确的答案,但其他求解者给出了NaN或不正确的答案。我也忘了在输出中包含运行时警告;他们现在在那里。我已相应地修改了这个问题。我或许可以使用有效的求解器,但如果我理解为什么其他人失败了,我会更开心。
我正在尝试使用scipy.sparse.linalg中的一个或多个求解器来求解稀疏的线性方程组。在测试用例中,系统小到可以直接求解,一些稀疏求解器给出了错误的答案,如下例所示:
import numpy as np
import scipy.sparse as ss
A = np.matrix([[ 0., 0., 0., 0., 0., 1., -1., -0., -0., -0., -0.],
[ 0., 0., 0., 0., 0., 2., -0., -1., -0., -0., -0.],
[ 0., 0., 0., 0., 0., 2., -0., -0., -1., -0., -0.],
[ 0., 0., 0., 0., 0., 2., -0., -0., -0., -1., -0.],
[ 0., 0., 0., 0., 0., 1., -0., -0., -0., -0., -1.],
[ 1., 2., 2., 2., 1., 0., -0., -0., -0., -0., -0.],
[-1., 0., 0., 0., 0., 0., -1., -0., -0., -0., -0.],
[ 0., -1., 0., 0., 0., 0., -0., -1., -0., -0., -0.],
[ 0., 0., -1., 0., 0., 0., -0., -0., -1., -0., -0.],
[ 0., 0., 0., -1., 0., 0., -0., -0., -0., -1., -0.],
[ 0., 0., 0., 0., -1., 0., -0., -0., -0., -0., -1.]])
b = np.matrix([0.,0.,0.,0.,0.,1.,0.,0.,0.,0.,0.]).T
As = ss.coo_matrix(A)
# The linear system Ax = b has a solution:
x1 = np.linalg.solve(A,b)
print("Solution to Ax = b:",x1)
print("Ax - b = ",A*x1-b)
print("Info and maximum error in solutions found by various other methods: ")
x2,info = ss.linalg.bicg(As,b)
print("bicg:",info,np.max(np.abs(x2-x1.ravel())))
x2,info = ss.linalg.bicgstab(As,b)
print("bicgstab:",info,np.max(np.abs(x2-x1.ravel())))
x2,info = ss.linalg.cgs(As,b)
print("cgs:",info,np.max(np.abs(x2-x1.ravel())))
x2,info = ss.linalg.gmres(As,b)
print("gmres:",info,np.max(np.abs(x2-x1.ravel())))
x2,info = ss.linalg.lgmres(As,b)
print("lgmres:",info,np.max(np.abs(x2-x1.ravel())))
x2,info = ss.linalg.minres(As,b)
print("minres:",info,np.max(np.abs(x2-x1.ravel())))
x2,info = ss.linalg.qmr(As,b)
print("qmr:",info,np.max(np.abs(x2-x1.ravel())))
当我运行它时,我得到以下输出:
Solution to Ax = b: [[ 0.07142857]
[ 0.14285714]
[ 0.14285714]
[ 0.14285714]
[ 0.07142857]
[-0.07142857]
[-0.07142857]
[-0.14285714]
[-0.14285714]
[-0.14285714]
[-0.07142857]]
Ax - b = [[ 0.00000000e+00]
[ 0.00000000e+00]
[ 2.77555756e-17]
[ 0.00000000e+00]
[ 1.38777878e-17]
[ 0.00000000e+00]
[ 2.77555756e-17]
[ -2.77555756e-17]
[ -5.55111512e-17]
[ 2.77555756e-17]
[ 0.00000000e+00]]
Info and maximum error in solutions found by various other methods:
bicg: 1 nan
bicgstab: 1 nan
cgs: 1 nan
gmres: 0 5.55111512313e-17
lgmres: 0 1.38777878078e-16
minres: 0 0.142857142857
qmr: -11 0.142857142857
/Users/ebunn/anaconda/lib/python3.5/site-packages/scipy/sparse/linalg/isolve/iterative.py:197: RuntimeWarning: invalid value encountered in multiply
work[slice2] *= sclr2
/Users/ebunn/anaconda/lib/python3.5/site-packages/scipy/sparse/linalg/isolve/iterative.py:318: RuntimeWarning: invalid value encountered in multiply
work[slice2] *= sclr2
/Users/ebunn/anaconda/lib/python3.5/site-packages/scipy/sparse/linalg/isolve/minres.py:244: RuntimeWarning: divide by zero encountered in double_scalars
Acond = gmax/gmin
x2的每个计算都应该是与x1相同的线性系统的解,因此最后七行中的所有误差都应为零(或至少很小)。
gmres和lgmres工作,但其他人没有。在大多数情况下,信息正确指示失败,但minres表示成功(info = 0),同时返回全零(不正确)的解决方案。
以下是一些可能相关的其他信息:
当然,对于这个系统来说,它并不重要,因为直接解决它是微不足道的。对于较大的问题,这是一个热身问题,稀疏性是必不可少的。
可能gmres和/或lgmres会满足我的需求,但我仍然想了解其他人出了什么问题,部分原因是为了我自己的理解而且我也许有更广泛的方法可供选择。特别是,这两种方法都没有利用A的对称性,并且有一种方法可能会很好。
答案 0 :(得分:1)
当我运行你的代码(py3)
时,我收到了一堆警告Maximum error in solutions found by various other methods:
bicg: nan
/usr/lib/python3/dist-packages/scipy/sparse/linalg/isolve/iterative.py:197: RuntimeWarning: invalid value encountered in multiply
work[slice2] *= sclr2
bicgstab: nan
/usr/lib/python3/dist-packages/scipy/sparse/linalg/isolve/iterative.py:318: RuntimeWarning: invalid value encountered in multiply
work[slice2] *= sclr2
cgs: nan
gmres: 0.285714285714
lgmres: 0.285714285714
/usr/lib/python3/dist-packages/scipy/sparse/linalg/isolve/minres.py:244: RuntimeWarning: divide by zero encountered in double_scalars
Acond = gmax/gmin
minres: 0.142857142857
qmr: 0.142857142857
正如沃伦警告的那样,对于gmres
案例,阵列形状可以咬你。非nan
个案例中的错误均为0.1428或2倍。
添加:
print(x2)
print(x2-x1.ravel())
产生
[ 0.07142857 0.14285714 0.14285714 0.14285714 0.07142857 -0.07142857
-0.07142857 -0.14285714 -0.14285714 -0.14285714 -0.07142857] 0
[[ 4.16333634e-17 0.00000000e+00 -5.55111512e-17 5.55111512e-17
0.00000000e+00 -1.38777878e-17 -1.38777878e-17 -2.77555756e-17
0.00000000e+00 -2.77555756e-17 0.00000000e+00]]
正确比较2种解决方案时没有错误。