passagemath-combinat 10.6.42__cp314-cp314-musllinux_1_2_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_combinat/__init__.py +3 -0
- passagemath_combinat-10.6.42.dist-info/METADATA +160 -0
- passagemath_combinat-10.6.42.dist-info/RECORD +400 -0
- passagemath_combinat-10.6.42.dist-info/WHEEL +5 -0
- passagemath_combinat-10.6.42.dist-info/top_level.txt +3 -0
- passagemath_combinat.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_combinat.libs/libsymmetrica-81fe8739.so.3.0.0 +0 -0
- sage/algebras/affine_nil_temperley_lieb.py +263 -0
- sage/algebras/all.py +24 -0
- sage/algebras/all__sagemath_combinat.py +35 -0
- sage/algebras/askey_wilson.py +935 -0
- sage/algebras/associated_graded.py +345 -0
- sage/algebras/cellular_basis.py +350 -0
- sage/algebras/cluster_algebra.py +2766 -0
- sage/algebras/down_up_algebra.py +860 -0
- sage/algebras/free_algebra.py +1698 -0
- sage/algebras/free_algebra_element.py +345 -0
- sage/algebras/free_algebra_quotient.py +405 -0
- sage/algebras/free_algebra_quotient_element.py +295 -0
- sage/algebras/free_zinbiel_algebra.py +885 -0
- sage/algebras/hall_algebra.py +783 -0
- sage/algebras/hecke_algebras/all.py +4 -0
- sage/algebras/hecke_algebras/ariki_koike_algebra.py +1796 -0
- sage/algebras/hecke_algebras/ariki_koike_specht_modules.py +475 -0
- sage/algebras/hecke_algebras/cubic_hecke_algebra.py +3520 -0
- sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +1473 -0
- sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py +1079 -0
- sage/algebras/iwahori_hecke_algebra.py +3095 -0
- sage/algebras/jordan_algebra.py +1773 -0
- sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py +113 -0
- sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py +156 -0
- sage/algebras/lie_conformal_algebras/all.py +18 -0
- sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py +134 -0
- sage/algebras/lie_conformal_algebras/examples.py +43 -0
- sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py +131 -0
- sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py +139 -0
- sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py +174 -0
- sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +167 -0
- sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py +107 -0
- sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py +135 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +353 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py +236 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py +78 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +328 -0
- sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py +117 -0
- sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py +86 -0
- sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py +82 -0
- sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py +205 -0
- sage/algebras/nil_coxeter_algebra.py +191 -0
- sage/algebras/q_commuting_polynomials.py +673 -0
- sage/algebras/q_system.py +608 -0
- sage/algebras/quantum_clifford.py +959 -0
- sage/algebras/quantum_groups/ace_quantum_onsager.py +693 -0
- sage/algebras/quantum_groups/all.py +9 -0
- sage/algebras/quantum_groups/fock_space.py +2219 -0
- sage/algebras/quantum_groups/q_numbers.py +207 -0
- sage/algebras/quantum_groups/quantum_group_gap.py +2695 -0
- sage/algebras/quantum_groups/representations.py +591 -0
- sage/algebras/quantum_matrix_coordinate_algebra.py +1006 -0
- sage/algebras/quantum_oscillator.py +623 -0
- sage/algebras/quaternion_algebra.py +20 -0
- sage/algebras/quaternion_algebra_element.py +55 -0
- sage/algebras/rational_cherednik_algebra.py +525 -0
- sage/algebras/schur_algebra.py +670 -0
- sage/algebras/shuffle_algebra.py +1011 -0
- sage/algebras/splitting_algebra.py +779 -0
- sage/algebras/tensor_algebra.py +709 -0
- sage/algebras/yangian.py +1082 -0
- sage/algebras/yokonuma_hecke_algebra.py +1018 -0
- sage/all__sagemath_combinat.py +35 -0
- sage/combinat/SJT.py +255 -0
- sage/combinat/affine_permutation.py +2405 -0
- sage/combinat/algebraic_combinatorics.py +55 -0
- sage/combinat/all.py +53 -0
- sage/combinat/all__sagemath_combinat.py +195 -0
- sage/combinat/alternating_sign_matrix.py +2063 -0
- sage/combinat/baxter_permutations.py +346 -0
- sage/combinat/bijectionist.py +3220 -0
- sage/combinat/binary_recurrence_sequences.py +1180 -0
- sage/combinat/blob_algebra.py +685 -0
- sage/combinat/catalog_partitions.py +27 -0
- sage/combinat/chas/all.py +23 -0
- sage/combinat/chas/fsym.py +1180 -0
- sage/combinat/chas/wqsym.py +2601 -0
- sage/combinat/cluster_complex.py +326 -0
- sage/combinat/colored_permutations.py +2039 -0
- sage/combinat/colored_permutations_representations.py +964 -0
- sage/combinat/composition_signed.py +142 -0
- sage/combinat/composition_tableau.py +855 -0
- sage/combinat/constellation.py +1729 -0
- sage/combinat/core.py +751 -0
- sage/combinat/counting.py +12 -0
- sage/combinat/crystals/affine.py +742 -0
- sage/combinat/crystals/affine_factorization.py +518 -0
- sage/combinat/crystals/affinization.py +331 -0
- sage/combinat/crystals/alcove_path.py +2013 -0
- sage/combinat/crystals/all.py +22 -0
- sage/combinat/crystals/bkk_crystals.py +141 -0
- sage/combinat/crystals/catalog.py +115 -0
- sage/combinat/crystals/catalog_elementary_crystals.py +18 -0
- sage/combinat/crystals/catalog_infinity_crystals.py +33 -0
- sage/combinat/crystals/catalog_kirillov_reshetikhin.py +18 -0
- sage/combinat/crystals/crystals.py +257 -0
- sage/combinat/crystals/direct_sum.py +260 -0
- sage/combinat/crystals/elementary_crystals.py +1251 -0
- sage/combinat/crystals/fast_crystals.py +441 -0
- sage/combinat/crystals/fully_commutative_stable_grothendieck.py +1205 -0
- sage/combinat/crystals/generalized_young_walls.py +1076 -0
- sage/combinat/crystals/highest_weight_crystals.py +436 -0
- sage/combinat/crystals/induced_structure.py +695 -0
- sage/combinat/crystals/infinity_crystals.py +730 -0
- sage/combinat/crystals/kac_modules.py +863 -0
- sage/combinat/crystals/kirillov_reshetikhin.py +4196 -0
- sage/combinat/crystals/kyoto_path_model.py +497 -0
- sage/combinat/crystals/letters.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/letters.pxd +79 -0
- sage/combinat/crystals/letters.pyx +3056 -0
- sage/combinat/crystals/littelmann_path.py +1518 -0
- sage/combinat/crystals/monomial_crystals.py +1262 -0
- sage/combinat/crystals/multisegments.py +462 -0
- sage/combinat/crystals/mv_polytopes.py +467 -0
- sage/combinat/crystals/pbw_crystal.py +511 -0
- sage/combinat/crystals/pbw_datum.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/pbw_datum.pxd +4 -0
- sage/combinat/crystals/pbw_datum.pyx +487 -0
- sage/combinat/crystals/polyhedral_realization.py +372 -0
- sage/combinat/crystals/spins.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/spins.pxd +21 -0
- sage/combinat/crystals/spins.pyx +756 -0
- sage/combinat/crystals/star_crystal.py +290 -0
- sage/combinat/crystals/subcrystal.py +464 -0
- sage/combinat/crystals/tensor_product.py +1177 -0
- sage/combinat/crystals/tensor_product_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/tensor_product_element.pxd +35 -0
- sage/combinat/crystals/tensor_product_element.pyx +1870 -0
- sage/combinat/crystals/virtual_crystal.py +420 -0
- sage/combinat/cyclic_sieving_phenomenon.py +204 -0
- sage/combinat/debruijn_sequence.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/debruijn_sequence.pyx +355 -0
- sage/combinat/decorated_permutation.py +270 -0
- sage/combinat/degree_sequences.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/degree_sequences.pyx +588 -0
- sage/combinat/derangements.py +527 -0
- sage/combinat/descent_algebra.py +1008 -0
- sage/combinat/diagram.py +1551 -0
- sage/combinat/diagram_algebras.py +5886 -0
- sage/combinat/dyck_word.py +4349 -0
- sage/combinat/e_one_star.py +1623 -0
- sage/combinat/enumerated_sets.py +123 -0
- sage/combinat/expnums.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/expnums.pyx +148 -0
- sage/combinat/fast_vector_partitions.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/fast_vector_partitions.pyx +346 -0
- sage/combinat/fqsym.py +1977 -0
- sage/combinat/free_dendriform_algebra.py +954 -0
- sage/combinat/free_prelie_algebra.py +1141 -0
- sage/combinat/fully_commutative_elements.py +1077 -0
- sage/combinat/fully_packed_loop.py +1523 -0
- sage/combinat/gelfand_tsetlin_patterns.py +1409 -0
- sage/combinat/gray_codes.py +311 -0
- sage/combinat/grossman_larson_algebras.py +667 -0
- sage/combinat/growth.py +4352 -0
- sage/combinat/hall_polynomial.py +188 -0
- sage/combinat/hillman_grassl.py +866 -0
- sage/combinat/integer_matrices.py +329 -0
- sage/combinat/integer_vectors_mod_permgroup.py +1238 -0
- sage/combinat/k_tableau.py +4564 -0
- sage/combinat/kazhdan_lusztig.py +215 -0
- sage/combinat/key_polynomial.py +885 -0
- sage/combinat/knutson_tao_puzzles.py +2286 -0
- sage/combinat/lr_tableau.py +311 -0
- sage/combinat/matrices/all.py +24 -0
- sage/combinat/matrices/hadamard_matrix.py +3790 -0
- sage/combinat/matrices/latin.py +2912 -0
- sage/combinat/misc.py +401 -0
- sage/combinat/multiset_partition_into_sets_ordered.py +3541 -0
- sage/combinat/ncsf_qsym/all.py +21 -0
- sage/combinat/ncsf_qsym/combinatorics.py +317 -0
- sage/combinat/ncsf_qsym/generic_basis_code.py +1427 -0
- sage/combinat/ncsf_qsym/ncsf.py +5637 -0
- sage/combinat/ncsf_qsym/qsym.py +4053 -0
- sage/combinat/ncsf_qsym/tutorial.py +447 -0
- sage/combinat/ncsym/all.py +21 -0
- sage/combinat/ncsym/bases.py +855 -0
- sage/combinat/ncsym/dual.py +593 -0
- sage/combinat/ncsym/ncsym.py +2076 -0
- sage/combinat/necklace.py +551 -0
- sage/combinat/non_decreasing_parking_function.py +634 -0
- sage/combinat/nu_dyck_word.py +1474 -0
- sage/combinat/output.py +861 -0
- sage/combinat/parallelogram_polyomino.py +4326 -0
- sage/combinat/parking_functions.py +1602 -0
- sage/combinat/partition_algebra.py +1998 -0
- sage/combinat/partition_kleshchev.py +1982 -0
- sage/combinat/partition_shifting_algebras.py +584 -0
- sage/combinat/partition_tuple.py +3114 -0
- sage/combinat/path_tableaux/all.py +13 -0
- sage/combinat/path_tableaux/catalog.py +29 -0
- sage/combinat/path_tableaux/dyck_path.py +380 -0
- sage/combinat/path_tableaux/frieze.py +476 -0
- sage/combinat/path_tableaux/path_tableau.py +728 -0
- sage/combinat/path_tableaux/semistandard.py +510 -0
- sage/combinat/perfect_matching.py +779 -0
- sage/combinat/plane_partition.py +3300 -0
- sage/combinat/q_bernoulli.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/q_bernoulli.pyx +128 -0
- sage/combinat/quickref.py +81 -0
- sage/combinat/recognizable_series.py +2051 -0
- sage/combinat/regular_sequence.py +4316 -0
- sage/combinat/regular_sequence_bounded.py +543 -0
- sage/combinat/restricted_growth.py +81 -0
- sage/combinat/ribbon.py +20 -0
- sage/combinat/ribbon_shaped_tableau.py +489 -0
- sage/combinat/ribbon_tableau.py +1180 -0
- sage/combinat/rigged_configurations/all.py +46 -0
- sage/combinat/rigged_configurations/bij_abstract_class.py +548 -0
- sage/combinat/rigged_configurations/bij_infinity.py +370 -0
- sage/combinat/rigged_configurations/bij_type_A.py +163 -0
- sage/combinat/rigged_configurations/bij_type_A2_dual.py +338 -0
- sage/combinat/rigged_configurations/bij_type_A2_even.py +218 -0
- sage/combinat/rigged_configurations/bij_type_A2_odd.py +199 -0
- sage/combinat/rigged_configurations/bij_type_B.py +900 -0
- sage/combinat/rigged_configurations/bij_type_C.py +267 -0
- sage/combinat/rigged_configurations/bij_type_D.py +771 -0
- sage/combinat/rigged_configurations/bij_type_D_tri.py +392 -0
- sage/combinat/rigged_configurations/bij_type_D_twisted.py +576 -0
- sage/combinat/rigged_configurations/bij_type_E67.py +402 -0
- sage/combinat/rigged_configurations/bijection.py +143 -0
- sage/combinat/rigged_configurations/kleber_tree.py +1475 -0
- sage/combinat/rigged_configurations/kr_tableaux.py +1898 -0
- sage/combinat/rigged_configurations/rc_crystal.py +461 -0
- sage/combinat/rigged_configurations/rc_infinity.py +540 -0
- sage/combinat/rigged_configurations/rigged_configuration_element.py +2403 -0
- sage/combinat/rigged_configurations/rigged_configurations.py +1918 -0
- sage/combinat/rigged_configurations/rigged_partition.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/rigged_configurations/rigged_partition.pxd +15 -0
- sage/combinat/rigged_configurations/rigged_partition.pyx +680 -0
- sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +499 -0
- sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py +428 -0
- sage/combinat/rsk.py +3438 -0
- sage/combinat/schubert_polynomial.py +508 -0
- sage/combinat/set_partition.py +3318 -0
- sage/combinat/set_partition_iterator.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/set_partition_iterator.pyx +136 -0
- sage/combinat/set_partition_ordered.py +1590 -0
- sage/combinat/sf/abreu_nigro.py +346 -0
- sage/combinat/sf/all.py +52 -0
- sage/combinat/sf/character.py +576 -0
- sage/combinat/sf/classical.py +319 -0
- sage/combinat/sf/dual.py +996 -0
- sage/combinat/sf/elementary.py +549 -0
- sage/combinat/sf/hall_littlewood.py +1028 -0
- sage/combinat/sf/hecke.py +336 -0
- sage/combinat/sf/homogeneous.py +464 -0
- sage/combinat/sf/jack.py +1428 -0
- sage/combinat/sf/k_dual.py +1458 -0
- sage/combinat/sf/kfpoly.py +447 -0
- sage/combinat/sf/llt.py +789 -0
- sage/combinat/sf/macdonald.py +2019 -0
- sage/combinat/sf/monomial.py +525 -0
- sage/combinat/sf/multiplicative.py +113 -0
- sage/combinat/sf/new_kschur.py +1786 -0
- sage/combinat/sf/ns_macdonald.py +964 -0
- sage/combinat/sf/orthogonal.py +246 -0
- sage/combinat/sf/orthotriang.py +355 -0
- sage/combinat/sf/powersum.py +963 -0
- sage/combinat/sf/schur.py +880 -0
- sage/combinat/sf/sf.py +1653 -0
- sage/combinat/sf/sfa.py +7053 -0
- sage/combinat/sf/symplectic.py +253 -0
- sage/combinat/sf/witt.py +721 -0
- sage/combinat/shifted_primed_tableau.py +2735 -0
- sage/combinat/shuffle.py +830 -0
- sage/combinat/sidon_sets.py +146 -0
- sage/combinat/similarity_class_type.py +1721 -0
- sage/combinat/sine_gordon.py +618 -0
- sage/combinat/six_vertex_model.py +784 -0
- sage/combinat/skew_partition.py +2053 -0
- sage/combinat/skew_tableau.py +2989 -0
- sage/combinat/sloane_functions.py +8935 -0
- sage/combinat/specht_module.py +1403 -0
- sage/combinat/species/all.py +48 -0
- sage/combinat/species/characteristic_species.py +321 -0
- sage/combinat/species/composition_species.py +273 -0
- sage/combinat/species/cycle_species.py +284 -0
- sage/combinat/species/empty_species.py +155 -0
- sage/combinat/species/functorial_composition_species.py +148 -0
- sage/combinat/species/generating_series.py +673 -0
- sage/combinat/species/library.py +148 -0
- sage/combinat/species/linear_order_species.py +169 -0
- sage/combinat/species/misc.py +83 -0
- sage/combinat/species/partition_species.py +290 -0
- sage/combinat/species/permutation_species.py +268 -0
- sage/combinat/species/product_species.py +423 -0
- sage/combinat/species/recursive_species.py +476 -0
- sage/combinat/species/set_species.py +192 -0
- sage/combinat/species/species.py +820 -0
- sage/combinat/species/structure.py +539 -0
- sage/combinat/species/subset_species.py +243 -0
- sage/combinat/species/sum_species.py +225 -0
- sage/combinat/subword.py +564 -0
- sage/combinat/subword_complex.py +2122 -0
- sage/combinat/subword_complex_c.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/subword_complex_c.pyx +119 -0
- sage/combinat/super_tableau.py +821 -0
- sage/combinat/superpartition.py +1154 -0
- sage/combinat/symmetric_group_algebra.py +3774 -0
- sage/combinat/symmetric_group_representations.py +1830 -0
- sage/combinat/t_sequences.py +877 -0
- sage/combinat/tableau.py +9506 -0
- sage/combinat/tableau_residues.py +860 -0
- sage/combinat/tableau_tuple.py +5353 -0
- sage/combinat/tiling.py +2432 -0
- sage/combinat/triangles_FHM.py +777 -0
- sage/combinat/tutorial.py +1857 -0
- sage/combinat/vector_partition.py +337 -0
- sage/combinat/words/abstract_word.py +1722 -0
- sage/combinat/words/all.py +59 -0
- sage/combinat/words/alphabet.py +268 -0
- sage/combinat/words/finite_word.py +7201 -0
- sage/combinat/words/infinite_word.py +113 -0
- sage/combinat/words/lyndon_word.py +652 -0
- sage/combinat/words/morphic.py +351 -0
- sage/combinat/words/morphism.py +3878 -0
- sage/combinat/words/paths.py +2932 -0
- sage/combinat/words/shuffle_product.py +278 -0
- sage/combinat/words/suffix_trees.py +1873 -0
- sage/combinat/words/word.py +769 -0
- sage/combinat/words/word_char.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/words/word_char.pyx +847 -0
- sage/combinat/words/word_datatypes.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/words/word_datatypes.pxd +4 -0
- sage/combinat/words/word_datatypes.pyx +1067 -0
- sage/combinat/words/word_generators.py +2026 -0
- sage/combinat/words/word_infinite_datatypes.py +1218 -0
- sage/combinat/words/word_options.py +99 -0
- sage/combinat/words/words.py +2396 -0
- sage/data_structures/all__sagemath_combinat.py +1 -0
- sage/databases/all__sagemath_combinat.py +13 -0
- sage/databases/findstat.py +4897 -0
- sage/databases/oeis.py +2058 -0
- sage/databases/sloane.py +393 -0
- sage/dynamics/all__sagemath_combinat.py +14 -0
- sage/dynamics/cellular_automata/all.py +7 -0
- sage/dynamics/cellular_automata/catalog.py +34 -0
- sage/dynamics/cellular_automata/elementary.py +612 -0
- sage/dynamics/cellular_automata/glca.py +477 -0
- sage/dynamics/cellular_automata/solitons.py +1463 -0
- sage/dynamics/finite_dynamical_system.py +1249 -0
- sage/dynamics/finite_dynamical_system_catalog.py +382 -0
- sage/games/all.py +7 -0
- sage/games/hexad.py +704 -0
- sage/games/quantumino.py +591 -0
- sage/games/sudoku.py +889 -0
- sage/games/sudoku_backtrack.cpython-314-x86_64-linux-musl.so +0 -0
- sage/games/sudoku_backtrack.pyx +189 -0
- sage/groups/all__sagemath_combinat.py +1 -0
- sage/groups/indexed_free_group.py +489 -0
- sage/libs/all__sagemath_combinat.py +6 -0
- sage/libs/lrcalc/__init__.py +1 -0
- sage/libs/lrcalc/lrcalc.py +525 -0
- sage/libs/symmetrica/__init__.py +7 -0
- sage/libs/symmetrica/all.py +101 -0
- sage/libs/symmetrica/kostka.pxi +168 -0
- sage/libs/symmetrica/part.pxi +193 -0
- sage/libs/symmetrica/plet.pxi +42 -0
- sage/libs/symmetrica/sab.pxi +196 -0
- sage/libs/symmetrica/sb.pxi +332 -0
- sage/libs/symmetrica/sc.pxi +192 -0
- sage/libs/symmetrica/schur.pxi +956 -0
- sage/libs/symmetrica/symmetrica.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/symmetrica/symmetrica.pxi +1172 -0
- sage/libs/symmetrica/symmetrica.pyx +39 -0
- sage/monoids/all.py +13 -0
- sage/monoids/automatic_semigroup.py +1054 -0
- sage/monoids/free_abelian_monoid.py +315 -0
- sage/monoids/free_abelian_monoid_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/monoids/free_abelian_monoid_element.pxd +16 -0
- sage/monoids/free_abelian_monoid_element.pyx +397 -0
- sage/monoids/free_monoid.py +335 -0
- sage/monoids/free_monoid_element.py +431 -0
- sage/monoids/hecke_monoid.py +65 -0
- sage/monoids/string_monoid.py +817 -0
- sage/monoids/string_monoid_element.py +547 -0
- sage/monoids/string_ops.py +143 -0
- sage/monoids/trace_monoid.py +972 -0
- sage/rings/all__sagemath_combinat.py +2 -0
- sage/sat/all.py +4 -0
- sage/sat/boolean_polynomials.py +405 -0
- sage/sat/converters/__init__.py +6 -0
- sage/sat/converters/anf2cnf.py +14 -0
- sage/sat/converters/polybori.py +611 -0
- sage/sat/solvers/__init__.py +5 -0
- sage/sat/solvers/cryptominisat.py +287 -0
- sage/sat/solvers/dimacs.py +783 -0
- sage/sat/solvers/picosat.py +228 -0
- sage/sat/solvers/sat_lp.py +156 -0
- sage/sat/solvers/satsolver.cpython-314-x86_64-linux-musl.so +0 -0
- sage/sat/solvers/satsolver.pxd +3 -0
- sage/sat/solvers/satsolver.pyx +405 -0
|
@@ -0,0 +1,3774 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
# sage.doctest: needs sage.combinat sage.modules sage.groups
|
|
3
|
+
r"""
|
|
4
|
+
Symmetric group algebra
|
|
5
|
+
"""
|
|
6
|
+
# ****************************************************************************
|
|
7
|
+
# Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
|
|
8
|
+
#
|
|
9
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
10
|
+
# https://www.gnu.org/licenses/
|
|
11
|
+
# ****************************************************************************
|
|
12
|
+
import itertools
|
|
13
|
+
|
|
14
|
+
from sage.algebras.cellular_basis import CellularBasis
|
|
15
|
+
from sage.algebras.group_algebra import GroupAlgebra_class
|
|
16
|
+
from sage.arith.misc import factorial
|
|
17
|
+
from sage.categories.algebras_with_basis import AlgebrasWithBasis
|
|
18
|
+
from sage.categories.weyl_groups import WeylGroups
|
|
19
|
+
from sage.combinat.free_module import CombinatorialFreeModule
|
|
20
|
+
from sage.combinat.partition import Partitions, Partitions_n, _Partitions
|
|
21
|
+
from sage.combinat.permutation import (
|
|
22
|
+
Permutation,
|
|
23
|
+
Permutations,
|
|
24
|
+
from_permutation_group_element,
|
|
25
|
+
)
|
|
26
|
+
from sage.combinat.permutation_cython import left_action_same_n, right_action_same_n
|
|
27
|
+
from sage.combinat.skew_tableau import SkewTableau
|
|
28
|
+
from sage.combinat.tableau import (
|
|
29
|
+
StandardTableaux,
|
|
30
|
+
StandardTableaux_shape,
|
|
31
|
+
StandardTableaux_size,
|
|
32
|
+
Tableau,
|
|
33
|
+
)
|
|
34
|
+
from sage.matrix.constructor import matrix
|
|
35
|
+
from sage.misc.cachefunc import cached_method
|
|
36
|
+
from sage.misc.lazy_attribute import lazy_attribute
|
|
37
|
+
from sage.misc.lazy_import import lazy_import
|
|
38
|
+
from sage.misc.persist import register_unpickle_override
|
|
39
|
+
from sage.modules.free_module_element import vector
|
|
40
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
41
|
+
from sage.rings.rational_field import QQ
|
|
42
|
+
|
|
43
|
+
lazy_import('sage.groups.perm_gps.permgroup_element',
|
|
44
|
+
'PermutationGroupElement')
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# TODO: Remove this function and replace it with the class
|
|
48
|
+
# TODO: Create parents for other bases (such as the seminormal basis)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def SymmetricGroupAlgebra(R, W, category=None):
|
|
52
|
+
r"""
|
|
53
|
+
Return the symmetric group algebra of order ``W`` over the ring ``R``.
|
|
54
|
+
|
|
55
|
+
INPUT:
|
|
56
|
+
|
|
57
|
+
- ``W`` -- a symmetric group; alternatively an integer `n` can be
|
|
58
|
+
provided, as shorthand for ``Permutations(n)``.
|
|
59
|
+
- ``R`` -- a base ring
|
|
60
|
+
- ``category`` -- a category (default: the category of ``W``)
|
|
61
|
+
|
|
62
|
+
This supports several implementations of the symmetric group. At
|
|
63
|
+
this point this has been tested with ``W=Permutations(n)`` and
|
|
64
|
+
``W=SymmetricGroup(n)``.
|
|
65
|
+
|
|
66
|
+
.. WARNING::
|
|
67
|
+
|
|
68
|
+
Some features are failing in the latter case, in particular if
|
|
69
|
+
the domain of the symmetric group is not `1,\ldots,n`.
|
|
70
|
+
|
|
71
|
+
.. NOTE::
|
|
72
|
+
|
|
73
|
+
The brave can also try setting ``W=WeylGroup(['A',n-1])``, but
|
|
74
|
+
little support for this currently exists.
|
|
75
|
+
|
|
76
|
+
EXAMPLES::
|
|
77
|
+
|
|
78
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ, 3); QS3
|
|
79
|
+
Symmetric group algebra of order 3 over Rational Field
|
|
80
|
+
sage: QS3(1)
|
|
81
|
+
[1, 2, 3]
|
|
82
|
+
sage: QS3(2)
|
|
83
|
+
2*[1, 2, 3]
|
|
84
|
+
sage: basis = [QS3(p) for p in Permutations(3)]
|
|
85
|
+
sage: a = sum(basis); a
|
|
86
|
+
[1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
|
|
87
|
+
sage: a^2
|
|
88
|
+
6*[1, 2, 3] + 6*[1, 3, 2] + 6*[2, 1, 3] + 6*[2, 3, 1]
|
|
89
|
+
+ 6*[3, 1, 2] + 6*[3, 2, 1]
|
|
90
|
+
sage: a^2 == 6*a
|
|
91
|
+
True
|
|
92
|
+
sage: b = QS3([3, 1, 2])
|
|
93
|
+
sage: b
|
|
94
|
+
[3, 1, 2]
|
|
95
|
+
sage: b*a
|
|
96
|
+
[1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
|
|
97
|
+
sage: b*a == a
|
|
98
|
+
True
|
|
99
|
+
|
|
100
|
+
We now construct the symmetric group algebra by providing
|
|
101
|
+
explicitly the underlying group::
|
|
102
|
+
|
|
103
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, Permutations(4)); SGA
|
|
104
|
+
Symmetric group algebra of order 4 over Rational Field
|
|
105
|
+
sage: SGA.group()
|
|
106
|
+
Standard permutations of 4
|
|
107
|
+
sage: SGA.an_element()
|
|
108
|
+
[1, 2, 3, 4] + 2*[1, 2, 4, 3] + 3*[1, 3, 2, 4] + [4, 1, 2, 3]
|
|
109
|
+
|
|
110
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, SymmetricGroup(4)); SGA
|
|
111
|
+
Symmetric group algebra of order 4 over Rational Field
|
|
112
|
+
sage: SGA.group()
|
|
113
|
+
Symmetric group of order 4! as a permutation group
|
|
114
|
+
sage: SGA.an_element()
|
|
115
|
+
() + (2,3,4) + 2*(1,3)(2,4) + 3*(1,4)(2,3)
|
|
116
|
+
|
|
117
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, WeylGroup(["A",3], prefix='s')); SGA
|
|
118
|
+
Symmetric group algebra of order 4 over Rational Field
|
|
119
|
+
sage: SGA.group()
|
|
120
|
+
Weyl Group of type ['A', 3] (as a matrix group acting
|
|
121
|
+
on the ambient space)
|
|
122
|
+
sage: SGA.an_element()
|
|
123
|
+
s1*s2*s3 + ... + 1
|
|
124
|
+
|
|
125
|
+
The preferred way to construct the symmetric group algebra is to
|
|
126
|
+
go through the usual ``algebra`` method::
|
|
127
|
+
|
|
128
|
+
sage: SGA = Permutations(3).algebra(QQ); SGA
|
|
129
|
+
Symmetric group algebra of order 3 over Rational Field
|
|
130
|
+
sage: SGA.group()
|
|
131
|
+
Standard permutations of 3
|
|
132
|
+
|
|
133
|
+
sage: SGA = SymmetricGroup(3).algebra(QQ); SGA
|
|
134
|
+
Symmetric group algebra of order 3 over Rational Field
|
|
135
|
+
sage: SGA.group()
|
|
136
|
+
Symmetric group of order 3! as a permutation group
|
|
137
|
+
|
|
138
|
+
The canonical embedding from the symmetric group algebra of order
|
|
139
|
+
`n` to the symmetric group algebra of order `p > n` is available as
|
|
140
|
+
a coercion::
|
|
141
|
+
|
|
142
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
|
|
143
|
+
sage: QS4 = SymmetricGroupAlgebra(QQ, 4)
|
|
144
|
+
sage: QS4.coerce_map_from(QS3)
|
|
145
|
+
Generic morphism:
|
|
146
|
+
From: Symmetric group algebra of order 3 over Rational Field
|
|
147
|
+
To: Symmetric group algebra of order 4 over Rational Field
|
|
148
|
+
|
|
149
|
+
sage: x3 = QS3([3,1,2]) + 2 * QS3([2,3,1]); x3
|
|
150
|
+
2*[2, 3, 1] + [3, 1, 2]
|
|
151
|
+
sage: QS4(x3)
|
|
152
|
+
2*[2, 3, 1, 4] + [3, 1, 2, 4]
|
|
153
|
+
|
|
154
|
+
This allows for mixed expressions::
|
|
155
|
+
|
|
156
|
+
sage: x4 = 3 * QS4([3, 1, 4, 2])
|
|
157
|
+
sage: x3 + x4
|
|
158
|
+
2*[2, 3, 1, 4] + [3, 1, 2, 4] + 3*[3, 1, 4, 2]
|
|
159
|
+
|
|
160
|
+
sage: QS0 = SymmetricGroupAlgebra(QQ, 0)
|
|
161
|
+
sage: QS1 = SymmetricGroupAlgebra(QQ, 1)
|
|
162
|
+
sage: x0 = QS0([])
|
|
163
|
+
sage: x1 = QS1([1])
|
|
164
|
+
sage: x0 * x1
|
|
165
|
+
[1]
|
|
166
|
+
sage: x3 - (2*x0 + x1) - x4
|
|
167
|
+
-3*[1, 2, 3, 4] + 2*[2, 3, 1, 4] + [3, 1, 2, 4] - 3*[3, 1, 4, 2]
|
|
168
|
+
|
|
169
|
+
Caveat: to achieve this, constructing ``SymmetricGroupAlgebra(QQ,
|
|
170
|
+
10)`` currently triggers the construction of all symmetric group
|
|
171
|
+
algebras of smaller order. Is this a feature we really want to have?
|
|
172
|
+
|
|
173
|
+
.. WARNING::
|
|
174
|
+
|
|
175
|
+
The semantics of multiplication in symmetric group algebras
|
|
176
|
+
with index set ``Permutations(n)`` is determined by the order
|
|
177
|
+
in which permutations are multiplied, which currently defaults
|
|
178
|
+
to "in such a way that multiplication is associative with
|
|
179
|
+
permutations acting on integers from the right", but can be
|
|
180
|
+
changed to the opposite order at runtime by setting the global
|
|
181
|
+
variable ``Permutations.options['mult']`` (see
|
|
182
|
+
:meth:`sage.combinat.permutation.Permutations.options` ).
|
|
183
|
+
On the other hand, the semantics of multiplication in symmetric
|
|
184
|
+
group algebras with index set ``SymmetricGroup(n)`` does not
|
|
185
|
+
depend on this global variable. (This has the awkward
|
|
186
|
+
consequence that the coercions between these two sorts of
|
|
187
|
+
symmetric group algebras do not respect multiplication when
|
|
188
|
+
this global variable is set to ``'r2l'``.)
|
|
189
|
+
In view of this, it is recommended that code not rely on the
|
|
190
|
+
usual multiplication function, but rather use the methods
|
|
191
|
+
:meth:`left_action_product` and :meth:`right_action_product`
|
|
192
|
+
for multiplying permutations (these methods don't depend on the
|
|
193
|
+
setting). See :issue:`14885` for more information.
|
|
194
|
+
|
|
195
|
+
We conclude by constructing the algebra of the symmetric group as
|
|
196
|
+
a monoid algebra::
|
|
197
|
+
|
|
198
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ, 3, category=Monoids())
|
|
199
|
+
sage: QS3.category()
|
|
200
|
+
Category of finite dimensional cellular monoid algebras
|
|
201
|
+
over Rational Field
|
|
202
|
+
sage: TestSuite(QS3).run(skip=['_test_construction'])
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
TESTS::
|
|
206
|
+
|
|
207
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
|
|
208
|
+
sage: TestSuite(QS3).run()
|
|
209
|
+
|
|
210
|
+
sage: QS3.group()
|
|
211
|
+
Standard permutations of 3
|
|
212
|
+
|
|
213
|
+
sage: QS3.one_basis()
|
|
214
|
+
[1, 2, 3]
|
|
215
|
+
|
|
216
|
+
sage: p1 = Permutation([1,2,3])
|
|
217
|
+
sage: p2 = Permutation([2,1,3])
|
|
218
|
+
sage: QS3.product_on_basis(p1,p2)
|
|
219
|
+
[2, 1, 3]
|
|
220
|
+
|
|
221
|
+
sage: W = WeylGroup(["A",3])
|
|
222
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, W)
|
|
223
|
+
sage: SGA.group() is W
|
|
224
|
+
True
|
|
225
|
+
sage: TestSuite(SGA).run(skip=["_test_cellular", "_test_construction"])
|
|
226
|
+
sage: W = WeylGroup(["A",2])
|
|
227
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, W)
|
|
228
|
+
sage: SGA._test_cellular()
|
|
229
|
+
|
|
230
|
+
sage: SG = SymmetricGroupAlgebra(ZZ, 3)
|
|
231
|
+
sage: SG.group().conjugacy_classes_representatives()
|
|
232
|
+
[[1, 2, 3], [2, 1, 3], [2, 3, 1]]
|
|
233
|
+
|
|
234
|
+
sage: SGg = SymmetricGroup(3).algebra(ZZ)
|
|
235
|
+
sage: SGg.group().conjugacy_classes_representatives()
|
|
236
|
+
[(), (1,2), (1,2,3)]
|
|
237
|
+
"""
|
|
238
|
+
from sage.rings.semirings.non_negative_integer_semiring import NN
|
|
239
|
+
if W in NN:
|
|
240
|
+
W = Permutations(W)
|
|
241
|
+
if category is None:
|
|
242
|
+
category = W.category()
|
|
243
|
+
return SymmetricGroupAlgebra_n(R, W, category.Algebras(R))
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
class SymmetricGroupAlgebra_n(GroupAlgebra_class):
|
|
247
|
+
|
|
248
|
+
def __init__(self, R, W, category):
|
|
249
|
+
"""
|
|
250
|
+
TESTS::
|
|
251
|
+
|
|
252
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
|
|
253
|
+
sage: TestSuite(QS3).run()
|
|
254
|
+
|
|
255
|
+
sage: QS3 in GroupAlgebras(QQ)
|
|
256
|
+
True
|
|
257
|
+
sage: QS3 in FiniteDimensionalAlgebrasWithBasis(QQ)
|
|
258
|
+
True
|
|
259
|
+
|
|
260
|
+
Check that :issue:`16926` works::
|
|
261
|
+
|
|
262
|
+
sage: S = SymmetricGroup(4)
|
|
263
|
+
sage: SGA = S.algebra(QQ)
|
|
264
|
+
sage: TestSuite(SGA).run(skip='_test_cellular')
|
|
265
|
+
sage: SGA._test_cellular() # long time
|
|
266
|
+
|
|
267
|
+
Checking that coercion works between equivalent indexing sets::
|
|
268
|
+
|
|
269
|
+
sage: G = SymmetricGroup(4).algebra(QQ)
|
|
270
|
+
sage: S = SymmetricGroupAlgebra(QQ,4)
|
|
271
|
+
sage: S(G.an_element())
|
|
272
|
+
[1, 2, 3, 4] + [1, 3, 4, 2] + 2*[3, 4, 1, 2] + 3*[4, 3, 2, 1]
|
|
273
|
+
sage: G(S.an_element())
|
|
274
|
+
() + 2*(3,4) + 3*(2,3) + (1,4,3,2)
|
|
275
|
+
|
|
276
|
+
Checking the recovery of `n`:
|
|
277
|
+
|
|
278
|
+
sage: SymmetricGroup(4).algebra(QQ).n
|
|
279
|
+
4
|
|
280
|
+
sage: SymmetricGroup(1).algebra(QQ).n
|
|
281
|
+
1
|
|
282
|
+
sage: SymmetricGroup(0).algebra(QQ).n
|
|
283
|
+
0
|
|
284
|
+
sage: Permutations(4).algebra(QQ).n
|
|
285
|
+
4
|
|
286
|
+
sage: Permutations(1).algebra(QQ).n
|
|
287
|
+
1
|
|
288
|
+
sage: Permutations(0).algebra(QQ).n
|
|
289
|
+
0
|
|
290
|
+
sage: SymmetricGroupAlgebra(QQ, WeylGroup(["A",3])).n
|
|
291
|
+
4
|
|
292
|
+
sage: SymmetricGroupAlgebra(QQ, WeylGroup(["A",1])).n
|
|
293
|
+
2
|
|
294
|
+
sage: SymmetricGroupAlgebra(QQ, WeylGroup(["A",0])).n # todo: not implemented
|
|
295
|
+
1
|
|
296
|
+
"""
|
|
297
|
+
if W not in WeylGroups or W.cartan_type().type() != 'A':
|
|
298
|
+
raise ValueError("W (=%s) should be a symmetric group or a nonnegative integer")
|
|
299
|
+
rank = W.cartan_type().rank()
|
|
300
|
+
if rank == 0: # Ambiguous: n=0 or n=1?
|
|
301
|
+
# The following trick works for both SymmetricGroup(n) and
|
|
302
|
+
# Permutations(n) and it's currently not possible to
|
|
303
|
+
# construct the WeylGroup for n=0
|
|
304
|
+
self.n = W.degree()
|
|
305
|
+
else:
|
|
306
|
+
self.n = W.cartan_type().rank() + 1
|
|
307
|
+
self._idempotent_cache = {}
|
|
308
|
+
category = category.Unital().FiniteDimensional().WithBasis().Cellular()
|
|
309
|
+
GroupAlgebra_class.__init__(self, R, W, prefix='',
|
|
310
|
+
latex_prefix='', category=category)
|
|
311
|
+
|
|
312
|
+
# Mixin class for extra methods for representations
|
|
313
|
+
from sage.combinat.specht_module import SymmetricGroupRepresentation
|
|
314
|
+
self._representation_mixin_class = SymmetricGroupRepresentation
|
|
315
|
+
|
|
316
|
+
def _repr_(self):
|
|
317
|
+
"""
|
|
318
|
+
Return a string representation of ``self``.
|
|
319
|
+
|
|
320
|
+
EXAMPLES::
|
|
321
|
+
|
|
322
|
+
sage: SymmetricGroupAlgebra(QQ, 3)
|
|
323
|
+
Symmetric group algebra of order 3 over Rational Field
|
|
324
|
+
"""
|
|
325
|
+
return "Symmetric group algebra of order {} over {}".format(self.n, self.base_ring())
|
|
326
|
+
|
|
327
|
+
def _coerce_map_from_(self, S):
|
|
328
|
+
"""
|
|
329
|
+
Return ``True`` or a morphism if there exists a coercion from ``S``
|
|
330
|
+
into ``self`` or ``False`` otherwise.
|
|
331
|
+
|
|
332
|
+
EXAMPLES:
|
|
333
|
+
|
|
334
|
+
Symmetric group algebras::
|
|
335
|
+
|
|
336
|
+
sage: SGA4 = SymmetricGroupAlgebra(QQ, 4)
|
|
337
|
+
sage: SGA2 = SymmetricGroupAlgebra(QQ, 2)
|
|
338
|
+
sage: SGA4.has_coerce_map_from(SGA2)
|
|
339
|
+
True
|
|
340
|
+
sage: SGA2Z = SymmetricGroupAlgebra(ZZ, 2)
|
|
341
|
+
sage: SGA4.has_coerce_map_from(SGA2Z)
|
|
342
|
+
True
|
|
343
|
+
sage: p = Permutation([2,1])
|
|
344
|
+
sage: SGA4(-3*SGA2Z.monomial(p))
|
|
345
|
+
-3*[2, 1, 3, 4]
|
|
346
|
+
|
|
347
|
+
Descent algebras::
|
|
348
|
+
|
|
349
|
+
sage: DA = DescentAlgebra(QQ, 4)
|
|
350
|
+
sage: SGA4 = SymmetricGroupAlgebra(QQ, 4)
|
|
351
|
+
sage: SGA4.has_coerce_map_from(DA.D())
|
|
352
|
+
True
|
|
353
|
+
sage: SGA4.has_coerce_map_from(DA.B())
|
|
354
|
+
True
|
|
355
|
+
sage: SGA4.has_coerce_map_from(DA.I())
|
|
356
|
+
True
|
|
357
|
+
sage: x = DA.B()[4]
|
|
358
|
+
sage: SGA4(x)
|
|
359
|
+
[1, 2, 3, 4]
|
|
360
|
+
|
|
361
|
+
sage: DAB = DescentAlgebra(ZZ,2).B()
|
|
362
|
+
sage: SGA4.has_coerce_map_from(DAB)
|
|
363
|
+
True
|
|
364
|
+
sage: SGA4(DAB[2])
|
|
365
|
+
[1, 2, 3, 4]
|
|
366
|
+
|
|
367
|
+
sage: QSG4 = SymmetricGroup(4).algebra(ZZ)
|
|
368
|
+
sage: DAB = DescentAlgebra(ZZ,4).B()
|
|
369
|
+
sage: QSG4(DAB[1,2,1])
|
|
370
|
+
() + (3,4) + (2,3,4) + (1,2) + (1,2)(3,4) + (1,2,3,4)
|
|
371
|
+
+ (1,3,2) + (1,3,4,2) + (1,3,4) + (1,4,3,2) + (1,4,2) + (1,4)
|
|
372
|
+
"""
|
|
373
|
+
# Symmetric group algebras of smaller rank
|
|
374
|
+
if (isinstance(S, SymmetricGroupAlgebra_n) and S.n <= self.n and
|
|
375
|
+
self.base_ring().has_coerce_map_from(S.base_ring())):
|
|
376
|
+
return S.canonical_embedding(self)
|
|
377
|
+
|
|
378
|
+
# Descent algebras
|
|
379
|
+
from sage.combinat.descent_algebra import DescentAlgebra
|
|
380
|
+
# TODO: A better way to handle all of the bases
|
|
381
|
+
if isinstance(S, (DescentAlgebra.D, DescentAlgebra.B, DescentAlgebra.I)):
|
|
382
|
+
# Same rank and base ring, just the natural morphism
|
|
383
|
+
if (S.realization_of()._n == self.n and
|
|
384
|
+
self.base_ring() == S.base_ring() and
|
|
385
|
+
self._indices == Permutations(self.n)):
|
|
386
|
+
return S.to_symmetric_group_algebra
|
|
387
|
+
# Otherwise compose with the canonical embedding in order to ensure
|
|
388
|
+
# that the right base ring and the right index set are being used.
|
|
389
|
+
# Slightly hacky!
|
|
390
|
+
if (S.realization_of()._n <= self.n and
|
|
391
|
+
self.base_ring().has_coerce_map_from(S.base_ring())):
|
|
392
|
+
phi = S.to_symmetric_group_algebra
|
|
393
|
+
return phi.codomain().canonical_embedding(self) * phi
|
|
394
|
+
|
|
395
|
+
return super()._coerce_map_from_(S)
|
|
396
|
+
|
|
397
|
+
def _element_constructor_(self, x):
|
|
398
|
+
"""
|
|
399
|
+
Construct an element of ``self``.
|
|
400
|
+
|
|
401
|
+
EXAMPLES::
|
|
402
|
+
|
|
403
|
+
sage: S = SymmetricGroupAlgebra(QQ, 4)
|
|
404
|
+
sage: G = SymmetricGroup(3)
|
|
405
|
+
sage: p = Permutation((1,2))
|
|
406
|
+
sage: S(p)
|
|
407
|
+
[2, 1, 3, 4]
|
|
408
|
+
sage: S(G(p))
|
|
409
|
+
[2, 1, 3, 4]
|
|
410
|
+
sage: S(p) == S(G(p))
|
|
411
|
+
True
|
|
412
|
+
"""
|
|
413
|
+
if isinstance(x, Permutation):
|
|
414
|
+
return self.monomial_from_smaller_permutation(x)
|
|
415
|
+
if isinstance(x, PermutationGroupElement):
|
|
416
|
+
return self.monomial_from_smaller_permutation(
|
|
417
|
+
from_permutation_group_element(x))
|
|
418
|
+
|
|
419
|
+
return super()._element_constructor_(x)
|
|
420
|
+
|
|
421
|
+
def _sibling(self, n):
|
|
422
|
+
r"""
|
|
423
|
+
Return the sibling group algebra of order `n`.
|
|
424
|
+
|
|
425
|
+
EXAMPLES::
|
|
426
|
+
|
|
427
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, Permutations(3))._sibling(4); SGA
|
|
428
|
+
Symmetric group algebra of order 4 over Rational Field
|
|
429
|
+
sage: SGA.group()
|
|
430
|
+
Standard permutations of 4
|
|
431
|
+
|
|
432
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, SymmetricGroup(3))._sibling(4); SGA
|
|
433
|
+
Symmetric group algebra of order 4 over Rational Field
|
|
434
|
+
sage: SGA.group()
|
|
435
|
+
Symmetric group of order 4! as a permutation group
|
|
436
|
+
|
|
437
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, WeylGroup(["A",2]))._sibling(4); SGA
|
|
438
|
+
Traceback (most recent call last):
|
|
439
|
+
...
|
|
440
|
+
NotImplementedError: Constructing the sibling algebra of a different order
|
|
441
|
+
only implemented for PermutationGroup and SymmetricGroup
|
|
442
|
+
"""
|
|
443
|
+
try:
|
|
444
|
+
W = self.basis().keys().__class__(n)
|
|
445
|
+
except (AttributeError, TypeError, ValueError):
|
|
446
|
+
raise NotImplementedError("Constructing the sibling algebra of a different order "
|
|
447
|
+
"only implemented for PermutationGroup and SymmetricGroup")
|
|
448
|
+
return SymmetricGroupAlgebra(self.base_ring(), W)
|
|
449
|
+
|
|
450
|
+
# _repr_ customization: output the basis element indexed by [1,2,3] as [1,2,3]
|
|
451
|
+
_repr_option_bracket = False
|
|
452
|
+
|
|
453
|
+
def left_action_product(self, left, right):
|
|
454
|
+
"""
|
|
455
|
+
Return the product of two elements ``left`` and ``right`` of
|
|
456
|
+
``self``, where multiplication is defined in such a way that
|
|
457
|
+
for two permutations `p` and `q`, the product `pq` is the
|
|
458
|
+
permutation obtained by first applying `q` and then applying
|
|
459
|
+
`p`. This definition of multiplication is tailored to make
|
|
460
|
+
multiplication of permutations associative with their action on
|
|
461
|
+
numbers if permutations are to act on numbers from the left.
|
|
462
|
+
|
|
463
|
+
EXAMPLES::
|
|
464
|
+
|
|
465
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
|
|
466
|
+
sage: p1 = Permutation([2, 1, 3])
|
|
467
|
+
sage: p2 = Permutation([3, 1, 2])
|
|
468
|
+
sage: QS3.left_action_product(QS3(p1), QS3(p2))
|
|
469
|
+
[3, 2, 1]
|
|
470
|
+
sage: x = QS3([1, 2, 3]) - 2*QS3([1, 3, 2])
|
|
471
|
+
sage: y = 1/2 * QS3([3, 1, 2]) + 3*QS3([1, 2, 3])
|
|
472
|
+
sage: QS3.left_action_product(x, y)
|
|
473
|
+
3*[1, 2, 3] - 6*[1, 3, 2] - [2, 1, 3] + 1/2*[3, 1, 2]
|
|
474
|
+
sage: QS3.left_action_product(0, x)
|
|
475
|
+
0
|
|
476
|
+
|
|
477
|
+
The method coerces its input into the algebra ``self``::
|
|
478
|
+
|
|
479
|
+
sage: QS4 = SymmetricGroupAlgebra(QQ, 4)
|
|
480
|
+
sage: QS4.left_action_product(QS3([1, 2, 3]), QS3([2, 1, 3]))
|
|
481
|
+
[2, 1, 3, 4]
|
|
482
|
+
sage: QS4.left_action_product(1, Permutation([4, 1, 2, 3]))
|
|
483
|
+
[4, 1, 2, 3]
|
|
484
|
+
|
|
485
|
+
TESTS::
|
|
486
|
+
|
|
487
|
+
sage: QS4 = SymmetricGroup(4).algebra(QQ)
|
|
488
|
+
sage: QS4.left_action_product(QS4((1,2)), QS4((2,3)))
|
|
489
|
+
(1,2,3)
|
|
490
|
+
sage: QS4.left_action_product(1, QS4((1,2)))
|
|
491
|
+
(1,2)
|
|
492
|
+
|
|
493
|
+
.. WARNING::
|
|
494
|
+
|
|
495
|
+
Note that coercion presently works from permutations of ``n``
|
|
496
|
+
into the ``n``-th symmetric group algebra, and also from all
|
|
497
|
+
smaller symmetric group algebras into the ``n``-th symmetric
|
|
498
|
+
group algebra, but not from permutations of integers smaller
|
|
499
|
+
than ``n`` into the ``n``-th symmetric group algebra.
|
|
500
|
+
"""
|
|
501
|
+
a = self(left)
|
|
502
|
+
b = self(right)
|
|
503
|
+
if not isinstance(self._indices, Permutations):
|
|
504
|
+
return b * a
|
|
505
|
+
P = Permutations(self.n)
|
|
506
|
+
return self.sum_of_terms([(P(left_action_same_n(p._list, q._list)), x * y)
|
|
507
|
+
for (p, x) in a for (q, y) in b])
|
|
508
|
+
# Why did we use left_action_same_n instead of
|
|
509
|
+
# left_action_product?
|
|
510
|
+
# Because having cast a and b into self, we already know that
|
|
511
|
+
# p and q are permutations of the same number of elements,
|
|
512
|
+
# and thus we don't need to waste our time on the input
|
|
513
|
+
# sanitizing of left_action_product.
|
|
514
|
+
|
|
515
|
+
def right_action_product(self, left, right):
|
|
516
|
+
"""
|
|
517
|
+
Return the product of two elements ``left`` and ``right`` of
|
|
518
|
+
``self``, where multiplication is defined in such a way that
|
|
519
|
+
for two permutations `p` and `q`, the product `pq` is the
|
|
520
|
+
permutation obtained by first applying `p` and then applying
|
|
521
|
+
`q`. This definition of multiplication is tailored to make
|
|
522
|
+
multiplication of permutations associative with their action on
|
|
523
|
+
numbers if permutations are to act on numbers from the right.
|
|
524
|
+
|
|
525
|
+
EXAMPLES::
|
|
526
|
+
|
|
527
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
|
|
528
|
+
sage: p1 = Permutation([2, 1, 3])
|
|
529
|
+
sage: p2 = Permutation([3, 1, 2])
|
|
530
|
+
sage: QS3.right_action_product(QS3(p1), QS3(p2))
|
|
531
|
+
[1, 3, 2]
|
|
532
|
+
sage: x = QS3([1, 2, 3]) - 2*QS3([1, 3, 2])
|
|
533
|
+
sage: y = 1/2 * QS3([3, 1, 2]) + 3*QS3([1, 2, 3])
|
|
534
|
+
sage: QS3.right_action_product(x, y)
|
|
535
|
+
3*[1, 2, 3] - 6*[1, 3, 2] + 1/2*[3, 1, 2] - [3, 2, 1]
|
|
536
|
+
sage: QS3.right_action_product(0, x)
|
|
537
|
+
0
|
|
538
|
+
|
|
539
|
+
The method coerces its input into the algebra ``self``::
|
|
540
|
+
|
|
541
|
+
sage: QS4 = SymmetricGroupAlgebra(QQ, 4)
|
|
542
|
+
sage: QS4.right_action_product(QS3([1, 2, 3]), QS3([2, 1, 3]))
|
|
543
|
+
[2, 1, 3, 4]
|
|
544
|
+
sage: QS4.right_action_product(1, Permutation([4, 1, 2, 3]))
|
|
545
|
+
[4, 1, 2, 3]
|
|
546
|
+
|
|
547
|
+
TESTS::
|
|
548
|
+
|
|
549
|
+
sage: QS4 = SymmetricGroup(4).algebra(QQ)
|
|
550
|
+
sage: QS4.right_action_product(QS4((1,2)), QS4((2,3)))
|
|
551
|
+
(1,3,2)
|
|
552
|
+
sage: QS4.right_action_product(1, QS4((1,2)))
|
|
553
|
+
(1,2)
|
|
554
|
+
|
|
555
|
+
.. WARNING::
|
|
556
|
+
|
|
557
|
+
Note that coercion presently works from permutations of ``n``
|
|
558
|
+
into the ``n``-th symmetric group algebra, and also from all
|
|
559
|
+
smaller symmetric group algebras into the ``n``-th symmetric
|
|
560
|
+
group algebra, but not from permutations of integers smaller
|
|
561
|
+
than ``n`` into the ``n``-th symmetric group algebra.
|
|
562
|
+
"""
|
|
563
|
+
a = self(left)
|
|
564
|
+
b = self(right)
|
|
565
|
+
if not isinstance(self._indices, Permutations):
|
|
566
|
+
return a * b
|
|
567
|
+
P = Permutations(self.n)
|
|
568
|
+
return self.sum_of_terms([(P(right_action_same_n(p._list, q._list)), x * y)
|
|
569
|
+
for (p, x) in a for (q, y) in b])
|
|
570
|
+
# Why did we use right_action_same_n instead of
|
|
571
|
+
# right_action_product?
|
|
572
|
+
# Because having cast a and b into self, we already know that
|
|
573
|
+
# p and q are permutations of the same number of elements,
|
|
574
|
+
# and thus we don't need to waste our time on the input
|
|
575
|
+
# sanitizing of right_action_product.
|
|
576
|
+
|
|
577
|
+
def canonical_embedding(self, other):
|
|
578
|
+
r"""
|
|
579
|
+
Return the canonical coercion of ``self`` into a symmetric
|
|
580
|
+
group algebra ``other``.
|
|
581
|
+
|
|
582
|
+
INPUT:
|
|
583
|
+
|
|
584
|
+
- ``other`` -- a symmetric group algebra with order `p`
|
|
585
|
+
satisfying `p \geq n`, where `n` is the order of ``self``,
|
|
586
|
+
over a ground ring into which the ground ring of ``self``
|
|
587
|
+
coerces.
|
|
588
|
+
|
|
589
|
+
EXAMPLES::
|
|
590
|
+
|
|
591
|
+
sage: QS2 = SymmetricGroupAlgebra(QQ, 2)
|
|
592
|
+
sage: QS4 = SymmetricGroupAlgebra(QQ, 4)
|
|
593
|
+
sage: phi = QS2.canonical_embedding(QS4); phi
|
|
594
|
+
Generic morphism:
|
|
595
|
+
From: Symmetric group algebra of order 2 over Rational Field
|
|
596
|
+
To: Symmetric group algebra of order 4 over Rational Field
|
|
597
|
+
|
|
598
|
+
sage: x = QS2([2,1]) + 2 * QS2([1,2])
|
|
599
|
+
sage: phi(x)
|
|
600
|
+
2*[1, 2, 3, 4] + [2, 1, 3, 4]
|
|
601
|
+
|
|
602
|
+
sage: loads(dumps(phi))
|
|
603
|
+
Generic morphism:
|
|
604
|
+
From: Symmetric group algebra of order 2 over Rational Field
|
|
605
|
+
To: Symmetric group algebra of order 4 over Rational Field
|
|
606
|
+
|
|
607
|
+
sage: ZS2 = SymmetricGroupAlgebra(ZZ, 2)
|
|
608
|
+
sage: phi = ZS2.canonical_embedding(QS4); phi
|
|
609
|
+
Generic morphism:
|
|
610
|
+
From: Symmetric group algebra of order 2 over Integer Ring
|
|
611
|
+
To: Symmetric group algebra of order 4 over Rational Field
|
|
612
|
+
|
|
613
|
+
sage: phi = ZS2.canonical_embedding(QS2); phi
|
|
614
|
+
Generic morphism:
|
|
615
|
+
From: Symmetric group algebra of order 2 over Integer Ring
|
|
616
|
+
To: Symmetric group algebra of order 2 over Rational Field
|
|
617
|
+
|
|
618
|
+
sage: QS4.canonical_embedding(QS2)
|
|
619
|
+
Traceback (most recent call last):
|
|
620
|
+
...
|
|
621
|
+
ValueError: There is no canonical embedding from Symmetric group
|
|
622
|
+
algebra of order 2 over Rational Field to Symmetric group
|
|
623
|
+
algebra of order 4 over Rational Field
|
|
624
|
+
|
|
625
|
+
sage: QS4g = SymmetricGroup(4).algebra(QQ)
|
|
626
|
+
sage: QS4.canonical_embedding(QS4g)(QS4([1,3,2,4]))
|
|
627
|
+
(2,3)
|
|
628
|
+
sage: QS4g.canonical_embedding(QS4)(QS4g((2,3)))
|
|
629
|
+
[1, 3, 2, 4]
|
|
630
|
+
sage: ZS2.canonical_embedding(QS4g)(ZS2([2,1]))
|
|
631
|
+
(1,2)
|
|
632
|
+
sage: ZS2g = SymmetricGroup(2).algebra(ZZ)
|
|
633
|
+
sage: ZS2g.canonical_embedding(QS4)(ZS2g((1,2)))
|
|
634
|
+
[2, 1, 3, 4]
|
|
635
|
+
"""
|
|
636
|
+
if not isinstance(other, SymmetricGroupAlgebra_n) or self.n > other.n:
|
|
637
|
+
raise ValueError("There is no canonical embedding from {0} to {1}".format(other, self))
|
|
638
|
+
return self.module_morphism(other.monomial_from_smaller_permutation, codomain=other) # category = self.category() (currently broken)
|
|
639
|
+
|
|
640
|
+
def monomial_from_smaller_permutation(self, permutation):
|
|
641
|
+
"""
|
|
642
|
+
Convert ``permutation`` into a permutation, possibly extending it
|
|
643
|
+
to the appropriate size, and return the corresponding basis
|
|
644
|
+
element of ``self``.
|
|
645
|
+
|
|
646
|
+
EXAMPLES::
|
|
647
|
+
|
|
648
|
+
sage: QS5 = SymmetricGroupAlgebra(QQ, 5)
|
|
649
|
+
sage: QS5.monomial_from_smaller_permutation([])
|
|
650
|
+
[1, 2, 3, 4, 5]
|
|
651
|
+
sage: QS5.monomial_from_smaller_permutation(Permutation([3,1,2]))
|
|
652
|
+
[3, 1, 2, 4, 5]
|
|
653
|
+
sage: QS5.monomial_from_smaller_permutation([5,3,4,1,2])
|
|
654
|
+
[5, 3, 4, 1, 2]
|
|
655
|
+
sage: QS5.monomial_from_smaller_permutation(SymmetricGroup(2)((1,2)))
|
|
656
|
+
[2, 1, 3, 4, 5]
|
|
657
|
+
|
|
658
|
+
sage: QS5g = SymmetricGroup(5).algebra(QQ)
|
|
659
|
+
sage: QS5g.monomial_from_smaller_permutation([2,1])
|
|
660
|
+
(1,2)
|
|
661
|
+
|
|
662
|
+
TESTS::
|
|
663
|
+
|
|
664
|
+
sage: QS5.monomial_from_smaller_permutation([5,3,4,1,2]).parent()
|
|
665
|
+
Symmetric group algebra of order 5 over Rational Field
|
|
666
|
+
"""
|
|
667
|
+
P = self.basis().keys()
|
|
668
|
+
return self.monomial(P(permutation))
|
|
669
|
+
|
|
670
|
+
def antipode(self, x):
|
|
671
|
+
r"""
|
|
672
|
+
Return the image of the element ``x`` of ``self`` under the
|
|
673
|
+
antipode of the Hopf algebra ``self`` (where the
|
|
674
|
+
comultiplication is the usual one on a group algebra).
|
|
675
|
+
|
|
676
|
+
Explicitly, this is obtained by replacing each permutation
|
|
677
|
+
`\sigma` by `\sigma^{-1}` in ``x`` while keeping all
|
|
678
|
+
coefficients as they are.
|
|
679
|
+
|
|
680
|
+
EXAMPLES::
|
|
681
|
+
|
|
682
|
+
sage: QS4 = SymmetricGroupAlgebra(QQ, 4)
|
|
683
|
+
sage: QS4.antipode(2 * QS4([1, 3, 4, 2]) - 1/2 * QS4([1, 4, 2, 3]))
|
|
684
|
+
-1/2*[1, 3, 4, 2] + 2*[1, 4, 2, 3]
|
|
685
|
+
sage: all( QS4.antipode(QS4(p)) == QS4(p.inverse())
|
|
686
|
+
....: for p in Permutations(4) )
|
|
687
|
+
True
|
|
688
|
+
|
|
689
|
+
sage: ZS3 = SymmetricGroupAlgebra(ZZ, 3)
|
|
690
|
+
sage: ZS3.antipode(ZS3.zero())
|
|
691
|
+
0
|
|
692
|
+
sage: ZS3.antipode(-ZS3(Permutation([2, 3, 1])))
|
|
693
|
+
-[3, 1, 2]
|
|
694
|
+
"""
|
|
695
|
+
return self.sum_of_terms([(p.inverse(), coeff) for
|
|
696
|
+
(p, coeff) in self(x)],
|
|
697
|
+
distinct=True)
|
|
698
|
+
|
|
699
|
+
@cached_method
|
|
700
|
+
def cell_poset(self):
|
|
701
|
+
"""
|
|
702
|
+
Return the cell poset of ``self``.
|
|
703
|
+
|
|
704
|
+
EXAMPLES::
|
|
705
|
+
|
|
706
|
+
sage: S = SymmetricGroupAlgebra(QQ, 4)
|
|
707
|
+
sage: S.cell_poset()
|
|
708
|
+
Finite poset containing 5 elements
|
|
709
|
+
"""
|
|
710
|
+
from sage.combinat.posets.posets import Poset
|
|
711
|
+
return Poset([Partitions_n(self.n), lambda x, y: y.dominates(x)])
|
|
712
|
+
|
|
713
|
+
def cell_module_indices(self, la):
|
|
714
|
+
r"""
|
|
715
|
+
Return the indices of the cell module of ``self``
|
|
716
|
+
indexed by ``la`` .
|
|
717
|
+
|
|
718
|
+
This is the finite set `M(\lambda)`.
|
|
719
|
+
|
|
720
|
+
EXAMPLES::
|
|
721
|
+
|
|
722
|
+
sage: S = SymmetricGroupAlgebra(QQ, 4)
|
|
723
|
+
sage: S.cell_module_indices([3,1])
|
|
724
|
+
Standard tableaux of shape [3, 1]
|
|
725
|
+
"""
|
|
726
|
+
return StandardTableaux(la)
|
|
727
|
+
|
|
728
|
+
def _from_cellular_index(self, x):
|
|
729
|
+
r"""
|
|
730
|
+
Return the image in ``self`` from the index of the
|
|
731
|
+
cellular basis ``x``.
|
|
732
|
+
|
|
733
|
+
EXAMPLES::
|
|
734
|
+
|
|
735
|
+
sage: S = SymmetricGroupAlgebra(QQ, 3)
|
|
736
|
+
sage: C = S.cellular_basis()
|
|
737
|
+
sage: [S._from_cellular_index(i) for i in C.basis().keys()]
|
|
738
|
+
[1/6*[1, 2, 3] - 1/6*[1, 3, 2] - 1/6*[2, 1, 3] + 1/6*[2, 3, 1]
|
|
739
|
+
+ 1/6*[3, 1, 2] - 1/6*[3, 2, 1],
|
|
740
|
+
1/3*[1, 2, 3] + 1/6*[1, 3, 2] - 1/3*[2, 1, 3] - 1/6*[2, 3, 1]
|
|
741
|
+
- 1/6*[3, 1, 2] + 1/6*[3, 2, 1],
|
|
742
|
+
1/3*[1, 3, 2] + 1/3*[2, 3, 1] - 1/3*[3, 1, 2] - 1/3*[3, 2, 1],
|
|
743
|
+
1/4*[1, 3, 2] - 1/4*[2, 3, 1] + 1/4*[3, 1, 2] - 1/4*[3, 2, 1],
|
|
744
|
+
1/3*[1, 2, 3] - 1/6*[1, 3, 2] + 1/3*[2, 1, 3] - 1/6*[2, 3, 1]
|
|
745
|
+
- 1/6*[3, 1, 2] - 1/6*[3, 2, 1],
|
|
746
|
+
1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3]
|
|
747
|
+
+ 1/6*[2, 3, 1] + 1/6*[3, 1, 2] + 1/6*[3, 2, 1]]
|
|
748
|
+
|
|
749
|
+
sage: S = SymmetricGroupAlgebra(GF(3), 3)
|
|
750
|
+
sage: C = S.cellular_basis()
|
|
751
|
+
sage: [S._from_cellular_index(i) for i in C.basis().keys()]
|
|
752
|
+
[[1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1],
|
|
753
|
+
[1, 2, 3] + [2, 1, 3],
|
|
754
|
+
[1, 3, 2] + [3, 1, 2],
|
|
755
|
+
[1, 3, 2] + [2, 3, 1],
|
|
756
|
+
[1, 2, 3] + [3, 2, 1],
|
|
757
|
+
[1, 2, 3]]
|
|
758
|
+
sage: TestSuite(C).run()
|
|
759
|
+
"""
|
|
760
|
+
if ~factorial(self.n) not in self.base_ring():
|
|
761
|
+
func = self.murphy_basis_element
|
|
762
|
+
else:
|
|
763
|
+
func = self.epsilon_ik
|
|
764
|
+
|
|
765
|
+
SGA = SymmetricGroupAlgebra(self.base_ring(), self.n)
|
|
766
|
+
P = self.basis().keys()
|
|
767
|
+
if SGA.basis().keys() is P: # Indexed by permutations
|
|
768
|
+
return func(x[1], x[2])
|
|
769
|
+
from sage.groups.perm_gps.permgroup_named import SymmetricGroup
|
|
770
|
+
if P == SymmetricGroup(self.n):
|
|
771
|
+
return func(x[1], x[2])
|
|
772
|
+
ret = func(x[1], x[2], mult='r2l')
|
|
773
|
+
try:
|
|
774
|
+
return self(ret)
|
|
775
|
+
except TypeError:
|
|
776
|
+
P = self.basis().keys()
|
|
777
|
+
return self._from_dict({P(i.to_matrix()): c for i, c in ret},
|
|
778
|
+
remove_zeros=False)
|
|
779
|
+
|
|
780
|
+
def cell_module(self, la, **kwds):
|
|
781
|
+
"""
|
|
782
|
+
Return the cell module indexed by ``la``.
|
|
783
|
+
|
|
784
|
+
EXAMPLES::
|
|
785
|
+
|
|
786
|
+
sage: S = SymmetricGroupAlgebra(QQ, 3)
|
|
787
|
+
sage: M = S.cell_module(Partition([2,1])); M
|
|
788
|
+
Cell module indexed by [2, 1] of Cellular basis of
|
|
789
|
+
Symmetric group algebra of order 3 over Rational Field
|
|
790
|
+
|
|
791
|
+
We check that the input ``la`` is standardized::
|
|
792
|
+
|
|
793
|
+
sage: N = S.cell_module([2,1])
|
|
794
|
+
sage: M is N
|
|
795
|
+
True
|
|
796
|
+
"""
|
|
797
|
+
la = _Partitions(la)
|
|
798
|
+
kwds['bracket'] = kwds.get('bracket', False)
|
|
799
|
+
return super().cell_module(la, **kwds)
|
|
800
|
+
|
|
801
|
+
def retract_plain(self, f, m):
|
|
802
|
+
r"""
|
|
803
|
+
Return the plain retract of the element `f \in R S_n`
|
|
804
|
+
to `R S_m`, where `m \leq n` (and where `R S_n` is ``self``).
|
|
805
|
+
|
|
806
|
+
If `m` is a nonnegative integer less or equal to `n`, then the
|
|
807
|
+
plain retract from `S_n` to `S_m` is defined as an `R`-linear
|
|
808
|
+
map `S_n \to S_m` which sends every permutation `p \in S_n`
|
|
809
|
+
to
|
|
810
|
+
|
|
811
|
+
.. MATH::
|
|
812
|
+
|
|
813
|
+
\begin{cases} \mbox{pret}(p) &\mbox{if } \mbox{pret}(p)\mbox{ is defined;} \\
|
|
814
|
+
0 & \mbox{otherwise} \end{cases}.
|
|
815
|
+
|
|
816
|
+
Here `\mbox{pret}(p)` denotes the plain retract of the
|
|
817
|
+
permutation `p` to `S_m`, which is defined in
|
|
818
|
+
:meth:`~sage.combinat.permutation.Permutation.retract_plain`.
|
|
819
|
+
|
|
820
|
+
EXAMPLES::
|
|
821
|
+
|
|
822
|
+
sage: SGA3 = SymmetricGroupAlgebra(QQ, 3)
|
|
823
|
+
sage: SGA3.retract_plain(2*SGA3([1,2,3]) - 4*SGA3([2,1,3]) + 7*SGA3([1,3,2]), 2)
|
|
824
|
+
2*[1, 2] - 4*[2, 1]
|
|
825
|
+
sage: SGA3.retract_plain(2*SGA3([1,3,2]) - 5*SGA3([2,3,1]), 2)
|
|
826
|
+
0
|
|
827
|
+
|
|
828
|
+
sage: SGA5 = SymmetricGroupAlgebra(QQ, 5)
|
|
829
|
+
sage: SGA5.retract_plain(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 4)
|
|
830
|
+
11*[3, 2, 1, 4]
|
|
831
|
+
sage: SGA5.retract_plain(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 3)
|
|
832
|
+
11*[3, 2, 1]
|
|
833
|
+
sage: SGA5.retract_plain(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 2)
|
|
834
|
+
0
|
|
835
|
+
sage: SGA5.retract_plain(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 1)
|
|
836
|
+
0
|
|
837
|
+
|
|
838
|
+
sage: SGA5.retract_plain(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 3)
|
|
839
|
+
8*[1, 2, 3] - 6*[1, 3, 2]
|
|
840
|
+
sage: SGA5.retract_plain(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 1)
|
|
841
|
+
8*[1]
|
|
842
|
+
sage: SGA5.retract_plain(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 0)
|
|
843
|
+
8*[]
|
|
844
|
+
|
|
845
|
+
TESTS:
|
|
846
|
+
|
|
847
|
+
Check this works with other indexing sets::
|
|
848
|
+
|
|
849
|
+
sage: G = SymmetricGroup(4).algebra(QQ)
|
|
850
|
+
sage: G.retract_plain(G.an_element(), 3)
|
|
851
|
+
()
|
|
852
|
+
|
|
853
|
+
.. SEEALSO::
|
|
854
|
+
|
|
855
|
+
:meth:`retract_direct_product`, :meth:`retract_okounkov_vershik`
|
|
856
|
+
"""
|
|
857
|
+
RSm = self._sibling(m)
|
|
858
|
+
I = RSm.group()
|
|
859
|
+
pairs = []
|
|
860
|
+
P = Permutations(self.n)
|
|
861
|
+
for (p, coeff) in f.monomial_coefficients().items():
|
|
862
|
+
p_ret = P(p).retract_plain(m)
|
|
863
|
+
if p_ret is not None:
|
|
864
|
+
pairs.append((I(p_ret), coeff))
|
|
865
|
+
return RSm.sum_of_terms(pairs, distinct=True)
|
|
866
|
+
|
|
867
|
+
def retract_direct_product(self, f, m):
|
|
868
|
+
r"""
|
|
869
|
+
Return the direct-product retract of the element `f \in R S_n`
|
|
870
|
+
to `R S_m`, where `m \leq n` (and where `R S_n` is ``self``).
|
|
871
|
+
|
|
872
|
+
If `m` is a nonnegative integer less or equal to `n`, then the
|
|
873
|
+
direct-product retract from `S_n` to `S_m` is defined as an
|
|
874
|
+
`R`-linear map `S_n \to S_m` which sends every permutation
|
|
875
|
+
`p \in S_n` to
|
|
876
|
+
|
|
877
|
+
.. MATH::
|
|
878
|
+
|
|
879
|
+
\begin{cases} \mbox{dret}(p) &\mbox{if } \mbox{dret}(p)\mbox{ is defined;} \\
|
|
880
|
+
0 & \mbox{otherwise} \end{cases}.
|
|
881
|
+
|
|
882
|
+
Here `\mbox{dret}(p)` denotes the direct-product retract of the
|
|
883
|
+
permutation `p` to `S_m`, which is defined in
|
|
884
|
+
:meth:`~sage.combinat.permutation.Permutation.retract_direct_product`.
|
|
885
|
+
|
|
886
|
+
EXAMPLES::
|
|
887
|
+
|
|
888
|
+
sage: SGA3 = SymmetricGroupAlgebra(QQ, 3)
|
|
889
|
+
sage: SGA3.retract_direct_product(2*SGA3([1,2,3]) - 4*SGA3([2,1,3]) + 7*SGA3([1,3,2]), 2)
|
|
890
|
+
2*[1, 2] - 4*[2, 1]
|
|
891
|
+
sage: SGA3.retract_direct_product(2*SGA3([1,3,2]) - 5*SGA3([2,3,1]), 2)
|
|
892
|
+
0
|
|
893
|
+
|
|
894
|
+
sage: SGA5 = SymmetricGroupAlgebra(QQ, 5)
|
|
895
|
+
sage: SGA5.retract_direct_product(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 4)
|
|
896
|
+
11*[3, 2, 1, 4]
|
|
897
|
+
sage: SGA5.retract_direct_product(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 3)
|
|
898
|
+
-6*[1, 3, 2] + 11*[3, 2, 1]
|
|
899
|
+
sage: SGA5.retract_direct_product(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 2)
|
|
900
|
+
0
|
|
901
|
+
sage: SGA5.retract_direct_product(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 1)
|
|
902
|
+
2*[1]
|
|
903
|
+
|
|
904
|
+
sage: SGA5.retract_direct_product(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 3)
|
|
905
|
+
8*[1, 2, 3] - 6*[1, 3, 2]
|
|
906
|
+
sage: SGA5.retract_direct_product(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 1)
|
|
907
|
+
2*[1]
|
|
908
|
+
sage: SGA5.retract_direct_product(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 0)
|
|
909
|
+
2*[]
|
|
910
|
+
|
|
911
|
+
TESTS:
|
|
912
|
+
|
|
913
|
+
Check this works with other indexing sets::
|
|
914
|
+
|
|
915
|
+
sage: G = SymmetricGroup(4).algebra(QQ)
|
|
916
|
+
sage: G.retract_direct_product(G.an_element(), 3)
|
|
917
|
+
()
|
|
918
|
+
|
|
919
|
+
.. SEEALSO::
|
|
920
|
+
|
|
921
|
+
:meth:`retract_plain`, :meth:`retract_okounkov_vershik`
|
|
922
|
+
"""
|
|
923
|
+
RSm = self._sibling(m)
|
|
924
|
+
I = RSm.group()
|
|
925
|
+
dct = {}
|
|
926
|
+
P = Permutations(self.n)
|
|
927
|
+
for (p, coeff) in f.monomial_coefficients().items():
|
|
928
|
+
p_ret = P(p).retract_direct_product(m)
|
|
929
|
+
if p_ret is not None:
|
|
930
|
+
p_ret = I(p_ret)
|
|
931
|
+
if p_ret not in dct:
|
|
932
|
+
dct[p_ret] = coeff
|
|
933
|
+
else:
|
|
934
|
+
dct[p_ret] += coeff
|
|
935
|
+
return RSm._from_dict(dct)
|
|
936
|
+
|
|
937
|
+
def retract_okounkov_vershik(self, f, m):
|
|
938
|
+
r"""
|
|
939
|
+
Return the Okounkov-Vershik retract of the element `f \in R S_n`
|
|
940
|
+
to `R S_m`, where `m \leq n` (and where `R S_n` is ``self``).
|
|
941
|
+
|
|
942
|
+
If `m` is a nonnegative integer less or equal to `n`, then the
|
|
943
|
+
Okounkov-Vershik retract from `S_n` to `S_m` is defined as an
|
|
944
|
+
`R`-linear map `S_n \to S_m` which sends every permutation
|
|
945
|
+
`p \in S_n` to the Okounkov-Vershik retract of the permutation
|
|
946
|
+
`p` to `S_m`, which is defined in
|
|
947
|
+
:meth:`~sage.combinat.permutation.Permutation.retract_okounkov_vershik`.
|
|
948
|
+
|
|
949
|
+
EXAMPLES::
|
|
950
|
+
|
|
951
|
+
sage: SGA3 = SymmetricGroupAlgebra(QQ, 3)
|
|
952
|
+
sage: SGA3.retract_okounkov_vershik(2*SGA3([1,2,3]) - 4*SGA3([2,1,3]) + 7*SGA3([1,3,2]), 2)
|
|
953
|
+
9*[1, 2] - 4*[2, 1]
|
|
954
|
+
sage: SGA3.retract_okounkov_vershik(2*SGA3([1,3,2]) - 5*SGA3([2,3,1]), 2)
|
|
955
|
+
2*[1, 2] - 5*[2, 1]
|
|
956
|
+
|
|
957
|
+
sage: SGA5 = SymmetricGroupAlgebra(QQ, 5)
|
|
958
|
+
sage: SGA5.retract_okounkov_vershik(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 4)
|
|
959
|
+
-6*[1, 3, 2, 4] + 8*[1, 4, 2, 3] + 11*[3, 2, 1, 4]
|
|
960
|
+
sage: SGA5.retract_okounkov_vershik(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 3)
|
|
961
|
+
2*[1, 3, 2] + 11*[3, 2, 1]
|
|
962
|
+
sage: SGA5.retract_okounkov_vershik(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 2)
|
|
963
|
+
13*[1, 2]
|
|
964
|
+
sage: SGA5.retract_okounkov_vershik(8*SGA5([1,4,2,5,3]) - 6*SGA5([1,3,2,5,4]) + 11*SGA5([3,2,1,4,5]), 1)
|
|
965
|
+
13*[1]
|
|
966
|
+
|
|
967
|
+
sage: SGA5.retract_okounkov_vershik(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 3)
|
|
968
|
+
8*[1, 2, 3] - 6*[1, 3, 2]
|
|
969
|
+
sage: SGA5.retract_okounkov_vershik(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 1)
|
|
970
|
+
2*[1]
|
|
971
|
+
sage: SGA5.retract_okounkov_vershik(8*SGA5([1,2,3,4,5]) - 6*SGA5([1,3,2,4,5]), 0)
|
|
972
|
+
2*[]
|
|
973
|
+
|
|
974
|
+
TESTS:
|
|
975
|
+
|
|
976
|
+
Check this works with other indexing sets::
|
|
977
|
+
|
|
978
|
+
sage: G = SymmetricGroup(4).algebra(QQ)
|
|
979
|
+
sage: G.retract_okounkov_vershik(G.an_element(), 3)
|
|
980
|
+
() + 4*(2,3) + 2*(1,3)
|
|
981
|
+
|
|
982
|
+
.. SEEALSO::
|
|
983
|
+
|
|
984
|
+
:meth:`retract_plain`, :meth:`retract_direct_product`
|
|
985
|
+
"""
|
|
986
|
+
RSm = self._sibling(m)
|
|
987
|
+
I = RSm.group()
|
|
988
|
+
dct = {}
|
|
989
|
+
P = Permutations(self.n)
|
|
990
|
+
for (p, coeff) in f.monomial_coefficients().items():
|
|
991
|
+
p_ret = I(P(p).retract_okounkov_vershik(m))
|
|
992
|
+
if p_ret not in dct:
|
|
993
|
+
dct[p_ret] = coeff
|
|
994
|
+
else:
|
|
995
|
+
dct[p_ret] += coeff
|
|
996
|
+
return RSm._from_dict(dct)
|
|
997
|
+
|
|
998
|
+
def central_orthogonal_idempotents(self):
|
|
999
|
+
r"""
|
|
1000
|
+
Return a maximal list of central orthogonal idempotents for ``self``.
|
|
1001
|
+
|
|
1002
|
+
This method does not require that ``self`` be semisimple, relying
|
|
1003
|
+
on Nakayama's Conjecture whenever ``self.base_ring()`` has
|
|
1004
|
+
positive characteristic.
|
|
1005
|
+
|
|
1006
|
+
EXAMPLES::
|
|
1007
|
+
|
|
1008
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ,3)
|
|
1009
|
+
sage: a = QS3.central_orthogonal_idempotents()
|
|
1010
|
+
sage: a[0] # [3]
|
|
1011
|
+
1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3] + 1/6*[2, 3, 1]
|
|
1012
|
+
+ 1/6*[3, 1, 2] + 1/6*[3, 2, 1]
|
|
1013
|
+
sage: a[1] # [2, 1]
|
|
1014
|
+
2/3*[1, 2, 3] - 1/3*[2, 3, 1] - 1/3*[3, 1, 2]
|
|
1015
|
+
|
|
1016
|
+
TESTS:
|
|
1017
|
+
|
|
1018
|
+
Check this works with other indexing sets::
|
|
1019
|
+
|
|
1020
|
+
sage: G = SymmetricGroup(3).algebra(QQ)
|
|
1021
|
+
sage: a = G.central_orthogonal_idempotents()
|
|
1022
|
+
sage: a[0]
|
|
1023
|
+
1/6*() + 1/6*(2,3) + 1/6*(1,2) + 1/6*(1,2,3) + 1/6*(1,3,2) + 1/6*(1,3)
|
|
1024
|
+
sage: a[1]
|
|
1025
|
+
2/3*() - 1/3*(1,2,3) - 1/3*(1,3,2)
|
|
1026
|
+
|
|
1027
|
+
sage: G = SymmetricGroup(3).algebra(GF(2))
|
|
1028
|
+
sage: a = G.central_orthogonal_idempotents()
|
|
1029
|
+
sage: a[0]
|
|
1030
|
+
(1,2,3) + (1,3,2)
|
|
1031
|
+
sage: a[1]
|
|
1032
|
+
() + (1,2,3) + (1,3,2)
|
|
1033
|
+
|
|
1034
|
+
Check this works in positive characteristic::
|
|
1035
|
+
|
|
1036
|
+
sage: def test_n_with_primes(n, primes):
|
|
1037
|
+
....: Sn = {p:SymmetricGroupAlgebra(GF(p), n) for p in primes}
|
|
1038
|
+
....: for p in primes:
|
|
1039
|
+
....: idems = Sn[p].central_orthogonal_idempotents()
|
|
1040
|
+
....: tst = [sum(idems)==Sn[p].one()]
|
|
1041
|
+
....: for i in range(len(idems)-1):
|
|
1042
|
+
....: e = idems[i]
|
|
1043
|
+
....: for j in range(i, len(idems)):
|
|
1044
|
+
....: f = idems[j]
|
|
1045
|
+
....: if i == j:
|
|
1046
|
+
....: tst.append(e*e == e)
|
|
1047
|
+
....: else:
|
|
1048
|
+
....: tst.append(e*f == 0)
|
|
1049
|
+
....: print("{0} blocks for p={1} ... {2}".format( len(idems), p, all(tst) ))
|
|
1050
|
+
sage: test_n_with_primes(5, [2,3,5,7]) # long time
|
|
1051
|
+
2 blocks for p=2 ... True
|
|
1052
|
+
3 blocks for p=3 ... True
|
|
1053
|
+
3 blocks for p=5 ... True
|
|
1054
|
+
7 blocks for p=7 ... True
|
|
1055
|
+
|
|
1056
|
+
.. SEEALSO::
|
|
1057
|
+
|
|
1058
|
+
- :meth:`central_orthogonal_idempotent`
|
|
1059
|
+
"""
|
|
1060
|
+
return [self.central_orthogonal_idempotent(key)
|
|
1061
|
+
for key in sorted(self._blocks_dictionary, reverse=True)]
|
|
1062
|
+
|
|
1063
|
+
def central_orthogonal_idempotent(self, la, block=True):
|
|
1064
|
+
r"""
|
|
1065
|
+
Return the central idempotent for the symmetric group of order `n`
|
|
1066
|
+
corresponding to the indecomposable block to which the partition
|
|
1067
|
+
``la`` is associated.
|
|
1068
|
+
|
|
1069
|
+
If ``self.base_ring()`` contains `\QQ`, this corresponds to the
|
|
1070
|
+
classical central idempotent corresponding to the irreducible
|
|
1071
|
+
representation indexed by ``la``.
|
|
1072
|
+
|
|
1073
|
+
Alternatively, if ``self.base_ring()`` has characteristic `p > 0`,
|
|
1074
|
+
then Theorem 2.8 in [Mur1983]_ provides that ``la`` is associated
|
|
1075
|
+
to an idempotent `f_\mu`, where `\mu` is the `p`-core of ``la``.
|
|
1076
|
+
This `f_\mu` is a sum of classical idempotents,
|
|
1077
|
+
|
|
1078
|
+
.. MATH::
|
|
1079
|
+
|
|
1080
|
+
f_\mu = \sum_{c(\lambda)=\mu} e_\lambda,
|
|
1081
|
+
|
|
1082
|
+
where the sum ranges over the partitions `\lambda` of `n` with
|
|
1083
|
+
`p`-core equal to `\mu`.
|
|
1084
|
+
|
|
1085
|
+
INPUT:
|
|
1086
|
+
|
|
1087
|
+
- ``la`` -- a partition of ``self.n`` or a
|
|
1088
|
+
``self.base_ring().characteristic()``-core of such
|
|
1089
|
+
a partition
|
|
1090
|
+
|
|
1091
|
+
- ``block`` -- boolean (default: ``True``); when ``False``,
|
|
1092
|
+
this returns the classical idempotent associated to ``la``
|
|
1093
|
+
(defined over `\QQ`)
|
|
1094
|
+
|
|
1095
|
+
OUTPUT:
|
|
1096
|
+
|
|
1097
|
+
If ``block=False`` and the corresponding coefficients are
|
|
1098
|
+
not defined over ``self.base_ring()``, then return ``None``.
|
|
1099
|
+
Otherwise return an element of ``self``.
|
|
1100
|
+
|
|
1101
|
+
EXAMPLES:
|
|
1102
|
+
|
|
1103
|
+
Asking for block idempotents in any characteristic, by
|
|
1104
|
+
passing a partition of ``self.n``::
|
|
1105
|
+
|
|
1106
|
+
sage: S0 = SymmetricGroup(4).algebra(QQ)
|
|
1107
|
+
sage: S2 = SymmetricGroup(4).algebra(GF(2))
|
|
1108
|
+
sage: S3 = SymmetricGroup(4).algebra(GF(3))
|
|
1109
|
+
sage: S0.central_orthogonal_idempotent([2,1,1])
|
|
1110
|
+
3/8*() - 1/8*(3,4) - 1/8*(2,3) - 1/8*(2,4) - 1/8*(1,2)
|
|
1111
|
+
- 1/8*(1,2)(3,4) + 1/8*(1,2,3,4) + 1/8*(1,2,4,3)
|
|
1112
|
+
+ 1/8*(1,3,4,2) - 1/8*(1,3) - 1/8*(1,3)(2,4)
|
|
1113
|
+
+ 1/8*(1,3,2,4) + 1/8*(1,4,3,2) - 1/8*(1,4)
|
|
1114
|
+
+ 1/8*(1,4,2,3) - 1/8*(1,4)(2,3)
|
|
1115
|
+
sage: S2.central_orthogonal_idempotent([2,1,1])
|
|
1116
|
+
()
|
|
1117
|
+
sage: idem = S3.central_orthogonal_idempotent([4]); idem
|
|
1118
|
+
() + (1,2)(3,4) + (1,3)(2,4) + (1,4)(2,3)
|
|
1119
|
+
sage: idem == S3.central_orthogonal_idempotent([1,1,1,1])
|
|
1120
|
+
True
|
|
1121
|
+
sage: S3.central_orthogonal_idempotent([2,2])
|
|
1122
|
+
() + (1,2)(3,4) + (1,3)(2,4) + (1,4)(2,3)
|
|
1123
|
+
|
|
1124
|
+
Asking for block idempotents in any characteristic, by
|
|
1125
|
+
passing `p`-cores::
|
|
1126
|
+
|
|
1127
|
+
sage: S0.central_orthogonal_idempotent([1,1])
|
|
1128
|
+
Traceback (most recent call last):
|
|
1129
|
+
...
|
|
1130
|
+
ValueError: [1, 1] is not a partition of integer 4
|
|
1131
|
+
sage: S2.central_orthogonal_idempotent([])
|
|
1132
|
+
()
|
|
1133
|
+
sage: S2.central_orthogonal_idempotent([1])
|
|
1134
|
+
Traceback (most recent call last):
|
|
1135
|
+
...
|
|
1136
|
+
ValueError: the 2-core of [1] is not a 2-core of a partition of 4
|
|
1137
|
+
sage: S3.central_orthogonal_idempotent([1])
|
|
1138
|
+
() + (1,2)(3,4) + (1,3)(2,4) + (1,4)(2,3)
|
|
1139
|
+
sage: S3.central_orthogonal_idempotent([7])
|
|
1140
|
+
() + (1,2)(3,4) + (1,3)(2,4) + (1,4)(2,3)
|
|
1141
|
+
|
|
1142
|
+
Asking for classical idempotents::
|
|
1143
|
+
|
|
1144
|
+
sage: S3.central_orthogonal_idempotent([2,2], block=False) is None
|
|
1145
|
+
True
|
|
1146
|
+
sage: S3.central_orthogonal_idempotent([2,1,1], block=False)
|
|
1147
|
+
(3,4) + (2,3) + (2,4) + (1,2) + (1,2)(3,4) + 2*(1,2,3,4)
|
|
1148
|
+
+ 2*(1,2,4,3) + 2*(1,3,4,2) + (1,3) + (1,3)(2,4)
|
|
1149
|
+
+ 2*(1,3,2,4) + 2*(1,4,3,2) + (1,4) + 2*(1,4,2,3)
|
|
1150
|
+
+ (1,4)(2,3)
|
|
1151
|
+
|
|
1152
|
+
.. SEEALSO::
|
|
1153
|
+
|
|
1154
|
+
- :meth:`sage.combinat.partition.Partition.core`
|
|
1155
|
+
"""
|
|
1156
|
+
la = _Partitions(la)
|
|
1157
|
+
R = self.base_ring()
|
|
1158
|
+
p = R.characteristic()
|
|
1159
|
+
|
|
1160
|
+
if not block or not p:
|
|
1161
|
+
if la in self._idempotent_cache:
|
|
1162
|
+
return self._idempotent_cache[la]
|
|
1163
|
+
if la.size() != self.n:
|
|
1164
|
+
raise ValueError("{0} is not a partition of integer {1}".format(la, self.n))
|
|
1165
|
+
else:
|
|
1166
|
+
mu = la.core(p)
|
|
1167
|
+
if mu in self._idempotent_cache:
|
|
1168
|
+
return self._idempotent_cache[mu]
|
|
1169
|
+
if mu not in self._blocks_dictionary:
|
|
1170
|
+
raise ValueError("the {1}-core of {0} is not a {1}-core of a partition of {2}".format(la, p, self.n))
|
|
1171
|
+
|
|
1172
|
+
from sage.data_structures.blas_dict import iaxpy
|
|
1173
|
+
from sage.libs.gap.libgap import libgap
|
|
1174
|
+
G = self._indices
|
|
1175
|
+
character_table = [c.sage() for c in libgap.Irr(libgap.SymmetricGroup(self.n))]
|
|
1176
|
+
Pn = Partitions_n(self.n)
|
|
1177
|
+
C = Pn.cardinality()
|
|
1178
|
+
# We get the indices of the partitions in the reverse lex order
|
|
1179
|
+
# (i.e., reverse of the iteration order of partitions).
|
|
1180
|
+
indices = {lam: C - 1 - i for i, lam in enumerate(Pn)}
|
|
1181
|
+
|
|
1182
|
+
if not block or not p:
|
|
1183
|
+
la_index = indices[la]
|
|
1184
|
+
big_coeff = character_table[la_index][0] / factorial(self.n)
|
|
1185
|
+
character_row = character_table[la_index]
|
|
1186
|
+
cpi = {g: big_coeff * character_row[indices[g.cycle_type()]]
|
|
1187
|
+
for g in G}
|
|
1188
|
+
else:
|
|
1189
|
+
# We compute the cycle types of the permutations
|
|
1190
|
+
cycles = {}
|
|
1191
|
+
for g in G:
|
|
1192
|
+
ind = indices[g.cycle_type()]
|
|
1193
|
+
if ind in cycles:
|
|
1194
|
+
cycles[ind].append(g)
|
|
1195
|
+
else:
|
|
1196
|
+
cycles[ind] = [g]
|
|
1197
|
+
|
|
1198
|
+
denom = factorial(self.n)
|
|
1199
|
+
cpi = {}
|
|
1200
|
+
for lam in self._blocks_dictionary[mu]:
|
|
1201
|
+
lam_index = indices[lam]
|
|
1202
|
+
big_coeff = character_table[lam_index][0] / denom
|
|
1203
|
+
character_row = character_table[lam_index]
|
|
1204
|
+
iaxpy(1,
|
|
1205
|
+
{g: big_coeff * character_row[ind]
|
|
1206
|
+
for ind in cycles for g in cycles[ind]},
|
|
1207
|
+
cpi)
|
|
1208
|
+
|
|
1209
|
+
if not all(R(cpi[g].denominator()) for g in cpi):
|
|
1210
|
+
return None
|
|
1211
|
+
|
|
1212
|
+
ret = self.element_class(self, {g: R(cpi[g]) for g in cpi if R(cpi[g])})
|
|
1213
|
+
if not block or not p:
|
|
1214
|
+
self._idempotent_cache[la] = ret
|
|
1215
|
+
else:
|
|
1216
|
+
self._idempotent_cache[mu] = ret
|
|
1217
|
+
return ret
|
|
1218
|
+
|
|
1219
|
+
@lazy_attribute
|
|
1220
|
+
def _blocks_dictionary(self):
|
|
1221
|
+
r"""
|
|
1222
|
+
Return the partitions of ``self.n``, themselves partitioned
|
|
1223
|
+
by their distinct `p`-cores, where `p` is the characteristic
|
|
1224
|
+
of ``self.base_ring()``
|
|
1225
|
+
|
|
1226
|
+
If the characteristic is zero, we take the `p`-core operation
|
|
1227
|
+
to be the identity map on partitions.
|
|
1228
|
+
|
|
1229
|
+
These lists of partitions, say with common `p`-core `\mu`,
|
|
1230
|
+
are components of the central orthogonal idempotent
|
|
1231
|
+
corresponding to `\mu`.
|
|
1232
|
+
|
|
1233
|
+
TESTS::
|
|
1234
|
+
|
|
1235
|
+
sage: B2 = SymmetricGroupAlgebra(GF(2), 4)._blocks_dictionary
|
|
1236
|
+
sage: [tuple(B2[key]) for key in sorted(B2)]
|
|
1237
|
+
[([4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1])]
|
|
1238
|
+
sage: B3 = SymmetricGroupAlgebra(GF(3), 4)._blocks_dictionary
|
|
1239
|
+
sage: [tuple(B3[key]) for key in sorted(B3)]
|
|
1240
|
+
[([4], [2, 2], [1, 1, 1, 1]), ([2, 1, 1],), ([3, 1],)]
|
|
1241
|
+
sage: B5 = SymmetricGroupAlgebra(GF(5), 4)._blocks_dictionary
|
|
1242
|
+
sage: [tuple(B5[key]) for key in sorted(B5)]
|
|
1243
|
+
[([1, 1, 1, 1],), ([2, 1, 1],), ([2, 2],), ([3, 1],), ([4],)]
|
|
1244
|
+
sage: B5 == SymmetricGroupAlgebra(QQ, 4)._blocks_dictionary
|
|
1245
|
+
True
|
|
1246
|
+
|
|
1247
|
+
.. SEEALSO::
|
|
1248
|
+
|
|
1249
|
+
:meth:`central_orthogonal_idempotent`
|
|
1250
|
+
"""
|
|
1251
|
+
p = self.base_ring().characteristic()
|
|
1252
|
+
if not p:
|
|
1253
|
+
return {la: [la] for la in Partitions_n(self.n)}
|
|
1254
|
+
|
|
1255
|
+
blocks = {}
|
|
1256
|
+
for la in Partitions_n(self.n):
|
|
1257
|
+
c = la.core(p)
|
|
1258
|
+
if c in blocks:
|
|
1259
|
+
blocks[c].append(la)
|
|
1260
|
+
else:
|
|
1261
|
+
blocks[c] = [la]
|
|
1262
|
+
return blocks
|
|
1263
|
+
|
|
1264
|
+
def ladder_idempotent(self, la):
|
|
1265
|
+
r"""
|
|
1266
|
+
Return the ladder idempotent of ``self``.
|
|
1267
|
+
|
|
1268
|
+
Let `F` be a field of characteristic `p`. The *ladder idempotent*
|
|
1269
|
+
of shape `\lambda` is the idempotent of `F[S_n]` defined as follows.
|
|
1270
|
+
Let `T` be the :meth:`ladder tableau
|
|
1271
|
+
<sage.combinat.partition.Partition.ladder_tableau>` of shape `\lambda`.
|
|
1272
|
+
Let `[T]` be the set of standard tableaux whose residue sequence
|
|
1273
|
+
is the same as for `T`. Let `\alpha` be the sizes of the ladders
|
|
1274
|
+
of `\lambda`. Then the ladder idempotent is constructed as
|
|
1275
|
+
|
|
1276
|
+
.. MATH::
|
|
1277
|
+
|
|
1278
|
+
\widetilde{e}_{\lambda} := \frac{1}{\alpha!}
|
|
1279
|
+
\left( \sum_{\sigma \in S_{\alpha}} \sigma \right)
|
|
1280
|
+
\left( \overline{\sum_{U \in [T]} E_U} \right),
|
|
1281
|
+
|
|
1282
|
+
where `E_{UU}` is the :meth:`seminormal_basis` element over `\QQ`
|
|
1283
|
+
and we project the sum to `F`, `S_{\alpha}` is the Young subgroup
|
|
1284
|
+
corresponding to `\alpha`, and `\alpha! = \alpha_1! \cdots \alpha_k!`.
|
|
1285
|
+
|
|
1286
|
+
EXAMPLES::
|
|
1287
|
+
|
|
1288
|
+
sage: SGA = SymmetricGroupAlgebra(GF(3), 4)
|
|
1289
|
+
sage: for la in Partitions(SGA.n):
|
|
1290
|
+
....: idem = SGA.ladder_idempotent(la)
|
|
1291
|
+
....: print(la)
|
|
1292
|
+
....: print(idem)
|
|
1293
|
+
....: assert idem^2 == idem
|
|
1294
|
+
[4]
|
|
1295
|
+
2*[1, 2, 3, 4] + 2*[1, 2, 4, 3] + 2*[2, 1, 3, 4] + 2*[2, 1, 4, 3]
|
|
1296
|
+
+ 2*[3, 4, 1, 2] + 2*[3, 4, 2, 1] + 2*[4, 3, 1, 2] + 2*[4, 3, 2, 1]
|
|
1297
|
+
[3, 1]
|
|
1298
|
+
2*[1, 2, 3, 4] + 2*[1, 2, 4, 3] + 2*[2, 1, 3, 4] + 2*[2, 1, 4, 3]
|
|
1299
|
+
+ [3, 4, 1, 2] + [3, 4, 2, 1] + [4, 3, 1, 2] + [4, 3, 2, 1]
|
|
1300
|
+
[2, 2]
|
|
1301
|
+
2*[1, 2, 3, 4] + 2*[1, 2, 4, 3] + 2*[2, 1, 3, 4] + 2*[2, 1, 4, 3]
|
|
1302
|
+
+ 2*[3, 4, 1, 2] + 2*[3, 4, 2, 1] + 2*[4, 3, 1, 2] + 2*[4, 3, 2, 1]
|
|
1303
|
+
[2, 1, 1]
|
|
1304
|
+
2*[1, 2, 3, 4] + [1, 2, 4, 3] + 2*[1, 3, 2, 4] + [1, 3, 4, 2]
|
|
1305
|
+
+ [1, 4, 2, 3] + 2*[1, 4, 3, 2] + 2*[2, 1, 3, 4] + [2, 1, 4, 3]
|
|
1306
|
+
+ 2*[2, 3, 1, 4] + [2, 3, 4, 1] + [2, 4, 1, 3] + 2*[2, 4, 3, 1]
|
|
1307
|
+
+ 2*[3, 1, 2, 4] + [3, 1, 4, 2] + 2*[3, 2, 1, 4] + [3, 2, 4, 1]
|
|
1308
|
+
+ [4, 1, 2, 3] + 2*[4, 1, 3, 2] + [4, 2, 1, 3] + 2*[4, 2, 3, 1]
|
|
1309
|
+
[1, 1, 1, 1]
|
|
1310
|
+
2*[1, 2, 3, 4] + [1, 2, 4, 3] + [2, 1, 3, 4] + 2*[2, 1, 4, 3]
|
|
1311
|
+
+ 2*[3, 4, 1, 2] + [3, 4, 2, 1] + [4, 3, 1, 2] + 2*[4, 3, 2, 1]
|
|
1312
|
+
|
|
1313
|
+
When `p = 0`, these idempotents will generate all of the simple
|
|
1314
|
+
modules (which are the :meth:`Specht modules <specht_module>`
|
|
1315
|
+
and also projective modules)::
|
|
1316
|
+
|
|
1317
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, 5)
|
|
1318
|
+
sage: for la in Partitions(SGA.n):
|
|
1319
|
+
....: idem = SGA.ladder_idempotent(la)
|
|
1320
|
+
....: assert idem^2 == idem
|
|
1321
|
+
....: print(la, SGA.principal_ideal(idem).dimension())
|
|
1322
|
+
[5] 1
|
|
1323
|
+
[4, 1] 4
|
|
1324
|
+
[3, 2] 5
|
|
1325
|
+
[3, 1, 1] 6
|
|
1326
|
+
[2, 2, 1] 5
|
|
1327
|
+
[2, 1, 1, 1] 4
|
|
1328
|
+
[1, 1, 1, 1, 1] 1
|
|
1329
|
+
sage: [StandardTableaux(la).cardinality() for la in Partitions(SGA.n)]
|
|
1330
|
+
[1, 4, 5, 6, 5, 4, 1]
|
|
1331
|
+
|
|
1332
|
+
REFERENCES:
|
|
1333
|
+
|
|
1334
|
+
- [Ryom2015]_
|
|
1335
|
+
"""
|
|
1336
|
+
R = self.base_ring()
|
|
1337
|
+
p = R.characteristic()
|
|
1338
|
+
n = self.n
|
|
1339
|
+
if not p:
|
|
1340
|
+
p = n + 1
|
|
1341
|
+
la = Partitions_n(n)(la)
|
|
1342
|
+
Tlad, alpha = la.ladder_tableau(p, ladder_lengths=True)
|
|
1343
|
+
if any(val >= p for val in alpha):
|
|
1344
|
+
raise ValueError(f"{la} is not {p}-ladder restricted")
|
|
1345
|
+
Tclass = Tlad.residue_sequence(p).standard_tableaux()
|
|
1346
|
+
Elad = sum(epsilon_ik(T, T) for T in Tclass)
|
|
1347
|
+
Elad = self.element_class(self, {sigma: R(c)
|
|
1348
|
+
for sigma, c in Elad._monomial_coefficients.items()})
|
|
1349
|
+
from sage.groups.perm_gps.permgroup_named import SymmetricGroup
|
|
1350
|
+
YG = SymmetricGroup(n).young_subgroup(alpha)
|
|
1351
|
+
coeff = ~R.prod(factorial(val) for val in alpha)
|
|
1352
|
+
G = self.group()
|
|
1353
|
+
eprod = self.element_class(self, {G(list(elt.tuple())): coeff
|
|
1354
|
+
for elt in YG})
|
|
1355
|
+
return Elad * eprod
|
|
1356
|
+
|
|
1357
|
+
@cached_method
|
|
1358
|
+
def algebra_generators(self):
|
|
1359
|
+
r"""
|
|
1360
|
+
Return generators of this group algebra (as algebra) as a
|
|
1361
|
+
list of permutations.
|
|
1362
|
+
|
|
1363
|
+
The generators used for the group algebra of `S_n` are the
|
|
1364
|
+
transposition `(2, 1)` and the `n`-cycle `(1, 2, \ldots, n)`,
|
|
1365
|
+
unless `n \leq 1` (in which case no generators are needed).
|
|
1366
|
+
|
|
1367
|
+
EXAMPLES::
|
|
1368
|
+
|
|
1369
|
+
sage: SymmetricGroupAlgebra(ZZ,5).algebra_generators()
|
|
1370
|
+
Family ([2, 1, 3, 4, 5], [2, 3, 4, 5, 1])
|
|
1371
|
+
|
|
1372
|
+
sage: SymmetricGroupAlgebra(QQ,0).algebra_generators()
|
|
1373
|
+
Family ()
|
|
1374
|
+
|
|
1375
|
+
sage: SymmetricGroupAlgebra(QQ,1).algebra_generators()
|
|
1376
|
+
Family ()
|
|
1377
|
+
|
|
1378
|
+
TESTS:
|
|
1379
|
+
|
|
1380
|
+
Check that :issue:`15309` is fixed::
|
|
1381
|
+
|
|
1382
|
+
sage: S3 = SymmetricGroupAlgebra(QQ, 3)
|
|
1383
|
+
sage: S3.algebra_generators()
|
|
1384
|
+
Family ([2, 1, 3], [2, 3, 1])
|
|
1385
|
+
sage: C = CombinatorialFreeModule(ZZ, ZZ)
|
|
1386
|
+
sage: M = C.module_morphism(lambda x: S3.zero(), codomain=S3)
|
|
1387
|
+
sage: M.register_as_coercion()
|
|
1388
|
+
"""
|
|
1389
|
+
from sage.sets.family import Family
|
|
1390
|
+
if self.n <= 1:
|
|
1391
|
+
return Family([])
|
|
1392
|
+
a = list(range(1, self.n + 1))
|
|
1393
|
+
a[0] = 2
|
|
1394
|
+
a[1] = 1
|
|
1395
|
+
b = list(range(2, self.n + 2))
|
|
1396
|
+
b[self.n - 1] = 1
|
|
1397
|
+
return Family([self.monomial(self._indices(a)), self.monomial(self._indices(b))])
|
|
1398
|
+
|
|
1399
|
+
def _conjugacy_classes_representatives_underlying_group(self):
|
|
1400
|
+
r"""
|
|
1401
|
+
Return a complete list of representatives of conjugacy
|
|
1402
|
+
classes of the underlying symmetric group.
|
|
1403
|
+
|
|
1404
|
+
.. WARNING::
|
|
1405
|
+
|
|
1406
|
+
This currently is only implemented when ``self`` is built using
|
|
1407
|
+
the index set ``Permutations(n)``.
|
|
1408
|
+
|
|
1409
|
+
EXAMPLES::
|
|
1410
|
+
|
|
1411
|
+
sage: SG=SymmetricGroupAlgebra(ZZ,3)
|
|
1412
|
+
sage: SG._conjugacy_classes_representatives_underlying_group()
|
|
1413
|
+
[[2, 3, 1], [2, 1, 3], [1, 2, 3]]
|
|
1414
|
+
|
|
1415
|
+
sage: SGg = SymmetricGroup(3).algebra(ZZ)
|
|
1416
|
+
sage: SGg._conjugacy_classes_representatives_underlying_group() # not tested
|
|
1417
|
+
[(1,2,3), (1,2), ()]
|
|
1418
|
+
"""
|
|
1419
|
+
P = self.basis().keys()
|
|
1420
|
+
return [P.element_in_conjugacy_classes(nu) for nu in Partitions_n(self.n)]
|
|
1421
|
+
|
|
1422
|
+
def rsw_shuffling_element(self, k):
|
|
1423
|
+
r"""
|
|
1424
|
+
Return the `k`-th Reiner-Saliola-Welker shuffling element in
|
|
1425
|
+
the group algebra ``self``.
|
|
1426
|
+
|
|
1427
|
+
The `k`-th Reiner-Saliola-Welker shuffling element in the
|
|
1428
|
+
symmetric group algebra `R S_n` over a ring `R` is defined as the
|
|
1429
|
+
sum `\sum_{\sigma \in S_n} \mathrm{noninv}_k(\sigma) \cdot \sigma`,
|
|
1430
|
+
where for every permutation `\sigma`, the number
|
|
1431
|
+
`\mathrm{noninv}_k(\sigma)` is the number of all
|
|
1432
|
+
`k`-noninversions of `\sigma` (that is, the number of all
|
|
1433
|
+
`k`-element subsets of `\{ 1, 2, \ldots, n \}` on which
|
|
1434
|
+
`\sigma` restricts to a strictly increasing map). See
|
|
1435
|
+
:meth:`sage.combinat.permutation.number_of_noninversions` for
|
|
1436
|
+
the `\mathrm{noninv}` map.
|
|
1437
|
+
|
|
1438
|
+
This element is more or less the operator `\nu_{k, 1^{n-k}}`
|
|
1439
|
+
introduced in [RSW2011]_; more precisely, `\nu_{k, 1^{n-k}}`
|
|
1440
|
+
is the left multiplication by this element.
|
|
1441
|
+
|
|
1442
|
+
It is a nontrivial theorem (Theorem 1.1 in [RSW2011]_) that
|
|
1443
|
+
the operators `\nu_{k, 1^{n-k}}` (for fixed `n` and varying
|
|
1444
|
+
`k`) pairwise commute. It is a conjecture (Conjecture 1.2 in
|
|
1445
|
+
[RSW2011]_) that all their eigenvalues are integers (which, in
|
|
1446
|
+
light of their commutativity and easily established symmetry,
|
|
1447
|
+
yields that they can be simultaneously diagonalized over `\QQ`
|
|
1448
|
+
with only integer eigenvalues).
|
|
1449
|
+
|
|
1450
|
+
EXAMPLES:
|
|
1451
|
+
|
|
1452
|
+
The Reiner-Saliola-Welker shuffling elements on `\QQ S_3`::
|
|
1453
|
+
|
|
1454
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
|
|
1455
|
+
sage: QS3.rsw_shuffling_element(0)
|
|
1456
|
+
[1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
|
|
1457
|
+
sage: QS3.rsw_shuffling_element(1)
|
|
1458
|
+
3*[1, 2, 3] + 3*[1, 3, 2] + 3*[2, 1, 3] + 3*[2, 3, 1] + 3*[3, 1, 2] + 3*[3, 2, 1]
|
|
1459
|
+
sage: QS3.rsw_shuffling_element(2)
|
|
1460
|
+
3*[1, 2, 3] + 2*[1, 3, 2] + 2*[2, 1, 3] + [2, 3, 1] + [3, 1, 2]
|
|
1461
|
+
sage: QS3.rsw_shuffling_element(3)
|
|
1462
|
+
[1, 2, 3]
|
|
1463
|
+
sage: QS3.rsw_shuffling_element(4)
|
|
1464
|
+
0
|
|
1465
|
+
|
|
1466
|
+
Checking the commutativity of Reiner-Saliola-Welker shuffling
|
|
1467
|
+
elements (we leave out the ones for which it is trivial)::
|
|
1468
|
+
|
|
1469
|
+
sage: def test_rsw_comm(n):
|
|
1470
|
+
....: QSn = SymmetricGroupAlgebra(QQ, n)
|
|
1471
|
+
....: rsws = [QSn.rsw_shuffling_element(k) for k in range(2, n)]
|
|
1472
|
+
....: return all(ri * rsws[j] == rsws[j] * ri
|
|
1473
|
+
....: for i, ri in enumerate(rsws) for j in range(i))
|
|
1474
|
+
sage: test_rsw_comm(3)
|
|
1475
|
+
True
|
|
1476
|
+
sage: test_rsw_comm(4) # long time
|
|
1477
|
+
True
|
|
1478
|
+
sage: test_rsw_comm(5) # not tested
|
|
1479
|
+
True
|
|
1480
|
+
|
|
1481
|
+
.. NOTE::
|
|
1482
|
+
|
|
1483
|
+
For large ``k`` (relative to ``n``), it might be faster to call
|
|
1484
|
+
``QSn.left_action_product(QSn.semi_rsw_element(k), QSn.antipode(binary_unshuffle_sum(k)))``
|
|
1485
|
+
than ``QSn.rsw_shuffling_element(n)``.
|
|
1486
|
+
|
|
1487
|
+
.. SEEALSO::
|
|
1488
|
+
|
|
1489
|
+
:meth:`semi_rsw_element`, :meth:`binary_unshuffle_sum`
|
|
1490
|
+
"""
|
|
1491
|
+
P = self.basis().keys()
|
|
1492
|
+
I = Permutations(self.n)
|
|
1493
|
+
return self.sum_of_terms([(p, I(p).number_of_noninversions(k)) for p in P],
|
|
1494
|
+
distinct=True)
|
|
1495
|
+
|
|
1496
|
+
def semi_rsw_element(self, k):
|
|
1497
|
+
r"""
|
|
1498
|
+
Return the `k`-th semi-RSW element in the group algebra ``self``.
|
|
1499
|
+
|
|
1500
|
+
The `k`-th semi-RSW element in the symmetric group algebra
|
|
1501
|
+
`R S_n` over a ring `R` is defined as the sum of all permutations
|
|
1502
|
+
`\sigma \in S_n` satisfying
|
|
1503
|
+
`\sigma(1) < \sigma(2) < \cdots < \sigma(k)`.
|
|
1504
|
+
|
|
1505
|
+
This element has the property that, if it is denoted by `s_k`,
|
|
1506
|
+
then `s_k S(s_k)` is `(n-k)!` times the `k`-th
|
|
1507
|
+
Reiner-Saliola-Welker shuffling element of `R S_n` (see
|
|
1508
|
+
:meth:`rsw_shuffling_element`). Here, `S` denotes the antipode
|
|
1509
|
+
of the group algebra `R S_n`.
|
|
1510
|
+
|
|
1511
|
+
The `k`-th semi-RSW element is the image of the complete
|
|
1512
|
+
non-commutative symmetric function `S^{(k, 1^{n-k})}` in the
|
|
1513
|
+
ring of non-commutative symmetric functions under the canonical
|
|
1514
|
+
projection on the symmetric group algebra (through the descent
|
|
1515
|
+
algebra).
|
|
1516
|
+
|
|
1517
|
+
EXAMPLES:
|
|
1518
|
+
|
|
1519
|
+
The semi-RSW elements on `\QQ S_3`::
|
|
1520
|
+
|
|
1521
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
|
|
1522
|
+
sage: QS3.semi_rsw_element(0)
|
|
1523
|
+
[1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
|
|
1524
|
+
sage: QS3.semi_rsw_element(1)
|
|
1525
|
+
[1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
|
|
1526
|
+
sage: QS3.semi_rsw_element(2)
|
|
1527
|
+
[1, 2, 3] + [1, 3, 2] + [2, 3, 1]
|
|
1528
|
+
sage: QS3.semi_rsw_element(3)
|
|
1529
|
+
[1, 2, 3]
|
|
1530
|
+
sage: QS3.semi_rsw_element(4)
|
|
1531
|
+
0
|
|
1532
|
+
|
|
1533
|
+
Let us check the relation with the `k`-th Reiner-Saliola-Welker
|
|
1534
|
+
shuffling element stated in the docstring::
|
|
1535
|
+
|
|
1536
|
+
sage: def test_rsw(n):
|
|
1537
|
+
....: ZSn = SymmetricGroupAlgebra(ZZ, n)
|
|
1538
|
+
....: for k in range(1, n):
|
|
1539
|
+
....: a = ZSn.semi_rsw_element(k)
|
|
1540
|
+
....: b = ZSn.left_action_product(a, ZSn.antipode(a))
|
|
1541
|
+
....: if factorial(n-k) * ZSn.rsw_shuffling_element(k) != b:
|
|
1542
|
+
....: return False
|
|
1543
|
+
....: return True
|
|
1544
|
+
sage: test_rsw(3)
|
|
1545
|
+
True
|
|
1546
|
+
sage: test_rsw(4)
|
|
1547
|
+
True
|
|
1548
|
+
sage: test_rsw(5) # long time
|
|
1549
|
+
True
|
|
1550
|
+
|
|
1551
|
+
Let us also check the statement about the complete
|
|
1552
|
+
non-commutative symmetric function::
|
|
1553
|
+
|
|
1554
|
+
sage: def test_rsw_ncsf(n):
|
|
1555
|
+
....: ZSn = SymmetricGroupAlgebra(ZZ, n)
|
|
1556
|
+
....: NSym = NonCommutativeSymmetricFunctions(ZZ)
|
|
1557
|
+
....: S = NSym.S()
|
|
1558
|
+
....: for k in range(1, n):
|
|
1559
|
+
....: a = S(Composition([k] + [1]*(n-k))).to_symmetric_group_algebra()
|
|
1560
|
+
....: if a != ZSn.semi_rsw_element(k):
|
|
1561
|
+
....: return False
|
|
1562
|
+
....: return True
|
|
1563
|
+
sage: test_rsw_ncsf(3)
|
|
1564
|
+
True
|
|
1565
|
+
sage: test_rsw_ncsf(4)
|
|
1566
|
+
True
|
|
1567
|
+
sage: test_rsw_ncsf(5) # long time
|
|
1568
|
+
True
|
|
1569
|
+
"""
|
|
1570
|
+
n = self.n
|
|
1571
|
+
if n < k:
|
|
1572
|
+
return self.zero()
|
|
1573
|
+
|
|
1574
|
+
def complement(xs):
|
|
1575
|
+
res = list(range(1, n + 1))
|
|
1576
|
+
for x in xs:
|
|
1577
|
+
res.remove(x)
|
|
1578
|
+
return res
|
|
1579
|
+
P = Permutations(n)
|
|
1580
|
+
I = self._indices
|
|
1581
|
+
return self.sum_of_monomials([I(P(complement(q) + list(q)))
|
|
1582
|
+
for q in itertools.permutations(range(1, n + 1), int(n - k))])
|
|
1583
|
+
|
|
1584
|
+
def binary_unshuffle_sum(self, k):
|
|
1585
|
+
r"""
|
|
1586
|
+
Return the `k`-th binary unshuffle sum in the group algebra
|
|
1587
|
+
``self``.
|
|
1588
|
+
|
|
1589
|
+
The `k`-th binary unshuffle sum in the symmetric group algebra
|
|
1590
|
+
`R S_n` over a ring `R` is defined as the sum of all permutations
|
|
1591
|
+
`\sigma \in S_n` satisfying
|
|
1592
|
+
`\sigma(1) < \sigma(2) < \cdots < \sigma(k)` and
|
|
1593
|
+
`\sigma(k+1) < \sigma(k+2) < \cdots < \sigma(n)`.
|
|
1594
|
+
|
|
1595
|
+
This element has the property that, if it is denoted by `t_k`,
|
|
1596
|
+
and if the `k`-th semi-RSW element (see :meth:`semi_rsw_element`)
|
|
1597
|
+
is denoted by `s_k`, then `s_k S(t_k)` and `t_k S(s_k)` both
|
|
1598
|
+
equal the `k`-th Reiner-Saliola-Welker shuffling element of
|
|
1599
|
+
`R S_n` (see :meth:`rsw_shuffling_element`).
|
|
1600
|
+
|
|
1601
|
+
The `k`-th binary unshuffle sum is the image of the complete
|
|
1602
|
+
non-commutative symmetric function `S^{(k, n-k)}` in the
|
|
1603
|
+
ring of non-commutative symmetric functions under the canonical
|
|
1604
|
+
projection on the symmetric group algebra (through the descent
|
|
1605
|
+
algebra).
|
|
1606
|
+
|
|
1607
|
+
EXAMPLES:
|
|
1608
|
+
|
|
1609
|
+
The binary unshuffle sums on `\QQ S_3`::
|
|
1610
|
+
|
|
1611
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
|
|
1612
|
+
sage: QS3.binary_unshuffle_sum(0)
|
|
1613
|
+
[1, 2, 3]
|
|
1614
|
+
sage: QS3.binary_unshuffle_sum(1)
|
|
1615
|
+
[1, 2, 3] + [2, 1, 3] + [3, 1, 2]
|
|
1616
|
+
sage: QS3.binary_unshuffle_sum(2)
|
|
1617
|
+
[1, 2, 3] + [1, 3, 2] + [2, 3, 1]
|
|
1618
|
+
sage: QS3.binary_unshuffle_sum(3)
|
|
1619
|
+
[1, 2, 3]
|
|
1620
|
+
sage: QS3.binary_unshuffle_sum(4)
|
|
1621
|
+
0
|
|
1622
|
+
|
|
1623
|
+
Let us check the relation with the `k`-th Reiner-Saliola-Welker
|
|
1624
|
+
shuffling element stated in the docstring::
|
|
1625
|
+
|
|
1626
|
+
sage: def test_rsw(n):
|
|
1627
|
+
....: ZSn = SymmetricGroupAlgebra(ZZ, n)
|
|
1628
|
+
....: for k in range(1, n):
|
|
1629
|
+
....: a = ZSn.semi_rsw_element(k)
|
|
1630
|
+
....: b = ZSn.binary_unshuffle_sum(k)
|
|
1631
|
+
....: c = ZSn.left_action_product(a, ZSn.antipode(b))
|
|
1632
|
+
....: d = ZSn.left_action_product(b, ZSn.antipode(a))
|
|
1633
|
+
....: e = ZSn.rsw_shuffling_element(k)
|
|
1634
|
+
....: if c != e or d != e:
|
|
1635
|
+
....: return False
|
|
1636
|
+
....: return True
|
|
1637
|
+
sage: test_rsw(3)
|
|
1638
|
+
True
|
|
1639
|
+
sage: test_rsw(4) # long time
|
|
1640
|
+
True
|
|
1641
|
+
sage: test_rsw(5) # long time
|
|
1642
|
+
True
|
|
1643
|
+
|
|
1644
|
+
Let us also check the statement about the complete
|
|
1645
|
+
non-commutative symmetric function::
|
|
1646
|
+
|
|
1647
|
+
sage: def test_rsw_ncsf(n):
|
|
1648
|
+
....: ZSn = SymmetricGroupAlgebra(ZZ, n)
|
|
1649
|
+
....: NSym = NonCommutativeSymmetricFunctions(ZZ)
|
|
1650
|
+
....: S = NSym.S()
|
|
1651
|
+
....: for k in range(1, n):
|
|
1652
|
+
....: a = S(Composition([k, n-k])).to_symmetric_group_algebra()
|
|
1653
|
+
....: if a != ZSn.binary_unshuffle_sum(k):
|
|
1654
|
+
....: return False
|
|
1655
|
+
....: return True
|
|
1656
|
+
sage: test_rsw_ncsf(3)
|
|
1657
|
+
True
|
|
1658
|
+
sage: test_rsw_ncsf(4)
|
|
1659
|
+
True
|
|
1660
|
+
sage: test_rsw_ncsf(5) # long time
|
|
1661
|
+
True
|
|
1662
|
+
"""
|
|
1663
|
+
n = self.n
|
|
1664
|
+
if n < k:
|
|
1665
|
+
return self.zero()
|
|
1666
|
+
|
|
1667
|
+
def complement(xs):
|
|
1668
|
+
res = list(range(1, n + 1))
|
|
1669
|
+
for x in xs:
|
|
1670
|
+
res.remove(x)
|
|
1671
|
+
return res
|
|
1672
|
+
P = Permutations(n)
|
|
1673
|
+
return self.sum_of_monomials([self._indices(P(list(q) + complement(q)))
|
|
1674
|
+
for q in itertools.combinations(range(1, n + 1), int(k))])
|
|
1675
|
+
|
|
1676
|
+
def specht_module(self, D):
|
|
1677
|
+
r"""
|
|
1678
|
+
Return the Specht module of ``self`` indexed by the diagram ``D``.
|
|
1679
|
+
|
|
1680
|
+
EXAMPLES::
|
|
1681
|
+
|
|
1682
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, 5)
|
|
1683
|
+
sage: SM = SGA.specht_module(Partition([3,1,1]))
|
|
1684
|
+
sage: SM
|
|
1685
|
+
Specht module of [3, 1, 1] over Rational Field
|
|
1686
|
+
sage: SM.frobenius_image()
|
|
1687
|
+
s[3, 1, 1]
|
|
1688
|
+
|
|
1689
|
+
sage: SM = SGA.specht_module([(1,1),(1,3),(2,2),(3,1),(3,2)])
|
|
1690
|
+
sage: SM
|
|
1691
|
+
Specht module of [(1, 1), (1, 3), (2, 2), (3, 1), (3, 2)] over Rational Field
|
|
1692
|
+
sage: SM.frobenius_image()
|
|
1693
|
+
s[2, 2, 1] + s[3, 1, 1] + s[3, 2]
|
|
1694
|
+
"""
|
|
1695
|
+
from sage.combinat.specht_module import SpechtModule
|
|
1696
|
+
return SpechtModule(self, D)
|
|
1697
|
+
|
|
1698
|
+
def tabloid_module(self, D):
|
|
1699
|
+
r"""
|
|
1700
|
+
Return the module of tabloids with the natural action of ``self``.
|
|
1701
|
+
|
|
1702
|
+
.. SEEALSO::
|
|
1703
|
+
|
|
1704
|
+
:class:`~sage.combinat.specht_module.TabloidModule`
|
|
1705
|
+
|
|
1706
|
+
EXAMPLES::
|
|
1707
|
+
|
|
1708
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, 5)
|
|
1709
|
+
sage: TM = SGA.tabloid_module(Partition([3,1,1]))
|
|
1710
|
+
sage: TM
|
|
1711
|
+
Tabloid module of [3, 1, 1] over Rational Field
|
|
1712
|
+
sage: s = SymmetricFunctions(QQ).s()
|
|
1713
|
+
sage: s(TM.frobenius_image())
|
|
1714
|
+
s[3, 1, 1] + s[3, 2] + 2*s[4, 1] + s[5]
|
|
1715
|
+
"""
|
|
1716
|
+
from sage.combinat.specht_module import TabloidModule
|
|
1717
|
+
return TabloidModule(self, D)
|
|
1718
|
+
|
|
1719
|
+
def specht_module_dimension(self, D):
|
|
1720
|
+
r"""
|
|
1721
|
+
Return the dimension of the Specht module of ``self`` indexed by ``D``.
|
|
1722
|
+
|
|
1723
|
+
EXAMPLES::
|
|
1724
|
+
|
|
1725
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, 5)
|
|
1726
|
+
sage: SGA.specht_module_dimension(Partition([3,1,1]))
|
|
1727
|
+
6
|
|
1728
|
+
sage: SGA.specht_module_dimension([(1,1),(1,3),(2,2),(3,1),(3,2)])
|
|
1729
|
+
16
|
|
1730
|
+
"""
|
|
1731
|
+
from sage.combinat.specht_module import _to_diagram, specht_module_spanning_set
|
|
1732
|
+
D = _to_diagram(D)
|
|
1733
|
+
span_set = specht_module_spanning_set(D, self)
|
|
1734
|
+
return matrix(self.base_ring(), [v.to_vector() for v in span_set]).rank()
|
|
1735
|
+
|
|
1736
|
+
def simple_module_parameterization(self):
|
|
1737
|
+
r"""
|
|
1738
|
+
Return a parameterization of the simple modules of ``self``.
|
|
1739
|
+
|
|
1740
|
+
The symmetric group algebra of `S_n` over a field of characteristic `p`
|
|
1741
|
+
has its simple modules indexed by all `p`-regular partitions of `n`.
|
|
1742
|
+
|
|
1743
|
+
EXAMPLES::
|
|
1744
|
+
|
|
1745
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, 6)
|
|
1746
|
+
sage: SGA.simple_module_parameterization()
|
|
1747
|
+
Partitions of the integer 6
|
|
1748
|
+
|
|
1749
|
+
sage: SGA = SymmetricGroupAlgebra(GF(2), 6)
|
|
1750
|
+
sage: SGA.simple_module_parameterization()
|
|
1751
|
+
2-Regular Partitions of the integer 6
|
|
1752
|
+
"""
|
|
1753
|
+
p = self.base_ring().characteristic()
|
|
1754
|
+
if p > 0:
|
|
1755
|
+
return Partitions(self.n, regular=p)
|
|
1756
|
+
return Partitions_n(self.n)
|
|
1757
|
+
|
|
1758
|
+
def simple_module(self, la):
|
|
1759
|
+
r"""
|
|
1760
|
+
Return the simple module of ``self`` indexed by the partition ``la``.
|
|
1761
|
+
|
|
1762
|
+
Over a field of characteristic `0`, this simply returns the Specht
|
|
1763
|
+
module.
|
|
1764
|
+
|
|
1765
|
+
.. SEEALSO::
|
|
1766
|
+
|
|
1767
|
+
:class:`sage.combinat.specht_module.SimpleModule`
|
|
1768
|
+
|
|
1769
|
+
EXAMPLES::
|
|
1770
|
+
|
|
1771
|
+
sage: SGA = SymmetricGroupAlgebra(GF(3), 5)
|
|
1772
|
+
sage: D = SGA.simple_module(Partition([3,1,1]))
|
|
1773
|
+
sage: D
|
|
1774
|
+
Simple module of [3, 1, 1] over Finite Field of size 3
|
|
1775
|
+
sage: D.brauer_character()
|
|
1776
|
+
(6, 0, -2, 0, 1)
|
|
1777
|
+
"""
|
|
1778
|
+
from sage.combinat.specht_module import SpechtModule
|
|
1779
|
+
return SpechtModule(self, la).simple_module()
|
|
1780
|
+
|
|
1781
|
+
def simple_module_dimension(self, la):
|
|
1782
|
+
r"""
|
|
1783
|
+
Return the dimension of the simple module of ``self`` indexed by the
|
|
1784
|
+
partition ``la``.
|
|
1785
|
+
|
|
1786
|
+
EXAMPLES::
|
|
1787
|
+
|
|
1788
|
+
sage: SGA = SymmetricGroupAlgebra(GF(5), 6)
|
|
1789
|
+
sage: SGA.simple_module_dimension(Partition([4,1,1]))
|
|
1790
|
+
10
|
|
1791
|
+
|
|
1792
|
+
TESTS::
|
|
1793
|
+
|
|
1794
|
+
sage: SGA = SymmetricGroupAlgebra(GF(5), 6)
|
|
1795
|
+
sage: SGA.simple_module_dimension(Partition([3,1,1]))
|
|
1796
|
+
Traceback (most recent call last):
|
|
1797
|
+
...
|
|
1798
|
+
ValueError: [3, 1, 1] is not a partition of 6
|
|
1799
|
+
"""
|
|
1800
|
+
if sum(la) != self.n:
|
|
1801
|
+
raise ValueError(f"{la} is not a partition of {self.n}")
|
|
1802
|
+
from sage.combinat.specht_module import simple_module_rank
|
|
1803
|
+
return simple_module_rank(la, self.base_ring())
|
|
1804
|
+
|
|
1805
|
+
def garsia_procesi_module(self, la):
|
|
1806
|
+
r"""
|
|
1807
|
+
Return the :class:`Garsia-Procesi module
|
|
1808
|
+
<sage.combinat.symmetric_group_representations.GarsiaProcesiModule>`
|
|
1809
|
+
of ``self`` indexed by ``la``.
|
|
1810
|
+
|
|
1811
|
+
EXAMPLES::
|
|
1812
|
+
|
|
1813
|
+
sage: SGA = SymmetricGroupAlgebra(GF(2), 6)
|
|
1814
|
+
sage: SGA.garsia_procesi_module(Partition([2,2,1,1]))
|
|
1815
|
+
Garsia-Procesi module of shape [2, 2, 1, 1] over Finite Field of size 2
|
|
1816
|
+
"""
|
|
1817
|
+
from sage.combinat.symmetric_group_representations import GarsiaProcesiModule
|
|
1818
|
+
return GarsiaProcesiModule(self, la)
|
|
1819
|
+
|
|
1820
|
+
def jucys_murphy(self, k):
|
|
1821
|
+
r"""
|
|
1822
|
+
Return the Jucys-Murphy element `J_k` (also known as a
|
|
1823
|
+
Young-Jucys-Murphy element) for the symmetric group
|
|
1824
|
+
algebra ``self``.
|
|
1825
|
+
|
|
1826
|
+
The Jucys-Murphy element `J_k` in the symmetric group algebra
|
|
1827
|
+
`R S_n` is defined for every `k \in \{ 1, 2, \ldots, n \}` by
|
|
1828
|
+
|
|
1829
|
+
.. MATH::
|
|
1830
|
+
|
|
1831
|
+
J_k = (1, k) + (2, k) + \cdots + (k-1, k) \in R S_n,
|
|
1832
|
+
|
|
1833
|
+
where the addends are transpositions in `S_n` (regarded as
|
|
1834
|
+
elements of `R S_n`). We note that there is not a dependence on `n`,
|
|
1835
|
+
so it is often suppressed in the notation.
|
|
1836
|
+
|
|
1837
|
+
EXAMPLES::
|
|
1838
|
+
|
|
1839
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
|
|
1840
|
+
sage: QS3.jucys_murphy(1)
|
|
1841
|
+
0
|
|
1842
|
+
sage: QS3.jucys_murphy(2)
|
|
1843
|
+
[2, 1, 3]
|
|
1844
|
+
sage: QS3.jucys_murphy(3)
|
|
1845
|
+
[1, 3, 2] + [3, 2, 1]
|
|
1846
|
+
|
|
1847
|
+
sage: QS4 = SymmetricGroupAlgebra(QQ, 4)
|
|
1848
|
+
sage: j3 = QS4.jucys_murphy(3); j3
|
|
1849
|
+
[1, 3, 2, 4] + [3, 2, 1, 4]
|
|
1850
|
+
sage: j4 = QS4.jucys_murphy(4); j4
|
|
1851
|
+
[1, 2, 4, 3] + [1, 4, 3, 2] + [4, 2, 3, 1]
|
|
1852
|
+
sage: j3*j4 == j4*j3
|
|
1853
|
+
True
|
|
1854
|
+
|
|
1855
|
+
sage: QS5 = SymmetricGroupAlgebra(QQ, 5)
|
|
1856
|
+
sage: QS5.jucys_murphy(4)
|
|
1857
|
+
[1, 2, 4, 3, 5] + [1, 4, 3, 2, 5] + [4, 2, 3, 1, 5]
|
|
1858
|
+
|
|
1859
|
+
TESTS::
|
|
1860
|
+
|
|
1861
|
+
sage: QS3.jucys_murphy(4)
|
|
1862
|
+
Traceback (most recent call last):
|
|
1863
|
+
...
|
|
1864
|
+
ValueError: k (= 4) must be between 1 and n (= 3) (inclusive)
|
|
1865
|
+
"""
|
|
1866
|
+
if k < 1 or k > self.n:
|
|
1867
|
+
raise ValueError("k (= {k}) must be between 1 and n (= {n}) (inclusive)".format(k=k, n=self.n))
|
|
1868
|
+
|
|
1869
|
+
res = self.zero()
|
|
1870
|
+
|
|
1871
|
+
for i in range(1, k):
|
|
1872
|
+
p = list(range(1, self.n + 1))
|
|
1873
|
+
p[i - 1] = k
|
|
1874
|
+
p[k - 1] = i
|
|
1875
|
+
res += self.monomial(self._indices(p))
|
|
1876
|
+
return res
|
|
1877
|
+
|
|
1878
|
+
def seminormal_basis(self, mult='l2r'):
|
|
1879
|
+
r"""
|
|
1880
|
+
Return a list of the seminormal basis elements of ``self``.
|
|
1881
|
+
|
|
1882
|
+
The seminormal basis of a symmetric group algebra is defined as
|
|
1883
|
+
follows:
|
|
1884
|
+
|
|
1885
|
+
Let `n` be a nonnegative integer. Let `R` be a `\QQ`-algebra.
|
|
1886
|
+
In the following, we will use the "left action" convention for
|
|
1887
|
+
multiplying permutations. This means that for all permutations
|
|
1888
|
+
`p` and `q` in `S_n`, the product `pq` is defined in such a way
|
|
1889
|
+
that `(pq)(i) = p(q(i))` for each `i \in \{ 1, 2, \ldots, n \}`
|
|
1890
|
+
(this is the same convention as in :meth:`left_action_product`,
|
|
1891
|
+
but not the default semantics of the `*` operator on
|
|
1892
|
+
permutations in Sage). Thus, for instance, `s_2 s_1` is the
|
|
1893
|
+
permutation obtained by first transposing `1` with `2` and
|
|
1894
|
+
then transposing `2` with `3` (where `s_i = (i, i+1)`).
|
|
1895
|
+
|
|
1896
|
+
For every partition `\lambda` of `n`, let
|
|
1897
|
+
|
|
1898
|
+
.. MATH::
|
|
1899
|
+
|
|
1900
|
+
\kappa_{\lambda} = \frac{n!}{f^{\lambda}}
|
|
1901
|
+
|
|
1902
|
+
where `f^{\lambda}` is the number of standard Young tableaux
|
|
1903
|
+
of shape `\lambda`. Note that `\kappa_{\lambda}` is an integer,
|
|
1904
|
+
namely the product of all hook lengths of `\lambda` (by the
|
|
1905
|
+
hook length formula). In Sage, this integer can be computed by
|
|
1906
|
+
using :func:`sage.combinat.symmetric_group_algebra.kappa()`.
|
|
1907
|
+
|
|
1908
|
+
Let `T` be a standard tableau of size `n`.
|
|
1909
|
+
|
|
1910
|
+
Let `a(T)` denote the formal sum (in `R S_n`) of all
|
|
1911
|
+
permutations in `S_n` which stabilize the rows of `T` (as
|
|
1912
|
+
sets), i. e., which map each entry `i` of `T` to an entry in
|
|
1913
|
+
the same row as `i`. (See
|
|
1914
|
+
:func:`sage.combinat.symmetric_group_algebra.a()` for
|
|
1915
|
+
an implementation of this.)
|
|
1916
|
+
|
|
1917
|
+
Let `b(T)` denote the signed formal sum (in `R S_n`) of all
|
|
1918
|
+
permutations in `S_n` which stabilize the columns of `T` (as
|
|
1919
|
+
sets). Here, "signed" means that each permutation is
|
|
1920
|
+
multiplied with its sign. (This is implemented in
|
|
1921
|
+
:func:`sage.combinat.symmetric_group_algebra.b()`.)
|
|
1922
|
+
|
|
1923
|
+
Define an element `e(T)` of `R S_n` to be `a(T) b(T)`. (This
|
|
1924
|
+
is implemented in :func:`sage.combinat.symmetric_group_algebra.e()`
|
|
1925
|
+
for `R = \QQ`.)
|
|
1926
|
+
|
|
1927
|
+
Let `\mathrm{sh}(T)` denote the shape of `T`.
|
|
1928
|
+
(See :meth:`~sage.combinat.tableau.Tableau.shape`.)
|
|
1929
|
+
|
|
1930
|
+
Let `\overline{T}` denote the standard tableau of size `n-1`
|
|
1931
|
+
obtained by removing the letter `n` (along with its cell) from
|
|
1932
|
+
`T` (if `n \geq 1`).
|
|
1933
|
+
|
|
1934
|
+
Now, we define an element `\epsilon(T)` of `R S_n`. We define
|
|
1935
|
+
it by induction on the size `n` of `T`, so we set
|
|
1936
|
+
`\epsilon(\emptyset) = 1` and only need to define `\epsilon(T)`
|
|
1937
|
+
for `n \geq 1`, assuming that `\epsilon(\overline{T})` is
|
|
1938
|
+
already defined. We do this by setting
|
|
1939
|
+
|
|
1940
|
+
.. MATH::
|
|
1941
|
+
|
|
1942
|
+
\epsilon(T) = \frac{1}{\kappa_{\mathrm{sh}(T)}}
|
|
1943
|
+
\epsilon(\overline{T})
|
|
1944
|
+
e(T) \epsilon(\overline{T}).
|
|
1945
|
+
|
|
1946
|
+
This element `\epsilon(T)` is implemented as
|
|
1947
|
+
:func:`sage.combinat.symmetric_group_algebra.epsilon` for
|
|
1948
|
+
`R = \QQ`, but it is also a particular case of the elements
|
|
1949
|
+
`\epsilon(T, S)` defined below.
|
|
1950
|
+
|
|
1951
|
+
Now let `S` be a further tableau of the same shape as `T`
|
|
1952
|
+
(possibly equal to `T`). Let `\pi_{T, S}` denote the
|
|
1953
|
+
permutation in `S_n` such that applying this permutation to
|
|
1954
|
+
the entries of `T` yields the tableau `S`. Define an element
|
|
1955
|
+
`\epsilon(T, S)` of `R S_n` by
|
|
1956
|
+
|
|
1957
|
+
.. MATH::
|
|
1958
|
+
|
|
1959
|
+
\epsilon(T, S) = \frac{1}{\kappa_{\mathrm{sh}(T)}}
|
|
1960
|
+
\epsilon(\overline S) \pi_{T, S}
|
|
1961
|
+
e(T) \epsilon(\overline T)
|
|
1962
|
+
= \frac{1}{\kappa_{\mathrm{sh}(T)}}
|
|
1963
|
+
\epsilon(\overline S) a(S) \pi_{T, S}
|
|
1964
|
+
b(T) \epsilon(\overline T).
|
|
1965
|
+
|
|
1966
|
+
This element `\epsilon(T, S)` is called *Young's seminormal
|
|
1967
|
+
unit corresponding to the bitableau `(T, S)`*, and is the
|
|
1968
|
+
return value of :meth:`epsilon_ik` applied to ``T`` and
|
|
1969
|
+
``S``. Note that `\epsilon(T, T) = \epsilon(T)`.
|
|
1970
|
+
|
|
1971
|
+
If we let `\lambda` run through all partitions of `n`, and
|
|
1972
|
+
`(T, S)` run through all pairs of tableaux of shape
|
|
1973
|
+
`\lambda`, then the elements `\epsilon(T, S)` form a basis
|
|
1974
|
+
of `R S_n`. This basis is called *Young's seminormal basis*
|
|
1975
|
+
and has the properties that
|
|
1976
|
+
|
|
1977
|
+
.. MATH::
|
|
1978
|
+
|
|
1979
|
+
\epsilon(T, S) \epsilon(U, V) = \delta_{T, V} \epsilon(U, S)
|
|
1980
|
+
|
|
1981
|
+
(where `\delta` stands for the Kronecker delta).
|
|
1982
|
+
|
|
1983
|
+
.. WARNING::
|
|
1984
|
+
|
|
1985
|
+
Because of our convention, we are multiplying our elements in
|
|
1986
|
+
reverse of those given in some papers, for example [Ram1997]_.
|
|
1987
|
+
Using the other convention of multiplying permutations, we would
|
|
1988
|
+
instead have
|
|
1989
|
+
`\epsilon(U, V) \epsilon(T, S) = \delta_{T, V} \epsilon(U, S)`.
|
|
1990
|
+
|
|
1991
|
+
In other words, Young's seminormal basis consists of the matrix
|
|
1992
|
+
units in a (particular) Artin-Wedderburn decomposition of `R S_n`
|
|
1993
|
+
into a direct product of matrix algebras over `\QQ`.
|
|
1994
|
+
|
|
1995
|
+
The output of :meth:`seminormal_basis` is a list of all
|
|
1996
|
+
elements of the seminormal basis of ``self``.
|
|
1997
|
+
|
|
1998
|
+
INPUT:
|
|
1999
|
+
|
|
2000
|
+
- ``mult`` -- string (default: ``'l2r'``); if set to ``'r2l'``,
|
|
2001
|
+
this causes the method to return the list of the
|
|
2002
|
+
antipodes (:meth:`antipode`) of all `\epsilon(T, S)`
|
|
2003
|
+
instead of the `\epsilon(T, S)` themselves.
|
|
2004
|
+
|
|
2005
|
+
EXAMPLES::
|
|
2006
|
+
|
|
2007
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ,3)
|
|
2008
|
+
sage: QS3.seminormal_basis()
|
|
2009
|
+
[1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] + 1/6*[3, 2, 1],
|
|
2010
|
+
1/3*[1, 2, 3] + 1/6*[1, 3, 2] - 1/3*[2, 1, 3] - 1/6*[2, 3, 1] - 1/6*[3, 1, 2] + 1/6*[3, 2, 1],
|
|
2011
|
+
1/3*[1, 3, 2] + 1/3*[2, 3, 1] - 1/3*[3, 1, 2] - 1/3*[3, 2, 1],
|
|
2012
|
+
1/4*[1, 3, 2] - 1/4*[2, 3, 1] + 1/4*[3, 1, 2] - 1/4*[3, 2, 1],
|
|
2013
|
+
1/3*[1, 2, 3] - 1/6*[1, 3, 2] + 1/3*[2, 1, 3] - 1/6*[2, 3, 1] - 1/6*[3, 1, 2] - 1/6*[3, 2, 1],
|
|
2014
|
+
1/6*[1, 2, 3] - 1/6*[1, 3, 2] - 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] - 1/6*[3, 2, 1]]
|
|
2015
|
+
|
|
2016
|
+
TESTS::
|
|
2017
|
+
|
|
2018
|
+
sage: QS3g = SymmetricGroup(3).algebra(QQ)
|
|
2019
|
+
sage: QS3g.seminormal_basis()
|
|
2020
|
+
[1/6*() + 1/6*(2,3) + 1/6*(1,2) + 1/6*(1,2,3) + 1/6*(1,3,2) + 1/6*(1,3),
|
|
2021
|
+
1/3*() + 1/6*(2,3) - 1/3*(1,2) - 1/6*(1,2,3) - 1/6*(1,3,2) + 1/6*(1,3),
|
|
2022
|
+
1/3*(2,3) + 1/3*(1,2,3) - 1/3*(1,3,2) - 1/3*(1,3),
|
|
2023
|
+
1/4*(2,3) - 1/4*(1,2,3) + 1/4*(1,3,2) - 1/4*(1,3),
|
|
2024
|
+
1/3*() - 1/6*(2,3) + 1/3*(1,2) - 1/6*(1,2,3) - 1/6*(1,3,2) - 1/6*(1,3),
|
|
2025
|
+
1/6*() - 1/6*(2,3) - 1/6*(1,2) + 1/6*(1,2,3) + 1/6*(1,3,2) - 1/6*(1,3)]
|
|
2026
|
+
"""
|
|
2027
|
+
basis = []
|
|
2028
|
+
for part in Partitions_n(self.n):
|
|
2029
|
+
stp = StandardTableaux_shape(part)
|
|
2030
|
+
basis.extend(self.epsilon_ik(t1, t2, mult=mult)
|
|
2031
|
+
for t1 in stp
|
|
2032
|
+
for t2 in stp)
|
|
2033
|
+
return basis
|
|
2034
|
+
|
|
2035
|
+
def dft(self, form=None, mult='l2r'):
|
|
2036
|
+
r"""
|
|
2037
|
+
Return the discrete Fourier transform for ``self``.
|
|
2038
|
+
|
|
2039
|
+
See [Mur1983]_ for the construction of central primitive orthogonal idempotents.
|
|
2040
|
+
For each idempotent `e_i` we have a homomorphic projection `v \mapsto v e_i`.
|
|
2041
|
+
Choose a basis for each submodule spanned by `\{\sigma e_i | \sigma \in S_n\}`.
|
|
2042
|
+
The change-of-basis from the standard basis `\{\sigma\}_\sigma` is returned.
|
|
2043
|
+
|
|
2044
|
+
INPUT:
|
|
2045
|
+
|
|
2046
|
+
- ``mult`` -- string (default: `l2r`); if set to `r2l`,
|
|
2047
|
+
this causes the method to use the antipodes
|
|
2048
|
+
(:meth:`antipode`) of the seminormal basis instead of
|
|
2049
|
+
the seminormal basis.
|
|
2050
|
+
|
|
2051
|
+
- ``form`` -- string (default: ``"modular"`` if `p|n!` else ``"seminormal"``);
|
|
2052
|
+
one of the following:
|
|
2053
|
+
|
|
2054
|
+
* ``"seminormal"`` -- use the seminormal basis
|
|
2055
|
+
* ``"modular"`` -- use the modular DFT, which uses the Peirce decomposition
|
|
2056
|
+
of the group algebra into blocks with central orthogonal idempotents
|
|
2057
|
+
* ``"unitary"`` -- use the unitary DFT, which computes the extended
|
|
2058
|
+
Cholesky decomposition of an `S_n`-invariant symmetric bilinear form as
|
|
2059
|
+
a change-of-basis matrix (for positive characteristics, it must be
|
|
2060
|
+
a finite field of square order)
|
|
2061
|
+
|
|
2062
|
+
EXAMPLES:
|
|
2063
|
+
|
|
2064
|
+
The default is the seminormal DFT when the characteristic does not divide the group order::
|
|
2065
|
+
|
|
2066
|
+
sage: QQ_S3 = SymmetricGroupAlgebra(QQ, 3)
|
|
2067
|
+
sage: QQ_S3.dft()
|
|
2068
|
+
[ 1 1 1 1 1 1]
|
|
2069
|
+
[ 1 1/2 -1 -1/2 -1/2 1/2]
|
|
2070
|
+
[ 0 3/4 0 3/4 -3/4 -3/4]
|
|
2071
|
+
[ 0 1 0 -1 1 -1]
|
|
2072
|
+
[ 1 -1/2 1 -1/2 -1/2 -1/2]
|
|
2073
|
+
[ 1 -1 -1 1 1 -1]
|
|
2074
|
+
|
|
2075
|
+
The unitary form works in characteristic zero::
|
|
2076
|
+
|
|
2077
|
+
sage: U = QQ_S3.dft(form='unitary'); U
|
|
2078
|
+
[-1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2]
|
|
2079
|
+
[ 1/3*sqrt3 1/6*sqrt3 -1/3*sqrt3 -1/6*sqrt3 -1/6*sqrt3 1/6*sqrt3]
|
|
2080
|
+
[ 0 1/2 0 1/2 -1/2 -1/2]
|
|
2081
|
+
[ 0 1/2 0 -1/2 1/2 -1/2]
|
|
2082
|
+
[ 1/3*sqrt3 -1/6*sqrt3 1/3*sqrt3 -1/6*sqrt3 -1/6*sqrt3 -1/6*sqrt3]
|
|
2083
|
+
[-1/6*sqrt3*sqrt2 1/6*sqrt3*sqrt2 1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 1/6*sqrt3*sqrt2]
|
|
2084
|
+
sage: U*U.H == 1
|
|
2085
|
+
True
|
|
2086
|
+
|
|
2087
|
+
Over finite fields of square order with characteristic `p > n`, we can perform the unitary DFT::
|
|
2088
|
+
|
|
2089
|
+
sage: GF25_S3 = SymmetricGroupAlgebra(GF(5**2), 3)
|
|
2090
|
+
sage: U = GF25_S3.dft(form='unitary'); U
|
|
2091
|
+
[ 1 1 1 1 1 1]
|
|
2092
|
+
[2*z2 + 4 z2 + 2 3*z2 + 1 4*z2 + 3 4*z2 + 3 z2 + 2]
|
|
2093
|
+
[ 0 2 0 2 3 3]
|
|
2094
|
+
[ 0 z2 + 1 0 4*z2 + 4 z2 + 1 4*z2 + 4]
|
|
2095
|
+
[2*z2 + 4 4*z2 + 3 2*z2 + 4 4*z2 + 3 4*z2 + 3 4*z2 + 3]
|
|
2096
|
+
[ 1 4 4 1 1 4]
|
|
2097
|
+
sage: U*U.H == 1
|
|
2098
|
+
True
|
|
2099
|
+
|
|
2100
|
+
Over fields of characteristic `p > 0` such that `p|n!`, we use the
|
|
2101
|
+
modular Fourier transform (:issue:`37751`)::
|
|
2102
|
+
|
|
2103
|
+
sage: GF2_S3 = SymmetricGroupAlgebra(GF(2), 3)
|
|
2104
|
+
sage: GF2_S3.dft()
|
|
2105
|
+
[1 0 0 0 1 0]
|
|
2106
|
+
[0 1 0 0 0 1]
|
|
2107
|
+
[0 0 1 0 0 1]
|
|
2108
|
+
[0 0 0 1 1 0]
|
|
2109
|
+
[1 0 0 1 1 0]
|
|
2110
|
+
[0 1 1 0 0 1]
|
|
2111
|
+
"""
|
|
2112
|
+
if form is None:
|
|
2113
|
+
form = "modular" if self.base_ring().characteristic().divides(self.group().cardinality()) else "seminormal"
|
|
2114
|
+
if form == "seminormal":
|
|
2115
|
+
if self.base_ring().characteristic().divides(self.group().cardinality()):
|
|
2116
|
+
raise ValueError("seminormal does not work when p | n!")
|
|
2117
|
+
return self._dft_seminormal(mult=mult)
|
|
2118
|
+
if form == "modular":
|
|
2119
|
+
return self._dft_modular()
|
|
2120
|
+
if form == "unitary":
|
|
2121
|
+
return self._dft_unitary()
|
|
2122
|
+
raise ValueError(f"invalid form (= {form})")
|
|
2123
|
+
|
|
2124
|
+
def _dft_unitary(self):
|
|
2125
|
+
"""
|
|
2126
|
+
Return the unitary form of the discrete Fourier transform for ``self``.
|
|
2127
|
+
|
|
2128
|
+
EXAMPLES::
|
|
2129
|
+
|
|
2130
|
+
sage: QQ_S3 = SymmetricGroupAlgebra(QQ, 3)
|
|
2131
|
+
sage: QQ_S3._dft_unitary()
|
|
2132
|
+
[-1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2]
|
|
2133
|
+
[ 1/3*sqrt3 1/6*sqrt3 -1/3*sqrt3 -1/6*sqrt3 -1/6*sqrt3 1/6*sqrt3]
|
|
2134
|
+
[ 0 1/2 0 1/2 -1/2 -1/2]
|
|
2135
|
+
[ 0 1/2 0 -1/2 1/2 -1/2]
|
|
2136
|
+
[ 1/3*sqrt3 -1/6*sqrt3 1/3*sqrt3 -1/6*sqrt3 -1/6*sqrt3 -1/6*sqrt3]
|
|
2137
|
+
[-1/6*sqrt3*sqrt2 1/6*sqrt3*sqrt2 1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 -1/6*sqrt3*sqrt2 1/6*sqrt3*sqrt2]
|
|
2138
|
+
sage: GF49_S3 = SymmetricGroupAlgebra(GF(7**2), 3)
|
|
2139
|
+
sage: GF49_S3._dft_unitary()
|
|
2140
|
+
[5*z2 + 5 5*z2 + 5 5*z2 + 5 5*z2 + 5 5*z2 + 5 5*z2 + 5]
|
|
2141
|
+
[2*z2 + 5 z2 + 6 5*z2 + 2 6*z2 + 1 6*z2 + 1 z2 + 6]
|
|
2142
|
+
[ 0 4*z2 + 5 0 4*z2 + 5 3*z2 + 2 3*z2 + 2]
|
|
2143
|
+
[ 0 3*z2 + 2 0 4*z2 + 5 3*z2 + 2 4*z2 + 5]
|
|
2144
|
+
[2*z2 + 5 6*z2 + 1 2*z2 + 5 6*z2 + 1 6*z2 + 1 6*z2 + 1]
|
|
2145
|
+
[5*z2 + 5 2*z2 + 2 2*z2 + 2 5*z2 + 5 5*z2 + 5 2*z2 + 2]
|
|
2146
|
+
|
|
2147
|
+
TESTS::
|
|
2148
|
+
|
|
2149
|
+
sage: QQ_S3 = SymmetricGroupAlgebra(QQ, 3)
|
|
2150
|
+
sage: U = QQ_S3._dft_unitary()
|
|
2151
|
+
sage: U*U.H == 1
|
|
2152
|
+
True
|
|
2153
|
+
sage: GF25_S3 = SymmetricGroupAlgebra(GF(5**2), 3)
|
|
2154
|
+
sage: U = GF25_S3._dft_unitary()
|
|
2155
|
+
sage: U*U.H == 1
|
|
2156
|
+
True
|
|
2157
|
+
sage: GF5_S3 = SymmetricGroupAlgebra(GF(5), 3)
|
|
2158
|
+
sage: U = GF5_S3._dft_unitary()
|
|
2159
|
+
Traceback (most recent call last):
|
|
2160
|
+
...
|
|
2161
|
+
ValueError: the base ring must be a finite field of square order
|
|
2162
|
+
sage: Z5_S3 = SymmetricGroupAlgebra(Integers(5), 3)
|
|
2163
|
+
sage: U = Z5_S3._dft_unitary()
|
|
2164
|
+
Traceback (most recent call last):
|
|
2165
|
+
...
|
|
2166
|
+
ValueError: the base ring must be a finite field of square order
|
|
2167
|
+
sage: F.<x> = FunctionField(GF(3))
|
|
2168
|
+
sage: GF3_x_S3 = SymmetricGroupAlgebra(F, 5)
|
|
2169
|
+
sage: U = GF3_x_S3._dft_unitary()
|
|
2170
|
+
Traceback (most recent call last):
|
|
2171
|
+
...
|
|
2172
|
+
ValueError: the base ring must be a finite field of square order
|
|
2173
|
+
sage: GF9_S3 = SymmetricGroupAlgebra(GF(3**2), 3)
|
|
2174
|
+
sage: U = GF9_S3._dft_unitary()
|
|
2175
|
+
Traceback (most recent call last):
|
|
2176
|
+
...
|
|
2177
|
+
NotImplementedError: not implemented when p|n!; dimension of invariant forms may be greater than one
|
|
2178
|
+
"""
|
|
2179
|
+
from sage.matrix.special import diagonal_matrix
|
|
2180
|
+
F = self.base_ring()
|
|
2181
|
+
G = self.group()
|
|
2182
|
+
|
|
2183
|
+
if F.characteristic() == 0:
|
|
2184
|
+
from sage.misc.functional import sqrt
|
|
2185
|
+
from sage.rings.number_field.number_field import NumberField
|
|
2186
|
+
dft_matrix = self.dft()
|
|
2187
|
+
n = dft_matrix.nrows()
|
|
2188
|
+
diag = [sum(dft_matrix[i, j] * dft_matrix[i, j].conjugate() for j in range(n))
|
|
2189
|
+
for i in range(n)]
|
|
2190
|
+
primes_needed = {factor for d in diag for factor, _ in d.squarefree_part().factor()}
|
|
2191
|
+
names = [f"sqrt{factor}" for factor in primes_needed]
|
|
2192
|
+
x = PolynomialRing(QQ, 'x').gen()
|
|
2193
|
+
K = NumberField([x**2 - d for d in primes_needed], names=names)
|
|
2194
|
+
dft_matrix = dft_matrix.change_ring(K)
|
|
2195
|
+
for i, d in enumerate(diag):
|
|
2196
|
+
dft_matrix[i] *= ~sqrt(K(d))
|
|
2197
|
+
return dft_matrix
|
|
2198
|
+
|
|
2199
|
+
# positive characteristic case
|
|
2200
|
+
assert F.characteristic() > 0, "F must have positive characteristic"
|
|
2201
|
+
if not (F.is_field() and F.is_finite() and F.order().is_square()):
|
|
2202
|
+
raise ValueError("the base ring must be a finite field of square order")
|
|
2203
|
+
if F.characteristic().divides(G.cardinality()):
|
|
2204
|
+
raise NotImplementedError("not implemented when p|n!; dimension of invariant forms may be greater than one")
|
|
2205
|
+
q = F.order().sqrt()
|
|
2206
|
+
|
|
2207
|
+
def conj_square_root(u):
|
|
2208
|
+
if not u:
|
|
2209
|
+
return F.zero()
|
|
2210
|
+
z = F.multiplicative_generator()
|
|
2211
|
+
k = u.log(z)
|
|
2212
|
+
if k % (q+1) != 0:
|
|
2213
|
+
raise ValueError(f"unable to factor as {u} is not in base field GF({q})")
|
|
2214
|
+
return z ** ((k//(q+1)) % (q-1))
|
|
2215
|
+
|
|
2216
|
+
dft_matrix = self.dft()
|
|
2217
|
+
n = dft_matrix.nrows()
|
|
2218
|
+
for i in range(n):
|
|
2219
|
+
d = sum(dft_matrix[i, j] * dft_matrix[i, j].conjugate() for j in range(n))
|
|
2220
|
+
dft_matrix[i] *= ~conj_square_root(d)
|
|
2221
|
+
return dft_matrix
|
|
2222
|
+
|
|
2223
|
+
def _dft_seminormal(self, mult='l2r'):
|
|
2224
|
+
"""
|
|
2225
|
+
Return the seminormal form of the discrete Fourier transform for ``self``.
|
|
2226
|
+
|
|
2227
|
+
INPUT:
|
|
2228
|
+
|
|
2229
|
+
- ``mult`` -- string (default: `l2r`); if set to `r2l`,
|
|
2230
|
+
this causes the method to use the antipodes
|
|
2231
|
+
(:meth:`antipode`) of the seminormal basis instead of
|
|
2232
|
+
the seminormal basis.
|
|
2233
|
+
|
|
2234
|
+
EXAMPLES::
|
|
2235
|
+
|
|
2236
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
|
|
2237
|
+
sage: QS3._dft_seminormal()
|
|
2238
|
+
[ 1 1 1 1 1 1]
|
|
2239
|
+
[ 1 1/2 -1 -1/2 -1/2 1/2]
|
|
2240
|
+
[ 0 3/4 0 3/4 -3/4 -3/4]
|
|
2241
|
+
[ 0 1 0 -1 1 -1]
|
|
2242
|
+
[ 1 -1/2 1 -1/2 -1/2 -1/2]
|
|
2243
|
+
[ 1 -1 -1 1 1 -1]
|
|
2244
|
+
|
|
2245
|
+
.. SEEALSO::
|
|
2246
|
+
|
|
2247
|
+
:meth:`seminormal_basis`
|
|
2248
|
+
"""
|
|
2249
|
+
snb = self.seminormal_basis(mult=mult)
|
|
2250
|
+
return matrix([vector(b) for b in snb]).inverse().transpose()
|
|
2251
|
+
|
|
2252
|
+
def _dft_modular(self):
|
|
2253
|
+
r"""
|
|
2254
|
+
Return the discrete Fourier transform when the characteristic divides the order of the group.
|
|
2255
|
+
|
|
2256
|
+
EXAMPLES::
|
|
2257
|
+
|
|
2258
|
+
sage: GF3S3 = SymmetricGroupAlgebra(GF(3), 3)
|
|
2259
|
+
sage: GF3S3._dft_modular()
|
|
2260
|
+
[1 0 0 0 0 0]
|
|
2261
|
+
[0 1 0 0 0 0]
|
|
2262
|
+
[0 0 1 0 0 0]
|
|
2263
|
+
[0 0 0 1 0 0]
|
|
2264
|
+
[0 0 0 0 1 0]
|
|
2265
|
+
[0 0 0 0 0 1]
|
|
2266
|
+
"""
|
|
2267
|
+
idempotents = self.central_orthogonal_idempotents()
|
|
2268
|
+
# project v onto each block U_i = F_p[S_n]*e_i via \pi_i: v |--> v*e_i
|
|
2269
|
+
B = self.basis()
|
|
2270
|
+
blocks = [self.submodule([b * idem for b in B]) for idem in idempotents]
|
|
2271
|
+
# compute the list of basis vectors lifted to the SGA from each block
|
|
2272
|
+
block_decomposition_basis = [u.lift() for block in blocks for u in block.basis()]
|
|
2273
|
+
# construct the matrix to the standard basis in the order given by the group
|
|
2274
|
+
G = self.group()
|
|
2275
|
+
mat = [[b[g] for b in block_decomposition_basis] for g in G]
|
|
2276
|
+
return matrix(self.base_ring(), mat)
|
|
2277
|
+
|
|
2278
|
+
def epsilon_ik(self, itab, ktab, star=0, mult='l2r'):
|
|
2279
|
+
r"""
|
|
2280
|
+
Return the seminormal basis element of ``self`` corresponding to the
|
|
2281
|
+
pair of tableaux ``itab`` and ``ktab`` (or restrictions of these
|
|
2282
|
+
tableaux, if the optional variable ``star`` is set).
|
|
2283
|
+
|
|
2284
|
+
INPUT:
|
|
2285
|
+
|
|
2286
|
+
- ``itab``, ``ktab`` -- two standard tableaux of size `n`
|
|
2287
|
+
|
|
2288
|
+
- ``star`` -- integer (default: `0`)
|
|
2289
|
+
|
|
2290
|
+
- ``mult`` -- string (default: `l2r`); if set to `r2l`,
|
|
2291
|
+
this causes the method to return the antipode
|
|
2292
|
+
(:meth:`antipode`) of `\epsilon(I, K)` instead of
|
|
2293
|
+
`\epsilon(I, K)` itself.
|
|
2294
|
+
|
|
2295
|
+
OUTPUT:
|
|
2296
|
+
|
|
2297
|
+
The element `\epsilon(I, K)`, where `I` and `K` are the tableaux
|
|
2298
|
+
obtained by removing all entries higher than `n - \mathrm{star}`
|
|
2299
|
+
from ``itab`` and ``ktab``, respectively. Here, we are using the
|
|
2300
|
+
notations from :meth:`seminormal_basis`.
|
|
2301
|
+
|
|
2302
|
+
EXAMPLES::
|
|
2303
|
+
|
|
2304
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
|
|
2305
|
+
sage: a = QS3.epsilon_ik([[1,2,3]], [[1,2,3]]); a
|
|
2306
|
+
1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] + 1/6*[3, 2, 1]
|
|
2307
|
+
sage: QS3.dft()*vector(a)
|
|
2308
|
+
(1, 0, 0, 0, 0, 0)
|
|
2309
|
+
sage: a = QS3.epsilon_ik([[1,2],[3]], [[1,2],[3]]); a
|
|
2310
|
+
1/3*[1, 2, 3] - 1/6*[1, 3, 2] + 1/3*[2, 1, 3] - 1/6*[2, 3, 1] - 1/6*[3, 1, 2] - 1/6*[3, 2, 1]
|
|
2311
|
+
sage: QS3.dft()*vector(a)
|
|
2312
|
+
(0, 0, 0, 0, 1, 0)
|
|
2313
|
+
|
|
2314
|
+
Let us take some properties of the seminormal basis listed in
|
|
2315
|
+
the docstring of :meth:`seminormal_basis`, and verify them on
|
|
2316
|
+
the situation of `S_3`.
|
|
2317
|
+
|
|
2318
|
+
First, check the formula
|
|
2319
|
+
|
|
2320
|
+
.. MATH::
|
|
2321
|
+
|
|
2322
|
+
\epsilon(T) = \frac{1}{\kappa_{\mathrm{sh}(T)}}
|
|
2323
|
+
\epsilon(\overline{T})
|
|
2324
|
+
e(T) \epsilon(\overline{T}).
|
|
2325
|
+
|
|
2326
|
+
In fact::
|
|
2327
|
+
|
|
2328
|
+
sage: from sage.combinat.symmetric_group_algebra import e
|
|
2329
|
+
sage: def test_sn1(n):
|
|
2330
|
+
....: QSn = SymmetricGroupAlgebra(QQ, n)
|
|
2331
|
+
....: QSn1 = SymmetricGroupAlgebra(QQ, n - 1)
|
|
2332
|
+
....: for T in StandardTableaux(n):
|
|
2333
|
+
....: TT = T.restrict(n-1)
|
|
2334
|
+
....: eTT = QSn1.epsilon_ik(TT, TT)
|
|
2335
|
+
....: eT = QSn.epsilon_ik(T, T)
|
|
2336
|
+
....: kT = prod(T.shape().hooks())
|
|
2337
|
+
....: if kT * eT != eTT * e(T) * eTT:
|
|
2338
|
+
....: return False
|
|
2339
|
+
....: return True
|
|
2340
|
+
sage: test_sn1(3)
|
|
2341
|
+
True
|
|
2342
|
+
sage: test_sn1(4) # long time
|
|
2343
|
+
True
|
|
2344
|
+
|
|
2345
|
+
Next, we check the identity
|
|
2346
|
+
|
|
2347
|
+
.. MATH::
|
|
2348
|
+
|
|
2349
|
+
\epsilon(T, S) = \frac{1}{\kappa_{\mathrm{sh}(T)}}
|
|
2350
|
+
\epsilon(\overline S) \pi_{T, S}
|
|
2351
|
+
e(T) \epsilon(\overline T)
|
|
2352
|
+
|
|
2353
|
+
which we used to define `\epsilon(T, S)`. In fact::
|
|
2354
|
+
|
|
2355
|
+
sage: from sage.combinat.symmetric_group_algebra import e
|
|
2356
|
+
sage: def test_sn2(n):
|
|
2357
|
+
....: QSn = SymmetricGroupAlgebra(QQ, n)
|
|
2358
|
+
....: mul = QSn.left_action_product
|
|
2359
|
+
....: QSn1 = SymmetricGroupAlgebra(QQ, n - 1)
|
|
2360
|
+
....: for lam in Partitions(n):
|
|
2361
|
+
....: k = prod(lam.hooks())
|
|
2362
|
+
....: for T in StandardTableaux(lam):
|
|
2363
|
+
....: for S in StandardTableaux(lam):
|
|
2364
|
+
....: TT = T.restrict(n-1)
|
|
2365
|
+
....: SS = S.restrict(n-1)
|
|
2366
|
+
....: eTT = QSn1.epsilon_ik(TT, TT)
|
|
2367
|
+
....: eSS = QSn1.epsilon_ik(SS, SS)
|
|
2368
|
+
....: eTS = QSn.epsilon_ik(T, S)
|
|
2369
|
+
....: piTS = [0] * n
|
|
2370
|
+
....: for (i, j) in T.cells():
|
|
2371
|
+
....: piTS[T[i][j] - 1] = S[i][j]
|
|
2372
|
+
....: piTS = QSn(Permutation(piTS))
|
|
2373
|
+
....: if k * eTS != mul(mul(eSS, piTS), mul(e(T), eTT)):
|
|
2374
|
+
....: return False
|
|
2375
|
+
....: return True
|
|
2376
|
+
sage: test_sn2(3)
|
|
2377
|
+
True
|
|
2378
|
+
sage: test_sn2(4) # long time
|
|
2379
|
+
True
|
|
2380
|
+
|
|
2381
|
+
Let us finally check the identity
|
|
2382
|
+
|
|
2383
|
+
.. MATH::
|
|
2384
|
+
|
|
2385
|
+
\epsilon(T, S) \epsilon(U, V) = \delta_{T, V} \epsilon(U, S)
|
|
2386
|
+
|
|
2387
|
+
In fact::
|
|
2388
|
+
|
|
2389
|
+
sage: def test_sn3(lam):
|
|
2390
|
+
....: n = lam.size()
|
|
2391
|
+
....: QSn = SymmetricGroupAlgebra(QQ, n)
|
|
2392
|
+
....: mul = QSn.left_action_product
|
|
2393
|
+
....: for T in StandardTableaux(lam):
|
|
2394
|
+
....: for S in StandardTableaux(lam):
|
|
2395
|
+
....: for U in StandardTableaux(lam):
|
|
2396
|
+
....: for V in StandardTableaux(lam):
|
|
2397
|
+
....: lhs = mul(QSn.epsilon_ik(T, S), QSn.epsilon_ik(U, V))
|
|
2398
|
+
....: if T == V:
|
|
2399
|
+
....: rhs = QSn.epsilon_ik(U, S)
|
|
2400
|
+
....: else:
|
|
2401
|
+
....: rhs = QSn.zero()
|
|
2402
|
+
....: if rhs != lhs:
|
|
2403
|
+
....: return False
|
|
2404
|
+
....: return True
|
|
2405
|
+
sage: all( test_sn3(lam) for lam in Partitions(3) )
|
|
2406
|
+
True
|
|
2407
|
+
sage: all( test_sn3(lam) for lam in Partitions(4) ) # long time
|
|
2408
|
+
True
|
|
2409
|
+
"""
|
|
2410
|
+
it = Tableau(itab)
|
|
2411
|
+
kt = Tableau(ktab)
|
|
2412
|
+
|
|
2413
|
+
stn = StandardTableaux_size(self.n)
|
|
2414
|
+
|
|
2415
|
+
if it not in stn:
|
|
2416
|
+
raise TypeError("it must be a standard tableau of size %s" % self.n)
|
|
2417
|
+
|
|
2418
|
+
if kt not in stn:
|
|
2419
|
+
raise TypeError("kt must be a standard tableau of size %s" % self.n)
|
|
2420
|
+
|
|
2421
|
+
if it.shape() != kt.shape():
|
|
2422
|
+
raise ValueError("it and kt must be of the same shape")
|
|
2423
|
+
|
|
2424
|
+
BR = self.base_ring()
|
|
2425
|
+
I = self._indices
|
|
2426
|
+
z_elts = {}
|
|
2427
|
+
epik = epsilon_ik(it, kt, star=star)
|
|
2428
|
+
for m, c in epik._monomial_coefficients.items():
|
|
2429
|
+
z_elts[I(m)] = BR(c)
|
|
2430
|
+
z = self._from_dict(z_elts)
|
|
2431
|
+
|
|
2432
|
+
if mult == 'l2r':
|
|
2433
|
+
return z
|
|
2434
|
+
else:
|
|
2435
|
+
return z.map_support(lambda x: x.inverse())
|
|
2436
|
+
|
|
2437
|
+
def murphy_basis(self):
|
|
2438
|
+
r"""
|
|
2439
|
+
Return the :class:`Murphy basis
|
|
2440
|
+
<sage.combinat.symmetric_group_algebra.MurphyBasis>` of ``self``.
|
|
2441
|
+
|
|
2442
|
+
EXAMPLES::
|
|
2443
|
+
|
|
2444
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, 3)
|
|
2445
|
+
sage: M = SGA.murphy_basis()
|
|
2446
|
+
sage: M(SGA.an_element())
|
|
2447
|
+
-C([1, 1, 1], [[1], [2], [3]], [[1], [2], [3]])
|
|
2448
|
+
+ C([2, 1], [[1, 2], [3]], [[1, 2], [3]])
|
|
2449
|
+
+ C([2, 1], [[1, 2], [3]], [[1, 3], [2]])
|
|
2450
|
+
+ 2*C([2, 1], [[1, 3], [2]], [[1, 2], [3]])
|
|
2451
|
+
+ 4*C([2, 1], [[1, 3], [2]], [[1, 3], [2]])
|
|
2452
|
+
- 3*C([3], [[1, 2, 3]], [[1, 2, 3]])
|
|
2453
|
+
"""
|
|
2454
|
+
return MurphyBasis(self)
|
|
2455
|
+
|
|
2456
|
+
@cached_method(key=lambda s, X, Y: (StandardTableaux()(X), StandardTableaux()(Y)))
|
|
2457
|
+
def murphy_basis_element(self, S, T):
|
|
2458
|
+
r"""
|
|
2459
|
+
Return the Murphy basis element indexed by ``S`` and ``T``.
|
|
2460
|
+
|
|
2461
|
+
.. SEEALSO::
|
|
2462
|
+
|
|
2463
|
+
:class:`~sage.combinat.symmetric_group_algebra.MurphyBasis`
|
|
2464
|
+
|
|
2465
|
+
EXAMPLES::
|
|
2466
|
+
|
|
2467
|
+
sage: import itertools
|
|
2468
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, 3)
|
|
2469
|
+
sage: for S, T in itertools.product(StandardTableaux([2,1]), repeat=2):
|
|
2470
|
+
....: print(S, T, SGA.murphy_basis_element(S, T))
|
|
2471
|
+
[[1, 3], [2]] [[1, 3], [2]] [1, 2, 3] + [2, 1, 3]
|
|
2472
|
+
[[1, 3], [2]] [[1, 2], [3]] [1, 3, 2] + [3, 1, 2]
|
|
2473
|
+
[[1, 2], [3]] [[1, 3], [2]] [1, 3, 2] + [2, 3, 1]
|
|
2474
|
+
[[1, 2], [3]] [[1, 2], [3]] [1, 2, 3] + [3, 2, 1]
|
|
2475
|
+
|
|
2476
|
+
TESTS::
|
|
2477
|
+
|
|
2478
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, 3)
|
|
2479
|
+
sage: SGA.murphy_basis_element([[1,2,3,4]], [[1,2],[3,4]])
|
|
2480
|
+
Traceback (most recent call last):
|
|
2481
|
+
...
|
|
2482
|
+
ValueError: [[1, 2, 3, 4]] is not an element of Standard tableaux of size 3
|
|
2483
|
+
sage: SGA.murphy_basis_element([[1,2,3]], [[1,2],[3]])
|
|
2484
|
+
Traceback (most recent call last):
|
|
2485
|
+
...
|
|
2486
|
+
ValueError: S and T must have the same shape
|
|
2487
|
+
"""
|
|
2488
|
+
std_tab = StandardTableaux(self.n)
|
|
2489
|
+
S = std_tab(S)
|
|
2490
|
+
T = std_tab(T)
|
|
2491
|
+
S = S.conjugate()
|
|
2492
|
+
T = T.conjugate()
|
|
2493
|
+
|
|
2494
|
+
la = S.shape()
|
|
2495
|
+
if la != T.shape():
|
|
2496
|
+
raise ValueError("S and T must have the same shape")
|
|
2497
|
+
|
|
2498
|
+
G = self.group()
|
|
2499
|
+
ds = G(list(sum((row for row in S), ())))
|
|
2500
|
+
dt = G(list(sum((row for row in T), ())))
|
|
2501
|
+
return self.monomial(~ds) * self._row_stabilizer(la) * self.monomial(dt)
|
|
2502
|
+
|
|
2503
|
+
@cached_method
|
|
2504
|
+
def _row_stabilizer(self, la):
|
|
2505
|
+
"""
|
|
2506
|
+
Return the row stabilizer element of a canonical standard tableau
|
|
2507
|
+
of shape ``la``.
|
|
2508
|
+
|
|
2509
|
+
EXAMPLES::
|
|
2510
|
+
|
|
2511
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, 3)
|
|
2512
|
+
sage: for la in Partitions(3):
|
|
2513
|
+
....: print(la, SGA._row_stabilizer(la))
|
|
2514
|
+
[3] [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
|
|
2515
|
+
[2, 1] [1, 2, 3] + [2, 1, 3]
|
|
2516
|
+
[1, 1, 1] [1, 2, 3]
|
|
2517
|
+
"""
|
|
2518
|
+
G = self.group()
|
|
2519
|
+
return self.sum_of_monomials(G(list(w.tuple())) for w in la.young_subgroup())
|
|
2520
|
+
|
|
2521
|
+
@cached_method
|
|
2522
|
+
def _column_antistabilizer(self, la):
|
|
2523
|
+
"""
|
|
2524
|
+
Return the column antistabilizer element of a canonical standard tableau
|
|
2525
|
+
of shape ``la``.
|
|
2526
|
+
|
|
2527
|
+
EXAMPLES::
|
|
2528
|
+
|
|
2529
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, 3)
|
|
2530
|
+
sage: for la in Partitions(3):
|
|
2531
|
+
....: print(la, SGA._column_antistabilizer(la))
|
|
2532
|
+
[3] [1, 2, 3]
|
|
2533
|
+
[2, 1] [1, 2, 3] - [3, 2, 1]
|
|
2534
|
+
[1, 1, 1] [1, 2, 3] - [1, 3, 2] - [2, 1, 3] + [2, 3, 1] + [3, 1, 2] - [3, 2, 1]
|
|
2535
|
+
"""
|
|
2536
|
+
T = []
|
|
2537
|
+
total = 1 # make it 1-based
|
|
2538
|
+
for r in la:
|
|
2539
|
+
T.append(list(range(total, total+r)))
|
|
2540
|
+
total += r
|
|
2541
|
+
T = Tableau(T)
|
|
2542
|
+
G = self.group()
|
|
2543
|
+
R = self.base_ring()
|
|
2544
|
+
return self._from_dict({G(list(w.tuple())): R(w.sign()) for w in T.column_stabilizer()},
|
|
2545
|
+
remove_zeros=False)
|
|
2546
|
+
|
|
2547
|
+
@cached_method
|
|
2548
|
+
def _young_symmetrizer(self, la):
|
|
2549
|
+
"""
|
|
2550
|
+
Return the Young symmetrizer of shape ``la`` of ``self``.
|
|
2551
|
+
|
|
2552
|
+
EXAMPLES::
|
|
2553
|
+
|
|
2554
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, 3)
|
|
2555
|
+
sage: for la in Partitions(3):
|
|
2556
|
+
....: print(la, SGA._young_symmetrizer(la))
|
|
2557
|
+
[3] [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
|
|
2558
|
+
[2, 1] [1, 2, 3] + [2, 1, 3] - [3, 1, 2] - [3, 2, 1]
|
|
2559
|
+
[1, 1, 1] [1, 2, 3] - [1, 3, 2] - [2, 1, 3] + [2, 3, 1] + [3, 1, 2] - [3, 2, 1]
|
|
2560
|
+
"""
|
|
2561
|
+
return self._column_antistabilizer(la) * self._row_stabilizer(la)
|
|
2562
|
+
|
|
2563
|
+
def young_symmetrizer(self, la):
|
|
2564
|
+
"""
|
|
2565
|
+
Return the Young symmetrizer of shape ``la`` of ``self``.
|
|
2566
|
+
|
|
2567
|
+
EXAMPLES::
|
|
2568
|
+
|
|
2569
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, SymmetricGroup(3))
|
|
2570
|
+
sage: SGA.young_symmetrizer([2,1])
|
|
2571
|
+
() + (1,2) - (1,3,2) - (1,3)
|
|
2572
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, 4)
|
|
2573
|
+
sage: SGA.young_symmetrizer([2,1,1])
|
|
2574
|
+
[1, 2, 3, 4] - [1, 2, 4, 3] + [2, 1, 3, 4] - [2, 1, 4, 3]
|
|
2575
|
+
- [3, 1, 2, 4] + [3, 1, 4, 2] - [3, 2, 1, 4] + [3, 2, 4, 1]
|
|
2576
|
+
+ [4, 1, 2, 3] - [4, 1, 3, 2] + [4, 2, 1, 3] - [4, 2, 3, 1]
|
|
2577
|
+
sage: SGA.young_symmetrizer([5,1,1])
|
|
2578
|
+
Traceback (most recent call last):
|
|
2579
|
+
...
|
|
2580
|
+
ValueError: the partition [5, 1, 1] is not of size 4
|
|
2581
|
+
"""
|
|
2582
|
+
la = _Partitions(la)
|
|
2583
|
+
if la.size() != self.n:
|
|
2584
|
+
raise ValueError("the partition {} is not of size {}".format(la, self.n))
|
|
2585
|
+
return self._young_symmetrizer(la)
|
|
2586
|
+
|
|
2587
|
+
def kazhdan_lusztig_cellular_basis(self):
|
|
2588
|
+
r"""
|
|
2589
|
+
Return the Kazhdan-Lusztig basis (at `q = 1`) of ``self``
|
|
2590
|
+
as a cellular basis.
|
|
2591
|
+
|
|
2592
|
+
EXAMPLES::
|
|
2593
|
+
|
|
2594
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, 3)
|
|
2595
|
+
sage: KL = SGA.kazhdan_lusztig_cellular_basis()
|
|
2596
|
+
sage: KL(SGA.an_element())
|
|
2597
|
+
C([2, 1], [[1, 2], [3]], [[1, 2], [3]])
|
|
2598
|
+
+ C([2, 1], [[1, 3], [2]], [[1, 2], [3]])
|
|
2599
|
+
+ 2*C([2, 1], [[1, 3], [2]], [[1, 3], [2]])
|
|
2600
|
+
- 3*C([3], [[1, 2, 3]], [[1, 2, 3]])
|
|
2601
|
+
"""
|
|
2602
|
+
return KLCellularBasis(self)
|
|
2603
|
+
|
|
2604
|
+
@cached_method
|
|
2605
|
+
def kazhdan_lusztig_basis_element(self, w):
|
|
2606
|
+
r"""
|
|
2607
|
+
Return the Kazhdan-Lusztig `C'_w` basis element at `q = 1`.
|
|
2608
|
+
|
|
2609
|
+
EXAMPLES::
|
|
2610
|
+
|
|
2611
|
+
sage: SGA = SymmetricGroupAlgebra(QQ, 3)
|
|
2612
|
+
sage: for w in SGA.group():
|
|
2613
|
+
....: print(w, SGA.kazhdan_lusztig_basis_element(w))
|
|
2614
|
+
[1, 2, 3] [1, 2, 3]
|
|
2615
|
+
[1, 3, 2] [1, 2, 3] + [1, 3, 2]
|
|
2616
|
+
[2, 1, 3] [1, 2, 3] + [2, 1, 3]
|
|
2617
|
+
[2, 3, 1] [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1]
|
|
2618
|
+
[3, 1, 2] [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [3, 1, 2]
|
|
2619
|
+
[3, 2, 1] [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
|
|
2620
|
+
"""
|
|
2621
|
+
from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet
|
|
2622
|
+
G = self.basis().keys()
|
|
2623
|
+
R = self.base_ring()
|
|
2624
|
+
one = R.one()
|
|
2625
|
+
# check if the KL polynomials can be computed using ``coxeter3``
|
|
2626
|
+
try:
|
|
2627
|
+
from sage.libs.coxeter3.coxeter_group import CoxeterGroup as Coxeter3Group
|
|
2628
|
+
except ImportError:
|
|
2629
|
+
# Fallback to using the KL polynomial
|
|
2630
|
+
from sage.combinat.kazhdan_lusztig import KazhdanLusztigPolynomial
|
|
2631
|
+
from sage.groups.perm_gps.permgroup_named import SymmetricGroup
|
|
2632
|
+
q = PolynomialRing(R, 'q').gen()
|
|
2633
|
+
self._KLG = SymmetricGroup(self.n)
|
|
2634
|
+
self._cellular_KL = KazhdanLusztigPolynomial(self._KLG, q)
|
|
2635
|
+
polyfunc = self._cellular_KL.P
|
|
2636
|
+
else:
|
|
2637
|
+
self._cellular_KL = Coxeter3Group(['A', self.n+1])
|
|
2638
|
+
self._KLG = self._cellular_KL
|
|
2639
|
+
polyfunc = self._cellular_KL.kazhdan_lusztig_polynomial
|
|
2640
|
+
|
|
2641
|
+
if w.parent() is not self._KLG:
|
|
2642
|
+
w = self._KLG.from_reduced_word(w.reduced_word())
|
|
2643
|
+
bruhat = RecursivelyEnumeratedSet([w], lambda u: u.bruhat_lower_covers(), structure='graded')
|
|
2644
|
+
return self.element_class(self, {G.from_reduced_word(v.reduced_word()): R(c(q=one))
|
|
2645
|
+
for v in bruhat if (c := polyfunc(v, w))})
|
|
2646
|
+
|
|
2647
|
+
|
|
2648
|
+
epsilon_ik_cache = {}
|
|
2649
|
+
|
|
2650
|
+
|
|
2651
|
+
def epsilon_ik(itab, ktab, star=0):
|
|
2652
|
+
r"""
|
|
2653
|
+
Return the seminormal basis element of the symmetric group
|
|
2654
|
+
algebra `\QQ S_n` corresponding to the pair of tableaux
|
|
2655
|
+
``itab`` and ``ktab`` (or restrictions of these tableaux,
|
|
2656
|
+
if the optional variable ``star`` is set).
|
|
2657
|
+
|
|
2658
|
+
INPUT:
|
|
2659
|
+
|
|
2660
|
+
- ``itab``, ``ktab`` -- two standard tableaux of same size
|
|
2661
|
+
|
|
2662
|
+
- ``star`` -- integer (default: `0`)
|
|
2663
|
+
|
|
2664
|
+
OUTPUT:
|
|
2665
|
+
|
|
2666
|
+
The element `\epsilon(I, K) \in \QQ S_n`, where `I` and `K`
|
|
2667
|
+
are the tableaux obtained by removing all entries higher
|
|
2668
|
+
than `n - \mathrm{star}` from ``itab`` and ``ktab``,
|
|
2669
|
+
respectively (where `n` is the size of ``itab`` and
|
|
2670
|
+
``ktab``). Here, we are using the notations from
|
|
2671
|
+
:meth:`~sage.combinat.symmetric_group_algebra.SymmetricGroupAlgebra_n.seminormal_basis`.
|
|
2672
|
+
|
|
2673
|
+
EXAMPLES::
|
|
2674
|
+
|
|
2675
|
+
sage: from sage.combinat.symmetric_group_algebra import epsilon_ik
|
|
2676
|
+
sage: epsilon_ik([[1,2],[3]], [[1,3],[2]])
|
|
2677
|
+
1/4*[1, 3, 2] - 1/4*[2, 3, 1] + 1/4*[3, 1, 2] - 1/4*[3, 2, 1]
|
|
2678
|
+
sage: epsilon_ik([[1,2],[3]], [[1,3],[2]], star=1)
|
|
2679
|
+
Traceback (most recent call last):
|
|
2680
|
+
...
|
|
2681
|
+
ValueError: the two tableaux must be of the same shape
|
|
2682
|
+
"""
|
|
2683
|
+
it = Tableau(itab)
|
|
2684
|
+
kt = Tableau(ktab)
|
|
2685
|
+
if star:
|
|
2686
|
+
it = it.restrict(it.size() - star)
|
|
2687
|
+
kt = kt.restrict(kt.size() - star)
|
|
2688
|
+
|
|
2689
|
+
if it.shape() != kt.shape():
|
|
2690
|
+
raise ValueError("the two tableaux must be of the same shape")
|
|
2691
|
+
|
|
2692
|
+
if kt == it:
|
|
2693
|
+
res = epsilon(itab)
|
|
2694
|
+
elif (it, kt) in epsilon_ik_cache:
|
|
2695
|
+
res = epsilon_ik_cache[(it, kt)]
|
|
2696
|
+
else:
|
|
2697
|
+
eik = e_ik(it, kt, star)
|
|
2698
|
+
QSn = eik.parent()
|
|
2699
|
+
mul = QSn.right_action_product
|
|
2700
|
+
epsilon_ik_cache[(it, kt)] = mul(mul(epsilon(it, star + 1), eik),
|
|
2701
|
+
epsilon(kt, star + 1)) * (1 / kappa(it.shape()))
|
|
2702
|
+
res = epsilon_ik_cache[(it, kt)]
|
|
2703
|
+
|
|
2704
|
+
return res
|
|
2705
|
+
|
|
2706
|
+
|
|
2707
|
+
epsilon_cache = {}
|
|
2708
|
+
|
|
2709
|
+
|
|
2710
|
+
def epsilon(tab, star=0):
|
|
2711
|
+
r"""
|
|
2712
|
+
The `(T, T)`-th element of the seminormal basis of the group
|
|
2713
|
+
algebra `\QQ[S_n]`, where `T` is the tableau ``tab`` (with its
|
|
2714
|
+
``star`` highest entries removed if the optional variable
|
|
2715
|
+
``star`` is set).
|
|
2716
|
+
|
|
2717
|
+
See the docstring of
|
|
2718
|
+
:meth:`~sage.combinat.symmetric_group_algebra.SymmetricGroupAlgebra_n.seminormal_basis`
|
|
2719
|
+
for the notation used herein.
|
|
2720
|
+
|
|
2721
|
+
EXAMPLES::
|
|
2722
|
+
|
|
2723
|
+
sage: from sage.combinat.symmetric_group_algebra import epsilon
|
|
2724
|
+
sage: epsilon([[1,2]])
|
|
2725
|
+
1/2*[1, 2] + 1/2*[2, 1]
|
|
2726
|
+
sage: epsilon([[1],[2]])
|
|
2727
|
+
1/2*[1, 2] - 1/2*[2, 1]
|
|
2728
|
+
"""
|
|
2729
|
+
t = Tableau(tab)
|
|
2730
|
+
|
|
2731
|
+
if star:
|
|
2732
|
+
t = t.restrict(t.size() - star)
|
|
2733
|
+
|
|
2734
|
+
if t in epsilon_cache:
|
|
2735
|
+
res = epsilon_cache[t]
|
|
2736
|
+
else:
|
|
2737
|
+
if t.size() == 2:
|
|
2738
|
+
epsilon_cache[t] = e(t) * (1 / kappa(t.shape()))
|
|
2739
|
+
res = epsilon_cache[t]
|
|
2740
|
+
elif t == Tableau([[1]]):
|
|
2741
|
+
epsilon_cache[t] = e(t)
|
|
2742
|
+
res = epsilon_cache[t]
|
|
2743
|
+
else:
|
|
2744
|
+
et = e(t)
|
|
2745
|
+
QSn = et.parent()
|
|
2746
|
+
mul = QSn.right_action_product
|
|
2747
|
+
epsilon_cache[t] = mul(mul(epsilon(t, 1), e(t)),
|
|
2748
|
+
epsilon(t, 1)) * (1 / kappa(t.shape()))
|
|
2749
|
+
res = epsilon_cache[t]
|
|
2750
|
+
|
|
2751
|
+
return res
|
|
2752
|
+
|
|
2753
|
+
|
|
2754
|
+
def pi_ik(itab, ktab):
|
|
2755
|
+
r"""
|
|
2756
|
+
Return the permutation `p` which sends every entry of the
|
|
2757
|
+
tableau ``itab`` to the respective entry of the tableau
|
|
2758
|
+
``ktab``, as an element of the corresponding symmetric group
|
|
2759
|
+
algebra.
|
|
2760
|
+
|
|
2761
|
+
This assumes that ``itab`` and ``ktab`` are tableaux (possibly
|
|
2762
|
+
given just as lists of lists) of the same shape. Both
|
|
2763
|
+
tableaux are allowed to be skew.
|
|
2764
|
+
|
|
2765
|
+
EXAMPLES::
|
|
2766
|
+
|
|
2767
|
+
sage: from sage.combinat.symmetric_group_algebra import pi_ik
|
|
2768
|
+
sage: pi_ik([[1,3],[2]], [[1,2],[3]])
|
|
2769
|
+
[1, 3, 2]
|
|
2770
|
+
|
|
2771
|
+
The same with skew tableaux::
|
|
2772
|
+
|
|
2773
|
+
sage: from sage.combinat.symmetric_group_algebra import pi_ik
|
|
2774
|
+
sage: pi_ik([[None,1,3],[2]], [[None,1,2],[3]])
|
|
2775
|
+
[1, 3, 2]
|
|
2776
|
+
"""
|
|
2777
|
+
it = SkewTableau(itab)
|
|
2778
|
+
kt = SkewTableau(ktab)
|
|
2779
|
+
n = kt.size()
|
|
2780
|
+
|
|
2781
|
+
p = [None] * n
|
|
2782
|
+
for i in range(len(kt)):
|
|
2783
|
+
for j in range(len(kt[i])):
|
|
2784
|
+
if it[i][j] is not None:
|
|
2785
|
+
p[it[i][j] - 1] = kt[i][j]
|
|
2786
|
+
|
|
2787
|
+
QSn = SymmetricGroupAlgebra(QQ, n)
|
|
2788
|
+
p = Permutation(p)
|
|
2789
|
+
return QSn(p)
|
|
2790
|
+
|
|
2791
|
+
|
|
2792
|
+
def kappa(alpha):
|
|
2793
|
+
r"""
|
|
2794
|
+
Return `\kappa_\alpha`, which is `n!` divided by the number
|
|
2795
|
+
of standard tableaux of shape `\alpha` (where `\alpha` is a
|
|
2796
|
+
partition of `n`).
|
|
2797
|
+
|
|
2798
|
+
INPUT:
|
|
2799
|
+
|
|
2800
|
+
- ``alpha`` -- integer partition (can be encoded as a list)
|
|
2801
|
+
|
|
2802
|
+
OUTPUT:
|
|
2803
|
+
|
|
2804
|
+
The factorial of the size of ``alpha``, divided by the number of
|
|
2805
|
+
standard tableaux of shape ``alpha``. Equivalently, the product
|
|
2806
|
+
of all hook lengths of ``alpha``.
|
|
2807
|
+
|
|
2808
|
+
EXAMPLES::
|
|
2809
|
+
|
|
2810
|
+
sage: from sage.combinat.symmetric_group_algebra import kappa
|
|
2811
|
+
sage: kappa(Partition([2,1]))
|
|
2812
|
+
3
|
|
2813
|
+
sage: kappa([2,1])
|
|
2814
|
+
3
|
|
2815
|
+
"""
|
|
2816
|
+
try:
|
|
2817
|
+
n = alpha.size()
|
|
2818
|
+
except AttributeError:
|
|
2819
|
+
n = sum(alpha)
|
|
2820
|
+
return factorial(n) / StandardTableaux(alpha).cardinality()
|
|
2821
|
+
|
|
2822
|
+
|
|
2823
|
+
def a(tableau, star=0, base_ring=QQ):
|
|
2824
|
+
r"""
|
|
2825
|
+
The row projection operator corresponding to the Young tableau
|
|
2826
|
+
``tableau`` (which is supposed to contain every integer from
|
|
2827
|
+
`1` to its size precisely once, but may and may not be standard).
|
|
2828
|
+
|
|
2829
|
+
This is the sum (in the group algebra of the relevant symmetric
|
|
2830
|
+
group over `\QQ`) of all the permutations which preserve
|
|
2831
|
+
the rows of ``tableau``. It is called `a_{\text{tableau}}` in
|
|
2832
|
+
[EGHLSVY]_, Section 4.2.
|
|
2833
|
+
|
|
2834
|
+
INPUT:
|
|
2835
|
+
|
|
2836
|
+
- ``tableau`` -- Young tableau which contains every integer
|
|
2837
|
+
from `1` to its size precisely once
|
|
2838
|
+
|
|
2839
|
+
- ``star`` -- nonnegative integer (default: `0`); when this
|
|
2840
|
+
optional variable is set, the method computes not the row
|
|
2841
|
+
projection operator of ``tableau``, but the row projection
|
|
2842
|
+
operator of the restriction of ``tableau`` to the entries
|
|
2843
|
+
``1, 2, ..., tableau.size() - star`` instead.
|
|
2844
|
+
|
|
2845
|
+
- ``base_ring`` -- commutative ring (default: ``QQ``); when this
|
|
2846
|
+
optional variable is set, the row projection operator is
|
|
2847
|
+
computed over a user-determined base ring instead of `\QQ`.
|
|
2848
|
+
(Note that symmetric group algebras currently don't preserve
|
|
2849
|
+
coercion, so e. g. a symmetric group algebra over `\ZZ`
|
|
2850
|
+
does not coerce into the corresponding one over `\QQ`; so
|
|
2851
|
+
convert manually or choose your base rings wisely!)
|
|
2852
|
+
|
|
2853
|
+
EXAMPLES::
|
|
2854
|
+
|
|
2855
|
+
sage: from sage.combinat.symmetric_group_algebra import a
|
|
2856
|
+
sage: a([[1,2]])
|
|
2857
|
+
[1, 2] + [2, 1]
|
|
2858
|
+
sage: a([[1],[2]])
|
|
2859
|
+
[1, 2]
|
|
2860
|
+
sage: a([])
|
|
2861
|
+
[]
|
|
2862
|
+
sage: a([[1, 5], [2, 3], [4]])
|
|
2863
|
+
[1, 2, 3, 4, 5] + [1, 3, 2, 4, 5] + [5, 2, 3, 4, 1] + [5, 3, 2, 4, 1]
|
|
2864
|
+
sage: a([[1,4], [2,3]], base_ring=ZZ)
|
|
2865
|
+
[1, 2, 3, 4] + [1, 3, 2, 4] + [4, 2, 3, 1] + [4, 3, 2, 1]
|
|
2866
|
+
|
|
2867
|
+
The same with a skew tableau::
|
|
2868
|
+
|
|
2869
|
+
sage: a([[None,1,4], [2,3]], base_ring=ZZ)
|
|
2870
|
+
[1, 2, 3, 4] + [1, 3, 2, 4] + [4, 2, 3, 1] + [4, 3, 2, 1]
|
|
2871
|
+
"""
|
|
2872
|
+
t = SkewTableau(tableau)
|
|
2873
|
+
if star:
|
|
2874
|
+
t = t.restrict(t.size() - star)
|
|
2875
|
+
|
|
2876
|
+
rs = t.row_stabilizer().list()
|
|
2877
|
+
n = t.size()
|
|
2878
|
+
|
|
2879
|
+
sgalg = SymmetricGroupAlgebra(base_ring, n)
|
|
2880
|
+
one = base_ring.one()
|
|
2881
|
+
P = Permutation
|
|
2882
|
+
|
|
2883
|
+
# Ugly hack for the case of an empty tableau, due to the
|
|
2884
|
+
# annoyance of Permutation(Tableau([]).row_stabilizer()[0])
|
|
2885
|
+
# being [1] rather than [] (which seems to have its origins in
|
|
2886
|
+
# permutation group code).
|
|
2887
|
+
# TODO: Fix this.
|
|
2888
|
+
if n <= 1:
|
|
2889
|
+
return sgalg.one()
|
|
2890
|
+
|
|
2891
|
+
rd = {P(h): one for h in rs}
|
|
2892
|
+
return sgalg._from_dict(rd)
|
|
2893
|
+
|
|
2894
|
+
|
|
2895
|
+
def b(tableau, star=0, base_ring=QQ):
|
|
2896
|
+
r"""
|
|
2897
|
+
The column projection operator corresponding to the Young tableau
|
|
2898
|
+
``tableau`` (which is supposed to contain every integer from
|
|
2899
|
+
`1` to its size precisely once, but may and may not be standard).
|
|
2900
|
+
|
|
2901
|
+
This is the signed sum (in the group algebra of the relevant
|
|
2902
|
+
symmetric group over `\QQ`) of all the permutations which
|
|
2903
|
+
preserve the column of ``tableau`` (where the signs are the usual
|
|
2904
|
+
signs of the permutations). It is called `b_{\text{tableau}}` in
|
|
2905
|
+
[EGHLSVY]_, Section 4.2.
|
|
2906
|
+
|
|
2907
|
+
INPUT:
|
|
2908
|
+
|
|
2909
|
+
- ``tableau`` -- Young tableau which contains every integer
|
|
2910
|
+
from `1` to its size precisely once
|
|
2911
|
+
|
|
2912
|
+
- ``star`` -- nonnegative integer (default: `0`). When this
|
|
2913
|
+
optional variable is set, the method computes not the column
|
|
2914
|
+
projection operator of ``tableau``, but the column projection
|
|
2915
|
+
operator of the restriction of ``tableau`` to the entries
|
|
2916
|
+
``1, 2, ..., tableau.size() - star`` instead.
|
|
2917
|
+
|
|
2918
|
+
- ``base_ring`` -- commutative ring (default: ``QQ``). When this
|
|
2919
|
+
optional variable is set, the column projection operator is
|
|
2920
|
+
computed over a user-determined base ring instead of `\QQ`.
|
|
2921
|
+
(Note that symmetric group algebras currently don't preserve
|
|
2922
|
+
coercion, so e. g. a symmetric group algebra over `\ZZ`
|
|
2923
|
+
does not coerce into the corresponding one over `\QQ`; so
|
|
2924
|
+
convert manually or choose your base rings wisely!)
|
|
2925
|
+
|
|
2926
|
+
EXAMPLES::
|
|
2927
|
+
|
|
2928
|
+
sage: from sage.combinat.symmetric_group_algebra import b
|
|
2929
|
+
sage: b([[1,2]])
|
|
2930
|
+
[1, 2]
|
|
2931
|
+
sage: b([[1],[2]])
|
|
2932
|
+
[1, 2] - [2, 1]
|
|
2933
|
+
sage: b([])
|
|
2934
|
+
[]
|
|
2935
|
+
sage: b([[1, 2, 4], [5, 3]])
|
|
2936
|
+
[1, 2, 3, 4, 5] - [1, 3, 2, 4, 5] - [5, 2, 3, 4, 1] + [5, 3, 2, 4, 1]
|
|
2937
|
+
sage: b([[1, 4], [2, 3]], base_ring=ZZ)
|
|
2938
|
+
[1, 2, 3, 4] - [1, 2, 4, 3] - [2, 1, 3, 4] + [2, 1, 4, 3]
|
|
2939
|
+
sage: b([[1, 4], [2, 3]], base_ring=Integers(5))
|
|
2940
|
+
[1, 2, 3, 4] + 4*[1, 2, 4, 3] + 4*[2, 1, 3, 4] + [2, 1, 4, 3]
|
|
2941
|
+
|
|
2942
|
+
The same with a skew tableau::
|
|
2943
|
+
|
|
2944
|
+
sage: b([[None, 2, 4], [1, 3], [5]])
|
|
2945
|
+
[1, 2, 3, 4, 5] - [1, 3, 2, 4, 5] - [5, 2, 3, 4, 1] + [5, 3, 2, 4, 1]
|
|
2946
|
+
|
|
2947
|
+
With the ``l2r`` setting for multiplication, the unnormalized
|
|
2948
|
+
Young symmetrizer ``e(tableau)`` should be the product
|
|
2949
|
+
``b(tableau) * a(tableau)`` for every ``tableau``. Let us check
|
|
2950
|
+
this on the standard tableaux of size 5::
|
|
2951
|
+
|
|
2952
|
+
sage: from sage.combinat.symmetric_group_algebra import a, b, e
|
|
2953
|
+
sage: all( e(t) == b(t) * a(t) for t in StandardTableaux(5) )
|
|
2954
|
+
True
|
|
2955
|
+
"""
|
|
2956
|
+
t = SkewTableau(tableau)
|
|
2957
|
+
if star:
|
|
2958
|
+
t = t.restrict(t.size() - star)
|
|
2959
|
+
|
|
2960
|
+
cs = t.column_stabilizer().list()
|
|
2961
|
+
n = t.size()
|
|
2962
|
+
|
|
2963
|
+
sgalg = SymmetricGroupAlgebra(base_ring, n)
|
|
2964
|
+
one = base_ring.one()
|
|
2965
|
+
P = Permutation
|
|
2966
|
+
|
|
2967
|
+
# Ugly hack for the case of an empty tableau, due to the
|
|
2968
|
+
# annoyance of Permutation(Tableau([]).row_stabilizer()[0])
|
|
2969
|
+
# being [1] rather than [] (which seems to have its origins in
|
|
2970
|
+
# permutation group code).
|
|
2971
|
+
# TODO: Fix this.
|
|
2972
|
+
if n <= 1:
|
|
2973
|
+
return sgalg.one()
|
|
2974
|
+
|
|
2975
|
+
cd = {P(v): v.sign() * one for v in cs}
|
|
2976
|
+
return sgalg._from_dict(cd)
|
|
2977
|
+
|
|
2978
|
+
|
|
2979
|
+
e_cache = {}
|
|
2980
|
+
|
|
2981
|
+
|
|
2982
|
+
def e(tableau, star=0):
|
|
2983
|
+
r"""
|
|
2984
|
+
The unnormalized Young projection operator corresponding to
|
|
2985
|
+
the Young tableau ``tableau`` (which is supposed to contain
|
|
2986
|
+
every integer from `1` to its size precisely once, but may
|
|
2987
|
+
and may not be standard).
|
|
2988
|
+
|
|
2989
|
+
If `n` is a nonnegative integer, and `T` is a Young tableau
|
|
2990
|
+
containing every integer from `1` to `n` exactly once, then
|
|
2991
|
+
the unnormalized Young projection operator `e(T)` is defined by
|
|
2992
|
+
|
|
2993
|
+
.. MATH::
|
|
2994
|
+
|
|
2995
|
+
e(T) = a(T) b(T) \in \QQ S_n,
|
|
2996
|
+
|
|
2997
|
+
where `a(T) \in \QQ S_n` is the sum of all permutations in `S_n`
|
|
2998
|
+
which fix the rows of `T` (as sets), and `b(T) \in \QQ S_n` is the
|
|
2999
|
+
signed sum of all permutations in `S_n` which fix the columns of
|
|
3000
|
+
`T` (as sets). Here, "signed" means that each permutation is
|
|
3001
|
+
multiplied with its sign; and the product on the group `S_n` is
|
|
3002
|
+
defined in such a way that `(pq)(i) = p(q(i))` for any
|
|
3003
|
+
permutations `p` and `q` and any `1 \leq i \leq n`.
|
|
3004
|
+
|
|
3005
|
+
Note that the definition of `e(T)` is not uniform across
|
|
3006
|
+
literature. Others define it as `b(T) a(T)` instead, or include
|
|
3007
|
+
certain scalar factors (we do not, whence "unnormalized").
|
|
3008
|
+
|
|
3009
|
+
EXAMPLES::
|
|
3010
|
+
|
|
3011
|
+
sage: from sage.combinat.symmetric_group_algebra import e
|
|
3012
|
+
sage: e([[1,2]])
|
|
3013
|
+
[1, 2] + [2, 1]
|
|
3014
|
+
sage: e([[1],[2]])
|
|
3015
|
+
[1, 2] - [2, 1]
|
|
3016
|
+
sage: e([])
|
|
3017
|
+
[]
|
|
3018
|
+
|
|
3019
|
+
There are differing conventions for the order of the symmetrizers
|
|
3020
|
+
and antisymmetrizers. This example illustrates our conventions::
|
|
3021
|
+
|
|
3022
|
+
sage: e([[1,2],[3]])
|
|
3023
|
+
[1, 2, 3] + [2, 1, 3] - [3, 1, 2] - [3, 2, 1]
|
|
3024
|
+
|
|
3025
|
+
To obtain the product `b(T) a(T)`, one has to take the antipode
|
|
3026
|
+
of this::
|
|
3027
|
+
|
|
3028
|
+
sage: QS3 = parent(e([[1,2],[3]]))
|
|
3029
|
+
sage: QS3.antipode(e([[1,2],[3]]))
|
|
3030
|
+
[1, 2, 3] + [2, 1, 3] - [2, 3, 1] - [3, 2, 1]
|
|
3031
|
+
|
|
3032
|
+
And here is an example for a skew tableau::
|
|
3033
|
+
|
|
3034
|
+
sage: e([[None, 2, 1], [4, 3]])
|
|
3035
|
+
[1, 2, 3, 4] + [1, 2, 4, 3] - [1, 3, 2, 4] - [1, 4, 2, 3]
|
|
3036
|
+
+ [2, 1, 3, 4] + [2, 1, 4, 3] - [2, 3, 1, 4] - [2, 4, 1, 3]
|
|
3037
|
+
|
|
3038
|
+
.. SEEALSO::
|
|
3039
|
+
|
|
3040
|
+
:func:`e_hat`
|
|
3041
|
+
"""
|
|
3042
|
+
# TODO:
|
|
3043
|
+
# The current method only computes the e's over QQ. There should be
|
|
3044
|
+
# a way to compute them over other base rings as well. Be careful
|
|
3045
|
+
# with the cache.
|
|
3046
|
+
|
|
3047
|
+
t = SkewTableau(tableau)
|
|
3048
|
+
if star:
|
|
3049
|
+
t = t.restrict(t.size() - star)
|
|
3050
|
+
|
|
3051
|
+
if t in e_cache:
|
|
3052
|
+
res = e_cache[t]
|
|
3053
|
+
else:
|
|
3054
|
+
rs = t.row_stabilizer().list()
|
|
3055
|
+
cs = t.column_stabilizer().list()
|
|
3056
|
+
n = t.size()
|
|
3057
|
+
|
|
3058
|
+
QSn = SymmetricGroupAlgebra(QQ, n)
|
|
3059
|
+
one = QQ.one()
|
|
3060
|
+
P = Permutation
|
|
3061
|
+
|
|
3062
|
+
rd = {P(h): one for h in rs}
|
|
3063
|
+
sym = QSn._from_dict(rd)
|
|
3064
|
+
|
|
3065
|
+
cd = {P(v): QQ(v.sign()) for v in cs}
|
|
3066
|
+
antisym = QSn._from_dict(cd)
|
|
3067
|
+
|
|
3068
|
+
res = QSn.right_action_product(antisym, sym)
|
|
3069
|
+
|
|
3070
|
+
# Ugly hack for the case of an empty tableau, due to the
|
|
3071
|
+
# annoyance of Permutation(Tableau([]).row_stabilizer()[0])
|
|
3072
|
+
# being [1] rather than [] (which seems to have its origins in
|
|
3073
|
+
# permutation group code).
|
|
3074
|
+
# TODO: Fix this.
|
|
3075
|
+
if n <= 1:
|
|
3076
|
+
return QSn.one()
|
|
3077
|
+
|
|
3078
|
+
e_cache[t] = res
|
|
3079
|
+
|
|
3080
|
+
return res
|
|
3081
|
+
|
|
3082
|
+
|
|
3083
|
+
ehat_cache = {}
|
|
3084
|
+
|
|
3085
|
+
|
|
3086
|
+
def e_hat(tab, star=0):
|
|
3087
|
+
r"""
|
|
3088
|
+
The Young projection operator corresponding to the Young tableau
|
|
3089
|
+
``tab`` (which is supposed to contain every integer from `1` to
|
|
3090
|
+
its size precisely once, but may and may not be standard). This
|
|
3091
|
+
is an idempotent in the rational group algebra.
|
|
3092
|
+
|
|
3093
|
+
If `n` is a nonnegative integer, and `T` is a Young tableau
|
|
3094
|
+
containing every integer from `1` to `n` exactly once, then
|
|
3095
|
+
the Young projection operator `\widehat{e}(T)` is defined by
|
|
3096
|
+
|
|
3097
|
+
.. MATH::
|
|
3098
|
+
|
|
3099
|
+
\widehat{e}(T) = \frac{1}{\kappa_\lambda} a(T) b(T) \in \QQ S_n,
|
|
3100
|
+
|
|
3101
|
+
where `\lambda` is the shape of `T`, where `\kappa_\lambda` is
|
|
3102
|
+
`n!` divided by the number of standard tableaux of shape
|
|
3103
|
+
`\lambda`, where `a(T) \in \QQ S_n` is the sum of all
|
|
3104
|
+
permutations in `S_n` which fix the rows of `T` (as sets), and
|
|
3105
|
+
where `b(T) \in \QQ S_n` is the signed sum of all permutations
|
|
3106
|
+
in `S_n` which fix the columns of `T` (as sets). Here, "signed"
|
|
3107
|
+
means that each permutation is multiplied with its sign; and
|
|
3108
|
+
the product on the group `S_n` is defined in such a way that
|
|
3109
|
+
`(pq)(i) = p(q(i))` for any permutations `p` and `q` and any
|
|
3110
|
+
`1 \leq i \leq n`.
|
|
3111
|
+
|
|
3112
|
+
Note that the definition of `\widehat{e}(T)` is not uniform
|
|
3113
|
+
across literature. Others define it as
|
|
3114
|
+
`\frac{1}{\kappa_\lambda} b(T) a(T)` instead.
|
|
3115
|
+
|
|
3116
|
+
EXAMPLES::
|
|
3117
|
+
|
|
3118
|
+
sage: from sage.combinat.symmetric_group_algebra import e_hat
|
|
3119
|
+
sage: e_hat([[1,2,3]])
|
|
3120
|
+
1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] + 1/6*[3, 2, 1]
|
|
3121
|
+
sage: e_hat([[1],[2]])
|
|
3122
|
+
1/2*[1, 2] - 1/2*[2, 1]
|
|
3123
|
+
|
|
3124
|
+
There are differing conventions for the order of the symmetrizers
|
|
3125
|
+
and antisymmetrizers. This example illustrates our conventions::
|
|
3126
|
+
|
|
3127
|
+
sage: e_hat([[1,2],[3]])
|
|
3128
|
+
1/3*[1, 2, 3] + 1/3*[2, 1, 3] - 1/3*[3, 1, 2] - 1/3*[3, 2, 1]
|
|
3129
|
+
|
|
3130
|
+
.. SEEALSO::
|
|
3131
|
+
|
|
3132
|
+
:func:`e`
|
|
3133
|
+
"""
|
|
3134
|
+
t = SkewTableau(tab)
|
|
3135
|
+
# This is for consistency's sake. This method is NOT meant
|
|
3136
|
+
# to be applied to skew tableaux, since the meaning of
|
|
3137
|
+
# \kappa is unclear in that case.
|
|
3138
|
+
if star:
|
|
3139
|
+
t = t.restrict(t.size() - star)
|
|
3140
|
+
if t in ehat_cache:
|
|
3141
|
+
res = ehat_cache[t]
|
|
3142
|
+
else:
|
|
3143
|
+
res = (1 / kappa(t.shape())) * e(t)
|
|
3144
|
+
return res
|
|
3145
|
+
|
|
3146
|
+
|
|
3147
|
+
e_ik_cache = {}
|
|
3148
|
+
|
|
3149
|
+
|
|
3150
|
+
def e_ik(itab, ktab, star=0):
|
|
3151
|
+
"""
|
|
3152
|
+
EXAMPLES::
|
|
3153
|
+
|
|
3154
|
+
sage: from sage.combinat.symmetric_group_algebra import e_ik
|
|
3155
|
+
sage: e_ik([[1,2,3]], [[1,2,3]])
|
|
3156
|
+
[1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
|
|
3157
|
+
sage: e_ik([[1,2,3]], [[1,2,3]], star=1)
|
|
3158
|
+
[1, 2] + [2, 1]
|
|
3159
|
+
"""
|
|
3160
|
+
it = SkewTableau(itab)
|
|
3161
|
+
kt = SkewTableau(ktab)
|
|
3162
|
+
if star:
|
|
3163
|
+
it = it.restrict(it.size() - star)
|
|
3164
|
+
kt = kt.restrict(kt.size() - star)
|
|
3165
|
+
|
|
3166
|
+
if it.shape() != kt.shape():
|
|
3167
|
+
raise ValueError("the two tableaux must be of the same shape")
|
|
3168
|
+
|
|
3169
|
+
if kt == it:
|
|
3170
|
+
return e(it)
|
|
3171
|
+
if (it, kt) in e_ik_cache:
|
|
3172
|
+
return e_ik_cache[(it, kt)]
|
|
3173
|
+
|
|
3174
|
+
pi = pi_ik(it, kt)
|
|
3175
|
+
QSn = pi.parent()
|
|
3176
|
+
res = QSn.right_action_product(e(it), pi)
|
|
3177
|
+
e_ik_cache[(it, kt)] = res
|
|
3178
|
+
return res
|
|
3179
|
+
|
|
3180
|
+
|
|
3181
|
+
def seminormal_test(n):
|
|
3182
|
+
"""
|
|
3183
|
+
Run a variety of tests to verify that the construction of the
|
|
3184
|
+
seminormal basis works as desired. The numbers appearing are
|
|
3185
|
+
results in James and Kerber's 'Representation Theory of the
|
|
3186
|
+
Symmetric Group' [JK1981]_.
|
|
3187
|
+
|
|
3188
|
+
EXAMPLES::
|
|
3189
|
+
|
|
3190
|
+
sage: from sage.combinat.symmetric_group_algebra import seminormal_test
|
|
3191
|
+
sage: seminormal_test(3)
|
|
3192
|
+
True
|
|
3193
|
+
"""
|
|
3194
|
+
for part in Partitions_n(n):
|
|
3195
|
+
for tab in StandardTableaux(part):
|
|
3196
|
+
# Theorem 3.1.10
|
|
3197
|
+
if not e(tab) * (1 / kappa(part)) - e_hat(tab) == 0:
|
|
3198
|
+
raise ValueError("3.1.10 - %s" % tab)
|
|
3199
|
+
|
|
3200
|
+
# Lemma 3.2.12 (ii)
|
|
3201
|
+
value = e(tab) * epsilon(tab, 1) * e(tab) - e(tab) * kappa(part)
|
|
3202
|
+
if value != 0:
|
|
3203
|
+
print(value)
|
|
3204
|
+
raise ValueError("3.2.12.2 - %s" % tab)
|
|
3205
|
+
|
|
3206
|
+
for tab2 in StandardTableaux(part):
|
|
3207
|
+
# 3.2.8 (i)
|
|
3208
|
+
if e_ik(tab, tab2) - e(tab) * pi_ik(tab, tab2) * e(tab2) * (1 / kappa(part)) != 0:
|
|
3209
|
+
raise ValueError("3.2.8.1 - %s, %s" % (tab, tab2))
|
|
3210
|
+
|
|
3211
|
+
# 3.2.8 (ii)
|
|
3212
|
+
if e(tab) * e_ik(tab, tab2) - e_ik(tab, tab2) * kappa(part) != 0:
|
|
3213
|
+
raise ValueError("3.2.8.2 - %s, %s" % (tab, tab2))
|
|
3214
|
+
|
|
3215
|
+
if tab == tab2:
|
|
3216
|
+
continue
|
|
3217
|
+
|
|
3218
|
+
if tab.last_letter_lequal(tab2):
|
|
3219
|
+
# Lemma 3.1.20
|
|
3220
|
+
if e(tab2) * e(tab) != 0:
|
|
3221
|
+
raise ValueError("3.1.20 - %s, %s" % (tab, tab2))
|
|
3222
|
+
if e_hat(tab2) * e_hat(tab) != 0:
|
|
3223
|
+
raise ValueError("3.1.20 - %s, %s" % (tab, tab2))
|
|
3224
|
+
return True
|
|
3225
|
+
|
|
3226
|
+
|
|
3227
|
+
#######################
|
|
3228
|
+
|
|
3229
|
+
|
|
3230
|
+
class SGACellularBasis(CellularBasis):
|
|
3231
|
+
r"""
|
|
3232
|
+
A cellular basis of the symmetric group algebra.
|
|
3233
|
+
"""
|
|
3234
|
+
def __init__(self, SGA):
|
|
3235
|
+
r"""
|
|
3236
|
+
Initialize ``self``.
|
|
3237
|
+
|
|
3238
|
+
EXAMPLES::
|
|
3239
|
+
|
|
3240
|
+
sage: SGA = SymmetricGroupAlgebra(GF(3), 3)
|
|
3241
|
+
sage: M = SGA.murphy_basis()
|
|
3242
|
+
sage: TestSuite(M).run()
|
|
3243
|
+
sage: KL = SGA.kazhdan_lusztig_cellular_basis()
|
|
3244
|
+
sage: TestSuite(KL).run()
|
|
3245
|
+
"""
|
|
3246
|
+
CellularBasis.__init__(self, SGA, self._to_sga)
|
|
3247
|
+
|
|
3248
|
+
def _repr_(self):
|
|
3249
|
+
r"""
|
|
3250
|
+
Return a string representation of ``self``.
|
|
3251
|
+
|
|
3252
|
+
EXAMPLES::
|
|
3253
|
+
|
|
3254
|
+
sage: SGA = SymmetricGroupAlgebra(GF(3), 4)
|
|
3255
|
+
sage: SGA.murphy_basis()
|
|
3256
|
+
Murphy basis of Symmetric group algebra of order 4 over Finite Field of size 3
|
|
3257
|
+
sage: SGA.kazhdan_lusztig_cellular_basis()
|
|
3258
|
+
Kazhdan-Lusztig basis of Symmetric group algebra of order 4 over Finite Field of size 3
|
|
3259
|
+
"""
|
|
3260
|
+
return self._name + " basis of {}".format(self._algebra)
|
|
3261
|
+
|
|
3262
|
+
@cached_method
|
|
3263
|
+
def one_basis(self):
|
|
3264
|
+
r"""
|
|
3265
|
+
Return the index of the basis element for the multiplicative identity.
|
|
3266
|
+
|
|
3267
|
+
EXAMPLES::
|
|
3268
|
+
|
|
3269
|
+
sage: SGA = SymmetricGroupAlgebra(GF(3), 4)
|
|
3270
|
+
sage: M = SGA.murphy_basis()
|
|
3271
|
+
sage: M.one_basis()
|
|
3272
|
+
([4], [[1, 2, 3, 4]], [[1, 2, 3, 4]])
|
|
3273
|
+
"""
|
|
3274
|
+
la = _Partitions([self._algebra.n])
|
|
3275
|
+
col = la.standard_tableaux()[0]
|
|
3276
|
+
return (la, col, col)
|
|
3277
|
+
|
|
3278
|
+
@cached_method
|
|
3279
|
+
def one(self):
|
|
3280
|
+
r"""
|
|
3281
|
+
Return the element `1` in ``self``.
|
|
3282
|
+
|
|
3283
|
+
EXAMPLES::
|
|
3284
|
+
|
|
3285
|
+
sage: SGA = SymmetricGroupAlgebra(GF(3), 4)
|
|
3286
|
+
sage: M = SGA.murphy_basis()
|
|
3287
|
+
sage: M.one()
|
|
3288
|
+
C([4], [[1, 2, 3, 4]], [[1, 2, 3, 4]])
|
|
3289
|
+
"""
|
|
3290
|
+
return self.monomial(self.one_basis())
|
|
3291
|
+
|
|
3292
|
+
|
|
3293
|
+
class MurphyBasis(SGACellularBasis):
|
|
3294
|
+
r"""
|
|
3295
|
+
The Murphy basis of a symmetric group algebra.
|
|
3296
|
+
|
|
3297
|
+
Let `R` be a commutative ring, and let `A = R[S_n]` denote the group
|
|
3298
|
+
algebra (over `R`) of `S_n`. The *Murphy basis* is the basis of `A`
|
|
3299
|
+
defined as follows. Let `S, T` be standard tableaux of shape `\lambda`.
|
|
3300
|
+
Define `T^{\lambda}` as the standard tableau of shape `\lambda` with
|
|
3301
|
+
the first row filled with `1, \ldots, \lambda_1`, the second row
|
|
3302
|
+
`\lambda_1+1, \ldots, \lambda_1+\lambda_2`, and so on. Let `d(S)` be
|
|
3303
|
+
the unique permutation such that `S = T^{\lambda} d(S)` under the natural
|
|
3304
|
+
action. Then the Murphy basis element indexed by `S` and `T` is
|
|
3305
|
+
|
|
3306
|
+
.. MATH::
|
|
3307
|
+
|
|
3308
|
+
M_{S'T'} = d(S)^{-1} R_{\lambda} d(T),
|
|
3309
|
+
|
|
3310
|
+
where `S'` denotes the conjugate tableau.
|
|
3311
|
+
The Murphy basis is a :class:`cellular basis
|
|
3312
|
+
<sage.algebras.cellular_basis.CellularBasis>` of `A`.
|
|
3313
|
+
|
|
3314
|
+
EXAMPLES::
|
|
3315
|
+
|
|
3316
|
+
sage: SGA = SymmetricGroupAlgebra(GF(3), 5)
|
|
3317
|
+
sage: M = SGA.murphy_basis()
|
|
3318
|
+
sage: for la in M.simple_module_parameterization():
|
|
3319
|
+
....: CM = M.cell_module(la)
|
|
3320
|
+
....: print(la, CM.dimension(), CM.simple_module().dimension())
|
|
3321
|
+
[2, 2, 1] 5 4
|
|
3322
|
+
[3, 1, 1] 6 6
|
|
3323
|
+
[3, 2] 5 1
|
|
3324
|
+
[4, 1] 4 4
|
|
3325
|
+
[5] 1 1
|
|
3326
|
+
|
|
3327
|
+
REFERENCES:
|
|
3328
|
+
|
|
3329
|
+
- [DJM1998]_
|
|
3330
|
+
- [Mathas2004]_
|
|
3331
|
+
"""
|
|
3332
|
+
_name = "Murphy"
|
|
3333
|
+
|
|
3334
|
+
def _to_sga(self, ind):
|
|
3335
|
+
r"""
|
|
3336
|
+
Return the element in the symmetric group algebra indexed by ``ind``.
|
|
3337
|
+
|
|
3338
|
+
EXAMPLES::
|
|
3339
|
+
|
|
3340
|
+
sage: SGA = SymmetricGroupAlgebra(GF(3), 3)
|
|
3341
|
+
sage: M = SGA.murphy_basis()
|
|
3342
|
+
sage: for ind in M.basis().keys():
|
|
3343
|
+
....: print(ind, M._to_sga(ind))
|
|
3344
|
+
([1, 1, 1], [[1], [2], [3]], [[1], [2], [3]]) [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
|
|
3345
|
+
([2, 1], [[1, 3], [2]], [[1, 3], [2]]) [1, 2, 3] + [2, 1, 3]
|
|
3346
|
+
([2, 1], [[1, 3], [2]], [[1, 2], [3]]) [1, 3, 2] + [3, 1, 2]
|
|
3347
|
+
([2, 1], [[1, 2], [3]], [[1, 3], [2]]) [1, 3, 2] + [2, 3, 1]
|
|
3348
|
+
([2, 1], [[1, 2], [3]], [[1, 2], [3]]) [1, 2, 3] + [3, 2, 1]
|
|
3349
|
+
([3], [[1, 2, 3]], [[1, 2, 3]]) [1, 2, 3]
|
|
3350
|
+
"""
|
|
3351
|
+
return self._algebra.murphy_basis_element(ind[1], ind[2])
|
|
3352
|
+
|
|
3353
|
+
|
|
3354
|
+
class KLCellularBasis(SGACellularBasis):
|
|
3355
|
+
"""
|
|
3356
|
+
The Kazhdan-Lusztig `C'` basis (at `q = 1`) of the symmetric group
|
|
3357
|
+
algebra realized as a :class:`cellular basis
|
|
3358
|
+
<sage.algebras.cellular_basis.CellularBasis>`
|
|
3359
|
+
|
|
3360
|
+
EXAMPLES::
|
|
3361
|
+
|
|
3362
|
+
sage: SGA = SymmetricGroupAlgebra(GF(3), 5)
|
|
3363
|
+
sage: KL = SGA.kazhdan_lusztig_cellular_basis()
|
|
3364
|
+
sage: for la in KL.simple_module_parameterization():
|
|
3365
|
+
....: CM = KL.cell_module(la)
|
|
3366
|
+
....: print(la, CM.dimension(), CM.simple_module().dimension())
|
|
3367
|
+
[2, 2, 1] 5 4
|
|
3368
|
+
[3, 1, 1] 6 6
|
|
3369
|
+
[3, 2] 5 1
|
|
3370
|
+
[4, 1] 4 4
|
|
3371
|
+
[5] 1 1
|
|
3372
|
+
"""
|
|
3373
|
+
_name = "Kazhdan-Lusztig"
|
|
3374
|
+
|
|
3375
|
+
def _to_sga(self, ind):
|
|
3376
|
+
r"""
|
|
3377
|
+
Return the element in the symmetric group algebra indexed by ``ind``.
|
|
3378
|
+
|
|
3379
|
+
EXAMPLES::
|
|
3380
|
+
|
|
3381
|
+
sage: SGA = SymmetricGroupAlgebra(GF(3), 3)
|
|
3382
|
+
sage: KL = SGA.kazhdan_lusztig_cellular_basis()
|
|
3383
|
+
sage: for ind in KL.basis().keys():
|
|
3384
|
+
....: print(ind, KL._to_sga(ind))
|
|
3385
|
+
([1, 1, 1], [[1], [2], [3]], [[1], [2], [3]]) [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1] + [3, 1, 2] + [3, 2, 1]
|
|
3386
|
+
([2, 1], [[1, 3], [2]], [[1, 3], [2]]) [1, 2, 3] + [2, 1, 3]
|
|
3387
|
+
([2, 1], [[1, 3], [2]], [[1, 2], [3]]) [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [3, 1, 2]
|
|
3388
|
+
([2, 1], [[1, 2], [3]], [[1, 3], [2]]) [1, 2, 3] + [1, 3, 2] + [2, 1, 3] + [2, 3, 1]
|
|
3389
|
+
([2, 1], [[1, 2], [3]], [[1, 2], [3]]) [1, 2, 3] + [1, 3, 2]
|
|
3390
|
+
([3], [[1, 2, 3]], [[1, 2, 3]]) [1, 2, 3]
|
|
3391
|
+
"""
|
|
3392
|
+
from sage.combinat.rsk import RSK_inverse
|
|
3393
|
+
S = ind[1]
|
|
3394
|
+
T = ind[2]
|
|
3395
|
+
w = RSK_inverse(T, S, output='permutation')
|
|
3396
|
+
return self._algebra.kazhdan_lusztig_basis_element(w)
|
|
3397
|
+
|
|
3398
|
+
|
|
3399
|
+
#######################
|
|
3400
|
+
|
|
3401
|
+
|
|
3402
|
+
def HeckeAlgebraSymmetricGroupT(R, n, q=None):
|
|
3403
|
+
r"""
|
|
3404
|
+
Return the Hecke algebra of the symmetric group `S_n` on the T-basis
|
|
3405
|
+
with quantum parameter ``q`` over the ring `R`.
|
|
3406
|
+
|
|
3407
|
+
If `R` is a commutative ring and `q` is an invertible element of `R`,
|
|
3408
|
+
and if `n` is a nonnegative integer, then the Hecke algebra of the
|
|
3409
|
+
symmetric group `S_n` over `R` with quantum parameter `q` is defined
|
|
3410
|
+
as the algebra generated by the generators `T_1, T_2, \ldots, T_{n-1}`
|
|
3411
|
+
with relations
|
|
3412
|
+
|
|
3413
|
+
.. MATH::
|
|
3414
|
+
|
|
3415
|
+
T_i T_{i+1} T_i = T_{i+1} T_i T_{i+1}
|
|
3416
|
+
|
|
3417
|
+
for all `i < n-1` ("braid relations"),
|
|
3418
|
+
|
|
3419
|
+
.. MATH::
|
|
3420
|
+
|
|
3421
|
+
T_i T_j = T_j T_i
|
|
3422
|
+
|
|
3423
|
+
for all `i` and `j` such that `| i-j | > 1` ("locality relations"),
|
|
3424
|
+
and
|
|
3425
|
+
|
|
3426
|
+
.. MATH::
|
|
3427
|
+
|
|
3428
|
+
T_i^2 = q + (q-1) T_i
|
|
3429
|
+
|
|
3430
|
+
for all `i` (the "quadratic relations", also known in the form
|
|
3431
|
+
`(T_i + 1) (T_i - q) = 0`). (This is only one of several existing
|
|
3432
|
+
definitions in literature, not all of which are fully equivalent.
|
|
3433
|
+
We are following the conventions of [Go1993]_.) For any permutation
|
|
3434
|
+
`w \in S_n`, we can define an element `T_w` of this Hecke algebra by
|
|
3435
|
+
setting `T_w = T_{i_1} T_{i_2} \cdots T_{i_k}`, where
|
|
3436
|
+
`w = s_{i_1} s_{i_2} \cdots s_{i_k}` is a reduced word for `w`
|
|
3437
|
+
(with `s_i` meaning the transposition `(i, i+1)`, and the product of
|
|
3438
|
+
permutations being evaluated by first applying `s_{i_k}`, then
|
|
3439
|
+
`s_{i_{k-1}}`, etc.). This element is independent of the choice of
|
|
3440
|
+
the reduced decomposition, and can be computed in Sage by calling
|
|
3441
|
+
``H[w]`` where ``H`` is the Hecke algebra and ``w`` is the
|
|
3442
|
+
permutation.
|
|
3443
|
+
|
|
3444
|
+
The Hecke algebra of the symmetric group `S_n` with quantum parameter
|
|
3445
|
+
`q` over `R` can be seen as a deformation of the group algebra
|
|
3446
|
+
`R S_n`; indeed, it becomes `R S_n` when `q = 1`.
|
|
3447
|
+
|
|
3448
|
+
.. WARNING::
|
|
3449
|
+
|
|
3450
|
+
The multiplication on the Hecke algebra of the symmetric group
|
|
3451
|
+
does *not* follow the global option ``mult`` of the
|
|
3452
|
+
:class:`Permutations` class (see
|
|
3453
|
+
:meth:`~sage.combinat.permutation.Permutations.options`).
|
|
3454
|
+
It is always as defined above. It does not match the default
|
|
3455
|
+
option (``mult=l2r``) of the symmetric group algebra!
|
|
3456
|
+
|
|
3457
|
+
EXAMPLES::
|
|
3458
|
+
|
|
3459
|
+
sage: HeckeAlgebraSymmetricGroupT(QQ, 3)
|
|
3460
|
+
Hecke algebra of the symmetric group of order 3 on the T basis over Univariate Polynomial Ring in q over Rational Field
|
|
3461
|
+
|
|
3462
|
+
::
|
|
3463
|
+
|
|
3464
|
+
sage: HeckeAlgebraSymmetricGroupT(QQ, 3, 2)
|
|
3465
|
+
Hecke algebra of the symmetric group of order 3 with q=2 on the T basis over Rational Field
|
|
3466
|
+
|
|
3467
|
+
The multiplication on the Hecke algebra follows a different convention
|
|
3468
|
+
than the one on the symmetric group algebra does by default::
|
|
3469
|
+
|
|
3470
|
+
sage: H3 = HeckeAlgebraSymmetricGroupT(QQ, 3)
|
|
3471
|
+
sage: H3([1,3,2]) * H3([2,1,3])
|
|
3472
|
+
T[3, 1, 2]
|
|
3473
|
+
sage: S3 = SymmetricGroupAlgebra(QQ, 3)
|
|
3474
|
+
sage: S3([1,3,2]) * S3([2,1,3])
|
|
3475
|
+
[2, 3, 1]
|
|
3476
|
+
|
|
3477
|
+
sage: TestSuite(H3).run()
|
|
3478
|
+
|
|
3479
|
+
.. NOTE::
|
|
3480
|
+
|
|
3481
|
+
:class:`~sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra` gives
|
|
3482
|
+
a different implementation of the Iwahori-Hecke algebras of a Coxeter
|
|
3483
|
+
system `(W,S)`. This includes the Hecke algebras of the symmetric group
|
|
3484
|
+
as special case.
|
|
3485
|
+
"""
|
|
3486
|
+
return HeckeAlgebraSymmetricGroup_t(R, n, q)
|
|
3487
|
+
|
|
3488
|
+
|
|
3489
|
+
class HeckeAlgebraSymmetricGroup_generic(CombinatorialFreeModule):
|
|
3490
|
+
def __init__(self, R, n, q=None):
|
|
3491
|
+
"""
|
|
3492
|
+
TESTS::
|
|
3493
|
+
|
|
3494
|
+
sage: HeckeAlgebraSymmetricGroupT(QQ, 3)
|
|
3495
|
+
Hecke algebra of the symmetric group of order 3 on the T basis over Univariate Polynomial Ring in q over Rational Field
|
|
3496
|
+
|
|
3497
|
+
::
|
|
3498
|
+
|
|
3499
|
+
sage: HeckeAlgebraSymmetricGroupT(QQ, 3, q=1)
|
|
3500
|
+
Hecke algebra of the symmetric group of order 3 with q=1 on the T basis over Rational Field
|
|
3501
|
+
"""
|
|
3502
|
+
self.n = n
|
|
3503
|
+
self._indices = Permutations(n)
|
|
3504
|
+
self._name = "Hecke algebra of the symmetric group of order {}".format(n)
|
|
3505
|
+
if q is None:
|
|
3506
|
+
q = PolynomialRing(R, 'q').gen()
|
|
3507
|
+
R = q.parent()
|
|
3508
|
+
else:
|
|
3509
|
+
if q not in R:
|
|
3510
|
+
raise ValueError("q must be in R (= {})".format(R))
|
|
3511
|
+
self._name += " with q={}".format(q)
|
|
3512
|
+
|
|
3513
|
+
self._q = q
|
|
3514
|
+
|
|
3515
|
+
CombinatorialFreeModule.__init__(self, R, self._indices,
|
|
3516
|
+
category=AlgebrasWithBasis(R),
|
|
3517
|
+
prefix="")
|
|
3518
|
+
|
|
3519
|
+
_repr_option_bracket = False
|
|
3520
|
+
|
|
3521
|
+
@cached_method
|
|
3522
|
+
def one_basis(self):
|
|
3523
|
+
"""
|
|
3524
|
+
Return the identity permutation.
|
|
3525
|
+
|
|
3526
|
+
EXAMPLES::
|
|
3527
|
+
|
|
3528
|
+
sage: HeckeAlgebraSymmetricGroupT(QQ, 3).one() # indirect doctest
|
|
3529
|
+
T[1, 2, 3]
|
|
3530
|
+
"""
|
|
3531
|
+
return self._indices.one()
|
|
3532
|
+
|
|
3533
|
+
def q(self):
|
|
3534
|
+
"""
|
|
3535
|
+
Return the variable or parameter `q`.
|
|
3536
|
+
|
|
3537
|
+
EXAMPLES::
|
|
3538
|
+
|
|
3539
|
+
sage: HeckeAlgebraSymmetricGroupT(QQ, 3).q()
|
|
3540
|
+
q
|
|
3541
|
+
sage: HeckeAlgebraSymmetricGroupT(QQ, 3, 2).q()
|
|
3542
|
+
2
|
|
3543
|
+
"""
|
|
3544
|
+
return self._q
|
|
3545
|
+
|
|
3546
|
+
def _element_constructor_(self, x):
|
|
3547
|
+
"""
|
|
3548
|
+
EXAMPLES::
|
|
3549
|
+
|
|
3550
|
+
sage: H3 = HeckeAlgebraSymmetricGroupT(QQ, 3)
|
|
3551
|
+
sage: H3([2,1]) # indirect doc test
|
|
3552
|
+
T[2, 1, 3]
|
|
3553
|
+
sage: H3( Permutations(3).an_element() )
|
|
3554
|
+
T[3, 1, 2]
|
|
3555
|
+
sage: H3( SymmetricGroup(3).an_element() )
|
|
3556
|
+
[1, 3, 2]
|
|
3557
|
+
sage: H3( [2, 1, 3, 4, 5, 6] )
|
|
3558
|
+
T[2, 1, 3]
|
|
3559
|
+
"""
|
|
3560
|
+
###################################################
|
|
3561
|
+
# Coerce permutations of size smaller that self.n #
|
|
3562
|
+
###################################################
|
|
3563
|
+
if not x:
|
|
3564
|
+
return self.one()
|
|
3565
|
+
if x in Permutations():
|
|
3566
|
+
if len(x) < self.n:
|
|
3567
|
+
return self.monomial(self._indices(
|
|
3568
|
+
list(x) + list(range(len(x) + 1, self.n + 1))
|
|
3569
|
+
))
|
|
3570
|
+
if all(x[i] == i+1 for i in range(self.n, len(x))):
|
|
3571
|
+
return self.monomial(self._indices(x[:self.n]))
|
|
3572
|
+
|
|
3573
|
+
return self._indices(x)
|
|
3574
|
+
|
|
3575
|
+
|
|
3576
|
+
class HeckeAlgebraSymmetricGroup_t(HeckeAlgebraSymmetricGroup_generic):
|
|
3577
|
+
|
|
3578
|
+
def __init__(self, R, n, q=None):
|
|
3579
|
+
"""
|
|
3580
|
+
TESTS::
|
|
3581
|
+
|
|
3582
|
+
sage: H3 = HeckeAlgebraSymmetricGroupT(QQ, 3)
|
|
3583
|
+
sage: H3 == loads(dumps(H3))
|
|
3584
|
+
True
|
|
3585
|
+
"""
|
|
3586
|
+
HeckeAlgebraSymmetricGroup_generic.__init__(self, R, n, q)
|
|
3587
|
+
self._name += " on the T basis"
|
|
3588
|
+
self.print_options(prefix='T')
|
|
3589
|
+
|
|
3590
|
+
def t_action_on_basis(self, perm, i):
|
|
3591
|
+
r"""
|
|
3592
|
+
Return the product `T_i \cdot T_{perm}`, where ``perm`` is a
|
|
3593
|
+
permutation in the symmetric group `S_n`.
|
|
3594
|
+
|
|
3595
|
+
EXAMPLES::
|
|
3596
|
+
|
|
3597
|
+
sage: H3 = HeckeAlgebraSymmetricGroupT(QQ, 3)
|
|
3598
|
+
sage: H3.t_action_on_basis(Permutation([2,1,3]), 1)
|
|
3599
|
+
q*T[1, 2, 3] + (q-1)*T[2, 1, 3]
|
|
3600
|
+
sage: H3.t_action_on_basis(Permutation([1,2,3]), 1)
|
|
3601
|
+
T[2, 1, 3]
|
|
3602
|
+
sage: H3 = HeckeAlgebraSymmetricGroupT(QQ, 3, 1)
|
|
3603
|
+
sage: H3.t_action_on_basis(Permutation([2,1,3]), 1)
|
|
3604
|
+
T[1, 2, 3]
|
|
3605
|
+
sage: H3.t_action_on_basis(Permutation([1,3,2]), 2)
|
|
3606
|
+
T[1, 2, 3]
|
|
3607
|
+
"""
|
|
3608
|
+
if i not in range(1, self.n):
|
|
3609
|
+
raise ValueError(f"i (= {i}) must be between 1 and n (={self.n})")
|
|
3610
|
+
|
|
3611
|
+
t_i = Permutation((i, i + 1))
|
|
3612
|
+
perm_i = t_i.right_action_product(perm)
|
|
3613
|
+
# This used to be perm_i = t_i * perm. I have changed it to
|
|
3614
|
+
# perm_i = t_i.right_action_product(perm) because it would
|
|
3615
|
+
# otherwise cause TestSuite(H3) to fail when
|
|
3616
|
+
# Permutations.options(mult) would be set to "r2l".
|
|
3617
|
+
# -- Darij, 19 Nov 2013
|
|
3618
|
+
|
|
3619
|
+
if perm[i - 1] < perm[i]:
|
|
3620
|
+
return self.monomial(self._indices(perm_i))
|
|
3621
|
+
else:
|
|
3622
|
+
# Ti^2 = (q - q^(-1))*Ti - q1*q2
|
|
3623
|
+
q = self.q()
|
|
3624
|
+
z_elt = {perm_i: q, perm: q - 1}
|
|
3625
|
+
return self._from_dict(z_elt)
|
|
3626
|
+
|
|
3627
|
+
def t_action(self, a, i):
|
|
3628
|
+
r"""
|
|
3629
|
+
Return the product `T_i \cdot a`.
|
|
3630
|
+
|
|
3631
|
+
EXAMPLES::
|
|
3632
|
+
|
|
3633
|
+
sage: H3 = HeckeAlgebraSymmetricGroupT(QQ, 3)
|
|
3634
|
+
sage: a = H3([2,1,3])+2*H3([1,2,3])
|
|
3635
|
+
sage: H3.t_action(a, 1)
|
|
3636
|
+
q*T[1, 2, 3] + (q+1)*T[2, 1, 3]
|
|
3637
|
+
sage: H3.t(1)*a
|
|
3638
|
+
q*T[1, 2, 3] + (q+1)*T[2, 1, 3]
|
|
3639
|
+
"""
|
|
3640
|
+
def t_i(x):
|
|
3641
|
+
return self.t_action_on_basis(x, i)
|
|
3642
|
+
return self._apply_module_endomorphism(a, t_i)
|
|
3643
|
+
|
|
3644
|
+
def product_on_basis(self, perm1, perm2):
|
|
3645
|
+
"""
|
|
3646
|
+
EXAMPLES::
|
|
3647
|
+
|
|
3648
|
+
sage: H3 = HeckeAlgebraSymmetricGroupT(QQ, 3, 1)
|
|
3649
|
+
sage: a = H3([2,1,3])+2*H3([1,2,3])-H3([3,2,1])
|
|
3650
|
+
sage: a^2 #indirect doctest
|
|
3651
|
+
6*T[1, 2, 3] + 4*T[2, 1, 3] - T[2, 3, 1]
|
|
3652
|
+
- T[3, 1, 2] - 4*T[3, 2, 1]
|
|
3653
|
+
|
|
3654
|
+
::
|
|
3655
|
+
|
|
3656
|
+
sage: QS3 = SymmetricGroupAlgebra(QQ, 3)
|
|
3657
|
+
sage: a = QS3([2,1,3])+2*QS3([1,2,3])-QS3([3,2,1])
|
|
3658
|
+
sage: a^2
|
|
3659
|
+
6*[1, 2, 3] + 4*[2, 1, 3] - [2, 3, 1] - [3, 1, 2] - 4*[3, 2, 1]
|
|
3660
|
+
"""
|
|
3661
|
+
res = self(perm1)
|
|
3662
|
+
for i in perm2.reduced_word():
|
|
3663
|
+
res = self.t_action(res, i)
|
|
3664
|
+
return res
|
|
3665
|
+
|
|
3666
|
+
def t(self, i):
|
|
3667
|
+
"""
|
|
3668
|
+
Return the element `T_i` of the Hecke algebra ``self``.
|
|
3669
|
+
|
|
3670
|
+
EXAMPLES::
|
|
3671
|
+
|
|
3672
|
+
sage: H3 = HeckeAlgebraSymmetricGroupT(QQ,3)
|
|
3673
|
+
sage: H3.t(1)
|
|
3674
|
+
T[2, 1, 3]
|
|
3675
|
+
sage: H3.t(2)
|
|
3676
|
+
T[1, 3, 2]
|
|
3677
|
+
sage: H3.t(0)
|
|
3678
|
+
Traceback (most recent call last):
|
|
3679
|
+
...
|
|
3680
|
+
ValueError: i (= 0) must be between 1 and n-1 (= 2)
|
|
3681
|
+
"""
|
|
3682
|
+
if i not in range(1, self.n):
|
|
3683
|
+
raise ValueError(f"i (= {i}) must be between 1 and n-1 (= {self.n - 1})")
|
|
3684
|
+
|
|
3685
|
+
P = self.basis().keys()
|
|
3686
|
+
return self.monomial(P(list(range(1, i)) + [i + 1, i] +
|
|
3687
|
+
list(range(i + 2, self.n + 1))))
|
|
3688
|
+
# The permutation here is simply the transposition (i, i+1).
|
|
3689
|
+
|
|
3690
|
+
def algebra_generators(self):
|
|
3691
|
+
"""
|
|
3692
|
+
Return the generators of the algebra.
|
|
3693
|
+
|
|
3694
|
+
EXAMPLES::
|
|
3695
|
+
|
|
3696
|
+
sage: HeckeAlgebraSymmetricGroupT(QQ,3).algebra_generators()
|
|
3697
|
+
[T[2, 1, 3], T[1, 3, 2]]
|
|
3698
|
+
"""
|
|
3699
|
+
return [self.t(i) for i in range(1, self.n)]
|
|
3700
|
+
|
|
3701
|
+
def jucys_murphy(self, k):
|
|
3702
|
+
r"""
|
|
3703
|
+
Return the Jucys-Murphy element `J_k` of the Hecke algebra.
|
|
3704
|
+
|
|
3705
|
+
These Jucys-Murphy elements are defined by
|
|
3706
|
+
|
|
3707
|
+
.. MATH::
|
|
3708
|
+
|
|
3709
|
+
J_k = (T_{k-1} T_{k-2} \cdots T_1) (T_1 T_2 \cdots T_{k-1}).
|
|
3710
|
+
|
|
3711
|
+
More explicitly,
|
|
3712
|
+
|
|
3713
|
+
.. MATH::
|
|
3714
|
+
|
|
3715
|
+
J_k = q^{k-1} + \sum_{l=1}^{k-1} (q^l - q^{l-1}) T_{(l, k)}.
|
|
3716
|
+
|
|
3717
|
+
For generic `q`, the `J_k` generate a maximal commutative
|
|
3718
|
+
sub-algebra of the Hecke algebra.
|
|
3719
|
+
|
|
3720
|
+
.. WARNING::
|
|
3721
|
+
|
|
3722
|
+
The specialization `q = 1` does *not* map these elements
|
|
3723
|
+
`J_k` to the Young-Jucys-Murphy elements of the group
|
|
3724
|
+
algebra `R S_n`. (Instead, it maps the "reduced"
|
|
3725
|
+
Jucys-Murphy elements `(J_k - q^{k-1}) / (q - 1)` to the
|
|
3726
|
+
Young-Jucys-Murphy elements of `R S_n`.)
|
|
3727
|
+
|
|
3728
|
+
EXAMPLES::
|
|
3729
|
+
|
|
3730
|
+
sage: H3 = HeckeAlgebraSymmetricGroupT(QQ,3)
|
|
3731
|
+
sage: j2 = H3.jucys_murphy(2); j2
|
|
3732
|
+
q*T[1, 2, 3] + (q-1)*T[2, 1, 3]
|
|
3733
|
+
sage: j3 = H3.jucys_murphy(3); j3
|
|
3734
|
+
q^2*T[1, 2, 3] + (q^2-q)*T[1, 3, 2] + (q-1)*T[3, 2, 1]
|
|
3735
|
+
sage: j2*j3 == j3*j2
|
|
3736
|
+
True
|
|
3737
|
+
sage: j0 = H3.jucys_murphy(1); j0 == H3.one()
|
|
3738
|
+
True
|
|
3739
|
+
sage: H3.jucys_murphy(0)
|
|
3740
|
+
Traceback (most recent call last):
|
|
3741
|
+
...
|
|
3742
|
+
ValueError: k (= 0) must be between 1 and n (= 3)
|
|
3743
|
+
"""
|
|
3744
|
+
if k not in range(2, self.n + 1):
|
|
3745
|
+
if k == 1:
|
|
3746
|
+
return self.one()
|
|
3747
|
+
raise ValueError(f"k (= {k}) must be between 1 and n (= {self.n})")
|
|
3748
|
+
|
|
3749
|
+
q = self.q()
|
|
3750
|
+
P = self._indices
|
|
3751
|
+
v = self.sum_of_terms(((P(list(range(1, l)) + [k] +
|
|
3752
|
+
list(range(l + 1, k)) + [l]),
|
|
3753
|
+
q**l - q**(l - 1))
|
|
3754
|
+
for l in range(1, k)),
|
|
3755
|
+
distinct=True)
|
|
3756
|
+
v += q**(k - 1) * self.one()
|
|
3757
|
+
return v
|
|
3758
|
+
|
|
3759
|
+
# old algorithm:
|
|
3760
|
+
# left = 1
|
|
3761
|
+
# right = 1
|
|
3762
|
+
# for j in range(1, k):
|
|
3763
|
+
# left *= self.t(k-j)
|
|
3764
|
+
# right *= self.t(j)
|
|
3765
|
+
# return left*right
|
|
3766
|
+
|
|
3767
|
+
|
|
3768
|
+
# For unpickling backward compatibility (Sage <= 4.1)
|
|
3769
|
+
register_unpickle_override('sage.combinat.symmetric_group_algebra',
|
|
3770
|
+
'HeckeAlgebraSymmetricGroupElement_t',
|
|
3771
|
+
CombinatorialFreeModule.Element)
|
|
3772
|
+
register_unpickle_override('sage.combinat.symmetric_group_algebra',
|
|
3773
|
+
'SymmetricGroupAlgebraElement_n',
|
|
3774
|
+
CombinatorialFreeModule.Element)
|