2
$\begingroup$

I have looked for an answer to this but the near duplicates I could find seemed slightly distinct.

I have a matrix $A$ which has eigenvalues in pairs $\lambda_1,-\lambda_1,\lambda_2,-\lambda_2,\dots$. I would like to sort the eigensystem such that the eigenvectors are in this order, with the eigenvalues having descending real parts. That is, I want to sort in descending order of the function $f=|\Re(\cdot)|$ and break ties by $g=\Re(\cdot)$.

What I was hoping for was something like:

f[z_] := Abs[Re[z]];
g[z_] := Re[z];
{eval,evec} = SortBy[Eigensystem[N[A]]\[Transpose],{f,z}]\[Transpose];

but this doesn't work. Replacing {f,g} with Abs@*Re does work but not for the tiebreak (neither does {Abs@*Re,Re}).

An example matrix that is $8\times 8$ is the following (although any anti-symmetric matrix has plus/minus pairs of eigenvalues):

A = {{0, 0, -1, -4*I, 0, 0, 0, 0}, 
    {0, 0, 0, -1, 0, 0, 0, 0}, {1, 0, 0, 0, -1, -4*I, 
      0, 0}, {4*I, 1, 0, 0, 0, -1, 0, 0}, 
    {0, 0, 1, 0, 0, 0, -1, -4*I}, {0, 0, 4*I, 1, 0, 0, 
      0, -1}, {0, 0, 0, 0, 1, 0, 0, 0}, 
    {0, 0, 0, 0, 4*I, 1, 0, 0}}

Edit: Additionally, I have realised since writing this that for my application I probably want to organise the sorting differently than I've asked for. In particular I want to order first by f[z_] :=Abs[Re[z]], then break ties first by g[z_]:=Re[z]*Im[z] and second by h[z_]:=Re[z]. So a solution that enables me to simply list three functions f,g,h which I've defined elsewhere in my code would be preferable.

$\endgroup$
  • 2
    $\begingroup$ What is your A? $\endgroup$ – cvgmt Nov 21 at 0:26
  • 1
    $\begingroup$ A is some matrix defined elsewhere in my code. A typical small example would beA = {{0,0,1,-I},{0,0,0,1},{-1,0,0,0},{I,-1,0,0}}. $\endgroup$ – jacob1729 Nov 21 at 12:53
2
$\begingroup$

New Edition

A = {{0, 0, 1, -I}, {0, 0, 0, 1}, {-1, 0, 0, 0}, {I, -1, 0, 0}};
result = Rule @@ Reverse@(A // N // Eigensystem) // Thread // 
  Association
SortBy[result, Re, Abs[#1] > Abs[#2] &]

Old Editon

We need a large A to test the code.

A = {{0, 0, 1, -I}, {0, 0, 0, 1}, {-1, 0, 0, 0}, {I, -1, 0, 0}};
result = Rule @@ Reverse@(A // N // Eigensystem) // Thread // 
  Association
ReverseSortBy[result, {Abs@*Re[#] &, Re[#] &}]

Original

What is your A?

use Association can keep the tie. Since we don't know A,here we set

eval=A//N//Eigensystem//First;
evac=A//N//Eigensystem//Last;
eval = {1 + 3 I, -(1 + 3 I), 2 - I, -(2 - I), 5 + I, -(5 + I), 
   3 - 8 I, -(3 - 8 I), 0.1 - 8 I, -(0.1 - 8 I)};
evac = Array[v, Length@eval];
result = ReverseSortBy[
  Association[Thread[evac -> eval]], {Abs[Re[#]] &, Re[#] &}]
{neweval, newevec} = {Values[result], Keys[result]};
<|v[5] -> 5 + I, v[6] -> -5 - I, v[7] -> 3 - 8 I, v[8] -> -3 + 8 I, 
 v[3] -> 2 - I, v[4] -> -2 + I, v[1] -> 1 + 3 I, v[2] -> -1 - 3 I, 
 v[9] -> 0.1 - 8. I, v[10] -> -0.1 + 8. I|>

{{5 + I, -5 - I, 3 - 8 I, -3 + 8 I, 2 - I, -2 + I, 1 + 3 I, -1 - 3 I, 
  0.1 - 8. I, -0.1 + 8. I}, {v[5], v[6], v[7], v[8], v[3], v[4], v[1],
   v[2], v[9], v[10]}}
| improve this answer | |
$\endgroup$
  • 2
    $\begingroup$ ReverseSortBy[Eigensystem[N[A]] // Transpose, {Abs[Re[#]], Re[#]} &] // Transpose should be enough $\endgroup$ – Roman Nov 21 at 19:39
  • $\begingroup$ I'm having difficulty getting the first solution to work at all. The original solution seems to sort in the opposite order to the one I want - that is, for an example 4x4 matrix I might get real parts in the order (-3.7 , +3.7, -0.27, +0.27) whilst I want (+3.7,-3.7+0.27,-0.27). $\endgroup$ – jacob1729 Nov 23 at 10:54
  • $\begingroup$ @Roman does that differ substantially than what I put in the OP? I can't get that to work either. $\endgroup$ – jacob1729 Nov 23 at 10:55
  • $\begingroup$ @jacob1729 you can edit you original question and add a 10*10 matrix so that we can easy to test the method. $\endgroup$ – cvgmt Nov 23 at 10:58
  • $\begingroup$ @cvgmt I have realised that the order I specified in the OP is not correct for my application and that I actually want order according to different functions - should I open a new question or is it easy to adapt this to ordering first by some function $f(z)$ and tie-break on a different function $g(z)$ where $f,g$ are not Mathematica built-ins like Re and Abs? $\endgroup$ – jacob1729 Nov 23 at 16:30

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.