X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=mjo%2Feja%2Feja_algebra.py;h=f2d7ba70c82ae38375d3496521eef14463566897;hb=2e4211deee2c4556f2c2b4dccc857106ce6bc89a;hp=afe0a677aaafd9ddf67355ed979d5ef023beb9c0;hpb=0d7746bc8dbe22bd5ce4ece76354e34454eda5d2;p=sage.d.git diff --git a/mjo/eja/eja_algebra.py b/mjo/eja/eja_algebra.py index afe0a67..f2d7ba7 100644 --- a/mjo/eja/eja_algebra.py +++ b/mjo/eja/eja_algebra.py @@ -1656,7 +1656,7 @@ class RationalBasisEJA(FiniteDimensionalEJA): subs_dict = { X[i]: BX[i] for i in range(len(X)) } return tuple( a_i.subs(subs_dict) for a_i in a ) -class ConcreteEJA(RationalBasisEJA): +class ConcreteEJA(FiniteDimensionalEJA): r""" A class for the Euclidean Jordan algebras that we know by name. @@ -1733,11 +1733,9 @@ class MatrixEJA: def trace_inner_product(X,Y): r""" A trace inner-product for matrices that aren't embedded in the - reals. + reals. It takes MATRICES as arguments, not EJA elements. """ - # We take the norm (absolute value) because Octonions() isn't - # smart enough yet to coerce its one() into the base field. - return (X*Y).trace().real().abs() + return (X*Y).trace().real() class RealEmbeddedMatrixEJA(MatrixEJA): @staticmethod @@ -1833,7 +1831,7 @@ class RealEmbeddedMatrixEJA(MatrixEJA): # as a REAL matrix will be 2*a = 2*Re(z_1). And so forth. return (X*Y).trace()/cls.dimension_over_reals() -class RealSymmetricEJA(ConcreteEJA, MatrixEJA): +class RealSymmetricEJA(ConcreteEJA, RationalBasisEJA, MatrixEJA): """ The rank-n simple EJA consisting of real symmetric n-by-n matrices, the usual symmetric Jordan product, and the trace inner @@ -2115,7 +2113,7 @@ class ComplexMatrixEJA(RealEmbeddedMatrixEJA): return matrix(F, n/d, elements) -class ComplexHermitianEJA(ConcreteEJA, ComplexMatrixEJA): +class ComplexHermitianEJA(ConcreteEJA, RationalBasisEJA, ComplexMatrixEJA): """ The rank-n simple EJA consisting of complex Hermitian n-by-n matrices over the real numbers, the usual symmetric Jordan product, @@ -2417,7 +2415,9 @@ class QuaternionMatrixEJA(RealEmbeddedMatrixEJA): return matrix(Q, n/d, elements) -class QuaternionHermitianEJA(ConcreteEJA, QuaternionMatrixEJA): +class QuaternionHermitianEJA(ConcreteEJA, + RationalBasisEJA, + QuaternionMatrixEJA): r""" The rank-n simple EJA consisting of self-adjoint n-by-n quaternion matrices, the usual symmetric Jordan product, and the @@ -2735,8 +2735,27 @@ class OctonionHermitianEJA(FiniteDimensionalEJA, MatrixEJA): return tuple( basis ) + @staticmethod + def trace_inner_product(X,Y): + r""" + The octonions don't know that the reals are embedded in them, + so we have to take the e0 component ourselves. + + SETUP:: + + sage: from mjo.eja.eja_algebra import OctonionHermitianEJA + + TESTS:: + + sage: J = OctonionHermitianEJA(2,field=QQ,orthonormalize=False) + sage: I = J.one().to_matrix() + sage: J.trace_inner_product(I, -I) + -2 + + """ + return (X*Y).trace().real().coefficient(0) -class HadamardEJA(ConcreteEJA): +class HadamardEJA(ConcreteEJA, RationalBasisEJA): """ Return the Euclidean Jordan Algebra corresponding to the set `R^n` under the Hadamard product. @@ -2828,7 +2847,7 @@ class HadamardEJA(ConcreteEJA): return cls(n, **kwargs) -class BilinearFormEJA(ConcreteEJA): +class BilinearFormEJA(ConcreteEJA, RationalBasisEJA): r""" The rank-2 simple EJA consisting of real vectors ``x=(x0, x_bar)`` with the half-trace inner product and jordan product ``x*y = @@ -3076,7 +3095,7 @@ class JordanSpinEJA(BilinearFormEJA): return cls(n, **kwargs) -class TrivialEJA(ConcreteEJA): +class TrivialEJA(ConcreteEJA, RationalBasisEJA): """ The trivial Euclidean Jordan algebra consisting of only a zero element. @@ -3361,9 +3380,17 @@ class CartesianProductEJA(FiniteDimensionalEJA): Return the space that our matrix basis lives in as a Cartesian product. + We don't simply use the ``cartesian_product()`` functor here + because it acts differently on SageMath MatrixSpaces and our + custom MatrixAlgebras, which are CombinatorialFreeModules. We + always want the result to be represented (and indexed) as + an ordered tuple. + SETUP:: - sage: from mjo.eja.eja_algebra import (HadamardEJA, + sage: from mjo.eja.eja_algebra import (ComplexHermitianEJA, + ....: HadamardEJA, + ....: OctonionHermitianEJA, ....: RealSymmetricEJA) EXAMPLES:: @@ -3376,10 +3403,44 @@ class CartesianProductEJA(FiniteDimensionalEJA): matrices over Algebraic Real Field, Full MatrixSpace of 2 by 2 dense matrices over Algebraic Real Field) + :: + + sage: J1 = ComplexHermitianEJA(1) + sage: J2 = ComplexHermitianEJA(1) + sage: J = cartesian_product([J1,J2]) + sage: J.one().to_matrix()[0] + [1 0] + [0 1] + sage: J.one().to_matrix()[1] + [1 0] + [0 1] + + :: + + sage: J1 = OctonionHermitianEJA(1) + sage: J2 = OctonionHermitianEJA(1) + sage: J = cartesian_product([J1,J2]) + sage: J.one().to_matrix()[0] + +----+ + | e0 | + +----+ + sage: J.one().to_matrix()[1] + +----+ + | e0 | + +----+ + """ - from sage.categories.cartesian_product import cartesian_product - return cartesian_product( [J.matrix_space() - for J in self.cartesian_factors()] ) + scalars = self.cartesian_factor(0).base_ring() + + # This category isn't perfect, but is good enough for what we + # need to do. + cat = MagmaticAlgebras(scalars).FiniteDimensional().WithBasis() + cat = cat.Unital().CartesianProducts() + factors = tuple( J.matrix_space() for J in self.cartesian_factors() ) + + from sage.sets.cartesian_product import CartesianProduct + return CartesianProduct(factors, cat) + @cached_method def cartesian_projection(self, i):