]> gitweb.michael.orlitzky.com - sage.d.git/commitdiff
eja: add element inverse() and is_invertible().
authorMichael Orlitzky <michael@orlitzky.com>
Sat, 6 Jul 2019 21:53:24 +0000 (17:53 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Mon, 29 Jul 2019 03:19:01 +0000 (23:19 -0400)
mjo/eja/euclidean_jordan_algebra.py

index 87a0ca0592b8103ec3410fef57a1134f26a0bf9b..636149a92a33a143be9fca84e6a2924ca9377613 100644 (file)
@@ -153,6 +153,76 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
                 raise ValueError('charpoly had no coefficients')
 
 
+        def inverse(self):
+            """
+            Return the Jordan-multiplicative inverse of this element.
+
+            We can't use the superclass method because it relies on the
+            algebra being associative.
+
+            TESTS:
+
+            The identity element is its own inverse::
+
+                sage: set_random_seed()
+                sage: J = random_eja()
+                sage: J.one().inverse() == J.one()
+                True
+
+            If an element has an inverse, it acts like one. TODO: this
+            can be a lot less ugly once ``is_invertible`` doesn't crash
+            on irregular elements::
+
+                sage: set_random_seed()
+                sage: J = random_eja()
+                sage: x = J.random_element()
+                sage: try:
+                ....:     x.inverse()*x == J.one()
+                ....: except:
+                ....:     True
+                True
+
+            """
+            if self.parent().is_associative():
+                elt = FiniteDimensionalAlgebraElement(self.parent(), self)
+                return elt.inverse()
+
+            # TODO: we can do better once the call to is_invertible()
+            # doesn't crash on irregular elements.
+            #if not self.is_invertible():
+            #    raise ArgumentError('element is not invertible')
+
+            # We do this a little different than the usual recursive
+            # call to a finite-dimensional algebra element, because we
+            # wind up with an inverse that lives in the subalgebra and
+            # we need information about the parent to convert it back.
+            V = self.span_of_powers()
+            assoc_subalg = self.subalgebra_generated_by()
+            # Mis-design warning: the basis used for span_of_powers()
+            # and subalgebra_generated_by() must be the same, and in
+            # the same order!
+            elt = assoc_subalg(V.coordinates(self.vector()))
+
+            # This will be in the subalgebra's coordinates...
+            fda_elt = FiniteDimensionalAlgebraElement(assoc_subalg, elt)
+            subalg_inverse = fda_elt.inverse()
+
+            # So we have to convert back...
+            basis = [ self.parent(v) for v in V.basis() ]
+            pairs = zip(subalg_inverse.vector(), basis)
+            return self.parent().linear_combination(pairs)
+
+
+        def is_invertible(self):
+            """
+            Return whether or not this element is invertible.
+
+            We can't use the superclass method because it relies on
+            the algebra being associative.
+            """
+            return not self.det().is_zero()
+
+
         def is_nilpotent(self):
             """
             Return whether or not some power of this element is zero.