How to solve the polynomial eigenvalue in python?

前端 未结 2 1155
清歌不尽
清歌不尽 2021-01-12 23:45

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

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

where

相关标签:
2条回答
  • 2021-01-13 00:20

    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!

    0 讨论(0)
  • 2021-01-13 00:40

    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))
    
    0 讨论(0)
提交回复
热议问题