X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=mjo%2Feja%2Feja_element.py;h=bd45b179541487bd82e3b06768a902a77cd0899d;hb=73ba2d67c0850074e655b4da61aa021e6d9b6816;hp=d9b6eb12fe27363721763fc1e6ccb60c7f98aabd;hpb=9528af011cbb4d5e6a38ef972e0d14e7928d5eef;p=sage.d.git diff --git a/mjo/eja/eja_element.py b/mjo/eja/eja_element.py index d9b6eb1..bd45b17 100644 --- a/mjo/eja/eja_element.py +++ b/mjo/eja/eja_element.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + from itertools import izip from sage.matrix.constructor import matrix @@ -34,7 +36,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): Return ``self`` raised to the power ``n``. Jordan algebras are always power-associative; see for - example Faraut and Koranyi, Proposition II.1.2 (ii). + example Faraut and Korányi, Proposition II.1.2 (ii). We have to override this because our superclass uses row vectors instead of column vectors! We, on the other hand, @@ -375,7 +377,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): True Ensure that the determinant is multiplicative on an associative - subalgebra as in Faraut and Koranyi's Proposition II.2.2:: + subalgebra as in Faraut and Korányi's Proposition II.2.2:: sage: set_random_seed() sage: J = random_eja().random_element().subalgebra_generated_by() @@ -405,7 +407,8 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): SETUP:: - sage: from mjo.eja.eja_algebra import (JordanSpinEJA, + sage: from mjo.eja.eja_algebra import (ComplexHermitianEJA, + ....: JordanSpinEJA, ....: random_eja) EXAMPLES: @@ -427,6 +430,13 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): sage: x.inverse() == J.from_vector(x_inverse) True + Trying to invert a non-invertible element throws an error: + + sage: JordanSpinEJA(3).zero().inverse() + Traceback (most recent call last): + ... + ValueError: element is not invertible + TESTS: The identity element is its own inverse:: @@ -452,13 +462,32 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): sage: (not x.is_invertible()) or (x.inverse().inverse() == x) True - The zero element is never invertible:: + Proposition II.2.3 in Faraut and Korányi says that the inverse + of an element is the inverse of its left-multiplication operator + applied to the algebra's identity, when that inverse exists:: sage: set_random_seed() - sage: J = random_eja().zero().inverse() - Traceback (most recent call last): - ... - ValueError: element is not invertible + sage: J = random_eja() + sage: x = J.random_element() + sage: (not x.operator().is_invertible()) or ( + ....: x.operator().inverse()(J.one()) == x.inverse() ) + True + + Proposition II.2.4 in Faraut and Korányi gives a formula for + the inverse based on the characteristic polynomial and the + Cayley-Hamilton theorem for Euclidean Jordan algebras:: + + sage: set_random_seed() + sage: J = ComplexHermitianEJA(3) + sage: x = J.random_element() + sage: while not x.is_invertible(): + ....: x = J.random_element() + sage: r = J.rank() + sage: a = x.characteristic_polynomial().coefficients(sparse=False) + sage: expected = (-1)^(r+1)/x.det() + sage: expected *= sum( a[i+1]*x^i for i in range(r) ) + sage: x.inverse() == expected + True """ if not self.is_invertible(): @@ -544,10 +573,11 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): TESTS: - The identity element is never nilpotent:: + The identity element is never nilpotent, except in a trivial EJA:: sage: set_random_seed() - sage: random_eja().one().is_nilpotent() + sage: J = random_eja() + sage: J.one().is_nilpotent() and not J.is_trivial() False The additive identity is always nilpotent:: @@ -591,11 +621,11 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): TESTS: The zero element should never be regular, unless the parent - algebra has dimension one:: + algebra has dimension less than or equal to one:: sage: set_random_seed() sage: J = random_eja() - sage: J.dimension() == 1 or not J.zero().is_regular() + sage: J.dimension() <= 1 or not J.zero().is_regular() True The unit element isn't regular unless the algebra happens to @@ -603,7 +633,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): sage: set_random_seed() sage: J = random_eja() - sage: J.dimension() == 1 or not J.one().is_regular() + sage: J.dimension() <= 1 or not J.one().is_regular() True """ @@ -647,14 +677,17 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): TESTS: - The zero and unit elements are both of degree one:: + The zero and unit elements are both of degree one in nontrivial + algebras:: sage: set_random_seed() sage: J = random_eja() - sage: J.zero().degree() - 1 - sage: J.one().degree() - 1 + sage: d = J.zero().degree() + sage: (J.is_trivial() and d == 0) or d == 1 + True + sage: d = J.one().degree() + sage: (J.is_trivial() and d == 0) or d == 1 + True Our implementation agrees with the definition:: @@ -1010,12 +1043,82 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): + def spectral_decomposition(self): + """ + Return the unique spectral decomposition of this element. + + ALGORITHM: + + Following Faraut and Korányi's Theorem III.1.1, we restrict this + element's left-multiplication-by operator to the subalgebra it + generates. We then compute the spectral decomposition of that + operator, and the spectral projectors we get back must be the + left-multiplication-by operators for the idempotents we + seek. Thus applying them to the identity element gives us those + idempotents. + + Since the eigenvalues are required to be distinct, we take + the spectral decomposition of the zero element to be zero + times the identity element of the algebra (which is idempotent, + obviously). - def subalgebra_generated_by(self): + SETUP:: + + sage: from mjo.eja.eja_algebra import RealSymmetricEJA + + EXAMPLES: + + The spectral decomposition of the identity is ``1`` times itself, + and the spectral decomposition of zero is ``0`` times the identity:: + + sage: J = RealSymmetricEJA(3,AA) + sage: J.one() + e0 + e2 + e5 + sage: J.one().spectral_decomposition() + [(1, e0 + e2 + e5)] + sage: J.zero().spectral_decomposition() + [(0, e0 + e2 + e5)] + + TESTS:: + + sage: J = RealSymmetricEJA(4,AA) + sage: x = sum(J.gens()) + sage: sd = x.spectral_decomposition() + sage: l0 = sd[0][0] + sage: l1 = sd[1][0] + sage: c0 = sd[0][1] + sage: c1 = sd[1][1] + sage: c0.inner_product(c1) == 0 + True + sage: c0.is_idempotent() + True + sage: c1.is_idempotent() + True + sage: c0 + c1 == J.one() + True + sage: l0*c0 + l1*c1 == x + True + + """ + P = self.parent() + A = self.subalgebra_generated_by(orthonormalize_basis=True) + result = [] + for (evalue, proj) in A(self).operator().spectral_decomposition(): + result.append( (evalue, proj(A.one()).superalgebra_element()) ) + return result + + def subalgebra_generated_by(self, orthonormalize_basis=False): """ Return the associative subalgebra of the parent EJA generated by this element. + Since our parent algebra is unital, we want "subalgebra" to mean + "unital subalgebra" as well; thus the subalgebra that an element + generates will itself be a Euclidean Jordan algebra after + restricting the algebra operations appropriately. This is the + subalgebra that Faraut and Korányi work with in section II.2, for + example. + SETUP:: sage: from mjo.eja.eja_algebra import random_eja @@ -1040,17 +1143,18 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): sage: A(x^2) == A(x)*A(x) True - The subalgebra generated by the zero element is trivial:: + By definition, the subalgebra generated by the zero element is + the one-dimensional algebra generated by the identity + element... unless the original algebra was trivial, in which + case the subalgebra is trivial too:: sage: set_random_seed() sage: A = random_eja().zero().subalgebra_generated_by() - sage: A - Euclidean Jordan algebra of dimension 0 over... - sage: A.one() - 0 + sage: (A.is_trivial() and A.dimension() == 0) or A.dimension() == 1 + True """ - return FiniteDimensionalEuclideanJordanElementSubalgebra(self) + return FiniteDimensionalEuclideanJordanElementSubalgebra(self, orthonormalize_basis) def subalgebra_idempotent(self): @@ -1144,6 +1248,12 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): """ P = self.parent() r = P.rank() + + if r == 0: + # Special case for the trivial algebra where + # the trace is an empty sum. + return P.base_ring().zero() + p = P._charpoly_coeff(r-1) # The _charpoly_coeff function already adds the factor of # -1 to ensure that _charpoly_coeff(r-1) is really what @@ -1162,8 +1272,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): TESTS: - The trace inner product is commutative, bilinear, and satisfies - the Jordan axiom: + The trace inner product is commutative, bilinear, and associative:: sage: set_random_seed() sage: J = random_eja() @@ -1183,7 +1292,7 @@ class FiniteDimensionalEuclideanJordanAlgebraElement(IndexedFreeModuleElement): ....: a*x.trace_inner_product(z) ) sage: actual == expected True - sage: # jordan axiom + sage: # associative sage: (x*y).trace_inner_product(z) == y.trace_inner_product(x*z) True