How to solve the polynomial eigenvalue in python?

梦想与她 提交于 2021-01-18 16:08:50

问题


In my python code, I would like to solve the polynomial eigenvalue problem:

A0 + lambda*A1 + lambda^2*A2 + lambda^3*A3 + .... = 0

where An are dense matrices, and lambda is a constant. In matlab it is possible to solve this problem using the polyeig function. It seems that there is no equivalent functionality in scipy. So far the only way I can think to do it is to form the corresponding companion matrix. This creates an equivalent linear eigenvalue problem which can be given to existing scipy solvers, however it is much larger and I believe it can be quite ill-conditioned.

Can anyone suggest an existing, open source or freely-available library which can solve this problem? I'd be quite happy with a fortran library which could be linked via f2py or C/C++ library to link via cython.

Edit: For anyone interested in solving nonlinear eigenvalue problems in python, the code I wrote myself to solve this problem can be found here. Note that I deal with the more general case of a nonlinear eigenvalue problem (in the sense that it has a nonlinear dependence on lambda). To understand the method, please read the paper mentioned in the code comments.


回答1:


This discussion points to a general method for turning a polynomial eigenvalue problem into a generalized eigenvalue problem, which can later be solved using scipy's linear algebra functions. Hope this helps!




回答2:


Here's my take on the implementation of polyeig in python. As a test case, I used the same example as the one provided in Mathworks.

scaling: The eigenvectors are not the same as the ones returned by Matlab (since they are defined to a scaling factor). I'm not sure what normalization Matlab uses, so in that case I simply normalized by the maximum value of each vector.

sorting: Matlab does not sort the eigenvalues. In that example, scipy seems to return the eigenvalues in the same order as Matlab. You can uncomment the lines in the script to sort the eigenvalues.

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


来源:https://stackoverflow.com/questions/8252428/how-to-solve-the-polynomial-eigenvalue-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!