]> gitweb.michael.orlitzky.com - sage.d.git/commitdiff
WIP: switch away from the algebra base class and use CombinatorialFreeModule.
authorMichael Orlitzky <michael@orlitzky.com>
Tue, 30 Jul 2019 22:17:16 +0000 (18:17 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Tue, 30 Jul 2019 22:17:16 +0000 (18:17 -0400)
mjo/eja/eja_algebra.py
mjo/eja/eja_element.py
mjo/eja/eja_operator.py
mjo/eja/eja_subalgebra.py

index 362b03a6695a00061034cb9168ba76021a9e2daf..5e9c07c01be4bb5ac13644c5335a8b45304c6b7e 100644 (file)
@@ -5,9 +5,10 @@ are used in optimization, and have some additional nice methods beyond
 what can be supported in a general Jordan Algebra.
 """
 
-from sage.algebras.finite_dimensional_algebras.finite_dimensional_algebra import FiniteDimensionalAlgebra
+#from sage.algebras.finite_dimensional_algebras.finite_dimensional_algebra import FiniteDimensionalAlgebra
 from sage.algebras.quatalg.quaternion_algebra import QuaternionAlgebra
 from sage.categories.finite_dimensional_algebras_with_basis import FiniteDimensionalAlgebrasWithBasis
+from sage.combinat.free_module import CombinatorialFreeModule
 from sage.matrix.constructor import matrix
 from sage.misc.cachefunc import cached_method
 from sage.misc.prandom import choice
@@ -20,50 +21,14 @@ from sage.structure.element import is_Matrix
 from sage.structure.category_object import normalize_names
 
 from mjo.eja.eja_element import FiniteDimensionalEuclideanJordanAlgebraElement
-from mjo.eja.eja_utils import _vec2mat, _mat2vec
-
-class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
-    @staticmethod
-    def __classcall_private__(cls,
-                              field,
-                              mult_table,
-                              rank,
-                              names='e',
-                              assume_associative=False,
-                              category=None,
-                              natural_basis=None):
-        n = len(mult_table)
-        mult_table = [b.base_extend(field) for b in mult_table]
-        for b in mult_table:
-            b.set_immutable()
-            if not (is_Matrix(b) and b.dimensions() == (n, n)):
-                raise ValueError("input is not a multiplication table")
-        mult_table = tuple(mult_table)
-
-        cat = FiniteDimensionalAlgebrasWithBasis(field)
-        cat.or_subcategory(category)
-        if assume_associative:
-            cat = cat.Associative()
-
-        names = normalize_names(n, names)
-
-        fda = super(FiniteDimensionalEuclideanJordanAlgebra, cls)
-        return fda.__classcall__(cls,
-                                 field,
-                                 mult_table,
-                                 rank,
-                                 assume_associative=assume_associative,
-                                 names=names,
-                                 category=cat,
-                                 natural_basis=natural_basis)
-
+from mjo.eja.eja_utils import _mat2vec
 
+class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
     def __init__(self,
                  field,
                  mult_table,
                  rank,
-                 names='e',
-                 assume_associative=False,
+                 prefix='e',
                  category=None,
                  natural_basis=None):
         """
@@ -86,11 +51,14 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
         self._rank = rank
         self._natural_basis = natural_basis
         self._multiplication_table = mult_table
+        if category is None:
+            category = FiniteDimensionalAlgebrasWithBasis(field).Unital()
         fda = super(FiniteDimensionalEuclideanJordanAlgebra, self)
         fda.__init__(field,
-                     mult_table,
-                     names=names,
+                     range(len(mult_table)),
+                     prefix=prefix,
                      category=category)
+        self.print_options(bracket='')
 
 
     def _repr_(self):
@@ -111,9 +79,15 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
             Euclidean Jordan algebra of degree 3 over Real Double Field
 
         """
+        # TODO: change this to say "dimension" and fix all the tests.
         fmt = "Euclidean Jordan algebra of degree {} over {}"
-        return fmt.format(self.degree(), self.base_ring())
+        return fmt.format(self.dimension(), self.base_ring())
 
+    def product_on_basis(self, i, j):
+        ei = self.basis()[i]
+        ej = self.basis()[j]
+        Lei = self._multiplication_table[i]
+        return self.from_vector(Lei*ej.to_vector())
 
     def _a_regular_element(self):
         """
@@ -153,7 +127,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
         """
         z = self._a_regular_element()
         V = self.vector_space()
-        V1 = V.span_of_basis( (z**k).vector() for k in range(self.rank()) )
+        V1 = V.span_of_basis( (z**k).to_vector() for k in range(self.rank()) )
         b =  (V1.basis() + V1.complement().basis())
         return V.span_of_basis(b)
 
@@ -205,11 +179,12 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
         n = self.dimension()
 
         # Construct a new algebra over a multivariate polynomial ring...
-        names = ['X' + str(i) for i in range(1,n+1)]
+        names = tuple('X' + str(i) for i in range(1,n+1))
         R = PolynomialRing(self.base_ring(), names)
-        J = FiniteDimensionalEuclideanJordanAlgebra(R,
-                                                    self._multiplication_table,
-                                                    r)
+        J = FiniteDimensionalEuclideanJordanAlgebra(
+              R,
+              tuple(self._multiplication_table),
+              r)
 
         idmat = matrix.identity(J.base_ring(), n)
 
@@ -235,13 +210,13 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
 
         # Handle the zeroth power separately, because computing
         # the unit element in J is mathematically suspect.
-        x0 = W.coordinates(self.one().vector())
-        l1  = [ matrix.column(x0) ]
-        l1 += [ matrix.column(W.coordinates((x**k).vector()))
+        x0 = W.coordinate_vector(self.one().to_vector())
+        l1  = [ x0.column() ]
+        l1 += [ W.coordinate_vector((x**k).to_vector()).column()
                 for k in range(1,r) ]
         l2 = [idmat.column(k-1).column() for k in range(r+1, n+1)]
         A_of_x = matrix.block(R, 1, n, (l1 + l2))
-        xr = W.coordinates((x**r).vector())
+        xr = W.coordinate_vector((x**r).to_vector())
         return (A_of_x, x, xr, A_of_x.det())
 
 
@@ -271,7 +246,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
             sage: J = JordanSpinEJA(3)
             sage: p = J.characteristic_polynomial(); p
             X1^2 - X2^2 - X3^2 + (-2*t)*X1 + t^2
-            sage: xvec = J.one().vector()
+            sage: xvec = J.one().to_vector()
             sage: p(*xvec)
             t^2 - 2*t + 1
 
@@ -359,7 +334,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
 
             sage: J = RealSymmetricEJA(2)
             sage: J.basis()
-            Family (e0, e1, e2)
+            Finite family {0: e0, 1: e1, 2: e2}
             sage: J.natural_basis()
             (
             [1 0]  [0 1]  [0 0]
@@ -370,7 +345,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
 
             sage: J = JordanSpinEJA(2)
             sage: J.basis()
-            Family (e0, e1)
+            Finite family {0: e0, 1: e1}
             sage: J.natural_basis()
             (
             [1]  [0]
@@ -379,7 +354,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
 
         """
         if self._natural_basis is None:
-            return tuple( b.vector().column() for b in self.basis() )
+            return tuple( b.to_vector().column() for b in self.basis() )
         else:
             return self._natural_basis
 
@@ -442,7 +417,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
 
         # Now if there's an identity element in the algebra, this should work.
         coeffs = A.solve_right(b)
-        return self.linear_combination(zip(coeffs,self.gens()))
+        return self.linear_combination(zip(self.gens(), coeffs))
 
 
     def rank(self):
@@ -520,7 +495,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
             Vector space of dimension 3 over Rational Field
 
         """
-        return self.zero().vector().parent().ambient_vector_space()
+        return self.zero().to_vector().parent().ambient_vector_space()
 
 
     Element = FiniteDimensionalEuclideanJordanAlgebraElement
@@ -559,18 +534,17 @@ class RealCartesianProductEJA(FiniteDimensionalEuclideanJordanAlgebra):
         e2
 
     """
-    @staticmethod
-    def __classcall_private__(cls, n, field=QQ):
-        # The FiniteDimensionalAlgebra constructor takes a list of
-        # matrices, the ith representing right multiplication by the ith
-        # basis element in the vector space. So if e_1 = (1,0,0), then
-        # right (Hadamard) multiplication of x by e_1 picks out the first
+    def __init__(self, n, field=QQ):
+        # The superclass constructor takes a list of matrices, the ith
+        # representing right multiplication by the ith basis element
+        # in the vector space. So if e_1 = (1,0,0), then right
+        # (Hadamard) multiplication of x by e_1 picks out the first
         # component of x; and likewise for the ith basis element e_i.
         Qs = [ matrix(field, n, n, lambda k,j: 1*(k == j == i))
                for i in xrange(n) ]
 
-        fdeja = super(RealCartesianProductEJA, cls)
-        return fdeja.__classcall_private__(cls, field, Qs, rank=n)
+        fdeja = super(RealCartesianProductEJA, self)
+        return fdeja.__init__(field, Qs, rank=n)
 
     def inner_product(self, x, y):
         return _usual_ip(x,y)
@@ -755,30 +729,21 @@ def _multiplication_table_from_matrix_basis(basis):
     dimension = basis[0].nrows()
 
     V = VectorSpace(field, dimension**2)
-    W = V.span( _mat2vec(s) for s in basis )
-
-    # Taking the span above reorders our basis (thanks, jerk!) so we
-    # need to put our "matrix basis" in the same order as the
-    # (reordered) vector basis.
-    S = tuple( _vec2mat(b) for b in W.basis() )
+    W = V.span_of_basis( _mat2vec(s) for s in basis )
 
     Qs = []
-    for s in S:
+    for s in basis:
         # Brute force the multiplication-by-s matrix by looping
         # through all elements of the basis and doing the computation
-        # to find out what the corresponding row should be. BEWARE:
-        # these multiplication tables won't be symmetric! It therefore
-        # becomes REALLY IMPORTANT that the underlying algebra
-        # constructor uses ROW vectors and not COLUMN vectors. That's
-        # why we're computing rows here and not columns.
-        Q_rows = []
-        for t in S:
-            this_row = _mat2vec((s*t + t*s)/2)
-            Q_rows.append(W.coordinates(this_row))
-        Q = matrix(field, W.dimension(), Q_rows)
+        # to find out what the corresponding row should be.
+        Q_cols = []
+        for t in basis:
+            this_col = _mat2vec((s*t + t*s)/2)
+            Q_cols.append(W.coordinates(this_col))
+        Q = matrix.column(field, W.dimension(), Q_cols)
         Qs.append(Q)
 
-    return (Qs, S)
+    return Qs
 
 
 def _embed_complex_matrix(M):
@@ -1009,7 +974,7 @@ def _unembed_quaternion_matrix(M):
 
 # The usual inner product on R^n.
 def _usual_ip(x,y):
-    return x.vector().inner_product(y.vector())
+    return x.to_vector().inner_product(y.to_vector())
 
 # The inner product used for the real symmetric simple EJA.
 # We keep it as a separate function because e.g. the complex
@@ -1068,17 +1033,15 @@ class RealSymmetricEJA(FiniteDimensionalEuclideanJordanAlgebra):
         True
 
     """
-    @staticmethod
-    def __classcall_private__(cls, n, field=QQ):
+    def __init__(self, n, field=QQ):
         S = _real_symmetric_basis(n, field=field)
-        (Qs, T) = _multiplication_table_from_matrix_basis(S)
+        Qs = _multiplication_table_from_matrix_basis(S)
 
-        fdeja = super(RealSymmetricEJA, cls)
-        return fdeja.__classcall_private__(cls,
-                                           field,
-                                           Qs,
-                                           rank=n,
-                                           natural_basis=T)
+        fdeja = super(RealSymmetricEJA, self)
+        return fdeja.__init__(field,
+                              Qs,
+                              rank=n,
+                              natural_basis=S)
 
     def inner_product(self, x, y):
         return _matrix_ip(x,y)
@@ -1122,17 +1085,16 @@ class ComplexHermitianEJA(FiniteDimensionalEuclideanJordanAlgebra):
         True
 
     """
-    @staticmethod
-    def __classcall_private__(cls, n, field=QQ):
+    def __init__(self, n, field=QQ):
         S = _complex_hermitian_basis(n)
-        (Qs, T) = _multiplication_table_from_matrix_basis(S)
+        Qs = _multiplication_table_from_matrix_basis(S)
+
+        fdeja = super(ComplexHermitianEJA, self)
+        return fdeja.__init__(field,
+                              Qs,
+                              rank=n,
+                              natural_basis=S)
 
-        fdeja = super(ComplexHermitianEJA, cls)
-        return fdeja.__classcall_private__(cls,
-                                           field,
-                                           Qs,
-                                           rank=n,
-                                           natural_basis=T)
 
     def inner_product(self, x, y):
         # Since a+bi on the diagonal is represented as
@@ -1183,17 +1145,15 @@ class QuaternionHermitianEJA(FiniteDimensionalEuclideanJordanAlgebra):
         True
 
     """
-    @staticmethod
-    def __classcall_private__(cls, n, field=QQ):
+    def __init__(self, n, field=QQ):
         S = _quaternion_hermitian_basis(n)
-        (Qs, T) = _multiplication_table_from_matrix_basis(S)
+        Qs = _multiplication_table_from_matrix_basis(S)
 
-        fdeja = super(QuaternionHermitianEJA, cls)
-        return fdeja.__classcall_private__(cls,
-                                           field,
-                                           Qs,
-                                           rank=n,
-                                           natural_basis=T)
+        fdeja = super(QuaternionHermitianEJA, self)
+        return fdeja.__init__(field,
+                              Qs,
+                              rank=n,
+                              natural_basis=S)
 
     def inner_product(self, x, y):
         # Since a+bi+cj+dk on the diagonal is represented as
@@ -1241,8 +1201,7 @@ class JordanSpinEJA(FiniteDimensionalEuclideanJordanAlgebra):
         0
 
     """
-    @staticmethod
-    def __classcall_private__(cls, n, field=QQ):
+    def __init__(self, n, field=QQ):
         Qs = []
         id_matrix = matrix.identity(field, n)
         for i in xrange(n):
@@ -1259,8 +1218,8 @@ class JordanSpinEJA(FiniteDimensionalEuclideanJordanAlgebra):
         # The rank of the spin algebra is two, unless we're in a
         # one-dimensional ambient space (because the rank is bounded by
         # the ambient dimension).
-        fdeja = super(JordanSpinEJA, cls)
-        return fdeja.__classcall_private__(cls, field, Qs, rank=min(n,2))
+        fdeja = super(JordanSpinEJA, self)
+        return fdeja.__init__(field, Qs, rank=min(n,2))
 
     def inner_product(self, x, y):
         return _usual_ip(x,y)
index 00a15a1c56897172f57aeec2d43a391f3b367a45..107603ce712ecf79d6de89a2e4fd573f17738798 100644 (file)
@@ -1,6 +1,6 @@
-from sage.algebras.finite_dimensional_algebras.finite_dimensional_algebra_element import FiniteDimensionalAlgebraElement
 from sage.matrix.constructor import matrix
 from sage.modules.free_module import VectorSpace
+from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement
 
 # TODO: make this unnecessary somehow.
 from sage.misc.lazy_import import lazy_import
@@ -10,7 +10,7 @@ lazy_import('mjo.eja.eja_subalgebra',
 from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator
 from mjo.eja.eja_utils import _mat2vec
 
-class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraElement):
+class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement):
     """
     An element of a Euclidean Jordan algebra.
     """
@@ -25,7 +25,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
                       dir(self.__class__) )
 
 
-    def __init__(self, A, elt=None):
+    def __init__(self, A, elt):
         """
 
         SETUP::
@@ -60,7 +60,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
             sage: set_random_seed()
             sage: J = random_eja()
             sage: v = J.vector_space().random_element()
-            sage: J(v).vector() == v
+            sage: J(v).to_vector() == v
             True
 
         """
@@ -75,8 +75,9 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
         # already fits into the algebra, but also happens to live
         # in the parent's "natural ambient space" (this happens with
         # vectors in R^n).
+        ifme = super(FiniteDimensionalEuclideanJordanAlgebraElement, self)
         try:
-            FiniteDimensionalAlgebraElement.__init__(self, A, elt)
+            ifme.__init__(A, elt)
         except ValueError:
             natural_basis = A.natural_basis()
             if elt in natural_basis[0].matrix_space():
@@ -85,8 +86,9 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
                 # natural-basis coordinates ourselves.
                 V = VectorSpace(elt.base_ring(), elt.nrows()**2)
                 W = V.span( _mat2vec(s) for s in natural_basis )
-                coords =  W.coordinates(_mat2vec(elt))
-                FiniteDimensionalAlgebraElement.__init__(self, A, coords)
+                coords =  W.coordinate_vector(_mat2vec(elt))
+                ifme.__init__(A, coords)
+
 
     def __pow__(self, n):
         """
@@ -228,7 +230,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
 
         """
         p = self.parent().characteristic_polynomial()
-        return p(*self.vector())
+        return p(*self.to_vector())
 
 
     def inner_product(self, other):
@@ -437,7 +439,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
         # -1 to ensure that _charpoly_coeff(0) is really what
         # appears in front of t^{0} in the charpoly. However,
         # we want (-1)^r times THAT for the determinant.
-        return ((-1)**r)*p(*self.vector())
+        return ((-1)**r)*p(*self.to_vector())
 
 
     def inverse(self):
@@ -465,7 +467,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
             sage: x = J.random_element()
             sage: while not x.is_invertible():
             ....:     x = J.random_element()
-            sage: x_vec = x.vector()
+            sage: x_vec = x.to_vector()
             sage: x0 = x_vec[0]
             sage: x_bar = x_vec[1:]
             sage: coeff = ~(x0^2 - x_bar.inner_product(x_bar))
@@ -765,8 +767,8 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
             sage: y = J.random_element()
             sage: while y == y.coefficient(0)*J.one():
             ....:     y = J.random_element()
-            sage: y0 = y.vector()[0]
-            sage: y_bar = y.vector()[1:]
+            sage: y0 = y.to_vector()[0]
+            sage: y_bar = y.to_vector()[1:]
             sage: actual = y.minimal_polynomial()
             sage: t = PolynomialRing(J.base_ring(),'t').gen(0)
             sage: expected = t^2 - 2*y0*t + (y0^2 - norm(y_bar)^2)
@@ -783,7 +785,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
 
         """
         A = self.subalgebra_generated_by()
-        return A(self).operator().minimal_polynomial()
+        return A.element_class(A,self).operator().minimal_polynomial()
 
 
 
@@ -837,7 +839,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
         """
         B = self.parent().natural_basis()
         W = B[0].matrix_space()
-        return W.linear_combination(zip(self.vector(), B))
+        return W.linear_combination(zip(B,self.to_vector()))
 
 
     def operator(self):
@@ -862,11 +864,10 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
 
         """
         P = self.parent()
-        fda_elt = FiniteDimensionalAlgebraElement(P, self)
         return FiniteDimensionalEuclideanJordanAlgebraOperator(
                  P,
                  P,
-                 fda_elt.matrix().transpose() )
+                 self.to_matrix() )
 
 
     def quadratic_representation(self, other=None):
@@ -887,7 +888,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
             sage: n = ZZ.random_element(1,10)
             sage: J = JordanSpinEJA(n)
             sage: x = J.random_element()
-            sage: x_vec = x.vector()
+            sage: x_vec = x.to_vector()
             sage: x0 = x_vec[0]
             sage: x_bar = x_vec[1:]
             sage: A = matrix(QQ, 1, [x_vec.inner_product(x_vec)])
@@ -1070,7 +1071,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
         # Our FiniteDimensionalAlgebraElement superclass uses rows.
         u_next = u**(s+1)
         A = u_next.operator().matrix()
-        c = J(A.solve_right(u_next.vector()))
+        c = J(A.solve_right(u_next.to_vector()))
 
         # Now c is the idempotent we want, but it still lives in the subalgebra.
         return c.superalgebra_element()
@@ -1116,7 +1117,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(FiniteDimensionalAlgebraEle
         # -1 to ensure that _charpoly_coeff(r-1) is really what
         # appears in front of t^{r-1} in the charpoly. However,
         # we want the negative of THAT for the trace.
-        return -p(*self.vector())
+        return -p(*self.to_vector())
 
 
     def trace_inner_product(self, other):
index 1f10048812301baa8c13c4d49f5e4475a9cc04d7..8973a951aa80f2275c527fd67d78b30259971866 100644 (file)
@@ -46,14 +46,14 @@ class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
         EXAMPLES::
 
             sage: J = JordanSpinEJA(3)
-            sage: x = J.linear_combination(zip(range(len(J.gens())), J.gens()))
+            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(x) == x
             True
 
         """
-        return self.codomain()(self.matrix()*x.vector())
+        return self.codomain().from_vector(self.matrix()*x.to_vector())
 
 
     def _add_(self, other):
index 5ac0a77c7a9ab27929f4c3e1d73238d93e1ccd1b..a774b985ff54a2ceeb01468b5887849a22ef2d65 100644 (file)
 from sage.matrix.constructor import matrix
-from sage.structure.category_object import normalize_names
 
 from mjo.eja.eja_algebra import FiniteDimensionalEuclideanJordanAlgebra
 from mjo.eja.eja_element import FiniteDimensionalEuclideanJordanAlgebraElement
 
 
-class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclideanJordanAlgebra):
+class FiniteDimensionalEuclideanJordanElementSubalgebraElement(FiniteDimensionalEuclideanJordanAlgebraElement):
     """
-    The subalgebra of an EJA generated by a single element.
-
     SETUP::
 
-        sage: from mjo.eja.eja_algebra import FiniteDimensionalEuclideanJordanAlgebra
+        sage: from mjo.eja.eja_algebra import random_eja
+
+    TESTS::
+
+    The natural representation of an element in the subalgebra is
+    the same as its natural representation in the superalgebra::
+
+        sage: set_random_seed()
+        sage: A = random_eja().random_element().subalgebra_generated_by()
+        sage: y = A.random_element()
+        sage: actual = y.natural_representation()
+        sage: expected = y.superalgebra_element().natural_representation()
+        sage: actual == expected
+        True
+
+    """
+    def __init__(self, A, elt):
+        """
+        SETUP::
+
+            sage: from mjo.eja.eja_algebra import RealSymmetricEJA
+            sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
+
+        EXAMPLES::
+
+            sage: J = RealSymmetricEJA(3)
+            sage: x = sum( i*J.gens()[i] for i in range(6) )
+            sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x)
+            sage: [ K.element_class(K,x^k) for k in range(J.rank()) ]
+            [f0, f1, f2]
+
+        ::
+
+        """
+        if elt in A.superalgebra():
+            # Try to convert a parent algebra element into a
+            # subalgebra element...
+            try:
+                coords = A.vector_space().coordinate_vector(elt.to_vector())
+                elt = A.from_vector(coords).monomial_coefficients()
+            except AttributeError:
+                # Catches a missing method in elt.to_vector()
+                pass
+
+        s = super(FiniteDimensionalEuclideanJordanElementSubalgebraElement,
+                  self)
+
+        s.__init__(A, elt)
+
+
+    def superalgebra_element(self):
+        """
+        Return the object in our algebra's superalgebra that corresponds
+        to myself.
+
+        SETUP::
+
+            sage: from mjo.eja.eja_algebra import (RealSymmetricEJA,
+            ....:                                  random_eja)
 
-    TESTS:
+        EXAMPLES::
+
+            sage: J = RealSymmetricEJA(3)
+            sage: x = sum(J.gens())
+            sage: x
+            e0 + e1 + e2 + e3 + e4 + e5
+            sage: A = x.subalgebra_generated_by()
+            sage: A.element_class(A,x)
+            f1
+            sage: A.element_class(A,x).superalgebra_element()
+            e0 + e1 + e2 + e3 + e4 + e5
+
+        TESTS:
+
+        We can convert back and forth faithfully::
+
+            sage: set_random_seed()
+            sage: J = random_eja()
+            sage: x = J.random_element()
+            sage: A = x.subalgebra_generated_by()
+            sage: A.element_class(A,x).superalgebra_element() == x
+            True
+            sage: y = A.random_element()
+            sage: A.element_class(A,y.superalgebra_element()) == y
+            True
+
+        """
+        return self.parent().superalgebra().linear_combination(
+          zip(self.parent()._superalgebra_basis, self.to_vector()) )
 
-    Ensure that non-clashing names are chosen::
 
-        sage: m1 = matrix.identity(QQ,2)
-        sage: m2 = matrix(QQ, [[0,1],
-        ....:                  [1,0]])
-        sage: J = FiniteDimensionalEuclideanJordanAlgebra(QQ,
-        ....:                                             [m1,m2],
-        ....:                                             2,
-        ....:                                             names='f')
-        sage: J.variable_names()
-        ('f0', 'f1')
-        sage: A = sum(J.gens()).subalgebra_generated_by()
-        sage: A.variable_names()
-        ('g0', 'g1')
 
+
+class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclideanJordanAlgebra):
+    """
+    The subalgebra of an EJA generated by a single element.
     """
-    @staticmethod
-    def __classcall_private__(cls, elt):
+    def __init__(self, elt):
         superalgebra = elt.parent()
 
         # First compute the vector subspace spanned by the powers of
         # the given element.
         V = superalgebra.vector_space()
         superalgebra_basis = [superalgebra.one()]
-        basis_vectors = [superalgebra.one().vector()]
+        basis_vectors = [superalgebra.one().to_vector()]
         W = V.span_of_basis(basis_vectors)
         for exponent in range(1, V.dimension()):
             new_power = elt**exponent
-            basis_vectors.append( new_power.vector() )
+            basis_vectors.append( new_power.to_vector() )
             try:
                 W = V.span_of_basis(basis_vectors)
                 superalgebra_basis.append( new_power )
@@ -58,7 +131,7 @@ class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclide
         # Now figure out the entries of the right-multiplication
         # matrix for the successive basis elements b0, b1,... of
         # that subspace.
-        F = superalgebra.base_ring()
+        field = superalgebra.base_ring()
         mult_table = []
         for b_right in superalgebra_basis:
                 b_right_rows = []
@@ -73,15 +146,18 @@ class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclide
                     # Multiply in the original EJA, but then get the
                     # coordinates from the subalgebra in terms of its
                     # basis.
-                    this_row = W.coordinates((b_left*b_right).vector())
+                    this_row = W.coordinates((b_left*b_right).to_vector())
                     b_right_rows.append(this_row)
-                b_right_matrix = matrix(F, b_right_rows)
+                b_right_matrix = matrix(field, b_right_rows)
                 mult_table.append(b_right_matrix)
 
         for m in mult_table:
             m.set_immutable()
         mult_table = tuple(mult_table)
 
+        # TODO: We'll have to redo this and make it unique again...
+        prefix = 'f'
+
         # The rank is the highest possible degree of a minimal
         # polynomial, and is bounded above by the dimension. We know
         # in this case that there's an element whose minimal
@@ -90,60 +166,23 @@ class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclide
         # its rank too.
         rank = W.dimension()
 
-        # EJAs are power-associative, and this algebra is nothin but
-        # powers.
-        assume_associative=True
-
-        # Figure out a non-conflicting set of names to use.
-        valid_names = ['f','g','h','a','b','c','d']
-        name_idx = 0
-        names = normalize_names(W.dimension(), valid_names[0])
-        # This loops so long as the list of collisions is nonempty.
-        # Just crash if we run out of names without finding a set that
-        # don't conflict with the parent algebra.
-        while [y for y in names if y in superalgebra.variable_names()]:
-            name_idx += 1
-            names = normalize_names(W.dimension(), valid_names[name_idx])
-
-        cat = superalgebra.category().Associative()
+        category = superalgebra.category().Associative()
         natural_basis = tuple( b.natural_representation()
                                for b in superalgebra_basis )
 
-        fdeja = super(FiniteDimensionalEuclideanJordanElementSubalgebra, cls)
-        return fdeja.__classcall__(cls,
-                                   F,
-                                   mult_table,
-                                   rank,
-                                   superalgebra_basis,
-                                   W,
-                                   assume_associative=assume_associative,
-                                   names=names,
-                                   category=cat,
-                                   natural_basis=natural_basis)
-
-    def __init__(self,
-                 field,
-                 mult_table,
-                 rank,
-                 superalgebra_basis,
-                 vector_space,
-                 assume_associative=True,
-                 names='f',
-                 category=None,
-                 natural_basis=None):
-
-        self._superalgebra = superalgebra_basis[0].parent()
-        self._vector_space = vector_space
+        self._superalgebra = superalgebra
+        self._vector_space = W
         self._superalgebra_basis = superalgebra_basis
 
+
         fdeja = super(FiniteDimensionalEuclideanJordanElementSubalgebra, self)
-        fdeja.__init__(field,
-                       mult_table,
-                       rank,
-                       assume_associative=assume_associative,
-                       names=names,
-                       category=category,
-                       natural_basis=natural_basis)
+        return fdeja.__init__(field,
+                              mult_table,
+                              rank,
+                              prefix=prefix,
+                              category=category,
+                              natural_basis=natural_basis)
+
 
 
     def superalgebra(self):
@@ -171,106 +210,15 @@ class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclide
             [ 1  0  0  1  0  1]
             [ 0  1  2  3  4  5]
             [ 5 11 14 26 34 45]
-            sage: (x^0).vector()
+            sage: (x^0).to_vector()
             (1, 0, 0, 1, 0, 1)
-            sage: (x^1).vector()
+            sage: (x^1).to_vector()
             (0, 1, 2, 3, 4, 5)
-            sage: (x^2).vector()
+            sage: (x^2).to_vector()
             (5, 11, 14, 26, 34, 45)
 
         """
         return self._vector_space
 
 
-    class Element(FiniteDimensionalEuclideanJordanAlgebraElement):
-        """
-
-        SETUP::
-
-            sage: from mjo.eja.eja_algebra import random_eja
-
-        TESTS::
-
-        The natural representation of an element in the subalgebra is
-        the same as its natural representation in the superalgebra::
-
-            sage: set_random_seed()
-            sage: A = random_eja().random_element().subalgebra_generated_by()
-            sage: y = A.random_element()
-            sage: actual = y.natural_representation()
-            sage: expected = y.superalgebra_element().natural_representation()
-            sage: actual == expected
-            True
-
-        """
-        def __init__(self, A, elt=None):
-            """
-            SETUP::
-
-                sage: from mjo.eja.eja_algebra import RealSymmetricEJA
-                sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra
-
-            EXAMPLES::
-
-                sage: J = RealSymmetricEJA(3)
-                sage: x = sum( i*J.gens()[i] for i in range(6) )
-                sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x)
-                sage: [ K(x^k) for k in range(J.rank()) ]
-                [f0, f1, f2]
-
-            ::
-
-            """
-            if elt in A.superalgebra():
-                    # Try to convert a parent algebra element into a
-                    # subalgebra element...
-                try:
-                    coords = A.vector_space().coordinates(elt.vector())
-                    elt = A(coords)
-                except AttributeError:
-                    # Catches a missing method in elt.vector()
-                    pass
-
-            FiniteDimensionalEuclideanJordanAlgebraElement.__init__(self,
-                                                                    A,
-                                                                    elt)
-
-        def superalgebra_element(self):
-            """
-            Return the object in our algebra's superalgebra that corresponds
-            to myself.
-
-            SETUP::
-
-                sage: from mjo.eja.eja_algebra import (RealSymmetricEJA,
-                ....:                                  random_eja)
-
-            EXAMPLES::
-
-                sage: J = RealSymmetricEJA(3)
-                sage: x = sum(J.gens())
-                sage: x
-                e0 + e1 + e2 + e3 + e4 + e5
-                sage: A = x.subalgebra_generated_by()
-                sage: A(x)
-                f1
-                sage: A(x).superalgebra_element()
-                e0 + e1 + e2 + e3 + e4 + e5
-
-            TESTS:
-
-            We can convert back and forth faithfully::
-
-                sage: set_random_seed()
-                sage: J = random_eja()
-                sage: x = J.random_element()
-                sage: A = x.subalgebra_generated_by()
-                sage: A(x).superalgebra_element() == x
-                True
-                sage: y = A.random_element()
-                sage: A(y.superalgebra_element()) == y
-                True
-
-            """
-            return self.parent().superalgebra().linear_combination(
-              zip(self.vector(), self.parent()._superalgebra_basis) )
+    Element = FiniteDimensionalEuclideanJordanElementSubalgebraElement