运行Octave 6.3.0 for Windows我需要得到某个矩阵的最小特征值。eigs(A,1,"sm")
应该这样做,但我经常得到奇异矩阵的错误结果。
eigs(A)
(返回所有前6个特征值/向量)是正确的(至少在机器精度上):
>> A = [[1 1 1];[1 1 1];[1 1 1]]
A =
1 1 1
1 1 1
1 1 1
>> [v lambda flag] = eigs(A)
v =
0.5774 -0.3094 -0.7556
0.5774 -0.4996 0.6458
0.5774 0.8091 0.1098
lambda =
Diagonal Matrix
3.0000e+00 0 0
0 -4.5198e-16 0
0 0 -1.5831e-17
flag = 0
但eigs(A,1,"sm")
不是:
>> [v lambda flag] = eigs(A,1,"sm")
warning: eigs: 'A - sigma*B' is singular, indicating sigma is exactly an eigenvalue so convergence is not guaranteed
warning: called from
eigs at line 298 column 20
warning: matrix singular to machine precision
warning: called from
eigs at line 298 column 20
warning: matrix singular to machine precision
warning: called from
eigs at line 298 column 20
warning: matrix singular to machine precision
warning: called from
eigs at line 298 column 20
warning: matrix singular to machine precision
warning: called from
eigs at line 298 column 20
v =
-0.7554
0.2745
0.5950
lambda = 0.4322
flag = 0
不仅返回的特征值是错误的,而且返回的标志是零,这表明在函数中每一个都是正确的…
这是一个错误的使用eigs()(但从文档我看不出什么是错误的)或一个bug?
编辑:如果不是bug,至少是设计问题…当请求两个最小值而不是单独请求最小值时,也没有问题。>> eigs(A,2,"sm")
ans =
-1.7700e-17
-5.8485e-16
编辑2:Matlab在线中的eigs()函数运行良好并返回正确的结果(在机器精度)
>> A=ones(3)
A =
1 1 1
1 1 1
1 1 1
>> [v lambda flag] = eigs(A,1,"smallestabs")
v =
-0.7556
0.6458
0.1098
lambda =
-1.5831e-17
flag =
0
经过更多的测试和调查,我想我可以回答:是的,Octave eigs()有一些缺陷。
eigs(A,1,"sm")
可能采用逆幂迭代法,即从任意x向量开始,反复求解y=Ax,然后求解x=y。显然,如果a是奇异的就有问题了。然而:
- Matlab eigs()在这种情况下运行良好,并返回正确的特征值(在机器精度)。我不知道它是做什么的,如果矩阵被检测为奇异,可能会在对角线上添加一个微小的值,但它比Octave做得更好(或至少不同)。
- 如果由于某些(好或坏)原因Octave的算法不能处理奇异矩阵,那么这应该反映在第三个返回参数("flag")中。相反,它总是零,好像一切正常。
eigs(A,1,"sm")
实际上相当于eigs(A,1,0)
,更通用的语法是eigs(A,1,sigma)
,意思是"找到与sigma最接近的特征值,以及相关联的特征向量"。为此,对矩阵A-sigma*I
采用幂次逆迭代法求解。问题:如果已经是一个精确特征值这个矩阵根据定义是奇异的。在这种情况下,Octave eigs()失败,而Matlab eigs()成功。当一个人提前知道确切的特征值,或者随机设置它时,失败是有点奇怪的。因此,在Octave中,正确的做法是测试(A-sigma.I)
是否为单数,如果是,则向sigma:eigs(A,1,sigma+eps*norm(A))
添加一个小值。Matlab eigs()可能会做类似的事情。