3
$\begingroup$

I want to sort the arguments of a function f while multiplying with the signature of the permutation, i.e. f is totally antisymmetric function. My idea was something like

f[2, 4, 3, 1] /. {f[x1_, x2_, x3_, x4_] -> Signature[{x1, x2, x3, x4}]*f[Sort[{x1, x2, x3, x4}][[1]], Sort[{x1, x2, x3, x4}][[2]], Sort[{x1, x2, x3, x4}][[3]], Sort[{x1, x2, x3, x4}][[4]]]}

where I would have expected the output to be

- f[1, 2, 3 ,4]

but instead I just get

f[2, 4, 3, 1]

Any ideas on how to achieve this?

$\endgroup$
2
  • 2
    $\begingroup$ How about f[{2, 4, 3}] /. f[l_List] :> (Signature[l] f[Sort[l]]), which gives -f[{2, 3, 4}] $\endgroup$
    – MelaGo
    Commented Jul 16 at 22:02
  • 2
    $\begingroup$ The signature of {2,4,3,1} is 1, not -1, so that part's not the issue. Use RuleDelayed instead of Rule, i.e., replace -> with :>. Then your code works. But f[4, 2, 3, 1] /. f[xs__] :> Signature[{xs}] f @@ Sort[{xs}] is shorter. $\endgroup$
    – march
    Commented Jul 17 at 0:09

1 Answer 1

5
$\begingroup$

Signature and Sort work on arbitrary heads, not just List:

f[3, 4, 2, 1] /. y_f :> Signature[y] Sort[y]

(* -f[1, 2, 3, 4] *)

f[3, 4, 2, 1] // Signature[#] Sort[#] &

(* -f[1, 2, 3, 4] *)

Another way:

Block[{f},
 call : f[x__] /; ! OrderedQ[{x}] && ! TrueQ@$sorting :=
  Block[{$sorting = True}, Signature[call] Sort[call]];
 f[3, 4, 2, 1]
 ]

(* -f[1, 2, 3, 4] *)

If you remove the enclosing Block[{f},...], the definition becomes permanent so that the antisymmetric property is automatically done. That's up to you.

Note: Instead of OrderedQ[{x}], one could use OrderedQ[Unevaluated@call]. Like Sort, its argument may have any head. But I chose the code with fewer letters.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.