Python numpy可以用实数算法对斜对称矩阵进行对角化吗?

Python numpy可以用实数算法对斜对称矩阵进行对角化吗?,python,numpy,matrix,linear-algebra,lapack,Python,Numpy,Matrix,Linear Algebra,Lapack,任何斜对称矩阵(A^T=-A)都可以转换为厄米矩阵(iA)并用复数对角化。但它是把它带入,并找到它的Eige值只使用真正的算术。这在numpy的任何地方都可以实现吗?让我们看看LAPACK库的功能。此例程计算任何实双精度平方矩阵的特征值。此外,此例程位于numpy库的python函数后面 dgeev()使用的方法如中所述。它需要将矩阵A缩减为其S 任何实方阵A都可以表示为: A=QSQ^t 其中: Q是一个实正交矩阵:QQ^t=I S是实块上三角矩阵。S对角线上的块大小为1×1或2×2 事实

任何斜对称矩阵(A^T=-A)都可以转换为厄米矩阵(iA)并用复数对角化。但它是把它带入,并找到它的Eige值只使用真正的算术。这在numpy的任何地方都可以实现吗?

让我们看看LAPACK库的功能。此例程计算任何实双精度平方矩阵的特征值。此外,此例程位于numpy库的python函数后面

dgeev()
使用的方法如中所述。它需要将矩阵
A
缩减为其
S

任何实方阵
A
都可以表示为:

A=QSQ^t

其中:

  • Q
    是一个实正交矩阵:
    QQ^t=I
  • S
    是实块上三角矩阵。S对角线上的块大小为1×1或2×2
事实上,如果
A
是斜对称的,那么这种分解似乎非常接近
A
的A。此外,我们还可以看到,斜对称矩阵A的Schur形式是。。。斜对称

实际上,让我们计算
s
的转置:

S^t=(Q^tAQ)^t
S^t=Q^t(Q^tA)^t
S^t=Q^tA^tQ
S^t=Q^t(-A)Q
S^t=-Q^tAQ
S^t=-S
因此,如果
Q
是特殊正交(
det(Q)=1
),则
S
是通过特殊正交变换获得的块对角形式。另外,可以通过排列
Q
的前两列来计算一个特殊的正交矩阵
P
,并且通过改变
S_{12}
S_{21}
的符号来获得矩阵
a
的另一种舒尔形式
Sd
。实际上,
A=PSdP^t
。然后,
Sd
是通过特殊正交变换获得的
a
的块对角形式

最后,即使应用于实数矩阵返回复数,也几乎不需要复杂的计算

如果您只想计算实Schur形式,请使用带有参数
output='real'
的函数

只需一段代码来检查:

将numpy导入为np
将scipy.linalg作为la导入
a=np.random.rand(4,4)
a=a-np.转置(a)
打印“a=”
打印
#特征值
w、 v=np.linalg.eig(a)
打印“特征值”
打印w
打印“特征向量”
印刷品
#舒尔分解
#进口西皮
#打印scipy.version.version
t、 z=la.schur(a,output='real',lwork=None,overwrite\u a=True,sort=None,check\u finite=True)
打印“舒尔表格”
打印t
打印“正交矩阵”
打印z

<代码> > P>是的,您可以通过在产品的中间插入一个酉变换,从而得到

A=V*U*V^-1=V*T'*T*U*T'*T*V^{-1}

一旦你有了这个想法,你可以通过平铺来优化代码,但是让我们通过显式地形成T来用一种简单的方式来实现

如果矩阵大小为偶数,则所有块都是复数共轭体。否则我们得到一个零作为特征值。特征值保证有零实部,因此第一件事是清除噪声,然后排序,使零位于左上角(任意选择)

显然,我们也需要对特征向量矩阵重新排序,以保持其等价性

vnew = v[:,perm]
到目前为止,我们除了在特征值分解中对中间的特征值矩阵重新排序外,什么也没做。现在我们从复数形式切换到实块对角形式

首先我们要知道有多少零特征值

numblocks = np.flatnonzero(unew).size // 2
num_zeros = n - (2 * numblocks)
然后我们基本上,形成另一个幺正变换(这次很复杂),并以同样的方式坚持它

T = sp.linalg.block_diag(*[1.]*num_zeros,np.kron(1/np.sqrt(2)*np.eye(numblocks),np.array([[1.,1j],[1,-1j]])))

Eigs = np.real(T.conj().T.dot(np.diag(unew).dot(T)))
Evecs = np.real(vnew.dot(T))
这将为您提供新的实值分解。所以代码都在一个地方

n = 5
a = np.random.rand(n,n)
a=a-np.transpose(a)
[u,v] = np.linalg.eig(a)

perm = np.argsort(np.abs(np.imag(u)))
unew = 1j*np.imag(u[perm])
vnew = v[perm,:]
numblocks = np.flatnonzero(unew).size // 2
num_zeros = n - (2 * numblocks)
T = sp.linalg.block_diag(*[1.]*num_zeros,np.kron(1/np.sqrt(2)*np.eye(numblocks),np.array([[1.,1j],[1,-1j]])))
Eigs = np.real(T.conj().T.dot(np.diag(unew).dot(T)))
Evecs = np.real(vnew.dot(T))
print(np.allclose(Evecs.dot(Eigs.dot(np.linalg.inv(Evecs))) - a,np.zeros((n,n))))
给出
真值
。请注意,这是获得真实光谱分解的简单方法。有很多地方需要跟踪数值误差累积

示例输出

Eigs
Out[379]: 
array([[ 0.        ,  0.        ,  0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.        , -0.61882847,  0.        ,  0.        ],
       [ 0.        ,  0.61882847,  0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  0.        ,  0.        , -1.05097581],
       [ 0.        ,  0.        ,  0.        ,  1.05097581,  0.        ]])

Evecs
Out[380]: 
array([[-0.15419078, -0.27710323, -0.39594838,  0.05427001, -0.51566173],
       [-0.22985364,  0.0834649 ,  0.23147553, -0.085043  , -0.74279915],
       [ 0.63465436,  0.49265672,  0.        ,  0.20226271, -0.38686576],
       [-0.02610706,  0.60684296, -0.17832525,  0.23822511,  0.18076858],
       [-0.14115513, -0.23511356,  0.08856671,  0.94454277,  0.        ]])

你为什么要那样?无论哪种方式,特征值都是相同的。
Eigs
Out[379]: 
array([[ 0.        ,  0.        ,  0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.        , -0.61882847,  0.        ,  0.        ],
       [ 0.        ,  0.61882847,  0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  0.        ,  0.        , -1.05097581],
       [ 0.        ,  0.        ,  0.        ,  1.05097581,  0.        ]])

Evecs
Out[380]: 
array([[-0.15419078, -0.27710323, -0.39594838,  0.05427001, -0.51566173],
       [-0.22985364,  0.0834649 ,  0.23147553, -0.085043  , -0.74279915],
       [ 0.63465436,  0.49265672,  0.        ,  0.20226271, -0.38686576],
       [-0.02610706,  0.60684296, -0.17832525,  0.23822511,  0.18076858],
       [-0.14115513, -0.23511356,  0.08856671,  0.94454277,  0.        ]])