4
$\begingroup$

I'm trying to implement a function which, given a matrix with one free parameter, would return the value of the parameter at which the lowest eigenvalue of the matrix is equal to a certain number.

Importantly, I'm planning to run this algorithm for extremely large sparse matrices, so I would like to use Arnoldi method.

Here's my attempt:

FitMat[matrix_, lowest_, param_, starting_, howmany_] := 
  Module[{mat, fu},
   mat[x_] := matrix /. {param -> x};
   fu[x_] := Min[Eigenvalues[mat[x], howmany
      , Method -> {"Arnoldi", "Criteria" -> "RealPart"}
      ]];
   Return[
    x /. FindRoot[fu[x] == lowest, {x, starting}
      ]
    ];
   ];

FitMat[( {
   {1, 2, 1},
   {3, 4, 1},
   {x, 4, 9}
  } ), -3, x, 50, 1]

This, however, results in the following error:

Eigenvalues::arm: Method -> Arnoldi can only be used for matrices of machine- or arbitrary-precision real numbers.

Please note that replacing mat[x_] and/or fu[x_] with mat[x_?NumericQ] and/or fu[x_?NumericQ] totally ruins the code, even if the Method specification is not used.

Could anyone please fix my solution or come up with a better one?

(Of course, the problem I'm trying to solve is highly non-linear; however, I typically do have a pretty good estimate for the value of starting. So, for small matrices the same code without specifying the Method works well.)

$\endgroup$
  • $\begingroup$ Does defining the function give this error? Or calling it? If so, what are the arguments? $\endgroup$ – mikado Oct 21 '19 at 22:10
  • 1
    $\begingroup$ Calling. Provided an example. $\endgroup$ – mavzolej Oct 21 '19 at 22:35
  • $\begingroup$ What do you mean by fu[x_?NumericQ] totally ruins the code? Without it I'm getting messages about a singular Jacobian whenever I try to insert the initial condition inside the function to avoid that issue. $\endgroup$ – b3m2a1 Oct 22 '19 at 4:59
  • $\begingroup$ However, if you just comment the line with Method, the code works as it should. $\endgroup$ – mavzolej Oct 22 '19 at 7:01
  • 1
    $\begingroup$ I was just drawing the parallel with this question - in my case, adding _NumericQ to definitions does not seem to resolve the issue. $\endgroup$ – mavzolej Oct 22 '19 at 7:06
5
$\begingroup$

I think there are a few things going on.

First, as the error message says, the Arnoldi method requires machine- or arbitrary-precision real numbers. Your matrix is made of integers, hence the message.

Second, you do need fu[x_?NumericQ] to avoid FindRoot from prematurely evaluating fu without a number.

Finally, for your example, there appears to be no such root. If you insert

Print[Plot[fu[x], {x, -100, 100}, PlotRange -> All]];

into FitMat, you'll see

Mathematica graphics

Clearly, this never equals -3, so FindRoot fails.

If you try

FitMat[({{1., 2., 1.}, {3., 4., 1.}, {x, 4., 9.}}), 15, x, 50, 1]

instead, you get the answer 63.0769 with no errors or messages.

EDIT:

To find where the smallest (most negative) eigenvalue equals -3 you can use the -1 option for the Arnoldi method together with a Shift. No Min needed!

FitMat[matrix_, lowest_, param_, starting_] := 
  Module[{mat, fu}, mat[x_] := matrix /. {param -> x};
   fu[x_?NumericQ] := 
    Eigenvalues[mat[x], -1, 
     Method -> {"Arnoldi", "Criteria" -> "RealPart", 
       "Shift" -> -1000}];
   Print[Plot[{fu[x], lowest}, {x, -100, 100}, PlotRange -> All]];
   Return[x /. FindRoot[fu[x] == lowest, {x, starting}]];];

FitMat[({{1., 2., 1.}, {3., 4., 1.}, {x, 4., 9.}}), -3, x, 50]

Mathematica graphics

(* 52. *)
$\endgroup$
  • $\begingroup$ If you run Eigenvalues[( { {1, 2, 1}, {3, 4, 1}, {52., 4, 9} } )], you will see that the lowest eigenvalue is -3. $\endgroup$ – mavzolej Oct 22 '19 at 12:33
  • $\begingroup$ Yes, but your Min is outside the Eigenvalues[{{1, 2, 1}, {3, 4, 1}, {52., 4, 9}}, 1, Method -> {"Arnoldi", "Criteria" -> "RealPart"}], which returns only one eigenvalue (the largest), so you might need to rethink you approach. $\endgroup$ – Chris K Oct 22 '19 at 12:40
  • 2
    $\begingroup$ Try Eigenvalues[{{1, 2, 1}, {3, 4, 1}, {52., 4, 9}}, -1, Method -> {"Arnoldi", "Criteria" -> "RealPart", "Shift" -> -1000}] instead -- see this answer by @CarlWoll. $\endgroup$ – Chris K Oct 22 '19 at 12:43
  • $\begingroup$ Thank you so much for the answer and comments! I was confused because of misunderstanding what "Criteria" -> "RealPart" does. $\endgroup$ – mavzolej Oct 22 '19 at 12:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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