X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=mjo%2Feja%2Feja_algebra.py;h=6252cc29a729472ef7f182cd3393ab3db98b6b58;hb=39d8d3190b721ea21e0e86618d774437bc1eeb35;hp=d9a3abc7508e69424d4432ed64875cf17c01cac8;hpb=093846a825b8293cc81661f0b4927662c5a0446d;p=sage.d.git diff --git a/mjo/eja/eja_algebra.py b/mjo/eja/eja_algebra.py index d9a3abc..6252cc2 100644 --- a/mjo/eja/eja_algebra.py +++ b/mjo/eja/eja_algebra.py @@ -33,6 +33,7 @@ from sage.rings.all import (ZZ, QQ, AA, QQbar, RR, RLF, CLF, from mjo.eja.eja_element import FiniteDimensionalEuclideanJordanAlgebraElement lazy_import('mjo.eja.eja_subalgebra', 'FiniteDimensionalEuclideanJordanSubalgebra') +from mjo.eja.eja_operator import FiniteDimensionalEuclideanJordanAlgebraOperator from mjo.eja.eja_utils import _mat2vec class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule): @@ -1061,6 +1062,33 @@ class ConcreteEuclideanJordanAlgebra: rank, and so on are known a priori. More to the point, they are the Euclidean Jordan algebras for which we are able to conjure up a "random instance." + + SETUP:: + + sage: from mjo.eja.eja_algebra import ConcreteEuclideanJordanAlgebra + + TESTS: + + Our natural basis is normalized with respect to the natural inner + product unless we specify otherwise:: + + sage: set_random_seed() + sage: J = ConcreteEuclideanJordanAlgebra.random_instance() + sage: all( b.norm() == 1 for b in J.gens() ) + True + + Since our natural basis is normalized with respect to the natural + inner product, and since we know that this algebra is an EJA, any + left-multiplication operator's matrix will be symmetric because + natural->EJA basis representation is an isometry and within the EJA + the operator is self-adjoint by the Jordan axiom:: + + sage: set_random_seed() + sage: J = ConcreteEuclideanJordanAlgebra.random_instance() + sage: x = J.random_element() + sage: x.operator().matrix().is_symmetric() + True + """ @staticmethod @@ -1335,25 +1363,6 @@ class RealSymmetricEJA(RealMatrixEuclideanJordanAlgebra, sage: RealSymmetricEJA(3, prefix='q').gens() (q0, q1, q2, q3, q4, q5) - Our natural basis is normalized with respect to the natural inner - product unless we specify otherwise:: - - sage: set_random_seed() - sage: J = RealSymmetricEJA.random_instance() - sage: all( b.norm() == 1 for b in J.gens() ) - True - - Since our natural basis is normalized with respect to the natural - inner product, and since we know that this algebra is an EJA, any - left-multiplication operator's matrix will be symmetric because - natural->EJA basis representation is an isometry and within the EJA - the operator is self-adjoint by the Jordan axiom:: - - sage: set_random_seed() - sage: x = RealSymmetricEJA.random_instance().random_element() - sage: x.operator().matrix().is_symmetric() - True - We can construct the (trivial) algebra of rank zero:: sage: RealSymmetricEJA(0) @@ -1623,25 +1632,6 @@ class ComplexHermitianEJA(ComplexMatrixEuclideanJordanAlgebra, sage: ComplexHermitianEJA(2, prefix='z').gens() (z0, z1, z2, z3) - Our natural basis is normalized with respect to the natural inner - product unless we specify otherwise:: - - sage: set_random_seed() - sage: J = ComplexHermitianEJA.random_instance() - sage: all( b.norm() == 1 for b in J.gens() ) - True - - Since our natural basis is normalized with respect to the natural - inner product, and since we know that this algebra is an EJA, any - left-multiplication operator's matrix will be symmetric because - natural->EJA basis representation is an isometry and within the EJA - the operator is self-adjoint by the Jordan axiom:: - - sage: set_random_seed() - sage: x = ComplexHermitianEJA.random_instance().random_element() - sage: x.operator().matrix().is_symmetric() - True - We can construct the (trivial) algebra of rank zero:: sage: ComplexHermitianEJA(0) @@ -1937,25 +1927,6 @@ class QuaternionHermitianEJA(QuaternionMatrixEuclideanJordanAlgebra, sage: QuaternionHermitianEJA(2, prefix='a').gens() (a0, a1, a2, a3, a4, a5) - Our natural basis is normalized with respect to the natural inner - product unless we specify otherwise:: - - sage: set_random_seed() - sage: J = QuaternionHermitianEJA.random_instance() - sage: all( b.norm() == 1 for b in J.gens() ) - True - - Since our natural basis is normalized with respect to the natural - inner product, and since we know that this algebra is an EJA, any - left-multiplication operator's matrix will be symmetric because - natural->EJA basis representation is an isometry and within the EJA - the operator is self-adjoint by the Jordan axiom:: - - sage: set_random_seed() - sage: x = QuaternionHermitianEJA.random_instance().random_element() - sage: x.operator().matrix().is_symmetric() - True - We can construct the (trivial) algebra of rank zero:: sage: QuaternionHermitianEJA(0) @@ -2448,7 +2419,8 @@ class DirectSumEJA(FiniteDimensionalEuclideanJordanAlgebra): SETUP:: - sage: from mjo.eja.eja_algebra import (HadamardEJA, + sage: from mjo.eja.eja_algebra import (random_eja, + ....: HadamardEJA, ....: RealSymmetricEJA, ....: DirectSumEJA) @@ -2462,8 +2434,25 @@ class DirectSumEJA(FiniteDimensionalEuclideanJordanAlgebra): sage: J.rank() 5 + TESTS: + + The external direct sum construction is only valid when the two factors + have the same base ring; an error is raised otherwise:: + + sage: set_random_seed() + sage: J1 = random_eja(AA) + sage: J2 = random_eja(QQ) + sage: J = DirectSumEJA(J1,J2) + Traceback (most recent call last): + ... + ValueError: algebras must share the same base field + """ - def __init__(self, J1, J2, field=AA, **kwargs): + def __init__(self, J1, J2, **kwargs): + if J1.base_ring() != J2.base_ring(): + raise ValueError("algebras must share the same base field") + field = J1.base_ring() + self._factors = (J1, J2) n1 = J1.dimension() n2 = J2.dimension() @@ -2535,9 +2524,16 @@ class DirectSumEJA(FiniteDimensionalEuclideanJordanAlgebra): """ (J1,J2) = self.factors() - n = J1.dimension() - pi_left = lambda x: J1.from_vector(x.to_vector()[:n]) - pi_right = lambda x: J2.from_vector(x.to_vector()[n:]) + m = J1.dimension() + n = J2.dimension() + V_basis = self.vector_space().basis() + # Need to specify the dimensions explicitly so that we don't + # wind up with a zero-by-zero matrix when we want e.g. a + # zero-by-two matrix (important for composing things). + P1 = matrix(self.base_ring(), m, m+n, V_basis[:m]) + P2 = matrix(self.base_ring(), n, m+n, V_basis[m:]) + pi_left = FiniteDimensionalEuclideanJordanAlgebraOperator(self,J1,P1) + pi_right = FiniteDimensionalEuclideanJordanAlgebraOperator(self,J2,P2) return (pi_left, pi_right) def inclusions(self): @@ -2546,7 +2542,8 @@ class DirectSumEJA(FiniteDimensionalEuclideanJordanAlgebra): SETUP:: - sage: from mjo.eja.eja_algebra import (JordanSpinEJA, + sage: from mjo.eja.eja_algebra import (random_eja, + ....: JordanSpinEJA, ....: RealSymmetricEJA, ....: DirectSumEJA) @@ -2571,14 +2568,39 @@ class DirectSumEJA(FiniteDimensionalEuclideanJordanAlgebra): sage: J.one().to_vector() (1, 0, 0, 1, 0, 1) + TESTS: + + Composing a projection with the corresponding inclusion should + produce the identity map, and mismatching them should produce + the zero map:: + + sage: set_random_seed() + sage: J1 = random_eja() + sage: J2 = random_eja() + sage: J = DirectSumEJA(J1,J2) + sage: (iota_left, iota_right) = J.inclusions() + sage: (pi_left, pi_right) = J.projections() + sage: pi_left*iota_left == J1.one().operator() + True + sage: pi_right*iota_right == J2.one().operator() + True + sage: (pi_left*iota_right).is_zero() + True + sage: (pi_right*iota_left).is_zero() + True + """ (J1,J2) = self.factors() - n = J1.dimension() + m = J1.dimension() + n = J2.dimension() V_basis = self.vector_space().basis() - I1 = matrix.column(self.base_ring(), V_basis[:n]) - I2 = matrix.column(self.base_ring(), V_basis[n:]) - iota_left = lambda x: self.from_vector(I1*x.to_vector()) - iota_right = lambda x: self.from_vector(I2*+x.to_vector()) + # Need to specify the dimensions explicitly so that we don't + # wind up with a zero-by-zero matrix when we want e.g. a + # two-by-zero matrix (important for composing things). + I1 = matrix.column(self.base_ring(), m, m+n, V_basis[:m]) + I2 = matrix.column(self.base_ring(), n, m+n, V_basis[m:]) + iota_left = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,self,I1) + iota_right = FiniteDimensionalEuclideanJordanAlgebraOperator(J2,self,I2) return (iota_left, iota_right) def inner_product(self, x, y): @@ -2597,7 +2619,7 @@ class DirectSumEJA(FiniteDimensionalEuclideanJordanAlgebra): EXAMPLE:: - sage: J1 = HadamardEJA(3) + sage: J1 = HadamardEJA(3,QQ) sage: J2 = QuaternionHermitianEJA(2,QQ,normalize_basis=False) sage: J = DirectSumEJA(J1,J2) sage: x1 = J1.one()