0
$\begingroup$

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.

$\endgroup$
5
  • 1
    $\begingroup$ 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. $\endgroup$
    – Natas
    Aug 15 '20 at 8:25
  • 1
    $\begingroup$ Or do you require that the entries of the random matrix be all integers? That makes the problem hard. $\endgroup$
    – Natas
    Aug 15 '20 at 8:33
  • $\begingroup$ @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. $\endgroup$ Aug 15 '20 at 8:52
  • $\begingroup$ I would rename the question to "Generate random matrix with specific eigenvalues". $\endgroup$
    – Natas
    Aug 15 '20 at 9:04
  • $\begingroup$ @Natas OK, I agree with your suggestion. Please revise it. $\endgroup$ Aug 15 '20 at 9:05
4
$\begingroup$

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
  ]
$\endgroup$
2
  • $\begingroup$ Thank you, but when I need more than 2 solutions, your method encountered difficulties. $\endgroup$ Aug 15 '20 at 9:05
  • $\begingroup$ Thanks for pointing this out. I guess the problem is hard after all. $\endgroup$
    – Natas
    Aug 15 '20 at 9:10

Not the answer you're looking for? Browse other questions tagged or ask your own question.