]> gitweb.michael.orlitzky.com - sage.d.git/commitdiff
eja: allow FDEJA constructor to work on a tuple basis.
authorMichael Orlitzky <michael@orlitzky.com>
Wed, 24 Feb 2021 03:22:19 +0000 (22:22 -0500)
committerMichael Orlitzky <michael@orlitzky.com>
Wed, 24 Feb 2021 03:22:19 +0000 (22:22 -0500)
mjo/eja/eja_algebra.py
mjo/eja/eja_element.py

index d23ae2cf93e91bdd7998fe8852c3b936e577b222..a4208519268cf204cfe43b80dddf882f9638fcd1 100644 (file)
@@ -85,7 +85,12 @@ class FiniteDimensionalEJA(CombinatorialFreeModule):
 
         # 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 not cartesian_product:
+            # The field for a cartesian product algebra comes from one
+            # of its factors and is the same for all factors, so
+            # there's no need to "reapply" it on product algebras.
+            basis = tuple( b.change_ring(field) for b in basis )
+
 
         if check_axioms:
             # Check commutativity of the Jordan and inner-products.
@@ -127,10 +132,17 @@ class FiniteDimensionalEJA(CombinatorialFreeModule):
         # we see in things like x = 1*e1 + 2*e2.
         vector_basis = basis
 
+        def flatten(b):
+            # flatten a vector, matrix, or cartesian product of those
+            # things into a long list.
+            if cartesian_product:
+                return sum(( b_i.list() for b_i in b ), [])
+            else:
+                return b.list()
+
         degree = 0
         if n > 0:
-            # Works on both column and square matrices...
-            degree = len(basis[0].list())
+            degree = len(flatten(basis[0]))
 
         # Build an ambient space that fits our matrix basis when
         # written out as "long vectors."
@@ -144,7 +156,7 @@ class FiniteDimensionalEJA(CombinatorialFreeModule):
             # Save a copy of the un-orthonormalized basis for later.
             # Convert it to ambient V (vector) coordinates while we're
             # at it, because we'd have to do it later anyway.
-            deortho_vector_basis = tuple( V(b.list()) for b in basis )
+            deortho_vector_basis = tuple( V(flatten(b)) for b in basis )
 
             from mjo.eja.eja_utils import gram_schmidt
             basis = tuple(gram_schmidt(basis, inner_product))
@@ -156,7 +168,7 @@ class FiniteDimensionalEJA(CombinatorialFreeModule):
         # Now create the vector space for the algebra, which will have
         # its own set of non-ambient coordinates (in terms of the
         # supplied basis).
-        vector_basis = tuple( V(b.list()) for b in basis )
+        vector_basis = tuple( V(flatten(b)) for b in basis )
         W = V.span_of_basis( vector_basis, check=check_axioms)
 
         if orthonormalize:
@@ -188,7 +200,7 @@ class FiniteDimensionalEJA(CombinatorialFreeModule):
                 # The jordan product returns a matrixy answer, so we
                 # have to convert it to the algebra coordinates.
                 elt = jordan_product(q_i, q_j)
-                elt = W.coordinate_vector(V(elt.list()))
+                elt = W.coordinate_vector(V(flatten(elt)))
                 self._multiplication_table[i][j] = self.from_vector(elt)
 
                 if not orthonormalize:
@@ -2812,23 +2824,32 @@ class CartesianProductEJA(CombinatorialFreeModule_CartesianProduct,
         if not all( J.base_ring() == field for J in modules ):
             raise ValueError("all factors must share the same base field")
 
-        basis = tuple( b.to_vector().column() for b in self.basis() )
+        # The definition of matrix_space() and self.basis() relies
+        # only on the stuff in the CFM_CartesianProduct class, which
+        # we've already initialized.
+        Js = self.cartesian_factors()
+        m = len(Js)
+        MS = self.matrix_space()
+        basis = tuple(
+            MS(tuple( self.cartesian_projection(i)(b).to_matrix()
+                      for i in range(m) ))
+            for b in self.basis()
+        )
 
-        # Define jordan/inner products that operate on thbasis.
-        def jordan_product(x_mat,y_mat):
-            x = self.from_vector(_mat2vec(x_mat))
-            y = self.from_vector(_mat2vec(y_mat))
-            return self.cartesian_jordan_product(x,y).to_vector().column()
+        # Define jordan/inner products that operate on that matrix_basis.
+        def jordan_product(x,y):
+            return MS(tuple(
+                (Js[i](x[i])*Js[i](y[i])).to_matrix() for i in range(m)
+            ))
 
-        def inner_product(x_mat, y_mat):
-            x = self.from_vector(_mat2vec(x_mat))
-            y = self.from_vector(_mat2vec(y_mat))
-            return self.cartesian_inner_product(x,y)
+        def inner_product(x, y):
+            return sum(
+                Js[i](x[i]).inner_product(Js[i](y[i])) for i in range(m)
+            )
 
-        # Use whatever category the superclass came up with. Usually
-        # some join of the EJA and Cartesian product
-        # categories. There's no need to check the field since it
-        # already came from an EJA.
+        # There's no need to check the field since it already came
+        # from an EJA. Likewise the axioms are guaranteed to be
+        # satisfied, unless the guy writing this class sucks.
         #
         # If you want the basis to be orthonormalized, orthonormalize
         # the factors.
@@ -2846,20 +2867,6 @@ class CartesianProductEJA(CombinatorialFreeModule_CartesianProduct,
         self.one.set_cache(self._cartesian_product_of_elements(ones))
         self.rank.set_cache(sum(J.rank() for J in modules))
 
-        # Now that everything else is ready, we clobber our computed
-        # matrix basis with the "correct" one consisting of ordered
-        # tuples. Since we didn't orthonormalize our basis, we can
-        # create these from the basis that was handed to us; that is,
-        # we don't need to use the one that the earlier __init__()
-        # method came up with.
-        m = len(self.cartesian_factors())
-        MS = self.matrix_space()
-        self._matrix_basis = tuple(
-            MS(tuple( self.cartesian_projection(i)(b).to_matrix()
-                      for i in range(m) ))
-            for b in self.basis()
-        )
-
     def matrix_space(self):
         r"""
         Return the space that our matrix basis lives in as a Cartesian
@@ -3177,4 +3184,11 @@ class CartesianProductEJA(CombinatorialFreeModule_CartesianProduct,
 
 
 FiniteDimensionalEJA.CartesianProduct = CartesianProductEJA
+
 random_eja = ConcreteEJA.random_instance
+#def random_eja(*args, **kwargs):
+#    from sage.categories.cartesian_product import cartesian_product
+#    J1 = HadamardEJA(1, **kwargs)
+#    J2 = RealSymmetricEJA(2, **kwargs)
+#    J =  cartesian_product([J1,J2])
+#    return J
index 347aa3c211278a15a691944c9a559076c5817acf..4c9993a2cae68c8064a087c344ef2a5bf23877c5 100644 (file)
@@ -1654,4 +1654,3 @@ class CartesianProductEJAElement(FiniteDimensionalEJAElement):
         return sum( ( W(tuple(alpha*b_i for b_i in b))
                       for (b,alpha) in pairs ),
                     W.zero())
-