X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=mjo%2Feja%2Feja_element.py;h=c47156d31e2c6989e1fe863091794520f395523c;hb=02c754829b2f2e8378561e6afd7cbfab2577f3f4;hp=fb1983859c849c40ae5294f8e45e8d2f14a13b57;hpb=3b7cb5424101ae1cde5f868d672dd613763fc439;p=sage.d.git diff --git a/mjo/eja/eja_element.py b/mjo/eja/eja_element.py index fb19838..c47156d 100644 --- a/mjo/eja/eja_element.py +++ b/mjo/eja/eja_element.py @@ -25,69 +25,6 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): dir(self.__class__) ) - def __init__(self, A, elt): - """ - - SETUP:: - - sage: from mjo.eja.eja_algebra import (RealSymmetricEJA, - ....: random_eja) - - EXAMPLES: - - The identity in `S^n` is converted to the identity in the EJA:: - - sage: J = RealSymmetricEJA(3) - sage: I = matrix.identity(QQ,3) - sage: J(I) == J.one() - True - - This skew-symmetric matrix can't be represented in the EJA:: - - sage: J = RealSymmetricEJA(3) - sage: A = matrix(QQ,3, lambda i,j: i-j) - sage: J(A) - Traceback (most recent call last): - ... - ArithmeticError: vector is not in free module - - TESTS: - - Ensure that we can convert any element of the parent's - underlying vector space back into an algebra element whose - vector representation is what we started with:: - - sage: set_random_seed() - sage: J = random_eja() - sage: v = J.vector_space().random_element() - sage: J(v).to_vector() == v - True - - """ - # Goal: if we're given a matrix, and if it lives in our - # parent algebra's "natural ambient space," convert it - # into an algebra element. - # - # The catch is, we make a recursive call after converting - # the given matrix into a vector that lives in the algebra. - # This we need to try the parent class initializer first, - # to avoid recursing forever if we're given something that - # already fits into the algebra, but also happens to live - # in the parent's "natural ambient space" (this happens with - # vectors in R^n). - ifme = super(FiniteDimensionalEuclideanJordanAlgebraElement, self) - try: - ifme.__init__(A, elt) - except ValueError: - natural_basis = A.natural_basis() - if elt in natural_basis[0].matrix_space(): - # Thanks for nothing! Matrix spaces aren't vector - # spaces in Sage, so we have to figure out its - # natural-basis coordinates ourselves. - V = VectorSpace(elt.base_ring(), elt.nrows()**2) - W = V.span( _mat2vec(s) for s in natural_basis ) - coords = W.coordinate_vector(_mat2vec(elt)) - ifme.__init__(A, coords) def __pow__(self, n): @@ -473,7 +410,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): sage: coeff = ~(x0^2 - x_bar.inner_product(x_bar)) sage: inv_vec = x_vec.parent()([x0] + (-x_bar).list()) sage: x_inverse = coeff*inv_vec - sage: x.inverse() == J(x_inverse) + sage: x.inverse() == J.from_vector(x_inverse) True TESTS: @@ -545,15 +482,23 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): sage: J.one().is_invertible() True - The zero element is never invertible:: + The zero element is never invertible in a non-trivial algebra:: sage: set_random_seed() sage: J = random_eja() - sage: J.zero().is_invertible() + sage: (not J.is_trivial()) and J.zero().is_invertible() False """ - zero = self.parent().zero() + if self.is_zero(): + if self.parent().is_trivial(): + return True + else: + return False + + # In fact, we only need to know if the constant term is non-zero, + # so we can pass in the field's zero element instead. + zero = self.base_ring().zero() p = self.minimal_polynomial() return not (p(zero) == zero) @@ -706,6 +651,11 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): True """ + if self.is_zero() and not self.parent().is_trivial(): + # The minimal polynomial of zero in a nontrivial algebra + # is "t"; in a trivial algebra it's "1" by convention + # (it's an empty product). + return 1 return self.subalgebra_generated_by().dimension() @@ -784,8 +734,20 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): 0 """ + if self.is_zero(): + # We would generate a zero-dimensional subalgebra + # where the minimal polynomial would be constant. + # That might be correct, but only if *this* algebra + # is trivial too. + if not self.parent().is_trivial(): + # Pretty sure we know what the minimal polynomial of + # the zero operator is going to be. This ensures + # consistency of e.g. the polynomial variable returned + # in the "normal" case without us having to think about it. + return self.operator().minimal_polynomial() + A = self.subalgebra_generated_by() - return A.element_class(A,self).operator().minimal_polynomial() + return A(self).operator().minimal_polynomial() @@ -864,10 +826,12 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): """ P = self.parent() + left_mult_by_self = lambda y: self*y + L = P.module_morphism(function=left_mult_by_self, codomain=P) return FiniteDimensionalEuclideanJordanAlgebraOperator( P, P, - self.to_matrix() ) + L.matrix() ) def quadratic_representation(self, other=None): @@ -1001,11 +965,17 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): sage: from mjo.eja.eja_algebra import random_eja - TESTS:: + TESTS: + + This subalgebra, being composed of only powers, is associative:: sage: set_random_seed() - sage: x = random_eja().random_element() - sage: x.subalgebra_generated_by().is_associative() + sage: x0 = random_eja().random_element() + sage: A = x0.subalgebra_generated_by() + sage: x = A.random_element() + sage: y = A.random_element() + sage: z = A.random_element() + sage: (x*y)*z == x*(y*z) True Squaring in the subalgebra should work the same as in @@ -1017,6 +987,15 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): sage: A(x^2) == A(x)*A(x) True + The subalgebra generated by the zero element is trivial:: + + sage: set_random_seed() + sage: A = random_eja().zero().subalgebra_generated_by() + sage: A + Euclidean Jordan algebra of dimension 0 over Rational Field + sage: A.one() + 0 + """ return FiniteDimensionalEuclideanJordanElementSubalgebra(self) @@ -1046,7 +1025,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): raise ValueError("this only works with non-nilpotent elements!") J = self.subalgebra_generated_by() - u = J.from_vector(self.to_vector()) + u = J(self) # The image of the matrix of left-u^m-multiplication # will be minimal for some natural number s... @@ -1071,7 +1050,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): # Our FiniteDimensionalAlgebraElement superclass uses rows. u_next = u**(s+1) A = u_next.operator().matrix() - c = J(A.solve_right(u_next.to_vector())) + c = J.from_vector(A.solve_right(u_next.to_vector())) # Now c is the idempotent we want, but it still lives in the subalgebra. return c.superalgebra_element()