np.linalg.eig为同一矩阵提供了不同的特征向量

2024-06-16 04:51:01 发布

您现在位置:Python中文网/ 问答频道 /正文

以下内容基于Python 3.7.6

我试图使用一个名为PySCF的包来解决简单的计算化学问题。其中一个计算涉及一个称为Fock矩阵的2D数组的计算。PySCF使用函数get_fock()[12]生成此函数。对于我的一个测试用例,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

然后,我为另一个矩阵F0分配了与F完全相同的元素(这次,硬编码到脚本中)。在这种情况下,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]]

为了确保我没有精神错乱,我在这两种情况下都检查了FF0:<class 'numpy.ndarray'>type。我还打印出了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)关系(如上所述)。我完全迷失在这里,忍不住认为我遗漏了一些非常基本的东西。任何帮助都将不胜感激


Tags: getnp矩阵h1printmf特征向量f0
1条回答
网友
1楼 · 发布于 2024-06-16 04:51:01

好的,你的矩阵是对称的,所以它保证是对角化的,有一些V.T @ F @ V,有一个V正交矩阵。矩阵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$')

Congruency transform on F

在这一点上,输入矩阵可能是不同的。但是当我们检查正交性时,我会说它违反了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$')

Ortogonality checks

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

我对维度为2到10的随机矩阵测试了上述断言,并且上述两个条件在1e-10的公差范围内有效。可能是F的结构?还尝试了与您的F0与一个小的附加噪音数千次,它的作品

相关问题 更多 >