Skip to main content

list manipulation - How to define even permutations correctly?


I define even permutations as following, but there may be some error. I use it in two different way and get different output.


evenper[x_] := Select[Permutations[x], Signature[#] == 1 &]

Way 1:


evenper[x_] := Select[Permutations[x], Signature[#] == 1 &]
manual=evenper[{a, b, c, d}]
phi = 1.61803398875;

p1 = manual /. {a -> phi, b -> 1, c -> 1/phi, d -> 0};
p2 = manual /. {a -> phi, b -> 1, c -> -1/phi, d -> 0};
p3 = manual /. {a -> phi, b -> -1, c -> 1/phi, d -> 0};
p4 = manual /. {a -> phi, b -> -1, c -> -1/phi, d -> 0};
p5 = manual /. {a -> -phi, b -> 1, c -> 1/phi, d -> 0};
p6 = manual /. {a -> -phi, b -> 1, c -> -1/phi, d -> 0};
p7 = manual /. {a -> -phi, b -> -1, c -> 1/phi, d -> 0};
p8 = manual /. {a -> -phi, b -> -1, c -> -1/phi, d -> 0};
list1=Union[p1, p2, p3, p4, p5, p6, p7, p8]//Sort;


This result is what I want.


Way 2:


evenper[x_] := Select[Permutations[x], Signature[#] == 1 &]

phi = 1.61803398875;
list20 = #*{phi, 1, 1/phi, 0} & /@ (Tuples[{{1, -1}, {1, -1}, {1, -1}, {1}}]);
list2 = Flatten[evenper[#] & /@ list20, 1] // Sort;

But you will find list1 != list2 as following


Position[list1, {-1.618033988749895`, 0, 0.6180339887498948`, -1}]

Position[list2, {-1.618033988749895`, 0, 0.6180339887498948`, -1}]
(*{}*)
(*{{6}}*)

Answer



Thanks for updating your Question. With the new, clearer example I believe I can see the issue.


Analysis


The first method uses evenper on Symbolic values that are in canonical order:


r1 = evenper[{a, b, c, d}]



{{a, b, c, d}, {a, c, d, b}, {a, d, b, c}, {b, a, d, c}, {b, c, a, d}, {b, d, c, a},
{c, a, b, d}, {c, b, d, a}, {c, d, a, b}, {d, a, c, b}, {d, b, a, c}, {d, c, b, a}}

Recalling the definition of Signature



Signature[list]
    gives the signature of the permutation needed to place the elements of list in canonical order.



We cannot therefore expect the same permutations to be selected if evenper is used on on elements that are not in canonical order:


rls = {a -> 2, b -> 1, c -> 3, d -> 4};

r2 = evenper[{a, b, c, d} /. rls]
r2 /. Reverse[rls, 2]
% === r1


{{2, 1, 4, 3}, {2, 3, 1, 4}, {2, 4, 3, 1}, {1, 2, 3, 4}, {1, 3, 4, 2}, {1, 4, 2, 3},
{3, 2, 4, 1}, {3, 1, 2, 4}, {3, 4, 1, 2}, {4, 2, 1, 3}, {4, 1, 3, 2}, {4, 3, 2, 1}}

{{a, b, d, c}, {a, c, b, d}, {a, d, c, b}, {b, a, c, d}, {b, c, d, a}, {b, d, a, c},
{c, a, d, b}, {c, b, a, d}, {c, d, b, a}, {d, a, b, c}, {d, b, c, a}, {d, c, a, b}}


False

Solution


If you wish to apply a certain set of permutations to arbitrary expressions, regardless of their canonical ordering, you can first permute a list of indices (natural numbers) and then use Part to extract them from the expression list:


Select[Permutations @ Range @ 3, Signature[#] == 1 &]
{z, a, p}[[#]] & /@ %


{{1, 2, 3}, {2, 3, 1}, {3, 1, 2}}


{{z, a, p}, {a, p, z}, {p, z, a}}

Applied to your problem:


perms = Select[Permutations @ Range @ 4, Signature[#] == 1 &];

phi = 1.61803398875;

tup = # {phi, 1, 1/phi, 0} & /@ Tuples[{1, -1}, 4];


result = Union @@ Outer[Part, tup, perms, 1];

result == list1


True



As rasher informed me in a comment a greatly improved method for Mathematica 8 or later is to use AlternatingGroup and Permute as follows:


fn = # ~Permute~ AlternatingGroup[Length @ #] &;


fn @ {z, a, p}


{{z, a, p}, {a, p, z}, {p, z, a}}

perms === fn @ Range @ 4


True


Comments