Skip to content

Commit

Permalink
Adding hypercenter and upper central series; improve generic example;…
Browse files Browse the repository at this point in the history
… fixing some bugs.
  • Loading branch information
tscrim committed Mar 29, 2024
1 parent b693ea9 commit 02b2233
Show file tree
Hide file tree
Showing 5 changed files with 301 additions and 82 deletions.
28 changes: 23 additions & 5 deletions src/sage/algebras/lie_algebras/quotient.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,11 @@ def __classcall_private__(cls, I, ambient=None, names=None,
index_set = [i for i in sorted_indices if i not in I_supp]

if names is None:
amb_names = dict(zip(sorted_indices, ambient.variable_names()))
names = [amb_names[i] for i in index_set]
try:
amb_names = dict(zip(sorted_indices, ambient.variable_names()))
names = [amb_names[i] for i in index_set]
except ValueError: # ambient has not assigned variable names
pass
elif isinstance(names, str):
if len(index_set) == 1:
names = [names]
Expand Down Expand Up @@ -252,15 +255,15 @@ def __init__(self, I, L, names, index_set, category=None):
B = L.basis()
sm = L.module().submodule_with_basis([I.reduce(B[i]).to_vector()
for i in index_set])
SB = sm.basis()
SB = [L.from_vector(b) for b in sm.basis()]

# compute and normalize structural coefficients for the quotient
s_coeff = {}
for i, ind_i in enumerate(index_set):
for j in range(i + 1, len(index_set)):
ind_j = index_set[j]

brkt = I.reduce(L.bracket(SB[i], SB[j]))
brkt = I.reduce(SB[i].bracket(SB[j]))
brktvec = sm.coordinate_vector(brkt.to_vector())
s_coeff[(ind_i, ind_j)] = dict(zip(index_set, brktvec))
s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff(
Expand Down Expand Up @@ -291,11 +294,26 @@ def _repr_(self):
L: General linear Lie algebra of rank 2 over Rational Field
I: Ideal ([0 0]
[0 1])
sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example()
sage: a,b,c = L.gens()
sage: I = L.ideal([a+2*b, b+3*c])
sage: Q = L.quotient(I)
sage: Q
Lie algebra quotient L/I of dimension 1 over Rational Field where
L: An example of a finite dimensional Lie algebra with basis:
the 3-dimensional abelian Lie algebra over Rational Field
I: Ideal ((1, 0, -6), (0, 1, 3))
"""
try:
ideal_repr = self._I._repr_short()
except AttributeError:
ideal_repr = repr(tuple(self._I.gens()))

return ("Lie algebra quotient L/I of dimension %s"
" over %s where\nL: %s\nI: Ideal %s" % (
self.dimension(), self.base_ring(),
self.ambient(), self._I._repr_short()))
self.ambient(), ideal_repr))

def _repr_generator(self, i):
r"""
Expand Down
65 changes: 0 additions & 65 deletions src/sage/algebras/lie_algebras/subalgebra.py
Original file line number Diff line number Diff line change
Expand Up @@ -857,71 +857,6 @@ def is_ideal(self, A):
return True
return super().is_ideal(A)

def reduce(self, X):
r"""
Reduce an element of the ambient Lie algebra modulo the
ideal ``self``.
INPUT:
- ``X`` -- an element of the ambient Lie algebra
OUTPUT:
An element `Y` of the ambient Lie algebra that is contained in a fixed
complementary submodule `V` to ``self`` such that `X = Y` mod ``self``.
When the base ring of ``self`` is a field, the complementary submodule
`V` is spanned by the elements of the basis that are not the leading
supports of the basis of ``self``.
EXAMPLES:
An example reduction in a 6 dimensional Lie algebra::
sage: sc = {('a','b'): {'d': 1}, ('a','c'): {'e': 1},
....: ('b','c'): {'f': 1}}
sage: L.<a,b,c,d,e,f> = LieAlgebra(QQ, sc)
sage: I = L.ideal(c)
sage: I.reduce(a + b + c + d + e + f)
a + b + d
The reduction of an element is zero if and only if the
element belongs to the subalgebra::
sage: I.reduce(c + e)
0
sage: c + e in I
True
Over non-fields, the complementary submodule may not be spanned by
a subset of the basis of the ambient Lie algebra::
sage: L.<X,Y,Z> = LieAlgebra(ZZ, {('X','Y'): {'Z': 3}})
sage: I = L.ideal(Y)
sage: I.basis()
Family (Y, 3*Z)
sage: I.reduce(3*Z)
0
sage: I.reduce(Y + 14*Z)
2*Z
"""
R = self.base_ring()
for Y in self.basis():
Y = self.lift(Y)
k, c = Y.leading_item(key=self._order)

if R.is_field():
X = X - X[k] / c * Y
else:
try:
q, _ = X[k].quo_rem(c)
X = X - q * Y
except AttributeError:
pass

return X

class Element(LieSubalgebraElementWrapper):
def adjoint_matrix(self, sparse=False):
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ def __init__(self, R, n=None, M=None, ambient=None):
self._ambient = ambient
Parent.__init__(self, base=R, category=cat)

from sage.categories.lie_algebras import LiftMorphism
self._lift_uea = LiftMorphism(self, self._construct_UEA())
self._lift_uea.register_as_coercion()

def _repr_(self):
"""
EXAMPLES::
Expand Down Expand Up @@ -135,6 +139,57 @@ def _element_constructor_(self, x):
x = x.value
return self.element_class(self, self._M(x))

def lift(self, x):
r"""
Return the lift of ``self``.
EXAMPLES::
sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example()
sage: a, b, c = L.gens()
sage: L.lift(a)
b0
sage: L.lift(b).parent() is L.universal_enveloping_algebra()
True
sage: I = L.ideal([a+2*b, b+3*c])
sage: I.lift(I.basis()[0])
(1, 0, -6)
"""
# FIXME: This method can likely be simplified or removed once we
# disentangle the UEA lift from the generic lift
A = self._ambient
if A is self:
return self._lift_uea(x)
return A.element_class(A, A._M(x.value))

def universal_enveloping_algebra(self):
r"""
Return the universal enveloping algebra of ``self``.
EXAMPLES::
sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example()
sage: L.universal_enveloping_algebra()
Noncommutative Multivariate Polynomial Ring in b0, b1, b2
over Rational Field, nc-relations: {}
"""
# FIXME: This method can likely be removed once we
# disentangle the UEA lift from the generic lift
return self._lift_uea.codomain()

def _order(self, x):
r"""
Return a key for sorting for the index ``x``.
TESTS::
sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example()
sage: L._order(2)
2
"""
return x

@cached_method
def zero(self):
"""
Expand Down Expand Up @@ -194,6 +249,8 @@ def subalgebra(self, gens):
[ 1 0 -1/2]
[ 0 1 1]
"""
if isinstance(gens, AbelianLieAlgebra):
gens = [self(g) for g in gens.gens()]
N = self._M.subspace([g.value for g in gens])
return AbelianLieAlgebra(self.base_ring(), M=N, ambient=self._ambient)

Expand Down Expand Up @@ -252,7 +309,7 @@ def gens(self) -> tuple:
sage: L.gens()
((1, 0, 0), (0, 1, 0), (0, 0, 1))
"""
return tuple(self._M.basis())
return tuple([self.element_class(self, b) for b in self._M.basis()])

def module(self):
"""
Expand Down Expand Up @@ -302,7 +359,36 @@ def from_vector(self, v, order=None):
"""
return self.element_class(self, self._M(v))

def leading_monomials(self):
r"""
Return the set of leading monomials of the basis of ``self``.
EXAMPLES::
sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example()
sage: a, b, c = L.lie_algebra_generators()
sage: I = L.ideal([2*a+b, b + c])
sage: I.leading_monomials()
((1, 0, 0), (0, 1, 0))
"""
# for free modules, the leading monomial is actually the trailing monomial
return tuple([self._ambient._M(b.value).trailing_monomial()
for b in self.basis()])

class Element(BaseExample.Element):
def __init__(self, parent, value):
"""
Initialize ``self``.
EXAMPLES::
sage: L = LieAlgebras(QQ).FiniteDimensional().WithBasis().example()
sage: a, b, c = L.lie_algebra_generators()
sage: TestSuite(a).run()
"""
value.set_immutable()
super().__init__(parent, value)

def __iter__(self):
"""
Iterate over ``self`` by returning pairs ``(i, c)`` where ``i``
Expand Down
14 changes: 14 additions & 0 deletions src/sage/categories/examples/lie_algebras.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,20 @@ def __ne__(self, rhs):
"""
return not self.__eq__(rhs)

def __hash__(self):
r"""
Return the hash of ``self``.
EXAMPLES::
sage: # needs sage.combinat sage.groups
sage: L = LieAlgebras(QQ).example()
sage: x, y = L.lie_algebra_generators()
sage: hash(x) == hash(x.value)
True
"""
return hash(self.value)

def __bool__(self) -> bool:
"""
Check non-zero.
Expand Down

0 comments on commit 02b2233

Please sign in to comment.