Please help me Sort/Split/Gather/Group(by) a set of symbolic
expressions!
(extreme TL;DR at bottom)
I have a set of symbols (which represent 2-vectors in a plane, ultimately) and I want to sort/split/group them symbolically without yet inserting numerical values.
Numeric (fully functional)
I have produced fully functional code with numerical values.
qq[1] = {0, 1}; qq[2] = {-Sqrt[3], -1}/2; qq[3] = {Sqrt[3], -1}/2;φ[{kx_, ky_}] = ArcTan[kx, ky];
Block[{order = 15, rings, stars}, rings[0] = {{0, 0}}; stars[0, 0] = rings[0]; rings[1] = Table[qq[s], {s, 1, 3}]; Do[rings[r] = Complement[ Flatten[Table[rings[r - 1][[s]] + (-1)^(r - 1) qq[σ], {s, 1, Length[rings[r - 1]]}, {σ, 1, 3}], 1], rings[r - 2]], {r, 2, order}]; Do[stars[r, s] = Sort[GatherBy[rings[r], Norm][[s]], φ[#1] < φ[#2] &], {r, 1, order}, {s, 1, Length@GatherBy[rings[r], Norm]}];Column[{stars[1, 1], stars[3, 1], stars[3, 2], Row[{stars[3, 7], " <-intentionally not defined, for example"}]}]]
Explanation:
The code initializes rings[0], rings[1], and stars[0,0].
Then it produces many rings[r], special sets of vectors which are produces by linear combinations of the qq[j]. This is done iteratively by adding certain qq[j] to the previous rings[r], and the Complement ensures that both duplicates are discarded as well as removing elements which exist in rings[r-2] already.
Then special sets stars[r,s] are produced. First, GatherBy is used to collect the elements in terms of their magnitude (Norm). Then, the elements are Sorted by a pure function which uses the \phi (ArcTan) function defined.
The Column portion of the code is included only to sample the desired output.
The elements, special linear combinations of the qq[j], are the "symbols" that need to be both Gathered and Sorted.
Symbolic (not yet functioning properly)
My best attempt to make the above code work without yet specifying the values of the qq[j] is:
Lφ[{a_, b_, c_}] = ArcTan[Sqrt[3] (c - b), 2 a - b - c];Lmag[{a_, b_, c_}] = Sqrt[Abs[a - b/2 - c/2]^2 + (3/4) Abs[b - c]^2]; Block[{order = 15, rings, stars, q1, q2, q3}, rings[0] = {0}; stars[0, 0] = rings[0]; rings[1] = {q1, q2, q3}; Do[rings[r] = Complement[Flatten[Table[rings[r - 1][[s]]+(-1)^(r - 1) Boole[σ ==1] q1 + (-1)^(r - 1) Boole[σ ==2] q2 + (-1)^(r-1) Boole[σ == 3] q3, {s, 1,
Length[rings[r - 1]]}, {σ, 1, 3}], 1],
rings[r - 2]], {r, 2, order}]; Do[stars[r, s] = Sort[Gather[rings[r],
Lmag@Coefficient[rings[r][[#1]], {q1, q2, q3}] ==
Lmag@Coefficient[rings[r][[#2]], {q1, q2, q3}] &][[s]],
Lφ@Coefficient[rings[r][[#1]], {q1, q2, q3}] <=
Lφ@Coefficient[rings[r][[#2]], {q1, q2, q3}] &], {r, 1, order}, {s, 1, Length@GatherBy[rings[r], Norm]}];]
This code gives several errors which are really not the problem with which I would primarily request your assistance, however. Note that I have checked, and the rings[r] part of the symbolic code is fully functional. Only the stars[r,s] portion does not work, because of the symbolic gathering and sorting.
To get at the root of my problem:
MWE
This code illustrates that my functions are capable of finding the magnitudes of the elements, and of course those numerical values can be sorted or gathered or split.
Lφ[{a_, b_, c_}] = ArcTan[Sqrt[3] (c - b), 2 a - b - c];Lmag[{a_, b_, c_}] = Sqrt[Abs[a - b/2 - c/2]^2 + (3/4) Abs[b - c]^2]; Block[{order = 15, rings, stars, q1, q2, q3}, rings[0] = {0}; stars[0, 0] = rings[0]; rings[1] = {q1, q2, q3}; Do[rings[r] =Complement[Flatten[Table[rings[r - 1][[s]] + (-1)^(r-1) Boole[σ ==1] q1 + (-1)^(r - 1) Boole[σ ==2] q2 +(-1)^(r - 1) Boole[σ == 3] q3, {s, 1,Length[rings[r - 1]]}, {σ,1,3}], 1], rings[r - 2]], {r, 2, order}];Column[{Table[ Lmag@Coefficient[rings[3(*r*)][[s]], {q1, q2, q3}], {s, 1, 9}],Sort@Table[
Lmag@Coefficient[rings[3(*r*)][[s]], {q1, q2, q3}], {s, 1, 9}], Gather@Sort@Table[Lmag@Coefficient[rings[3(*r*)][[s]], {q1, q2, q3}], {s, 1,
9}], Split@
Sort@Table[
Lmag@Coefficient[rings[3(*r*)][[s]], {q1, q2, q3}], {s, 1,
9}]}]]
However, if I replace the body of this MWE (starting with Column) with something like
Gather[rings[3], Lmag@Coefficient[rings[3][[#1]], {q1, q2, q3}] &];
or Sort, SortBy, Split, SplitBy, GatherBy, GroupBy, etc., with similar 1 argument or two-argument comparison pure functions, I either get errors or outputs that are not properly sorted or grouped, etc.
Once I can properly gather the symbolic expressions (for example, in this given example, q1-q2+q3 should be in stars[3,1] but 2q1-q2 should be in stars[3,2]), then sorting them by a pure function in the phase may be similar, but assisting me with that as well would be greatly appreciated!
Extreme Context-Free TL;DR Version
Why doesn't this Sort properly?
Lmag[{a_, b_, c_}] = Sqrt[Abs[a - b/2 - c/2]^2 + (3/4) Abs[b - c]^2];
Block[{rings, q1, q2, q3},
rings[3] = {2 q1 - q2, 2 q2 - q1,
2 q1 - q3, q1 + q2 - q3,
2 q2 - q3, q1 - q2 + q3,
-q1 + q2 + q3, 2 q3 - q1,
2 q3 - q2};
Print@Table[Lmag@Coefficient[rings[3][[s]], {q1, q2, q3}], {s, 1, 9}];
Print@rings[3];
Sort[rings[3],
Lmag@Coefficient[rings[3][[#1]], {q1, q2, q3}] <=Lmag@Coefficient[rings[3][[#2]],
{q1, q2, q3}] &]]
Column
andRow
. Those should be used strictly for output formatting, if you are trying to sort things after applying such format functions that could be the source of your trouble. BTW You should throw in some returns so your code can be read without too much side to side scrolling.. $\endgroup$Sort[rings[3], Lmag@Coefficient[#1, {q1, q2, q3}] <= Lmag@Coefficient[#2, {q1, q2, q3}] &]
. The items passed to the sort function are the actual list items, not indices. $\endgroup$Sort
always passes pairs of list items.#
is the same as#1
. Running something like this should be instructive:Sort[Range[4], (Print["args", {#1, #2}]; #1 > #2) &]
$\endgroup$