X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=mjo%2Feja%2Feja_algebra.py;h=d012dd86c09a0596933059d1a43d7aca55e5d9a2;hb=5631bdae846420eb81bd193e2b568abb2d31af4b;hp=631d695aa75208a65cb457a4ca11280f44823765;hpb=76352ef33974a5ec638b8b1fcab5508f915ea976;p=sage.d.git diff --git a/mjo/eja/eja_algebra.py b/mjo/eja/eja_algebra.py index 631d695..d012dd8 100644 --- a/mjo/eja/eja_algebra.py +++ b/mjo/eja/eja_algebra.py @@ -84,25 +84,34 @@ class FiniteDimensionalEJA(CombinatorialFreeModule): INPUT: - - basis -- a tuple of basis elements in "matrix form," which - must be the same form as the arguments to ``jordan_product`` - and ``inner_product``. In reality, "matrix form" can be either - vectors, matrices, or a Cartesian product (ordered tuple) - of vectors or matrices. All of these would ideally be vector - spaces in sage with no special-casing needed; but in reality - we turn vectors into column-matrices and Cartesian products - `(a,b)` into column matrices `(a,b)^{T}` after converting - `a` and `b` themselves. - - - jordan_product -- function of two ``basis`` elements (in - matrix form) that returns their jordan product, also in matrix - form; this will be applied to ``basis`` to compute a - multiplication table for the algebra. - - - inner_product -- function of two ``basis`` elements (in matrix - form) that returns their inner product. This will be applied - to ``basis`` to compute an inner-product table (basically a - matrix) for this algebra. + - ``basis`` -- a tuple; a tuple of basis elements in "matrix + form," which must be the same form as the arguments to + ``jordan_product`` and ``inner_product``. In reality, "matrix + form" can be either vectors, matrices, or a Cartesian product + (ordered tuple) of vectors or matrices. All of these would + ideally be vector spaces in sage with no special-casing + needed; but in reality we turn vectors into column-matrices + and Cartesian products `(a,b)` into column matrices + `(a,b)^{T}` after converting `a` and `b` themselves. + + - ``jordan_product`` -- a function; afunction of two ``basis`` + elements (in matrix form) that returns their jordan product, + also in matrix form; this will be applied to ``basis`` to + compute a multiplication table for the algebra. + + - ``inner_product`` -- a function; a function of two ``basis`` + elements (in matrix form) that returns their inner + product. This will be applied to ``basis`` to compute an + inner-product table (basically a matrix) for this algebra. + + - ``field`` -- a subfield of the reals (default: ``AA``); the scalar + field for the algebra. + + - ``orthonormalize`` -- boolean (default: ``True``); whether or + not to orthonormalize the basis. Doing so is expensive and + generally rules out using the rationals as your ``field``, but + is required for spectral decompositions. + """ Element = FiniteDimensionalEJAElement @@ -169,7 +178,8 @@ class FiniteDimensionalEJA(CombinatorialFreeModule): category = MagmaticAlgebras(field).FiniteDimensional() - category = category.WithBasis().Unital() + category = category.WithBasis().Unital().Commutative() + if associative: # Element subalgebras can take advantage of this. category = category.Associative() @@ -413,6 +423,18 @@ class FiniteDimensionalEJA(CombinatorialFreeModule): """ return "Associative" in self.category().axioms() + def _is_commutative(self): + r""" + Whether or not this algebra's multiplication table is commutative. + + This method should of course always return ``True``, unless + this algebra was constructed with ``check_axioms=False`` and + passed an invalid multiplication table. + """ + return all( self.product_on_basis(i,j) == self.product_on_basis(i,j) + for i in range(self.dimension()) + for j in range(self.dimension()) ) + def _is_jordanian(self): r""" Whether or not this algebra's multiplication table respects the @@ -420,7 +442,7 @@ class FiniteDimensionalEJA(CombinatorialFreeModule): We only check one arrangement of `x` and `y`, so for a ``True`` result to be truly true, you should also check - :meth:`is_commutative`. This method should of course always + :meth:`_is_commutative`. This method should of course always return ``True``, unless this algebra was constructed with ``check_axioms=False`` and passed an invalid multiplication table. """ @@ -430,6 +452,81 @@ class FiniteDimensionalEJA(CombinatorialFreeModule): for i in range(self.dimension()) for j in range(self.dimension()) ) + def _jordan_product_is_associative(self): + r""" + Return whether or not this algebra's Jordan product is + associative; that is, whether or not `x*(y*z) = (x*y)*z` + for all `x,y,x`. + + This method should agree with :meth:`is_associative` unless + you lied about the value of the ``associative`` parameter + when you constructed the algebra. + + SETUP:: + + sage: from mjo.eja.eja_algebra import (RealSymmetricEJA, + ....: ComplexHermitianEJA, + ....: QuaternionHermitianEJA) + + EXAMPLES:: + + sage: J = RealSymmetricEJA(4, orthonormalize=False) + sage: J._jordan_product_is_associative() + False + sage: x = sum(J.gens()) + sage: A = x.subalgebra_generated_by() + sage: A._jordan_product_is_associative() + True + + :: + + sage: J = ComplexHermitianEJA(2,field=QQ,orthonormalize=False) + sage: J._jordan_product_is_associative() + False + sage: x = sum(J.gens()) + sage: A = x.subalgebra_generated_by(orthonormalize=False) + sage: A._jordan_product_is_associative() + True + + :: + + sage: J = QuaternionHermitianEJA(2) + sage: J._jordan_product_is_associative() + False + sage: x = sum(J.gens()) + sage: A = x.subalgebra_generated_by() + sage: A._jordan_product_is_associative() + True + + """ + R = self.base_ring() + + # Used to check whether or not something is zero. + epsilon = R.zero() + if not R.is_exact(): + # I don't know of any examples that make this magnitude + # necessary because I don't know how to make an + # associative algebra when the element subalgebra + # construction is unreliable (as it is over RDF; we can't + # find the degree of an element because we can't compute + # the rank of a matrix). But even multiplication of floats + # is non-associative, so *some* epsilon is needed... let's + # just take the one from _inner_product_is_associative? + epsilon = 1e-15 + + for i in range(self.dimension()): + for j in range(self.dimension()): + for k in range(self.dimension()): + x = self.gens()[i] + y = self.gens()[j] + z = self.gens()[k] + diff = (x*y)*z - x*(y*z) + + if diff.norm() > epsilon: + return False + + return True + def _inner_product_is_associative(self): r""" Return whether or not this algebra's inner product `B` is @@ -439,11 +536,14 @@ class FiniteDimensionalEJA(CombinatorialFreeModule): this algebra was constructed with ``check_axioms=False`` and passed an invalid Jordan or inner-product. """ + R = self.base_ring() - # Used to check whether or not something is zero in an inexact - # ring. This number is sufficient to allow the construction of - # QuaternionHermitianEJA(2, field=RDF) with check_axioms=True. - epsilon = 1e-16 + # Used to check whether or not something is zero. + epsilon = R.zero() + if not R.is_exact(): + # This choice is sufficient to allow the construction of + # QuaternionHermitianEJA(2, field=RDF) with check_axioms=True. + epsilon = 1e-15 for i in range(self.dimension()): for j in range(self.dimension()): @@ -453,12 +553,8 @@ class FiniteDimensionalEJA(CombinatorialFreeModule): z = self.gens()[k] diff = (x*y).inner_product(z) - x.inner_product(y*z) - if self.base_ring().is_exact(): - if diff != 0: - return False - else: - if diff.abs() > epsilon: - return False + if diff.abs() > epsilon: + return False return True @@ -505,18 +601,13 @@ class FiniteDimensionalEJA(CombinatorialFreeModule): TESTS: - Ensure that we can convert any element of the two non-matrix - simple algebras (whose matrix representations are columns) - back and forth faithfully:: + Ensure that we can convert any element back and forth + faithfully between its matrix and algebra representations:: sage: set_random_seed() - sage: J = HadamardEJA.random_instance() - sage: x = J.random_element() - sage: J(x.to_vector().column()) == x - True - sage: J = JordanSpinEJA.random_instance() + sage: J = random_eja() sage: x = J.random_element() - sage: J(x.to_vector().column()) == x + sage: J(x.to_matrix()) == x True We cannot coerce elements between algebras just because their @@ -532,7 +623,6 @@ 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(): @@ -1767,9 +1857,9 @@ class RealSymmetricEJA(ConcreteEJA, RealMatrixEJA): In theory, our "field" can be any subfield of the reals:: - sage: RealSymmetricEJA(2, field=RDF) + sage: RealSymmetricEJA(2, field=RDF, check_axioms=True) Euclidean Jordan algebra of dimension 3 over Real Double Field - sage: RealSymmetricEJA(2, field=RR) + sage: RealSymmetricEJA(2, field=RR, check_axioms=True) Euclidean Jordan algebra of dimension 3 over Real Field with 53 bits of precision @@ -2035,9 +2125,9 @@ class ComplexHermitianEJA(ConcreteEJA, ComplexMatrixEJA): In theory, our "field" can be any subfield of the reals:: - sage: ComplexHermitianEJA(2, field=RDF) + sage: ComplexHermitianEJA(2, field=RDF, check_axioms=True) Euclidean Jordan algebra of dimension 4 over Real Double Field - sage: ComplexHermitianEJA(2, field=RR) + sage: ComplexHermitianEJA(2, field=RR, check_axioms=True) Euclidean Jordan algebra of dimension 4 over Real Field with 53 bits of precision @@ -2332,9 +2422,9 @@ class QuaternionHermitianEJA(ConcreteEJA, QuaternionMatrixEJA): In theory, our "field" can be any subfield of the reals:: - sage: QuaternionHermitianEJA(2, field=RDF) + sage: QuaternionHermitianEJA(2, field=RDF, check_axioms=True) Euclidean Jordan algebra of dimension 6 over Real Double Field - sage: QuaternionHermitianEJA(2, field=RR) + sage: QuaternionHermitianEJA(2, field=RR, check_axioms=True) Euclidean Jordan algebra of dimension 6 over Real Field with 53 bits of precision