]> gitweb.michael.orlitzky.com - sage.d.git/commitdiff
eja: begin major overhaul of class hierarchy and naming.
authorMichael Orlitzky <michael@orlitzky.com>
Sun, 6 Dec 2020 04:52:48 +0000 (23:52 -0500)
committerMichael Orlitzky <michael@orlitzky.com>
Sun, 6 Dec 2020 04:52:48 +0000 (23:52 -0500)
mjo/eja/eja_algebra.py
mjo/eja/eja_element.py
mjo/eja/eja_element_subalgebra.py
mjo/eja/eja_operator.py
mjo/eja/eja_subalgebra.py

index 3b13ce10bbf864ceb667f3ba4fc1f8b520327292..1250fbda7981aba5474af0a3d2615c969bc9d1e1 100644 (file)
@@ -29,14 +29,204 @@ from sage.modules.free_module import FreeModule, VectorSpace
 from sage.rings.all import (ZZ, QQ, AA, QQbar, RR, RLF, CLF,
                             PolynomialRing,
                             QuadraticField)
 from sage.rings.all import (ZZ, QQ, AA, QQbar, RR, RLF, CLF,
                             PolynomialRing,
                             QuadraticField)
-from mjo.eja.eja_element import FiniteDimensionalEuclideanJordanAlgebraElement
-from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+from mjo.eja.eja_element import FiniteDimensionalEJAElement
+from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
 from mjo.eja.eja_utils import _mat2vec
 
 from mjo.eja.eja_utils import _mat2vec
 
-class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
+class FiniteDimensionalEJA(CombinatorialFreeModule):
     r"""
     r"""
-    The lowest-level class for representing a Euclidean Jordan algebra.
+    A finite-dimensional Euclidean Jordan algebra.
+
+    INPUT:
+
+      - basis -- a tuple of basis elements in their matrix form.
+
+      - jordan_product -- function of two elements (in matrix form)
+        that returns their jordan product in this algebra; this will
+        be applied to ``basis`` to compute a multiplication table for
+        the algebra.
+
+      - inner_product -- function of two elements (in matrix form) that
+        returns their inner product. This will be applied to ``basis`` to
+        compute an inner-product table (basically a matrix) for this algebra.
+
     """
     """
+    Element = FiniteDimensionalEJAElement
+
+    def __init__(self,
+                 basis,
+                 jordan_product,
+                 inner_product,
+                 field=AA,
+                 orthonormalize=True,
+                 associative=False,
+                 check_field=True,
+                 check_axioms=True,
+                 prefix='e'):
+
+        if check_field:
+            if not field.is_subring(RR):
+                # Note: this does return true for the real algebraic
+                # field, the rationals, and any quadratic field where
+                # we've specified a real embedding.
+                raise ValueError("scalar field is not real")
+
+        # If the basis given to us wasn't over the field that it's
+        # supposed to be over, fix that. Or, you know, crash.
+        basis = tuple( b.change_ring(field) for b in basis )
+
+        if check_axioms:
+            # Check commutativity of the Jordan and inner-products.
+            # This has to be done before we build the multiplication
+            # and inner-product tables/matrices, because we take
+            # advantage of symmetry in the process.
+            if not all( jordan_product(bi,bj) == jordan_product(bj,bi)
+                        for bi in basis
+                        for bj in basis ):
+                raise ValueError("Jordan product is not commutative")
+
+            if not all( inner_product(bi,bj) == inner_product(bj,bi)
+                        for bi in basis
+                        for bj in basis ):
+                raise ValueError("inner-product is not commutative")
+
+
+        category = MagmaticAlgebras(field).FiniteDimensional()
+        category = category.WithBasis().Unital()
+        if associative:
+            # Element subalgebras can take advantage of this.
+            category = category.Associative()
+
+        # Call the superclass constructor so that we can use its from_vector()
+        # method to build our multiplication table.
+        n = len(basis)
+        super().__init__(field,
+                         range(n),
+                         prefix=prefix,
+                         category=category,
+                         bracket=False)
+
+        # Now comes all of the hard work. We'll be constructing an
+        # ambient vector space V that our (vectorized) basis lives in,
+        # as well as a subspace W of V spanned by those (vectorized)
+        # basis elements. The W-coordinates are the coefficients that
+        # we see in things like x = 1*e1 + 2*e2.
+        vector_basis = basis
+
+        from sage.structure.element import is_Matrix
+        basis_is_matrices = False
+
+        degree = 0
+        if n > 0:
+            if is_Matrix(basis[0]):
+                if basis[0].is_square():
+                    # TODO: this ugly is_square() hack works around the problem
+                    # of passing to_matrix()ed vectors in as the basis from a
+                    # subalgebra. They aren't REALLY matrices, at least not of
+                    # the type that we assume here... Ugh.
+                    basis_is_matrices = True
+                    from mjo.eja.eja_utils import _vec2mat
+                    vector_basis = tuple( map(_mat2vec,basis) )
+                    degree = basis[0].nrows()**2
+                else:
+                    # convert from column matrices to vectors, yuck
+                    basis = tuple( map(_mat2vec,basis) )
+                    vector_basis = basis
+                    degree = basis[0].degree()
+            else:
+                degree = basis[0].degree()
+
+        # Build an ambient space that fits...
+        V = VectorSpace(field, degree)
+
+        # We overwrite the name "vector_basis" in a second, but never modify it
+        # in place, to this effectively makes a copy of it.
+        deortho_vector_basis = vector_basis
+        self._deortho_matrix = None
+
+        if orthonormalize:
+            from mjo.eja.eja_utils import gram_schmidt
+            if basis_is_matrices:
+                vector_ip = lambda x,y: inner_product(_vec2mat(x), _vec2mat(y))
+                vector_basis = gram_schmidt(vector_basis, vector_ip)
+            else:
+                vector_basis = gram_schmidt(vector_basis, inner_product)
+
+            # Normalize the "matrix" basis, too!
+            basis = vector_basis
+
+            if basis_is_matrices:
+                basis = tuple( map(_vec2mat,basis) )
+
+        # Save the matrix "basis" for later... this is the last time we'll
+        # reference it in this constructor.
+        if basis_is_matrices:
+            self._matrix_basis = basis
+        else:
+            MS = MatrixSpace(self.base_ring(), degree, 1)
+            self._matrix_basis = tuple( MS(b) for b in basis )
+
+        # Now create the vector space for the algebra...
+        W = V.span_of_basis( vector_basis, check=check_axioms)
+
+        if orthonormalize:
+            # Now "W" is the vector space of our algebra coordinates. The
+            # variables "X1", "X2",...  refer to the entries of vectors in
+            # W. Thus to convert back and forth between the orthonormal
+            # coordinates and the given ones, we need to stick the original
+            # basis in W.
+            U = V.span_of_basis( deortho_vector_basis, check=check_axioms)
+            self._deortho_matrix = matrix( U.coordinate_vector(q)
+                                           for q in vector_basis )
+
+
+        # Now we actually compute the multiplication and inner-product
+        # tables/matrices using the possibly-orthonormalized basis.
+        self._inner_product_matrix = matrix.zero(field, n)
+        self._multiplication_table = [ [0 for j in range(i+1)] for i in range(n) ]
+
+        print("vector_basis:")
+        print(vector_basis)
+        # Note: the Jordan and inner-products are defined in terms
+        # of the ambient basis. It's important that their arguments
+        # are in ambient coordinates as well.
+        for i in range(n):
+            for j in range(i+1):
+                # ortho basis w.r.t. ambient coords
+                q_i = vector_basis[i]
+                q_j = vector_basis[j]
+
+                if basis_is_matrices:
+                    q_i = _vec2mat(q_i)
+                    q_j = _vec2mat(q_j)
+
+                elt = jordan_product(q_i, q_j)
+                ip = inner_product(q_i, q_j)
+
+                if basis_is_matrices:
+                    # do another mat2vec because the multiplication
+                    # table is in terms of vectors
+                    elt = _mat2vec(elt)
+
+                # TODO: the jordan product turns things back into
+                # matrices here even if they're supposed to be
+                # vectors. ugh. Can we get rid of vectors all together
+                # please?
+                elt = W.coordinate_vector(elt)
+                self._multiplication_table[i][j] = self.from_vector(elt)
+                self._inner_product_matrix[i,j] = ip
+                self._inner_product_matrix[j,i] = ip
+
+        self._inner_product_matrix._cache = {'hermitian': True}
+        self._inner_product_matrix.set_immutable()
+
+        if check_axioms:
+            if not self._is_jordanian():
+                raise ValueError("Jordan identity does not hold")
+            if not self._inner_product_is_associative():
+                raise ValueError("inner product is not associative")
+
+
     def _coerce_map_from_base_ring(self):
         """
         Disable the map from the base ring into the algebra.
     def _coerce_map_from_base_ring(self):
         """
         Disable the map from the base ring into the algebra.
@@ -61,190 +251,130 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
         """
         return None
 
         """
         return None
 
-    def __init__(self,
-                 field,
-                 multiplication_table,
-                 inner_product_table,
-                 prefix='e',
-                 category=None,
-                 matrix_basis=None,
-                 check_field=True,
-                 check_axioms=True):
-        """
-        INPUT:
 
 
-          * field -- the scalar field for this algebra (must be real)
+    def product_on_basis(self, i, j):
+        # We only stored the lower-triangular portion of the
+        # multiplication table.
+        if j <= i:
+            return self._multiplication_table[i][j]
+        else:
+            return self._multiplication_table[j][i]
+
+    def inner_product(self, x, y):
+        """
+        The inner product associated with this Euclidean Jordan algebra.
 
 
-          * multiplication_table -- the multiplication table for this
-            algebra's implicit basis. Only the lower-triangular portion
-            of the table is used, since the multiplication is assumed
-            to be commutative.
+        Defaults to the trace inner product, but can be overridden by
+        subclasses if they are sure that the necessary properties are
+        satisfied.
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_algebra import (
-            ....:   FiniteDimensionalEuclideanJordanAlgebra,
-            ....:   JordanSpinEJA,
-            ....:   random_eja)
+            sage: from mjo.eja.eja_algebra import (random_eja,
+            ....:                                  HadamardEJA,
+            ....:                                  BilinearFormEJA)
 
         EXAMPLES:
 
 
         EXAMPLES:
 
-        By definition, Jordan multiplication commutes::
+        Our inner product is "associative," which means the following for
+        a symmetric bilinear form::
 
             sage: set_random_seed()
             sage: J = random_eja()
 
             sage: set_random_seed()
             sage: J = random_eja()
-            sage: x,y = J.random_elements(2)
-            sage: x*y == y*x
+            sage: x,y,z = J.random_elements(3)
+            sage: (x*y).inner_product(z) == y.inner_product(x*z)
             True
 
             True
 
-        An error is raised if the Jordan product is not commutative::
-
-            sage: JP = ((1,2),(0,0))
-            sage: IP = ((1,0),(0,1))
-            sage: FiniteDimensionalEuclideanJordanAlgebra(QQ,JP,IP)
-            Traceback (most recent call last):
-            ...
-            ValueError: Jordan product is not commutative
-
-        An error is raised if the inner-product is not commutative::
+        TESTS:
 
 
-            sage: JP = ((1,0),(0,1))
-            sage: IP = ((1,2),(0,0))
-            sage: FiniteDimensionalEuclideanJordanAlgebra(QQ,JP,IP)
-            Traceback (most recent call last):
-            ...
-            ValueError: inner-product is not commutative
+        Ensure that this is the usual inner product for the algebras
+        over `R^n`::
 
 
-        TESTS:
+            sage: set_random_seed()
+            sage: J = HadamardEJA.random_instance()
+            sage: x,y = J.random_elements(2)
+            sage: actual = x.inner_product(y)
+            sage: expected = x.to_vector().inner_product(y.to_vector())
+            sage: actual == expected
+            True
 
 
-        The ``field`` we're given must be real with ``check_field=True``::
+        Ensure that this is one-half of the trace inner-product in a
+        BilinearFormEJA that isn't just the reals (when ``n`` isn't
+        one). This is in Faraut and Koranyi, and also my "On the
+        symmetry..." paper::
 
 
-            sage: JordanSpinEJA(2, field=QQbar)
-            Traceback (most recent call last):
-            ...
-            ValueError: scalar field is not real
-            sage: JordanSpinEJA(2, field=QQbar, check_field=False)
-            Euclidean Jordan algebra of dimension 2 over Algebraic Field
+            sage: set_random_seed()
+            sage: J = BilinearFormEJA.random_instance()
+            sage: n = J.dimension()
+            sage: x = J.random_element()
+            sage: y = J.random_element()
+            sage: (n == 1) or (x.inner_product(y) == (x*y).trace()/2)
+            True
+        """
+        B = self._inner_product_matrix
+        return (B*x.to_vector()).inner_product(y.to_vector())
 
 
-        The multiplication table must be square with ``check_axioms=True``::
 
 
-            sage: FiniteDimensionalEuclideanJordanAlgebra(QQ,((),()),((1,),))
-            Traceback (most recent call last):
-            ...
-            ValueError: multiplication table is not square
+    def _is_commutative(self):
+        r"""
+        Whether or not this algebra's multiplication table is commutative.
 
 
-        The multiplication and inner-product tables must be the same
-        size (and in particular, the inner-product table must also be
-        square) with ``check_axioms=True``::
+        This method should of course always return ``True``, unless
+        this algebra was constructed with ``check_axioms=False`` and
+        passed an invalid multiplication table.
+        """
+        return all( self.product_on_basis(i,j) == self.product_on_basis(i,j)
+                    for i in range(self.dimension())
+                    for j in range(self.dimension()) )
 
 
-            sage: FiniteDimensionalEuclideanJordanAlgebra(QQ,((1,),),(()))
-            Traceback (most recent call last):
-            ...
-            ValueError: multiplication and inner-product tables are
-            different sizes
-            sage: FiniteDimensionalEuclideanJordanAlgebra(QQ,((1,),),((1,2),))
-            Traceback (most recent call last):
-            ...
-            ValueError: multiplication and inner-product tables are
-            different sizes
+    def _is_jordanian(self):
+        r"""
+        Whether or not this algebra's multiplication table respects the
+        Jordan identity `(x^{2})(xy) = x(x^{2}y)`.
 
 
+        We only check one arrangement of `x` and `y`, so for a
+        ``True`` result to be truly true, you should also check
+        :meth:`_is_commutative`. This method should of course always
+        return ``True``, unless this algebra was constructed with
+        ``check_axioms=False`` and passed an invalid multiplication table.
         """
         """
-        if check_field:
-            if not field.is_subring(RR):
-                # Note: this does return true for the real algebraic
-                # field, the rationals, and any quadratic field where
-                # we've specified a real embedding.
-                raise ValueError("scalar field is not real")
+        return all( (self.monomial(i)**2)*(self.monomial(i)*self.monomial(j))
+                    ==
+                    (self.monomial(i))*((self.monomial(i)**2)*self.monomial(j))
+                    for i in range(self.dimension())
+                    for j in range(self.dimension()) )
 
 
+    def _inner_product_is_associative(self):
+        r"""
+        Return whether or not this algebra's inner product `B` is
+        associative; that is, whether or not `B(xy,z) = B(x,yz)`.
 
 
-        # The multiplication and inner-product tables should be square
-        # if the user wants us to verify them. And we verify them as
-        # soon as possible, because we want to exploit their symmetry.
-        n = len(multiplication_table)
-        if check_axioms:
-            if not all( len(l) == n for l in multiplication_table ):
-                raise ValueError("multiplication table is not square")
-
-            # If the multiplication table is square, we can check if
-            # the inner-product table is square by comparing it to the
-            # multiplication table's dimensions.
-            msg = "multiplication and inner-product tables are different sizes"
-            if not len(inner_product_table) == n:
-                raise ValueError(msg)
-
-            if not all( len(l) == n for l in inner_product_table ):
-                raise ValueError(msg)
-
-            # Check commutativity of the Jordan product (symmetry of
-            # the multiplication table) and the commutativity of the
-            # inner-product (symmetry of the inner-product table)
-            # first if we're going to check them at all.. This has to
-            # be done before we define product_on_basis(), because
-            # that method assumes that self._multiplication_table is
-            # symmetric. And it has to be done before we build
-            # self._inner_product_matrix, because the process used to
-            # construct it assumes symmetry as well.
-            if not all(    multiplication_table[j][i]
-                        == multiplication_table[i][j]
-                        for i in range(n)
-                        for j in range(i+1) ):
-                raise ValueError("Jordan product is not commutative")
+        This method should of course always return ``True``, unless
+        this algebra was constructed with ``check_axioms=False`` and
+        passed an invalid multiplication table.
+        """
 
 
-            if not all( inner_product_table[j][i]
-                        == inner_product_table[i][j]
-                        for i in range(n)
-                        for j in range(i+1) ):
-                raise ValueError("inner-product is not commutative")
+        # Used to check whether or not something is zero in an inexact
+        # ring. This number is sufficient to allow the construction of
+        # QuaternionHermitianEJA(2, field=RDF) with check_axioms=True.
+        epsilon = 1e-16
 
 
-        self._matrix_basis = matrix_basis
-
-        if category is None:
-            category = MagmaticAlgebras(field).FiniteDimensional()
-            category = category.WithBasis().Unital()
-
-        fda = super(FiniteDimensionalEuclideanJordanAlgebra, self)
-        fda.__init__(field,
-                     range(n),
-                     prefix=prefix,
-                     category=category)
-        self.print_options(bracket='')
-
-        # The multiplication table we're given is necessarily in terms
-        # of vectors, because we don't have an algebra yet for
-        # anything to be an element of. However, it's faster in the
-        # long run to have the multiplication table be in terms of
-        # algebra elements. We do this after calling the superclass
-        # constructor so that from_vector() knows what to do.
-        #
-        # Note: we take advantage of symmetry here, and only store
-        # the lower-triangular portion of the table.
-        self._multiplication_table = [ [ self.vector_space().zero()
-                                         for j in range(i+1) ]
-                                       for i in range(n) ]
+        for i in range(self.dimension()):
+            for j in range(self.dimension()):
+                for k in range(self.dimension()):
+                    x = self.monomial(i)
+                    y = self.monomial(j)
+                    z = self.monomial(k)
+                    diff = (x*y).inner_product(z) - x.inner_product(y*z)
 
 
-        for i in range(n):
-            for j in range(i+1):
-                elt = self.from_vector(multiplication_table[i][j])
-                self._multiplication_table[i][j] = elt
-
-        self._multiplication_table = tuple(map(tuple, self._multiplication_table))
-
-        # Save our inner product as a matrix, since the efficiency of
-        # matrix multiplication will usually outweigh the fact that we
-        # have to store a redundant upper- or lower-triangular part.
-        # Pre-cache the fact that these are Hermitian (real symmetric,
-        # in fact) in case some e.g. matrix multiplication routine can
-        # take advantage of it.
-        ip_matrix_constructor = lambda i,j: inner_product_table[i][j] if j <= i else inner_product_table[j][i]
-        self._inner_product_matrix = matrix(field, n, ip_matrix_constructor)
-        self._inner_product_matrix._cache = {'hermitian': True}
-        self._inner_product_matrix.set_immutable()
+                    if self.base_ring().is_exact():
+                        if diff != 0:
+                            return False
+                    else:
+                        if diff.abs() > epsilon:
+                            return False
 
 
-        if check_axioms:
-            if not self._is_jordanian():
-                raise ValueError("Jordan identity does not hold")
-            if not self._inner_product_is_associative():
-                raise ValueError("inner product is not associative")
+        return True
 
     def _element_constructor_(self, elt):
         """
 
     def _element_constructor_(self, elt):
         """
@@ -307,6 +437,12 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
             # that the integer 3 belongs to the space of 2-by-2 matrices.
             raise ValueError(msg)
 
             # that the integer 3 belongs to the space of 2-by-2 matrices.
             raise ValueError(msg)
 
+        try:
+            elt = elt.column()
+        except (AttributeError, TypeError):
+            # Try to convert a vector into a column-matrix
+            pass
+
         if elt not in self.matrix_space():
             raise ValueError(msg)
 
         if elt not in self.matrix_space():
             raise ValueError(msg)
 
@@ -351,74 +487,6 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
         fmt = "Euclidean Jordan algebra of dimension {} over {}"
         return fmt.format(self.dimension(), self.base_ring())
 
         fmt = "Euclidean Jordan algebra of dimension {} over {}"
         return fmt.format(self.dimension(), self.base_ring())
 
-    def product_on_basis(self, i, j):
-        # We only stored the lower-triangular portion of the
-        # multiplication table.
-        if j <= i:
-            return self._multiplication_table[i][j]
-        else:
-            return self._multiplication_table[j][i]
-
-    def _is_commutative(self):
-        r"""
-        Whether or not this algebra's multiplication table is commutative.
-
-        This method should of course always return ``True``, unless
-        this algebra was constructed with ``check_axioms=False`` and
-        passed an invalid multiplication table.
-        """
-        return all( self.product_on_basis(i,j) == self.product_on_basis(i,j)
-                    for i in range(self.dimension())
-                    for j in range(self.dimension()) )
-
-    def _is_jordanian(self):
-        r"""
-        Whether or not this algebra's multiplication table respects the
-        Jordan identity `(x^{2})(xy) = x(x^{2}y)`.
-
-        We only check one arrangement of `x` and `y`, so for a
-        ``True`` result to be truly true, you should also check
-        :meth:`_is_commutative`. This method should of course always
-        return ``True``, unless this algebra was constructed with
-        ``check_axioms=False`` and passed an invalid multiplication table.
-        """
-        return all( (self.monomial(i)**2)*(self.monomial(i)*self.monomial(j))
-                    ==
-                    (self.monomial(i))*((self.monomial(i)**2)*self.monomial(j))
-                    for i in range(self.dimension())
-                    for j in range(self.dimension()) )
-
-    def _inner_product_is_associative(self):
-        r"""
-        Return whether or not this algebra's inner product `B` is
-        associative; that is, whether or not `B(xy,z) = B(x,yz)`.
-
-        This method should of course always return ``True``, unless
-        this algebra was constructed with ``check_axioms=False`` and
-        passed an invalid multiplication table.
-        """
-
-        # Used to check whether or not something is zero in an inexact
-        # ring. This number is sufficient to allow the construction of
-        # QuaternionHermitianEJA(2, field=RDF) with check_axioms=True.
-        epsilon = 1e-16
-
-        for i in range(self.dimension()):
-            for j in range(self.dimension()):
-                for k in range(self.dimension()):
-                    x = self.monomial(i)
-                    y = self.monomial(j)
-                    z = self.monomial(k)
-                    diff = (x*y).inner_product(z) - x.inner_product(y*z)
-
-                    if self.base_ring().is_exact():
-                        if diff != 0:
-                            return False
-                    else:
-                        if diff.abs() > epsilon:
-                            return False
-
-        return True
 
     @cached_method
     def characteristic_polynomial_of(self):
 
     @cached_method
     def characteristic_polynomial_of(self):
@@ -681,11 +749,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
             [0], [1]
             )
         """
             [0], [1]
             )
         """
-        if self._matrix_basis is None:
-            M = self.matrix_space()
-            return tuple( M(b.to_vector()) for b in self.basis() )
-        else:
-            return self._matrix_basis
+        return self._matrix_basis
 
 
     def matrix_space(self):
 
 
     def matrix_space(self):
@@ -703,8 +767,6 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
         """
         if self.is_trivial():
             return MatrixSpace(self.base_ring(), 0)
         """
         if self.is_trivial():
             return MatrixSpace(self.base_ring(), 0)
-        elif self._matrix_basis is None or len(self._matrix_basis) == 0:
-            return MatrixSpace(self.base_ring(), self.dimension(), 1)
         else:
             return self._matrix_basis[0].matrix_space()
 
         else:
             return self._matrix_basis[0].matrix_space()
 
@@ -898,14 +960,14 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
         if not c.is_idempotent():
             raise ValueError("element is not idempotent: %s" % c)
 
         if not c.is_idempotent():
             raise ValueError("element is not idempotent: %s" % c)
 
-        from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanSubalgebra
+        from mjo.eja.eja_subalgebra import FiniteDimensionalEJASubalgebra
 
         # Default these to what they should be if they turn out to be
         # trivial, because eigenspaces_left() won't return eigenvalues
         # corresponding to trivial spaces (e.g. it returns only the
         # eigenspace corresponding to lambda=1 if you take the
         # decomposition relative to the identity element).
 
         # Default these to what they should be if they turn out to be
         # trivial, because eigenspaces_left() won't return eigenvalues
         # corresponding to trivial spaces (e.g. it returns only the
         # eigenspace corresponding to lambda=1 if you take the
         # decomposition relative to the identity element).
-        trivial = FiniteDimensionalEuclideanJordanSubalgebra(self, ())
+        trivial = FiniteDimensionalEJASubalgebra(self, ())
         J0 = trivial                          # eigenvalue zero
         J5 = VectorSpace(self.base_ring(), 0) # eigenvalue one-half
         J1 = trivial                          # eigenvalue one
         J0 = trivial                          # eigenvalue zero
         J5 = VectorSpace(self.base_ring(), 0) # eigenvalue one-half
         J1 = trivial                          # eigenvalue one
@@ -915,9 +977,9 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
                 J5 = eigspace
             else:
                 gens = tuple( self.from_vector(b) for b in eigspace.basis() )
                 J5 = eigspace
             else:
                 gens = tuple( self.from_vector(b) for b in eigspace.basis() )
-                subalg = FiniteDimensionalEuclideanJordanSubalgebra(self,
-                                                                    gens,
-                                                                    check_axioms=False)
+                subalg = FiniteDimensionalEJASubalgebra(self,
+                                                        gens,
+                                                        check_axioms=False)
                 if eigval == 0:
                     J0 = subalg
                 elif eigval == 1:
                 if eigval == 0:
                     J0 = subalg
                 elif eigval == 1:
@@ -1132,9 +1194,9 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
         return self.zero().to_vector().parent().ambient_vector_space()
 
 
         return self.zero().to_vector().parent().ambient_vector_space()
 
 
-    Element = FiniteDimensionalEuclideanJordanAlgebraElement
+    Element = FiniteDimensionalEJAElement
 
 
-class RationalBasisEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebra):
+class RationalBasisEJA(FiniteDimensionalEJA):
     r"""
     New class for algebras whose supplied basis elements have all rational entries.
 
     r"""
     New class for algebras whose supplied basis elements have all rational entries.
 
@@ -1162,10 +1224,9 @@ class RationalBasisEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebr
                  inner_product,
                  field=AA,
                  orthonormalize=True,
                  inner_product,
                  field=AA,
                  orthonormalize=True,
-                 prefix='e',
-                 category=None,
                  check_field=True,
                  check_field=True,
-                 check_axioms=True):
+                 check_axioms=True,
+                 **kwargs):
 
         if check_field:
             # Abuse the check_field parameter to check that the entries of
 
         if check_field:
             # Abuse the check_field parameter to check that the entries of
@@ -1173,32 +1234,6 @@ class RationalBasisEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebr
             if not all( all(b_i in QQ for b_i in b.list()) for b in basis ):
                 raise TypeError("basis not rational")
 
             if not all( all(b_i in QQ for b_i in b.list()) for b in basis ):
                 raise TypeError("basis not rational")
 
-        # Temporary(?) hack to ensure that the matrix and vector bases
-        # are over the same ring.
-        basis = tuple( b.change_ring(field) for b in basis )
-
-        n = len(basis)
-        vector_basis = basis
-
-        from sage.structure.element import is_Matrix
-        basis_is_matrices = False
-
-        degree = 0
-        if n > 0:
-            if is_Matrix(basis[0]):
-                basis_is_matrices = True
-                from mjo.eja.eja_utils import _vec2mat
-                vector_basis = tuple( map(_mat2vec,basis) )
-                degree = basis[0].nrows()**2
-            else:
-                degree = basis[0].degree()
-
-        V = VectorSpace(field, degree)
-
-        # Save a copy of an algebra with the original, rational basis
-        # and over QQ where computations are fast.
-        self._rational_algebra = None
-
         if field is not QQ:
             # There's no point in constructing the extra algebra if this
             # one is already rational.
         if field is not QQ:
             # There's no point in constructing the extra algebra if this
             # one is already rational.
@@ -1206,128 +1241,23 @@ class RationalBasisEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebr
             # Note: the same Jordan and inner-products work here,
             # because they are necessarily defined with respect to
             # ambient coordinates and not any particular basis.
             # Note: the same Jordan and inner-products work here,
             # because they are necessarily defined with respect to
             # ambient coordinates and not any particular basis.
-            self._rational_algebra = RationalBasisEuclideanJordanAlgebra(
+            self._rational_algebra = FiniteDimensionalEJA(
                                        basis,
                                        jordan_product,
                                        inner_product,
                                        field=QQ,
                                        orthonormalize=False,
                                        basis,
                                        jordan_product,
                                        inner_product,
                                        field=QQ,
                                        orthonormalize=False,
-                                       prefix=prefix,
-                                       category=category,
                                        check_field=False,
                                        check_field=False,
-                                       check_axioms=False)
-
-        if orthonormalize:
-            # Compute the deorthonormalized tables before we orthonormalize
-            # the given basis. The "check" parameter here guarantees that
-            # the basis is linearly-independent.
-            W = V.span_of_basis( vector_basis, check=check_axioms)
-
-            # Note: the Jordan and inner-products are defined in terms
-            # of the ambient basis. It's important that their arguments
-            # are in ambient coordinates as well.
-            for i in range(n):
-                for j in range(i+1):
-                    # given basis w.r.t. ambient coords
-                    q_i = vector_basis[i]
-                    q_j = vector_basis[j]
-
-                    if basis_is_matrices:
-                        q_i = _vec2mat(q_i)
-                        q_j = _vec2mat(q_j)
-
-                    elt = jordan_product(q_i, q_j)
-                    ip = inner_product(q_i, q_j)
-
-                    if basis_is_matrices:
-                        # do another mat2vec because the multiplication
-                        # table is in terms of vectors
-                        elt = _mat2vec(elt)
-
-        # We overwrite the name "vector_basis" in a second, but never modify it
-        # in place, to this effectively makes a copy of it.
-        deortho_vector_basis = vector_basis
-        self._deortho_matrix = None
-
-        if orthonormalize:
-            from mjo.eja.eja_utils import gram_schmidt
-            if basis_is_matrices:
-                vector_ip = lambda x,y: inner_product(_vec2mat(x), _vec2mat(y))
-                vector_basis = gram_schmidt(vector_basis, vector_ip)
-            else:
-                vector_basis = gram_schmidt(vector_basis, inner_product)
-
-            # Normalize the "matrix" basis, too!
-            basis = vector_basis
+                                       check_axioms=False,
+                                       **kwargs)
 
 
-            if basis_is_matrices:
-                basis = tuple( map(_vec2mat,basis) )
-
-        W = V.span_of_basis( vector_basis, check=check_axioms)
-
-        # Now "W" is the vector space of our algebra coordinates. The
-        # variables "X1", "X2",...  refer to the entries of vectors in
-        # W. Thus to convert back and forth between the orthonormal
-        # coordinates and the given ones, we need to stick the original
-        # basis in W.
-        U = V.span_of_basis( deortho_vector_basis, check=check_axioms)
-        self._deortho_matrix = matrix( U.coordinate_vector(q)
-                                       for q in vector_basis )
-
-        # If the superclass constructor is going to verify the
-        # symmetry of this table, it has better at least be
-        # square...
-        if check_axioms:
-            mult_table = [ [0 for j in range(n)] for i in range(n) ]
-            ip_table = [ [0 for j in range(n)] for i in range(n) ]
-        else:
-            mult_table = [ [0 for j in range(i+1)] for i in range(n) ]
-            ip_table = [ [0 for j in range(i+1)] for i in range(n) ]
-
-        # Note: the Jordan and inner-products are defined in terms
-        # of the ambient basis. It's important that their arguments
-        # are in ambient coordinates as well.
-        for i in range(n):
-            for j in range(i+1):
-                # ortho basis w.r.t. ambient coords
-                q_i = vector_basis[i]
-                q_j = vector_basis[j]
-
-                if basis_is_matrices:
-                    q_i = _vec2mat(q_i)
-                    q_j = _vec2mat(q_j)
-
-                elt = jordan_product(q_i, q_j)
-                ip = inner_product(q_i, q_j)
-
-                if basis_is_matrices:
-                    # do another mat2vec because the multiplication
-                    # table is in terms of vectors
-                    elt = _mat2vec(elt)
-
-                elt = W.coordinate_vector(elt)
-                mult_table[i][j] = elt
-                ip_table[i][j] = ip
-                if check_axioms:
-                    # The tables are square if we're verifying that they
-                    # are commutative.
-                    mult_table[j][i] = elt
-                    ip_table[j][i] = ip
-
-        if basis_is_matrices:
-            for m in basis:
-                m.set_immutable()
-        else:
-            basis = tuple( x.column() for x in basis )
-
-        super().__init__(field,
-                         mult_table,
-                         ip_table,
-                         prefix,
-                         category,
-                         basis, # matrix basis
-                         check_field,
-                         check_axioms)
+        super().__init__(basis,
+                         jordan_product,
+                         inner_product,
+                         field=field,
+                         check_field=check_field,
+                         check_axioms=check_axioms,
+                         **kwargs)
 
     @cached_method
     def _charpoly_coefficients(self):
 
     @cached_method
     def _charpoly_coefficients(self):
@@ -1358,8 +1288,7 @@ class RationalBasisEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebr
             # rationals if this one is already over the
             # rationals. Likewise, if we never orthonormalized our
             # basis, we might as well just use the given one.
             # rationals if this one is already over the
             # rationals. Likewise, if we never orthonormalized our
             # basis, we might as well just use the given one.
-            superclass = super(RationalBasisEuclideanJordanAlgebra, self)
-            return superclass._charpoly_coefficients()
+            return super()._charpoly_coefficients()
 
         # Do the computation over the rationals. The answer will be
         # the same, because all we've done is a change of basis.
 
         # Do the computation over the rationals. The answer will be
         # the same, because all we've done is a change of basis.
@@ -1377,7 +1306,7 @@ class RationalBasisEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebr
         subs_dict = { X[i]: BX[i] for i in range(len(X)) }
         return tuple( a_i.subs(subs_dict) for a_i in a )
 
         subs_dict = { X[i]: BX[i] for i in range(len(X)) }
         return tuple( a_i.subs(subs_dict) for a_i in a )
 
-class ConcreteEuclideanJordanAlgebra(RationalBasisEuclideanJordanAlgebra):
+class ConcreteEJA(RationalBasisEJA):
     r"""
     A class for the Euclidean Jordan algebras that we know by name.
 
     r"""
     A class for the Euclidean Jordan algebras that we know by name.
 
@@ -1388,7 +1317,7 @@ class ConcreteEuclideanJordanAlgebra(RationalBasisEuclideanJordanAlgebra):
 
     SETUP::
 
 
     SETUP::
 
-        sage: from mjo.eja.eja_algebra import ConcreteEuclideanJordanAlgebra
+        sage: from mjo.eja.eja_algebra import ConcreteEJA
 
     TESTS:
 
 
     TESTS:
 
@@ -1396,7 +1325,7 @@ class ConcreteEuclideanJordanAlgebra(RationalBasisEuclideanJordanAlgebra):
     product, unless we specify otherwise::
 
         sage: set_random_seed()
     product, unless we specify otherwise::
 
         sage: set_random_seed()
-        sage: J = ConcreteEuclideanJordanAlgebra.random_instance()
+        sage: J = ConcreteEJA.random_instance()
         sage: all( b.norm() == 1 for b in J.gens() )
         True
 
         sage: all( b.norm() == 1 for b in J.gens() )
         True
 
@@ -1407,7 +1336,7 @@ class ConcreteEuclideanJordanAlgebra(RationalBasisEuclideanJordanAlgebra):
     EJA the operator is self-adjoint by the Jordan axiom::
 
         sage: set_random_seed()
     EJA the operator is self-adjoint by the Jordan axiom::
 
         sage: set_random_seed()
-        sage: J = ConcreteEuclideanJordanAlgebra.random_instance()
+        sage: J = ConcreteEJA.random_instance()
         sage: x = J.random_element()
         sage: x.operator().is_self_adjoint()
         True
         sage: x = J.random_element()
         sage: x.operator().is_self_adjoint()
         True
@@ -1439,13 +1368,13 @@ class ConcreteEuclideanJordanAlgebra(RationalBasisEuclideanJordanAlgebra):
         from sage.misc.prandom import choice
         eja_class = choice(cls.__subclasses__())
 
         from sage.misc.prandom import choice
         eja_class = choice(cls.__subclasses__())
 
-        # These all bubble up to the RationalBasisEuclideanJordanAlgebra
-        # superclass constructor, so any (kw)args valid there are also
-        # valid here.
+        # These all bubble up to the RationalBasisEJA superclass
+        # constructor, so any (kw)args valid there are also valid
+        # here.
         return eja_class.random_instance(*args, **kwargs)
 
 
         return eja_class.random_instance(*args, **kwargs)
 
 
-class MatrixEuclideanJordanAlgebra:
+class MatrixEJA:
     @staticmethod
     def dimension_over_reals():
         r"""
     @staticmethod
     def dimension_over_reals():
         r"""
@@ -1566,14 +1495,13 @@ class MatrixEuclideanJordanAlgebra:
             return tr.coefficient_tuple()[0]
 
 
             return tr.coefficient_tuple()[0]
 
 
-class RealMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
+class RealMatrixEJA(MatrixEJA):
     @staticmethod
     def dimension_over_reals():
         return 1
 
 
     @staticmethod
     def dimension_over_reals():
         return 1
 
 
-class RealSymmetricEJA(ConcreteEuclideanJordanAlgebra,
-                       RealMatrixEuclideanJordanAlgebra):
+class RealSymmetricEJA(ConcreteEJA, RealMatrixEJA):
     """
     The rank-n simple EJA consisting of real symmetric n-by-n
     matrices, the usual symmetric Jordan product, and the trace inner
     """
     The rank-n simple EJA consisting of real symmetric n-by-n
     matrices, the usual symmetric Jordan product, and the trace inner
@@ -1693,15 +1621,15 @@ class RealSymmetricEJA(ConcreteEuclideanJordanAlgebra,
                                                **kwargs)
 
         # TODO: this could be factored out somehow, but is left here
                                                **kwargs)
 
         # TODO: this could be factored out somehow, but is left here
-        # because the MatrixEuclideanJordanAlgebra is not presently
-        # a subclass of the FDEJA class that defines rank() and one().
+        # 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)
         self.one.set_cache(self(idV))
 
 
 
         self.rank.set_cache(n)
         idV = matrix.identity(ZZ, self.dimension_over_reals()*n)
         self.one.set_cache(self(idV))
 
 
 
-class ComplexMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
+class ComplexMatrixEJA(MatrixEJA):
     @staticmethod
     def dimension_over_reals():
         return 2
     @staticmethod
     def dimension_over_reals():
         return 2
@@ -1715,8 +1643,7 @@ class ComplexMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_algebra import \
-            ....:   ComplexMatrixEuclideanJordanAlgebra
+            sage: from mjo.eja.eja_algebra import ComplexMatrixEJA
 
         EXAMPLES::
 
 
         EXAMPLES::
 
@@ -1726,7 +1653,7 @@ class ComplexMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
             sage: x3 = F(-i)
             sage: x4 = F(6)
             sage: M = matrix(F,2,[[x1,x2],[x3,x4]])
             sage: x3 = F(-i)
             sage: x4 = F(6)
             sage: M = matrix(F,2,[[x1,x2],[x3,x4]])
-            sage: ComplexMatrixEuclideanJordanAlgebra.real_embed(M)
+            sage: ComplexMatrixEJA.real_embed(M)
             [ 4 -2| 1  2]
             [ 2  4|-2  1]
             [-----+-----]
             [ 4 -2| 1  2]
             [ 2  4|-2  1]
             [-----+-----]
@@ -1742,14 +1669,14 @@ class ComplexMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
             sage: F = QuadraticField(-1, 'I')
             sage: X = random_matrix(F, n)
             sage: Y = random_matrix(F, n)
             sage: F = QuadraticField(-1, 'I')
             sage: X = random_matrix(F, n)
             sage: Y = random_matrix(F, n)
-            sage: Xe = ComplexMatrixEuclideanJordanAlgebra.real_embed(X)
-            sage: Ye = ComplexMatrixEuclideanJordanAlgebra.real_embed(Y)
-            sage: XYe = ComplexMatrixEuclideanJordanAlgebra.real_embed(X*Y)
+            sage: Xe = ComplexMatrixEJA.real_embed(X)
+            sage: Ye = ComplexMatrixEJA.real_embed(Y)
+            sage: XYe = ComplexMatrixEJA.real_embed(X*Y)
             sage: Xe*Ye == XYe
             True
 
         """
             sage: Xe*Ye == XYe
             True
 
         """
-        super(ComplexMatrixEuclideanJordanAlgebra,cls).real_embed(M)
+        super(ComplexMatrixEJA,cls).real_embed(M)
         n = M.nrows()
 
         # We don't need any adjoined elements...
         n = M.nrows()
 
         # We don't need any adjoined elements...
@@ -1771,8 +1698,7 @@ class ComplexMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_algebra import \
-            ....:   ComplexMatrixEuclideanJordanAlgebra
+            sage: from mjo.eja.eja_algebra import ComplexMatrixEJA
 
         EXAMPLES::
 
 
         EXAMPLES::
 
@@ -1780,7 +1706,7 @@ class ComplexMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
             ....:                 [-2,  1,  -4,  3],
             ....:                 [ 9,  10, 11, 12],
             ....:                 [-10, 9, -12, 11] ])
             ....:                 [-2,  1,  -4,  3],
             ....:                 [ 9,  10, 11, 12],
             ....:                 [-10, 9, -12, 11] ])
-            sage: ComplexMatrixEuclideanJordanAlgebra.real_unembed(A)
+            sage: ComplexMatrixEJA.real_unembed(A)
             [  2*I + 1   4*I + 3]
             [ 10*I + 9 12*I + 11]
 
             [  2*I + 1   4*I + 3]
             [ 10*I + 9 12*I + 11]
 
@@ -1791,12 +1717,12 @@ class ComplexMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
             sage: set_random_seed()
             sage: F = QuadraticField(-1, 'I')
             sage: M = random_matrix(F, 3)
             sage: set_random_seed()
             sage: F = QuadraticField(-1, 'I')
             sage: M = random_matrix(F, 3)
-            sage: Me = ComplexMatrixEuclideanJordanAlgebra.real_embed(M)
-            sage: ComplexMatrixEuclideanJordanAlgebra.real_unembed(Me) == M
+            sage: Me = ComplexMatrixEJA.real_embed(M)
+            sage: ComplexMatrixEJA.real_unembed(Me) == M
             True
 
         """
             True
 
         """
-        super(ComplexMatrixEuclideanJordanAlgebra,cls).real_unembed(M)
+        super(ComplexMatrixEJA,cls).real_unembed(M)
         n = ZZ(M.nrows())
         d = cls.dimension_over_reals()
 
         n = ZZ(M.nrows())
         d = cls.dimension_over_reals()
 
@@ -1837,8 +1763,7 @@ class ComplexMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
         return matrix(F, n/d, elements)
 
 
         return matrix(F, n/d, elements)
 
 
-class ComplexHermitianEJA(ConcreteEuclideanJordanAlgebra,
-                          ComplexMatrixEuclideanJordanAlgebra):
+class ComplexHermitianEJA(ConcreteEJA, ComplexMatrixEJA):
     """
     The rank-n simple EJA consisting of complex Hermitian n-by-n
     matrices over the real numbers, the usual symmetric Jordan product,
     """
     The rank-n simple EJA consisting of complex Hermitian n-by-n
     matrices over the real numbers, the usual symmetric Jordan product,
@@ -1961,8 +1886,8 @@ class ComplexHermitianEJA(ConcreteEuclideanJordanAlgebra,
                                                   self.trace_inner_product,
                                                   **kwargs)
         # TODO: this could be factored out somehow, but is left here
                                                   self.trace_inner_product,
                                                   **kwargs)
         # TODO: this could be factored out somehow, but is left here
-        # because the MatrixEuclideanJordanAlgebra is not presently
-        # a subclass of the FDEJA class that defines rank() and one().
+        # 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)
         self.one.set_cache(self(idV))
         self.rank.set_cache(n)
         idV = matrix.identity(ZZ, self.dimension_over_reals()*n)
         self.one.set_cache(self(idV))
@@ -1979,7 +1904,7 @@ class ComplexHermitianEJA(ConcreteEuclideanJordanAlgebra,
         n = ZZ.random_element(cls._max_random_instance_size() + 1)
         return cls(n, **kwargs)
 
         n = ZZ.random_element(cls._max_random_instance_size() + 1)
         return cls(n, **kwargs)
 
-class QuaternionMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
+class QuaternionMatrixEJA(MatrixEJA):
     @staticmethod
     def dimension_over_reals():
         return 4
     @staticmethod
     def dimension_over_reals():
         return 4
@@ -1995,8 +1920,7 @@ class QuaternionMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_algebra import \
-            ....:   QuaternionMatrixEuclideanJordanAlgebra
+            sage: from mjo.eja.eja_algebra import QuaternionMatrixEJA
 
         EXAMPLES::
 
 
         EXAMPLES::
 
@@ -2004,7 +1928,7 @@ class QuaternionMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
             sage: i,j,k = Q.gens()
             sage: x = 1 + 2*i + 3*j + 4*k
             sage: M = matrix(Q, 1, [[x]])
             sage: i,j,k = Q.gens()
             sage: x = 1 + 2*i + 3*j + 4*k
             sage: M = matrix(Q, 1, [[x]])
-            sage: QuaternionMatrixEuclideanJordanAlgebra.real_embed(M)
+            sage: QuaternionMatrixEJA.real_embed(M)
             [ 1  2  3  4]
             [-2  1 -4  3]
             [-3  4  1 -2]
             [ 1  2  3  4]
             [-2  1 -4  3]
             [-3  4  1 -2]
@@ -2017,14 +1941,14 @@ class QuaternionMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
             sage: Q = QuaternionAlgebra(QQ,-1,-1)
             sage: X = random_matrix(Q, n)
             sage: Y = random_matrix(Q, n)
             sage: Q = QuaternionAlgebra(QQ,-1,-1)
             sage: X = random_matrix(Q, n)
             sage: Y = random_matrix(Q, n)
-            sage: Xe = QuaternionMatrixEuclideanJordanAlgebra.real_embed(X)
-            sage: Ye = QuaternionMatrixEuclideanJordanAlgebra.real_embed(Y)
-            sage: XYe = QuaternionMatrixEuclideanJordanAlgebra.real_embed(X*Y)
+            sage: Xe = QuaternionMatrixEJA.real_embed(X)
+            sage: Ye = QuaternionMatrixEJA.real_embed(Y)
+            sage: XYe = QuaternionMatrixEJA.real_embed(X*Y)
             sage: Xe*Ye == XYe
             True
 
         """
             sage: Xe*Ye == XYe
             True
 
         """
-        super(QuaternionMatrixEuclideanJordanAlgebra,cls).real_embed(M)
+        super(QuaternionMatrixEJA,cls).real_embed(M)
         quaternions = M.base_ring()
         n = M.nrows()
 
         quaternions = M.base_ring()
         n = M.nrows()
 
@@ -2040,7 +1964,7 @@ class QuaternionMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
             d = t[3]
             cplxM = matrix(F, 2, [[ a + b*i, c + d*i],
                                  [-c + d*i, a - b*i]])
             d = t[3]
             cplxM = matrix(F, 2, [[ a + b*i, c + d*i],
                                  [-c + d*i, a - b*i]])
-            realM = ComplexMatrixEuclideanJordanAlgebra.real_embed(cplxM)
+            realM = ComplexMatrixEJA.real_embed(cplxM)
             blocks.append(realM)
 
         # We should have real entries by now, so use the realest field
             blocks.append(realM)
 
         # We should have real entries by now, so use the realest field
@@ -2056,8 +1980,7 @@ class QuaternionMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_algebra import \
-            ....:   QuaternionMatrixEuclideanJordanAlgebra
+            sage: from mjo.eja.eja_algebra import QuaternionMatrixEJA
 
         EXAMPLES::
 
 
         EXAMPLES::
 
@@ -2065,7 +1988,7 @@ class QuaternionMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
             ....:                 [-2,  1, -4,  3],
             ....:                 [-3,  4,  1, -2],
             ....:                 [-4, -3,  2,  1]])
             ....:                 [-2,  1, -4,  3],
             ....:                 [-3,  4,  1, -2],
             ....:                 [-4, -3,  2,  1]])
-            sage: QuaternionMatrixEuclideanJordanAlgebra.real_unembed(M)
+            sage: QuaternionMatrixEJA.real_unembed(M)
             [1 + 2*i + 3*j + 4*k]
 
         TESTS:
             [1 + 2*i + 3*j + 4*k]
 
         TESTS:
@@ -2075,12 +1998,12 @@ class QuaternionMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
             sage: set_random_seed()
             sage: Q = QuaternionAlgebra(QQ, -1, -1)
             sage: M = random_matrix(Q, 3)
             sage: set_random_seed()
             sage: Q = QuaternionAlgebra(QQ, -1, -1)
             sage: M = random_matrix(Q, 3)
-            sage: Me = QuaternionMatrixEuclideanJordanAlgebra.real_embed(M)
-            sage: QuaternionMatrixEuclideanJordanAlgebra.real_unembed(Me) == M
+            sage: Me = QuaternionMatrixEJA.real_embed(M)
+            sage: QuaternionMatrixEJA.real_unembed(Me) == M
             True
 
         """
             True
 
         """
-        super(QuaternionMatrixEuclideanJordanAlgebra,cls).real_unembed(M)
+        super(QuaternionMatrixEJA,cls).real_unembed(M)
         n = ZZ(M.nrows())
         d = cls.dimension_over_reals()
 
         n = ZZ(M.nrows())
         d = cls.dimension_over_reals()
 
@@ -2096,7 +2019,7 @@ class QuaternionMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
         elements = []
         for l in range(n/d):
             for m in range(n/d):
         elements = []
         for l in range(n/d):
             for m in range(n/d):
-                submat = ComplexMatrixEuclideanJordanAlgebra.real_unembed(
+                submat = ComplexMatrixEJA.real_unembed(
                     M[d*l:d*l+d,d*m:d*m+d] )
                 if submat[0,0] != submat[1,1].conjugate():
                     raise ValueError('bad on-diagonal submatrix')
                     M[d*l:d*l+d,d*m:d*m+d] )
                 if submat[0,0] != submat[1,1].conjugate():
                     raise ValueError('bad on-diagonal submatrix')
@@ -2111,8 +2034,7 @@ class QuaternionMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra):
         return matrix(Q, n/d, elements)
 
 
         return matrix(Q, n/d, elements)
 
 
-class QuaternionHermitianEJA(ConcreteEuclideanJordanAlgebra,
-                             QuaternionMatrixEuclideanJordanAlgebra):
+class QuaternionHermitianEJA(ConcreteEJA, QuaternionMatrixEJA):
     r"""
     The rank-n simple EJA consisting of self-adjoint n-by-n quaternion
     matrices, the usual symmetric Jordan product, and the
     r"""
     The rank-n simple EJA consisting of self-adjoint n-by-n quaternion
     matrices, the usual symmetric Jordan product, and the
@@ -2236,8 +2158,8 @@ class QuaternionHermitianEJA(ConcreteEuclideanJordanAlgebra,
                                                      self.trace_inner_product,
                                                      **kwargs)
         # TODO: this could be factored out somehow, but is left here
                                                      self.trace_inner_product,
                                                      **kwargs)
         # TODO: this could be factored out somehow, but is left here
-        # because the MatrixEuclideanJordanAlgebra is not presently
-        # a subclass of the FDEJA class that defines rank() and one().
+        # 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)
         self.one.set_cache(self(idV))
         self.rank.set_cache(n)
         idV = matrix.identity(ZZ, self.dimension_over_reals()*n)
         self.one.set_cache(self(idV))
@@ -2259,7 +2181,7 @@ class QuaternionHermitianEJA(ConcreteEuclideanJordanAlgebra,
         return cls(n, **kwargs)
 
 
         return cls(n, **kwargs)
 
 
-class HadamardEJA(ConcreteEuclideanJordanAlgebra):
+class HadamardEJA(ConcreteEJA):
     """
     Return the Euclidean Jordan Algebra corresponding to the set
     `R^n` under the Hadamard product.
     """
     Return the Euclidean Jordan Algebra corresponding to the set
     `R^n` under the Hadamard product.
@@ -2344,7 +2266,7 @@ class HadamardEJA(ConcreteEuclideanJordanAlgebra):
         return cls(n, **kwargs)
 
 
         return cls(n, **kwargs)
 
 
-class BilinearFormEJA(ConcreteEuclideanJordanAlgebra):
+class BilinearFormEJA(ConcreteEJA):
     r"""
     The rank-2 simple EJA consisting of real vectors ``x=(x0, x_bar)``
     with the half-trace inner product and jordan product ``x*y =
     r"""
     The rank-2 simple EJA consisting of real vectors ``x=(x0, x_bar)``
     with the half-trace inner product and jordan product ``x*y =
@@ -2576,7 +2498,7 @@ class JordanSpinEJA(BilinearFormEJA):
         return cls(n, **kwargs)
 
 
         return cls(n, **kwargs)
 
 
-class TrivialEJA(ConcreteEuclideanJordanAlgebra):
+class TrivialEJA(ConcreteEJA):
     """
     The trivial Euclidean Jordan algebra consisting of only a zero element.
 
     """
     The trivial Euclidean Jordan algebra consisting of only a zero element.
 
@@ -2629,7 +2551,7 @@ class TrivialEJA(ConcreteEuclideanJordanAlgebra):
         # inappropriate for us.
         return cls(**kwargs)
 
         # inappropriate for us.
         return cls(**kwargs)
 
-class DirectSumEJA(FiniteDimensionalEuclideanJordanAlgebra):
+class DirectSumEJA(ConcreteEJA):
     r"""
     The external (orthogonal) direct sum of two other Euclidean Jordan
     algebras. Essentially the Cartesian product of its two factors.
     r"""
     The external (orthogonal) direct sum of two other Euclidean Jordan
     algebras. Essentially the Cartesian product of its two factors.
@@ -2757,8 +2679,8 @@ class DirectSumEJA(FiniteDimensionalEuclideanJordanAlgebra):
         # zero-by-two matrix (important for composing things).
         P1 = matrix(self.base_ring(), m, m+n, V_basis[:m])
         P2 = matrix(self.base_ring(), n, m+n, V_basis[m:])
         # zero-by-two matrix (important for composing things).
         P1 = matrix(self.base_ring(), m, m+n, V_basis[:m])
         P2 = matrix(self.base_ring(), n, m+n, V_basis[m:])
-        pi_left = FiniteDimensionalEuclideanJordanAlgebraOperator(self,J1,P1)
-        pi_right = FiniteDimensionalEuclideanJordanAlgebraOperator(self,J2,P2)
+        pi_left = FiniteDimensionalEJAOperator(self,J1,P1)
+        pi_right = FiniteDimensionalEJAOperator(self,J2,P2)
         return (pi_left, pi_right)
 
     def inclusions(self):
         return (pi_left, pi_right)
 
     def inclusions(self):
@@ -2824,8 +2746,8 @@ class DirectSumEJA(FiniteDimensionalEuclideanJordanAlgebra):
         # two-by-zero matrix (important for composing things).
         I1 = matrix.column(self.base_ring(), m, m+n, V_basis[:m])
         I2 = matrix.column(self.base_ring(), n, m+n, V_basis[m:])
         # two-by-zero matrix (important for composing things).
         I1 = matrix.column(self.base_ring(), m, m+n, V_basis[:m])
         I2 = matrix.column(self.base_ring(), n, m+n, V_basis[m:])
-        iota_left = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,self,I1)
-        iota_right = FiniteDimensionalEuclideanJordanAlgebraOperator(J2,self,I2)
+        iota_left = FiniteDimensionalEJAOperator(J1,self,I1)
+        iota_right = FiniteDimensionalEJAOperator(J2,self,I2)
         return (iota_left, iota_right)
 
     def inner_product(self, x, y):
         return (iota_left, iota_right)
 
     def inner_product(self, x, y):
@@ -2869,4 +2791,4 @@ class DirectSumEJA(FiniteDimensionalEuclideanJordanAlgebra):
 
 
 
 
 
 
-random_eja = ConcreteEuclideanJordanAlgebra.random_instance
+random_eja = ConcreteEJA.random_instance
index 6812e2807a7ff3c3a4f7253c7af9750f5de8fbb2..6181f032e644423989cf135cd65eeafcb943585f 100644 (file)
@@ -2,10 +2,10 @@ from sage.matrix.constructor import matrix
 from sage.modules.free_module import VectorSpace
 from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement
 
 from sage.modules.free_module import VectorSpace
 from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement
 
-from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
 from mjo.eja.eja_utils import _mat2vec
 
 from mjo.eja.eja_utils import _mat2vec
 
-class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
+class FiniteDimensionalEJAElement(IndexedFreeModuleElement):
     """
     An element of a Euclidean Jordan algebra.
     """
     """
     An element of a Euclidean Jordan algebra.
     """
@@ -1122,10 +1122,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
         P = self.parent()
         left_mult_by_self = lambda y: self*y
         L = P.module_morphism(function=left_mult_by_self, codomain=P)
         P = self.parent()
         left_mult_by_self = lambda y: self*y
         L = P.module_morphism(function=left_mult_by_self, codomain=P)
-        return FiniteDimensionalEuclideanJordanAlgebraOperator(
-                 P,
-                 P,
-                 L.matrix() )
+        return FiniteDimensionalEJAOperator(P, P, L.matrix() )
 
 
     def quadratic_representation(self, other=None):
 
 
     def quadratic_representation(self, other=None):
@@ -1370,8 +1367,8 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
             True
 
         """
             True
 
         """
-        from mjo.eja.eja_element_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
-        return FiniteDimensionalEuclideanJordanElementSubalgebra(self, orthonormalize_basis)
+        from mjo.eja.eja_element_subalgebra import FiniteDimensionalEJAElementSubalgebra
+        return FiniteDimensionalEJAElementSubalgebra(self, orthonormalize_basis)
 
 
     def subalgebra_idempotent(self):
 
 
     def subalgebra_idempotent(self):
index 7edf1df940fb3e16435eb7d232fea0ceb58eff7a..dceb3b405a4c5a663c61a966993ce890ed516b49 100644 (file)
@@ -2,24 +2,20 @@ from sage.matrix.constructor import matrix
 from sage.misc.cachefunc import cached_method
 from sage.rings.all import QQ
 
 from sage.misc.cachefunc import cached_method
 from sage.rings.all import QQ
 
-from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanSubalgebra
+from mjo.eja.eja_subalgebra import FiniteDimensionalEJASubalgebra
 
 
 
 
-class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclideanJordanSubalgebra):
-    def __init__(self, elt, orthonormalize_basis):
-        self._superalgebra = elt.parent()
-        category = self._superalgebra.category().Associative()
-        V = self._superalgebra.vector_space()
-        field = self._superalgebra.base_ring()
+class FiniteDimensionalEJAElementSubalgebra(FiniteDimensionalEJASubalgebra):
+    def __init__(self, elt, orthonormalize=True, **kwargs):
+        superalgebra = elt.parent()
 
 
-        # This list is guaranteed to contain all independent powers,
-        # because it's the maximal set of powers that could possibly
-        # be independent (by a dimension argument).
-        powers = [ elt**k for k in range(V.dimension()) ]
-        power_vectors = [ p.to_vector() for p in powers ]
-        P = matrix(field, power_vectors)
+        powers = tuple( elt**k for k in range(superalgebra.dimension()) )
+        power_vectors = ( p.to_vector() for p in powers )
+        P = matrix(superalgebra.base_ring(), power_vectors)
 
 
-        if orthonormalize_basis == False:
+        if orthonormalize:
+            basis = powers # let god sort 'em out
+        else:
             # Echelonize the matrix ourselves, because otherwise the
             # call to P.pivot_rows() below can choose a non-optimal
             # row-reduction algorithm. In particular, scaling can
             # Echelonize the matrix ourselves, because otherwise the
             # call to P.pivot_rows() below can choose a non-optimal
             # row-reduction algorithm. In particular, scaling can
@@ -29,39 +25,26 @@ class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclide
             # Beware: QQ supports an entirely different set of "algorithm"
             # keywords than do AA and RR.
             algo = None
             # Beware: QQ supports an entirely different set of "algorithm"
             # keywords than do AA and RR.
             algo = None
-            if field is not QQ:
+            if superalgebra.base_ring() is not QQ:
                 algo = "scaled_partial_pivoting"
                 algo = "scaled_partial_pivoting"
-            P.echelonize(algorithm=algo)
+                P.echelonize(algorithm=algo)
 
 
-            # In this case, we just need to figure out which elements
-            # of the "powers" list are redundant... First compute the
-            # vector subspace spanned by the powers of the given
-            # element.
+                # In this case, we just need to figure out which elements
+                # of the "powers" list are redundant... First compute the
+                # vector subspace spanned by the powers of the given
+                # element.
 
 
-            # Figure out which powers form a linearly-independent set.
-            ind_rows = P.pivot_rows()
+                # Figure out which powers form a linearly-independent set.
+                ind_rows = P.pivot_rows()
 
 
-            # Pick those out of the list of all powers.
-            superalgebra_basis = tuple(map(powers.__getitem__, ind_rows))
-        else:
-            # If we're going to orthonormalize the basis anyway, we
-            # might as well just do Gram-Schmidt on the whole list of
-            # powers. The redundant ones will get zero'd out. If this
-            # looks like a roundabout way to orthonormalize, it is.
-            # But converting everything from algebra elements to vectors
-            # to matrices and then back again turns out to be about
-            # as fast as reimplementing our own Gram-Schmidt that
-            # works in an EJA.
-            G,_ = P.gram_schmidt(orthonormal=True)
-            basis_vectors = [ g for g in G.rows() if not g.is_zero() ]
-            superalgebra_basis = [ self._superalgebra.from_vector(b)
-                                   for b in basis_vectors ]
-
-        fdeja = super(FiniteDimensionalEuclideanJordanElementSubalgebra, self)
-        fdeja.__init__(self._superalgebra,
-                       superalgebra_basis,
-                       category=category,
-                       check_axioms=False)
+                # Pick those out of the list of all powers.
+                basis = tuple(map(powers.__getitem__, ind_rows))
+
+
+        super().__init__(superalgebra,
+                         basis,
+                         associative=True,
+                         **kwargs)
 
         # The rank is the highest possible degree of a minimal
         # polynomial, and is bounded above by the dimension. We know
 
         # The rank is the highest possible degree of a minimal
         # polynomial, and is bounded above by the dimension. We know
index 0b52f555d51f58341fe56f5b63984f88cdf99da0..6ec335f7560f174cf205b1f814fc7a1438a35e6c 100644 (file)
@@ -2,14 +2,14 @@ from sage.matrix.constructor import matrix
 from sage.categories.all import FreeModules
 from sage.categories.map import Map
 
 from sage.categories.all import FreeModules
 from sage.categories.map import Map
 
-class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
+class FiniteDimensionalEJAOperator(Map):
     r"""
     An operator between two finite-dimensional Euclidean Jordan algebras.
 
     SETUP::
 
         sage: from mjo.eja.eja_algebra import HadamardEJA
     r"""
     An operator between two finite-dimensional Euclidean Jordan algebras.
 
     SETUP::
 
         sage: from mjo.eja.eja_algebra import HadamardEJA
-        sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+        sage: from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
 
     EXAMPLES:
 
 
     EXAMPLES:
 
@@ -19,12 +19,12 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
         sage: J = HadamardEJA(3)
         sage: V = VectorSpace(J.base_ring(), 3)
         sage: M = matrix.identity(J.base_ring(), 3)
         sage: J = HadamardEJA(3)
         sage: V = VectorSpace(J.base_ring(), 3)
         sage: M = matrix.identity(J.base_ring(), 3)
-        sage: FiniteDimensionalEuclideanJordanAlgebraOperator(V,J,M)
+        sage: FiniteDimensionalEJAOperator(V,J,M)
         Traceback (most recent call last):
         ...
         TypeError: domain must be a finite-dimensional Euclidean
         Jordan algebra
         Traceback (most recent call last):
         ...
         TypeError: domain must be a finite-dimensional Euclidean
         Jordan algebra
-        sage: FiniteDimensionalEuclideanJordanAlgebraOperator(J,V,M)
+        sage: FiniteDimensionalEJAOperator(J,V,M)
         Traceback (most recent call last):
         ...
         TypeError: codomain must be a finite-dimensional Euclidean
         Traceback (most recent call last):
         ...
         TypeError: codomain must be a finite-dimensional Euclidean
@@ -33,16 +33,14 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
     """
 
     def __init__(self, domain_eja, codomain_eja, mat):
     """
 
     def __init__(self, domain_eja, codomain_eja, mat):
-        from mjo.eja.eja_algebra import FiniteDimensionalEuclideanJordanAlgebra
+        from mjo.eja.eja_algebra import FiniteDimensionalEJA
 
         # I guess we should check this, because otherwise you could
         # pass in pretty much anything algebraish.
 
         # I guess we should check this, because otherwise you could
         # pass in pretty much anything algebraish.
-        if not isinstance(domain_eja,
-                          FiniteDimensionalEuclideanJordanAlgebra):
+        if not isinstance(domain_eja, FiniteDimensionalEJA):
             raise TypeError('domain must be a finite-dimensional '
                             'Euclidean Jordan algebra')
             raise TypeError('domain must be a finite-dimensional '
                             'Euclidean Jordan algebra')
-        if not isinstance(codomain_eja,
-                          FiniteDimensionalEuclideanJordanAlgebra):
+        if not isinstance(codomain_eja, FiniteDimensionalEJA):
             raise TypeError('codomain must be a finite-dimensional '
                             'Euclidean Jordan algebra')
 
             raise TypeError('codomain must be a finite-dimensional '
                             'Euclidean Jordan algebra')
 
@@ -63,7 +61,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
         # The Map initializer will set our parent to a homset, which
         # is explicitly NOT what we want, because these ain't algebra
         # homomorphisms.
         # The Map initializer will set our parent to a homset, which
         # is explicitly NOT what we want, because these ain't algebra
         # homomorphisms.
-        super(FiniteDimensionalEuclideanJordanAlgebraOperator,self).__init__(parent)
+        super().__init__(parent)
 
         # Keep a matrix around to do all of the real work. It would
         # be nice if we could use a VectorSpaceMorphism instead, but
 
         # Keep a matrix around to do all of the real work. It would
         # be nice if we could use a VectorSpaceMorphism instead, but
@@ -78,7 +76,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+            sage: from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
             sage: from mjo.eja.eja_algebra import JordanSpinEJA
 
         EXAMPLES::
             sage: from mjo.eja.eja_algebra import JordanSpinEJA
 
         EXAMPLES::
@@ -86,7 +84,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
             sage: J = JordanSpinEJA(3)
             sage: x = J.linear_combination(zip(J.gens(),range(len(J.gens()))))
             sage: id = identity_matrix(J.base_ring(), J.dimension())
             sage: J = JordanSpinEJA(3)
             sage: x = J.linear_combination(zip(J.gens(),range(len(J.gens()))))
             sage: id = identity_matrix(J.base_ring(), J.dimension())
-            sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
+            sage: f = FiniteDimensionalEJAOperator(J,J,id)
             sage: f(x) == x
             True
 
             sage: f(x) == x
             True
 
@@ -100,7 +98,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+            sage: from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
             sage: from mjo.eja.eja_algebra import (
             ....:   JordanSpinEJA,
             ....:   RealSymmetricEJA )
             sage: from mjo.eja.eja_algebra import (
             ....:   JordanSpinEJA,
             ....:   RealSymmetricEJA )
@@ -111,8 +109,8 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
 
             sage: J = RealSymmetricEJA(2)
             sage: id = identity_matrix(J.base_ring(), J.dimension())
 
             sage: J = RealSymmetricEJA(2)
             sage: id = identity_matrix(J.base_ring(), J.dimension())
-            sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
-            sage: g = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
+            sage: f = FiniteDimensionalEJAOperator(J,J,id)
+            sage: g = FiniteDimensionalEJAOperator(J,J,id)
             sage: f + g
             Linear operator between finite-dimensional Euclidean Jordan
             algebras represented by the matrix:
             sage: f + g
             Linear operator between finite-dimensional Euclidean Jordan
             algebras represented by the matrix:
@@ -129,15 +127,15 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
             sage: id1 = identity_matrix(J1.base_ring(), 3)
             sage: J2 = JordanSpinEJA(3)
             sage: id2 = identity_matrix(J2.base_ring(), 3)
             sage: id1 = identity_matrix(J1.base_ring(), 3)
             sage: J2 = JordanSpinEJA(3)
             sage: id2 = identity_matrix(J2.base_ring(), 3)
-            sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,J1,id1)
-            sage: g = FiniteDimensionalEuclideanJordanAlgebraOperator(J2,J2,id2)
+            sage: f = FiniteDimensionalEJAOperator(J1,J1,id1)
+            sage: g = FiniteDimensionalEJAOperator(J2,J2,id2)
             sage: f + g
             Traceback (most recent call last):
             ...
             TypeError: unsupported operand parent(s) for +: ...
 
         """
             sage: f + g
             Traceback (most recent call last):
             ...
             TypeError: unsupported operand parent(s) for +: ...
 
         """
-        return FiniteDimensionalEuclideanJordanAlgebraOperator(
+        return FiniteDimensionalEJAOperator(
                 self.domain(),
                 self.codomain(),
                 self.matrix() + other.matrix())
                 self.domain(),
                 self.codomain(),
                 self.matrix() + other.matrix())
@@ -150,7 +148,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+            sage: from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
             sage: from mjo.eja.eja_algebra import (
             ....:   JordanSpinEJA,
             ....:   HadamardEJA,
             sage: from mjo.eja.eja_algebra import (
             ....:   JordanSpinEJA,
             ....:   HadamardEJA,
@@ -164,12 +162,8 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
             sage: mat1 = matrix(AA, [[1,2,3],
             ....:                    [4,5,6]])
             sage: mat2 = matrix(AA, [[7,8]])
             sage: mat1 = matrix(AA, [[1,2,3],
             ....:                    [4,5,6]])
             sage: mat2 = matrix(AA, [[7,8]])
-            sage: g = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,
-            ....:                                                     J2,
-            ....:                                                     mat1)
-            sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J2,
-            ....:                                                     J3,
-            ....:                                                     mat2)
+            sage: g = FiniteDimensionalEJAOperator(J1, J2, mat1)
+            sage: f = FiniteDimensionalEJAOperator(J2, J3, mat2)
             sage: f*g
             Linear operator between finite-dimensional Euclidean Jordan
             algebras represented by the matrix:
             sage: f*g
             Linear operator between finite-dimensional Euclidean Jordan
             algebras represented by the matrix:
@@ -180,7 +174,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
             Algebraic Real Field
 
         """
             Algebraic Real Field
 
         """
-        return FiniteDimensionalEuclideanJordanAlgebraOperator(
+        return FiniteDimensionalEJAOperator(
           other.domain(),
           self.codomain(),
           self.matrix()*other.matrix())
           other.domain(),
           self.codomain(),
           self.matrix()*other.matrix())
@@ -202,14 +196,14 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+            sage: from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
             sage: from mjo.eja.eja_algebra import RealSymmetricEJA
 
         EXAMPLES::
 
             sage: J = RealSymmetricEJA(2)
             sage: id = identity_matrix(J.base_ring(), J.dimension())
             sage: from mjo.eja.eja_algebra import RealSymmetricEJA
 
         EXAMPLES::
 
             sage: J = RealSymmetricEJA(2)
             sage: id = identity_matrix(J.base_ring(), J.dimension())
-            sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
+            sage: f = FiniteDimensionalEJAOperator(J,J,id)
             sage: ~f
             Linear operator between finite-dimensional Euclidean Jordan
             algebras represented by the matrix:
             sage: ~f
             Linear operator between finite-dimensional Euclidean Jordan
             algebras represented by the matrix:
@@ -220,7 +214,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
             Codomain: Euclidean Jordan algebra of dimension 3 over...
 
         """
             Codomain: Euclidean Jordan algebra of dimension 3 over...
 
         """
-        return FiniteDimensionalEuclideanJordanAlgebraOperator(
+        return FiniteDimensionalEJAOperator(
                 self.codomain(),
                 self.domain(),
                 ~self.matrix())
                 self.codomain(),
                 self.domain(),
                 ~self.matrix())
@@ -237,7 +231,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+            sage: from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
             sage: from mjo.eja.eja_algebra import RealSymmetricEJA
 
         EXAMPLES:
             sage: from mjo.eja.eja_algebra import RealSymmetricEJA
 
         EXAMPLES:
@@ -267,7 +261,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
         """
         try:
             if other in self.codomain().base_ring():
         """
         try:
             if other in self.codomain().base_ring():
-                return FiniteDimensionalEuclideanJordanAlgebraOperator(
+                return FiniteDimensionalEJAOperator(
                     self.domain(),
                     self.codomain(),
                     self.matrix()*other)
                     self.domain(),
                     self.codomain(),
                     self.matrix()*other)
@@ -278,7 +272,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
 
         # This should eventually delegate to _composition_ after performing
         # some sanity checks for us.
 
         # This should eventually delegate to _composition_ after performing
         # some sanity checks for us.
-        mor = super(FiniteDimensionalEuclideanJordanAlgebraOperator,self)
+        mor = super(FiniteDimensionalEJAOperator,self)
         return mor.__mul__(other)
 
 
         return mor.__mul__(other)
 
 
@@ -288,14 +282,14 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+            sage: from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
             sage: from mjo.eja.eja_algebra import RealSymmetricEJA
 
         EXAMPLES::
 
             sage: J = RealSymmetricEJA(2)
             sage: id = identity_matrix(J.base_ring(), J.dimension())
             sage: from mjo.eja.eja_algebra import RealSymmetricEJA
 
         EXAMPLES::
 
             sage: J = RealSymmetricEJA(2)
             sage: id = identity_matrix(J.base_ring(), J.dimension())
-            sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
+            sage: f = FiniteDimensionalEJAOperator(J,J,id)
             sage: -f
             Linear operator between finite-dimensional Euclidean Jordan
             algebras represented by the matrix:
             sage: -f
             Linear operator between finite-dimensional Euclidean Jordan
             algebras represented by the matrix:
@@ -306,7 +300,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
             Codomain: Euclidean Jordan algebra of dimension 3 over...
 
         """
             Codomain: Euclidean Jordan algebra of dimension 3 over...
 
         """
-        return FiniteDimensionalEuclideanJordanAlgebraOperator(
+        return FiniteDimensionalEJAOperator(
                 self.domain(),
                 self.codomain(),
                 -self.matrix())
                 self.domain(),
                 self.codomain(),
                 -self.matrix())
@@ -318,7 +312,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+            sage: from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
             sage: from mjo.eja.eja_algebra import RealSymmetricEJA
 
         TESTS:
             sage: from mjo.eja.eja_algebra import RealSymmetricEJA
 
         TESTS:
@@ -328,7 +322,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
 
             sage: J = RealSymmetricEJA(2)
             sage: id = identity_matrix(J.base_ring(), J.dimension())
 
             sage: J = RealSymmetricEJA(2)
             sage: id = identity_matrix(J.base_ring(), J.dimension())
-            sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
+            sage: f = FiniteDimensionalEJAOperator(J,J,id)
             sage: f^0 + f^1 + f^2
             Linear operator between finite-dimensional Euclidean Jordan
             algebras represented by the matrix:
             sage: f^0 + f^1 + f^2
             Linear operator between finite-dimensional Euclidean Jordan
             algebras represented by the matrix:
@@ -350,7 +344,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
         else:
             mat = self.matrix()**n
 
         else:
             mat = self.matrix()**n
 
-        return FiniteDimensionalEuclideanJordanAlgebraOperator(
+        return FiniteDimensionalEJAOperator(
                  self.domain(),
                  self.codomain(),
                  mat)
                  self.domain(),
                  self.codomain(),
                  mat)
@@ -364,14 +358,14 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+            sage: from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
             sage: from mjo.eja.eja_algebra import JordanSpinEJA
 
         EXAMPLES::
 
             sage: J = JordanSpinEJA(2)
             sage: id = identity_matrix(J.base_ring(), J.dimension())
             sage: from mjo.eja.eja_algebra import JordanSpinEJA
 
         EXAMPLES::
 
             sage: J = JordanSpinEJA(2)
             sage: id = identity_matrix(J.base_ring(), J.dimension())
-            sage: FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
+            sage: FiniteDimensionalEJAOperator(J,J,id)
             Linear operator between finite-dimensional Euclidean Jordan
             algebras represented by the matrix:
             [1 0]
             Linear operator between finite-dimensional Euclidean Jordan
             algebras represented by the matrix:
             [1 0]
@@ -398,14 +392,14 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+            sage: from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
             sage: from mjo.eja.eja_algebra import RealSymmetricEJA
 
         EXAMPLES::
 
             sage: J = RealSymmetricEJA(2)
             sage: id = identity_matrix(J.base_ring(),J.dimension())
             sage: from mjo.eja.eja_algebra import RealSymmetricEJA
 
         EXAMPLES::
 
             sage: J = RealSymmetricEJA(2)
             sage: id = identity_matrix(J.base_ring(),J.dimension())
-            sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
+            sage: f = FiniteDimensionalEJAOperator(J,J,id)
             sage: f - (f*2)
             Linear operator between finite-dimensional Euclidean Jordan
             algebras represented by the matrix:
             sage: f - (f*2)
             Linear operator between finite-dimensional Euclidean Jordan
             algebras represented by the matrix:
@@ -449,7 +443,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+            sage: from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
             sage: from mjo.eja.eja_algebra import (random_eja,
             ....:                                  JordanSpinEJA,
             ....:                                  RealSymmetricEJA)
             sage: from mjo.eja.eja_algebra import (random_eja,
             ....:                                  JordanSpinEJA,
             ....:                                  RealSymmetricEJA)
@@ -462,13 +456,13 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
             sage: M = matrix(R, [ [0, 0],
             ....:                 [0, 0],
             ....:                 [0, 0] ])
             sage: M = matrix(R, [ [0, 0],
             ....:                 [0, 0],
             ....:                 [0, 0] ])
-            sage: L = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,J2,M)
+            sage: L = FiniteDimensionalEJAOperator(J1,J2,M)
             sage: L.is_zero()
             True
             sage: M = matrix(R, [ [0, 0],
             ....:                 [0, 1],
             ....:                 [0, 0] ])
             sage: L.is_zero()
             True
             sage: M = matrix(R, [ [0, 0],
             ....:                 [0, 1],
             ....:                 [0, 0] ])
-            sage: L = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,J2,M)
+            sage: L = FiniteDimensionalEJAOperator(J1,J2,M)
             sage: L.is_zero()
             False
 
             sage: L.is_zero()
             False
 
@@ -591,14 +585,14 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+            sage: from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
             sage: from mjo.eja.eja_algebra import RealSymmetricEJA
 
         EXAMPLES::
 
             sage: J = RealSymmetricEJA(2)
             sage: mat = matrix(J.base_ring(), J.dimension(), range(9))
             sage: from mjo.eja.eja_algebra import RealSymmetricEJA
 
         EXAMPLES::
 
             sage: J = RealSymmetricEJA(2)
             sage: mat = matrix(J.base_ring(), J.dimension(), range(9))
-            sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,mat)
+            sage: f = FiniteDimensionalEJAOperator(J,J,mat)
             sage: f.matrix()
             [0 1 2]
             [3 4 5]
             sage: f.matrix()
             [0 1 2]
             [3 4 5]
@@ -615,7 +609,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
 
         SETUP::
 
 
         SETUP::
 
-            sage: from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
+            sage: from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
             sage: from mjo.eja.eja_algebra import RealSymmetricEJA
 
         EXAMPLES::
             sage: from mjo.eja.eja_algebra import RealSymmetricEJA
 
         EXAMPLES::
@@ -680,7 +674,7 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
             # for the spectral theorem to work.
             us[i] = us[i]/us[i].norm()
             mat = us[i].column()*us[i].row()
             # for the spectral theorem to work.
             us[i] = us[i]/us[i].norm()
             mat = us[i].column()*us[i].row()
-            Pi = FiniteDimensionalEuclideanJordanAlgebraOperator(
+            Pi = FiniteDimensionalEJAOperator(
                    self.domain(),
                    self.codomain(),
                    mat)
                    self.domain(),
                    self.codomain(),
                    mat)
index e7308ea34b9a36aef09a84069a1289e072487ec7..3eee24866216ca84aa8acf2484e07d01d6cad019 100644 (file)
@@ -1,9 +1,9 @@
 from sage.matrix.constructor import matrix
 
 from sage.matrix.constructor import matrix
 
-from mjo.eja.eja_algebra import FiniteDimensionalEuclideanJordanAlgebra
-from mjo.eja.eja_element import FiniteDimensionalEuclideanJordanAlgebraElement
+from mjo.eja.eja_algebra import FiniteDimensionalEJA
+from mjo.eja.eja_element import FiniteDimensionalEJAElement
 
 
-class FiniteDimensionalEuclideanJordanSubalgebraElement(FiniteDimensionalEuclideanJordanAlgebraElement):
+class FiniteDimensionalEJASubalgebraElement(FiniteDimensionalEJAElement):
     """
     SETUP::
 
     """
     SETUP::
 
@@ -83,23 +83,12 @@ class FiniteDimensionalEuclideanJordanSubalgebraElement(FiniteDimensionalEuclide
             True
 
         """
             True
 
         """
-        # As with the _element_constructor_() method on the
-        # algebra... even in a subspace of a subspace, the basis
-        # elements belong to the ambient space. As a result, only one
-        # level of coordinate_vector() is needed, regardless of how
-        # deeply we're nested.
-        W = self.parent().vector_space()
-        V = self.parent().superalgebra().vector_space()
+        return self._superalgebra(self.to_matrix())
 
 
-        # Multiply on the left because basis_matrix() is row-wise.
-        ambient_coords = self.to_vector()*W.basis_matrix()
-        V_coords = V.coordinate_vector(ambient_coords)
-        return self.parent().superalgebra().from_vector(V_coords)
 
 
 
 
 
 
-
-class FiniteDimensionalEuclideanJordanSubalgebra(FiniteDimensionalEuclideanJordanAlgebra):
+class FiniteDimensionalEJASubalgebra(FiniteDimensionalEJA):
     """
     A subalgebra of an EJA with a given basis.
 
     """
     A subalgebra of an EJA with a given basis.
 
@@ -108,7 +97,7 @@ class FiniteDimensionalEuclideanJordanSubalgebra(FiniteDimensionalEuclideanJorda
         sage: from mjo.eja.eja_algebra import (ComplexHermitianEJA,
         ....:                                  JordanSpinEJA,
         ....:                                  RealSymmetricEJA)
         sage: from mjo.eja.eja_algebra import (ComplexHermitianEJA,
         ....:                                  JordanSpinEJA,
         ....:                                  RealSymmetricEJA)
-        sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanSubalgebra
+        sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEJASubalgebra
 
     EXAMPLES:
 
 
     EXAMPLES:
 
@@ -120,11 +109,11 @@ class FiniteDimensionalEuclideanJordanSubalgebra(FiniteDimensionalEuclideanJorda
         ....:                    [0,0] ])
         sage: E22 = matrix(AA, [ [0,0],
         ....:                    [0,1] ])
         ....:                    [0,0] ])
         sage: E22 = matrix(AA, [ [0,0],
         ....:                    [0,1] ])
-        sage: K1 = FiniteDimensionalEuclideanJordanSubalgebra(J, (J(E11),))
+        sage: K1 = FiniteDimensionalEJASubalgebra(J, (J(E11),))
         sage: K1.one().to_matrix()
         [1 0]
         [0 0]
         sage: K1.one().to_matrix()
         [1 0]
         [0 0]
-        sage: K2 = FiniteDimensionalEuclideanJordanSubalgebra(J, (J(E22),))
+        sage: K2 = FiniteDimensionalEJASubalgebra(J, (J(E22),))
         sage: K2.one().to_matrix()
         [0 0]
         [0 1]
         sage: K2.one().to_matrix()
         [0 0]
         [0 1]
@@ -151,12 +140,10 @@ class FiniteDimensionalEuclideanJordanSubalgebra(FiniteDimensionalEuclideanJorda
         1
 
     """
         1
 
     """
-    def __init__(self, superalgebra, basis, category=None, check_axioms=True):
+    def __init__(self, superalgebra, basis, **kwargs):
         self._superalgebra = superalgebra
         V = self._superalgebra.vector_space()
         field = self._superalgebra.base_ring()
         self._superalgebra = superalgebra
         V = self._superalgebra.vector_space()
         field = self._superalgebra.base_ring()
-        if category is None:
-            category = self._superalgebra.category()
 
         # A half-assed attempt to ensure that we don't collide with
         # the superalgebra's prefix (ignoring the fact that there
 
         # A half-assed attempt to ensure that we don't collide with
         # the superalgebra's prefix (ignoring the fact that there
@@ -170,52 +157,20 @@ class FiniteDimensionalEuclideanJordanSubalgebra(FiniteDimensionalEuclideanJorda
         except ValueError:
             prefix = prefixen[0]
 
         except ValueError:
             prefix = prefixen[0]
 
-        # If our superalgebra is a subalgebra of something else, then
-        # these vectors won't have the right coordinates for
-        # V.span_of_basis() unless we use V.from_vector() on them.
-        W = V.span_of_basis( (V.from_vector(b.to_vector()) for b in basis),
-                             check=check_axioms)
-
-        n = len(basis)
-        if check_axioms:
-            # The tables are square if we're verifying that they
-            # are commutative.
-            mult_table = [[W.zero() for j in range(n)] for i in range(n)]
-            ip_table = [ [ self._superalgebra.inner_product(basis[i],basis[j])
-                           for j in range(n) ]
-                         for i in range(n) ]
-        else:
-            mult_table = [[W.zero() for j in range(i+1)] for i in range(n)]
-            ip_table = [ [ self._superalgebra.inner_product(basis[i],basis[j])
-                           for j in range(i+1) ]
-                         for i in range(n) ]
-
-        for i in range(n):
-            for j in range(i+1):
-                product = basis[i]*basis[j]
-                # product.to_vector() might live in a vector subspace
-                # if our parent algebra is already a subalgebra. We
-                # use V.from_vector() to make it "the right size" in
-                # that case.
-                product_vector = V.from_vector(product.to_vector())
-                mult_table[i][j] = W.coordinate_vector(product_vector)
-                if check_axioms:
-                    mult_table[j][i] = mult_table[i][j]
-
+        # The superalgebra constructor expects these to be in original matrix
+        # form, not algebra-element form.
         matrix_basis = tuple( b.to_matrix() for b in basis )
         matrix_basis = tuple( b.to_matrix() for b in basis )
+        def jordan_product(x,y):
+            return (self._superalgebra(x)*self._superalgebra(y)).to_matrix()
 
 
+        def inner_product(x,y):
+            return self._superalgebra(x).inner_product(self._superalgebra(y))
 
 
-        self._vector_space = W
-
-        fdeja = super(FiniteDimensionalEuclideanJordanSubalgebra, self)
-        fdeja.__init__(field,
-                       mult_table,
-                       ip_table,
-                       prefix=prefix,
-                       category=category,
-                       matrix_basis=matrix_basis,
-                       check_field=False,
-                       check_axioms=check_axioms)
+        super().__init__(matrix_basis,
+                         jordan_product,
+                         inner_product,
+                         prefix=prefix,
+                         **kwargs)
 
 
 
 
 
 
@@ -228,7 +183,7 @@ class FiniteDimensionalEuclideanJordanSubalgebra(FiniteDimensionalEuclideanJorda
         SETUP::
 
             sage: from mjo.eja.eja_algebra import RealSymmetricEJA
         SETUP::
 
             sage: from mjo.eja.eja_algebra import RealSymmetricEJA
-            sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanSubalgebra
+            sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEJASubalgebra
 
         EXAMPLES::
 
 
         EXAMPLES::
 
@@ -238,7 +193,7 @@ class FiniteDimensionalEuclideanJordanSubalgebra(FiniteDimensionalEuclideanJorda
             ....:                  [1,0,0] ])
             sage: x = J(X)
             sage: basis = ( x, x^2 ) # x^2 is the identity matrix
             ....:                  [1,0,0] ])
             sage: x = J(X)
             sage: basis = ( x, x^2 ) # x^2 is the identity matrix
-            sage: K = FiniteDimensionalEuclideanJordanSubalgebra(J, basis)
+            sage: K = FiniteDimensionalEJASubalgebra(J, basis, orthonormalize=False)
             sage: K(J.one())
             f1
             sage: K(J.one() + x)
             sage: K(J.one())
             f1
             sage: K(J.one() + x)
@@ -247,23 +202,10 @@ class FiniteDimensionalEuclideanJordanSubalgebra(FiniteDimensionalEuclideanJorda
         ::
 
         """
         ::
 
         """
-        if elt not in self.superalgebra():
-            raise ValueError("not an element of this subalgebra")
-
-        # The extra hackery is because foo.to_vector() might not live
-        # in foo.parent().vector_space()! Subspaces of subspaces still
-        # have user bases in the ambient space, though, so only one
-        # level of coordinate_vector() is needed. In other words, if V
-        # is itself a subspace, the basis elements for W will be of
-        # the same length as the basis elements for V -- namely
-        # whatever the dimension of the ambient (parent of V?) space is.
-        V = self.superalgebra().vector_space()
-        W = self.vector_space()
-
-        # Multiply on the left because basis_matrix() is row-wise.
-        ambient_coords = elt.to_vector()*V.basis_matrix()
-        W_coords = W.coordinate_vector(ambient_coords)
-        return self.from_vector(W_coords)
+        if elt in self.superalgebra():
+            return super()._element_constructor_(elt.to_matrix())
+        else:
+            return super()._element_constructor_(elt)
 
 
 
 
 
 
@@ -286,38 +228,4 @@ class FiniteDimensionalEuclideanJordanSubalgebra(FiniteDimensionalEuclideanJorda
         return self._superalgebra
 
 
         return self._superalgebra
 
 
-    def vector_space(self):
-        """
-        SETUP::
-
-            sage: from mjo.eja.eja_algebra import RealSymmetricEJA
-            sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanSubalgebra
-
-        EXAMPLES::
-
-            sage: J = RealSymmetricEJA(3)
-            sage: E11 = matrix(ZZ, [ [1,0,0],
-            ....:                    [0,0,0],
-            ....:                    [0,0,0] ])
-            sage: E22 = matrix(ZZ, [ [0,0,0],
-            ....:                    [0,1,0],
-            ....:                    [0,0,0] ])
-            sage: b1 = J(E11)
-            sage: b2 = J(E22)
-            sage: basis = (b1, b2)
-            sage: K = FiniteDimensionalEuclideanJordanSubalgebra(J,basis)
-            sage: K.vector_space()
-            Vector space of degree 6 and dimension 2 over...
-            User basis matrix:
-            [1 0 0 0 0 0]
-            [0 0 1 0 0 0]
-            sage: b1.to_vector()
-            (1, 0, 0, 0, 0, 0)
-            sage: b2.to_vector()
-            (0, 0, 1, 0, 0, 0)
-
-        """
-        return self._vector_space
-
-
-    Element = FiniteDimensionalEuclideanJordanSubalgebraElement
+    Element = FiniteDimensionalEJASubalgebraElement