# Generate "nice" random matrix

I don't frequent this community, so please give criticism if this is a poor question.

I am trying to make a tool which generates a small (say, $$4\times 4$$) matrix with integer entries, which has a "nice" Jordan normal form — i.e., one that can be computed by hand. The purpose is for manual practice.

Here is what I have:

  A := RandomInteger[{-1, 1}, {4, 4}] (*This generates a random 4×4 matrix*)
Dynamic[MatrixForm[A]] (*This is the random matrix*)
Dynamic[MatrixForm[Part[JordanDecomposition[A], 2]]] (*Here is its Jordan Normal form*)


As it is, about $$1$$ in $$10$$ of these matrices has relatively nice Jordan Normal form, and that is with random entries of $$-1,\,0$$, and $$1$$. Complex eigenvalues are fine, but obviously eigenvalues like Root[#^4 - #^2 + 3 # + 2 &, 1] are intractable.

The easiest solution here would be to somehow loop the random generator until the entries in the final output are rational complex numbers. I have tried and failed to use conditional statements to achieve this, so any help would be appreciated.

• Could you generate some nice random matrices, treat them as a Jordan decomposition and create a matrix that should return them? Aug 7, 2018 at 19:23
• Yes but then the question is how to generate random Jordan matrices as well as how to generate a nonzero matrix to conjugate by. Aug 7, 2018 at 19:24
• Why do you say things like Root[#^4-#^2+3 #+2&, 1] are intractable? They're perfectly good algebraic constants. The Root representation has nice properties. For example, real Root constants don't grow parasitic imaginary parts when evaluated numerically. Oct 5, 2018 at 14:23

You can create random matrices until the eigenvalues do not have a Root form:

While[
A = RandomInteger[{-1, 1}, {4, 4}];
!FreeQ[RootReduce @ Eigenvalues[A], _Root]
];

Eigenvalues[A]
JordanDecomposition[A][[2]]


{-2, I Sqrt[2], -I Sqrt[2], 0}

{{-2, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, -I Sqrt[2], 0}, {0, 0, 0, I Sqrt[2]}}

• Beautiful. "While" is exactly what I was looking for; thanks. Aug 7, 2018 at 20:41
• Beginner question: how can I check against two forms in the eigenvalues? For example, I cannot see how to use FreeQ to check for both "Root" and "Sqrt." Aug 7, 2018 at 20:57
• @ElliotG That's a bit tricky. Use | to have multiple patterns, but the pattern for Sqrt is not _Sqrt it is Power[_, 1/2]. So, you could use FreeQ[expr, _Root | Power[_, _Rational]] Aug 7, 2018 at 21:07

I'll present another method to generate "nice" random matrices. I make no claims on the distribution followed by the matrices from my procedure.

This method has three steps:

1. use RandomInteger[] to generate the eigenvalues, and randomly convert clusters of identical eigenvalues into Jordan blocks
2. reduce a random integer matrix to Hermite normal form and take its unimodular factor
3. multiply the generated matrices appropriately

An implementation might look like this:

BlockRandom[SeedRandom["jordan", Method -> "ExtendedCA"]; (* for reproducibility *)
With[{n = 4 (* matrix size *), erange = {-2, 2} (* range of eigenvalues *)},
vm = First[HermiteDecomposition[RandomInteger[{-1, 1}, {n, n}]]];
jm = SparseArray[Band[{1, 1}] ->
(If[Length[#] == 1, {#},
DiagonalMatrix[#] +
DiagonalMatrix[RandomInteger[1, Length[#] - 1],
1]] & /@
Split[Sort[RandomInteger[erange, n]]])];
mat = Inverse[vm].jm.vm]];

MatrixForm[mat]


$$\begin{pmatrix} 0 & 0 & -1 & 0 \\ 0 & 0 & 1 & 0 \\ 1 & 0 & -2 & 0 \\ -2 & 0 & -1 & 2 \\ \end{pmatrix}$$

Check the Jordan form:

MatrixForm /@ JordanDecomposition[mat]


$$\{\begin{pmatrix} 1 & 0 & 0 & 0 \\ -1 & 0 & 1 & 0 \\ 1 & -1 & 0 & 0 \\ 1 & 0 & 0 & 1 \\ \end{pmatrix}, \begin{pmatrix} -1 & 1 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 2 \\ \end{pmatrix}\}$$