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
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::
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
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))
+ 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))
+
+ def cartesian_factors(self):
+ return self._sets
def matrix_space(self):
r"""
"""
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
"""
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())
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