【问题标题】:np.linalg.eig gives different eigenvectors for the same matrixnp.linalg.eig 为同一矩阵给出不同的特征向量
【发布时间】:2021-02-01 02:14:07
【问题描述】:

以下基于 Python 3.7.6。

我正在尝试使用一个名为 PySCF 的包来解决简单的计算化学问题。其中一项计算涉及对称为 Fock 矩阵的 2D 数组的评估。 PySCF 使用函数 get_fock() [1, 2] 生成它。对于我的一个测试用例,Fock 矩阵的计算结果为

F = [[ 2. -1.  0.  0.  0. -1.]
 [-1.  2. -1.  0.  0.  0.]
 [ 0. -1.  2. -1.  0.  0.]
 [ 0.  0. -1.  2. -1.  0.]
 [ 0.  0.  0. -1.  2. -1.]
 [-1.  0.  0.  0. -1.  2.]]

我尝试使用energies, C = np.linalg.eig(F) 找到该矩阵的特征值和特征向量,它给出了以下特征向量矩阵:

C = [[-0.40824829  0.57735027  0.40824829  0.57735027  0.2468088   0.08939109]
 [ 0.40824829 -0.28867513  0.40824829  0.28867513 -0.57541553 -0.44927503]
 [-0.40824829 -0.28867513  0.40824829 -0.28867513  0.32860673 -0.53866612]
 [ 0.40824829  0.57735027  0.40824829 -0.57735027  0.2468088  -0.08939109]
 [-0.40824829 -0.28867513  0.40824829 -0.28867513 -0.57541553  0.44927503]
 [ 0.40824829 -0.28867513  0.40824829  0.28867513  0.32860673  0.53866612]]

然而,np.matmul(np.matmul(C.T,F),C) 应该返回一个对角矩阵,其元素是F 的特征值。这不是发生的情况,但我应该注意F正确特征值(单独验证)确实存储在energies 中。

然后我分配了另一个矩阵 F0F 完全相同的元素(这一次,硬编码到脚本中)。在这种情况下,np.linalg.eig(F0) 实际上给了我一个不同的特征向量矩阵:

C0 = [[ 0.23192061  0.41790651 -0.52112089 -0.23192061  0.52112089 -0.41790651]
 [-0.41790651 -0.52112089  0.23192061 -0.41790651  0.23192061 -0.52112089]
 [ 0.52112089  0.23192061  0.41790651 -0.52112089 -0.41790651 -0.23192061]
 [-0.52112089  0.23192061 -0.41790651 -0.52112089 -0.41790651  0.23192061]
 [ 0.41790651 -0.52112089 -0.23192061 -0.41790651  0.23192061  0.52112089]
 [-0.23192061  0.41790651  0.52112089 -0.23192061  0.52112089  0.41790651]]

为了确保我没有发疯,我检查了typeFF0<class 'numpy.ndarray'> 在这两种情况下。我还打印出F-F0,正如预期的那样,它只是一个 0 矩阵。我在下面粘贴了我的脚本,这是对 PySCF 示例脚本之一 [3] 的改编。

import numpy as np
from numpy import zeros, matrix
from pyscf import gto, scf, ao2mo, cc, tools

hubbard_U = 2.
hubbard_t = 1.

mol = gto.M(verbose=4)
n = n_basis = 6
mol.nelectron = 12
mol.verbose = 9
mol.incore_anyway = True

h1 = np.zeros((n,n))
for i in range(n-1):
    h1[i,i+1] = h1[i+1,i] = -hubbard_t # -ve Hubbard t
h1[n-1,0] = h1[0,n-1] = -hubbard_t # periodicity

eri = np.zeros((n,n,n,n))
for i in range(n):
    eri[i,i,i,i] = hubbard_U # Hubbard U

mf = scf.RHF(mol)
mf.conv_tol = 1e-8
mf.get_hcore = lambda *args: h1
mf.get_ovlp = lambda *args: np.eye(n)
mf._eri = ao2mo.restore(8, eri, n)
mf.kernel(np.ones((n, n)))

F = np.copy(mf.get_fock())

print('F =')
print(F)
energies, C = np.linalg.eig(F)
print('\nC =', C)
F0 = [[2., -1.,  0.,  0.,  0.,  0.],
 [-1., 2., -1.,  0.,  0.,  0.],
 [ 0., -1., 2., -1.,  0.,  0.],
 [ 0.,  0., -1., 2., -1.,  0.],
 [ 0.,  0.,  0., -1., 2., -1.],
 [ 0.,  0.,  0.,  0., -1., 2.]]
print('\nF - F0 =', F-F0)

energies0, C0 = np.linalg.eig(F0)
print('\nC0 =', C0)

为什么完全相同的矩阵可以给出两组完全不同的特征向量? 如果正在进行某种简单的酉变换,这不应该影响实值矩阵的np.matmul(np.matmul(C.T,F),C) 关系(如上所述)。 我完全迷失在这里,不禁认为我错过了一些非常基本的东西。任何帮助将不胜感激。

【问题讨论】:

    标签: python python-3.x numpy linear-algebra numpy-ndarray


    【解决方案1】:

    好吧,您的矩阵是对称的,因此可以保证它是可对角化的,其中一些V.T @ F @ VV 是正交矩阵。矩阵V 对列的-1 进行排列和乘法是唯一的。 (或者在对应于相同特征值的子空间上进行旋转,这里不是这种情况,因为您有不同的特征向量)。

    numpy.linalg.eig 的文档说右特征值没有保证的顺序,并且特征向量具有单位长度。这给了我们两个健全性检查。

            D, W = np.linalg.eig(F)
            assert(np.all(np.abs( W @ W.T - np.eye(W.shape[0])) < tol))
            assert(np.all(np.abs( F @ W - W @ np.diag(D)) < tol))
    

    我检查了你的两个矩阵,确实C0F 的特征向量矩阵,而C 不是。

    plt.subplot(121), plt.imshow(C.T @ F0 @ C), plt.title('$C^T F C$')
    plt.subplot(122), plt.imshow(C0.T @ F0 @ C0), plt.title('$C_0 F C_0$')
    

    到目前为止,输入矩阵可能不同。但是当我们检查正交性 C @ C.T ~ I 时,我会说它违反了 eig 的陈述。

    
    plt.subplot(121), plt.imshow(C @ C.T), plt.title('$C C^T$')
    plt.subplot(122), plt.imshow(C0 @ C0.T), plt.title('$C_0 C_0^T$')
    
    

    如果您可以重现故障,这些库将在许多地方使用,这将是一个重要的 (BUG) 发现。

    我针对维度为 2 到 10 的随机矩阵测试了上述断言,并且上述两个条件在 1e-10 的容差范围内有效。可能与F的结构有关吗?还尝试了数千次带有少量附加噪声的 F0,它可以工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-09
      • 2021-10-15
      • 1970-01-01
      • 2018-10-12
      • 2014-11-16
      • 2019-04-27
      • 2012-08-08
      相关资源
      最近更新 更多