2

For convenience, let me start with a simple example. The following code calculates the sorted eigenvalues of a 4x4 Hermitian matrix with a parameter x

eigen[x_] := 
 Sort[Eigenvalues[(1 - x^2) KroneckerProduct[PauliMatrix[3], 
      PauliMatrix[0]] + 
    Cos[x] KroneckerProduct[PauliMatrix[1], PauliMatrix[3]] + 
    KroneckerProduct[PauliMatrix[2], PauliMatrix[3]] + 
    3 Sin[x] KroneckerProduct[PauliMatrix[1], PauliMatrix[1]]]]

If I call eigen with a numerical value, say 1.0, then everything works fine. But if I call eigen as eigen[x], the Sort function won't be able to correctly sort the eigenvalues. For example, on my machine, eigen[x] /. {x -> 1.0} returns {-1.61733, 1.61733, -3.56559, 3.56559}.

I want to minimize the difference between the third smallest eigenvalue and the second smallest eigenvalue, so I write FindMinimum[eigen[x][[3]]-eigen[x][[2]], {x, 1.0}]. However, it seems that FindMinimum will try to evaluate the first argument with the symbol x such that the eigenvalues are not correctly sorted.

Is there a way that I can instruct the internal function (e.g., FindMinimum) to leave the first argument unevaluated? I notice that FindMinimum already have HoldAll attribute but still tries to manipulate the symbolic expression.

atbug
  • 685
  • 4
  • 10
  • @J.M.'sennui I haven't, but I already played with NumericQ a bit. If I define the function as eigen[x_?NumericQ]:=..., eigen[x][[1]] will be evaluated to x, which is clearly not what I want. – atbug Dec 25 '20 at 17:37
  • With the definition eigen[x_?NumericQ]:=..., eigen[x] returns unevaluated, so eigen[x][[1]] is the argument of the unevaluated function. You use the function as before, i.e., eigen[1.] – Bob Hanlon Dec 25 '20 at 17:44

1 Answers1

2
Clear["Global`*"]

eigen[x_?NumericQ] := 
 Sort[Eigenvalues[(1 - x^2) KroneckerProduct[PauliMatrix[3], 
      PauliMatrix[0]] + 
    Cos[x] KroneckerProduct[PauliMatrix[1], PauliMatrix[3]] + 
    KroneckerProduct[PauliMatrix[2], PauliMatrix[3]] + 
    3 Sin[x] KroneckerProduct[PauliMatrix[1], PauliMatrix[1]]]]

Use a helper function to evaluate eigen

dif[x_?NumericQ] := Module[{lst = eigen[x]}, lst[[3]] - lst[[1]]]

{min, arg} = FindMinimum[dif[x], {x, 1.0}]

(* {3.4641, {x -> -1.2991310^-8}} )

Bob Hanlon
  • 157,611
  • 7
  • 77
  • 198