如何解决python中的多项式特征值?

时间:2011-11-24 05:04:31

标签: python matlab numpy scipy

在我的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。请注意,我处理非线性特征值问题的更一般情况(在某种意义上它与λ有非线性依赖关系)。要了解该方法,请阅读代码注释中提到的文章。

2 个答案:

答案 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))