Diagonalization

This is a follow-up on prior work, to find the algebraic and geometric multiplicities of the eigenvalues of a matrix, determine whether or not it's diagonalizable, and if it is, diagonalize it. The matrix is one we have encountered before (at the link provided above):

$$ \left[ \begin{array}{rrrr} 9&-4&-2&-4\\ -56&32&-28&44\\ -14&-14&6&-14\\ 42&-33&21&-45 \end{array} \right] $$

On to the work.

In [1]:
from sympy import *
init_printing(use_latex='mathjax')
In [2]:
M=Matrix([[9,-4,-2,-4],[-56,32,-28,44],[-14,-14,6,-14],[42,-33,21,-45]])
M
Out[2]:
$\displaystyle \left[\begin{matrix}9 & -4 & -2 & -4\\-56 & 32 & -28 & 44\\-14 & -14 & 6 & -14\\42 & -33 & 21 & -45\end{matrix}\right]$

The eigenvals method returns the eigenvalues together with their respective algebraic multiplicities (see Definition 8.40):

In [3]:
M.eigenvals()
Out[3]:
$\displaystyle \left\{ -12 : 2, \ 13 : 2\right\}$

That says that it has eigenvalues $-12$ and $13$, each with algebraic multiplicity $2$. If you call the eigenvects method, you will also get a basis for each eigenspace. In particular, you also recover the geometric multiplicity (Definition 8.40 again): it is simply the number of vectors listed by SymPy for the respective eigenvalue.

In [4]:
M.eigenvects()
Out[4]:
$\displaystyle \left[ \left( -12, \ 2, \ \left[ \left[\begin{matrix}\frac{2}{7}\\1\\1\\0\end{matrix}\right], \ \left[\begin{matrix}0\\-1\\0\\1\end{matrix}\right]\right]\right), \ \left( 13, \ 2, \ \left[ \left[\begin{matrix}- \frac{1}{2}\\0\\1\\0\end{matrix}\right], \ \left[\begin{matrix}\frac{1}{3}\\- \frac{4}{3}\\0\\1\end{matrix}\right]\right]\right)\right]$

So: the eigenspace for eigenvalue $-12$ has dimension $2$ (i.e. the geometric multiplicity of the eigenvalue $-12$ is also $2$, just like its algebraic multiplicity), and the vectors

$$ \left[ \begin{array}{r} \frac 27\\ 1\\ 1\\ 0 \end{array} \right] \text{ and } \left[ \begin{array}{r} 0\\ -1\\ 0\\ 1 \end{array} \right] $$

form a basis for it. Similarly for the other eigenvalue. How about a quick sanity check that these indeed are eigenvectors? I'll pick one for each eigenvalue, being careful to define the entries as Rational numbers so they don't get rounded; that would lead to rounding errors, as described in this longer document I linked a long time ago on our class web page.

Because for each eigenvalue the algebraic and geometric multiplicities coincide, the matrix is diagonalizable: this is a reformulation of Proposition 8.43 in our textbook. In any case, it never hurts to simply ask SymPy to do the diagonalization for us:

In [5]:
P, D = M.diagonalize()

The diagonalize method returns two things: an invertible matrix $P$, and a diagonal matrix $D$ such that $M=PDP^{-1}$. The above command asks for this data and saves it to variables $P$ and $D$ respectively. Let's see what we got:

In [6]:
P
Out[6]:
$\displaystyle \left[\begin{matrix}2 & 0 & -1 & 1\\7 & -1 & 0 & -4\\7 & 0 & 2 & 0\\0 & 1 & 0 & 3\end{matrix}\right]$
In [7]:
D
Out[7]:
$\displaystyle \left[\begin{matrix}-12 & 0 & 0 & 0\\0 & -12 & 0 & 0\\0 & 0 & 13 & 0\\0 & 0 & 0 & 13\end{matrix}\right]$

And let's also check that indeed $M=PDP^{-1}$:

In [8]:
M==P*D*P**(-1)
Out[8]:
True

Yep!

It's maybe good to know what happens if you ask for diagonalization when it's not possible:

In [9]:
A=Matrix([[1,1],[0,1]]); A
Out[9]:
$\displaystyle \left[\begin{matrix}1 & 1\\0 & 1\end{matrix}\right]$
In [10]:
A.diagonalize()
---------------------------------------------------------------------------
MatrixError                               Traceback (most recent call last)
Cell In[10], line 1
----> 1 A.diagonalize()

File ~/.local/lib/python3.8/site-packages/sympy/matrices/matrices.py:386, in MatrixEigen.diagonalize(self, reals_only, sort, normalize)
    385 def diagonalize(self, reals_only=False, sort=False, normalize=False):
--> 386     return _diagonalize(self, reals_only=reals_only, sort=sort,
    387             normalize=normalize)

File ~/.local/lib/python3.8/site-packages/sympy/matrices/eigen.py:697, in _diagonalize(M, reals_only, sort, normalize)
    693 is_diagonalizable, eigenvecs = _is_diagonalizable_with_eigen(M,
    694             reals_only=reals_only)
    696 if not is_diagonalizable:
--> 697     raise MatrixError("Matrix is not diagonalizable")
    699 if sort:
    700     eigenvecs = sorted(eigenvecs, key=default_sort_key)

MatrixError: Matrix is not diagonalizable

As you might have expected, an error.