Skip to content

Commit

Permalink
Speed improvements to computing the radical over finite fields.
Browse files Browse the repository at this point in the history
  • Loading branch information
tscrim committed Mar 31, 2024
1 parent 148242d commit 83973fd
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 25 deletions.
62 changes: 39 additions & 23 deletions src/sage/categories/finite_dimensional_algebras_with_basis.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,20 +203,25 @@ def root_fcn(s, x):
def root_fcn(s, x):
return x ** (1 / s)

s, n = 1, self.dimension()
s = 1
n = self.dimension()
B = [b.on_left_matrix() for b in self.basis()]
I = B[0].parent().one()
while s <= n:
BB = B + [I]
G = matrix([[(-1)**s * (b*bb).characteristic_polynomial()[n-s]
for bb in BB] for b in B])
C = G.left_kernel().basis()
# We use the fact that p_{AB}(x) = p_{BA}(x)
data = [[None]*(len(B)+1) for _ in B]
for i, b in enumerate(B):
for j, bb in enumerate(B[i:], start=i):
val = (-1)**s * (b*bb).charpoly()[n-s]
data[i][j] = data[j][i] = val
data[i][-1] = (-1)**s * b.charpoly()[n-s]
C = matrix(data).left_kernel().basis()
if 1 < s < F.order():
C = [vector(F, [root_fcn(s, ci) for ci in c]) for c in C]
B = [sum(ci*b for (ci,b) in zip(c,B)) for c in C]
B = [sum(ci * b for (ci, b) in zip(c, B)) for c in C]
s = p * s
e = vector(self.one())
rad_basis = [b*e for b in B]
rad_basis = [b * e for b in B]

return tuple([self.from_vector(vec) for vec in rad_basis])

Expand Down Expand Up @@ -275,7 +280,7 @@ def radical(self):
sage: # needs sage.graphs sage.modules
sage: TestSuite(radical).run()
"""
category = AssociativeAlgebras(self.base_ring()).WithBasis().FiniteDimensional().Subobjects()
category = AssociativeAlgebras(self.category().base_ring()).WithBasis().FiniteDimensional().Subobjects()
radical = self.submodule(self.radical_basis(),
category=category,
already_echelonized=True)
Expand Down Expand Up @@ -424,7 +429,7 @@ def subalgebra(self, gens, category=None, *args, **opts):
sage: MS = MatrixSpace(QQ, 5)
sage: A = MS.subalgebra([bg.adjoint_matrix() for bg in L.lie_algebra_generators()])
sage: A.dimension()
6
7
sage: L.<x,y,z> = LieAlgebra(GF(3), {('x','z'): {'x':1, 'y':1}, ('y','z'): {'y':1}})
sage: MS = MatrixSpace(L.base_ring(), L.dimension())
Expand All @@ -434,21 +439,29 @@ def subalgebra(self, gens, category=None, *args, **opts):
5
"""
# add the unit to make sure it is unital
basis = self.echelon_form([self(g) for g in gens] + [self.one()])
while not basis[-1]:
basis.pop()
dim = 0
while dim != len(basis):
dim = len(basis)
basis = self.echelon_form(basis + [b * bp for b in basis for bp in basis])
while not basis[-1]:
basis.pop()
basis = []
new_elts = [self(g) for g in gens] + [self.one()]
while new_elts:
basis = self.echelon_form(basis + new_elts)
leadsupp = {b.leading_support(): b for b in basis}
sortsupp = sorted(leadsupp)
new_elts = []
# We (re)implement the reduction here
for b in basis:
for bp in basis:
elt = b * bp
for s in sortsupp:
c = elt[s]
if c:
elt -= c * leadsupp[s]
if elt:
new_elts.append(elt)
C = FiniteDimensionalAlgebrasWithBasis(self.category().base_ring())
category = C.Subobjects().or_subcategory(category)
return self.submodule(basis, check=False, already_echelonized=True,
category=category)

def ideal(self, gens, side='left', *args, **opts):
def ideal(self, gens, side='left', category=None, *args, **opts):
r"""
Return the ``side`` ideal of ``self`` generated by ``gens``.
Expand All @@ -462,17 +475,20 @@ def ideal(self, gens, side='left', *args, **opts):
sage: I.dimension()
25
"""
C = AssociativeAlgebras(self.category().base_ring()).WithBasis().FiniteDimensional()
category = C.Subobjects().or_subcategory(category)
if gens in self:
gens = [gens]
gens = [self(gens)]
if side == 'left':
return self.submodule([b * self(g) for b in self.basis() for g in gens],
*args, **opts)
category=category, *args, **opts)
if side == 'right':
return self.submodule([self(g) * b for b in self.basis() for g in gens],
*args, **opts)
category=category, *args, **opts)
if side == 'twosided':
return self.submodule([b * self(g) * bp for b in self.basis()
for bp in self.basis() for g in gens], *args, **opts)
for bp in self.basis() for g in gens],
category=category, *args, **opts)
raise ValueError("side must be either 'left', 'right', or 'twosided'")

def principal_ideal(self, a, side='left', *args, **opts):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1583,9 +1583,9 @@ def is_semisimple(self):
sage: sp4 = LieAlgebra(GF(3), cartan_type=['C',2])
sage: sp4.killing_form_matrix().det()
0
sage: sp4.solvable_radical_basis()
sage: sp4.solvable_radical_basis() # long time
()
sage: sp4.is_semisimple()
sage: sp4.is_semisimple() # long time
True
"""
if self.base_ring().characteristic() == 0:
Expand Down

0 comments on commit 83973fd

Please sign in to comment.