X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=mjo%2Feja%2Feja_algebra.py;h=79187594472d82e24a0b700305b7ddfc7b192536;hb=b259821a73cb75a6d5a81d13256802be023b0fa9;hp=5e2c315adbe7730cd7c25f9947ac8ff426f00611;hpb=fd6a4ce03de36bb2551160e08440b0c0049746e1;p=sage.d.git diff --git a/mjo/eja/eja_algebra.py b/mjo/eja/eja_algebra.py index 5e2c315..7918759 100644 --- a/mjo/eja/eja_algebra.py +++ b/mjo/eja/eja_algebra.py @@ -170,6 +170,17 @@ from mjo.eja.eja_element import FiniteDimensionalEJAElement from mjo.eja.eja_operator import FiniteDimensionalEJAOperator from mjo.eja.eja_utils import _all2list, _mat2vec +def EuclideanJordanAlgebras(field): + r""" + The category of Euclidean Jordan algebras over ``field``, which + must be a subfield of the real numbers. For now this is just a + convenient wrapper around all of the other category axioms that + apply to all EJAs. + """ + category = MagmaticAlgebras(field).FiniteDimensional() + category = category.WithBasis().Unital().Commutative() + return category + class FiniteDimensionalEJA(CombinatorialFreeModule): r""" A finite-dimensional Euclidean Jordan algebra. @@ -228,6 +239,26 @@ class FiniteDimensionalEJA(CombinatorialFreeModule): """ Element = FiniteDimensionalEJAElement + @staticmethod + def _check_input_field(field): + if not field.is_subring(RR): + # Note: this does return true for the real algebraic + # field, the rationals, and any quadratic field where + # we've specified a real embedding. + raise ValueError("scalar field is not real") + + @staticmethod + def _check_input_axioms(basis, jordan_product, inner_product): + if not all( jordan_product(bi,bj) == jordan_product(bj,bi) + for bi in basis + for bj in basis ): + raise ValueError("Jordan product is not commutative") + + if not all( inner_product(bi,bj) == inner_product(bj,bi) + for bi in basis + for bj in basis ): + raise ValueError("inner-product is not commutative") + def __init__(self, basis, jordan_product, @@ -244,30 +275,14 @@ class FiniteDimensionalEJA(CombinatorialFreeModule): n = len(basis) if check_field: - if not field.is_subring(RR): - # Note: this does return true for the real algebraic - # field, the rationals, and any quadratic field where - # we've specified a real embedding. - raise ValueError("scalar field is not real") + self._check_input_field(field) if check_axioms: # Check commutativity of the Jordan and inner-products. # This has to be done before we build the multiplication # and inner-product tables/matrices, because we take # advantage of symmetry in the process. - if not all( jordan_product(bi,bj) == jordan_product(bj,bi) - for bi in basis - for bj in basis ): - raise ValueError("Jordan product is not commutative") - - if not all( inner_product(bi,bj) == inner_product(bj,bi) - for bi in basis - for bj in basis ): - raise ValueError("inner-product is not commutative") - - - category = MagmaticAlgebras(field).FiniteDimensional() - category = category.WithBasis().Unital().Commutative() + self._check_input_axioms(basis, jordan_product, inner_product) if n <= 1: # All zero- and one-dimensional algebras are just the real @@ -286,6 +301,8 @@ class FiniteDimensionalEJA(CombinatorialFreeModule): for bj in basis for bk in basis) + category = EuclideanJordanAlgebras(field) + if associative: # Element subalgebras can take advantage of this. category = category.Associative() @@ -690,8 +707,8 @@ class FiniteDimensionalEJA(CombinatorialFreeModule): def _element_constructor_(self, elt): """ - Construct an element of this algebra from its vector or matrix - representation. + Construct an element of this algebra or a subalgebra from its + EJA element, vector, or matrix representation. This gets called only after the parent element _call_ method fails to find a coercion for the argument. @@ -730,6 +747,16 @@ class FiniteDimensionalEJA(CombinatorialFreeModule): sage: J( (J1.matrix_basis()[1], J2.matrix_basis()[2]) ) b1 + b5 + Subalgebra elements are embedded into the superalgebra:: + + sage: J = JordanSpinEJA(3) + sage: J.one() + b0 + sage: x = sum(J.gens()) + sage: A = x.subalgebra_generated_by() + sage: J(A.one()) + b0 + TESTS: Ensure that we can convert any element back and forth @@ -754,6 +781,7 @@ class FiniteDimensionalEJA(CombinatorialFreeModule): Traceback (most recent call last): ... ValueError: not an element of this algebra + """ msg = "not an element of this algebra" if elt in self.base_ring(): @@ -763,13 +791,16 @@ class FiniteDimensionalEJA(CombinatorialFreeModule): # that the integer 3 belongs to the space of 2-by-2 matrices. raise ValueError(msg) - try: - # Try to convert a vector into a column-matrix... + if hasattr(elt, 'superalgebra_element'): + # Handle subalgebra elements + if elt.parent().superalgebra() == self: + return elt.superalgebra_element() + + if hasattr(elt, 'sparse_vector'): + # Convert a vector into a column-matrix. We check for + # "sparse_vector" and not "column" because matrices also + # have a "column" method. elt = elt.column() - except (AttributeError, TypeError): - # and ignore failure, because we weren't really expecting - # a vector as an argument anyway. - pass if elt not in self.matrix_space(): raise ValueError(msg) @@ -1395,7 +1426,7 @@ class FiniteDimensionalEJA(CombinatorialFreeModule): # 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 = self.subalgebra(()) + trivial = self.subalgebra((), check_axioms=False) J0 = trivial # eigenvalue zero J5 = VectorSpace(self.base_ring(), 0) # eigenvalue one-half J1 = trivial # eigenvalue one