# Why does my matrix lose rank?

I want to check the rank of a matrix for observability, but Mathematica loses a rank if the matrix contains very large numbers.

Let's say my matrix is

myM = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {5.4 10^0, 1, 1, 1}};


with this matrix I get a rank of 4

MatrixRank[myM]


but if I change the matrix to

myM = {{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {5.4 10^12, 1, 1, 1}};


(first entry in the last row) the rank of my matrix is only 3.

Can somebody explain it to me please?

-
It is because you used an inexact number. This is covered in the docs. Look at Possible Issues under MatrixRank –  m_goldberg Mar 15 at 19:14

The rank of a matrix is typically determined by performing a Gaussian elimination and is given by the number of non-zero rows. In your second case, the large number $5.4\times 10^{12}$, when eventually used as a pivot, gives a badly conditioned matrix (myM2 is the second matrix in your question):

RowReduce[myM2]


RowReduce::luc: Result for RowReduce of badly conditioned matrix {{1.,0.,0.,0.},{0.,1.,0.,0.},{0.,0.,1.,0.},{5.4*10^12,1.,1.,1.}} may contain significant numerical errors. >>

(* {{1, 0., 0., 1.85185*10^-13},
{0, 1, 0., 0.},
{0, 0, 1, 0.},
{0, 0, 0, 0}} *)


If you're aware of the numerical ill-conditionings and want to proceed, you can set a different Tolerance when computing the matrix rank or use exact quantities to get a rank of 4:

MatrixRank[myM2, Tolerance -> 0]
(* 4 *)

MatrixRank[{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {54 10^11, 1, 1, 1}}]
(* 4 *)

-
Thanks rm-rf! Well explained! So you would say my Model is still observable, because my matrix has full rank, even mathematica says it hasn't!? –  Phab Mar 15 at 20:40
Observability says that you can read out the state of the system from the outputs. When the system is poorly conditioned (like this) it means that you will not be able to reliably recover the values of the state. –  bill s Apr 16 at 15:23
Just in case someone has a similar problem: I "fixed" this issue with die poorly conditioned matrix by normalizing it. –  Phab Dec 5 at 10:51

The rank of a matrix is typically determined by performing a Gaussian elimination and is given by the number of non-zero rows.

What rm has described is the procedure for rank determination in exact arithmetic. When inexact numbers enter into the fray, things are... a little different.

The most reliable approach for (numerical) rank determination in inexact arithmetic is the use of the singular value decomposition (SVD). In particular, the (numerical) rank is determined by counting the number of singular values that are not "tiny" (for some application-dependent definition of "tiny"). (See e.g. Golub and Van Loan for more details.)

To use your matrix as an example,

SingularValueList[myM]
{5.4*10^12, 1., 1.}


Only three singular values are returned, and this is consistent with the result returned by MatrixRank[myM]. (Put another way, your matrix may not actually be singular/rank-deficient, but it just as well might be.) As mentioned in rm's answer, one can tweak the Tolerance option, if you know what you're doing:

SingularValueList[myM, Tolerance -> 0]
{5.4*10^12, 1., 1., 1.85185*10^-13}


Now, all four singular values are returned, and thus MatrixRank[myM, Tolerance -> 0] gives 4.

-
Here's some Rationalize weirdness (which I noticed when this question was asked)... –  rm -rf Apr 16 at 14:49
Peculiar, peculiar... –  Ｊ. Ｍ. Apr 16 at 14:58