Geometric Algebra in Raku

This module is an attempt to implement basic Geometric
Algebra in Raku.
With this module you can create euclidean and anti-euclidean vectors of
arbitrary size. You can then add and substract them, as well as multiplying
them by real scalars as you would do with any vectors, but you can also
multiply and divide as made possible by the geometric algebra.
Euclidean space
The module exports an array constant @e
which serves as an orthonormal basis
for an Euclidean space of infinite, countable dimension.
use Clifford;
say @e[0]**2; # +1
say @e[0] + 2*@e[1]; # e0+2*e1
say @e[0]*@e[1]; # e0∧e1
Anti-Euclidean space
The module also exports an array constant @ē
which serves as an orthonormal
basis for an anti-Euclidean space of infinite, countable dimension. This
space is orthogonal to the Euclidean space.
use Clifford;
say @ē[0]**2; # -1
say @e[0] + @ē[0]; # e0 + ē0
say @e[0]*@ē[0]; # e0∧ē0
The ē
character is the voyel e
with a macron.
It is available as a default digraph on Vim as e-
.
Minkowski plane
The module exports two constants no
and ni
which form a null basis of a
Minkowski plane. This plane
is orthogonal to both the Euclidean space and the anti-Euclidean space.
use Clifford;
say no; # 𝑜
say ni; # ∞
say no**2; # 0
say ni**2; # 0
say no*@e[0]; # 𝑜∧e0
say ni*@ē[0]; # ∞∧ē0
say no*ni; # -1+𝑜∧∞
say (no*ni + ni*no)/2 # -1
Operations
Grade projection
The AT-POS
method returns the grade projection:
say (no + @e[1] + @e[0]*@e[1])[1]; # 𝑜+e1
Derived products
There are several multiplicative operators derived from the geometric product.
They are extensively discussed by Leo Dorst in his 2002 paper
the inner products of Geometric Algebra.
This module uses unicode symbols as infix operators, but a ASCII method form is
also available.
name | digraph | infix notation | method notation |
---|
outer product | AN | $a ∧ $b | $a.op($b) |
inner product | .M | $a · $b | $a.ip($b) |
scalar product | *- | $a ∗ $b | $a.sp($b) |
commutator | *X | $a × $b | $a.co($b) |
left contraction | 7> | $a ⌋ $b | $a.lc($b) |
right contraction | 7< | $a ⌊ $b | $a.rc($b) |
dot product | Sb | $a ∙ $b | $a.dp($b) |
All those infix operators are tighter than &infix:<*>
.
All symbols are available as Vim digraphs by default.
Beware of the symbol used for the scalar product. It is the asterisk operator
(digraph *-
), not the usual multiplication sign (*
). Here they are besides
one an other: ∗*
. Also the symbols for inner product ("centered dot") and
dot product ("bullet operator", or "fat dot") look very similar in certain
fonts, apparently.
Involutions
The module also implements the three involutions:
given 1 + @e[0] + @e[0]∧@e[1] + @e[0]∧@e[1]∧@e[2] {
say .reversion; # 1+e0-e0∧e1-e0∧e1∧e2
say .involution; # 1-e0+e0∧e1-e0∧e1∧e2
say .conjugation; # 1-e0-e0∧e1+e0∧e1∧e2
}
Here the involution called 'involution' is the so-called main involution.
The module exports two postfix operators &postfix:<~>
and &postfix:<^>
respectively for the reversion and the main involution.
Optimization
This module attempts to optimize computations by generating code during
runtime, as inspired by Pablo Colapinto's work (see next section). In order to
understand how the method works, consider for instance the geometric product of
two vectors X = x1*e1 + x2*e2 + x3*e3
and Y = y1*e1 + y2*e2 + y3*e3
:
X*Y = (x1*y1+x2*y2+x3*y3) +
(x1*y2-x2*y1)*e1∧e2 +
(x2*y3-x3*y2)*e2∧e3 +
(x3*y1-x1*y3)*e3∧e1
This multivector is a linear combination of the unit scalar and the basis
bivectors e1∧e2
, e2∧e3
and e3∧e1
. It would have been possible to know
that beforehand by taking all possible products from e1
, e2
and e3
and
classify them, keeping track of the sign changes.
Assuming an array of coefficients can be associated with a list of basis unit multivectors in order
to form a generic multivector, the coefficients of a product of two vectors could have been
calculated by a function such as:
sub (@x, @y) {
@x[0]*@y[0]+@x[1]*@y[1]+@x[2]*@y[2],
@x[0]*@y[1]-@x[1]*@y[0],
@x[1]*@y[2]-@x[2]*@y[1],
@x[2]*@y[0]-@x[0]*@y[2]
}
This would be very efficient but we would have to use a different function for
all possible kinds of products, and there are infinitely many of them. Since
it's not possible to precompute an infinity of things, the module starts from
nothing and generates a function at runtime, every time it encounters a product
type it has never seen before.
To generate a function, early versions of this module were simply generating the literal string that defines it in
Perl 6 and use EVAL
on it. Current version uses a closure.
External links