Ask Your Question
3

Diagonalize matrix numerically over $\mathbb{C}$

asked 2021-10-07 10:54:43 +0100

SageUserNick gravatar image

updated 2021-10-07 11:13:44 +0100

tmonteil gravatar image

Suppose I have a matrix m:

$$ m = \left(\begin{array}{rr} 2 & -3 \\ 1 & 0 \end{array}\right). $$ It is diagonalizable and has complex eigenvalues. I now want to diagonalize it, but get an error:

In [20]: m = matrix([[2, -3], [1, 0]]); m.diagonalization()  
...   
ValueError: matrix entries must be from a field

When I specify the field m = matrix(CDF, [[2, -3], [1, 0]]), I get ValueError: base field must be exact, but Complex Double Field is not. Specifying ComplexLazyField() instead of CDF raises NotImplementedError.

So, apparently, Sage is trying to diagonalize the matrix symbolically, i.e. exactly. But what if I don't care about exactness and just want a straightforward numerical answer?

This is how I would do it with sympy:

In [22]: import sympy as sp  
          ...: m = sp.Matrix([[2, -3], [1, 0]])  
          ...: m.diagonalize()  
Out[22]:  
(Matrix([    
 [1 - sqrt(2)*I, 1 + sqrt(2)*I],    
 [            1,             1]]),   
 Matrix([     
 [1 - sqrt(2)*I,             0],    
 [            0, 1 + sqrt(2)*I]]))

Notice that the output is actually exact. I know I can run this same Python code in Sage, but I assume there's a more native way to do it.

To sum up, how do I get Sage to diagonalize a matrix over $\mathbb{C}$? How do I change the code if I only need the numerical answer?

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
3

answered 2021-10-07 11:12:44 +0100

tmonteil gravatar image

The errors message are quite clear: you should provide a field that is exact. This is because of numerical stability issues in the algorithms.

Let us try with the first exact field that contains ZZ that we have in mind:

sage: m = matrix(QQ,[[2, -3], [1, 0]])
sage: m.diagonalization()
ValueError: not diagonalizable over Rational Field

The answer tells that the eigenvalues are not rational, so we need to use a larger field: the field of algebraic numbers:

sage: m = m.change_ring(QQbar)
sage: m.diagonalization()
(
[1 - 1.414213562373095?*I                        0]  [                                          1                                           1]
[                       0 1 + 1.414213562373095?*I], [0.3333333333333334? + 0.4714045207910317?*I 0.3333333333333334? - 0.4714045207910317?*I]
)

Wile the results looks numerical, but it is only for screen printing, they are actually genuine algebraic numbers, see for the first entry:

sage: m.diagonalization()[0][0][0]
1 - 1.414213562373095?*I
sage: parent(m.diagonalization()[0][0][0])
Algebraic Field
sage: (m.diagonalization()[0][0][0]).minpoly()
x^2 - 2*x + 3

Now, if you want to get only numerical result, you can do:

sage: m.diagonalization()[0].change_ring(CDF)
[1.0 - 1.414213562373095*I                       0.0]
[                      0.0 1.0 + 1.414213562373095*I]
sage: m.diagonalization()[1].change_ring(CDF)
[                                       1.0                                        1.0]
[0.33333333333333337 + 0.4714045207910317*I 0.33333333333333337 - 0.4714045207910317*I]

By the way, instead of changinf the base ring of the matrix, you can change it for the computation of the diagonalization:

sage: m = matrix([[2, -3], [1, 0]])
sage: m.diagonalization(QQbar)
(
[1 - 1.414213562373095?*I                        0]  [                                          1                                           1]
[                       0 1 + 1.414213562373095?*I], [0.3333333333333334? + 0.4714045207910317?*I 0.3333333333333334? - 0.4714045207910317?*I]
)
edit flag offensive delete link more

Comments

Thank you for a good answer, I accepted it. My mistake was I didn't try other fields. I should have googled for algebraic complex numbers, i.e. QQbar. Also didn't know you can change the field after constructing the matrix.

SageUserNick gravatar imageSageUserNick ( 2021-10-07 11:42:28 +0100 )edit

Is there a way to display the numerically-looking numbers the way sympy does it? I.e. sqrt(2) instead of 1.414213562373?

SageUserNick gravatar imageSageUserNick ( 2021-10-07 11:45:23 +0100 )edit

Note that when you use change_ring method, the original matrix is not modified, but a new one is constructed, this is why i wrote m = m.change_ring(QQbar) and not m.change_ring(QQbar).

tmonteil gravatar imagetmonteil ( 2021-10-07 11:45:57 +0100 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 2021-10-07 10:53:53 +0100

Seen: 1,436 times

Last updated: Oct 07 '21