# Generate random matrix with specific eigenvalues [duplicate]

I want to generate some matrices of order 3 with eigenvalues 1,2, -2.

mat[lis_List] :=
Module[{k},
While[Eigenvalues[k = RandomInteger[{1, 10}, {3, 3}]] != lis]; k]
Eigenvalues[#] & /@ Table[mat[{1, 2, -2}], 3]


But the above code has been running, how can I do to quickly generate a random matrix that meets the conditions?

Transpose[
EulerMatrix[{k = (2 π)/RandomInteger[{1, 5}], 0, 0}]] . {{1, 0,
0}, {0, 2, 0}, {0, 0, -1}} . EulerMatrix[{k, 0, 0}]
Eigenvalues[%]


I hope there are more and faster ways to accomplish this task.

Note: the elements of the obtained matrix should be all integers or rational numbers. If the rational matrix cannot be obtained, all elements of the matrix can be considered to use real numbers.

• Just use that $\mathrm{det}(M^{-1} A M) = \mathrm{det}(A)$. 0. Set $A = \mathrm{diag}(1, 2, -2)$. 1. Create random matrix $M$ 2. If $M$ is invertible compute $A' = M A M^{-1}$, else go back to 1. – Natas Aug 15 '20 at 8:25
• Or do you require that the entries of the random matrix be all integers? That makes the problem hard. – Natas Aug 15 '20 at 8:33
• @Natas It's better to be all integers or rational numbers. If you still can't find a suitable solution, it can be all real numbers. – A little mouse on the pampas Aug 15 '20 at 8:52
• I would rename the question to "Generate random matrix with specific eigenvalues". – Natas Aug 15 '20 at 9:04
• @Natas OK, I agree with your suggestion. Please revise it. – A little mouse on the pampas Aug 15 '20 at 9:05

## Using similarity transformation

A similarity transformation does not change the eigenvalues of a matrix, i.e. the matrix $$A$$ and $$M^{-1} A M$$ have the same eigenvalues.

Using this you can define a function

randomMatrixWithEigenvalues[eigenvalues_List] :=
Module[{n = Length[eigenvalues], a, m},
a = DiagonalMatrix@eigenvalues;
m = RandomInteger[{1, 10}, {n, n}];
While[Det[m] == 0, m = RandomInteger[{1, 10}, {n, n}];];
Inverse[m].a.m
]


which will in general give you a matrix over the rationals.

eigenvalues = {1, 2, -2};
Sort@eigenvalues ==
Sort@Eigenvalues@randomMatrixWithEigenvalues[eigenvalues]
(* True *)


## Using FindInstance

You can also notice that per definition of eigenvalues the random matrix $$X$$ must satisfy

$$\mathrm{det}(X - \lambda I) = \prod_{i} (\lambda_i - \lambda)$$

and you can therefore also define

randomIntegerMatrixWithEigenvalues[eigenvalues_List] :=
Module[{n = Length[eigenvalues], x, \[Lambda], a},
x = Array[a, {n, n}];
x /. First@FindInstance[
And @@ (# == 0 & /@
CoefficientList[#, \[Lambda]] &@(Subtract @@ (Det[
x - \[Lambda] IdentityMatrix[n]] ==
Times @@ (# - \[Lambda] & /@ eigenvalues)))),
Flatten[{x}],
Integers
]
]


Then you can get a random matrix with integer coefficients

x = randomIntegerMatrixWithEigenvalues[eigenvalues]
(* {{3,2,-2},{-2,-1,-1},{-1,-1,-1}} *)

Sort@eigenvalues == Sort@Eigenvalues@x
(* True *)


## Using HermiteDecomposition

This is adapted from J.M.'s answer to the question Generate “nice” random matrix

randomIntegerMatrixWithEigenvalues[eigenvalues_] :=
Module[{n = Length[eigenvalues], vm, jm},
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@eigenvalues)];
Inverse[vm].jm.vm
]

• Thank you, but when I need more than 2 solutions, your method encountered difficulties. – A little mouse on the pampas Aug 15 '20 at 9:05
• Thanks for pointing this out. I guess the problem is hard after all. – Natas Aug 15 '20 at 9:10