X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;ds=sidebyside;f=mjo%2Feja%2Feja_algebra.py;h=055bbbda83d7576fda8f5e1794d759c2eee467bc;hb=f807c8c9046723a059eb4eea03dff89293510160;hp=2b769ac447bce5b149782bbf96ada23631f9b2c9;hpb=823fb2a587e26436f46854fe44be0e8df46a6715;p=sage.d.git diff --git a/mjo/eja/eja_algebra.py b/mjo/eja/eja_algebra.py index 2b769ac..055bbbd 100644 --- a/mjo/eja/eja_algebra.py +++ b/mjo/eja/eja_algebra.py @@ -235,66 +235,6 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule): def product_on_basis(self, i, j): return self._multiplication_table[i][j] - def _a_regular_element(self): - """ - Guess a regular element. Needed to compute the basis for our - characteristic polynomial coefficients. - - SETUP:: - - sage: from mjo.eja.eja_algebra import random_eja - - TESTS: - - Ensure that this hacky method succeeds for every algebra that we - know how to construct:: - - sage: set_random_seed() - sage: J = random_eja() - sage: J._a_regular_element().is_regular() - True - - """ - gs = self.gens() - z = self.sum( (i+1)*gs[i] for i in range(len(gs)) ) - if not z.is_regular(): - raise ValueError("don't know a regular element") - return z - - - @cached_method - def _charpoly_basis_space(self): - """ - Return the vector space spanned by the basis used in our - characteristic polynomial coefficients. This is used not only to - compute those coefficients, but also any time we need to - evaluate the coefficients (like when we compute the trace or - determinant). - """ - z = self._a_regular_element() - # Don't use the parent vector space directly here in case this - # happens to be a subalgebra. In that case, we would be e.g. - # two-dimensional but span_of_basis() would expect three - # coordinates. - V = VectorSpace(self.base_ring(), self.vector_space().dimension()) - basis = [ (z**k).to_vector() for k in range(self.rank()) ] - V1 = V.span_of_basis( basis ) - b = (V1.basis() + V1.complement().basis()) - return V.span_of_basis(b) - - - def _charpoly_coeff(self, i): - """ - Return the coefficient polynomial "a_{i}" of this algebra's - general characteristic polynomial. - - Having this be a separate cached method lets us compute and - store the trace/determinant (a_{r-1} and a_{0} respectively) - separate from the entire characteristic polynomial. - """ - return self._charpoly_coefficients()[i] - - @cached_method def characteristic_polynomial(self): """ @@ -748,6 +688,14 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule): for k in range(n) ) L_x = matrix(F, n, n, L_x_i_j) + + r = None + if self.rank.is_in_cache(): + r = self.rank() + # There's no need to pad the system with redundant + # columns if we *know* they'll be redundant. + n = r + # Compute an extra power in case the rank is equal to # the dimension (otherwise, we would stop at x^(r-1)). x_powers = [ (L_x**k)*self.one().to_vector() @@ -756,7 +704,8 @@ class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule): AE = A.extended_echelon_form() E = AE[:,n:] A_rref = AE[:,:n] - r = A_rref.rank() + if r is None: + r = A_rref.rank() b = x_powers[r] # The theory says that only the first "r" coefficients are @@ -954,7 +903,7 @@ class HadamardEJA(FiniteDimensionalEuclideanJordanAlgebra): return x.to_vector().inner_product(y.to_vector()) -def random_eja(field=AA, nontrivial=False): +def random_eja(field=AA): """ Return a "random" finite-dimensional Euclidean Jordan Algebra. @@ -968,21 +917,17 @@ def random_eja(field=AA, nontrivial=False): Euclidean Jordan algebra of dimension... """ - eja_classes = [HadamardEJA, - JordanSpinEJA, - RealSymmetricEJA, - ComplexHermitianEJA, - QuaternionHermitianEJA] - if not nontrivial: - eja_classes.append(TrivialEJA) - classname = choice(eja_classes) + classname = choice([TrivialEJA, + HadamardEJA, + JordanSpinEJA, + RealSymmetricEJA, + ComplexHermitianEJA, + QuaternionHermitianEJA]) return classname.random_instance(field=field) - - class MatrixEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebra): @staticmethod def _max_test_case_size(): @@ -1044,7 +989,26 @@ class MatrixEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebra): J = MatrixEuclideanJordanAlgebra(QQ, basis, normalize_basis=False) - return J._charpoly_coefficients() + a = J._charpoly_coefficients() + + # Unfortunately, changing the basis does change the + # coefficients of the characteristic polynomial, but since + # these are really the coefficients of the "characteristic + # polynomial of" function, everything is still nice and + # unevaluated. It's therefore "obvious" how scaling the + # basis affects the coordinate variables X1, X2, et + # cetera. Scaling the first basis vector up by "n" adds a + # factor of 1/n into every "X1" term, for example. So here + # we simply undo the basis_normalizer scaling that we + # performed earlier. + # + # The a[0] access here is safe because trivial algebras + # won't have any basis normalizers and therefore won't + # make it to this "else" branch. + XS = a[0].parent().gens() + subs_dict = { XS[i]: self._basis_normalizers[i]*XS[i] + for i in range(len(XS)) } + return tuple( a_i.subs(subs_dict) for a_i in a ) @staticmethod @@ -1062,6 +1026,9 @@ class MatrixEuclideanJordanAlgebra(FiniteDimensionalEuclideanJordanAlgebra): # is supposed to hold the entire long vector, and the subspace W # of V will be spanned by the vectors that arise from symmetric # matrices. Thus for S^2, dim(V) == 4 and dim(W) == 3. + if len(basis) == 0: + return [] + field = basis[0].base_ring() dimension = basis[0].nrows() @@ -1219,6 +1186,11 @@ class RealSymmetricEJA(RealMatrixEuclideanJordanAlgebra): sage: x.operator().matrix().is_symmetric() True + We can construct the (trivial) algebra of rank zero:: + + sage: RealSymmetricEJA(0) + Euclidean Jordan algebra of dimension 0 over Algebraic Real Field + """ @classmethod def _denormalized_basis(cls, n, field): @@ -1492,6 +1464,11 @@ class ComplexHermitianEJA(ComplexMatrixEuclideanJordanAlgebra): sage: x.operator().matrix().is_symmetric() True + We can construct the (trivial) algebra of rank zero:: + + sage: ComplexHermitianEJA(0) + Euclidean Jordan algebra of dimension 0 over Algebraic Real Field + """ @classmethod @@ -1787,6 +1764,11 @@ class QuaternionHermitianEJA(QuaternionMatrixEuclideanJordanAlgebra): sage: x.operator().matrix().is_symmetric() True + We can construct the (trivial) algebra of rank zero:: + + sage: QuaternionHermitianEJA(0) + Euclidean Jordan algebra of dimension 0 over Algebraic Real Field + """ @classmethod def _denormalized_basis(cls, n, field):