]> gitweb.michael.orlitzky.com - sage.d.git/commitdiff
eja: begin moving the associative subalgebra stuff into its own class.
authorMichael Orlitzky <michael@orlitzky.com>
Tue, 30 Jul 2019 01:12:05 +0000 (21:12 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Tue, 30 Jul 2019 01:12:05 +0000 (21:12 -0400)
mjo/eja/eja_subalgebra.py [new file with mode: 0644]

diff --git a/mjo/eja/eja_subalgebra.py b/mjo/eja/eja_subalgebra.py
new file mode 100644 (file)
index 0000000..7c883d9
--- /dev/null
@@ -0,0 +1,182 @@
+from sage.matrix.constructor import matrix
+from sage.structure.category_object import normalize_names
+
+from mjo.eja.eja_algebra import FiniteDimensionalEuclideanJordanAlgebra
+from mjo.eja.eja_element import FiniteDimensionalEuclideanJordanAlgebraElement
+
+
+class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclideanJordanAlgebra):
+    """
+    The subalgebra of an EJA generated by a single element.
+    """
+    @staticmethod
+    def __classcall_private__(cls, elt):
+        superalgebra = elt.parent()
+
+        # First compute the vector subspace spanned by the powers of
+        # the given element.
+        V = superalgebra.vector_space()
+        eja_basis = [superalgebra.one()]
+        basis_vectors = [superalgebra.one().vector()]
+        W = V.span_of_basis(basis_vectors)
+        for exponent in range(1, V.dimension()):
+            new_power = elt**exponent
+            basis_vectors.append( new_power.vector() )
+            try:
+                W = V.span_of_basis(basis_vectors)
+                eja_basis.append( new_power )
+            except ValueError:
+                # Vectors weren't independent; bail and keep the
+                # last subspace that worked.
+                break
+
+        # Make the basis hashable for UniqueRepresentation.
+        eja_basis = tuple(eja_basis)
+
+        # Now figure out the entries of the right-multiplication
+        # matrix for the successive basis elements b0, b1,... of
+        # that subspace.
+        F = superalgebra.base_ring()
+        mult_table = []
+        for b_right in eja_basis:
+                b_right_rows = []
+                # The first row of the right-multiplication matrix by
+                # b1 is what we get if we apply that matrix to b1. The
+                # second row of the right multiplication matrix by b1
+                # is what we get when we apply that matrix to b2...
+                #
+                # IMPORTANT: this assumes that all vectors are COLUMN
+                # vectors, unlike our superclass (which uses row vectors).
+                for b_left in eja_basis:
+                    # Multiply in the original EJA, but then get the
+                    # coordinates from the subalgebra in terms of its
+                    # basis.
+                    this_row = W.coordinates((b_left*b_right).vector())
+                    b_right_rows.append(this_row)
+                b_right_matrix = matrix(F, b_right_rows)
+                mult_table.append(b_right_matrix)
+
+        for m in mult_table:
+            m.set_immutable()
+        mult_table = tuple(mult_table)
+
+        # The rank is the highest possible degree of a minimal
+        # polynomial, and is bounded above by the dimension. We know
+        # in this case that there's an element whose minimal
+        # polynomial has the same degree as the space's dimension
+        # (remember how we constructed the space?), so that must be
+        # its rank too.
+        rank = W.dimension()
+
+        # EJAs are power-associative, and this algebra is nothin but
+        # powers.
+        assume_associative=True
+
+        # TODO: Un-hard-code this. It should be possible to get the "next"
+        # name based on the parent's generator names.
+        names = 'f'
+        names = normalize_names(W.dimension(), names)
+
+        cat = superalgebra.category().Associative()
+
+        # TODO: compute this and actually specify it.
+        natural_basis = None
+
+        fdeja = super(FiniteDimensionalEuclideanJordanElementSubalgebra, cls)
+        return fdeja.__classcall__(cls,
+                                   F,
+                                   mult_table,
+                                   rank,
+                                   eja_basis,
+                                   W,
+                                   assume_associative=assume_associative,
+                                   names=names,
+                                   category=cat,
+                                   natural_basis=natural_basis)
+
+    def __init__(self,
+                 field,
+                 mult_table,
+                 rank,
+                 eja_basis,
+                 vector_space,
+                 assume_associative=True,
+                 names='f',
+                 category=None,
+                 natural_basis=None):
+
+        self._superalgebra = eja_basis[0].parent()
+        self._vector_space = vector_space
+        self._eja_basis = eja_basis
+
+        fdeja = super(FiniteDimensionalEuclideanJordanElementSubalgebra, self)
+        fdeja.__init__(field,
+                       mult_table,
+                       rank,
+                       assume_associative=assume_associative,
+                       names=names,
+                       category=category,
+                       natural_basis=natural_basis)
+
+
+    def vector_space(self):
+        """
+        SETUP::
+
+            sage: from mjo.eja.eja_algebra import RealSymmetricEJA
+            sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
+
+        EXAMPLES::
+
+            sage: J = RealSymmetricEJA(3)
+            sage: x = sum( i*J.gens()[i] for i in range(6) )
+            sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x)
+            sage: K.vector_space()
+            Vector space of degree 6 and dimension 3 over Rational Field
+            User basis matrix:
+            [ 1  0  0  1  0  1]
+            [ 0  1  2  3  4  5]
+            [ 5 11 14 26 34 45]
+            sage: (x^0).vector()
+            (1, 0, 0, 1, 0, 1)
+            sage: (x^1).vector()
+            (0, 1, 2, 3, 4, 5)
+            sage: (x^2).vector()
+            (5, 11, 14, 26, 34, 45)
+
+        """
+        return self._vector_space
+
+
+    class Element(FiniteDimensionalEuclideanJordanAlgebraElement):
+        def __init__(self, A, elt=None):
+            """
+            SETUP::
+
+                sage: from mjo.eja.eja_algebra import RealSymmetricEJA
+                sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
+
+            EXAMPLES::
+
+                sage: J = RealSymmetricEJA(3)
+                sage: x = sum( i*J.gens()[i] for i in range(6) )
+                sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x)
+                sage: [ K(x^k) for k in range(J.rank()) ]
+                [f0, f1, f2]
+
+            ::
+
+            """
+            if elt in A._superalgebra:
+                    # Try to convert a parent algebra element into a
+                    # subalgebra element...
+                try:
+                    coords = A.vector_space().coordinates(elt.vector())
+                    elt = A(coords)
+                except AttributeError:
+                    # Catches a missing method in elt.vector()
+                    pass
+
+            FiniteDimensionalEuclideanJordanAlgebraElement.__init__(self,
+                                                                    A,
+                                                                    elt)