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"""
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):
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)
# 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
# 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 = {}
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.