【问题标题】:How to get real eigenvalues and eigenvectors for a tridiagonal Toeplitz matrix?如何获得三对角 Toeplitz 矩阵的真实特征值和特征向量?
【发布时间】:2018-08-06 14:04:15
【问题描述】:

我构造了一个 100*100 矩阵 k 并想使用 numpy.linalg.eig 对其进行对角化。

k=np.zeros((100,100))
np.fill_diagonal(k,-2)
np.fill_diagonal(k[1:,:-1],1.5)
np.fill_diagonal(k[:-1,1:],0.5)

当我尝试更小的矩阵时,比如

w,v=np.linalg.eig(k[:10,:10])

特征值w 和特征向量v 是实数。但是当我尝试更大的矩阵或整个完整的矩阵时

w,v=np.linalg.eig(k)

wv 原来是复数,虚部不可忽略。

我也尝试scipy.linalg.eig,它有类似的问题。

我想取特征值和特征向量的自然对数。在我的模型中,复数没有物理意义。

我怎样才能只有独立的实数特征值和特征向量?如果没有,如何通过python将复杂的特征值和特征向量变为实数?

【问题讨论】:

  • 你能证明任何三对角方阵都必须有实特征值吗?如果你做不到,那么你能做的并不多。根据维基百科,实对称三对角矩阵具有实特征值,如果所有非对角元素均非零,则所有特征值都是不同的(简单)。您的矩阵似乎不属于此类,因此这些可能是该矩阵的特征值。你没有做错任何事,也无法改变。
  • 有趣的是,直到 64 x 64 大小的所有特征值都是实数。在 65 x 65 大小处出现虚部,并且它们不是很小:大约 0.01。突然的变化,让我怀疑。如果特征值是正确的,并且您不想要复杂的特征值,那么唯一的方法是过滤掉虚部超过某个阈值(1e-16 左右)的那些。
  • 虚部足够大以至于不可忽略。我只是想知道python是否可以将复杂的特征值/向量对更改为真实的。
  • 根据 Wikipedia,如果非对角线值的乘积为正(在这种情况下为 0.5*1.5 = .75),Toepelitz tridiagonal matrix(这似乎是)应该具有真正的特征值
  • @DanielF 很好的发现!特征向量 can also be found in closed form,所以 OP 根本不需要 NumPy 的 eig(这显然在这里挣扎)。

标签: python numpy scipy linear-algebra eigenvalue


【解决方案1】:

转置修正特征值

显然,LAPACK 讨厌非对称三对角矩阵,其中较大的非对角元素位于对角线下方。使用转置矩阵(其中较大元素位于对角线上方)会产生实特征值。 (理论上,矩阵和它的转置具有相同的特征值。)除了是真实的之外,它们同意theoretical values 直到排序和合理的错误。

a, b, c, n = -2, 0.5, 1.5, 100
k = np.zeros((n, n))
np.fill_diagonal(k, a)
np.fill_diagonal(k[:-1, 1:], b)
np.fill_diagonal(k[1:, :-1], c)

theory = a - 2*np.sqrt(b*c) * np.cos(np.pi * np.arange(1, n+1) / (n+1))
computed = np.sort(np.linalg.eig(k.T)[0])
print(np.max(np.abs(theory - computed)))

这会打印出6.183001044490766e-08,这是计算出的特征值和理论特征值之间的最大差异。如果不转置 T,这个误差会上升到 0.26。

特征向量

您还需要特征向量。 np.eig 为转置矩阵返回的特征向量是原始矩阵的 left 特征向量:也就是说,它们满足 vec.dot(k) = lam*vec 而不是 k.dot(vec) = lam*vec。如果您想为原始矩阵获得正确的特征向量,请使用 SciPy 的eig

from scipy import linalg as la
evals, right_evects, left_evects = (np.real(_) for _ in la.eig(k.T, left=True, right=True))

SciPy 的特征解算器与 NumPy 的不同之处在于它返回带有 +0j 的特征向量和特征值;它认为它们很复杂,但正确地将虚部评估为 0。我截断了上面的虚部。请注意,SciPy 的返回顺序是“evals,left,right”,但由于 k 被转置,我左右切换。

让我们检查这些特征向量:

np.max([np.linalg.norm(k.dot(vec) - ev*vec) for ev, vec in zip(evals, right_evects.T)])

返回1.845213984555825e-14,还不错。使用特征向量对数组进行转置是因为zip 从矩阵中选择行,而我们需要列。

奖励内容

那么...问题解决了吗?好吧,我没有说我可以对角化你的矩阵。试图反转由左或右特征向量形成的矩阵看起来像是一个失败的命题;反过来很可怕。

此外,我们不应该过于相信上述特征向量测试。它对正确的特征向量给出了一个微小的错误......让我们在错误的特征向量上尝试一下,那些具有非平凡虚部的。

wrong_evals, wrong_evects = np.linalg.eig(k)
np.max([np.linalg.norm(k.dot(vec) - ev*vec) for ev, vec in zip(wrong_evals, wrong_evects.T)])

这将返回 1.7136373586499598e-14。错误的特征向量甚至比真实的更好!

【讨论】:

  • 非常感谢您的帮助!我能为此做些什么吗?任何其他python包可以处理这个问题?
  • 我也尝试将complex conjugated 对更改为真实的,但这并没有缩小错误范围。
  • @FTP 我认为您的最后一个观察结果可能是解释“错误结果”的候选者,因为这个表达式很可能是算法最小化的。这留下了n=64 的切换之谜,这可能归结为一些硬编码的策略切换。无论如何,我不会称它为错误,它只是在数字上非常棘手。
  • @kinderchan mpmath 也可以解决特征问题,并且特别注意精度,这是图书馆的重点。不幸的是,import mpmath as mp; mp.eig(mp.matrix(k)) 似乎需要很长时间;我没有耐心等待它返回。
【解决方案2】:

@Daniel F 和 @FTP 比我快,看看他们的 cmets,但既然我有代码,我不妨分享一下:

import numpy as np
from scipy import sparse

def tri_toep_eig(a, b, c, n):
    evals = a + 2*np.sqrt(b*c) * np.cos(np.pi * np.arange(1, n+1) / (n+1))
    evecs = np.sin(np.outer(np.arange(1, n+1) * np.pi / (n+1),
                            np.arange(1, n+1))) \
        * np.sqrt(b/c)**np.arange(n)[:, None]
    return evals, evecs

def tri_toep(a, b, c, n):
    return sparse.dia_matrix((np.outer((b, a, c), np.ones((n,))),
                              (-1, 0, 1)), (n, n))
def check(a, b, c, n):
    evals, evecs = tri_toep_eig(a, b, c, n)
    tt = tri_toep(a, b, c, n)
    for eva, eve in zip(evals, evecs.T):
        assert np.allclose(tt @ eve, eva * eve)

check(-2, 0.5, 1.5, 100)

【讨论】:

  • 我是Toepelitz三对角矩阵的新手,你能解释一下参数并添加一些cmets吗?
  • 我碰巧对非对角元素使用了相同的数字作为示例,如果bc 是具有不同值的数组呢?
  • @kinderchan 恐怕这只适用于 Toeplitz 三对角矩阵。 a 是主对角线元素的值,b, c 是两个子对角线。 n 是维度。如果您的对角线不是恒定的,则很可能存在真正的复杂特征值等。
  • 是的,但它们是复共轭特征值 a+bia-bi 对,有些是真实的,我想将复共轭特征值对更改为真实的,是否有 python 库处理这个问题?
  • @kinderchan 更改它们是什么意思?
猜你喜欢
  • 2012-08-08
  • 2018-10-31
  • 2019-04-27
  • 2017-09-27
  • 2011-09-29
  • 1970-01-01
  • 1970-01-01
  • 2012-03-18
  • 1970-01-01
相关资源
最近更新 更多