在我的python代码中,我想解决多项式特征值问题:
A0 + lambda*A1 + lambda^2*A2 + lambda^3*A3 + .... = 0
其中An
是密集矩阵,lambda
是常量。在matlab中,可以使用polyeig function来解决此问题。似乎scipy中没有相同的功能。到目前为止,我能想到的唯一方法就是形成相应的伴随矩阵。这会产生一个等效的线性特征值问题,可以给现有的scipy求解器,但它要大得多,我相信它可能会非常恶劣。
有人可以建议现有的,开源的或免费提供的库可以解决这个问题吗?我对一个可以通过f2py或C / C ++库链接的fortran库非常满意,可以通过cython链接。
编辑:对于任何有兴趣解决python中非线性特征值问题的人来说,我自己编写的代码可以找到here。请注意,我处理非线性特征值问题的更一般情况(在某种意义上它与λ有非线性依赖关系)。要了解该方法,请阅读代码注释中提到的文章。
答案 0 :(得分:2)
This discussion指向将多项式特征值问题转化为广义特征值问题的一般方法,后来可以使用scipy's linear algebra函数求解。希望这有帮助!
答案 1 :(得分:1)
以下是我对 Python 中 polyeig
的实现的看法。作为测试用例,我使用了与 Mathworks 中提供的示例相同的示例。
scaling:特征向量与 Matlab 返回的特征向量不同(因为它们被定义为缩放因子)。我不确定 Matlab 使用什么归一化,因此在这种情况下,我只是通过每个向量的最大值进行归一化。
排序:Matlab 不对特征值进行排序。在该示例中,scipy
似乎以与 Matlab 相同的顺序返回特征值。您可以取消注释脚本中的行以对特征值进行排序。
import numpy as np
from scipy import linalg
def polyeig(*A):
"""
Solve the polynomial eigenvalue problem:
(A0 + e A1 +...+ e**p Ap)x=0
Return the eigenvectors [x_i] and eigenvalues [e_i] that are solutions.
Usage:
X,e = polyeig(A0,A1,..,Ap)
Most common usage, to solve a second order system: (K + C e + M e**2) x =0
X,e = polyeig(K,C,M)
"""
if len(A)<=0:
raise Exception('Provide at least one matrix')
for Ai in A:
if Ai.shape[0] != Ai.shape[1]:
raise Exception('Matrices must be square')
if Ai.shape != A[0].shape:
raise Exception('All matrices must have the same shapes');
n = A[0].shape[0]
l = len(A)-1
# Assemble matrices for generalized problem
C = np.block([
[np.zeros((n*(l-1),n)), np.eye(n*(l-1))],
[-np.column_stack( A[0:-1])]
])
D = np.block([
[np.eye(n*(l-1)), np.zeros((n*(l-1), n))],
[np.zeros((n, n*(l-1))), A[-1] ]
]);
# Solve generalized eigenvalue problem
e, X = linalg.eig(C, D);
if np.all(np.isreal(e)):
e=np.real(e)
X=X[:n,:]
# Sort eigenvalues/vectors
#I = np.argsort(e)
#X = X[:,I]
#e = e[I]
# Scaling each mode by max
X /= np.tile(np.max(np.abs(X),axis=0), (n,1))
return X, e
if __name__=='__main__':
M = np.diag([3,1,3,1])
C = np.array([[0.4 , 0 , -0.3 , 0], [0 , 0 , 0 , 0], [-0.3 , 0 , 0.5 , -0.2 ], [ 0 , 0 , -0.2 , 0.2]])
K = np.array([[-7 , 2 , 4 , 0], [2 , -4 , 2 , 0], [4 , 2 , -9 , 3 ], [ 0 , 0 , 3 , -3]])
X,e = polyeig(K,C,M)
print('X:\n',X)
print('e:\n',e)
# Test that first eigenvector and value satisfy eigenvalue problem:
s = e[0];
x = X[:,0];
res = (M*s**2 + C*s + K).dot(x) # residuals
assert(np.all(np.abs(res)<1e-12))