X-Git-Url: http://gitweb.michael.orlitzky.com/?p=sage.d.git;a=blobdiff_plain;f=mjo%2Feja%2Feja_algebra.py;h=5bf597565b2ae292032c3f0a532763d7889cd2a8;hp=4d0c802c38c8320a8f10f8faeb50678a85d84e95;hb=db1f7761ebf564221669137ae07476ea45d82a2c;hpb=a339e89c225bb46379332ecb8b0c50b918d34ac6 diff --git a/mjo/eja/eja_algebra.py b/mjo/eja/eja_algebra.py index 4d0c802..5bf5975 100644 --- a/mjo/eja/eja_algebra.py +++ b/mjo/eja/eja_algebra.py @@ -1725,6 +1725,21 @@ class ConcreteEJA(RationalBasisEJA): class MatrixEJA: + @staticmethod + def jordan_product(X,Y): + return (X*Y + Y*X)/2 + + @staticmethod + def trace_inner_product(X,Y): + r""" + A trace inner-product for matrices that aren't embedded in the + reals. + """ + # 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().abs() + +class RealEmbeddedMatrixEJA(MatrixEJA): @staticmethod def dimension_over_reals(): r""" @@ -1770,9 +1785,6 @@ class MatrixEJA: raise ValueError("the matrix 'M' must be a real embedding") return M - @staticmethod - def jordan_product(X,Y): - return (X*Y + Y*X)/2 @classmethod def trace_inner_product(cls,X,Y): @@ -1781,29 +1793,11 @@ class MatrixEJA: SETUP:: - sage: from mjo.eja.eja_algebra import (RealSymmetricEJA, - ....: ComplexHermitianEJA, + sage: from mjo.eja.eja_algebra import (ComplexHermitianEJA, ....: QuaternionHermitianEJA) EXAMPLES:: - This gives the same answer as it would if we computed the trace - from the unembedded (original) matrices:: - - sage: set_random_seed() - sage: J = RealSymmetricEJA.random_instance() - sage: x,y = J.random_elements(2) - sage: Xe = x.to_matrix() - sage: Ye = y.to_matrix() - sage: X = J.real_unembed(Xe) - sage: Y = J.real_unembed(Ye) - sage: expected = (X*Y).trace() - sage: actual = J.trace_inner_product(Xe,Ye) - sage: actual == expected - True - - :: - sage: set_random_seed() sage: J = ComplexHermitianEJA.random_instance() sage: x,y = J.random_elements(2) @@ -1839,14 +1833,7 @@ class 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 RealMatrixEJA(MatrixEJA): - @staticmethod - def dimension_over_reals(): - return 1 - - -class RealSymmetricEJA(ConcreteEJA, RealMatrixEJA): +class RealSymmetricEJA(ConcreteEJA, MatrixEJA): """ The rank-n simple EJA consisting of real symmetric n-by-n matrices, the usual symmetric Jordan product, and the trace inner @@ -1975,12 +1962,12 @@ class RealSymmetricEJA(ConcreteEJA, RealMatrixEJA): # because the MatrixEJA is not presently a subclass of the # FDEJA class that defines rank() and one(). self.rank.set_cache(n) - idV = matrix.identity(ZZ, self.dimension_over_reals()*n) + idV = self.matrix_space().one() self.one.set_cache(self(idV)) -class ComplexMatrixEJA(MatrixEJA): +class ComplexMatrixEJA(RealEmbeddedMatrixEJA): # A manual dictionary-cache for the complex_extension() method, # since apparently @classmethods can't also be @cached_methods. _complex_extension = {} @@ -2282,7 +2269,7 @@ class ComplexHermitianEJA(ConcreteEJA, ComplexMatrixEJA): n = ZZ.random_element(cls._max_random_instance_size() + 1) return cls(n, **kwargs) -class QuaternionMatrixEJA(MatrixEJA): +class QuaternionMatrixEJA(RealEmbeddedMatrixEJA): # A manual dictionary-cache for the quaternion_extension() method, # since apparently @classmethods can't also be @cached_methods.