Octave eigs() function bugged?



运行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()可能会做类似的事情。

最新更新