How can I implement anti-commuting (Grassmann) numbers (variables)?

I am looking for a way to define anti-commuting numbers (variables) in Mathematica. Let say we have a set of four variables like ${x_1,x_2,x_3,x_4}$ from which I need to get all possible permutations, then multiply them so they appear as a sum as

$\qquad x_1*x_2*x_3*x_4+x_1*x_2*x_4*x_3+(22\,{\rm terms})$

But these variables are Grassmann anti-commutative, so whenever we interchange any two of them we should get a negative sign, i.e., $x_1*x_2 = -x_2*x_1$, for example the above expression should appear as

$\qquad x_1*x_2*x_3*x_4-x_1*x_2*x_4*x_3+(22\,{\rm terms})$

I know how to permute the variables, but I do not know how get their signs correctly. Any ideas?

• Your 2nd expression, it should be $x_1*x_2*x_3*x_4-x_1*x_2*x_3*x_4+(22\,{\rm terms})$, and reduce to just $(22\,{\rm terms})$, right? Dec 1 '17 at 5:04

3 Answers

I've been adding to the implementation above for the purposes of understanding Grassmann variables (and Grassmann integration) a bit better. Here are my additional contributions.

Unprotect[NonCommutativeMultiply];
ClearAttributes[NonCommutativeMultiply,Flat]
(*Linearity of addition:*)
NonCommutativeMultiply[H___,Plus[A_,B__],T___]:=NonCommutativeMultiply[H,A,T]+NonCommutativeMultiply[H,Plus[B],T]
(*Scalars come out. Define C[i] symbols to be scalars. *)
ScalarQ[f_]:=Or[NumericQ[f],Head[f]===C]
NonCommutativeMultiply[H___,Times[c_,A__],T___]:=c NonCommutativeMultiply[H,Times[A],T]/;ScalarQ[c]
NonCommutativeMultiply[H___,c_,T___]:=c NonCommutativeMultiply[H,T]/;ScalarQ[c];
(* Allow NonCommutativeMultiply[\[Psi]] to simplify to \[Psi] *)
NonCommutativeMultiply[H_]:=H/;(Head[H]===Symbol);
(*One-way flatness:*)
NonCommutativeMultiply[H___,NonCommutativeMultiply[M___],T___]:=NonCommutativeMultiply[H,M,T];
(*Canonical ordering:*)
NonCommutativeMultiply[H___,B_,A_,T___]:=-NonCommutativeMultiply[H,A,B,T]/;Not[OrderedQ[{B,A}]]
(*Squares vanish:*)
NonCommutativeMultiply[H___,A_,M___,A_,T___]:=0
(* 1**2**3 should simplify to 6, not Times[6,NonCommutativeMultiply[]] *)
NonCommutativeMultiply[]:=Sequence[];


Grassmann Integration definitions. I work with the convention integral(dx x) = 1, where the differential comes first.

(* Linearity of addition: *)
GrassmannIntegrate[var_,a_+b_]:=GrassmannIntegrate[var,a]+GrassmannIntegrate[var,b];
(* Scalars come out: *)
GrassmannIntegrate[var_,c_ y_]:=c GrassmannIntegrate[var,y]/;(FreeQ[c,var]&&FreeQ[c,NonCommutativeMultiply]);
(* Integral of a scalar is zero: *)
GrassmannIntegrate[var_,c_]:=0/;FreeQ[c,var];
(* Integral of var is one: *)
GrassmannIntegrate[var_,var_]:=1;
(* Integral of (a___**var_**b___) is (-1)^k a___**b___: *)
GrassmannIntegrate[var_,x_NonCommutativeMultiply]:=Block[{NonCommutativeMultiply}, Replace[x,NonCommutativeMultiply[a___,var,b___]:> If[Length[{a,b}]==0,1,(-1)^(Length[{a}])NonCommutativeMultiply[a,b]]]];
(* Allow multivariable integrals. Integration is done starting with the last variable passed in, to make sure we don't swap any variables in the integration measure. So eg GrassmannMultivariableIntegrate[{a,b},a**b]\[Equal]-GrassmannMultivariableIntegrate[{b,a},a**b] *)
GrassmannMultivariableIntegrate[vars_List,x_]:=
If[Length[vars]==1,GrassmannIntegrate[vars[[1]],x],
GrassmannMultivariableIntegrate[Most[vars], GrassmannIntegrate[Last[vars],x]]];


Testing it:

In[] := {a**a===0,
a**b+b**a===0,
1**2**3===6,
(a**b+c**d)**(a**b+c**d)===2 a**b**c**d,
GrassmannIntegrate[a,b**a]===-b,
GrassmannIntegrate[a,(a-b)**(C[1]+C[2] a)]==C[1]+C[2]b
}
Out[] := {True,True,True,True,True,True}


Find the determinant of a matrix using differential forms:

In[]:= matrix=RandomInteger[{-10,10},{3,3}]
{v1,v2,v3}=Total/@Thread[Times[matrix,{dx,dy,dz}]]
v1**v2**v3
Det[matrix]
Out[]= {{-1,-6,3},{-3,10,-6},{-6,10,1}}
Out[]= {-dx-3 dy-6 dz,-6 dx+10 dy+10 dz,3 dx-6 dy+dz}
Out[]= -214 dx**dy**dz
Out[]= -214


I don't recommend this for production code! It's already painfully slow for a seven by seven matrix, so clearly this isn't fit for any sort of numerics. I haven't given any thought to optimization either.

In[]:= matrix=RandomInteger[{-10,10},{7,7}];
mults=Total/@Thread[Times[matrix,{da,db,dc,dd,de,df,dg}]];
AbsoluteTiming[NonCommutativeMultiply@@mults]
Out[]= {102.951,12754089 da**db**dc**dd**de**df**dg}


To define anti-commutative multiplication you first have to choose some canonical ordering. For this you can use for example the OrderedQ function: OrderedQ[{x[1],x[2]}] evaluates to True whereas OrderedQ[{x[2],x[1]}] evaluates to False.

Then you can define some arbitrary symbol having the appropriate properties. I normally use CenterDot because it displays nicely, but you could also use NonCommutativeMultiply (which I find has some annoying preset attributes) or anything else for that matter.

If you define

CenterDot[a___, b_, c_, d___] /; ! OrderedQ[{b, c}] := -CenterDot[a, c, b, d]


Then CenterDot[x[2], x[1], x[3], x[4]] evaluates to -CenterDot[x[1], x[2], x[3], x[4]] and so on. For your particular problem of course

Sum[CenterDot @@ x /@ p, {p, Permutations@Range@4}]


evaluates to 0, but you get the idea.

Finally, you should remember that Mathematica knows nothing a priori about this new anti-commutative multiplication, so you will probably have to define other usual properties, such as linearity, squares evaluating to zero, etc.

You probably want to use NonCommutativeMultiply, as Fidel suggests.

Unprotect[NonCommutativeMultiply];
ClearAttributes[NonCommutativeMultiply, Flat]
(* Canonical ordering: *)
NonCommutativeMultiply[H___, B_, A_,T___] := -NonCommutativeMultiply[H, A, B, T] /; Not[OrderedQ[{B, A}]]
(* Linearity of addition: *)
NonCommutativeMultiply[H___, Plus[A_, B__], T___] := NonCommutativeMultiply[H, A, T] + NonCommutativeMultiply[H, Plus[B], T]
(* Scalars come out: *)
ScalarQ[f_] := Or[NumericQ[f]](* you can put other conditions in the Or *)
NonCommutativeMultiply[H___, Times[c_, A__], T___] := c NonCommutativeMultiply[H, Times[A], T] /; ScalarQ[c]
NonCommutativeMultiply[H___, c_, T___] := c NonCommutativeMultiply[H, T] /; ScalarQ[c]
(* Squares vanish: *)
NonCommutativeMultiply[H___, A_, M___, A_, T___] := 0
(* One-way flatness: *)
NonCommutativeMultiply[H___, NonCommutativeMultiply[M___], T___] :=  NonCommutativeMultiply[H, M, T]


Now x1**x2**x3**x4 remains as-is but x2**(x3+x1)**x4**x1 evaluates to - (x1**x2**x3**x4) (the term with x1 twice evaluated to 0).

• Great suggestions, it solved my problem, thx Dec 2 '17 at 14:46
• Beware future visitors: (a**b+c**d)**(a**b+c**d)=2 a**b**c**d isn't handled properly by this implementation.
– user273
Mar 14 '18 at 22:33
• If the "CanonicalOrdering" and "squares vanish" definitions are moved after "One-way flatness", the procedure simplifies correctly (assuming a,b,... are grassmann monomials). This ensures we distribute, etc. as far as possible before figuring out signs and zeros.
– user273
Mar 14 '18 at 22:50
• You can also change "canonical ordering" to NonCommutativeMultiply[H__, B_, A_, T___] := -NonCommutativeMultiply[H, A, B, T] /; OrderedQ[{A, B}] NonCommutativeMultiply[H___, B_, A_, T__] := -NonCommutativeMultiply[A, B, T] /; OrderedQ[{A, B}]. But moving one-way flatness to the top is the best way to do it. Mar 14 '18 at 22:56