pygae / galgebra

Symbolic Geometric Algebra/Calculus package for SymPy :crystal_ball:
https://galgebra.rtfd.io/
BSD 3-Clause "New" or "Revised" License
225 stars 62 forks source link

Projective geometric algebra #480

Closed technolapin closed 3 months ago

technolapin commented 2 years ago

I am working with projective geometric algebra (metric: [0, 1, 1, 1] ), but I have trouble to find a way to make it work with galgebra because of the nilpotent basis vector.

For instance, this code

p3g = [0, 1, 1, 1]
p3ga = Ga('e_0 e_1 e_2 e_3', g=p3g, coords=oxyz, norm=False, wedge=False)
e0, e1, e2, e3 = p3ga.mv()
ux = p3ga.mv('u_x', 'scalar')
uy = p3ga.mv('u_y', 'scalar')
uz = p3ga.mv('u_z', 'scalar')
u = e1*ux + e2*uy+e3*uz
print("u", u)
print("u*", u.dual())

prints

: !!!!If I**2 = 0, I cannot be normalized!!!!
: u u_x*e_1 + u_y*e_2 + u_z*e_3
: u* zoo*(u_x + u_y + u_z)

when u should be `u_xe_23 - u_ye_13 + u_ze_12`

How should I do to make it work? Is there a way to give a user-defined dualization method, or to add the antiproduct?

abrombo commented 2 years ago

Consider the following code -

from __future__ import print_function
from sympy import Symbol, symbols, sin, cos, Rational, expand, simplify, collect
from galgebra.printer import Format, Eprint, Print_Function, xpdf, Fmt
from galgebra.ga import Ga, one, zero
from galgebra.mv import Nga, cross

g = '1 0 0 0 ,0 1 0 0 ,0 0 1 1 ,0 0 1 0 '
p3d = Ga('e_1 e_2 e_3 n',g=g)
(e1,e2,e3,n) = p3d.mv()

print('g_{ij} =',p3d.g)
print(n|n)
I = p3d.I()
print(I)
print(I*I)

with following output -

g_{ij} = Matrix([
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 1],
[0, 0, 1, 0]])
0
e_1^e_2^e_3^n
-1
abrombo commented 2 years ago

Remember that for conformal geometric algebra with basis e_x, e_y, e_z, n_0, ninfty the metric tensor is - g{ij} = Matrix([ [1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 1], [0, 0, 0, 1, 0]])

so that e_x**2 = e_y**2 = e_z**2 = 1 and n_0**2 = n_infty**2 = 0, and n_0|n_infty = 2 the question is for the projective model as opposed to the conformal model is e_x|n_infty = e_y|n_infty = e_z|n_infty not equal to zero?

from __future__ import print_function
from sympy import Symbol, symbols, sin, cos, Rational, expand, simplify, collect
from galgebra.printer import Format, Eprint, Print_Function, xpdf, Fmt
from galgebra.ga import Ga, one, zero
from galgebra.mv import Nga, cross

g = '1 0 0 1 ,0 1 0 1 ,0 0 1 1 ,1 1 1 0'
p3d = Ga('e_1 e_2 e_3 n',g=g)
(e1,e2,e3,n) = p3d.mv()

print('g_{ij} =',p3d.g)
print(n|n)
I = p3d.I()
print(I)
print(I*I)
g_{ij} = Matrix([
[1, 0, 0, 1],
[0, 1, 0, 1],
[0, 0, 1, 1],
[1, 1, 1, 0]])
0
sqrt(3)*e_1^e_2^e_3^n/3
-1
abrombo commented 2 years ago

I think this link may be relevant to your question. My question is why not use conformal geometric algebra instead of projective?

https://terathon.com/blog/projective-geometric-algebra-done-right/

Projective Geometric Algebra Done Right – Eric Lengyel's Blog
abrombo commented 2 years ago

Then there is this code -

from __future__ import print_function
from sympy import Symbol, symbols, sin, cos, Rational, expand, simplify, collect
from galgebra.printer import Format, Eprint, Print_Function, xpdf, Fmt
from galgebra.ga import Ga, one, zero
from galgebra.mv import Nga, cross

g = '1 0 0 0 ,0 1 0 0 ,0 0 1 0 ,0 0 0 0'
p3d = Ga('e_1 e_2 e_3 n',g=g,norm=False)
(e1,e2,e3,n) = p3d.mv()

print('g_{ij} =',p3d.g)
print(n|n)
I = e1^e2^e3^n
print(I)
print(I*I)
(a1,a2,a3) = symbols('a_1 a_2 a_3',real=True)
a = a1*e1+a2*e2+a3*e3
print(a)
print(a*I)

with output

g_{ij} = Matrix([
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 0]])
0
e_1^e_2^e_3^n
0
a_1*e_1 + a_2*e_2 + a_3*e_3
a_3*e_1^e_2^n - a_2*e_1^e_3^n + a_1*e_2^e_3^n
abrombo commented 2 years ago

Since galgebra tries to normalize |I**2| to one for the case were I**2 = 0 (I did not make the normalization optional) you need to word around it. I am not familiar with the projective model (only the conformal model for 3d geometry) look at the following code and see if it would help -

from __future__ import print_function
from sympy import Symbol, symbols, sin, cos, Rational, expand, simplify, collect
from galgebra.printer import Format, Eprint, Print_Function, xpdf, Fmt
from galgebra.ga import Ga, one, zero
from galgebra.mv import Nga, cross

g = '1 0 0 0 ,0 1 0 0 ,0 0 1 0 ,0 0 0 0'
p3d = Ga('e_1 e_2 e_3 n',g=g,norm=False)
(e1,e2,e3,n) = p3d.mv()

print('g_{ij} =',p3d.g)
print(n|n)
I = e1^e2^e3
print(I)
print(I*I)
(a1,a2,a3) = symbols('a_1 a_2 a_3',real=True)
a = a1*e1+a2*e2+a3*e3
print(a)
a_s = -I*a
a_ss = -I*a_s
print(a_s)
print(a_ss)

with output -

!!!!If I**2 = 0, I cannot be normalized!!!!
g_{ij} = Matrix([
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 0]])
0
e_1^e_2^e_3
-1
a_1*e_1 + a_2*e_2 + a_3*e_3
-a_3*e_1^e_2 + a_2*e_1^e_3 - a_1*e_2^e_3
-a_1*e_1 - a_2*e_2 - a_3*e_3
abrombo commented 2 years ago

Note that p3d.I() is normalized pseudoscalar and p3d.E() is unnormalized pseudoscalar.

eric-wieser commented 1 year ago

I think #68 has some code that computes a reasonable dual for PGA.

Thanks for the comments above @abrombo; I've edited them to include syntax highlighting.