what can be supported in a general Jordan Algebra.
"""
-from itertools import izip, repeat
+from itertools import repeat
from sage.algebras.quatalg.quaternion_algebra import QuaternionAlgebra
from sage.categories.magmatic_algebras import MagmaticAlgebras
from sage.matrix.constructor import matrix
from sage.matrix.matrix_space import MatrixSpace
from sage.misc.cachefunc import cached_method
+from sage.misc.lazy_import import lazy_import
from sage.misc.prandom import choice
from sage.misc.table import table
from sage.modules.free_module import FreeModule, VectorSpace
PolynomialRing,
QuadraticField)
from mjo.eja.eja_element import FiniteDimensionalEuclideanJordanAlgebraElement
+lazy_import('mjo.eja.eja_subalgebra',
+ 'FiniteDimensionalEuclideanJordanSubalgebra')
from mjo.eja.eja_utils import _mat2vec
class FiniteDimensionalEuclideanJordanAlgebra(CombinatorialFreeModule):
return self.linear_combination(zip(self.gens(), coeffs))
+ def peirce_decomposition(self, c):
+ """
+ The Peirce decomposition of this algebra relative to the
+ idempotent ``c``.
+
+ In the future, this can be extended to a complete system of
+ orthogonal idempotents.
+
+ INPUT:
+
+ - ``c`` -- an idempotent of this algebra.
+
+ OUTPUT:
+
+ A triple (J0, J5, J1) containing two subalgebras and one subspace
+ of this algebra,
+
+ - ``J0`` -- the algebra on the eigenspace of ``c.operator()``
+ corresponding to the eigenvalue zero.
+
+ - ``J5`` -- the eigenspace (NOT a subalgebra) of ``c.operator()``
+ corresponding to the eigenvalue one-half.
+
+ - ``J1`` -- the algebra on the eigenspace of ``c.operator()``
+ corresponding to the eigenvalue one.
+
+ These are the only possible eigenspaces for that operator, and this
+ algebra is a direct sum of them. The spaces ``J0`` and ``J1`` are
+ orthogonal, and are subalgebras of this algebra with the appropriate
+ restrictions.
+
+ SETUP::
+
+ sage: from mjo.eja.eja_algebra import random_eja, RealSymmetricEJA
+
+ EXAMPLES:
+
+ The canonical example comes from the symmetric matrices, which
+ decompose into diagonal and off-diagonal parts::
+
+ sage: J = RealSymmetricEJA(3)
+ sage: C = matrix(QQ, [ [1,0,0],
+ ....: [0,1,0],
+ ....: [0,0,0] ])
+ sage: c = J(C)
+ sage: J0,J5,J1 = J.peirce_decomposition(c)
+ sage: J0
+ Euclidean Jordan algebra of dimension 1...
+ sage: J5
+ Vector space of degree 6 and dimension 2...
+ sage: J1
+ Euclidean Jordan algebra of dimension 3...
+
+ TESTS:
+
+ Every algebra decomposes trivially with respect to its identity
+ element::
+
+ sage: set_random_seed()
+ sage: J = random_eja()
+ sage: J0,J5,J1 = J.peirce_decomposition(J.one())
+ sage: J0.dimension() == 0 and J5.dimension() == 0
+ True
+ sage: J1.superalgebra() == J and J1.dimension() == J.dimension()
+ True
+
+ The identity elements in the two subalgebras are the
+ projections onto their respective subspaces of the
+ superalgebra's identity element::
+
+ sage: set_random_seed()
+ sage: J = random_eja()
+ sage: x = J.random_element()
+ sage: if not J.is_trivial():
+ ....: while x.is_nilpotent():
+ ....: x = J.random_element()
+ sage: c = x.subalgebra_idempotent()
+ sage: J0,J5,J1 = J.peirce_decomposition(c)
+ sage: J1(c) == J1.one()
+ True
+ sage: J0(J.one() - c) == J0.one()
+ True
+
+ """
+ if not c.is_idempotent():
+ raise ValueError("element is not idempotent: %s" % c)
+
+ # Default these to what they should be if they turn out to be
+ # trivial, because eigenspaces_left() won't return eigenvalues
+ # corresponding to trivial spaces (e.g. it returns only the
+ # eigenspace corresponding to lambda=1 if you take the
+ # decomposition relative to the identity element).
+ trivial = FiniteDimensionalEuclideanJordanSubalgebra(self, ())
+ J0 = trivial # eigenvalue zero
+ J5 = VectorSpace(self.base_ring(), 0) # eigenvalue one-half
+ J1 = trivial # eigenvalue one
+
+ for (eigval, eigspace) in c.operator().matrix().left_eigenspaces():
+ if eigval == ~(self.base_ring()(2)):
+ J5 = eigspace
+ else:
+ gens = tuple( self.from_vector(b) for b in eigspace.basis() )
+ subalg = FiniteDimensionalEuclideanJordanSubalgebra(self, gens)
+ if eigval == 0:
+ J0 = subalg
+ elif eigval == 1:
+ J1 = subalg
+ else:
+ raise ValueError("unexpected eigenvalue: %s" % eigval)
+
+ return (J0, J5, J1)
+
+
def random_elements(self, count):
"""
Return ``count`` random elements as a tuple.
basis = tuple( s.change_ring(field) for s in basis )
self._basis_normalizers = tuple(
~(self.natural_inner_product(s,s).sqrt()) for s in basis )
- basis = tuple(s*c for (s,c) in izip(basis,self._basis_normalizers))
+ basis = tuple(s*c for (s,c) in zip(basis,self._basis_normalizers))
Qs = self.multiplication_table_from_matrix_basis(basis)
# with had entries in a nice field.
return super(MatrixEuclideanJordanAlgebra, self)._charpoly_coeff(i)
else:
- basis = ( (b/n) for (b,n) in izip(self.natural_basis(),
- self._basis_normalizers) )
+ basis = ( (b/n) for (b,n) in zip(self.natural_basis(),
+ self._basis_normalizers) )
# Do this over the rationals and convert back at the end.
J = MatrixEuclideanJordanAlgebra(QQ,
(_,x,_,_) = J._charpoly_matrix_system()
p = J._charpoly_coeff(i)
# p might be missing some vars, have to substitute "optionally"
- pairs = izip(x.base_ring().gens(), self._basis_normalizers)
+ pairs = zip(x.base_ring().gens(), self._basis_normalizers)
substitutions = { v: v*c for (v,c) in pairs }
result = p.subs(substitutions)