From 40fe88c9c758ef6468bf67acd6da9c4333b755f9 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Mon, 29 Jul 2019 21:12:05 -0400 Subject: [PATCH] eja: begin moving the associative subalgebra stuff into its own class. --- mjo/eja/eja_subalgebra.py | 182 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 mjo/eja/eja_subalgebra.py diff --git a/mjo/eja/eja_subalgebra.py b/mjo/eja/eja_subalgebra.py new file mode 100644 index 0000000..7c883d9 --- /dev/null +++ b/mjo/eja/eja_subalgebra.py @@ -0,0 +1,182 @@ +from sage.matrix.constructor import matrix +from sage.structure.category_object import normalize_names + +from mjo.eja.eja_algebra import FiniteDimensionalEuclideanJordanAlgebra +from mjo.eja.eja_element import FiniteDimensionalEuclideanJordanAlgebraElement + + +class FiniteDimensionalEuclideanJordanElementSubalgebra(FiniteDimensionalEuclideanJordanAlgebra): + """ + The subalgebra of an EJA generated by a single element. + """ + @staticmethod + def __classcall_private__(cls, elt): + superalgebra = elt.parent() + + # First compute the vector subspace spanned by the powers of + # the given element. + V = superalgebra.vector_space() + eja_basis = [superalgebra.one()] + basis_vectors = [superalgebra.one().vector()] + W = V.span_of_basis(basis_vectors) + for exponent in range(1, V.dimension()): + new_power = elt**exponent + basis_vectors.append( new_power.vector() ) + try: + W = V.span_of_basis(basis_vectors) + eja_basis.append( new_power ) + except ValueError: + # Vectors weren't independent; bail and keep the + # last subspace that worked. + break + + # Make the basis hashable for UniqueRepresentation. + eja_basis = tuple(eja_basis) + + # Now figure out the entries of the right-multiplication + # matrix for the successive basis elements b0, b1,... of + # that subspace. + F = superalgebra.base_ring() + mult_table = [] + for b_right in eja_basis: + b_right_rows = [] + # The first row of the right-multiplication matrix by + # b1 is what we get if we apply that matrix to b1. The + # second row of the right multiplication matrix by b1 + # is what we get when we apply that matrix to b2... + # + # IMPORTANT: this assumes that all vectors are COLUMN + # vectors, unlike our superclass (which uses row vectors). + for b_left in eja_basis: + # Multiply in the original EJA, but then get the + # coordinates from the subalgebra in terms of its + # basis. + this_row = W.coordinates((b_left*b_right).vector()) + b_right_rows.append(this_row) + b_right_matrix = matrix(F, b_right_rows) + mult_table.append(b_right_matrix) + + for m in mult_table: + m.set_immutable() + mult_table = tuple(mult_table) + + # The rank is the highest possible degree of a minimal + # polynomial, and is bounded above by the dimension. We know + # in this case that there's an element whose minimal + # polynomial has the same degree as the space's dimension + # (remember how we constructed the space?), so that must be + # its rank too. + rank = W.dimension() + + # EJAs are power-associative, and this algebra is nothin but + # powers. + assume_associative=True + + # TODO: Un-hard-code this. It should be possible to get the "next" + # name based on the parent's generator names. + names = 'f' + names = normalize_names(W.dimension(), names) + + cat = superalgebra.category().Associative() + + # TODO: compute this and actually specify it. + natural_basis = None + + fdeja = super(FiniteDimensionalEuclideanJordanElementSubalgebra, cls) + return fdeja.__classcall__(cls, + F, + mult_table, + rank, + eja_basis, + W, + assume_associative=assume_associative, + names=names, + category=cat, + natural_basis=natural_basis) + + def __init__(self, + field, + mult_table, + rank, + eja_basis, + vector_space, + assume_associative=True, + names='f', + category=None, + natural_basis=None): + + self._superalgebra = eja_basis[0].parent() + self._vector_space = vector_space + self._eja_basis = eja_basis + + fdeja = super(FiniteDimensionalEuclideanJordanElementSubalgebra, self) + fdeja.__init__(field, + mult_table, + rank, + assume_associative=assume_associative, + names=names, + category=category, + natural_basis=natural_basis) + + + def vector_space(self): + """ + SETUP:: + + sage: from mjo.eja.eja_algebra import RealSymmetricEJA + sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra + + EXAMPLES:: + + sage: J = RealSymmetricEJA(3) + sage: x = sum( i*J.gens()[i] for i in range(6) ) + sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x) + sage: K.vector_space() + Vector space of degree 6 and dimension 3 over Rational Field + User basis matrix: + [ 1 0 0 1 0 1] + [ 0 1 2 3 4 5] + [ 5 11 14 26 34 45] + sage: (x^0).vector() + (1, 0, 0, 1, 0, 1) + sage: (x^1).vector() + (0, 1, 2, 3, 4, 5) + sage: (x^2).vector() + (5, 11, 14, 26, 34, 45) + + """ + return self._vector_space + + + class Element(FiniteDimensionalEuclideanJordanAlgebraElement): + def __init__(self, A, elt=None): + """ + SETUP:: + + sage: from mjo.eja.eja_algebra import RealSymmetricEJA + sage: from mjo.eja.eja_subalgebra import FiniteDimensionalEuclideanJordanElementSubalgebra + + EXAMPLES:: + + sage: J = RealSymmetricEJA(3) + sage: x = sum( i*J.gens()[i] for i in range(6) ) + sage: K = FiniteDimensionalEuclideanJordanElementSubalgebra(x) + sage: [ K(x^k) for k in range(J.rank()) ] + [f0, f1, f2] + + :: + + """ + if elt in A._superalgebra: + # Try to convert a parent algebra element into a + # subalgebra element... + try: + coords = A.vector_space().coordinates(elt.vector()) + elt = A(coords) + except AttributeError: + # Catches a missing method in elt.vector() + pass + + FiniteDimensionalEuclideanJordanAlgebraElement.__init__(self, + A, + elt) -- 2.44.2