X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=mjo%2Feja%2Feja_algebra.py;h=1040d37071d9000cbbd69111306284e7a9745edc;hb=516438a5d7d7578d93c9780f62ceca41ae2e2f12;hp=00de418a36cca4ecdf7bd6c6e70daf7cc8531344;hpb=429dda48b69d960fb71a3e321b07097d2eae6965;p=sage.d.git diff --git a/mjo/eja/eja_algebra.py b/mjo/eja/eja_algebra.py index 00de418..1040d37 100644 --- a/mjo/eja/eja_algebra.py +++ b/mjo/eja/eja_algebra.py @@ -3018,8 +3018,7 @@ class TrivialEJA(ConcreteEJA): 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 @@ -3115,6 +3114,33 @@ class CartesianProductEJA(CombinatorialFreeModule_CartesianProduct, 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:: @@ -3142,37 +3168,39 @@ class CartesianProductEJA(CombinatorialFreeModule_CartesianProduct, 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") - 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() - 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( - (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( - 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 @@ -3192,50 +3220,12 @@ class CartesianProductEJA(CombinatorialFreeModule_CartesianProduct, 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""" @@ -3333,8 +3323,11 @@ class CartesianProductEJA(CombinatorialFreeModule_CartesianProduct, """ 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 @@ -3441,8 +3434,8 @@ class CartesianProductEJA(CombinatorialFreeModule_CartesianProduct, """ 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()) @@ -3488,3 +3481,16 @@ class RationalBasisCartesianProductEJA(CartesianProductEJA, 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