5
$\begingroup$

I do have some multi-indexed variable, e.g. like this

\begin{align*}f_{123} &= 1\\f_{345} &= 1/2\end{align*}

where $f$ is antisymmetric under permutation of any pair of indices, i.e. e.g. $f_{132}=-1$ and so on. Also, $f_{ijk}=0$ for $(ijk)$ not being a permutation of either $(123)$ or $(345)$. I am wondering what the right "Mathematica way" is to set up such a scenario.

My current attempt:

Define all values depending on the indices

ClearAll[f, f2];
f[{1, 2, 3}] = 1;
f[{3, 4, 5}] = 1/2;

Explicitly set all f to zero if their argument is not {1,2,3} or {3,4,5}.

f[list_ /; list != {1, 2, 3} || {3, 4, 5}] := 0;

Then define an f2 which takes a 3dim list as argument, evaluates the Signature[list] and multiplies with f called with Sorted list:

 f2[list_?(VectorQ[#, NumericQ] &) /; Length[list] == 3] := Signature[list]*f[Sort@list];

This works as I want it to work. However, I feel like there must be another way to accomplish this - and I actually think that my attempt is not the best one (I have a gut feeling that it might miss certain cases and lead to errors at some point).

P.S.: If you do have better suggestions for Tags, I would much appreciate an edit/suggestion.

$\endgroup$
4
  • $\begingroup$ I'd have done f[idx_ /; ! MatchQ[Sort[idx], {1, 2, 3} | {4, 5, 6}]] := 0 myself. $\endgroup$ Commented Apr 1, 2016 at 12:43
  • $\begingroup$ @MartinBüttner Thanks for the suggestion. Of course, it is way more practicable to just use f[_]=0, not thinking straight there :) $\endgroup$
    – Lukas
    Commented Apr 1, 2016 at 12:47
  • $\begingroup$ That depends on your application. Would you want, say, f["stuff"] or f[{1, 2, 3, 4, 5}] to return 0 as well? $\endgroup$ Commented Apr 1, 2016 at 12:49
  • $\begingroup$ @J.M. That's right. Actually, in the way I need it right now it doesn't matter whether I use f[_]:=0 or the explicitly stated "zero cases". However, it is true that this might cause issues if the code develops. So I will probably stick to explicitly stating when f should be zero and when it should stay unevaluated. $\endgroup$
    – Lukas
    Commented Apr 1, 2016 at 12:55

4 Answers 4

3
$\begingroup$

Since v10.1 you can use also OrderlessPatternSequence like this :

f[x : {OrderlessPatternSequence[1, 2, 3]}] := Signature[x]*1
f[x : {OrderlessPatternSequence[3, 4, 5]}] := Signature[x]*1/2

then

f[{2, 1, 3}]

-1

or

f[{5, 3, 4}]

1/2

$\endgroup$
3
  • $\begingroup$ That is really nice! Unfortunately I am still using 10.0.1 and cannot make use of OrderlessPatternSequence. But that seems to a very elegant solution which is also exremely transparent $\endgroup$
    – Lukas
    Commented Apr 1, 2016 at 22:09
  • $\begingroup$ I learned something! $\endgroup$
    – evanb
    Commented Apr 1, 2016 at 23:38
  • $\begingroup$ I decided to accept this answer (although I cannot use it) since it appears to me as the most elegant approach that also differs most from how I did it. $\endgroup$
    – Lukas
    Commented Apr 5, 2016 at 8:48
2
$\begingroup$

Not very elegant, but (hopefully) transparent:

The basic data

p1 = {1, 2, 3}; pp1 = Permutations[p1];
p2 = {4, 5, 6}; pp2 = Permutations[p2];

The function

g[x_] := Which[MemberQ[pp1, x], Signature[x], MemberQ[pp2, x], 
         Signature[x]/2, True, 0]

(* or ending with 1/2] in which case x is returned unevaluated *)

All tuples

t = Tuples[Range[6], 3];
Length[%] == 6^3

(* Out[84]= True *)

Check g on t

{#, g[#]} & /@ t;
Select[%, #[[2]] != 0 &]

(*
{{{1, 2, 3}, 1}, {{1, 3, 2}, -1}, {{2, 1, 3}, -1}, {{2, 3, 1}, 
  1}, {{3, 1, 2}, 1}, {{3, 2, 1}, -1}, {{4, 5, 6}, 1/
  2}, {{4, 6, 5}, -(1/2)}, {{5, 4, 6}, -(1/2)}, {{5, 6, 4}, 1/
  2}, {{6, 4, 5}, 1/2}, {{6, 5, 4}, -(1/2)}}
*)
$\endgroup$
3
  • $\begingroup$ I don't see the sign change anywhere... $\endgroup$ Commented Apr 1, 2016 at 16:49
  • $\begingroup$ @J.M. oops, you are right, I missed it. Now corrected. BTW your elegant solution can't possibly be beaten. $\endgroup$ Commented Apr 1, 2016 at 17:21
  • $\begingroup$ @Dr.WolfgangHintze Indeed a very transparent solution and I like (from a pedagogic point of view) the combination of Permutations and MemberQ. Thanks for this $\endgroup$
    – Lukas
    Commented Apr 1, 2016 at 21:59
2
$\begingroup$

How about

f[{1, 2, 3}] = 1;
f[{3, 4, 5}] = 1/2;
f[list_List /; Not[OrderedQ[list]]] := Signature[list] f[Sort@list]

Only bind the last definition if the argument isn't sorted, in which case sort and use Signature to get the correct sign. Then f[{3,2,1}] yields -1 and f[{4,5,3}] yields 1/2. You can then add f[___]:=0 default, if you want. With that default, f[{1,2,3,4}] and f[{5,1,2,3,4}] yield 0.

You can instead add the default

f[list_ /; OrderedQ[list] && Not[MemberQ[{{1, 2, 3}, {3, 4, 5}}, list]]] := 0

but this line MUST come after the previous list-reordering definition.

$\endgroup$
2
  • $\begingroup$ Also pretty compact solution. Thank you! $\endgroup$
    – Lukas
    Commented Apr 1, 2016 at 22:05
  • $\begingroup$ There might be a smart way to use the DownValues of f to smartly rewrite the last clause in the last line there. $\endgroup$
    – evanb
    Commented Apr 1, 2016 at 23:39
2
$\begingroup$

depending on how you use it , it might be good performance-wise to precompute an array:

fa = SparseArray[
   Flatten[
    Function[{t},
      (  # -> t[[2]] & /@ NestList[RotateLeft, t[[1]], 2])] /@
      { {{1, 2, 3},   1},
        {{2, 1, 3},  -1},
        {{3, 4, 5}, 1/2},
        {{4, 3, 5},-1/2} }, 1] (*,{n,n,n}*) ];
                                  (* ^ add dimension spec to handle #>5 *)
f[list_?(VectorQ[#, NumericQ] &) /; Length[list] == 3 &&
     Max[list] <= 5] := Extract[fa, list]   

f /@ {{1, 2, 3}, {4, 3, 5}, {3, 2, 1},{1,4,5}}

{1, -(1/2), -1, 0}

$\endgroup$
3
  • $\begingroup$ That looks pretty compact. However, I do not understand what the NestList[...] part does (and consequently what it is needed for). Could you elaborate on that briefly? $\endgroup$
    – Lukas
    Commented Apr 1, 2016 at 22:02
  • $\begingroup$ evaluate this: NestList[RotateLeft,{1, 2, 3}, 2], it should be clear. $\endgroup$
    – george2079
    Commented Apr 1, 2016 at 22:27
  • $\begingroup$ True. In what case do you think is the precomputed array favorable? Even for 20 nonzero values, the result is given instantly. So I suspect maybe for more than 3 indices and a few 100 nonzero values? $\endgroup$
    – Lukas
    Commented Apr 2, 2016 at 8:06

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.