Search code examples
pythonnumpymatrixeigenvalueeigenvector

Eigenvector of matrix computed by Python does not appear to be an eigenvector


Apologies in advance, Python is not my strong suit.

The eigenvector corresponding to the real eigenvalue of this matrix (as computed by Python) does not appear to be an eigenvector, whereas the eigenvector as computed by Wolfram Alpha appears to work. (My colleague confirmed that the same pathology appears to be the case when performing the calculation in R, though I do not have the transcript.) Code snippet:

>>> import numpy as np
>>> in_matrix = np.array([[0.904, 0.012, 0.427], [-0.0032, 0.99975, -0.02207], [-0.4271, 0.0186, 0.904]])
>>> evals, evecs = np.linalg.eig(in_matrix)
>>> print evals
[ 0.90388357+0.42760138j  0.90388357-0.42760138j  0.99998285+0.j]
>>> print evecs[2]
[ 0.70696571+0.j  0.70696571-0.j  0.01741090+0.j]
>>> print in_matrix.dot(evecs[2])
[ 0.65501505+0.j  0.70414242+0.j -0.27305604+0.j]

Note that multiplying evecs[2] by the in_matrix variable produces a new vector which is NOT evecs[2] (eigenvector should be 1).

Plugging the same matrix into Wolfram Alpha produces the eigenvector (-0.0474067, -0.998724, 0.0174109) for the real eigenvalue. Multiplying in_matrix by this eigenvector does produce the same vector, as expected.

>>> wolfram_vec = np.array([-0.0474067, -0.998724, 0.0174109])
>>> print in_matrix.dot(wolfram_vec)
[-0.04740589 -0.99870688  0.01741059]

The Wolfram (correct) eigenvector corresponds to a negative Y axis, whereas numpy gives (sqrt(2), sqrt(2), 0).

Bottom line: eigenvector from numpy is not an eigenvector, but Wolfram Alpha eigenvector is correct (and looks it). Can anyone shed any light onto this?

This has been tested on a standard installation of Python 2.7.10 on Mac OS X and on a customised installation of Python 2.7.8 on Centos 6.8.


Solution

  • Quoting the docs:

    v : (..., M, M) array
        The normalized (unit "length") eigenvectors, such that the
        column ``v[:,i]`` is the eigenvector corresponding to the
        eigenvalue ``w[i]``.
    

    You need to extract the columns, evecs[:, i], not the rows, evecs[i].

    In [30]: evecs[:, 2]
    Out[30]: array([-0.04740673+0.j, -0.99872392+0.j,  0.01741090+0.j])
    

    which you may recognize the same as the Wolfram vector. All three eigenvectors are correct:

    In [31]: in_matrix.dot(evecs[:, 0]) - evals[0] * evecs[:, 0]
    Out[31]: 
    array([  5.55111512e-17 +1.11022302e-16j,
            -7.11236625e-17 +1.38777878e-17j,   2.22044605e-16 -1.66533454e-16j])
    
    In [32]: in_matrix.dot(evecs[:, 1]) - evals[1] * evecs[:, 1]
    Out[32]: 
    array([  5.55111512e-17 -1.11022302e-16j,
            -7.11236625e-17 -1.38777878e-17j,   2.22044605e-16 +1.66533454e-16j])
    
    In [33]: in_matrix.dot(evecs[:, 2]) - evals[2] * evecs[:, 2]
    Out[33]: array([  3.46944695e-17+0.j,   4.44089210e-16+0.j,   3.15719673e-16+0.j])
    

    where each result is [0, 0, 0] to within the expected precision.