## Naming

What should this domain be called?

I renamed from CliffordAlgebra to GrassmannAlgebra just to avoid name clashes while experimenting. However since it doesn't define proper Grassmann bases it does not justify such a name change?

I guess that if this were put back into the Axiom/FriCAS codebase there would be advantages in doing this so that it does not break existing applications?

Although a lot of people don't like the Hestenes terminology, most books use the term 'Geometric Algebra', for example: [Dorst, Fontijne & Mann, Geometric Algebra for Computer Science] and [Doran & Lasenby, Geometric Algebra for Physicists] so potential users would be looking for that terminology?

I like the name 'Multivector', which seems to me to represent what it is, the names Grassmann and Clifford could be reserved for the multiplication types. However Bertfried does not like this term due to:

- Its association with the Hestenes flavor of the algebra.
- The multivector concept does not allow the option of containing models called Hopf Gebras.
- Multivector just refers to the module, not to the (Hopf) algebraic structure.

## Theoretical Questions

These changes are driven, in part, by the practical reasons above. The implementation, so far, is effectively Clifford algebra with exterior and inner products bolted on. That is the domain inherits from ring where the Clifford product is the ring product, I don't know how to define proper Grassmann bases. Also I don't know how this algebra can be used with an equation solver.

## Possible Performance Improvements

- Caching multiplication tables. Currently products are computed each time they are needed, it would be more efficient to store multiplication tables once for each type definition but Bertfried has explained that multiplication tables become too big for dim V > 8, therefore Caching option is being investigated.
- Allow efficient storage of sparse multivectors, see 'efficient storage' below.
- Currently the multiplications make heavy use of recursion (not necessarily tail recursion). There may be ways to improve speed and use of stack/heap.

## Efficient Storage

At present, when an instance of the multivector is created, a PrimitiveArray of instances of a field is created. The length of this PrimitiveArray is fixed n^2 so that the position in the array indicates the type. I must admit that I have not looked at PrimitiveArray to see what happens internally when a given index is not set, but when a index that was not specifically set is then read then zero is returned. I therefore assume that it takes space with instances of the field set to zero. I can think of a number of alternative designs, for instance,

- we could create
2 domains:
- Multivector - contains multiple MultivectorElements, just the non-zero, position not significant.
- MultivectorElement - contains one instance of a field and an integer to indicate the bases.

- or another design could be:
- Multivector - contains just the non-zero MultivectorBlades, position not significant.
- MultivectorBlade - contains one instance of a blade, for instance a complete vector or a complete bivector and so on.

notes from Bertfried:

You will need to store the basis elements and the additive aggregates somehow. To do this it would be good to implement a sort of ordering on the basis. Franz Lehner has used some such representations in his tensor package, and you get the aggregate as listOfTerms(%), where a term is a record Record( r::R, b:S) with R a ring element and b an index set indexing the basis (such a domain can take as an argument a name for the basis elements, used in the output form). However, that would need to write two categories, one for the module and one for the algebra. This would have the advantage to allow a Clifford algebra to have different bases, a need which will come soon up in applications.

For technical reasons (and further applications, like Groeber basis algorithms over Grassmann and Clifford algebras), the best order relations are those which are 'admissible'. One such order is the following:

V = R-span {ei}_{i=0}^n

/\V = {1, e1, e2, e12, e3, e13 , e123, e4, ...}

This has the advantage, that spaces V^k = R-span ei}_{i=0}^k and their Grassmann algebras are embedded neatly into larger such spaces or projected out of such spaces by just setting (in the projection case) the elements 2^k+l for l>0 to zero.

For the moment such considerations are irrelevant, if you (we) are willing to rewrite the stuff later to be amenable to such a treatment. The advantage is, that zero elements are not stored, moved, or iterated over, and for Clifford algebras of base space dimension say >6 this makes a big difference (as experience tells).

## Symbolic indexes and bilinear forms

It would be useful to have symbolic indexes (e(i) instead of e(1)) which would be propagated to higher grade terms.

Also bilinear forms with symbolic entries

Do you have any views about whether the bilinear form should be supplied to the domain constructor as 'List List Ring', 'SquareMatrix Ring' or create a custom domain called BilinearForm ? Would I be correct in thinking that Matrix or a custom domain would not add much value so I might as well use a List of Lists for efficiency?

notes from Bertfried:

given an expression like

ei..j /\ ek..l or e(i..j)*e(k..l) you can substitute the abstract indices by two sets of non overlapping natural number index sets,

like (i..j) -> [1..n],

and (k..l) -> [n+1..n+m],

then use your algorithm and substitute back. Actually what you do is just computing some permutations and their signs (in the case of the wedge) that is called 'shuffle' and could operate directly on any ordered set (eg using the domain perm in perm.spad).

## Support for multivectors whose elements are non-commutative algebras

Currently Clifford algebras are constrained to have elements of type 'Field' it would be good to change this to 'Ring' or 'IntegralDomain'.

Currently Clifford algebra inherits from VectorSpace, this could be changed to Module. However both Module and Algebra seem to require CommutativeRing. I am not sure what category a module over a non-commutative algebra should inherit from?

Note: the Complex, Quaternion and Octonion all have their own category (why?) They also require elements of CommutativeRing (should this restriction be removed also?).

How would a Clifford Algebra whose elements are Clifford Algebra be represented? For instance would e(1) represent the basis for the inner or outer basis? I guess we need to be able change the designations of bases to allow for multiple Clifford algebras at the same time?

Is there a loss of associativity in these sort of cases?

I will check if division or swapping of operands is done. Its easy enough to check if they are done directly but also other packages are used so I need for check for secondary effects. Under what circumstances would Axiom swap operands when matching?

One issue is that LinearSystemMatrixPackage is used which requires a Field so I need to find an alternative way to calculate recip() if possible. Or perhaps recip() should try to coerce the Ring into a Field and if that fails then recip() fails.

## Infix Operator Precidence

> We deal with several products and we should be able to define a

> precedence. FriCAS allows me to type in an expression like

>

> A/\B*C/\D

>

> and its not clear what happens, since these structures do not

> associate over another

>

> (A/\B)*(C/\D) -- is what I expected

> ((A/\B)*C)/\D -- is what I got

I can only guess that the precedence of the infix operators /\ and * (in the interpreter) is the same and therefore they are evaluated in the order given?

I did ask about infix precedence here:

http://groups.google.com/group/fricas-devel/browse_thread/thread/6fdbe45592659961?hl=en#

To summarise:

- Precedence for a given operator, such as /\, is global, so if we fix this it may break logical operators which also use /\.
- Compiler and interpreter work differently.
- Precedence cant be changed from SPAD so changes would require a lisp file.

To summarise the summery:

- Its all very messy and I don't know what to do - help anyone!

## Input and Output

> A minor point is the output, which could be condensed and made more

> intuitive by grouping the Grassmann wedge indices into a single

> subset, like e(1,2,3,4)

It would be very easy to input in this form, for instance:

(2) -> a:B1 := e(1,2,3)

(2) e e e

1 2 3

Type: GrassmannAlgebra(3,Fraction(Integer),[[1,0,0],[0,1,0],[0,0,1]])

The only issue is that I can only work out how to do this by having a separate

definition and implementation for each grade:

e: (PI,PI) -> %

e: (PI,PI,PI) -> %

...

e(i,j) == _/_\(e(i),e(j))

e(i,j,k) == _/_\(e(i,j),e(k))

...

Does anyone know if these can be combined by defining them recursively in some way?

I guess it does not matter as there must be a limited number of parameters to a function anyway?

I could probably change the output to use this notation, although I would need to read up on OutputForm first, but would you really want this in

preference to the suffix notation?

Would you prefer:

Option 1 | Option 2 | Option 3 | Option 4 |
---|---|---|---|

e(1,2,3) |
e e e 1 2 3 |
e 1 2 3 |
e 1,2,3 |

would have advantages in not requiring a monospaced font although I find it less readable | what is currently implemented | might be confusing for indicies over 9? | not particular advantage over current implementation |

We also want to represent Clifford basis elements like e(ij)

## Known Bugs

I have not yet managed to implement this rule Bertfried gave me:

> iii) Since every term u can be recursively be decomposed as a Clifford

product

> you can finally evaluate u * v by

> u = w*x (where the grade of w is strictly less than that of u

> u * v = (w*x)*v = w*(x*v) and use the above recursion with 1*1=1

I have implemented this as follows but I know this won't work for higher grades (its not recursive as is required):

-- if none of the above is true then apply:

-- u*v = u/\v + \/(u,v)

-- so,

-- u/\v = u*v - \/(u,v)

-- (u/\v)*w = v*v*w - bilinear(u,v)*w

uType:SINT := leftMostBase(op1type) -- highest ^factor

vType:SINT := xor(op1type,uType) -- remaining ^factors

ut:% := New; ut.uType := 1$K

wt:% := New; wt.op2type := 1$K

resul := ut * cliffordProdTerm(1$K,vType,1$K,op2type)

resul := resul - bilinear(uType,vType)*wt

resul := (op1mult*op2mult)*resul -- apply 'scalar' multipliers

resul

Also Inverse is not implementined well enough to be able to do transforms. I suspect that the current recip(x: %) function would not work with non-diagonal forms.

## Relationship to Other Algebras

Since there are many accidental and not so accidental isomorphisms between Clifford Algebras and Cayley-Dickson (Complex, Quaternion and Octonion), Spinor and Hopf Algebras, do we need lots of coerce functions? Or can we represent some of these by choosing a suitable category hierarchy?

Are there common functions between these algebras that could be separated out into categories?

This issue is discussed in more detail on this page.