|
20 | 20 | from sage.categories.lie_algebras import LieAlgebras |
21 | 21 | from sage.structure.indexed_generators import standardize_names_index_set |
22 | 22 | from sage.rings.integer_ring import ZZ |
23 | | -from collections import OrderedDict |
| 23 | +from collections import defaultdict |
24 | 24 |
|
25 | 25 | class NilpotentLieAlgebra_dense(LieAlgebraWithStructureCoefficients): |
26 | 26 | r""" |
@@ -349,52 +349,60 @@ def __init__(self, R, r, s, names, naming, category, **kwds): |
349 | 349 | from sage.algebras.lie_algebras.lie_algebra import LieAlgebra |
350 | 350 |
|
351 | 351 | 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)} |
352 | 353 | L = LieAlgebra(R, free_gen_names).Lyndon() |
353 | 354 |
|
354 | | - basis_dict = OrderedDict() |
| 355 | + basis_by_deg = {d: [] for d in range(1, s+1)} |
355 | 356 | for d in range(1, s + 1): |
356 | 357 | for X in L.graded_basis(d): |
357 | 358 | # 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] |
359 | 360 | for s in X.leading_support().to_word()) |
360 | | - basis_dict[w] = X |
| 361 | + basis_by_deg[d].append((w, X)) |
361 | 362 |
|
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: |
363 | 366 | if not naming: |
364 | 367 | if r > 10: |
365 | 368 | naming = 'linear' |
366 | 369 | else: |
367 | 370 | naming = 'index' |
368 | 371 | if naming == 'linear': |
369 | 372 | names = ['%s_%d' % (names[0], k + 1) |
370 | | - for k in range(len(basis_dict))] |
| 373 | + for k in range(len(index_set))] |
371 | 374 | elif naming == 'index': |
372 | 375 | if r > 10: |
373 | 376 | raise ValueError("'index' naming scheme not supported for " |
374 | 377 | "over 10 generators") |
375 | 378 | names = ['%s_%s' % (names[0], "".join(str(s) for s in w)) |
376 | | - for w in basis_dict] |
| 379 | + for w in index_set] |
377 | 380 | else: |
378 | 381 | raise ValueError("unknown naming scheme %s" % naming) |
379 | 382 |
|
380 | 383 | # extract structural coefficients from the free Lie algebra |
381 | 384 | 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) |
398 | 406 | s_coeff = LieAlgebraWithStructureCoefficients._standardize_s_coeff( |
399 | 407 | s_coeff, index_set) |
400 | 408 |
|
|
0 commit comments