在犰狳 C++ 中为复杂特征值分解找到不同的值

Posted

技术标签:

【中文标题】在犰狳 C++ 中为复杂特征值分解找到不同的值【英文标题】:Different values found for complex eigenvalue decomposition in Armadillo C++ 【发布时间】:2019-09-23 11:31:53 【问题描述】:

在similar question 之后,与NumPy 中的已知工作解决方案相比,我在Armadillo 中重现相同的特征值分解时遇到问题。以下是示例代码:

cx_mat R

R << (+4.498e+00 + 0.000e+00 * 1i)  <<  (+9.472e-01 - 3.194e+00 * 1i)  <<  (-3.650e-01 - 2.374e-01 * 1i)  <<  (+2.044e+00 - 1.742e+00 * 1i) << endr
  << (+9.472e-01 + 3.194e+00 * 1i)  <<  (+2.467e+00 + 0.000e+00 * 1i)  <<  (+9.169e-02 - 3.091e-01 * 1i)  <<  (+1.668e+00 + 1.085e+00 * 1i) << endr
  << (-3.650e-01 + 2.374e-01 * 1i)  <<  (+9.169e-02 + 3.091e-01 * 1i)  <<  (+4.215e-02 + 0.000e+00 * 1i)  <<  (-7.394e-02 + 2.493e-01 * 1i) << endr
  << (+2.044e+00 + 1.742e+00 * 1i)  <<  (+1.668e+00 - 1.085e+00 * 1i)  <<  (-7.394e-02 - 2.493e-01 * 1i)  <<  (+1.604e+00 + 0.000e+00 * 1i) << endr;

cout << R << endl;

cx_vec sigmai;
cx_mat vi;
eig_gen(sigmai, vi, R);

cout << abs(sigmai) << endl;
cout << sigmai << endl;
cout << vi << endl;

对我来说,这产生了结果:

(+4.498e+00,+0.000e+00)    (+9.472e-01,-3.194e+00)    (-3.650e-01,-2.374e-01)    (+2.044e+00,-1.742e+00)
(+9.472e-01,+3.194e+00)    (+2.467e+00,+0.000e+00)    (+9.169e-02,-3.091e-01)    (+1.668e+00,+1.085e+00)
(-3.650e-01,+2.374e-01)    (+9.169e-02,+3.091e-01)    (+4.215e-02,+0.000e+00)    (-7.394e-02,+2.493e-01)
(+2.044e+00,+1.742e+00)    (+1.668e+00,-1.085e+00)    (-7.394e-02,-2.493e-01)    (+1.604e+00,+0.000e+00)

8.6114e+00
7.9193e-04
5.1075e-04
1.2430e-05

(+8.611e+00,+6.461e-16)
(-7.919e-04,-2.056e-16)
(+5.107e-04,+2.945e-16)
(+1.243e-05,+1.975e-19)

(+7.227e-01,+0.000e+00)    (-8.313e-02,+2.617e-01)    (-4.869e-01,+4.050e-01)    (+3.047e-02,+1.466e-02)
(+1.522e-01,+5.132e-01)    (+7.915e-01,+0.000e+00)    (+2.233e-01,+1.582e-01)    (-3.507e-02,+1.047e-01)
(-5.864e-02,+3.814e-02)    (+3.060e-02,+9.116e-02)    (+8.535e-03,-1.240e-02)    (+9.928e-01,+0.000e+00)
(+3.285e-01,+2.799e-01)    (-4.454e-01,+3.009e-01)    (+7.237e-01,+0.000e+00)    (-1.148e-02,-3.005e-02)

然后,在 Python 中运行相同的计算(使用 NumPy)显示...

R = np.matrix([ \
    [ 4.498+0.j,     0.947-3.194j, -0.365-0.237j , 2.044-1.742j], \
    [ 0.947+3.194j , 2.467+0.j ,    0.092-0.309j,  1.668+1.085j], \
    [-0.365+0.237j,  0.092+0.309j , 0.042+0.j  ,  -0.074+0.249j], \
    [ 2.044+1.742j , 1.668-1.085j, -0.074-0.249j , 1.604+0.j   ] \
])

print(R)
print()

sigmai, vi = lin.eig(R)
print(np.abs(sigmai))
print()
print(sigmai)
print()
print(vi)
print()
[[ 4.498+0.j     0.947-3.194j -0.365-0.237j  2.044-1.742j]
 [ 0.947+3.194j  2.467+0.j     0.092-0.309j  1.668+1.085j]
 [-0.365+0.237j  0.092+0.309j  0.042+0.j    -0.074+0.249j]
 [ 2.044+1.742j  1.668-1.085j -0.074-0.249j  1.604+0.j   ]]

[8.611e+00 9.758e-04 6.199e-04 2.093e-05]

[ 8.611e+00+2.121e-16j -9.758e-04-6.774e-17j  6.199e-04+2.675e-16j
  2.093e-05-1.656e-17j]

[[ 0.723+0.j    -0.095+0.237j -0.379+0.478j  0.203-0.001j]
 [ 0.152+0.513j  0.726+0.j     0.342+0.081j  0.248-0.026j]
 [-0.059+0.038j -0.447-0.005j  0.342-0.076j  0.82 +0.j   ]
 [ 0.328+0.28j  -0.397+0.223j  0.618+0.j    -0.462+0.103j]]

鉴于它是一个特征向量,我已经尝试检查是否有不同的缩放因子在起作用 - 唉,据我所见,没有相关性。有趣的是,只有第一个找到的特征向量/值是相同的。此外,只有实数的值出现在相同的位置。

【问题讨论】:

【参考方案1】:

使用以下代码测试后:

cx_mat test;
test = (R - sigmai(0) * eye((uword) 4, (uword) 4)) * vi.col(0);
cout << test << endl;
test = (R - sigmai(1) * eye((uword) 4, (uword) 4)) * vi.col(1);
cout << test << endl;
test = (R - sigmai(2) * eye((uword) 4, (uword) 4)) * vi.col(2);
cout << test << endl;
test = (R - sigmai(3) * eye((uword) 4, (uword) 4)) * vi.col(3);
cout << test << endl;

输出向量全为零(或接近零)。该方法正常工作,我一定是检查我的数学不正确。

【讨论】:

以上是关于在犰狳 C++ 中为复杂特征值分解找到不同的值的主要内容,如果未能解决你的问题,请参考以下文章

犰狳 C++ LU 分解

在 C++ 中为多维特征矩阵赋值?

C++特征值/向量分解,只需要快速的前n个向量

c++大特征分解速度

lanczos算法及C++实现实对称三对角阵特征值分解的分治算法

特征:找到一个三角矩阵