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}