Skip to content
This repository was archived by the owner on Jan 30, 2023. It is now read-only.

Commit a60ef68

Browse files
committed
Speedup constructor for free Nilpotent Lie algebras.
1 parent d1fe093 commit a60ef68

File tree

1 file changed

+31
-23
lines changed

1 file changed

+31
-23
lines changed

src/sage/algebras/lie_algebras/nilpotent_lie_algebra.py

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from sage.categories.lie_algebras import LieAlgebras
2121
from sage.structure.indexed_generators import standardize_names_index_set
2222
from sage.rings.integer_ring import ZZ
23-
from collections import OrderedDict
23+
from collections import defaultdict
2424

2525
class NilpotentLieAlgebra_dense(LieAlgebraWithStructureCoefficients):
2626
r"""
@@ -349,52 +349,60 @@ def __init__(self, R, r, s, names, naming, category, **kwds):
349349
from sage.algebras.lie_algebras.lie_algebra import LieAlgebra
350350

351351
free_gen_names = ['F%d' % k for k in range(r)]
352+
free_gen_names_inv = {val: i+1 for i,val in enumerate(free_gen_names)}
352353
L = LieAlgebra(R, free_gen_names).Lyndon()
353354

354-
basis_dict = OrderedDict()
355+
basis_by_deg = {d: [] for d in range(1, s+1)}
355356
for d in range(1, s + 1):
356357
for X in L.graded_basis(d):
357358
# convert brackets of form [X_1, [X_1, X_2]] to words (1,1,2)
358-
w = tuple(free_gen_names.index(s) + 1
359+
w = tuple(free_gen_names_inv[s]
359360
for s in X.leading_support().to_word())
360-
basis_dict[w] = X
361+
basis_by_deg[d].append((w, X))
361362

362-
if len(names) == 1 and len(basis_dict) > 1:
363+
index_set = [ind for d in basis_by_deg for ind, val in basis_by_deg[d]]
364+
365+
if len(names) == 1 and len(index_set) > 1:
363366
if not naming:
364367
if r > 10:
365368
naming = 'linear'
366369
else:
367370
naming = 'index'
368371
if naming == 'linear':
369372
names = ['%s_%d' % (names[0], k + 1)
370-
for k in range(len(basis_dict))]
373+
for k in range(len(index_set))]
371374
elif naming == 'index':
372375
if r > 10:
373376
raise ValueError("'index' naming scheme not supported for "
374377
"over 10 generators")
375378
names = ['%s_%s' % (names[0], "".join(str(s) for s in w))
376-
for w in basis_dict]
379+
for w in index_set]
377380
else:
378381
raise ValueError("unknown naming scheme %s" % naming)
379382

380383
# extract structural coefficients from the free Lie algebra
381384
s_coeff = {}
382-
for k, X_ind in enumerate(basis_dict):
383-
X = basis_dict[X_ind]
384-
degX = len(X_ind)
385-
for Y_ind in basis_dict.keys()[k+1:]:
386-
# brackets are only computed when deg(X) + deg(Y) <= s
387-
degY = len(Y_ind)
388-
if degX + degY > s:
389-
continue
390-
391-
Y = basis_dict[Y_ind]
392-
Z = L[X, Y]
393-
if not Z.is_zero():
394-
s_coeff[(X_ind, Y_ind)] = {W: Z[basis_dict[W].leading_support()]
395-
for W in basis_dict}
396-
397-
names, index_set = standardize_names_index_set(names, basis_dict.keys())
385+
for dx in range(1, s + 1):
386+
# Brackets are only computed when deg(X) + deg(Y) <= s
387+
# We also require deg(Y) >= deg(X) by the ordering
388+
for dy in range(dx, s + 1 - dx):
389+
if dx == dy:
390+
for i, val in enumerate(basis_by_deg[dx]):
391+
X_ind, X = val
392+
for Y_ind, Y in basis_by_deg[dy][i+1:]:
393+
Z = L[X, Y]
394+
if not Z.is_zero():
395+
s_coeff[(X_ind, Y_ind)] = {W_ind: Z[W.leading_support()]
396+
for W_ind, W in basis_by_deg[dx+dy]}
397+
else:
398+
for X_ind, X in basis_by_deg[dx]:
399+
for Y_ind, Y in basis_by_deg[dy]:
400+
Z = L[X, Y]
401+
if not Z.is_zero():
402+
s_coeff[(X_ind, Y_ind)] = {W_ind: Z[W.leading_support()]
403+
for W_ind, W in basis_by_deg[dx+dy]}
404+
405+
names, index_set = standardize_names_index_set(names, index_set)
398406
s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff(
399407
s_coeff, index_set)
400408

0 commit comments

Comments
 (0)