From 9c56ea54bd4ec94229c5003bf6a33bc242391cd8 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 9 Apr 2024 10:57:53 +0900 Subject: [PATCH] Implementation of faithful repr of a Lie algebra in char p > 0. --- .../algebras/lie_algebras/representation.py | 239 ++++++++++++++++++ ...ite_dimensional_lie_algebras_with_basis.py | 17 +- 2 files changed, 252 insertions(+), 4 deletions(-) diff --git a/src/sage/algebras/lie_algebras/representation.py b/src/sage/algebras/lie_algebras/representation.py index c6bd62dd0cc..98f2e90fcfd 100644 --- a/src/sage/algebras/lie_algebras/representation.py +++ b/src/sage/algebras/lie_algebras/representation.py @@ -791,3 +791,242 @@ def _acted_upon_(self, scalar, self_on_left=False): return P._project(P._to_pbw(scalar) * self._lift_pbw()) return super()._acted_upon_(scalar, self_on_left) + + +class FaithfulRepresentationPBWPosChar(CombinatorialFreeModule, Representation_abstract): + r""" + A faithful representation of a finite dimensional Lie algebra + in positive characteristic. + + .. WARNING:: + + This is often a very large dimensional representation relative + to the dimension of the Lie algebra. + + ALGORITHM: + + We implement the algorithm given in [deG2000] Section 6.6. Let `L` + be a finite dimensional Lie algebra over a ring of characteristic `p` + with basis `(b_1, \ldots, b_n)`. We compute (monic) `p`-polynomials + `f_i` such that `A = \mathrm{ad}(b_i)` solves `f_i(A) = 0` by using + minimal polynomial of `A`. The `(f_1, \ldots, f_n)` is a Gröbner basis + for an ideal `I` of the universal enveloping algebra `U(L)` such that + the quotient `U(L) / I` is a faithful representation of `L`. + + EXAMPLES:: + + sage: sl2 = LieAlgebra(GF(3), cartan_type=['A',1]) + sage: F = sl2.faithful_representation() + sage: F + Faithful representation with p-multiplicies (1, 3, 1) of Lie algebra + of ['A', 1] in the Chevalley basis + sage: F.dimension() + 243 + """ + def __init__(self, L): + r""" + Initialize ``self``. + + EXAMPLES:: + + sage: sl2 = LieAlgebra(GF(3), cartan_type=['A',1]) + sage: F = sl2.faithful_representation() + sage: TestSuite(F).run() + """ + R = L.base_ring() + self._p = R.characteristic() + if self._p == 0: + raise ValueError("the Lie algebra must be over a ring of positive characteristic") + + self._pbw = L.pbw_basis() + self._key_order = tuple(self._pbw.algebra_generators().keys()) + + # calculate the Gröbner basis and p-exponents + gb = [] + p_exp = [] + B = L.basis() + for k in self._key_order: + b = B[k] + ad = b.adjoint_matrix() + g = ad.minpoly() + d = g.degree() + # TODO: Use the sparse polynomial ring? + x = g.parent().gen() + r = [x**(self._p**i) % g for i in range(d+1)] + deg = max(ri.degree() for ri in r) + mat = matrix(R, [[ri[j] for ri in r] for j in range(deg+1)]) + la = mat.right_kernel_matrix()[0] + if la: + mongen = self._pbw._indices.monoid_generators()[k] + gb.append(self._pbw._from_dict({mongen ** (self._p ** i): val + for i, val in enumerate(la) if val}, + remove_zeros=False)) + p_exp.append(max(la.support())) + + self._groebner_basis = gb + self._p_exp = tuple(p_exp) + self._degrees = [self._p ** m for m in self._p_exp] + + from sage.groups.abelian_gps.abelian_group import AbelianGroup + indices = AbelianGroup(self._degrees) + + Representation_abstract.__init__(self, L) + CombinatorialFreeModule.__init__(self, R, indices, prefix='', bracket=False) + + def _repr_(self): + r""" + Return a string representation of ``self``. + + EXAMPLES:: + + sage: sl3 = LieAlgebra(GF(3), cartan_type=['A',2]) + sage: sl3.faithful_representation() + Faithful representation with p-multiplicies (1, 1, 1, 3, 3, 1, 1, 1) + of Lie algebra of ['A', 2] in the Chevalley basis + """ + return "Faithful representation with p-multiplicies {} of {}".format(self.p_exponents(), self._lie_algebra) + + def _latex_(self): + r""" + Return a string representation of ``self``. + + EXAMPLES:: + + sage: sl2 = LieAlgebra(GF(3), cartan_type=['A',1]) + sage: latex(sl2.faithful_representation()) + U(\mathfrak{g}(A_{1})_{\Bold{F}_{3}}) / \langle PBW_{\alpha_{1}}^{3}, + 2 PBW_{\alpha^\vee_{1}}^{27} + PBW_{\alpha^\vee_{1}}, + PBW_{-\alpha_{1}}^{3} \rangle + """ + from sage.misc.latex import latex + g = latex(self._lie_algebra) + data = ', '.join(latex(f) for f in self._groebner_basis) + return "U({}) / \\langle {} \\rangle".format(g, data) + + @cached_method + def p_exponents(self): + """ + Return the `p`-exponents of ``self``. + + Let `p` be the characteristic of the base ring of ``self`. + The `p`-*exponents* are the exponents `m_i` such that the `i`-th + `p`-polynomial `f_i` is of degree `p^{m_i}`. + + EXAMPLES:: + + sage: sp4 = LieAlgebra(GF(3), cartan_type=['C',2]) + sage: F = sp4.faithful_representation() + sage: F.p_exponents() + (1, 1, 1, 1, 3, 3, 1, 1, 1, 1) + """ + return self._p_exp + + def groebner_basis(self): + """ + Return the defining Gröbner basis of ``self``. + + EXAMPLES:: + + sage: sp4 = LieAlgebra(GF(3), cartan_type=['C',2]) + sage: F = sp4.faithful_representation() + sage: F.groebner_basis() + [PBW[alpha[2]]^3, + PBW[alpha[1]]^3, + PBW[alpha[1] + alpha[2]]^3, + PBW[2*alpha[1] + alpha[2]]^3, + 2*PBW[alphacheck[1]]^27 + PBW[alphacheck[1]], + 2*PBW[alphacheck[2]]^27 + PBW[alphacheck[2]], + PBW[-alpha[2]]^3, + PBW[-alpha[1]]^3, + PBW[-alpha[1] - alpha[2]]^3, + PBW[-2*alpha[1] - alpha[2]]^3] + """ + return self._groebner_basis + + def _project(self, x): + r""" + The projection to ``self`` from the PBW basis. + + EXAMPLES:: + + sage: sl2 = LieAlgebra(GF(3), cartan_type=['A',1]) + sage: F = sl2.faithful_representation() + sage: PBW = F._pbw + sage: elt = PBW.an_element(); elt + PBW[alpha[1]]^2*PBW[alphacheck[1]]^2*PBW[-alpha[1]]^3 + + 2*PBW[alpha[1]] + 1 + sage: F._project(elt) + 1 + 2*f0 + sage: F._project(elt^2) + 1 + f0 + f0^2 + sage: F._project(elt^3) + 1 + + sage: elt = PBW(sum(sl2.basis())); elt + PBW[alpha[1]] + PBW[alphacheck[1]] + PBW[-alpha[1]] + sage: F._project(elt) + f2 + f1 + f0 + sage: F._project(elt^2) + 2*f2 + f2^2 + 2*f1 + 2*f1*f2 + f1^2 + 2*f0 + 2*f0*f2 + 2*f0*f1 + f0^2 + sage: F._project(elt^3) + 2*f2 + f1 + f1^3 + 2*f0 + sage: F._project(elt^4) + f2 + 2*f2^2 + f1 + f1^2 + f1^3*f2 + f1^4 + f0 + f0*f2 + f0*f1^3 + 2*f0^2 + """ + reduction = True + while reduction: + reduction = False + mc = x._monomial_coefficients + for m, c in mc.items(): + d = m.dict() + for k, e, g in zip(self._key_order, self._degrees, self._groebner_basis): + if k not in d: + continue + if d[k] >= e: + d[k] -= e + x -= self._pbw.monomial(self._pbw._indices(d)) * g + reduction = True + break + data = {} + for m, c in x._monomial_coefficients.items(): + d = m.dict() + data[self._indices([d.get(k, 0) for k in self._key_order])] = c + return self.element_class(self, data) + + class Element(CombinatorialFreeModule.Element): + def _acted_upon_(self, scalar, self_on_left=False): + r""" + Return the action of ``scalar`` on ``self``. + + EXAMPLES:: + + sage: sl2 = LieAlgebra(GF(3), cartan_type=['A',1]) + sage: F = sl2.faithful_representation() + sage: v = F.an_element(); v + 1 + 2*f2 + f0*f1*f2 + sage: sl2.an_element() * v + f2 + 2*f2^2 + f1 + 2*f1*f2 + 2*f1^2*f2 + f0 + 2*f0*f2 + 2*f0*f2^2 + + 2*f0*f1*f2 + f0*f1*f2^2 + f0*f1^2*f2 + f0^2*f1*f2 + sage: sl2.pbw_basis().an_element() * v + 1 + 2*f2 + 2*f0 + f0*f2 + f0*f1*f2 + 2*f0^2*f1*f2 + sage: 5 * v + 2 + f2 + 2*f0*f1*f2 + sage: v * 5 + 2 + f2 + 2*f0*f1*f2 + sage: v._acted_upon_(sl2.an_element(), True) is None + True + """ + P = self.parent() + if scalar in P._lie_algebra or scalar in P._pbw: + if self_on_left: + return None + if not self: # we are (already) the zero vector + return self + scalar = P._pbw(scalar) + monoid = P._pbw._indices + I = P._key_order + lift = P._pbw.element_class(P._pbw, {monoid(list(zip(I, m.exponents()))): coeff + for m, coeff in self._monomial_coefficients.items()}) + return P._project(scalar * lift) + + return super()._acted_upon_(scalar, self_on_left) diff --git a/src/sage/categories/finite_dimensional_lie_algebras_with_basis.py b/src/sage/categories/finite_dimensional_lie_algebras_with_basis.py index 63a9ef29bc4..cf2754fd4ec 100644 --- a/src/sage/categories/finite_dimensional_lie_algebras_with_basis.py +++ b/src/sage/categories/finite_dimensional_lie_algebras_with_basis.py @@ -1939,7 +1939,7 @@ def faithful_representation(self, algorithm=None): - ``algorithm`` -- one of the following depending on the classification of the Lie algebra: - Nilpotent Lie algebras: + Nilpotent: * ``'regular'`` -- use the universal enveloping algebra quotient :class:`~sage.algebras.lie_algebras.representation.FaithfulRepresentationNilpotentPBW` @@ -1947,7 +1947,7 @@ def faithful_representation(self, algorithm=None): precise details, see the documentation of :class:`~sage.algebras.lie_algebras.representation.FaithfulRepresentationNilpotentPBW`) - Solvable but not nilpotent: + Solvable: * Not implemented @@ -1957,7 +1957,13 @@ def faithful_representation(self, algorithm=None): General case - * Not implemented + * ``'generic'`` -- generic algortihm (only implemented currently + for positive characteristic) + + Note that the algorithm for any more generic cases can be used + in the specialized cases. For instance, using ``'generic'`` for + any Lie algebra (e.g., even if nilpotent) will use the generic + implementation. EXAMPLES:: @@ -2007,7 +2013,10 @@ def faithful_representation(self, algorithm=None): if algorithm == "minimal": from sage.algebras.lie_algebras.representation import FaithfulRepresentationNilpotentPBW return FaithfulRepresentationNilpotentPBW(self, minimal=True) - else: + if algorithm is None or algorithm == "generic": + if self.base_ring().characteristic() > 0: + from sage.algebras.lie_algebras.representation import FaithfulRepresentationPBWPosChar + return FaithfulRepresentationPBWPosChar(self) raise NotImplementedError("only implemented for nilpotent Lie algebras") raise ValueError("invalid algorithm '{}'".format(algorithm))