我在方阵上使用 NumPy 的 linalg.eig 。我的方阵是二维域的函数,我正在沿着该域上的参数化圆查看其特征向量的复角。只要我考虑的路径是平滑的,我就期望每个特征向量分量的复角是平滑的。然而,在某些情况下,Python 的情况并非如此(尽管其他编程语言也是如此)。对于参数 M=0
(矩阵中出现在对角线上的一些参数),我的组件如下所示:
理想情况下它们应该看起来像(M=0.1
):
我尝试过的:
- 我验证了这两种情况下的矩阵都是 Hermitian 矩阵。
- 当我使用 linalg.eigh 时,
M=0.1
变得不连续,而M=0
有时会变得连续。 - 使用
np.unwrap
没有执行任何操作。 - 分量相位之间的差异(即特征向量
v=[[v1],[v2]]
的np.angle(v1-v2)
)是平滑/连续的,但这不是我想要的。 - 在求解之前修复 NumPy 种子对于种子的不同值没有任何作用。例如:
np.random.seed(1)
。
我还能做什么?我尝试使用 Sympy 的 eigenvects 只是因为我没有选择,并且我在这里提出了另一个问题,询问另一种潜在的方法:How do I force first component of NumPy eigenvectors to be real? 。但是,我不知道还能尝试什么。
这是一个在 Jupyter 笔记本中运行良好的最小工作示例:
import numpy as np
from numpy import linalg as LA
import matplotlib.pyplot as plt
M = 0.01; # nonzero M is okay
M = 0.0; # M=0 causes problems
def matrix_generator(kx,ky,M):
a = 2.46; t = 1; k = np.array((kx,ky));
d1 = (a/2)*np.array((1,np.sqrt(3)));d2 = (a/2)*np.array((1,-np.sqrt(3)));d3 = -a*np.array((1,0));
sx = np.matrix([[0,1],[1,0]]);sy = np.matrix([[0,-1j],[1j,0]]);sz = np.matrix([[1,0],[0,-1]]);
hx = np.cos(k@d1)+np.cos(k@d2)+np.cos(k@d3);hy = np.sin(k@d1)+np.sin(k@d2)+np.sin(k@d3);
return -t*(hx*sx - hy*sy + M*sz)
n_segs = 200; #number of segments in (kx,ky) loop
evecs_along_loop = np.zeros((n_segs,2,2),dtype=float)
# parameterize circular loop
kx0 = 0.5; ky0 = 1; r1=0.2; r2=0.2;
a = np.linspace(0.0, 2*np.pi, num=n_segs+2)
kloop=np.zeros((n_segs+2,2))
for i in range(n_segs+2):
kloop[i,:]=np.array([kx0 + r1*np.cos(a[i]), ky0 + r2*np.sin(a[i])])
# assign eigenvector complex angles
for j in np.arange(n_segs):
np.random.seed(2)
H = matrix_generator(kloop[j][0],kloop[j][1],M)
eval0, psi0 = LA.eig(H)
evecs_along_loop[j,:,:] = np.angle(psi0)
# plot eigenvector complex angles
for p in np.arange(2):
for q in np.arange(2):
print(f"Phase for eigenvector element {p},{q}:")
fig = plt.figure()
ax = plt.axes()
ax.plot((evecs_along_loop[:,p,q]))
plt.show()
对 anon01 评论的澄清:
对于 M=0
,某个值为 (kx,ky)
的样本矩阵将如下所示:
a = np.matrix([[0.+0.j, 0.99286437+1.03026667j],
[0.99286437-1.03026667j, 0.+0.j]])
对于M == 0
,对角线将非零(但为实数)。
最佳答案
我认为总的来说这是一个棘手的问题。根本问题是特征向量(与特征值不同)没有明确定义。具有特征值 c 的 M 的特征向量 v 是任意非零向量,其中
M*v = c*v
特别是对于任何非零标量 s,将特征向量乘以 s 会产生特征向量,即使您(像往常一样)要求特征向量的长度为 1,我们仍然可以自由地乘以绝对值为 1 的任何标量。更糟糕的是,如果 v1,..vd 是 c 的正交特征向量,则 v 的任何非零线性组合也是 c 的特征向量。
因此,不同的特征分解例程很可能会得出非常不同的特征向量,但仍然在完成它们的工作。此外,某些例程可能会为靠近的矩阵生成相距较远的特征向量。
一个简单易处理的情况是,您知道所有特征值都是非简并的(即每个特征空间的维度为 1),并且您碰巧知道对于特定的 i,每个特征向量的第 i 个分量将是非退化的零。然后,您可以将特征向量 v 乘以绝对值为 1 的标量,选择该标量以便相乘后 v[i] 为正实数。在C中
s = conj(v[i])/cabs(v[i])
where
conj(z) is the complex conjugate of the complex number z,
and cabs(z) is the absolute value of the complex number z
请注意,上面假设我们对每个特征向量使用相同的索引,尽管因子 s 因特征向量而异。
这会给特征向量带来一种唯一性,并且人们希望这意味着它们会随着矩阵的参数而不断变化。
关于python - 如何消除 NumPy 特征向量分量的复杂角度的不连续性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67640569/