]> gitweb.michael.orlitzky.com - sage.d.git/blobdiff - mjo/octonions.py
octonions: add QuaternionMatrixAlgebra; prepare for rename...
[sage.d.git] / mjo / octonions.py
index cd25f18a6500b45ce621fa9ae94b6d7c28760750..78365e298ec7a46fcaff0603039f6410aa768c96 100644 (file)
@@ -1,3 +1,4 @@
+from sage.misc.cachefunc import cached_method
 from sage.algebras.quatalg.quaternion_algebra import QuaternionAlgebra
 from sage.combinat.free_module import CombinatorialFreeModule
 from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement
@@ -6,6 +7,8 @@ from sage.rings.all import AA, ZZ
 from sage.matrix.matrix_space import MatrixSpace
 from sage.misc.table import table
 
+from mjo.matrix_algebra import HurwitzMatrixAlgebra
+
 class Octonion(IndexedFreeModuleElement):
     def conjugate(self):
         r"""
@@ -138,6 +141,11 @@ class Octonion(IndexedFreeModuleElement):
         """
         return self._norm_squared().sqrt()
 
+    # The absolute value notation is typically used for complex numbers...
+    # and norm() isn't supported in AA, so this lets us use abs() in all
+    # of the division algebras we need.
+    abs = norm
+
     def inverse(self):
         r"""
         Return the inverse of this element if it exists.
@@ -336,3 +344,126 @@ class Octonions(CombinatorialFreeModule):
                for i in range(n) ]
 
         return table(M, header_row=True, header_column=True, frame=True)
+
+
+
+class OctonionMatrixAlgebra(HurwitzMatrixAlgebra):
+    r"""
+    The algebra of ``n``-by-``n`` matrices with octonion entries over
+    (a subfield of) the real numbers.
+
+    The usual matrix spaces in SageMath don't support octonion entries
+    because they assume that the entries of the matrix come from a
+    commutative and associative ring, and the octonions are neither.
+
+    SETUP::
+
+        sage: from mjo.octonions import OctonionMatrixAlgebra
+
+    EXAMPLES::
+
+        sage: OctonionMatrixAlgebra(3)
+        Module of 3 by 3 matrices with entries in Octonion algebra with base
+        ring Algebraic Real Field over the scalar ring Algebraic Real Field
+        sage: OctonionMatrixAlgebra(3,QQ)
+        Module of 3 by 3 matrices with entries in Octonion algebra with base
+        ring Rational Field over the scalar ring Rational Field
+
+    ::
+
+        sage: A = OctonionMatrixAlgebra(2)
+        sage: e0,e1,e2,e3,e4,e5,e6,e7 = A.entry_algebra().gens()
+        sage: A([ [e0+e4, e1+e5],
+        ....:     [e2-e6, e3-e7] ])
+        +---------+---------+
+        | e0 + e4 | e1 + e5 |
+        +---------+---------+
+        | e2 - e6 | e3 - e7 |
+        +---------+---------+
+
+    ::
+
+        sage: A1 = OctonionMatrixAlgebra(1,QQ)
+        sage: A2 = OctonionMatrixAlgebra(1,QQ)
+        sage: cartesian_product([A1,A2])
+        Module of 1 by 1 matrices with entries in Octonion algebra with
+        base ring Rational Field over the scalar ring Rational Field (+)
+        Module of 1 by 1 matrices with entries in Octonion algebra with
+        base ring Rational Field over the scalar ring Rational Field
+
+    TESTS::
+
+        sage: set_random_seed()
+        sage: A = OctonionMatrixAlgebra(ZZ.random_element(10))
+        sage: x = A.random_element()
+        sage: x*A.one() == x and A.one()*x == x
+        True
+
+    """
+    def __init__(self, n, scalars=AA, prefix="E", **kwargs):
+        super().__init__(Octonions(field=scalars),
+                         scalars,
+                         n,
+                         prefix=prefix,
+                         **kwargs)
+
+class QuaternionMatrixAlgebra(HurwitzMatrixAlgebra):
+    r"""
+    The algebra of ``n``-by-``n`` matrices with quaternion entries over
+    (a subfield of) the real numbers.
+
+    The usual matrix spaces in SageMath don't support quaternion entries
+    because they assume that the entries of the matrix come from a
+    commutative ring, and the quaternions are not commutative.
+
+    SETUP::
+
+        sage: from mjo.octonions import QuaternionMatrixAlgebra
+
+    EXAMPLES::
+
+        sage: QuaternionMatrixAlgebra(3)
+        Module of 3 by 3 matrices with entries in Quaternion
+        Algebra (-1, -1) with base ring Algebraic Real Field
+        over the scalar ring Algebraic Real Field
+        sage: QuaternionMatrixAlgebra(3,QQ)
+        Module of 3 by 3 matrices with entries in Quaternion
+        Algebra (-1, -1) with base ring Rational Field over
+        the scalar ring Rational Field
+
+    ::
+
+        sage: A = QuaternionMatrixAlgebra(2)
+        sage: i,j,k = A.entry_algebra().gens()
+        sage: A([ [1+i, j-2],
+        ....:     [k,   k+j] ])
+        +-------+--------+
+        | 1 + i | -2 + j |
+        +-------+--------+
+        | k     | j + k  |
+        +-------+--------+
+
+    ::
+
+        sage: A1 = QuaternionMatrixAlgebra(1,QQ)
+        sage: A2 = QuaternionMatrixAlgebra(2,QQ)
+        sage: cartesian_product([A1,A2])
+        Module of 1 by 1 matrices with entries in Quaternion Algebra
+        (-1, -1) with base ring Rational Field over the scalar ring
+        Rational Field (+) Module of 2 by 2 matrices with entries in
+        Quaternion Algebra (-1, -1) with base ring Rational Field over
+        the scalar ring Rational Field
+
+    TESTS::
+
+        sage: set_random_seed()
+        sage: A = QuaternionMatrixAlgebra(ZZ.random_element(10))
+        sage: x = A.random_element()
+        sage: x*A.one() == x and A.one()*x == x
+        True
+
+    """
+    def __init__(self, n, scalars=AA, **kwargs):
+        # The -1,-1 gives us the "usual" definition of quaternion
+        Q = QuaternionAlgebra(scalars,-1,-1)
+        super().__init__(Q, scalars, n, **kwargs)