# How to specify algebraic relations between objects?

so I'm wanting to screw around a bit with Geometric Algebra in Mathematica. To start, I want to create some basis objects: $e_1,~ e_2,~e_3$ and then specify the relations between them which are $$e_i e_j =-e_je_i ~~~\mathrm{For}~~ i \ne j$$ and $$e_i e_j= \bigg{\{} \begin{array}{lr} -e_je_i,& \mathrm{For}~ i\ne j \\ 1,& \mathrm{For}~ i=j \end{array}$$ Hence, I'm hoping that say the command:

Simplify[e1 e2 e1 e2]


Would return

-1


This feels like something Mathematica should be capable of doing fairly elegantly but I really don't know as I'm not a very experienced user. Could anyone shed some light on how they might approach this?

• Typically, I use operations that don't have definitions associated with them (in particular, NonCommutativeMultiply (infix notation: **)), and define replacement rules or destructuring functions to simplify them. How much functionality do you need? What kind of algebra are the e's a basis of? Nov 2, 2016 at 20:21
• The e's are the basis vectors of 'Geometric Algebra' which is essentially a generalization of regular vector algebra and complex numbers. Essentially, if you have two vectors that are elements of the Geometric Algebra, $u$ and $v$, $uv=u \cdot v +u \wedge v$ where the dot product and wedge products there are the operations we're familiar with from regular vector algebra and exterior algebra. Nov 2, 2016 at 20:24
• So is it safe to assume that we extend this basis to the full space by allowing scalar multiplication by elements of a field (complex numbers) and addition of the vectors? So that all elements of the space are straight-up linear combinations of the es? Then, you allow multiplication of the linear combinations by linearly extending multiplication of the basis vectors? Nov 2, 2016 at 20:26
• Yes, that's correct. It's a very nice way to work with vectors. For instance, you can do rotations of any object using $v'=e^{B\theta /2} v e^{-B\theta /2}$ where B is some bivector specifying the plane of rotation, ie it could be $B=e_1 e_2$ for a rotation in the plane spanned by $e_1$ and $e_2$. For vectors lying in the plane of rotation, this simplifies even more to the form you're familiar with from complex numbers, $v'=e^{B\theta}v$ Nov 2, 2016 at 20:32
• I can write something to get you started. I'll add more details later if I can find the time. Nov 2, 2016 at 20:44

There are different ways to go about doing this. I'll set UpValues on e for the multiplication of the basis vectors as you've defined them, and I'll use replacement Rules for the simplification of products of vectors expanded in the basis.

First of all

Unprotect[e]
ClearAll@e
e /: NonCommutativeMultiply[e[i_], e[j_]] /; i < j := -NonCommutativeMultiply[e[j], e[i]]
e /: NonCommutativeMultiply[e[i_], e[i_]] := 1
Protect[e]


This sets up a "normal order" for the products of basis vectors. It might not be what you want, but it aids in simplifying compound expressions. Once you've run the lines above, then (non-commutative) products of the es are automatically sorted according to descending order left to right:

e[3] ** e[3]
(* 1 *)


and

e[1] ** e[2]
(* -e[2] ** e[1] *)


and

e[2] ** e[1]
(* e[2] ** e[1] *)


To extend this basis to a linear space, we form all formal linear combinations of these basis elements. Particular examples are

ClearAll[a,b]
vec1 = Sum[e[j] a[j], {j, 1, 3}]
vec2 = Sum[e[j] b[j], {j, 1, 3}]
(* a[1] e[1] + a[2] e[2] + a[3] e[3] *)
(* b[1] e[1] + b[2] e[2] + b[3] e[3] *)


Then, we can implement some linearity rules and scalar rules

ncmRules = {
a___ ** (-b_) ** c___ :> -a ** b ** c,
a_Plus ** b_ :> (# ** b & /@ a),
a_ ** b_Plus :> (a ** # & /@ b),
x___ ** a_ ** y_ /; FreeQ[a, e] :> a x ** y,
x_ ** a_ ** y___ /; FreeQ[a, e] :> a x ** y,
x___ ** (a_ y_) ** z_ /; FreeQ[a, e] :> a x ** y ** z,
(x_) ** (a_ y_) ** z___ /; FreeQ[a, e] :> a x ** y ** z,
NonCommutativeMultiply[a_] :> a
};


and define a function that applies these rules:

ncmSimplify[expr_] := expr //. ncmRules


For instance,

Collect[vec1 ** vec2 // ncmSimplify, _e ** _e]
(* a[1] b[1] + a[2] b[2] + a[3] b[3]
+ (a[2] b[1] - a[1] b[2]) e[2] ** e[1]
+ (a[3] b[1] - a[1] b[3]) e[3] ** e[1]
+ (a[3] b[2] - a[2] b[3]) e[3] ** e[2] *)


and

e[1] ** e[2] ** e[1] ** e[2] // ncmSimplify
(* -1 *)

• @Mason. See if this works for you. See if you can increase the functionality by adding rules, but be careful of adding rules that lead to infinite recursion, because ncmSimplify is defined using ReplaceRepeated (//.), which scans an expression, replacing parts until it doesn't change anymore. Nov 2, 2016 at 21:02
• Wow that was fast! I'll play around with this tonight, but it looks like it's exactly what I wanted. Yes, your product between two vectors looks good. Scalars are an element of this space. I'll try and add some rules to get more functionality if I can but this is a great start, I'll keep you updated! Nov 2, 2016 at 21:26
• @Mason. I noticed an error in the definition of ncmRules. I missed the factor of b in a b x ** y in the third replacement rule, which would cause the expansion of vec1 ** vec2 to not include the expansion coefficients of vec2. It should be fixed and working now, and I updated the example to show this. Nov 3, 2016 at 16:07
• I hadn't noticed the problem, thanks for catching that. One thing I've noticed since playing around with it over the past little while is that I can't quite figure out how to make Mathematica know that e[1]**e[2]**e[1]**e[2]=-1 Any advice on fixing that out? Nov 3, 2016 at 17:07
• I suspect that the way to do this is to modify ncmRules such that stuff**(-e[i] ** e[j]) -> -1*stuff ** e[i] ** e[j] Nov 3, 2016 at 17:48

There is a new paclet for doing Geometric Algebra:

PacletInstall["https://wolfr.am/N9OenlOc"]
<< GeometricAlgebra;


You can construct multivectors of any algebra with it, and use it in computations:

{e1, e2, e3} = MultivectorBasis[GeometricAlgebra[3], 1];

e1 ** e2 ** e1 ** e2
(e1 ** e2) ^ 2
e1 ^ (3/5)


And more:

Inverse[2 e1]
MultivectorFunction[Exp, e1]
(e1 + 3 e2)["Normalize"]
(e1 + 2 e2 + e3)["Conjugate"]
e1["Dual"]
MultivectorMatrix[e1 + I e2]
ConvertGeometricAlgebra[e1, GeometricAlgebra[0, 3]]
`