]> gitweb.michael.orlitzky.com - sage.d.git/commitdiff
eja: factor out a class for real-embedded matrices.
authorMichael Orlitzky <michael@orlitzky.com>
Wed, 3 Mar 2021 13:38:41 +0000 (08:38 -0500)
committerMichael Orlitzky <michael@orlitzky.com>
Wed, 3 Mar 2021 13:38:41 +0000 (08:38 -0500)
mjo/eja/TODO
mjo/eja/eja_algebra.py

index 1ba2a464d066de3144512962c9e6e33fa8c2518e..13b00ac6a3056eaf623ac5c2905be6c7d049706c 100644 (file)
@@ -28,13 +28,10 @@ sage: a0 = (1/4)*X[4]**2*X[6]**2 - (1/2)*X[2]*X[5]*X[6]**2 - (1/2)*X[3]*X[4]*X[6
        sage: e0*[[[[]]]]
        [[[[]]]]*e0
 
-8. Factor out a class for matrices with real embeddings (i.e. not the
-   octonions).
-
-9. In fact, could my octonion matrix algebra be generalized for any
+8. In fact, could my octonion matrix algebra be generalized for any
    algebra of matrices over the reals whose entries are not real? Then
    we wouldn't need real embeddings at all. They might even be fricking
    vector spaces if I did that...
 
-10. Add HurwitzMatrixAlgebra subclass between MatrixAlgebra and
-    OctonionMatrixAlgebra.
+9. Add HurwitzMatrixAlgebra subclass between MatrixAlgebra and
+   OctonionMatrixAlgebra.
index 4d0c802c38c8320a8f10f8faeb50678a85d84e95..5bf597565b2ae292032c3f0a532763d7889cd2a8 100644 (file)
@@ -1725,6 +1725,21 @@ class ConcreteEJA(RationalBasisEJA):
 
 
 class MatrixEJA:
+    @staticmethod
+    def jordan_product(X,Y):
+        return (X*Y + Y*X)/2
+
+    @staticmethod
+    def trace_inner_product(X,Y):
+        r"""
+        A trace inner-product for matrices that aren't embedded in the
+        reals.
+        """
+        # We take the norm (absolute value) because Octonions() isn't
+        # smart enough yet to coerce its one() into the base field.
+        return (X*Y).trace().abs()
+
+class RealEmbeddedMatrixEJA(MatrixEJA):
     @staticmethod
     def dimension_over_reals():
         r"""
@@ -1770,9 +1785,6 @@ class MatrixEJA:
             raise ValueError("the matrix 'M' must be a real embedding")
         return M
 
-    @staticmethod
-    def jordan_product(X,Y):
-        return (X*Y + Y*X)/2
 
     @classmethod
     def trace_inner_product(cls,X,Y):
@@ -1781,29 +1793,11 @@ class MatrixEJA:
 
         SETUP::
 
-            sage: from mjo.eja.eja_algebra import (RealSymmetricEJA,
-            ....:                                  ComplexHermitianEJA,
+            sage: from mjo.eja.eja_algebra import (ComplexHermitianEJA,
             ....:                                  QuaternionHermitianEJA)
 
         EXAMPLES::
 
-        This gives the same answer as it would if we computed the trace
-        from the unembedded (original) matrices::
-
-            sage: set_random_seed()
-            sage: J = RealSymmetricEJA.random_instance()
-            sage: x,y = J.random_elements(2)
-            sage: Xe = x.to_matrix()
-            sage: Ye = y.to_matrix()
-            sage: X = J.real_unembed(Xe)
-            sage: Y = J.real_unembed(Ye)
-            sage: expected = (X*Y).trace()
-            sage: actual = J.trace_inner_product(Xe,Ye)
-            sage: actual == expected
-            True
-
-        ::
-
             sage: set_random_seed()
             sage: J = ComplexHermitianEJA.random_instance()
             sage: x,y = J.random_elements(2)
@@ -1839,14 +1833,7 @@ class MatrixEJA:
         # as a REAL matrix will be 2*a = 2*Re(z_1). And so forth.
         return (X*Y).trace()/cls.dimension_over_reals()
 
-
-class RealMatrixEJA(MatrixEJA):
-    @staticmethod
-    def dimension_over_reals():
-        return 1
-
-
-class RealSymmetricEJA(ConcreteEJA, RealMatrixEJA):
+class RealSymmetricEJA(ConcreteEJA, MatrixEJA):
     """
     The rank-n simple EJA consisting of real symmetric n-by-n
     matrices, the usual symmetric Jordan product, and the trace inner
@@ -1975,12 +1962,12 @@ class RealSymmetricEJA(ConcreteEJA, RealMatrixEJA):
         # because the MatrixEJA is not presently a subclass of the
         # FDEJA class that defines rank() and one().
         self.rank.set_cache(n)
-        idV = matrix.identity(ZZ, self.dimension_over_reals()*n)
+        idV = self.matrix_space().one()
         self.one.set_cache(self(idV))
 
 
 
-class ComplexMatrixEJA(MatrixEJA):
+class ComplexMatrixEJA(RealEmbeddedMatrixEJA):
     # A manual dictionary-cache for the complex_extension() method,
     # since apparently @classmethods can't also be @cached_methods.
     _complex_extension = {}
@@ -2282,7 +2269,7 @@ class ComplexHermitianEJA(ConcreteEJA, ComplexMatrixEJA):
         n = ZZ.random_element(cls._max_random_instance_size() + 1)
         return cls(n, **kwargs)
 
-class QuaternionMatrixEJA(MatrixEJA):
+class QuaternionMatrixEJA(RealEmbeddedMatrixEJA):
 
     # A manual dictionary-cache for the quaternion_extension() method,
     # since apparently @classmethods can't also be @cached_methods.