]> gitweb.michael.orlitzky.com - sage.d.git/commitdiff
mjo/hurwitz.py: delete custom Octonions implementation
authorMichael Orlitzky <michael@orlitzky.com>
Thu, 9 Apr 2026 00:29:34 +0000 (20:29 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Thu, 9 Apr 2026 00:30:35 +0000 (20:30 -0400)
Everything has been updated to use the Sage OctonionAlgebra.

mjo/hurwitz.py

index 6d021685b322ff664cc92eb18eb7c21ced4ff01f..467cf734a1a65710f4c3b806f0be388eebe320ee 100644 (file)
@@ -1,303 +1,7 @@
-from sage.misc.cachefunc import cached_method
-from sage.combinat.free_module import CombinatorialFreeModule
-from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement
 from sage.rings.all import AA
 
 from mjo.matrix_algebra import MatrixAlgebra, MatrixAlgebraElement
 
-class Octonion(IndexedFreeModuleElement):
-    def conjugate(self):
-        r"""
-        SETUP::
-
-            sage: from mjo.hurwitz import Octonions
-
-        EXAMPLES::
-
-            sage: O = Octonions()
-            sage: x = sum(O.gens())
-            sage: x.conjugate()
-            e0 - e1 - e2 - e3 - e4 - e5 - e6 - e7
-
-        TESTS::
-
-        Conjugating twice gets you the original element::
-
-            sage: O = Octonions()
-            sage: x = O.random_element()
-            sage: x.conjugate().conjugate() == x
-            True
-
-        """
-        from sage.rings.all import ZZ
-        from sage.matrix.matrix_space import MatrixSpace
-        C = MatrixSpace(ZZ,8).diagonal_matrix((1,-1,-1,-1,-1,-1,-1,-1))
-        return self.parent().from_vector(C*self.to_vector())
-
-    def real(self):
-        r"""
-        Return the real part of this octonion.
-
-        The real part of an octonion is its projection onto the span
-        of the first generator. In other words, the "first dimension"
-        is real and the others are imaginary.
-
-        SETUP::
-
-            sage: from mjo.hurwitz import Octonions
-
-        EXAMPLES::
-
-            sage: O = Octonions()
-            sage: x = sum(O.gens())
-            sage: x.real()
-            e0
-
-        TESTS:
-
-        This method is idempotent::
-
-            sage: O = Octonions()
-            sage: x = O.random_element()
-            sage: x.real().real() == x.real()
-            True
-
-        """
-        return (self + self.conjugate())/2
-
-    def imag(self):
-        r"""
-        Return the imaginary part of this octonion.
-
-        The imaginary part of an octonion is its projection onto the
-        orthogonal complement of the span of the first generator. In
-        other words, the "first dimension" is real and the others are
-        imaginary.
-
-        SETUP::
-
-            sage: from mjo.hurwitz import Octonions
-
-        EXAMPLES::
-
-            sage: O = Octonions()
-            sage: x = sum(O.gens())
-            sage: x.imag()
-            e1 + e2 + e3 + e4 + e5 + e6 + e7
-
-        TESTS:
-
-        This method is idempotent::
-
-            sage: O = Octonions()
-            sage: x = O.random_element()
-            sage: x.imag().imag() == x.imag()
-            True
-
-        """
-        return (self - self.conjugate())/2
-
-    def _norm_squared(self):
-        return (self*self.conjugate()).coefficient(0)
-
-    def norm(self):
-        r"""
-        Return the norm of this octonion.
-
-        SETUP::
-
-            sage: from mjo.hurwitz import Octonions
-
-        EXAMPLES::
-
-            sage: O = Octonions()
-            sage: O.one().norm()
-            1
-
-        TESTS:
-
-        The norm is nonnegative and belongs to the base field::
-
-            sage: O = Octonions()
-            sage: n = O.random_element().norm()
-            sage: n >= 0 and n in O.base_ring()
-            True
-
-        The norm is homogeneous::
-
-            sage: O = Octonions()
-            sage: x = O.random_element()
-            sage: alpha = O.base_ring().random_element()
-            sage: (alpha*x).norm() == alpha.abs()*x.norm()
-            True
-
-        """
-        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.
-
-        SETUP::
-
-            sage: from mjo.hurwitz import Octonions
-
-        EXAMPLES::
-
-            sage: O = Octonions()
-            sage: x = sum(O.gens())
-            sage: x*x.inverse() == O.one()
-            True
-
-        ::
-
-            sage: O = Octonions()
-            sage: O.one().inverse() == O.one()
-            True
-
-        TESTS::
-
-            sage: O = Octonions()
-            sage: x = O.random_element()
-            sage: x.is_zero() or ( x*x.inverse() == O.one() )
-            True
-
-        """
-        if self.is_zero():
-            raise ValueError("zero is not invertible")
-        return self.conjugate()/self._norm_squared()
-
-
-
-class Octonions(CombinatorialFreeModule):
-    r"""
-    SETUP::
-
-        sage: from mjo.hurwitz import Octonions
-
-    EXAMPLES::
-
-        sage: Octonions()
-        Octonion algebra with base ring Algebraic Real Field
-        sage: Octonions(field=QQ)
-        Octonion algebra with base ring Rational Field
-
-    """
-    def __init__(self,
-                 field=AA,
-                 prefix="e"):
-
-        # Not associative, not commutative
-        from sage.categories.magmatic_algebras import MagmaticAlgebras
-        category = MagmaticAlgebras(field).FiniteDimensional()
-        category = category.WithBasis().Unital()
-
-        super().__init__(field,
-                         range(8),
-                         element_class=Octonion,
-                         category=category,
-                         prefix=prefix,
-                         bracket=False)
-
-        # The product of each basis element is plus/minus another
-        # basis element that can simply be looked up on
-        # https://en.wikipedia.org/wiki/Octonion
-        e0, e1, e2, e3, e4, e5, e6, e7 = self.gens()
-        self._multiplication_table = (
-            (e0, e1, e2, e3, e4, e5, e6, e7),
-            (e1,-e0, e3,-e2, e5,-e4,-e7, e6),
-            (e2,-e3,-e0, e1, e6, e7,-e4,-e5),
-            (e3, e2,-e1,-e0, e7,-e6, e5,-e4),
-            (e4,-e5,-e6,-e7,-e0, e1, e2, e3),
-            (e5, e4,-e7, e6,-e1,-e0,-e3, e2),
-            (e6, e7, e4,-e5,-e2, e3,-e0,-e1),
-            (e7,-e6, e5, e4,-e3,-e2, e1,-e0),
-        )
-
-    def product_on_basis(self, i, j):
-        return self._multiplication_table[i][j]
-
-    def one_basis(self):
-        r"""
-        Return the monomial index (basis element) corresponding to the
-        octonion unit element.
-
-        SETUP::
-
-            sage: from mjo.hurwitz import Octonions
-
-        TESTS:
-
-        This gives the correct unit element::
-
-            sage: O = Octonions()
-            sage: x = O.random_element()
-            sage: x*O.one() == x and O.one()*x == x
-            True
-
-        """
-        return 0
-
-    def _repr_(self):
-        return ("Octonion algebra with base ring %s" % self.base_ring())
-
-    def multiplication_table(self):
-        """
-        Return a visual representation of this algebra's multiplication
-        table (on basis elements).
-
-        SETUP::
-
-            sage: from mjo.hurwitz import Octonions
-
-        EXAMPLES:
-
-        The multiplication table is what Wikipedia says it is::
-
-            sage: Octonions().multiplication_table()
-            ┌────╥────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐
-            │ *  ║ e0 │ e1  │ e2  │ e3  │ e4  │ e5  │ e6  │ e7  │
-            ╞════╫════╪═════╪═════╪═════╪═════╪═════╪═════╪═════╡
-            │ e0 ║ e0 │ e1  │ e2  │ e3  │ e4  │ e5  │ e6  │ e7  │
-            ├────╫────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
-            │ e1 ║ e1 │ -e0 │ e3  │ -e2 │ e5  │ -e4 │ -e7 │ e6  │
-            ├────╫────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
-            │ e2 ║ e2 │ -e3 │ -e0 │ e1  │ e6  │ e7  │ -e4 │ -e5 │
-            ├────╫────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
-            │ e3 ║ e3 │ e2  │ -e1 │ -e0 │ e7  │ -e6 │ e5  │ -e4 │
-            ├────╫────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
-            │ e4 ║ e4 │ -e5 │ -e6 │ -e7 │ -e0 │ e1  │ e2  │ e3  │
-            ├────╫────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
-            │ e5 ║ e5 │ e4  │ -e7 │ e6  │ -e1 │ -e0 │ -e3 │ e2  │
-            ├────╫────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
-            │ e6 ║ e6 │ e7  │ e4  │ -e5 │ -e2 │ e3  │ -e0 │ -e1 │
-            ├────╫────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤
-            │ e7 ║ e7 │ -e6 │ e5  │ e4  │ -e3 │ -e2 │ e1  │ -e0 │
-            └────╨────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘
-
-        """
-        n = self.dimension()
-        # Prepend the header row.
-        M = [["*"] + list(self.gens())]
-
-        # And to each subsequent row, prepend an entry that belongs to
-        # the left-side "header column."
-        M += [ [self.monomial(i)] + [ self.monomial(i)*self.monomial(j)
-                                    for j in range(n) ]
-               for i in range(n) ]
-
-        from sage.misc.table import table
-        return table(M, header_row=True, header_column=True, frame=True)
-
-
-
-
-
 class HurwitzMatrixAlgebraElement(MatrixAlgebraElement):
     def conjugate(self):
         r"""