]> gitweb.michael.orlitzky.com - sage.d.git/commitdiff
eja: implement subalgebra_generated_by() in terms of the new class.
authorMichael Orlitzky <michael@orlitzky.com>
Tue, 30 Jul 2019 03:26:49 +0000 (23:26 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Tue, 30 Jul 2019 03:26:49 +0000 (23:26 -0400)
mjo/eja/eja_element.py
mjo/eja/eja_subalgebra.py

index a8594ca02688493355d9de5f867b3c0cfc1faf07..00a15a1c56897172f57aeec2d43a391f3b367a45 100644 (file)
@@ -5,6 +5,8 @@ from sage.modules.free_module import VectorSpace
 # TODO: make this unnecessary somehow.
 from sage.misc.lazy_import import lazy_import
 lazy_import('mjo.eja.eja_algebra', 'FiniteDimensionalEuclideanJordanAlgebra')
+lazy_import('mjo.eja.eja_subalgebra',
+            'FiniteDimensionalEuclideanJordanElementSubalgebra')
 from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
 from mjo.eja.eja_utils import _mat2vec
 
@@ -702,7 +704,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
             True
 
         """
-        return self.span_of_powers().dimension()
+        return self.subalgebra_generated_by().dimension()
 
 
     def left_matrix(self):
@@ -780,13 +782,8 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
             0
 
         """
-        V = self.span_of_powers()
-        assoc_subalg = self.subalgebra_generated_by()
-        # Mis-design warning: the basis used for span_of_powers()
-        # and subalgebra_generated_by() must be the same, and in
-        # the same order!
-        elt = assoc_subalg(V.coordinates(self.vector()))
-        return elt.operator().minimal_polynomial()
+        A = self.subalgebra_generated_by()
+        return A(self).operator().minimal_polynomial()
 
 
 
@@ -992,19 +989,6 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
         return ( L*M + M*L - (self*other).operator() )
 
 
-    def span_of_powers(self):
-        """
-        Return the vector space spanned by successive powers of
-        this element.
-        """
-        # The dimension of the subalgebra can't be greater than
-        # the big algebra, so just put everything into a list
-        # and let span() get rid of the excess.
-        #
-        # We do the extra ambient_vector_space() in case we're messing
-        # with polynomials and the direct parent is a module.
-        V = self.parent().vector_space()
-        return V.span( (self**d).vector() for d in xrange(V.dimension()) )
 
 
     def subalgebra_generated_by(self):
@@ -1028,54 +1012,12 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
 
             sage: set_random_seed()
             sage: x = random_eja().random_element()
-            sage: u = x.subalgebra_generated_by().random_element()
-            sage: u.operator()(u) == u^2
+            sage: A = x.subalgebra_generated_by()
+            sage: A(x^2) == A(x)*A(x)
             True
 
         """
-        # First get the subspace spanned by the powers of myself...
-        V = self.span_of_powers()
-        F = self.base_ring()
-
-        # Now figure out the entries of the right-multiplication
-        # matrix for the successive basis elements b0, b1,... of
-        # that subspace.
-        mats = []
-        for b_right in V.basis():
-            eja_b_right = self.parent()(b_right)
-            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 V.basis():
-                eja_b_left = self.parent()(b_left)
-                # Multiply in the original EJA, but then get the
-                # coordinates from the subalgebra in terms of its
-                # basis.
-                this_row = V.coordinates((eja_b_left*eja_b_right).vector())
-                b_right_rows.append(this_row)
-            b_right_matrix = matrix(F, b_right_rows)
-            mats.append(b_right_matrix)
-
-        # It's an algebra of polynomials in one element, and EJAs
-        # are power-associative.
-        #
-        # TODO: choose generator names intelligently.
-        #
-        # 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, so that must be its rank too.
-        return FiniteDimensionalEuclideanJordanAlgebra(
-                 F,
-                 mats,
-                 V.dimension(),
-                 assume_associative=True,
-                 names='f')
+        return FiniteDimensionalEuclideanJordanElementSubalgebra(self)
 
 
     def subalgebra_idempotent(self):
@@ -1102,18 +1044,14 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
         if self.is_nilpotent():
             raise ValueError("this only works with non-nilpotent elements!")
 
-        V = self.span_of_powers()
         J = self.subalgebra_generated_by()
-        # Mis-design warning: the basis used for span_of_powers()
-        # and subalgebra_generated_by() must be the same, and in
-        # the same order!
-        u = J(V.coordinates(self.vector()))
+        u = J(self)
 
         # The image of the matrix of left-u^m-multiplication
         # will be minimal for some natural number s...
         s = 0
-        minimal_dim = V.dimension()
-        for i in xrange(1, V.dimension()):
+        minimal_dim = J.dimension()
+        for i in xrange(1, minimal_dim):
             this_dim = (u**i).operator().matrix().image().dimension()
             if this_dim < minimal_dim:
                 minimal_dim = this_dim
@@ -1132,15 +1070,10 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
         # Our FiniteDimensionalAlgebraElement superclass uses rows.
         u_next = u**(s+1)
         A = u_next.operator().matrix()
-        c_coordinates = A.solve_right(u_next.vector())
+        c = J(A.solve_right(u_next.vector()))
 
-        # Now c_coordinates is the idempotent we want, but it's in
-        # the coordinate system of the subalgebra.
-        #
-        # We need the basis for J, but as elements of the parent algebra.
-        #
-        basis = [self.parent(v) for v in V.basis()]
-        return self.parent().linear_combination(zip(c_coordinates, basis))
+        # Now c is the idempotent we want, but it still lives in the subalgebra.
+        return c.superalgebra_element()
 
 
     def trace(self):
index 7c883d92fab3f3f2ee158737bdb0ec12bdf7effd..0ff3519fa15ba4eb1e968ca64d92e69326368b1e 100644 (file)
@@ -16,7 +16,7 @@ class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclide
         # First compute the vector subspace spanned by the powers of
         # the given element.
         V = superalgebra.vector_space()
-        eja_basis = [superalgebra.one()]
+        superalgebra_basis = [superalgebra.one()]
         basis_vectors = [superalgebra.one().vector()]
         W = V.span_of_basis(basis_vectors)
         for exponent in range(1, V.dimension()):
@@ -24,21 +24,21 @@ class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclide
             basis_vectors.append( new_power.vector() )
             try:
                 W = V.span_of_basis(basis_vectors)
-                eja_basis.append( new_power )
+                superalgebra_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)
+        superalgebra_basis = tuple(superalgebra_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:
+        for b_right in superalgebra_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
@@ -47,7 +47,7 @@ class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclide
                 #
                 # IMPORTANT: this assumes that all vectors are COLUMN
                 # vectors, unlike our superclass (which uses row vectors).
-                for b_left in eja_basis:
+                for b_left in superalgebra_basis:
                     # Multiply in the original EJA, but then get the
                     # coordinates from the subalgebra in terms of its
                     # basis.
@@ -87,7 +87,7 @@ class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclide
                                    F,
                                    mult_table,
                                    rank,
-                                   eja_basis,
+                                   superalgebra_basis,
                                    W,
                                    assume_associative=assume_associative,
                                    names=names,
@@ -98,16 +98,16 @@ class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclide
                  field,
                  mult_table,
                  rank,
-                 eja_basis,
+                 superalgebra_basis,
                  vector_space,
                  assume_associative=True,
                  names='f',
                  category=None,
                  natural_basis=None):
 
-        self._superalgebra = eja_basis[0].parent()
+        self._superalgebra = superalgebra_basis[0].parent()
         self._vector_space = vector_space
-        self._eja_basis = eja_basis
+        self._superalgebra_basis = superalgebra_basis
 
         fdeja = super(FiniteDimensionalEuclideanJordanElementSubalgebra, self)
         fdeja.__init__(field,
@@ -119,6 +119,13 @@ class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclide
                        natural_basis=natural_basis)
 
 
+    def superalgebra(self):
+        """
+        Return the superalgebra that this algebra was generated from.
+        """
+        return self._superalgebra
+
+
     def vector_space(self):
         """
         SETUP::
@@ -167,7 +174,7 @@ class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclide
             ::
 
             """
-            if elt in A._superalgebra:
+            if elt in A.superalgebra():
                     # Try to convert a parent algebra element into a
                     # subalgebra element...
                 try:
@@ -180,3 +187,43 @@ class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclide
             FiniteDimensionalEuclideanJordanAlgebraElement.__init__(self,
                                                                     A,
                                                                     elt)
+
+        def superalgebra_element(self):
+            """
+            Return the object in our algebra's superalgebra that corresponds
+            to myself.
+
+            SETUP::
+
+                sage: from mjo.eja.eja_algebra import (RealSymmetricEJA,
+                ....:                                  random_eja)
+
+            EXAMPLES::
+
+                sage: J = RealSymmetricEJA(3)
+                sage: x = sum(J.gens())
+                sage: x
+                e0 + e1 + e2 + e3 + e4 + e5
+                sage: A = x.subalgebra_generated_by()
+                sage: A(x)
+                f1
+                sage: A(x).superalgebra_element()
+                e0 + e1 + e2 + e3 + e4 + e5
+
+            TESTS:
+
+            We can convert back and forth faithfully::
+
+                sage: set_random_seed()
+                sage: J = random_eja()
+                sage: x = J.random_element()
+                sage: A = x.subalgebra_generated_by()
+                sage: A(x).superalgebra_element() == x
+                True
+                sage: y = A.random_element()
+                sage: A(y.superalgebra_element()) == y
+                True
+
+            """
+            return self.parent().superalgebra().linear_combination(
+              zip(self.vector(), self.parent()._superalgebra_basis) )