# 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? – mikado Aug 7 '18 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. – Elliot G Aug 7 '18 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. – John Doty Oct 5 '18 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. – Elliot G Aug 7 '18 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." – Elliot G Aug 7 '18 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]] – Carl Woll Aug 7 '18 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}\}$$