Skip to content

Commit

Permalink
Implementation of faithful repr of a Lie algebra in char p > 0.
Browse files Browse the repository at this point in the history
  • Loading branch information
tscrim committed Apr 10, 2024
1 parent 643d320 commit 9c56ea5
Show file tree
Hide file tree
Showing 2 changed files with 252 additions and 4 deletions.
239 changes: 239 additions & 0 deletions src/sage/algebras/lie_algebras/representation.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
17 changes: 13 additions & 4 deletions src/sage/categories/finite_dimensional_lie_algebras_with_basis.py
Original file line number Diff line number Diff line change
Expand Up @@ -1939,15 +1939,15 @@ 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`
* ``'minimal'`` -- construct the minimal representation (for
precise details, see the documentation of
:class:`~sage.algebras.lie_algebras.representation.FaithfulRepresentationNilpotentPBW`)
Solvable but not nilpotent:
Solvable:
* Not implemented
Expand All @@ -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::
Expand Down Expand Up @@ -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))

Expand Down

0 comments on commit 9c56ea5

Please sign in to comment.