Python 为什么是scipy';谁的稀疏解算器给出了错误的答案?
注意:正如沃伦·韦克瑟(Warren Weckesser)所指出的,我在最初发布的代码中犯了一个愚蠢的错误。更正后,一些解算器给出正确答案,但其他解算器给出NaN或错误答案。我还忘了在输出中包含运行时警告;他们现在在那里。我相应地修改了这个问题。我也许能够使用有效的解决方案,但如果我能理解其他解决方案失败的原因,我会更高兴 我正在尝试使用scipy.sparse.linalg中的一个或多个解算器来解线性方程的稀疏系统。在测试用例中,系统小到可以直接求解,一些稀疏解算器给出了错误的答案,如以下示例所示:Python 为什么是scipy';谁的稀疏解算器给出了错误的答案?,python,numpy,scipy,sparse-matrix,Python,Numpy,Scipy,Sparse Matrix,注意:正如沃伦·韦克瑟(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和LGMRE起作用,但其他的不起作用。在大多数情况下,info正确地指示失败,但minres指示成功(info=0),同时返回全零(不正确)的解决方案
以下是一些可能相关的附加信息:
- 矩阵A是对称的,但不是正定的
- 矩阵A的条件相当好
- 如果我用所有稀疏解算器中的原始矩阵A替换稀疏表示形式,则结果不变——也就是说,如果我说ss.linalg.bicg(A,b),而不是ss.linalg.bicg(As,b),等等
- 实际上,包含biggstab是不公平的,因为文档中说它只适用于正定矩阵。我把它包括进来是希望它能起作用,因为这种方法原则上适用于不定矩阵
- 我正在运行Python 3.5.1,scipy版本0.17.0
可能gmres和/或LGMRE会满足我的需求,但我仍然想了解其他方法的问题,部分原因是我自己的理解,但也可能是为了让我有更广泛的方法可供选择。特别是,这两种方法都不能利用A的对称性,如果有一种方法可以利用A的对称性,那就更好了。我在运行代码时收到了一大堆警告(py3) 正如Warren警告的那样,对于
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]]
正确比较两种解决方案时没有错误。小心!因为
A
是一个np.矩阵
,x1
也是一个np.矩阵
,具有形状(11,1)<另一方面,code>x2是一个具有形状(11,)的np.ndarray
,因此当您计算x2-x1
时,广播应用,结果是(11,11)。你可以通过几种方式避免这种情况;例如,使用A=np.array(…)
(但随后将A*x1
替换为A.dot(x1)
),或在执行减法x2-x1
之前展平x1
。代码可以复制粘贴以供测试,这很好。但是您的错误表明您实际上没有查看任何x2
结果。您似乎立即跳到了与x1
的比较中。谢谢!我真傻。正如您可能已经猜到的,我对Python编程相当陌生。我早该弄明白的。
[ 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]]