This page was generated from doc/tutorials/algebra.nblink.

Introduction to using GAlgebra

This is a tutorial to introduce you to galgebra, a symbolic geometric algebra library for python.

A geometric algebra is defined by a set of symbols that represent the basis vectors of a real vector space, a metric tensor, and possible a set of coordinate symbols. If coordinates are defined the metric tensor can be a function of them.

The following cell imports all the functions needed in the tutorial from sympy, ga, and printer.

[1]:
import sympy
from galgebra.ga import Ga
from galgebra.printer import latex
from IPython.display import Math

# tell sympy to use our printing by default
sympy.init_printing(latex_printer=latex, use_latex='mathjax')

Printing in sympy

Sympy will show pretty \(\LaTeX\) renderings of symbolic expressions by default

[2]:
sympy.S('n')**2
[2]:
$\displaystyle n^{2}$

But if we want to append freeform text on the same line, we must use Math, latex, and f-strings in tandem:

[3]:
Math(f"y = { latex(sympy.S('n')**2) }")
[3]:
$\displaystyle y = n^{2}$

Creating an algebra

To start with we will define the geometric algebra of a 3 dimensional Euclidaen vector space, o3d, with coordinates \(x\), \(y\), and \(z\) and unit vectors \(e_x\), \(e_y\), and \(e_z\).

[4]:
xyz = (x, y, z) = sympy.symbols('x y z', real=True)
o3d = Ga('e_x e_y e_z', g=[1, 1, 1], coords=xyz)
grad = o3d.grad

The metric tensor \(g\) is:

[5]:
Math(f'g = {latex(o3d.g)}')
[5]:
$\displaystyle g = \left[\begin{array}{ccc}1 & 0 & 0\\0 & 1 & 0\\0 & 0 & 1\end{array}\right]$

Creating multivectors

The most general element of a geometric algebra is a multivector. To define a scalar S, a vector V, a bivector B, and a pseudo-scalar P (these are the only pure grade multivectors we can have in three dimensions):

[6]:
o3d.mv('S', 'scalar')
[6]:
\begin{equation*} S = S \end{equation*}
[7]:
o3d.mv('V', 'vector')
[7]:
\begin{equation*} V = V^{x} \boldsymbol{e}_{x} + V^{y} \boldsymbol{e}_{y} + V^{z} \boldsymbol{e}_{z} \end{equation*}
[8]:
o3d.mv('B', 'bivector')
[8]:
\begin{equation*} B = B^{xy} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y} + B^{xz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{z} + B^{yz} \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \end{equation*}
[9]:
o3d.mv('I', 'pseudo')
[9]:
\begin{equation*} I = I^{xyz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \end{equation*}

We can also extract the basis vectors from o3d. If we name them ex, ey, and ez and form vectors from linear combinations of them:

[10]:
ex, ey, ez = o3d.mv()
Math(f'{latex(ex)}, {latex(ey)}, {latex(ez)}')
[10]:
$\displaystyle \boldsymbol{e}_{x}, \boldsymbol{e}_{y}, \boldsymbol{e}_{z}$

Multivector operators

Binary operations that we can apply to vectors or multivectors in general are addition, +, subtraction, -, geometric product, *, inner (dot) product, |, outer (wedge) product, ^, left contraction, <, right contraction, >. Because operator precedence is immuatable in Python we need to always use parenthesis to determine the correct order of the operations in our expression. Examples for +, -, *, |, and ^ follow:

[11]:
a = o3d.mv('a','vector')
b = o3d.mv('b','vector')
Math(fr'''
\begin{{align}}
    a &= {latex(a)} \\
    b &= {latex(b)}
\end{{align}}
''')
[11]:
$\displaystyle \begin{align} a &= a^{x} \boldsymbol{e}_{x} + a^{y} \boldsymbol{e}_{y} + a^{z} \boldsymbol{e}_{z} \\ b &= b^{x} \boldsymbol{e}_{x} + b^{y} \boldsymbol{e}_{y} + b^{z} \boldsymbol{e}_{z} \end{align} $
[12]:
Math(fr'''
\begin{{align}}
    a+b         &= {latex(a+b)} \\
    a-b         &= {latex(a-b)} \\
    ab          &= {latex(a*b)} \\
    a\cdot b    &= {latex(a|b)} \\
    a \rfloor b &= {latex(a<b)} \\
    a \lfloor b &= {latex(a>b)} \\
    a\wedge b   &= {latex(a^b)}
\end{{align}}
''')
[12]:
$\displaystyle \begin{align} a+b &= \left ( a^{x} + b^{x}\right ) \boldsymbol{e}_{x} + \left ( a^{y} + b^{y}\right ) \boldsymbol{e}_{y} + \left ( a^{z} + b^{z}\right ) \boldsymbol{e}_{z} \\ a-b &= \left ( a^{x} - b^{x}\right ) \boldsymbol{e}_{x} + \left ( a^{y} - b^{y}\right ) \boldsymbol{e}_{y} + \left ( a^{z} - b^{z}\right ) \boldsymbol{e}_{z} \\ ab &= \left ( a^{x} b^{x} + a^{y} b^{y} + a^{z} b^{z}\right ) + \left ( a^{x} b^{y} - a^{y} b^{x}\right ) \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y} + \left ( a^{x} b^{z} - a^{z} b^{x}\right ) \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{z} + \left ( a^{y} b^{z} - a^{z} b^{y}\right ) \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \\ a\cdot b &= a^{x} b^{x} + a^{y} b^{y} + a^{z} b^{z} \\ a \rfloor b &= a^{x} b^{x} + a^{y} b^{y} + a^{z} b^{z} \\ a \lfloor b &= a^{x} b^{x} + a^{y} b^{y} + a^{z} b^{z} \\ a\wedge b &= \left ( a^{x} b^{y} - a^{y} b^{x}\right ) \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y} + \left ( a^{x} b^{z} - a^{z} b^{x}\right ) \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{z} + \left ( a^{y} b^{z} - a^{z} b^{y}\right ) \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \end{align} $
[13]:
B = o3d.mv('B','bivector')
B
[13]:
\begin{equation*} B = B^{xy} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y} + B^{xz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{z} + B^{yz} \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \end{equation*}
[14]:
Math(fr'''
\begin{{align}}
BB          &= {latex(B*B)} \\
a+B         &= {latex(a+B)} \\
a-B         &= {latex(a-B)} \\
aB          &= {latex(a*B)} \\
a\cdot B    &= {latex(a|B)} \\
a \rfloor B &= {latex(a<B)} \\
a \lfloor B &= {latex(a>B)} \\
a\wedge B   &= {latex(a^B)} \\
\end{{align}}
''')
[14]:
$\displaystyle \begin{align} BB &= - {\left ( B^{xy} \right )}^{2} - {\left ( B^{xz} \right )}^{2} - {\left ( B^{yz} \right )}^{2} \\ a+B &= a^{x} \boldsymbol{e}_{x} + a^{y} \boldsymbol{e}_{y} + a^{z} \boldsymbol{e}_{z} + B^{xy} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y} + B^{xz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{z} + B^{yz} \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \\ a-B &= a^{x} \boldsymbol{e}_{x} + a^{y} \boldsymbol{e}_{y} + a^{z} \boldsymbol{e}_{z} - B^{xy} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y} - B^{xz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{z} - B^{yz} \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \\ aB &= \left ( - B^{xy} a^{y} - B^{xz} a^{z}\right ) \boldsymbol{e}_{x} + \left ( B^{xy} a^{x} - B^{yz} a^{z}\right ) \boldsymbol{e}_{y} + \left ( B^{xz} a^{x} + B^{yz} a^{y}\right ) \boldsymbol{e}_{z} + \left ( B^{xy} a^{z} - B^{xz} a^{y} + B^{yz} a^{x}\right ) \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \\ a\cdot B &= \left ( - B^{xy} a^{y} - B^{xz} a^{z}\right ) \boldsymbol{e}_{x} + \left ( B^{xy} a^{x} - B^{yz} a^{z}\right ) \boldsymbol{e}_{y} + \left ( B^{xz} a^{x} + B^{yz} a^{y}\right ) \boldsymbol{e}_{z} \\ a \rfloor B &= \left ( - B^{xy} a^{y} - B^{xz} a^{z}\right ) \boldsymbol{e}_{x} + \left ( B^{xy} a^{x} - B^{yz} a^{z}\right ) \boldsymbol{e}_{y} + \left ( B^{xz} a^{x} + B^{yz} a^{y}\right ) \boldsymbol{e}_{z} \\ a \lfloor B &= 0 \\ a\wedge B &= \left ( B^{xy} a^{z} - B^{xz} a^{y} + B^{yz} a^{x}\right ) \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \\ \end{align} $

More examples

Additionally, we can define multivector fields that are functions of the coordinates. Some concrete examples are (vector and bivector fields):

[15]:
Vf = x**2*ex + y**2*ey + z**2*ez
Bf = x*(ey^ez) + y*(ex^ez) + z*(ex^ey)
Math(fr'''
\begin{{align}}
\text{{Vector Field:}}   && V_f &= {latex(Vf)} \\
\text{{Bivector Field:}} && B_f &= {latex(Bf)}
\end{{align}}
''')
[15]:
$\displaystyle \begin{align} \text{Vector Field:} && V_f &= x^{2} \boldsymbol{e}_{x} + y^{2} \boldsymbol{e}_{y} + z^{2} \boldsymbol{e}_{z} \\ \text{Bivector Field:} && B_f &= z \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y} + y \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{z} + x \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \end{align} $

In addition to binary algebraic operations the most important member functions for multivectors are grade(i), rev(), and norm2(). For a general multivector, M, we have:

[16]:
M = o3d.mv('M', 'mv')
Math('M = %s' % latex(M))
[16]:
$\displaystyle M = M + M^{x} \boldsymbol{e}_{x} + M^{y} \boldsymbol{e}_{y} + M^{z} \boldsymbol{e}_{z} + M^{xy} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y} + M^{xz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{z} + M^{yz} \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} + M^{xyz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z}$
[17]:
Math(fr'''
\begin{{align}}
\text{{Grade 0:}} && \left<M\right>_0 &= {latex(M.grade(0))} \\
\text{{Grade 1:}} && \left<M\right>_1 &= {latex(M.grade(1))} \\
\text{{Grade 2:}} && \left<M\right>_2 &= {latex(M.grade(2))} \\
\text{{Grade 3:}} && \left<M\right>_3 &= {latex(M.grade(3))} \\
\text{{Reverse:}} && M^\dagger        &= {latex(M.rev())}
\end{{align}}
''')
[17]:
$\displaystyle \begin{align} \text{Grade 0:} && \left<M\right>_0 &= M \\ \text{Grade 1:} && \left<M\right>_1 &= M^{x} \boldsymbol{e}_{x} + M^{y} \boldsymbol{e}_{y} + M^{z} \boldsymbol{e}_{z} \\ \text{Grade 2:} && \left<M\right>_2 &= M^{xy} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y} + M^{xz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{z} + M^{yz} \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \\ \text{Grade 3:} && \left<M\right>_3 &= M^{xyz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \\ \text{Reverse:} && M^\dagger &= M + M^{x} \boldsymbol{e}_{x} + M^{y} \boldsymbol{e}_{y} + M^{z} \boldsymbol{e}_{z} - M^{xy} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y} - M^{xz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{z} - M^{yz} \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} - M^{xyz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \end{align} $

More printing options

A problem in displaying multivectors is that the expression can be very long and does not display nicely on the page. To alleviate this problem one can use the multivector member function Fmt(). The default is Fmt(1) which displays the multivector on one line, Fmt(2) displayes the multivector one grade per line, and Fmt(3) displayes the mulitvector one base or basis blade per line. Some examples are:

[18]:
M.Fmt(1)
[18]:
\begin{equation*} M + M^{x} \boldsymbol{e}_{x} + M^{y} \boldsymbol{e}_{y} + M^{z} \boldsymbol{e}_{z} + M^{xy} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y} + M^{xz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{z} + M^{yz} \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} + M^{xyz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \end{equation*}
[19]:
M.Fmt(2)
[19]:
\begin{equation*} \begin{aligned}[t] & M \\ & + M^{x} \boldsymbol{e}_{x} + M^{y} \boldsymbol{e}_{y} + M^{z} \boldsymbol{e}_{z} \\ & + M^{xy} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y} + M^{xz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{z} + M^{yz} \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \\ & + M^{xyz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \end{aligned} \end{equation*}
[20]:
M.Fmt(3)
[20]:
\begin{equation*} \begin{aligned}[t] & M \\ & + M^{x} \boldsymbol{e}_{x} \\ & + M^{y} \boldsymbol{e}_{y} \\ & + M^{z} \boldsymbol{e}_{z} \\ & + M^{xy} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y} \\ & + M^{xz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{z} \\ & + M^{yz} \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \\ & + M^{xyz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z} \end{aligned} \end{equation*}