为什么eig()和ishermitian()在不同的计算机和MATLAB版本上表现不同,有没有办法绕过它?

时间:2017-11-17 00:32:14

标签: matlab

我将首先简明地陈述我的问题和情况,然后详细介绍我迄今为止在解决问题方面取得的进展。

函数eig()在计算机体系结构和MATLAB版本的不同组合中表现不同,我注意到了两种方式。首先,对于相同的精确代码,输出中的特征值和特征向量的顺序是不同的。现在,我已经在几个地方读过,MATLAB不保证输出中那些特定的顺序,所以为了安全起见之后应该总是排序,所以尽管我认为这是一个更大问题的一部分,我会让那张幻灯片。行为不同的另一种方式是,在它们的顺序不是递增的情况下,特征值是错误的。这就是我知道他们错了的方法:我正在处理中等大小的复杂Hermitian矩阵,而我得到的特征值很复杂,但它们对于Hermitian矩阵应该是真实的。在订单升序的架构/版本组合中,特征值也应该是真实的。当它们很复杂时,虚部就是机器epsilon的顺序,所以很明显它们根本就不应该存在。因此,围绕这个的hacky方式就是采取真实的部分,以防万一它不应该是复杂的,然后排序。这个问题的一个实际问题是,当eig()正在使用其认为矩阵是非Hermitian的例程时,它需要两倍的时间并且使用两倍的内存,可能是因为复数而不是实数。所以,问题是,为什么会这样,我们能解决它吗?

很抱歉很长时间的介绍。我注意到的一件事是,在具有正确特征值的架构/版本组合中,如果我将复杂的Hermitian矩阵直接赋予ishermitian(),它也始终给出正确的答案。当特征值不正确时,ishermitian()也是不正确的。一些简单的例子如下。所以,我的想法是eig()正在以ishermitian()的方式测试矩阵是否是Hermitian。

在具有不正确特征值的架构/版本组合中,ishermitian()对于简单的事情仍然是正确的:

>> test=[1 2 3]+[4 5 6]*1i; 
>> mat=test'*test;
>> ishermitian(mat)

ans =

     1
根据定义,复矢量及其共轭转置的外积是厄米特矩阵。所以我们可以用一个与我正在处理的矩阵大小相同的矩阵再次尝试这个。来自同一台电脑:

>> test=randn(1,64)+randn(1,64)*1i;
>> mat=test'*test;
>> ishermitian(mat)

ans =

     0

我们可以看到eig()的相应问题:

>> vals=eig(mat);       
>> whos vals
  Name       Size            Bytes  Class     Attributes

  vals      64x1              1024  double    complex   

现在,在不同的计算机上使用相同的代码:

>> test=randn(1,64)+randn(1,64)*1i;
>> mat=test'*test;
>> ishermitian(mat)

ans =

     1

>> vals=eig(mat);
>> whos vals
  Name       Size            Bytes  Class     Attributes

  vals      64x1               512  double              

我已经在各种系统上对此进行了测试,我没有注意到有关架构或版本对此负责的任何规则,因此我不会厌倦所有这些细节。但我很好奇一个结果与另一个结果的频繁程度。根据我迄今为止的经验,似乎大约有一半。奇怪的是,在同一台计算机上:

>> test2=test';
>> mat=test2*test;
>> ishermitian(mat)

ans =

     0

>> vals=eig(mat);
>> whos vals
  Name       Size            Bytes  Class     Attributes

  vals      64x1              1024  double    complex   

因此,如果将转置分配给另一个变量,则会出现一些类似于另一台计算机的精度问题,但如果不这样做,则可以正常工作。我错过了为什么会发生这种情况,和/或是否有解决办法?

2 个答案:

答案 0 :(得分:1)

要解决这个问题,请尝试舍入到某个(小)度,或者只是通过复制明确地制作矩阵hermitian(不涉及数字操作)。

答案 1 :(得分:1)

我准备写一些东西来对这些数字进行一些调整,但我遇到this random thing实际上似乎解决了这个问题:

>> test=randn(1,64)+randn(1,64)*1i;
>> mat=test'*test;             
>> ishermitian(mat)

ans =

     0

>> vals=eig(mat);
>> whos vals
  Name       Size            Bytes  Class     Attributes

  vals      64x1              1024  double    complex   

>> mat=(mat+mat')/2;
>> ishermitian(mat)

ans =

     1

>> vals=eig(mat);
>> whos vals
  Name       Size            Bytes  Class     Attributes

  vals      64x1               512  double              

我现在到处都可以得到所有预期的结果,并且按照预期花费了一半的时间等等。显然mat=(mat+mat')/2;正在以某种方式解决舍入/精度问题,但它已经#39对我来说不直观的原因。理论上这个操作应该让我回到我已经拥有的东西,因为mat==mat'如果它是Hermitian但我们在这种情况下知道mat~=mat'无论出于何种原因。关于为什么这个操作像小型四舍五入一样工作的任何想法?