X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=mjo%2Feja%2Feja_algebra.py;h=ae5baa0eff4a64dac97944bbdaf5a8ec132495bd;hb=1adac51be4b18c6045d69bea652d8f2059e09b26;hp=29ff1da38480b3b9b07d1ff39555948e31785732;hpb=393a3fbd21087c3ba22f47b8a3b41ae987e4a841;p=sage.d.git diff --git a/mjo/eja/eja_algebra.py b/mjo/eja/eja_algebra.py index 29ff1da..ae5baa0 100644 --- a/mjo/eja/eja_algebra.py +++ b/mjo/eja/eja_algebra.py @@ -5,6 +5,8 @@ are used in optimization, and have some additional nice methods beyond what can be supported in a general Jordan Algebra. """ +from itertools import repeat + from sage.algebras.quatalg.quaternion_algebra import QuaternionAlgebra from sage.categories.magmatic_algebras import MagmaticAlgebras from sage.combinat.free_module import CombinatorialFreeModule @@ -51,8 +53,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule): sage: set_random_seed() sage: J = random_eja() - sage: x = J.random_element() - sage: y = J.random_element() + sage: x,y = J.random_elements(2) sage: x*y == y*x True @@ -446,9 +447,7 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule): sage: set_random_seed() sage: J = random_eja() - sage: x = J.random_element() - sage: y = J.random_element() - sage: z = J.random_element() + sage: x,y,z = J.random_elements(3) sage: (x*y).inner_product(z) == y.inner_product(x*z) True @@ -657,6 +656,25 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule): s = super(FiniteDimensionalEuclideanJordanAlgebra, self) return s.random_element() + def random_elements(self, count): + """ + Return ``count`` random elements as a tuple. + + SETUP:: + + sage: from mjo.eja.eja_algebra import JordanSpinEJA + + EXAMPLES:: + + sage: J = JordanSpinEJA(3) + sage: x,y,z = J.random_elements(3) + sage: all( [ x in J, y in J, z in J ]) + True + sage: len( J.random_elements(10) ) == 10 + True + + """ + return tuple( self.random_element() for idx in xrange(count) ) @classmethod def random_instance(cls, field=QQ, **kwargs): @@ -713,18 +731,12 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule): The rank of the `n`-by-`n` Hermitian real, complex, or quaternion matrices is `n`:: - sage: RealSymmetricEJA(2).rank() - 2 - sage: ComplexHermitianEJA(2).rank() - 2 + sage: RealSymmetricEJA(4).rank() + 4 + sage: ComplexHermitianEJA(3).rank() + 3 sage: QuaternionHermitianEJA(2).rank() 2 - sage: RealSymmetricEJA(5).rank() - 5 - sage: ComplexHermitianEJA(5).rank() - 5 - sage: QuaternionHermitianEJA(5).rank() - 5 TESTS: @@ -824,8 +836,7 @@ class RealCartesianProductEJA(FiniteDimensionalEuclideanJordanAlgebra): sage: set_random_seed() sage: J = RealCartesianProductEJA.random_instance() - sage: x = J.random_element() - sage: y = J.random_element() + sage: x,y = J.random_elements(2) sage: X = x.natural_representation() sage: Y = y.natural_representation() sage: x.inner_product(y) == J.natural_inner_product(X,Y) @@ -996,7 +1007,33 @@ class MatrixEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebra): return tr.coefficient_tuple()[0] -class RealSymmetricEJA(MatrixEuclideanJordanAlgebra): +class RealMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra): + @staticmethod + def real_embed(M): + """ + Embed the matrix ``M`` into a space of real matrices. + + The matrix ``M`` can have entries in any field at the moment: + the real numbers, complex numbers, or quaternions. And although + they are not a field, we can probably support octonions at some + point, too. This function returns a real matrix that "acts like" + the original with respect to matrix multiplication; i.e. + + real_embed(M*N) = real_embed(M)*real_embed(N) + + """ + return M + + + @staticmethod + def real_unembed(M): + """ + The inverse of :meth:`real_embed`. + """ + return M + + +class RealSymmetricEJA(RealMatrixEuclideanJordanAlgebra): """ The rank-n simple EJA consisting of real symmetric n-by-n matrices, the usual symmetric Jordan product, and the trace inner @@ -1032,8 +1069,7 @@ class RealSymmetricEJA(MatrixEuclideanJordanAlgebra): sage: set_random_seed() sage: J = RealSymmetricEJA.random_instance() - sage: x = J.random_element() - sage: y = J.random_element() + sage: x,y = J.random_elements(2) sage: actual = (x*y).natural_representation() sage: X = x.natural_representation() sage: Y = y.natural_representation() @@ -1104,30 +1140,6 @@ class RealSymmetricEJA(MatrixEuclideanJordanAlgebra): def _max_test_case_size(): return 5 # Dimension 10 - @staticmethod - def real_embed(M): - """ - Embed the matrix ``M`` into a space of real matrices. - - The matrix ``M`` can have entries in any field at the moment: - the real numbers, complex numbers, or quaternions. And although - they are not a field, we can probably support octonions at some - point, too. This function returns a real matrix that "acts like" - the original with respect to matrix multiplication; i.e. - - real_embed(M*N) = real_embed(M)*real_embed(N) - - """ - return M - - - @staticmethod - def real_unembed(M): - """ - The inverse of :meth:`real_embed`. - """ - return M - class ComplexMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra): @@ -1249,6 +1261,37 @@ class ComplexMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra): return matrix(F, n/2, elements) + @classmethod + def natural_inner_product(cls,X,Y): + """ + Compute a natural inner product in this algebra directly from + its real embedding. + + SETUP:: + + sage: from mjo.eja.eja_algebra import ComplexHermitianEJA + + TESTS: + + This gives the same answer as the slow, default method implemented + in :class:`MatrixEuclideanJordanAlgebra`:: + + sage: set_random_seed() + sage: J = ComplexHermitianEJA.random_instance() + sage: x,y = J.random_elements(2) + sage: Xe = x.natural_representation() + sage: Ye = y.natural_representation() + sage: X = ComplexHermitianEJA.real_unembed(Xe) + sage: Y = ComplexHermitianEJA.real_unembed(Ye) + sage: expected = (X*Y).trace().vector()[0] + sage: actual = ComplexHermitianEJA.natural_inner_product(Xe,Ye) + sage: actual == expected + True + + """ + return RealMatrixEuclideanJordanAlgebra.natural_inner_product(X,Y)/2 + + class ComplexHermitianEJA(ComplexMatrixEuclideanJordanAlgebra): """ The rank-n simple EJA consisting of complex Hermitian n-by-n @@ -1275,8 +1318,7 @@ class ComplexHermitianEJA(ComplexMatrixEuclideanJordanAlgebra): sage: set_random_seed() sage: J = ComplexHermitianEJA.random_instance() - sage: x = J.random_element() - sage: y = J.random_element() + sage: x,y = J.random_elements(2) sage: actual = (x*y).natural_representation() sage: X = x.natural_representation() sage: Y = y.natural_representation() @@ -1498,6 +1540,36 @@ class QuaternionMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra): return matrix(Q, n/4, elements) + @classmethod + def natural_inner_product(cls,X,Y): + """ + Compute a natural inner product in this algebra directly from + its real embedding. + + SETUP:: + + sage: from mjo.eja.eja_algebra import QuaternionHermitianEJA + + TESTS: + + This gives the same answer as the slow, default method implemented + in :class:`MatrixEuclideanJordanAlgebra`:: + + sage: set_random_seed() + sage: J = QuaternionHermitianEJA.random_instance() + sage: x,y = J.random_elements(2) + sage: Xe = x.natural_representation() + sage: Ye = y.natural_representation() + sage: X = QuaternionHermitianEJA.real_unembed(Xe) + sage: Y = QuaternionHermitianEJA.real_unembed(Ye) + sage: expected = (X*Y).trace().coefficient_tuple()[0] + sage: actual = QuaternionHermitianEJA.natural_inner_product(Xe,Ye) + sage: actual == expected + True + + """ + return RealMatrixEuclideanJordanAlgebra.natural_inner_product(X,Y)/4 + class QuaternionHermitianEJA(QuaternionMatrixEuclideanJordanAlgebra): """ @@ -1525,8 +1597,7 @@ class QuaternionHermitianEJA(QuaternionMatrixEuclideanJordanAlgebra): sage: set_random_seed() sage: J = QuaternionHermitianEJA.random_instance() - sage: x = J.random_element() - sage: y = J.random_element() + sage: x,y = J.random_elements(2) sage: actual = (x*y).natural_representation() sage: X = x.natural_representation() sage: Y = y.natural_representation() @@ -1691,8 +1762,7 @@ class JordanSpinEJA(FiniteDimensionalEuclideanJordanAlgebra): sage: set_random_seed() sage: J = JordanSpinEJA.random_instance() - sage: x = J.random_element() - sage: y = J.random_element() + sage: x,y = J.random_elements(2) sage: X = x.natural_representation() sage: Y = y.natural_representation() sage: x.inner_product(y) == J.natural_inner_product(X,Y)