]> gitweb.michael.orlitzky.com - sage.d.git/blobdiff - mjo/eja/eja_algebra.py
eja: compute the unit element of the algebra ourselves.
[sage.d.git] / mjo / eja / eja_algebra.py
index fb840edb93ed564c7372eacac2e3b9913a4a2350..362b03a6695a00061034cb9168ba76021a9e2daf 100644 (file)
@@ -232,7 +232,13 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
         # the first equivalent thing instead so that we can pass in
         # standard coordinates.
         x = J(W(R.gens()))
-        l1 = [matrix.column(W.coordinates((x**k).vector())) for k in range(r)]
+
+        # Handle the zeroth power separately, because computing
+        # the unit element in J is mathematically suspect.
+        x0 = W.coordinates(self.one().vector())
+        l1  = [ matrix.column(x0) ]
+        l1 += [ matrix.column(W.coordinates((x**k).vector()))
+                for k in range(1,r) ]
         l2 = [idmat.column(k-1).column() for k in range(r+1, n+1)]
         A_of_x = matrix.block(R, 1, n, (l1 + l2))
         xr = W.coordinates((x**r).vector())
@@ -378,6 +384,67 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
             return self._natural_basis
 
 
+    @cached_method
+    def one(self):
+        """
+        Return the unit element of this algebra.
+
+        SETUP::
+
+            sage: from mjo.eja.eja_algebra import (RealCartesianProductEJA,
+            ....:                                  random_eja)
+
+        EXAMPLES::
+
+            sage: J = RealCartesianProductEJA(5)
+            sage: J.one()
+            e0 + e1 + e2 + e3 + e4
+
+        TESTS::
+
+        The identity element acts like the identity::
+
+            sage: set_random_seed()
+            sage: J = random_eja()
+            sage: x = J.random_element()
+            sage: J.one()*x == x and x*J.one() == x
+            True
+
+        The matrix of the unit element's operator is the identity::
+
+            sage: set_random_seed()
+            sage: J = random_eja()
+            sage: actual = J.one().operator().matrix()
+            sage: expected = matrix.identity(J.base_ring(), J.dimension())
+            sage: actual == expected
+            True
+
+        """
+        # We can brute-force compute the matrices of the operators
+        # that correspond to the basis elements of this algebra.
+        # If some linear combination of those basis elements is the
+        # algebra identity, then the same linear combination of
+        # their matrices has to be the identity matrix.
+        #
+        # Of course, matrices aren't vectors in sage, so we have to
+        # appeal to the "long vectors" isometry.
+        oper_vecs = [ _mat2vec(g.operator().matrix()) for g in self.gens() ]
+
+        # Now we use basis linear algebra to find the coefficients,
+        # of the matrices-as-vectors-linear-combination, which should
+        # work for the original algebra basis too.
+        A = matrix.column(self.base_ring(), oper_vecs)
+
+        # We used the isometry on the left-hand side already, but we
+        # still need to do it for the right-hand side. Recall that we
+        # wanted something that summed to the identity matrix.
+        b = _mat2vec( matrix.identity(self.base_ring(), self.dimension()) )
+
+        # Now if there's an identity element in the algebra, this should work.
+        coeffs = A.solve_right(b)
+        return self.linear_combination(zip(coeffs,self.gens()))
+
+
     def rank(self):
         """
         Return the rank of this EJA.