]> gitweb.michael.orlitzky.com - sage.d.git/blobdiff - mjo/eja/eja_algebra.py
eja: begin dropping CFM_CartesianProduct, tests all broken.
[sage.d.git] / mjo / eja / eja_algebra.py
index 00de418a36cca4ecdf7bd6c6e70daf7cc8531344..1040d37071d9000cbbd69111306284e7a9745edc 100644 (file)
@@ -3018,8 +3018,7 @@ class TrivialEJA(ConcreteEJA):
         return cls(**kwargs)
 
 
         return cls(**kwargs)
 
 
-class CartesianProductEJA(CombinatorialFreeModule_CartesianProduct,
-                          FiniteDimensionalEJA):
+class CartesianProductEJA(FiniteDimensionalEJA):
     r"""
     The external (orthogonal) direct sum of two or more Euclidean
     Jordan algebras. Every Euclidean Jordan algebra decomposes into an
     r"""
     The external (orthogonal) direct sum of two or more Euclidean
     Jordan algebras. Every Euclidean Jordan algebra decomposes into an
@@ -3115,6 +3114,33 @@ class CartesianProductEJA(CombinatorialFreeModule_CartesianProduct,
         sage: CP2.is_associative()
         False
 
         sage: CP2.is_associative()
         False
 
+    Cartesian products of Cartesian products work::
+
+        sage: J1 = JordanSpinEJA(1)
+        sage: J2 = JordanSpinEJA(1)
+        sage: J3 = JordanSpinEJA(1)
+        sage: J = cartesian_product([J1,cartesian_product([J2,J3])])
+        sage: J.multiplication_table()
+        +--------------++---------+--------------+--------------+
+        | *            || e(0, 0) | e(1, (0, 0)) | e(1, (1, 0)) |
+        +==============++=========+==============+==============+
+        | e(0, 0)      || e(0, 0) | 0            | 0            |
+        +--------------++---------+--------------+--------------+
+        | e(1, (0, 0)) || 0       | e(1, (0, 0)) | 0            |
+        +--------------++---------+--------------+--------------+
+        | e(1, (1, 0)) || 0       | 0            | e(1, (1, 0)) |
+        +--------------++---------+--------------+--------------+
+        sage: HadamardEJA(3).multiplication_table()
+        +----++----+----+----+
+        | *  || e0 | e1 | e2 |
+        +====++====+====+====+
+        | e0 || e0 | 0  | 0  |
+        +----++----+----+----+
+        | e1 || 0  | e1 | 0  |
+        +----++----+----+----+
+        | e2 || 0  | 0  | e2 |
+        +----++----+----+----+
+
     TESTS:
 
     All factors must share the same base field::
     TESTS:
 
     All factors must share the same base field::
@@ -3142,37 +3168,39 @@ class CartesianProductEJA(CombinatorialFreeModule_CartesianProduct,
     Element = FiniteDimensionalEJAElement
 
 
     Element = FiniteDimensionalEJAElement
 
 
-    def __init__(self, algebras, **kwargs):
-        CombinatorialFreeModule_CartesianProduct.__init__(self,
-                                                          algebras,
-                                                          **kwargs)
-        field = algebras[0].base_ring()
-        if not all( J.base_ring() == field for J in algebras ):
+    def __init__(self, factors, **kwargs):
+        m = len(factors)
+        if m == 0:
+            return TrivialEJA()
+
+        self._sets = factors
+
+        field = factors[0].base_ring()
+        if not all( J.base_ring() == field for J in factors ):
             raise ValueError("all factors must share the same base field")
 
             raise ValueError("all factors must share the same base field")
 
-        associative = all( m.is_associative() for m in algebras )
+        associative = all( f.is_associative() for f in factors )
 
 
-        # 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()
         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()
-        )
+        basis = []
+        zero = MS.zero()
+        for i in range(m):
+            for b in factors[i].matrix_basis():
+                z = list(zero)
+                z[i] = b
+                basis.append(z)
+
+        basis = tuple( MS(b) for b in basis )
 
         # Define jordan/inner products that operate on that matrix_basis.
         def jordan_product(x,y):
             return MS(tuple(
 
         # 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)
+                (factors[i](x[i])*factors[i](y[i])).to_matrix() for i in range(m)
             ))
 
         def inner_product(x, y):
             return sum(
             ))
 
         def inner_product(x, y):
             return sum(
-                Js[i](x[i]).inner_product(Js[i](y[i])) for i in range(m)
+                factors[i](x[i]).inner_product(factors[i](y[i])) for i in range(m)
             )
 
         # There's no need to check the field since it already came
             )
 
         # There's no need to check the field since it already came
@@ -3192,50 +3220,12 @@ class CartesianProductEJA(CombinatorialFreeModule_CartesianProduct,
                                       check_field=False,
                                       check_axioms=False)
 
                                       check_field=False,
                                       check_axioms=False)
 
-        ones = tuple(J.one() for J in algebras)
-        self.one.set_cache(self._cartesian_product_of_elements(ones))
-        self.rank.set_cache(sum(J.rank() for J in algebras))
-
-    def product_on_basis(self, i, j):
-        r"""
-        Return the product of the monomials indexed by ``i`` and ``j``.
-
-        This overrides the superclass method because here, both ``i``
-        and ``j`` will be ordered pairs.
-
-        SETUP::
-
-            sage: from mjo.eja.eja_algebra import (ComplexHermitianEJA,
-            ....:                                  JordanSpinEJA,
-            ....:                                  RealSymmetricEJA)
+        ones = tuple(J.one().to_matrix() for J in factors)
+        self.one.set_cache(self(ones))
+        self.rank.set_cache(sum(J.rank() for J in factors))
 
 
-        TESTS::
-
-            sage: J1 = RealSymmetricEJA(2,field=QQ,orthonormalize=False)
-            sage: J2 = ComplexHermitianEJA(0,field=QQ,orthonormalize=False)
-            sage: J3 = JordanSpinEJA(2,field=QQ,orthonormalize=False)
-            sage: J = cartesian_product([J1,J2,J3])
-            sage: x = sum(J.gens())
-            sage: x*J.one()
-            e(0, 0) + e(0, 1) + e(0, 2) + e(2, 0) + e(2, 1)
-            sage: x*x
-            2*e(0, 0) + 2*e(0, 1) + 2*e(0, 2) + 2*e(2, 0) + 2*e(2, 1)
-
-        """
-        factor = i[0]
-        assert(j[0] == i[0])
-        n = self.cartesian_factors()[factor].dimension()
-
-        # The superclass method indexes into a matrix, so we have to
-        # turn the tuples i and j into integers. This is easy enough
-        # given that the first coordinate of i and j corresponds to
-        # the factor, and the second coordinate corresponds to the
-        # index of the generator within that factor. And of course
-        # we should never be multiplying two elements from different
-        # factors.
-        l = n*factor + i[1]
-        m = n*factor + j[1]
-        super().product_on_basis(l, m)
+    def cartesian_factors(self):
+        return self._sets
 
     def matrix_space(self):
         r"""
 
     def matrix_space(self):
         r"""
@@ -3333,8 +3323,11 @@ class CartesianProductEJA(CombinatorialFreeModule_CartesianProduct,
 
         """
         Ji = self.cartesian_factors()[i]
 
         """
         Ji = self.cartesian_factors()[i]
-        # Requires the fix on Trac 31421/31422 to work!
-        Pi = super().cartesian_projection(i)
+
+        Pi = self._module_morphism(lambda j_t: Ji.monomial(j_t[1])
+                                   if i == j_t[0] else Ji.zero(),
+                                   codomain=Ji)
+
         return FiniteDimensionalEJAOperator(self,Ji,Pi.matrix())
 
     @cached_method
         return FiniteDimensionalEJAOperator(self,Ji,Pi.matrix())
 
     @cached_method
@@ -3441,8 +3434,8 @@ class CartesianProductEJA(CombinatorialFreeModule_CartesianProduct,
 
         """
         Ji = self.cartesian_factors()[i]
 
         """
         Ji = self.cartesian_factors()[i]
-        # Requires the fix on Trac 31421/31422 to work!
-        Ei = super().cartesian_embedding(i)
+        Ei = Ji._module_morphism(lambda t: self.monomial((i, t)),
+                                 codomain=self)
         return FiniteDimensionalEJAOperator(Ji,self,Ei.matrix())
 
 
         return FiniteDimensionalEJAOperator(Ji,self,Ei.matrix())
 
 
@@ -3488,3 +3481,16 @@ class RationalBasisCartesianProductEJA(CartesianProductEJA,
 RationalBasisEJA.CartesianProduct = RationalBasisCartesianProductEJA
 
 random_eja = ConcreteEJA.random_instance
 RationalBasisEJA.CartesianProduct = RationalBasisCartesianProductEJA
 
 random_eja = ConcreteEJA.random_instance
+
+# def random_eja(*args, **kwargs):
+#     J1 = ConcreteEJA.random_instance(*args, **kwargs)
+
+#     # This might make Cartesian products appear roughly as often as
+#     # any other ConcreteEJA.
+#     if ZZ.random_element(len(ConcreteEJA.__subclasses__()) + 1) == 0:
+#         # Use random_eja() again so we can get more than two factors.
+#         J2 = random_eja(*args, **kwargs)
+#         J = cartesian_product([J1,J2])
+#         return J
+#     else:
+#         return J1