Ask Your Question

Revision history [back]

How can I manipulate Clifford Algebra elements symbolically?

Problem

Sometimes I would like to run functions from the Expression class on a Clifford algebra element. For example, simplification:

qf = DiagonalQuadraticForm(SR,[1,1,1])
Cl.<e1,e2,e3> = CliffordAlgebra(qf) 
u, v = var(‘u v’)
((sin(u)^2 + cos(u)^2)*e1).simplify_full()

I receive the error:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In [91], line 4
      1 #u,v = var('u v')
      2 #SR(e1)
      3 #e1.simplify_full()
----> 4 ((sin(u)**Integer(2) + cos(u)**Integer(2))*e1).simplify_full()
File /ext/sage/10.2/src/sage/structure/element.pyx:489, in sage.structure.element.Element.__getattr__()
    487         AttributeError: 'LeftZeroSemigroup_with_category.element_class' object has no attribute 'blah_blah'...
    488     """
--> 489     return self.getattr_from_category(name)
    490 
    491 cdef getattr_from_category(self, name) noexcept:
File /ext/sage/10.2/src/sage/structure/element.pyx:502, in sage.structure.element.Element.getattr_from_category()
    500     else:
    501         cls = P._abstract_element_class
--> 502     return getattr_from_other_class(self, cls, name)
    503 
    504 def __dir__(self):
File /ext/sage/10.2/src/sage/cpython/getattr.pyx:357, in sage.cpython.getattr.getattr_from_other_class()
    355     dummy_error_message.cls = type(self)
    356     dummy_error_message.name = name
--> 357     raise AttributeError(dummy_error_message)
    358 cdef PyObject* attr = instance_getattr(cls, name)
    359 if attr is NULL:
AttributeError: 'CliffordAlgebra_with_category.element_class' object has no attribute 'simplify_full' 

The behavior I would like is to treat e1, e2, and e3 as symbols. But SR(e1) throws TypeError: Unable to convert e1 to a symbolic expression.

Why I think this should work

An analogous addition of structure preserves simplification operations, namely with vectors: vector([sin(u)^2 + cos(u)^2,u]).simplify_full() returns (1,u).

Current Workaround

My current workaround is to extract the coefficients, map them with the operations in question, and then recreate the Clifford algebra term.

def lift(fxn):
    def fxn_aux(ga_term, *args):
        a,b,c,d,e,f,g,h = [fxn(x, *args) for x in ga_term.dense_coefficient_list()]
        return a + b*e1 + c*e2 + d*e3 + e*e1*e2 + f*e1*e3 + g*e2*e3 + h*e1*e2*e3
    return fxn_aux
simp = lift(Expression.simplify_full)
ga_diff = lift(diff)
u,v = var('u v')
s = cos(u)*e1+sin(u)*cos(v)*e2+sin(u)*sin(v)*e3
show(simp(3 + (cos(u)^2 + sin(u)^2)*e1))
show(ga_diff(s,u))

Question

Is there a more elegant or canonical way to do this?