This notebook is part of the `galgebra` documentation: https://galgebra.readthedocs.io/.

# 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`.


```python
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


```python
sympy.S('n')**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:


```python
Math(f"y = { latex(sympy.S('n')**2) }")
```




$\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$.


```python
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:


```python
Math(f'g = {latex(o3d.g)}')
```




$\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):


```python
o3d.mv('S', 'scalar')
```




$\displaystyle S = S$




```python
o3d.mv('V', 'vector')
```




$\displaystyle V = V^{x} \boldsymbol{e}_{x} + V^{y} \boldsymbol{e}_{y} + V^{z} \boldsymbol{e}_{z}$




```python
o3d.mv('B', 'bivector')
```




$\displaystyle 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}$




```python
o3d.mv('I', 'pseudo')
```




$\displaystyle I = I^{xyz} \boldsymbol{e}_{x}\wedge \boldsymbol{e}_{y}\wedge \boldsymbol{e}_{z}$



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:


```python
ex, ey, ez = o3d.mv()
Math(f'{latex(ex)}, {latex(ey)}, {latex(ez)}')
```




$\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:


```python
a = o3d.mv('a','vector')
b = o3d.mv('b','vector')
Math(fr'''
\begin{{align}}
    a &= {latex(a)} \\
    b &= {latex(b)}
\end{{align}}
''')
```




$\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}
$




```python
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}}
''')
```




$\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}
$




```python
B = o3d.mv('B','bivector')
B
```




$\displaystyle 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}$




```python
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}}
''')
```




$\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):


```python
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}}
''')
```




$\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:


```python
M = o3d.mv('M', 'mv')
Math('M = %s' % latex(M))
```




$\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}$




```python
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}}
''')
```




$\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: 


```python
M.Fmt(1)
```




$\displaystyle 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}$




```python
M.Fmt(2)
```




$\displaystyle  \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} $




```python
M.Fmt(3)
```




$\displaystyle  \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} $



241778ce65998187567018ff566a5c7f62801123
ipynb
Jupyter Notebook
examples/ipython/tutorial_algebra.ipynb
pygae/galgebra
3a53b29fb141be1ae47d8df8fc7005c10869cded
BSD-3-Clause
2018-09-18T12:30:14.000Z
2022-03-16T08:02:48.000Z
examples/ipython/tutorial_algebra.ipynb
caiomrcs/galgebra
3a53b29fb141be1ae47d8df8fc7005c10869cded
BSD-3-Clause
2018-09-19T01:42:30.000Z
2022-01-18T14:02:00.000Z
examples/ipython/tutorial_algebra.ipynb
caiomrcs/galgebra
3a53b29fb141be1ae47d8df8fc7005c10869cded
BSD-3-Clause
2019-02-22T08:25:50.000Z
2022-01-15T05:20:22.000Z
Qwen/Qwen-72B
1. YES
2. YES