from sage.modules.free_module import VectorSpace
from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement
-from mjo.eja.eja_operator import FiniteDimensionalEJAOperator
+from mjo.eja.eja_operator import EJAOperator
from mjo.eja.eja_utils import _scale
-class FiniteDimensionalEJAElement(IndexedFreeModuleElement):
+class EJAElement(IndexedFreeModuleElement):
"""
An element of a Euclidean Jordan algebra.
"""
P = self.parent()
left_mult_by_self = lambda y: self*y
L = P.module_morphism(function=left_mult_by_self, codomain=P)
- return FiniteDimensionalEJAOperator(P, P, L.matrix() )
+ return EJAOperator(P, P, L.matrix() )
def quadratic_representation(self, other=None):
if self.is_nilpotent():
raise ValueError("this only works with non-nilpotent elements!")
- J = self.subalgebra_generated_by()
+ # The subalgebra is transient (we return an element of the
+ # superalgebra, i.e. this algebra) so why bother
+ # orthonormalizing?
+ J = self.subalgebra_generated_by(orthonormalize=False)
u = J(self)
# The image of the matrix of left-u^m-multiplication
# subspace... or do we? Can't we just solve, knowing that
# A(c) = u^(s+1) should have a solution in the big space,
# too?
- #
- # Beware, solve_right() means that we're using COLUMN vectors.
- # Our FiniteDimensionalAlgebraElement superclass uses rows.
u_next = u**(s+1)
A = u_next.operator().matrix()
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.
+ # Now c is the idempotent we want, but it still lives in
+ # the subalgebra.
return c.superalgebra_element()
return self.trace_inner_product(self).sqrt()
-class CartesianProductEJAElement(FiniteDimensionalEJAElement):
- def det(self):
- r"""
- Compute the determinant of this product-element using the
- determianants of its factors.
-
- This result Follows from the spectral decomposition of (say)
- the pair `(x,y)` in terms of the Jordan frame `\left\{ (c_1,
- 0),(c_2, 0),...,(0,d_1),(0,d_2),... \right\}.
- """
- from sage.misc.misc_c import prod
- return prod( f.det() for f in self.cartesian_factors() )
+class CartesianProductParentEJAElement(EJAElement):
+ r"""
+ An intermediate class for elements that have a Cartesian
+ product as their parent algebra.
+ This is needed because the ``to_matrix`` method (which gives you a
+ representation from the superalgebra) needs to do special stuff
+ for Cartesian products. Specifically, an EJA subalgebra of a
+ Cartesian product EJA will not itself be a Cartesian product (it
+ has its own basis) -- but we want ``to_matrix()`` to be able to
+ give us a Cartesian product representation.
+ """
def to_matrix(self):
# An override is necessary to call our custom _scale().
B = self.parent().matrix_basis()
# Aaaaand linear combinations don't work in Cartesian
# product spaces, even though they provide a method with
- # that name. This is hidden behind an "if" because the
+ # that name. This is hidden in a subclass because the
# _scale() function is slow.
pairs = zip(B, self.to_vector())
return W.sum( _scale(b, alpha) for (b,alpha) in pairs )
+
+class CartesianProductEJAElement(CartesianProductParentEJAElement):
+ def det(self):
+ r"""
+ Compute the determinant of this product-element using the
+ determianants of its factors.
+
+ This result Follows from the spectral decomposition of (say)
+ the pair `(x,y)` in terms of the Jordan frame `\left\{ (c_1,
+ 0),(c_2, 0),...,(0,d_1),(0,d_2),... \right\}.
+ """
+ from sage.misc.misc_c import prod
+ return prod( f.det() for f in self.cartesian_factors() )