<jupyter_start><jupyter_text>Brief introduction to linear algebra using PGATed Corcovilos, 2021-03-18<jupyter_code># import libraries
from sympy import *
from galgebra.ga import Ga
# setup notebook pretty printing
init_printing()
# set up the algebra
pga3coords = (w,x,y,z) = symbols('w x y z', real=True)
pga3 = Ga('e_0 e_1 e_2 e_3',g=[0,1,1,1], coords=pga3coords)

e0, e1, e2, e3 = pga3.mv()
# define some useful functions for PGA
def J3(x):
    # J map for pga3 multivectors to calculate the orthogonal complement
    coef_list = x.blade_coefs()
    # flip sign of e02 and e1
    signs = [1,
            1,-1,1,-1,
            1,-1,1,1,-1,1,
            1,-1,1,-1,
            1]
    size = len(signs)
    return pga3.mv(sum(signs[mm]*coef_list[mm]*flatten(pga3.blades)[size-1-mm] for mm in range(size)))

def vee3(a,b):
    # regressive product for pga3
    return J3(J3(a)^J3(b))
t= symbols('t', real=True) # real parameter to use later<jupyter_output><empty_output><jupyter_text>Systems of linear equationsEach linear equation may be represented by a vector in PGA.Let's solve the system$$\begin{aligned}a:&& x + \phantom{2}y + z -1 &= 0 \\b:&& 2x + \phantom{2}y + z +0&= 0 \\c:&& x -2y -z -2 &= 0\end{aligned}$$<jupyter_code>a = e1 + e2 + e3 - e0
b = 2*e1 + e2 + e3
c = e1 -2*e2-e3 -2*e0<jupyter_output><empty_output><jupyter_text>The solution is the intersection point of the 3 planes described by each equation above.<jupyter_code>a^b^c<jupyter_output><empty_output><jupyter_text>The trivector terms describe a point.  It's easier to read off if we normalize it and look at its orthogonal complement:<jupyter_code>J3(a^b^c)<jupyter_output><empty_output><jupyter_text>The coefficient of $e_1$ is the $x$ value, etc.  So the solution of the original system of equations is$$\begin{aligned}x&=-1\\y&=-5\\z&=7\end{aligned}$$<jupyter_code># Let's define p as a generic point
p=J3(x*e1 + y*e2 + z*e3 + e0)
p<jupyter_output><empty_output><jupyter_text>We can represent this as equations for x,y,z by setting terms of the expression below equal to zero: $p\vee(a\wedge b\wedge c)=0$.  PGA is a Regressive Product Null Space (RPNS) representation.<jupyter_code>vee3(p,a^b^c)<jupyter_output><empty_output><jupyter_text>Setting the line above equal to zero gives a redundant set of equations, but looking at the line three terms we can read off$$\begin{aligned}x&=-1\\y&=-5\\z&=7\end{aligned}$$  Under-defined systemLet's try something different.  Let's do an under-defined system.$$\begin{aligned}a:&& x + y + z -1 &= 0 \\b:&& 2x + y + z +0&= 0 \\%x -2y -z &= 2\end{aligned}$$ Again, the solution is $a\wedge b$:<jupyter_code>a^b<jupyter_output><empty_output><jupyter_text>This is the Plücker representation of a line in 3D space.  As before, we can get this into a more familiar form by computing $p \vee (a\wedge b)=0$.<jupyter_code>vee3(p,a^b)<jupyter_output><empty_output><jupyter_text>Parametric form of the line(TODO generalize the method to higher dimensional solution spaces.)The solution to the system above is a line of points: $x=-1, y=-z+2$.To put this in parametric form, we need the direction of the line $d$ and any point on the line $P$:$$\begin{aligned}d &= a\wedge b \wedge e_0 \\P &= d^* \wedge (a\wedge b)\end{aligned}$$Then the line consists of the points $P + dt$ for a scalar value $t$.<jupyter_code>d=a^b^e0 # direction of the line
d
P = J3(d)^(a^b) # a point on the line
P
(P+d*t)<jupyter_output><empty_output><jupyter_text>Or, translating to coordinates and rescaling $t$:$$x = -1,\quady = 1-t, \quad z=1+t$$  Over-defined systemLet's look at an over-defined system in 2D:$$\begin{aligned}x&= 0\\y&= 0\\x+y&= 1\end{aligned}$$This clearly has no solution, but can we find a "best fit"?One way to answer is to sum the 3 normalized intersection points.(Q: what happens if I use the _unnormalized_ points? Is this useful?)<jupyter_code>sum([e1^e2,-e2^(e1+e2-e0),-(e1+e2-e0)^e1])/3<jupyter_output><empty_output><jupyter_text>To generalize to larger systems, for an _N_-dimensional space with _m_ equations, form all $\binom{m}{N}$ of the _N_-wise wedge products, normalize, and sum them. This method also works when two or more of the (hyper-)planes are parallel.  The intersection point is then ideal, and that point can be discarded before summing. (Q: does this give the same result as the least-squares solution, using pseudo-inverse?  It seems like that is different?)  Gaussian eliminationOne of the standard solution techniques in linear algebra is Gaussian elimination.  What does that look like in PGA?  It's almost trivial.Let's go back to our earlier problem:$$\begin{aligned}a:&&x + \phantom{2}y + z -1 &= 0 \\b:&&2x + \phantom{2}y + z +0 &= 0 \\c:&&x -2y -z -2 &= 0\end{aligned}$$The idea of Gaussian elimination is to add a scalar multiple of one row to another row to zero out coefficients in the lower left triangle of the matrix.For example, we could replace row $b$ with $b-2a$ and row $c$ with $c-a$, to eliminate the coefficients of $x$ in the bottom two rows:<jupyter_code>b-2*a, c-a<jupyter_output><empty_output><jupyter_text>$$\begin{aligned}a:&&x + \phantom{3}y +\phantom{2} z -1 &= 0 \\b-2a:&&0x  -\phantom{3}y - \phantom{2}z +2&= 0 \\c-\phantom{2}a:&&0x -3y -2z -1 &= 0\end{aligned}$$Then add -3 times the second row to the third row:<jupyter_code>-3*(b-2*a)+(c-a)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13764044943820225, 'fraction_numerical': 0.02958801498127341, 'mean_word_length': 4.604407135362015, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '451253', 'license': 'MIT', 'n_tokens_mistral': 2003, 'n_tokens_neox': 1904, 'n_words': 645, 'path': 'linear algebra.ipynb', 'repo_name': 'corcoted/GA-scratch', 'size': '5340'}