From f1752f438aa849da1e909c67cac2cd7ac670e86f Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 25 Aug 2019 23:40:41 -0400 Subject: [PATCH] eja: refactor the matrix EJA hierarchy (mainly constructors) a bit. --- mjo/eja/eja_algebra.py | 62 +++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/mjo/eja/eja_algebra.py b/mjo/eja/eja_algebra.py index cea1476..02cf32c 100644 --- a/mjo/eja/eja_algebra.py +++ b/mjo/eja/eja_algebra.py @@ -885,17 +885,20 @@ class MatrixEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebra): # field can have dimension 4 (quaternions) too. return 2 - @classmethod - def _denormalized_basis(cls, n, field): - raise NotImplementedError - - def __init__(self, n, field=QQ, normalize_basis=True, **kwargs): - S = self._denormalized_basis(n, field) - + def __init__(self, field, basis, rank, normalize_basis=True, **kwargs): + """ + Compared to the superclass constructor, we take a basis instead of + a multiplication table because the latter can be computed in terms + of the former when the product is known (like it is here). + """ # Used in this class's fast _charpoly_coeff() override. self._basis_normalizers = None - if n > 1 and normalize_basis: + # We're going to loop through this a few times, so now's a good + # time to ensure that it isn't a generator expression. + basis = tuple(basis) + + if rank > 1 and normalize_basis: # We'll need sqrt(2) to normalize the basis, and this # winds up in the multiplication table, so the whole # algebra needs to be over the field extension. @@ -904,18 +907,18 @@ class MatrixEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebra): p = z**2 - 2 if p.is_irreducible(): field = NumberField(p, 'sqrt2', embedding=RLF(2).sqrt()) - S = [ s.change_ring(field) for s in S ] + basis = tuple( s.change_ring(field) for s in basis ) self._basis_normalizers = tuple( - ~(self.natural_inner_product(s,s).sqrt()) for s in S ) - S = tuple( s*c for (s,c) in zip(S,self._basis_normalizers) ) + ~(self.natural_inner_product(s,s).sqrt()) for s in basis ) + basis = tuple(s*c for (s,c) in izip(basis,self._basis_normalizers)) - Qs = self.multiplication_table_from_matrix_basis(S) + Qs = self.multiplication_table_from_matrix_basis(basis) fdeja = super(MatrixEuclideanJordanAlgebra, self) return fdeja.__init__(field, Qs, - rank=n, - natural_basis=S, + rank=rank, + natural_basis=basis, **kwargs) @@ -930,11 +933,13 @@ class MatrixEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebra): # with had entries in a nice field. return super(MatrixEuclideanJordanAlgebra, self)._charpoly_coeff(i) else: - # If we didn't unembed first, this number would be wrong - # by a power-of-two factor for complex/quaternion matrices. - n = self.real_unembed(self.natural_basis_space().zero()).nrows() - field = self.base_ring().base_ring() # yeeeeaaaahhh - J = self.__class__(n, field, False) + basis = ( (b/n) for (b,n) in izip(self.natural_basis(), + self._basis_normalizers) ) + field = self.base_ring().base_ring() # yeeeaahhhhhhh + J = MatrixEuclideanJordanAlgebra(field, + basis, + self.rank(), + normalize_basis=False) (_,x,_,_) = J._charpoly_matrix_system() p = J._charpoly_coeff(i) # p might be missing some vars, have to substitute "optionally" @@ -1136,7 +1141,7 @@ class RealSymmetricEJA(RealMatrixEuclideanJordanAlgebra): else: Sij = Eij + Eij.transpose() S.append(Sij) - return tuple(S) + return S @staticmethod @@ -1144,6 +1149,10 @@ class RealSymmetricEJA(RealMatrixEuclideanJordanAlgebra): return 4 # Dimension 10 + def __init__(self, n, field=QQ, **kwargs): + basis = self._denormalized_basis(n, field) + super(RealSymmetricEJA, self).__init__(field, basis, n, **kwargs) + class ComplexMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra): @staticmethod @@ -1356,6 +1365,7 @@ class ComplexHermitianEJA(ComplexMatrixEuclideanJordanAlgebra): True """ + @classmethod def _denormalized_basis(cls, n, field): """ @@ -1407,9 +1417,13 @@ class ComplexHermitianEJA(ComplexMatrixEuclideanJordanAlgebra): # Since we embedded these, we can drop back to the "field" that we # started with instead of the complex extension "F". - return tuple( s.change_ring(field) for s in S ) + return ( s.change_ring(field) for s in S ) + def __init__(self, n, field=QQ, **kwargs): + basis = self._denormalized_basis(n,field) + super(ComplexHermitianEJA,self).__init__(field, basis, n, **kwargs) + class QuaternionMatrixEuclideanJordanAlgebra(MatrixEuclideanJordanAlgebra): @staticmethod @@ -1685,8 +1699,12 @@ class QuaternionHermitianEJA(QuaternionMatrixEuclideanJordanAlgebra): S.append(Sij_J) Sij_K = cls.real_embed(K*Eij - K*Eij.transpose()) S.append(Sij_K) - return tuple(S) + return S + + def __init__(self, n, field=QQ, **kwargs): + basis = self._denormalized_basis(n,field) + super(QuaternionHermitianEJA,self).__init__(field, basis, n, **kwargs) class JordanSpinEJA(FiniteDimensionalEuclideanJordanAlgebra): -- 2.43.2