Eigendecomposition: Python Example¶
Example¶
In [ ]:
# import SymPy. It is a neat Python library for symbolic mathematics
from sympy import *
In [ ]:
# Define a 4x4 matrix
# You might also want to try other matrices.
A = Matrix([[2,-1,-1,0],[-1,3,-1,-1], [-1,-1,3,-1],[0,-1,-1,2]])
A
Out[ ]:
$\displaystyle \left[\begin{matrix}2 & -1 & -1 & 0\\-1 & 3 & -1 & -1\\-1 & -1 & 3 & -1\\0 & -1 & -1 & 2\end{matrix}\right]$
In [ ]:
A.eigenvects
Out[ ]:
sympy.matrices.matrices.MatrixEigen.eigenvects
def eigenvects(error_when_incomplete=True, iszerofunc=_iszero, **flags)
Compute eigenvectors of the matrix. Parameters ========== error_when_incomplete : bool, optional Raise an error when not all eigenvalues are computed. This is caused by ``roots`` not returning a full list of eigenvalues. iszerofunc : function, optional Specifies a zero testing function to be used in ``rref``. Default value is ``_iszero``, which uses SymPy's naive and fast default assumption handler. It can also accept any user-specified zero testing function, if it is formatted as a function which accepts a single symbolic argument and returns ``True`` if it is tested as zero and ``False`` if it is tested as non-zero, and ``None`` if it is undecidable. simplify : bool or function, optional If ``True``, ``as_content_primitive()`` will be used to tidy up normalization artifacts. It will also be used by the ``nullspace`` routine. chop : bool or positive number, optional If the matrix contains any Floats, they will be changed to Rationals for computation purposes, but the answers will be returned after being evaluated with evalf. The ``chop`` flag is passed to ``evalf``. When ``chop=True`` a default precision will be used; a number will be interpreted as the desired level of precision. Returns ======= ret : [(eigenval, multiplicity, eigenspace), ...] A ragged list containing tuples of data obtained by ``eigenvals`` and ``nullspace``. ``eigenspace`` is a list containing the ``eigenvector`` for each eigenvalue. ``eigenvector`` is a vector in the form of a ``Matrix``. e.g. a vector of length 3 is returned as ``Matrix([a_1, a_2, a_3])``. Raises ====== NotImplementedError If failed to compute nullspace. Examples ======== >>> from sympy import Matrix >>> M = Matrix(3, 3, [0, 1, 1, 1, 0, 0, 1, 1, 1]) >>> M.eigenvects() [(-1, 1, [Matrix([ [-1], [ 1], [ 0]])]), (0, 1, [Matrix([ [ 0], [-1], [ 1]])]), (2, 1, [Matrix([ [2/3], [1/3], [ 1]])])] See Also ======== eigenvals MatrixSubspaces.nullspace
In [ ]:
# eigenvects() returns a list of tuples of the form (eigenvalue, algebraic_multiplicity, [eigenvectors])
# We will only need the eigenvalues and eigenvectors
eig_vecs = A.eigenvects()
eig_vecs[0]
Out[ ]:
(0, 1, [Matrix([ [1], [1], [1], [1]])])
In [ ]:
# Extract the eigenvectors from eig_vecs
v = [v for ev in eig_vecs for v in ev[-1]]
v
Out[ ]:
[Matrix([ [1], [1], [1], [1]]), Matrix([ [-1], [ 0], [ 0], [ 1]]), Matrix([ [ 0], [-1], [ 1], [ 0]]), Matrix([ [ 1], [-2], [ 0], [ 1]])]
In [ ]:
# Extract the eigenvalues from eig_vecs
λ = [ev[0] for ev in eig_vecs for _ in range(len(ev[-1]))]
λ
Out[ ]:
[0, 2, 4, 4]
In [ ]:
Q = Matrix.hstack(*v)
Q
Out[ ]:
$\displaystyle \left[\begin{matrix}1 & -1 & 0 & 1\\1 & 0 & -1 & -2\\1 & 0 & 1 & 0\\1 & 1 & 0 & 1\end{matrix}\right]$
In [ ]:
Λ = diag(*λ)
Λ
Out[ ]:
$\displaystyle \left[\begin{matrix}0 & 0 & 0 & 0\\0 & 2 & 0 & 0\\0 & 0 & 4 & 0\\0 & 0 & 0 & 4\end{matrix}\right]$
In [ ]:
# Use the relation we found above:
A_new = Q * Λ * Q**-1
A_new
Out[ ]:
$\displaystyle \left[\begin{matrix}2 & -1 & -1 & 0\\-1 & 3 & -1 & -1\\-1 & -1 & 3 & -1\\0 & -1 & -1 & 2\end{matrix}\right]$
In [ ]:
# Verify, that our 'new' matrix is in fact equal to the original one
A_new == A
Out[ ]:
True