From e09be8bb4f245fd948a073f28d52ca9efa372bbb Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sat, 6 Jul 2019 17:53:24 -0400 Subject: [PATCH] eja: add element inverse() and is_invertible(). --- mjo/eja/euclidean_jordan_algebra.py | 70 +++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/mjo/eja/euclidean_jordan_algebra.py b/mjo/eja/euclidean_jordan_algebra.py index 87a0ca0..636149a 100644 --- a/mjo/eja/euclidean_jordan_algebra.py +++ b/mjo/eja/euclidean_jordan_algebra.py @@ -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. -- 2.44.2