# Take real or complex entries of eigensystem or separate them as a whole

Posted 4 months ago
1126 Views
|
33 Replies
|
10 Total Likes
|
 I want to do the conditional assignment of variables as shown below: {val, vec}={{-((1 + I)/Sqrt[2]), (1 + I)/Sqrt[2], -((1 - I)/Sqrt[2]), (1 - I)/ Sqrt[2]}, {{(1 - I)/Sqrt[2], I, (1 + I)/Sqrt[2], 1}, {-((1 - I)/Sqrt[2]), I, -((1 + I)/Sqrt[2]), 1}, {(1 + I)/Sqrt[ 2], -I, (1 - I)/Sqrt[2], 1}, {-((1 + I)/Sqrt[2]), -I, -((1 - I)/Sqrt[2]), 1}}}; If [(Select[{val, vec}//Transpose, Element[#,Reals]&]//Length)>0, {rval,rvec}=Select[{val, vec}//Transpose, Element[#,Reals]&] ] But I didn't come up with a more concise method to achieve this goal. Any hints will be appreciated.Regards,Zhao
33 Replies
Sort By:
Posted 4 months ago
 What are you trying to do? On brief inspection, it seems to me like Select[{val, vec} // Transpose, Element[#, Reals] &] cannot ever be true.Please provide a simplified example that illustrates a specific question that you have.
Posted 4 months ago
 I want to calculate the eigensystem of a real matrix, and then extract the real eigenvectors and eigenvalues, if such terms exist. However, I cannot know whether such a situation exists in advance, so it must be determined in real time based on the actual calculation results. For example, see the following calculations: In[7]:= gen1={{-1,2,-1},{-(3/2),3/2,-(1/2)},{-(1/2),3/2,-(3/2)}}; {val, vec}=Eigensystem[%,Cubics -> True]//ComplexExpand gen2={ {0,0,0,-1}, {1,0,0,0}, {0,-1,0,0}, {0,0,-1,0} }; {val, vec}=gen2//Eigensystem[#,Cubics -> True]&//ComplexExpand Out[8]= {{-1, I, -I}, {{1/2, 1/2, 1}, {3/2 - I/2, 3/2 + I/2, 1}, {3/2 + I/2, 3/2 - I/2, 1}}} Out[10]= {{-((1 + I)/Sqrt[2]), (1 + I)/Sqrt[2], -((1 - I)/Sqrt[2]), ( 1 - I)/Sqrt[ 2]}, {{(1 - I)/Sqrt[2], I, (1 + I)/Sqrt[2], 1}, {-((1 - I)/Sqrt[2]), I, -((1 + I)/Sqrt[2]), 1}, {(1 + I)/Sqrt[2], -I, (1 - I)/Sqrt[2], 1}, {-((1 + I)/Sqrt[2]), -I, -((1 - I)/Sqrt[2]), 1}}} As you can see, in the first example, there are real eigenvalues and eigenvectors, but in the second example, there is no such result.
Posted 4 months ago
 What were you expecting this to give you? {val, vec}//Transpose 
Posted 4 months ago
 See the following: In[17]:= gen1={{-1,2,-1},{-(3/2),3/2,-(1/2)},{-(1/2),3/2,-(3/2)}}; {val1, vec1}=Eigensystem[%,Cubics -> True]//ComplexExpand; Select[{val1, vec1}//Transpose, Element[#,Reals]&] Select[{val1, vec1}, Element[#,Reals]&] Out[19]= {{-1, {1/2, 1/2, 1}}} Out[20]= {} As you can see, without Transpose the real eigen value and eigen vector pairs can't be selected out.
Posted 4 months ago
 Obviously I can execute the code and see what it produces. The point of the question was for you to explain to me in words the semantics of the situation. At the time I asked the question I was suspicious that you had unintentionally generated a structure that would always cause your Element check to fail. I later came to realize that your structure was as you desired but you misunderstood how Element worked.
Posted 4 months ago
 What qualifies? If an element at the top level of {val, vec}//Transpose contains only real values at every level?
Posted 4 months ago
 Because real eigen value corresponding to real eigen vector, and vice versa. So, I think this is enough.
Posted 4 months ago
 Can you just stop making me reverse engineer your code, please? Give me a sample input that you want to process, explain what processing you're trying to do, and give me an expected result to test against.Like, in one case, the first element of {val, vec} // Transpose is {-1, {1/2, 1/2, 1}}. Do you want that specific element to be selected or rejected?In another case, the first element of {val, vec} // Transpose is {(-1 - I)/Sqrt[2], {(1 - I)/Sqrt[2], I, (1 + I)/Sqrt[2], 1}}. Do you want that specific element to be selected or rejected?
Posted 4 months ago
 I want to select all real eigenvalue/vector pairs, so in the first example, I should select it, but in the second example, I should not.
Posted 4 months ago
 Maybe what you want is Select[{val, vec} // Transpose, FreeQ[_Complex]] 
Posted 4 months ago
 Yes. This does the trick: In[47]:= gen1={{-1,2,-1},{-(3/2),3/2,-(1/2)},{-(1/2),3/2,-(3/2)}}; {val1, vec1}=Eigensystem[%,Cubics -> True]//ComplexExpand Select[{val1, vec1}//Transpose, Element[#,Reals]&] Select[{val1, vec1} // Transpose, FreeQ[_Complex]] Out[48]= {{-1, I, -I}, {{1/2, 1/2, 1}, {3/2 - I/2, 3/2 + I/2, 1}, {3/2 + I/2, 3/2 - I/2, 1}}} Out[49]= {{-1, {1/2, 1/2, 1}}} Out[50]= {{-1, {1/2, 1/2, 1}}} But my real goal is to simplify the logic of the If statement in the following code to complete the same assignment operation. In[101]:= gen1={{-1,2,-1},{-(3/2),3/2,-(1/2)},{-(1/2),3/2,-(3/2)}}; {val1, vec1}=Eigensystem[%,Cubics -> True]//ComplexExpand; If [(Select[{val1, vec1}//Transpose, FreeQ[_Complex]]//Length)>0, {rval1,rvec1}=Select[{val1, vec1}//Transpose, FreeQ[_Complex]]//Transpose ] Out[103]= {{-1}, {{1/2, 1/2, 1}}} 
Posted 4 months ago
 Something like this might work Cases[{val, vec} // Transpose // N, {_Real, {__Real}}] 
Posted 4 months ago
 Conversion to numerical value may cause loss of precision, so I don't want to do this.
Posted 4 months ago
 Okay, so we had two questions.Question 1: Given a structure like this, {a, {b, c, d}}, where a,b,c,d are all numbers, how can I determine that all of the numbers are non-complex? For example, given a list of such structures like this, {{2, {2, 2, 2}}, {I, {2, 2, 2}}, {2, {2, I, 2}}}, how could I use Select and some predicate to obtain the result {{2, {2, 2, 2}}}? Answer 1: Select[{{2, {2, 2, 2}}, {I, {2, 2, 2}}, {2, {2, I, 2}}}, FreeQ[_Complex]] Question 2: Given a condition like this, If[Length[complicatedList] > 0, myVariable = complicatedList], how can I avoid repeating complicatedList? complicatedList is actually an expression that filters and restructures a list and so is quite a large expression. I don't want to repeat it because it makes the code hard to read and error prone. Answer 2:First off, I recommend that you don't put the assignment inside the If. Burying assignments is a great way to cause confusion later. Instead, shoot for something like this: myVariable = If[Length[complicatedList] > 0, complicatedList, Missing["no ducklings found"]] This will make it much easier to trace and debug things later. You could use something else other than Missing, a default value for example. Just make sure that the assignment always happens. But this doesn't get rid of the duplication. You could use With for that: myVariable = With[ {temp = complicatedList}, If[Length[temp] > 0, temp, Missing["no ducklings found"]]] If you prefer terse and don't mind the hidden assignments, you could do this: If[(myVariable = Length[complicatedList]) > 0, myVariable, myVariable = Missing["no ducklings found"]] If for some reason the expression Length[complicatedList]) > 0 can fail to definitively produce either True or False, then you should use the 4-argument form of If.
Posted 4 months ago
 The With version seems better, but the last method seem wrong: In[437]:= {val, vec}={{-1, I, -I}, {{1/2, 1/2, 1}, {3/2 - I/2, 3/2 + I/2, 1}, {3/2 + I/2, 3/2 - I/2, 1}}}; myVariable = With[ {temp = Select[{val, vec}//Transpose, FreeQ[_Complex]]}, If[Length[temp] > 0, temp, Missing["no ducklings found"]]] myVariable =If[(myVariable = Length[Select[{val, vec}//Transpose, FreeQ[_Complex]]]) > 0, myVariable, myVariable = Missing["no ducklings found"]] Out[438]= {{-1, {1/2, 1/2, 1}}} Out[439]= 1 
Posted 4 months ago
 Yes, that was a mistake. Good catch! Can you see how to fix it? Also, this kind of mistake is easy to make, so I almost exclusively use With in such situations.
Posted 4 months ago
 Can you see how to fix it? I gave it a rough thought when I posted, but didn't seem to come up with an obvious solution.
Posted 4 months ago
 If[Length[myVariable = complicatedList] > 0, myVariable, myVariable = Missing["no ducklings found"]] By the way, the same sort of mistake was in my other example: myVariable = If[Length[complicatedList] > 0, complicatedList, Missing["no ducklings found"]] I'm very frustrated at this mistake, because we're now overlooking the whole point I was trying to make about how to ask good questions. Did you get the point? Will you try that in the future? Or should I just give up?
Posted 4 months ago
 I'm very frustrated at this mistake, because we're now overlooking the whole point I was trying to make about how to ask good questions. Did you get the point? Will you try that in the future? Or should I just give up? A good or bad habit takes a long time and a lot of practice to form or correct. As far as a single problem is concerned, its role is at best to imperceptibly influence certain habits. So, I think, no matter what, it is not a bad thing. In the world, there is no absolute good or bad, everything depends on specific circumstances. It's like saying: There is no absolute truth!
Posted 4 months ago
 Here is another approach: a = {{1, 0, 0}, {0, 0, 1}, {0, -1, 0}}; b = {{1, 0, 0}, {0, 0, 1}, {0, 1, 0}}; c = {{0, 0, 0, -1}, {1, 0, 0, 0}, {0, -1, 0, 0}, {0, 0, -1, 0}}; getRealES[m_] := Select[Eigensystem[m] // Transpose, FreeQ[Complex]] /. {} -> "None real" In[5]:= getRealES[a] getRealES[b] getRealES[c] Out[5]= {{1, {1, 0, 0}}} Out[6]= {{-1, {0, -1, 1}}, {1, {0, 1, 1}}, {1, {1, 0, 0}}} Out[7]= "None real" 
Posted 4 months ago
 Just a further comment on this question.If the purpose is to distinguish all real and complex eigensystems, the following method is sufficient: In[582]:= Unprotect[a,b,c]; Clear[a,b,c]; a = {{1, 0, 0}, {0, 0, 1}, {0, -1, 0}}; b = {{1, 0, 0}, {0, 0, 1}, {0, 1, 0}}; c = {{0, 0, 0, -1}, {1, 0, 0, 0}, {0, -1, 0, 0}, {0, 0, -1, 0}}; getRealES[m_] := Select[Eigensystem[m,Cubics -> True]//ComplexExpand, FreeQ[Complex]] /. {} -> "None real" getRealES[a] getRealES[b] getRealES[c] Out[588]= "None real" Out[589]= {{-1, 1, 1}, {{0, -1, 1}, {0, 1, 1}, {1, 0, 0}}} Out[590]= "None real" 
Posted 4 months ago
 What's the difference between the following two usages? FreeQ[_Complex] FreeQ[Complex] 
Posted 4 months ago
 In this case there is no difference. Two ways of saying the same thing.
Posted 4 months ago
 A variant: getRealES2[m_] := Select[Eigensystem[m] // Transpose, Element[#, Reals] &] /. {} :> Print["None real"] 
Posted 4 months ago
 In nature, you're defining a function by using SetDelayed (:=). So I can't find any reason to further use the following command: RuleDelayed (:>). I mean, a plain Rule (->) should be enough here.Please correct me if I'm wrong
Posted 4 months ago
 You are right Zhao. A plain Rule works fine.
Posted 4 months ago
 The following is a confirmation of the equivalence of the above two methods: In[681]:= Unprotect[a,b,c]; Clear[a,b,c]; a = {{1, 0, 0}, {0, 0, 1}, {0, -1, 0}}; b = {{1, 0, 0}, {0, 0, 1}, {0, 1, 0}}; c = {{0, 0, 0, -1}, {1, 0, 0, 0}, {0, -1, 0, 0}, {0, 0, -1, 0}}; getRealES[m_] := Select[Eigensystem[m,Cubics -> True]//ComplexExpand, FreeQ[Complex]] /. {} -> "None real" getRealES2[m_] := Select[Eigensystem[m,Cubics -> True]//ComplexExpand, Element[#, Reals] &] /. {} :> Print["None real"] In[688]:= getRealES[a] getRealES[b] getRealES[c] Out[688]= "None real" Out[689]= {{-1, 1, 1}, {{0, -1, 1}, {0, 1, 1}, {1, 0, 0}}} Out[690]= "None real" In[691]:= getRealES2[a] getRealES2[b] getRealES2[c] During evaluation of In[691]:= None real Out[692]= {{-1, 1, 1}, {{0, -1, 1}, {0, 1, 1}, {1, 0, 0}}} During evaluation of In[691]:= None real 
Posted 4 months ago
 Bad code typing Zhao!It should be: Eigensystem[m] // Transpose Not, as in your code: Eigensystem[m, Cubics -> True] // ComplexExpand Very confusing for those who want follow this thread and run the code examples by themselves
Posted 4 months ago
 Maybe not so bad, because they can compare different possibilities, just as shown in the reply by Daniel Lichtblau.
Posted 4 months ago
 I reverse my last post. RuleDelayed is there for a reason. Without it I have seen this happening:
Posted 4 months ago
 Good catch. Really, it seems that RuleDelayed is necessary.
Posted 4 months ago
 As pointed out, the question is quite unclear. I gather the idea is to take real eigenvalues and corresponding eigenvectors. Maybe something like this? gen1 = {{-1, 2, -1}, {-(3/2), 3/2, -(1/2)}, {-(1/2), 3/2, -(3/2)}}; {vals, vecs} = Eigensystem[gen1, Cubics -> True] // ComplexExpand; predicate = FreeQ[N[#], Complex] &; realvals = Select[vals, predicate]; realvecs = Pick[vecs, Map[predicate, vals]]; realsys = {realvals, realvecs} (* Out[252]= {{-1}, {{1/2, 1/2, 1}}} *) 
Posted 4 months ago
 As pointed out, the question is quite unclear. I've re-titled this question as follows, with the hope that it can clear some confusion:Take real or complex entries of eigensystem or separate them as a whole. As for your FreeQ[N[#], Complex] &, I tried the following methods, and they all do the trick: In[29]:= vals Select[vals, FreeQ[N[#], Complex] &] Select[vals, FreeQ[Complex] ] Select[vals, FreeQ[_Complex] ] Select[vals, Element[#, Reals]& ] Out[29]= {-1, I, -I} Out[30]= {-1} Out[31]= {-1} Out[32]= {-1} Out[33]= {-1} But I don't quite understand why do you use N command here.