passagemath-combinat 10.6.42__cp314-cp314t-win_amd64.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/DELVEWHEEL +2 -0
- passagemath_combinat-10.6.42.dist-info/METADATA +160 -0
- passagemath_combinat-10.6.42.dist-info/RECORD +401 -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-10-3a5f019e2510aeaad918cab2b57a689d.dll +0 -0
- passagemath_combinat.libs/libsymmetrica-3-7dcf900932804d0df5fd0919b4668720.dll +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 +44 -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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +0 -0
- sage/combinat/debruijn_sequence.pyx +355 -0
- sage/combinat/decorated_permutation.py +270 -0
- sage/combinat/degree_sequences.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +0 -0
- sage/combinat/expnums.pyx +148 -0
- sage/combinat/fast_vector_partitions.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +0 -0
- sage/combinat/words/word_char.pyx +847 -0
- sage/combinat/words/word_datatypes.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +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.cp314t-win_amd64.pyd +0 -0
- sage/sat/solvers/satsolver.pxd +3 -0
- sage/sat/solvers/satsolver.pyx +405 -0
|
@@ -0,0 +1,1982 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
# sage.doctest: needs sage.combinat sage.modules
|
|
3
|
+
r"""
|
|
4
|
+
Kleshchev partitions
|
|
5
|
+
====================
|
|
6
|
+
|
|
7
|
+
A partition (tuple) `\mu` is Kleshchev if it can be recursively
|
|
8
|
+
obtained by adding a sequence of good nodes to the empty
|
|
9
|
+
:class:`PartitionTuple` of the same :meth:`~PartitionTuple.level`
|
|
10
|
+
and *multicharge*. In this way, the set of Kleshchev multipartitions becomes
|
|
11
|
+
a realization of a Kashiwara crystal :mod:`sage.combinat.crystals.crystals`
|
|
12
|
+
for a irreducible integral highest weight representation of
|
|
13
|
+
`U_q(\widehat{\mathfrak{sl}}_e)`.
|
|
14
|
+
|
|
15
|
+
The Kleshchev multipartitions first appeared in the work of Ariki and Mathas
|
|
16
|
+
[AM2000]_ where it was shown that they index the irreducible representations
|
|
17
|
+
of the cyclotomic Hecke algebras of type `A` [AK1994]_. Soon afterwards Ariki
|
|
18
|
+
[Ariki2001]_ showed that the set of Kleshchev multipartitions naturally label
|
|
19
|
+
the irreducible representations of these algebras. As a far reaching
|
|
20
|
+
generalization of these ideas the Ariki-Brundan-Kleshchev categorification
|
|
21
|
+
theorem [Ariki1996]_ [BK2009]_ says that these algebras categorify the
|
|
22
|
+
irreducible integral highest weight representations of the quantum group
|
|
23
|
+
`U_q(\widehat{\mathfrak{sl}}_e)` of the affine special linear group. Under
|
|
24
|
+
this categorification, `q` corresponds to the grading shift on the
|
|
25
|
+
cyclotomic Hecke algebras, where the grading from the Brundan-Kleshchev
|
|
26
|
+
graded isomorphism theorem to the *KLR algebras* of type `A` [BK2009]_.
|
|
27
|
+
|
|
28
|
+
The group algebras of the symmetric group in characteristic `p` are an
|
|
29
|
+
important special case of the cyclotomic Hecke algebras of type `A`.
|
|
30
|
+
In this case, depending on your prefer convention, the set of Kleshchev
|
|
31
|
+
partitions is the set of *`p`-regular* or *`p`-restricted*
|
|
32
|
+
:class:`~sage.combinat.partition.Partitions`. In this case, Kleshchev
|
|
33
|
+
[Kle1995]_ proved that the *modular branching rules* were given by adding
|
|
34
|
+
and removing *good nodes*; see :meth:`~KleshchevPartition.good_cells`.
|
|
35
|
+
Lascoux, Leclerc and Thibon [LLT1996]_ noticed that Kleshchev's branching
|
|
36
|
+
rules coincided with Kashiwara's crystal operators for the fundamental
|
|
37
|
+
representation of `L(\Lambda_0)` of `U_q(\widehat{\mathfrak{sl}}_p)`
|
|
38
|
+
and their celebrated *LLT conjecture* said that decomposition matrices of
|
|
39
|
+
the :class:`sage.algebras.iwahori_hecke_algebra.IwahoriHeckeAlgebra` of
|
|
40
|
+
the symmetric group should be computable using the canonical basis of
|
|
41
|
+
`L(\Lambda_0)`. This was proved and generalised to all cyclotomic Hecke
|
|
42
|
+
algebras of type `A` by Ariki [Ariki1996]_ and then further generalized
|
|
43
|
+
to the graded setting by Brundan and Kleshchev [BK2009]_.
|
|
44
|
+
|
|
45
|
+
The main class for accessing Kleshchev partition (tuples) is
|
|
46
|
+
:class:`~KleshchevPartitions`. Unfortunately, just as with the
|
|
47
|
+
symmetric group, different authors use different conventions when
|
|
48
|
+
defining Kleshchev partitions, which depends on whether you read
|
|
49
|
+
components from left to right, or right to left, and whether you
|
|
50
|
+
read the nodes in the partition in each component from top to bottom
|
|
51
|
+
or bottom to top. The :class:`~KleshchevPartitions` class supports
|
|
52
|
+
these four different conventions::
|
|
53
|
+
|
|
54
|
+
sage: KleshchevPartitions(2, [0,0], size=2, convention='left regular')[:]
|
|
55
|
+
[([1], [1]), ([2], [])]
|
|
56
|
+
sage: KleshchevPartitions(2, [0,0], size=2, convention='left restricted')[:]
|
|
57
|
+
[([1], [1]), ([], [1, 1])]
|
|
58
|
+
sage: KleshchevPartitions(2, [0,0], size=2, convention='right regular')[:]
|
|
59
|
+
[([1], [1]), ([], [2])]
|
|
60
|
+
sage: KleshchevPartitions(2, [0,0], size=2, convention='right restricted')[:]
|
|
61
|
+
[([1], [1]), ([1, 1], [])]
|
|
62
|
+
|
|
63
|
+
By default, the ``left restricted`` convention is used. As a shorthand,
|
|
64
|
+
``LG``, ``LS``, ``RG`` and ``RS``, respectively, can be used to specify the
|
|
65
|
+
``convention`` With the ``left`` convention the partition tuples should be
|
|
66
|
+
ordered with the most dominant partitions in the partition tuple on the left
|
|
67
|
+
and with the ``right`` convention the most dominant partition is on the right.
|
|
68
|
+
|
|
69
|
+
The :class:`~KleshchevPartitions` class can automatically convert between
|
|
70
|
+
these four different conventions::
|
|
71
|
+
|
|
72
|
+
sage: KPlg = KleshchevPartitions(2, [0,0], size=2, convention='left regular')
|
|
73
|
+
sage: KPls = KleshchevPartitions(2, [0,0], size=2, convention='left restricted')
|
|
74
|
+
sage: [KPlg(mu) for mu in KPls] # indirect doc test
|
|
75
|
+
[([1], [1]), ([2], [])]
|
|
76
|
+
|
|
77
|
+
AUTHORS:
|
|
78
|
+
|
|
79
|
+
- Andrew Mathas and Travis Scrimshaw (2018-05-1): Initial version
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
from .partition import Partition, Partitions
|
|
83
|
+
from .partition_tuple import PartitionTuple, PartitionTuples
|
|
84
|
+
|
|
85
|
+
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
|
|
86
|
+
from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
|
|
87
|
+
from sage.misc.lazy_attribute import lazy_attribute
|
|
88
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
|
89
|
+
from sage.rings.integer_ring import ZZ
|
|
90
|
+
from sage.rings.semirings.non_negative_integer_semiring import NN
|
|
91
|
+
from sage.cpython.getattr import getattr_from_other_class
|
|
92
|
+
|
|
93
|
+
from collections import defaultdict
|
|
94
|
+
|
|
95
|
+
#--------------------------------------------------
|
|
96
|
+
# Kleshchev partition - element classes
|
|
97
|
+
#--------------------------------------------------
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class KleshchevPartition(Partition):
|
|
101
|
+
r"""
|
|
102
|
+
Abstract base class for Kleshchev partitions. See
|
|
103
|
+
:class:`~KleshchevPartitions`.
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
def conormal_cells(self, i=None):
|
|
107
|
+
r"""
|
|
108
|
+
Return a dictionary of the cells of ``self`` which are conormal.
|
|
109
|
+
|
|
110
|
+
Following [Kle1995]_, the *conormal* cells are computed by
|
|
111
|
+
reading up (or down) the rows of the partition and marking all
|
|
112
|
+
of the addable and removable cells of `e`-residue `i` and then
|
|
113
|
+
recursively removing all adjacent pairs of removable and addable
|
|
114
|
+
cells (in that order) from this list. The addable `i`-cells that
|
|
115
|
+
remain at the end of the this process are the conormal `i`-cells.
|
|
116
|
+
|
|
117
|
+
When computing conormal cells you can either read the cells in order
|
|
118
|
+
from top to bottom (this corresponds to labeling the simple modules
|
|
119
|
+
of the symmetric group by regular partitions) or from bottom to top
|
|
120
|
+
(corresponding to labeling the simples by restricted partitions).
|
|
121
|
+
By default we read down the partition but this can be changed by
|
|
122
|
+
setting ``convention = 'RS'``.
|
|
123
|
+
|
|
124
|
+
INPUT:
|
|
125
|
+
|
|
126
|
+
- ``i`` -- (optional) a residue
|
|
127
|
+
|
|
128
|
+
OUTPUT:
|
|
129
|
+
|
|
130
|
+
If no residue ``i`` is specified then a dictionary of conormal cells
|
|
131
|
+
is returned, which gives the conormal cells for ``0 <= i < e``.
|
|
132
|
+
|
|
133
|
+
EXAMPLES::
|
|
134
|
+
|
|
135
|
+
sage: KP = KleshchevPartitions(3, convention='regular')
|
|
136
|
+
sage: KP([5,4,4,3,2]).conormal_cells()
|
|
137
|
+
{0: [(1, 4)], 1: [(5, 0), (4, 2)]}
|
|
138
|
+
sage: KP([5,4,4,3,2]).conormal_cells(0)
|
|
139
|
+
[(1, 4)]
|
|
140
|
+
sage: KP([5,4,4,3,2]).conormal_cells(1)
|
|
141
|
+
[(5, 0), (4, 2)]
|
|
142
|
+
sage: KP = KleshchevPartitions(3, convention='restricted')
|
|
143
|
+
sage: KP([5,4,4,3,2]).conormal_cells()
|
|
144
|
+
{0: [(1, 4), (3, 3)], 2: [(0, 5)]}
|
|
145
|
+
"""
|
|
146
|
+
# We use a dictionary for the conormal nodes as the indexing set is Z when e=0
|
|
147
|
+
conormals = defaultdict(list) # the conormal cells of each residue
|
|
148
|
+
carry = defaultdict(int) # a tally of #(removable cells) - #(addable cells)
|
|
149
|
+
|
|
150
|
+
# determine if we read up or down the partition
|
|
151
|
+
KP = self.parent()
|
|
152
|
+
rows = list(range(len(self)+1))
|
|
153
|
+
if KP._convention[1] == 'G':
|
|
154
|
+
rows.reverse()
|
|
155
|
+
|
|
156
|
+
# work through the rows
|
|
157
|
+
for row in rows:
|
|
158
|
+
if row == len(self): # addable cell at bottom of partition
|
|
159
|
+
res = KP._multicharge[0] - row
|
|
160
|
+
if carry[res] == 0:
|
|
161
|
+
conormals[res].append((row, 0))
|
|
162
|
+
else:
|
|
163
|
+
carry[res] += 1
|
|
164
|
+
else:
|
|
165
|
+
res = KP._multicharge[0] + self[row] - row - 1
|
|
166
|
+
if row == len(self)-1 or self[row] > self[row+1]: # removable cell
|
|
167
|
+
carry[res] -= 1
|
|
168
|
+
if row == 0 or self[row-1] > self[row]: # addable cell
|
|
169
|
+
if carry[res+1] >= 0:
|
|
170
|
+
conormals[res+1].append((row, self[row]))
|
|
171
|
+
else:
|
|
172
|
+
carry[res+1] += 1
|
|
173
|
+
|
|
174
|
+
# finally return the result
|
|
175
|
+
return dict(conormals) if i is None else conormals[i]
|
|
176
|
+
|
|
177
|
+
def cogood_cells(self, i=None):
|
|
178
|
+
r"""
|
|
179
|
+
Return a list of the cells of ``self`` that are cogood.
|
|
180
|
+
|
|
181
|
+
The cogood `i`-cell is the 'last' conormal `i`-cell. As with the
|
|
182
|
+
conormal cells we can choose to read either up or down the partition as
|
|
183
|
+
specified by :meth:`~KleshchevPartitions.convention`.
|
|
184
|
+
|
|
185
|
+
INPUT:
|
|
186
|
+
|
|
187
|
+
- ``i`` -- (optional) a residue
|
|
188
|
+
|
|
189
|
+
OUTPUT:
|
|
190
|
+
|
|
191
|
+
If no residue ``i`` is specified then a dictionary of cogood cells
|
|
192
|
+
is returned, which gives the cogood cells for ``0 <= i < e``.
|
|
193
|
+
|
|
194
|
+
EXAMPLES::
|
|
195
|
+
|
|
196
|
+
sage: KP = KleshchevPartitions(3, convention='regular')
|
|
197
|
+
sage: KP([5,4,4,3,2]).cogood_cells()
|
|
198
|
+
{0: (1, 4), 1: (4, 2)}
|
|
199
|
+
sage: KP([5,4,4,3,2]).cogood_cells(0)
|
|
200
|
+
(1, 4)
|
|
201
|
+
sage: KP([5,4,4,3,2]).cogood_cells(1)
|
|
202
|
+
(4, 2)
|
|
203
|
+
sage: KP = KleshchevPartitions(4, convention='restricted')
|
|
204
|
+
sage: KP([5,4,4,3,2]).cogood_cells()
|
|
205
|
+
{1: (0, 5), 2: (4, 2), 3: (1, 4)}
|
|
206
|
+
sage: KP([5,4,4,3,2]).cogood_cells(0)
|
|
207
|
+
sage: KP([5,4,4,3,2]).cogood_cells(2)
|
|
208
|
+
(4, 2)
|
|
209
|
+
"""
|
|
210
|
+
conormal_cells = self.conormal_cells(i)
|
|
211
|
+
if i is None:
|
|
212
|
+
return {i: conormal_cells[i][-1] for i in conormal_cells}
|
|
213
|
+
elif not conormal_cells:
|
|
214
|
+
return None
|
|
215
|
+
|
|
216
|
+
return conormal_cells[-1]
|
|
217
|
+
|
|
218
|
+
def normal_cells(self, i=None):
|
|
219
|
+
r"""
|
|
220
|
+
Return a dictionary of the cells of the partition that are normal.
|
|
221
|
+
|
|
222
|
+
Following [Kle1995]_, the *normal* cells are computed by
|
|
223
|
+
reading up (or down) the rows of the partition and marking all
|
|
224
|
+
of the addable and removable cells of `e`-residue `i` and then
|
|
225
|
+
recursively removing all adjacent pairs of removable and
|
|
226
|
+
addable cells (in that order) from this list. The removable
|
|
227
|
+
`i`-cells that remain at the end of the this process are the
|
|
228
|
+
normal `i`-cells.
|
|
229
|
+
|
|
230
|
+
When computing normal cells you can either read the cells in order
|
|
231
|
+
from top to bottom (this corresponds to labeling the simple modules
|
|
232
|
+
of the symmetric group by regular partitions) or from bottom to top
|
|
233
|
+
(corresponding to labeling the simples by restricted partitions).
|
|
234
|
+
By default we read down the partition but this can be changed by
|
|
235
|
+
setting ``convention = 'RS'``.
|
|
236
|
+
|
|
237
|
+
INPUT:
|
|
238
|
+
|
|
239
|
+
- ``i`` -- (optional) a residue
|
|
240
|
+
|
|
241
|
+
OUTPUT:
|
|
242
|
+
|
|
243
|
+
If no residue ``i`` is specified then a dictionary of normal cells
|
|
244
|
+
is returned, which gives the normal cells for ``0 <= i < e``.
|
|
245
|
+
|
|
246
|
+
EXAMPLES::
|
|
247
|
+
|
|
248
|
+
sage: KP = KleshchevPartitions(3, convention='regular')
|
|
249
|
+
sage: KP([5,4,4,3,2]).normal_cells()
|
|
250
|
+
{1: [(2, 3), (0, 4)]}
|
|
251
|
+
sage: KP([5,4,4,3,2]).normal_cells(1)
|
|
252
|
+
[(2, 3), (0, 4)]
|
|
253
|
+
sage: KP = KleshchevPartitions(3, convention='restricted')
|
|
254
|
+
sage: KP([5,4,4,3,2]).normal_cells()
|
|
255
|
+
{0: [(4, 1)], 2: [(3, 2)]}
|
|
256
|
+
sage: KP([5,4,4,3,2]).normal_cells(2)
|
|
257
|
+
[(3, 2)]
|
|
258
|
+
"""
|
|
259
|
+
# We use a dictionary for the normal nodes as the indexing set is Z when e=0
|
|
260
|
+
normals = defaultdict(list) # the normal cells of each residue
|
|
261
|
+
carry = defaultdict(int) # a tally of #(removable cells)-#(addable cells)
|
|
262
|
+
|
|
263
|
+
# determine if we read up or down the partition
|
|
264
|
+
KP = self.parent()
|
|
265
|
+
rows = list(range(len(self)+1))
|
|
266
|
+
if KP._convention[1] == 'S':
|
|
267
|
+
rows.reverse()
|
|
268
|
+
|
|
269
|
+
# work through the rows
|
|
270
|
+
for row in rows:
|
|
271
|
+
if row == len(self): # addable cell at bottom of partition
|
|
272
|
+
carry[KP._multicharge[0]-row] += 1
|
|
273
|
+
else:
|
|
274
|
+
res = KP._multicharge[0] + self[row] - row - 1
|
|
275
|
+
if row == len(self) - 1 or self[row] > self[row+1]: # removable cell
|
|
276
|
+
if carry[res] == 0:
|
|
277
|
+
normals[res].insert(0, (row, self[row]-1))
|
|
278
|
+
else:
|
|
279
|
+
carry[res] -= 1
|
|
280
|
+
if row == 0 or self[row-1] > self[row]: # addable cell
|
|
281
|
+
carry[res+1] += 1
|
|
282
|
+
|
|
283
|
+
# finally return the result
|
|
284
|
+
return dict(normals) if i is None else normals[i]
|
|
285
|
+
|
|
286
|
+
def good_cells(self, i=None):
|
|
287
|
+
"""
|
|
288
|
+
Return a list of the cells of ``self`` that are good.
|
|
289
|
+
|
|
290
|
+
The good `i`-cell is the 'first' normal `i`-cell. As with the normal
|
|
291
|
+
cells we can choose to read either up or down the partition as
|
|
292
|
+
specified by :meth:`~KleshchevPartitions.convention`.
|
|
293
|
+
|
|
294
|
+
INPUT:
|
|
295
|
+
|
|
296
|
+
- ``i`` -- (optional) a residue
|
|
297
|
+
|
|
298
|
+
OUTPUT:
|
|
299
|
+
|
|
300
|
+
If no residue ``i`` is specified then a dictionary of good cells
|
|
301
|
+
is returned, which gives the good cells for ``0 <= i < e``.
|
|
302
|
+
|
|
303
|
+
EXAMPLES::
|
|
304
|
+
|
|
305
|
+
sage: KP3 = KleshchevPartitions(3, convention='regular')
|
|
306
|
+
sage: KP3([5,4,4,3,2]).good_cells()
|
|
307
|
+
{1: (2, 3)}
|
|
308
|
+
sage: KP3([5,4,4,3,2]).good_cells(1)
|
|
309
|
+
(2, 3)
|
|
310
|
+
sage: KP4 = KleshchevPartitions(4, convention='restricted')
|
|
311
|
+
sage: KP4([5,4,4,3,2]).good_cells()
|
|
312
|
+
{1: (2, 3)}
|
|
313
|
+
sage: KP4([5,4,4,3,2]).good_cells(0)
|
|
314
|
+
sage: KP4([5,4,4,3,2]).good_cells(1)
|
|
315
|
+
(2, 3)
|
|
316
|
+
"""
|
|
317
|
+
normal_cells = self.normal_cells(i)
|
|
318
|
+
if i is None:
|
|
319
|
+
return {j: normal_cells[j][0] for j in normal_cells}
|
|
320
|
+
elif not normal_cells:
|
|
321
|
+
return None
|
|
322
|
+
|
|
323
|
+
return normal_cells[0]
|
|
324
|
+
|
|
325
|
+
def good_residue_sequence(self):
|
|
326
|
+
"""
|
|
327
|
+
Return a sequence of good nodes from the empty partition
|
|
328
|
+
to ``self``, or ``None`` if no such sequence exists.
|
|
329
|
+
|
|
330
|
+
EXAMPLES::
|
|
331
|
+
|
|
332
|
+
sage: KP = KleshchevPartitions(3, convention='regular')
|
|
333
|
+
sage: KP([5,4,4,3,2]).good_residue_sequence()
|
|
334
|
+
[0, 2, 1, 1, 0, 2, 0, 2, 1, 1, 0, 2, 0, 2, 2, 0, 1, 1]
|
|
335
|
+
sage: KP = KleshchevPartitions(3, convention='restricted')
|
|
336
|
+
sage: KP([5,4,4,3,2]).good_residue_sequence()
|
|
337
|
+
[0, 1, 2, 2, 0, 1, 0, 2, 1, 2, 0, 1, 0, 2, 1, 2, 1, 0]
|
|
338
|
+
"""
|
|
339
|
+
if not self:
|
|
340
|
+
return []
|
|
341
|
+
|
|
342
|
+
good_cells = self.good_cells()
|
|
343
|
+
assert good_cells
|
|
344
|
+
|
|
345
|
+
res = sorted(good_cells)[0]
|
|
346
|
+
r, c = good_cells[res]
|
|
347
|
+
good_seq = type(self)(self.parent(), self.remove_cell(r,c)).good_residue_sequence()
|
|
348
|
+
good_seq.append(self.parent()._index_set(res))
|
|
349
|
+
return good_seq
|
|
350
|
+
|
|
351
|
+
def good_cell_sequence(self):
|
|
352
|
+
"""
|
|
353
|
+
Return a sequence of good nodes from the empty partition
|
|
354
|
+
to ``self``, or ``None`` if no such sequence exists.
|
|
355
|
+
|
|
356
|
+
EXAMPLES::
|
|
357
|
+
|
|
358
|
+
sage: KP = KleshchevPartitions(3, convention='regular')
|
|
359
|
+
sage: KP([5,4,4,3,2]).good_cell_sequence()
|
|
360
|
+
[(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2),
|
|
361
|
+
(3, 0), (2, 1), (1, 2), (3, 1), (0, 3), (1, 3),
|
|
362
|
+
(2, 2), (3, 2), (4, 0), (4, 1), (0, 4), (2, 3)]
|
|
363
|
+
sage: KP = KleshchevPartitions(3, convention='restricted')
|
|
364
|
+
sage: KP([5,4,4,3,2]).good_cell_sequence()
|
|
365
|
+
[(0, 0), (0, 1), (1, 0), (0, 2), (1, 1), (2, 0),
|
|
366
|
+
(0, 3), (2, 1), (1, 2), (1, 3), (3, 0), (3, 1),
|
|
367
|
+
(2, 2), (4, 0), (2, 3), (3, 2), (0, 4), (4, 1)]
|
|
368
|
+
"""
|
|
369
|
+
if not self:
|
|
370
|
+
return []
|
|
371
|
+
|
|
372
|
+
good_cells = self.good_cells()
|
|
373
|
+
assert good_cells
|
|
374
|
+
|
|
375
|
+
cell = good_cells[sorted(good_cells)[0]]
|
|
376
|
+
good_seq = type(self)(self.parent(), self.remove_cell(*cell)).good_cell_sequence()
|
|
377
|
+
good_seq.append(cell)
|
|
378
|
+
return good_seq
|
|
379
|
+
|
|
380
|
+
def mullineux_conjugate(self):
|
|
381
|
+
r"""
|
|
382
|
+
Return the partition tuple that is the Mullineux conjugate of ``self``.
|
|
383
|
+
|
|
384
|
+
It follows from results in [BK2009]_, [Mat2015]_ that if `\nu` is the
|
|
385
|
+
Mullineux conjugate of the Kleshchev partition tuple `\mu` then the
|
|
386
|
+
simple module `D^\nu =(D^\mu)^{\text{sgn}}` is obtained from `D^\mu`
|
|
387
|
+
by twisting by the `\text{sgn}`-automorphism with is the
|
|
388
|
+
Iwahori-Hecke algebra analogue of tensoring with the one
|
|
389
|
+
dimensional sign representation.
|
|
390
|
+
|
|
391
|
+
EXAMPLES::
|
|
392
|
+
|
|
393
|
+
sage: KP = KleshchevPartitions(3, convention='regular')
|
|
394
|
+
sage: KP([5,4,4,3,2]).mullineux_conjugate()
|
|
395
|
+
[9, 7, 1, 1]
|
|
396
|
+
sage: KP = KleshchevPartitions(3, convention='restricted')
|
|
397
|
+
sage: KP([5,4,4,3,2]).mullineux_conjugate()
|
|
398
|
+
[3, 2, 2, 2, 2, 2, 2, 1, 1, 1]
|
|
399
|
+
sage: KP = KleshchevPartitions(3, [2], convention='regular')
|
|
400
|
+
sage: mc = KP([5,4,4,3,2]).mullineux_conjugate(); mc
|
|
401
|
+
[9, 7, 1, 1]
|
|
402
|
+
sage: mc.parent().multicharge()
|
|
403
|
+
(1,)
|
|
404
|
+
sage: KP = KleshchevPartitions(3, [2], convention='restricted')
|
|
405
|
+
sage: mc = KP([5,4,4,3,2]).mullineux_conjugate(); mc
|
|
406
|
+
[3, 2, 2, 2, 2, 2, 2, 1, 1, 1]
|
|
407
|
+
sage: mc.parent().multicharge()
|
|
408
|
+
(1,)
|
|
409
|
+
"""
|
|
410
|
+
P = self.parent()
|
|
411
|
+
if not self:
|
|
412
|
+
size = None
|
|
413
|
+
if isinstance(P, KleshchevPartitions_size):
|
|
414
|
+
size = P._size
|
|
415
|
+
KP = KleshchevPartitions(P._e, [-c for c in P._multicharge],
|
|
416
|
+
size=size, convention=P._convention)
|
|
417
|
+
return KP.element_class(KP, [])
|
|
418
|
+
|
|
419
|
+
good_cells = self.good_cells()
|
|
420
|
+
assert good_cells
|
|
421
|
+
|
|
422
|
+
r, c = sorted(good_cells.values())[0]
|
|
423
|
+
# This is technically wrong when the parent has a fixed size because
|
|
424
|
+
# the resulting Kleshchev partition after removing a cell has abs
|
|
425
|
+
# smaller size. However, this is useful to avoid constructing
|
|
426
|
+
# transient parents.
|
|
427
|
+
mu = P.element_class(P, self.remove_cell(r, c)).mullineux_conjugate()
|
|
428
|
+
# add back on a cogood cell of residue -residue(k,r,c)
|
|
429
|
+
KP = mu.parent()
|
|
430
|
+
return KP.element_class(KP, mu.add_cell(*mu.cogood_cells( r-c-self.parent()._multicharge[0]) ))
|
|
431
|
+
|
|
432
|
+
def is_regular(self):
|
|
433
|
+
r"""
|
|
434
|
+
Return ``True`` if ``self`` is a `e`-regular partition tuple.
|
|
435
|
+
|
|
436
|
+
A partition tuple is `e`-regular if we can get to the empty partition
|
|
437
|
+
tuple by successively removing a sequence of good cells in the down
|
|
438
|
+
direction. Equivalently, all partitions are `0`-regular and if `e > 0`
|
|
439
|
+
then a partition is `e`-regular if no `e` nonzero parts of ``self``
|
|
440
|
+
are equal.
|
|
441
|
+
|
|
442
|
+
EXAMPLES::
|
|
443
|
+
|
|
444
|
+
sage: KP = KleshchevPartitions(2)
|
|
445
|
+
sage: KP([2,1,1]).is_regular()
|
|
446
|
+
False
|
|
447
|
+
sage: KP = KleshchevPartitions(3)
|
|
448
|
+
sage: KP([2,1,1]).is_regular()
|
|
449
|
+
True
|
|
450
|
+
sage: KP([]).is_regular()
|
|
451
|
+
True
|
|
452
|
+
"""
|
|
453
|
+
if self.size() == 0 or self.parent()._e == 0:
|
|
454
|
+
return True
|
|
455
|
+
KP = self.parent()
|
|
456
|
+
return super().is_regular(KP._e, KP._multicharge)
|
|
457
|
+
|
|
458
|
+
def is_restricted(self):
|
|
459
|
+
r"""
|
|
460
|
+
Return ``True`` if ``self`` is an `e`-restricted partition tuple.
|
|
461
|
+
|
|
462
|
+
A partition tuple is `e`-restricted if we can get to the empty
|
|
463
|
+
partition tuple by successively removing a sequence of good cells in
|
|
464
|
+
the up direction. Equivalently, all partitions are `0`-restricted and
|
|
465
|
+
if `e > 0` then a partition is `e`-restricted if the difference of
|
|
466
|
+
successive parts of ``self`` are always strictly less than `e`.
|
|
467
|
+
|
|
468
|
+
EXAMPLES::
|
|
469
|
+
|
|
470
|
+
sage: KP = KleshchevPartitions(2, convention='regular')
|
|
471
|
+
sage: KP([3,1]).is_restricted()
|
|
472
|
+
False
|
|
473
|
+
sage: KP = KleshchevPartitions(3, convention='regular')
|
|
474
|
+
sage: KP([3,1]).is_restricted()
|
|
475
|
+
True
|
|
476
|
+
sage: KP([]).is_restricted()
|
|
477
|
+
True
|
|
478
|
+
"""
|
|
479
|
+
if self.size() == 0 or self.parent()._e == 0:
|
|
480
|
+
return True
|
|
481
|
+
KP = self.parent()
|
|
482
|
+
return super().is_restricted(KP._e, KP._multicharge)
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
class KleshchevPartitionTuple(PartitionTuple):
|
|
486
|
+
r"""
|
|
487
|
+
Abstract base class for Kleshchev partition tuples. See
|
|
488
|
+
:class:`~KleshchevPartitions`.
|
|
489
|
+
"""
|
|
490
|
+
|
|
491
|
+
def conormal_cells(self, i=None):
|
|
492
|
+
r"""
|
|
493
|
+
Return a dictionary of the cells of the partition that are conormal.
|
|
494
|
+
|
|
495
|
+
Following [Kle1995]_, the *conormal* cells are computed by
|
|
496
|
+
reading up (or down) the rows of the partition and marking all
|
|
497
|
+
of the addable and removable cells of `e`-residue `i` and then
|
|
498
|
+
recursively removing all adjacent pairs of removable and addable
|
|
499
|
+
cells (in that order) from this list. The addable `i`-cells that
|
|
500
|
+
remain at the end of the this process are the conormal `i`-cells.
|
|
501
|
+
|
|
502
|
+
When computing conormal cells you can either read the cells in order
|
|
503
|
+
from top to bottom (this corresponds to labeling the simple modules
|
|
504
|
+
of the symmetric group by regular partitions) or from bottom to top
|
|
505
|
+
(corresponding to labeling the simples by restricted partitions).
|
|
506
|
+
By default we read down the partition but this can be changed by
|
|
507
|
+
setting ``convention = 'RS'``.
|
|
508
|
+
|
|
509
|
+
INPUT:
|
|
510
|
+
|
|
511
|
+
- ``i`` -- (optional) a residue
|
|
512
|
+
|
|
513
|
+
OUTPUT:
|
|
514
|
+
|
|
515
|
+
If no residue ``i`` is specified then a dictionary of conormal cells
|
|
516
|
+
is returned, which gives the conormal cells for ``0 <= i < e``.
|
|
517
|
+
|
|
518
|
+
EXAMPLES::
|
|
519
|
+
|
|
520
|
+
sage: KP = KleshchevPartitions(3, [0,1], convention="left regular")
|
|
521
|
+
sage: KP([[4, 2], [5, 3, 1]]).conormal_cells()
|
|
522
|
+
{0: [(1, 2, 1), (1, 1, 3), (1, 0, 5)],
|
|
523
|
+
1: [(1, 3, 0), (0, 2, 0), (0, 1, 2), (0, 0, 4)]}
|
|
524
|
+
sage: KP([[4, 2], [5, 3, 1]]).conormal_cells(1)
|
|
525
|
+
[(1, 3, 0), (0, 2, 0), (0, 1, 2), (0, 0, 4)]
|
|
526
|
+
sage: KP([[4, 2], [5, 3, 1]]).conormal_cells(2)
|
|
527
|
+
[]
|
|
528
|
+
sage: KP = KleshchevPartitions(3, [0,1], convention="right restricted")
|
|
529
|
+
sage: KP([[4, 2], [5, 3, 1]]).conormal_cells(0)
|
|
530
|
+
[(1, 0, 5), (1, 1, 3), (1, 2, 1)]
|
|
531
|
+
"""
|
|
532
|
+
# We use a dictionary for the conormal nodes as the indexing set is Z when e=0
|
|
533
|
+
conormals = defaultdict(list) # the conormal cells of each residue
|
|
534
|
+
carry = defaultdict(int) # a tally of #(removable cells)-#(addable cells)
|
|
535
|
+
|
|
536
|
+
part_lens = [len(part) for part in self] # so we don't repeatedly call these
|
|
537
|
+
# the indices for the rows ending in addable nodes
|
|
538
|
+
KP = self.parent()
|
|
539
|
+
if KP._convention[0] == 'L':
|
|
540
|
+
rows = [(k,r) for k,ell in enumerate(part_lens) for r in range(ell+1)]
|
|
541
|
+
else:
|
|
542
|
+
rows = [(k,r) for k,ell in reversed(list(enumerate(part_lens))) for r in range(ell+1)]
|
|
543
|
+
if KP._convention[1] == 'G':
|
|
544
|
+
rows.reverse()
|
|
545
|
+
|
|
546
|
+
for row in rows:
|
|
547
|
+
k,r = row
|
|
548
|
+
if r == part_lens[k]: # addable cell at bottom of a component
|
|
549
|
+
res = KP._multicharge[k] - r
|
|
550
|
+
if carry[res] == 0:
|
|
551
|
+
conormals[res].append((k, r, 0))
|
|
552
|
+
else:
|
|
553
|
+
carry[res] += 1
|
|
554
|
+
else:
|
|
555
|
+
part = self[k]
|
|
556
|
+
res = KP._multicharge[k] + (part[r] - r - 1)
|
|
557
|
+
if r == part_lens[k] - 1 or part[r] > part[r+1]: # removable cell
|
|
558
|
+
carry[res] -= 1
|
|
559
|
+
if r == 0 or part[r-1] > part[r]: # addable cell
|
|
560
|
+
if carry[res+1] == 0:
|
|
561
|
+
conormals[res+1].append((k, r, part[r]))
|
|
562
|
+
else:
|
|
563
|
+
carry[res+1] += 1
|
|
564
|
+
|
|
565
|
+
# finally return the result
|
|
566
|
+
if i is None:
|
|
567
|
+
return dict(conormals)
|
|
568
|
+
return conormals[i]
|
|
569
|
+
|
|
570
|
+
def cogood_cells(self, i=None):
|
|
571
|
+
r"""
|
|
572
|
+
Return a list of the cells of the partition that are cogood.
|
|
573
|
+
|
|
574
|
+
The cogood `i`-cell is the 'last' conormal `i`-cell. As with the
|
|
575
|
+
conormal cells we can choose to read either up or down the partition
|
|
576
|
+
as specified by :meth:`~KleshchevPartitions.convention`.
|
|
577
|
+
|
|
578
|
+
INPUT:
|
|
579
|
+
|
|
580
|
+
- ``i`` -- (optional) a residue
|
|
581
|
+
|
|
582
|
+
OUTPUT:
|
|
583
|
+
|
|
584
|
+
If no residue ``i`` is specified then a dictionary of cogood cells
|
|
585
|
+
is returned, which gives the cogood cells for ``0 <= i < e``.
|
|
586
|
+
|
|
587
|
+
EXAMPLES::
|
|
588
|
+
|
|
589
|
+
sage: KP = KleshchevPartitions(3, [0,1])
|
|
590
|
+
sage: pt = KP([[4, 2], [5, 3, 1]])
|
|
591
|
+
sage: pt.cogood_cells()
|
|
592
|
+
{0: (1, 2, 1), 1: (1, 3, 0)}
|
|
593
|
+
sage: pt.cogood_cells(0)
|
|
594
|
+
(1, 2, 1)
|
|
595
|
+
sage: KP = KleshchevPartitions(4, [0,1], convention="left regular")
|
|
596
|
+
sage: pt = KP([[5, 2, 2], [6, 1, 1]])
|
|
597
|
+
sage: pt.cogood_cells()
|
|
598
|
+
{1: (0, 0, 5), 2: (1, 3, 0)}
|
|
599
|
+
sage: pt.cogood_cells(0) is None
|
|
600
|
+
True
|
|
601
|
+
sage: pt.cogood_cells(1) is None
|
|
602
|
+
False
|
|
603
|
+
"""
|
|
604
|
+
conormal_cells = self.conormal_cells(i)
|
|
605
|
+
if i is None:
|
|
606
|
+
return {j: conormal_cells[j][-1] for j in conormal_cells}
|
|
607
|
+
elif not conormal_cells:
|
|
608
|
+
return None
|
|
609
|
+
|
|
610
|
+
return conormal_cells[-1]
|
|
611
|
+
|
|
612
|
+
def normal_cells(self, i=None):
|
|
613
|
+
r"""
|
|
614
|
+
Return a dictionary of the removable cells of the partition that
|
|
615
|
+
are normal.
|
|
616
|
+
|
|
617
|
+
Following [Kle1995]_, the *normal* cells are computed by
|
|
618
|
+
reading up (or down) the rows of the partition and marking all
|
|
619
|
+
of the addable and removable cells of `e`-residue `i` and then
|
|
620
|
+
recursively removing all adjacent pairs of removable and
|
|
621
|
+
addable cells (in that order) from this list. The removable
|
|
622
|
+
`i`-cells that remain at the end of the this process are the
|
|
623
|
+
normal `i`-cells.
|
|
624
|
+
|
|
625
|
+
When computing normal cells you can either read the cells in order
|
|
626
|
+
from top to bottom (this corresponds to labeling the simple modules
|
|
627
|
+
of the symmetric group by regular partitions) or from bottom to top
|
|
628
|
+
(corresponding to labeling the simples by restricted partitions).
|
|
629
|
+
By default we read down the partition but this can be changed by
|
|
630
|
+
setting ``convention = 'RS'``.
|
|
631
|
+
|
|
632
|
+
INPUT:
|
|
633
|
+
|
|
634
|
+
- ``i`` -- (optional) a residue
|
|
635
|
+
|
|
636
|
+
OUTPUT:
|
|
637
|
+
|
|
638
|
+
If no residue ``i`` is specified then a dictionary of normal cells
|
|
639
|
+
is returned, which gives the normal cells for ``0 <= i < e``.
|
|
640
|
+
|
|
641
|
+
EXAMPLES::
|
|
642
|
+
|
|
643
|
+
sage: KP = KleshchevPartitions(3, [0,1], convention="left restricted")
|
|
644
|
+
sage: KP([[4, 2], [5, 3, 1]]).normal_cells()
|
|
645
|
+
{2: [(1, 0, 4), (1, 1, 2), (1, 2, 0)]}
|
|
646
|
+
sage: KP([[4, 2], [5, 3, 1]]).normal_cells(1)
|
|
647
|
+
[]
|
|
648
|
+
sage: KP = KleshchevPartitions(3, [0,1], convention="left regular")
|
|
649
|
+
sage: KP([[4, 2], [5, 3, 1]]).normal_cells()
|
|
650
|
+
{0: [(0, 1, 1), (0, 0, 3)], 2: [(1, 2, 0), (1, 1, 2), (1, 0, 4)]}
|
|
651
|
+
sage: KP = KleshchevPartitions(3, [0,1], convention="right regular")
|
|
652
|
+
sage: KP([[4, 2], [5, 3, 1]]).normal_cells()
|
|
653
|
+
{2: [(1, 2, 0), (1, 1, 2), (1, 0, 4)]}
|
|
654
|
+
sage: KP = KleshchevPartitions(3, [0,1], convention="right restricted")
|
|
655
|
+
sage: KP([[4, 2], [5, 3, 1]]).normal_cells()
|
|
656
|
+
{0: [(0, 0, 3), (0, 1, 1)], 2: [(1, 0, 4), (1, 1, 2), (1, 2, 0)]}
|
|
657
|
+
"""
|
|
658
|
+
# We use a dictionary for the normal nodes as the indexing set is Z when e=0
|
|
659
|
+
normals = defaultdict(list) # the normal cells of each residue
|
|
660
|
+
carry = defaultdict(int) # a tally of #(removable cells)-#(addable cells)
|
|
661
|
+
|
|
662
|
+
part_lens = [len(part) for part in self] # so we don't repeatedly call these
|
|
663
|
+
KP = self.parent()
|
|
664
|
+
if KP._convention[0] == 'L':
|
|
665
|
+
rows = [(k, r) for k, ell in enumerate(part_lens) for r in range(ell+1)]
|
|
666
|
+
else:
|
|
667
|
+
rows = [(k, r) for k, ell in reversed(list(enumerate(part_lens))) for r in range(ell+1)]
|
|
668
|
+
if KP._convention[1] == 'S':
|
|
669
|
+
rows.reverse()
|
|
670
|
+
|
|
671
|
+
for row in rows:
|
|
672
|
+
k, r = row
|
|
673
|
+
if r == part_lens[k]: # addable cell at bottom of a component
|
|
674
|
+
carry[KP._multicharge[k]-r] += 1
|
|
675
|
+
else:
|
|
676
|
+
part = self[k]
|
|
677
|
+
res = KP._multicharge[k] + (part[r] - r - 1)
|
|
678
|
+
if r == part_lens[k]-1 or part[r] > part[r+1]: # removable cell
|
|
679
|
+
if carry[res] == 0:
|
|
680
|
+
normals[res].insert(0, (k, r, part[r]-1))
|
|
681
|
+
else:
|
|
682
|
+
carry[res] -= 1
|
|
683
|
+
if r == 0 or part[r-1] > part[r]: # addable cell
|
|
684
|
+
carry[res+1] += 1
|
|
685
|
+
|
|
686
|
+
# finally return the result
|
|
687
|
+
if i is None:
|
|
688
|
+
return dict(normals) # change the defaultdict into a dict
|
|
689
|
+
|
|
690
|
+
return normals[i]
|
|
691
|
+
|
|
692
|
+
def good_cells(self, i=None):
|
|
693
|
+
r"""
|
|
694
|
+
Return a list of the cells of the partition tuple which are good.
|
|
695
|
+
|
|
696
|
+
The good `i`-cell is the 'first' normal `i`-cell. As with the normal
|
|
697
|
+
cells we can choose to read either up or down the partition as specified
|
|
698
|
+
by :meth:`~KleshchevPartitions.convention`.
|
|
699
|
+
|
|
700
|
+
INPUT:
|
|
701
|
+
|
|
702
|
+
- ``i`` -- (optional) a residue
|
|
703
|
+
|
|
704
|
+
OUTPUT:
|
|
705
|
+
|
|
706
|
+
If no residue ``i`` is specified then a dictionary of good cells
|
|
707
|
+
is returned, which gives the good cells for ``0 <= i < e``.
|
|
708
|
+
|
|
709
|
+
EXAMPLES::
|
|
710
|
+
|
|
711
|
+
sage: KP = KleshchevPartitions(3, [0,1])
|
|
712
|
+
sage: pt = KP([[4, 2], [5, 3, 1]])
|
|
713
|
+
sage: pt.good_cells()
|
|
714
|
+
{2: (1, 0, 4)}
|
|
715
|
+
sage: pt.good_cells(2)
|
|
716
|
+
(1, 0, 4)
|
|
717
|
+
sage: KP = KleshchevPartitions(4, [0,1], convention="left regular")
|
|
718
|
+
sage: pt = KP([[5, 2, 2], [6, 2, 1]])
|
|
719
|
+
sage: pt.good_cells()
|
|
720
|
+
{0: (0, 0, 4), 2: (1, 0, 5), 3: (0, 2, 1)}
|
|
721
|
+
sage: pt.good_cells(1) is None
|
|
722
|
+
True
|
|
723
|
+
"""
|
|
724
|
+
normal_cells = self.normal_cells(i)
|
|
725
|
+
if i is None:
|
|
726
|
+
return {j: normal_cells[j][0] for j in normal_cells}
|
|
727
|
+
elif not normal_cells:
|
|
728
|
+
return None
|
|
729
|
+
|
|
730
|
+
return normal_cells[0]
|
|
731
|
+
|
|
732
|
+
def good_residue_sequence(self):
|
|
733
|
+
"""
|
|
734
|
+
Return a sequence of good nodes from the empty partition to ``self``.
|
|
735
|
+
|
|
736
|
+
EXAMPLES::
|
|
737
|
+
|
|
738
|
+
sage: KP = KleshchevPartitions(3, [0,1])
|
|
739
|
+
sage: KP([[4, 2], [5, 3, 1]]).good_residue_sequence()
|
|
740
|
+
[0, 1, 2, 1, 2, 0, 1, 0, 2, 2, 0, 1, 0, 2, 2]
|
|
741
|
+
"""
|
|
742
|
+
if self.size() == 0:
|
|
743
|
+
return []
|
|
744
|
+
good_cells = self.good_cells()
|
|
745
|
+
assert good_cells
|
|
746
|
+
|
|
747
|
+
res = sorted(good_cells.keys())[0]
|
|
748
|
+
k, r, c = good_cells[res]
|
|
749
|
+
good_seq = type(self)(self.parent(), self.remove_cell(k,r,c)).good_residue_sequence()
|
|
750
|
+
good_seq.append( self.parent()._index_set(res) )
|
|
751
|
+
return good_seq
|
|
752
|
+
|
|
753
|
+
def good_cell_sequence(self):
|
|
754
|
+
"""
|
|
755
|
+
Return a sequence of good nodes from the empty partition to ``self``.
|
|
756
|
+
|
|
757
|
+
EXAMPLES::
|
|
758
|
+
|
|
759
|
+
sage: KP = KleshchevPartitions(3,[0,1])
|
|
760
|
+
sage: KP([[4, 2], [5, 3, 1]]).good_cell_sequence()
|
|
761
|
+
[(0, 0, 0), (1, 0, 0), (1, 0, 1), (0, 0, 1), (0, 1, 0),
|
|
762
|
+
(1, 1, 0), (1, 1, 1), (1, 0, 2), (1, 2, 0), (0, 0, 2),
|
|
763
|
+
(0, 1, 1), (1, 0, 3), (0, 0, 3), (1, 1, 2), (1, 0, 4)]
|
|
764
|
+
"""
|
|
765
|
+
if self.size() == 0:
|
|
766
|
+
return []
|
|
767
|
+
good_cells = self.good_cells()
|
|
768
|
+
assert good_cells
|
|
769
|
+
|
|
770
|
+
cell = good_cells[sorted(good_cells)[0]]
|
|
771
|
+
good_seq = type(self)(self.parent(), self.remove_cell(*cell)).good_cell_sequence()
|
|
772
|
+
good_seq.append(cell)
|
|
773
|
+
return good_seq
|
|
774
|
+
|
|
775
|
+
def mullineux_conjugate(self):
|
|
776
|
+
r"""
|
|
777
|
+
Return the partition that is the Mullineux conjugate of ``self``.
|
|
778
|
+
|
|
779
|
+
It follows from results in [Kle1996]_ [Bru1998]_ that if `\nu` is the
|
|
780
|
+
Mullineux conjugate of the Kleshchev partition tuple `\mu` then the
|
|
781
|
+
simple module `D^\nu =(D^\mu)^{\text{sgn}}` is obtained from `D^\mu`
|
|
782
|
+
by twisting by the `\text{sgn}`-automorphism with is the Hecke algebra
|
|
783
|
+
analogue of tensoring with the one dimensional sign representation.
|
|
784
|
+
|
|
785
|
+
EXAMPLES::
|
|
786
|
+
|
|
787
|
+
sage: KP = KleshchevPartitions(3, [0,1])
|
|
788
|
+
sage: mc = KP([[4, 2], [5, 3, 1]]).mullineux_conjugate(); mc
|
|
789
|
+
([2, 2, 1, 1], [3, 2, 2, 1, 1])
|
|
790
|
+
sage: mc.parent()
|
|
791
|
+
Kleshchev partitions with e=3 and multicharge=(0,2)
|
|
792
|
+
"""
|
|
793
|
+
P = self.parent()
|
|
794
|
+
if self.size() == 0:
|
|
795
|
+
size = None
|
|
796
|
+
if isinstance(P, KleshchevPartitions_size):
|
|
797
|
+
size = P._size
|
|
798
|
+
KP = KleshchevPartitions(P._e, [-c for c in P._multicharge],
|
|
799
|
+
size=size, convention=P._convention)
|
|
800
|
+
return KP.element_class(KP, [[]]*P._level)
|
|
801
|
+
|
|
802
|
+
good_cells = self.good_cells()
|
|
803
|
+
assert good_cells
|
|
804
|
+
|
|
805
|
+
k,r,c = sorted(good_cells.values())[0]
|
|
806
|
+
# This is technically wrong when the parent has a fixed size because
|
|
807
|
+
# the resulting Kleshchev partition after removing a cell has abs
|
|
808
|
+
# smaller size. However, this is useful to avoid constructing
|
|
809
|
+
# transient parents.
|
|
810
|
+
mu = P.element_class(P, self.remove_cell(k,r,c)).mullineux_conjugate()
|
|
811
|
+
# add back on a cogood cell of residue -residue(k,r,c)
|
|
812
|
+
KP = mu.parent()
|
|
813
|
+
return KP.element_class(KP, mu.add_cell(*mu.cogood_cells( r-c-self.parent()._multicharge[k])))
|
|
814
|
+
|
|
815
|
+
def is_regular(self):
|
|
816
|
+
r"""
|
|
817
|
+
Return ``True`` if ``self`` is a `e`-regular partition tuple.
|
|
818
|
+
|
|
819
|
+
A partition tuple is `e`-regular if we can get to the
|
|
820
|
+
empty partition tuple by successively removing a sequence
|
|
821
|
+
of good cells in the down direction.
|
|
822
|
+
|
|
823
|
+
EXAMPLES::
|
|
824
|
+
|
|
825
|
+
sage: KP = KleshchevPartitions(2, [0,2], convention="right restricted")
|
|
826
|
+
sage: KP([[3,2,1], [2,1,1]]).is_regular()
|
|
827
|
+
False
|
|
828
|
+
sage: KP = KleshchevPartitions(4, [0,2], convention="right restricted")
|
|
829
|
+
sage: KP([[3,2,1], [2,1,1]]).is_regular()
|
|
830
|
+
True
|
|
831
|
+
sage: KP([[], []]).is_regular()
|
|
832
|
+
True
|
|
833
|
+
"""
|
|
834
|
+
if self.size() == 0:
|
|
835
|
+
return True
|
|
836
|
+
KP = self.parent()
|
|
837
|
+
return _is_regular(self.to_list(), KP._multicharge, KP._convention)
|
|
838
|
+
|
|
839
|
+
def is_restricted(self):
|
|
840
|
+
r"""
|
|
841
|
+
Return ``True`` if ``self`` is an `e`-restricted partition tuple.
|
|
842
|
+
|
|
843
|
+
A partition tuple is `e`-restricted if we can get to the
|
|
844
|
+
empty partition tuple by successively removing a sequence
|
|
845
|
+
of good cells in the up direction.
|
|
846
|
+
|
|
847
|
+
EXAMPLES::
|
|
848
|
+
|
|
849
|
+
sage: KP = KleshchevPartitions(2, [0,2], convention="left regular")
|
|
850
|
+
sage: KP([[3,2,1], [3,1]]).is_restricted()
|
|
851
|
+
False
|
|
852
|
+
sage: KP = KleshchevPartitions(3, [0,2], convention="left regular")
|
|
853
|
+
sage: KP([[3,2,1], [3,1]]).is_restricted()
|
|
854
|
+
True
|
|
855
|
+
sage: KP([[], []]).is_restricted()
|
|
856
|
+
True
|
|
857
|
+
"""
|
|
858
|
+
if self.size() == 0:
|
|
859
|
+
return True
|
|
860
|
+
KP = self.parent()
|
|
861
|
+
return _is_restricted(self.to_list(), KP._multicharge, KP._convention)
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
class KleshchevCrystalMixin:
|
|
865
|
+
"""
|
|
866
|
+
Mixin class for the crystal structure of a Kleshchev partition.
|
|
867
|
+
"""
|
|
868
|
+
|
|
869
|
+
def epsilon(self, i):
|
|
870
|
+
r"""
|
|
871
|
+
Return the Kashiwara crystal operator `\varepsilon_i` applied to ``self``.
|
|
872
|
+
|
|
873
|
+
INPUT:
|
|
874
|
+
|
|
875
|
+
- ``i`` -- an element of the index set
|
|
876
|
+
|
|
877
|
+
EXAMPLES::
|
|
878
|
+
|
|
879
|
+
sage: C = crystals.KleshchevPartitions(3, [0,2], convention="left regular")
|
|
880
|
+
sage: x = C([[5,4,1],[3,2,1,1]])
|
|
881
|
+
sage: [x.epsilon(i) for i in C.index_set()]
|
|
882
|
+
[0, 3, 0]
|
|
883
|
+
"""
|
|
884
|
+
return len(self.normal_cells(i))
|
|
885
|
+
|
|
886
|
+
def phi(self, i):
|
|
887
|
+
r"""
|
|
888
|
+
Return the Kashiwara crystal operator `\varphi_i` applied to ``self``.
|
|
889
|
+
|
|
890
|
+
INPUT:
|
|
891
|
+
|
|
892
|
+
- ``i`` -- an element of the index set
|
|
893
|
+
|
|
894
|
+
EXAMPLES::
|
|
895
|
+
|
|
896
|
+
sage: C = crystals.KleshchevPartitions(3, [0,2], convention="left regular")
|
|
897
|
+
sage: x = C([[5,4,1],[3,2,1,1]])
|
|
898
|
+
sage: [x.phi(i) for i in C.index_set()]
|
|
899
|
+
[3, 2, 0]
|
|
900
|
+
"""
|
|
901
|
+
return len(self.conormal_cells(i))
|
|
902
|
+
|
|
903
|
+
def Epsilon(self):
|
|
904
|
+
r"""
|
|
905
|
+
Return `\varepsilon` of ``self``.
|
|
906
|
+
|
|
907
|
+
EXAMPLES::
|
|
908
|
+
|
|
909
|
+
sage: C = crystals.KleshchevPartitions(3, [0,2], convention="left regular")
|
|
910
|
+
sage: x = C([[5,4,1],[3,2,1,1]])
|
|
911
|
+
sage: x.Epsilon()
|
|
912
|
+
3*Lambda[1]
|
|
913
|
+
"""
|
|
914
|
+
P = self.parent()
|
|
915
|
+
WLR = P.weight_lattice_realization()
|
|
916
|
+
La = WLR.fundamental_weights()
|
|
917
|
+
n = self.normal_cells()
|
|
918
|
+
return WLR.sum(len(n[i])*La[i] for i in P.index_set() if i in n)
|
|
919
|
+
|
|
920
|
+
def Phi(self):
|
|
921
|
+
r"""
|
|
922
|
+
Return `\phi` of ``self``.
|
|
923
|
+
|
|
924
|
+
EXAMPLES::
|
|
925
|
+
|
|
926
|
+
sage: C = crystals.KleshchevPartitions(3, [0,2], convention="left regular")
|
|
927
|
+
sage: x = C([[5,4,1],[3,2,1,1]])
|
|
928
|
+
sage: x.Phi()
|
|
929
|
+
3*Lambda[0] + 2*Lambda[1]
|
|
930
|
+
"""
|
|
931
|
+
P = self.parent()
|
|
932
|
+
WLR = P.weight_lattice_realization()
|
|
933
|
+
La = WLR.fundamental_weights()
|
|
934
|
+
c = self.conormal_cells()
|
|
935
|
+
return WLR.sum(len(c[i])*La[i] for i in P.index_set() if i in c)
|
|
936
|
+
|
|
937
|
+
def weight(self):
|
|
938
|
+
r"""
|
|
939
|
+
Return the weight of ``self``.
|
|
940
|
+
|
|
941
|
+
EXAMPLES::
|
|
942
|
+
|
|
943
|
+
sage: # needs sage.graphs
|
|
944
|
+
sage: C = crystals.KleshchevPartitions(3, [0,2], convention="left regular")
|
|
945
|
+
sage: x = C([[5,4,1], [3,2,1,1]])
|
|
946
|
+
sage: x.weight()
|
|
947
|
+
3*Lambda[0] - Lambda[1] - 5*delta
|
|
948
|
+
sage: x.Phi() - x.Epsilon()
|
|
949
|
+
3*Lambda[0] - Lambda[1]
|
|
950
|
+
|
|
951
|
+
sage: # needs sage.graphs
|
|
952
|
+
sage: C = crystals.KleshchevPartitions(3, [0,2], convention="right regular")
|
|
953
|
+
sage: y = C([[5,1,1], [4,2,2,1,1]])
|
|
954
|
+
sage: y.weight()
|
|
955
|
+
6*Lambda[0] - 4*Lambda[1] - 4*delta
|
|
956
|
+
sage: y.Phi() - y.Epsilon()
|
|
957
|
+
6*Lambda[0] - 4*Lambda[1]
|
|
958
|
+
|
|
959
|
+
sage: # needs sage.graphs
|
|
960
|
+
sage: C = crystals.KleshchevPartitions(3, [0,2], convention="left regular")
|
|
961
|
+
sage: y = C([[5,1,1], [4,2,2,1,1]])
|
|
962
|
+
sage: y.weight()
|
|
963
|
+
6*Lambda[0] - 4*Lambda[1] - 4*delta
|
|
964
|
+
sage: y.Phi() - y.Epsilon()
|
|
965
|
+
6*Lambda[0] - 4*Lambda[1]
|
|
966
|
+
"""
|
|
967
|
+
WLR = self.parent().weight_lattice_realization()
|
|
968
|
+
alpha = WLR.simple_roots()
|
|
969
|
+
La = WLR.fundamental_weights()
|
|
970
|
+
r = self.parent()._multicharge
|
|
971
|
+
wt = WLR.sum(La[ZZ(x)] for x in r)
|
|
972
|
+
return wt - WLR.sum(alpha[self.content(*c, multicharge=r)]
|
|
973
|
+
for c in self.cells())
|
|
974
|
+
|
|
975
|
+
|
|
976
|
+
class KleshchevPartitionCrystal(KleshchevPartition, KleshchevCrystalMixin):
|
|
977
|
+
"""
|
|
978
|
+
Kleshchev partition with the crystal structure.
|
|
979
|
+
"""
|
|
980
|
+
|
|
981
|
+
def e(self, i):
|
|
982
|
+
r"""
|
|
983
|
+
Return the action of `e_i` on ``self``.
|
|
984
|
+
|
|
985
|
+
INPUT:
|
|
986
|
+
|
|
987
|
+
- ``i`` -- an element of the index set
|
|
988
|
+
|
|
989
|
+
EXAMPLES::
|
|
990
|
+
|
|
991
|
+
sage: C = crystals.KleshchevPartitions(3, convention="left regular")
|
|
992
|
+
sage: x = C([5,4,1])
|
|
993
|
+
sage: x.e(0)
|
|
994
|
+
sage: x.e(1)
|
|
995
|
+
[5, 4]
|
|
996
|
+
"""
|
|
997
|
+
P = self.parent()
|
|
998
|
+
cell = self.good_cells(i)
|
|
999
|
+
if cell is None:
|
|
1000
|
+
return None
|
|
1001
|
+
r, _ = cell
|
|
1002
|
+
mu = list(self)
|
|
1003
|
+
mu[r] -= 1
|
|
1004
|
+
return type(self)(P, mu)
|
|
1005
|
+
|
|
1006
|
+
def f(self, i):
|
|
1007
|
+
r"""
|
|
1008
|
+
Return the action of `f_i` on ``self``.
|
|
1009
|
+
|
|
1010
|
+
INPUT:
|
|
1011
|
+
|
|
1012
|
+
- ``i`` -- an element of the index set
|
|
1013
|
+
|
|
1014
|
+
EXAMPLES::
|
|
1015
|
+
|
|
1016
|
+
sage: C = crystals.KleshchevPartitions(3, convention="left regular")
|
|
1017
|
+
sage: x = C([5,4,1])
|
|
1018
|
+
sage: x.f(0)
|
|
1019
|
+
[5, 5, 1]
|
|
1020
|
+
sage: x.f(1)
|
|
1021
|
+
sage: x.f(2)
|
|
1022
|
+
[5, 4, 2]
|
|
1023
|
+
"""
|
|
1024
|
+
P = self.parent()
|
|
1025
|
+
cell = self.cogood_cells(i)
|
|
1026
|
+
if cell is None:
|
|
1027
|
+
return None
|
|
1028
|
+
r,c = cell
|
|
1029
|
+
mu = list(self)
|
|
1030
|
+
if c == 0:
|
|
1031
|
+
mu.append(1)
|
|
1032
|
+
else:
|
|
1033
|
+
mu[r] += 1
|
|
1034
|
+
return type(self)(P, mu)
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
class KleshchevPartitionTupleCrystal(KleshchevPartitionTuple, KleshchevCrystalMixin):
|
|
1038
|
+
"""
|
|
1039
|
+
Kleshchev partition tuple with the crystal structure.
|
|
1040
|
+
"""
|
|
1041
|
+
|
|
1042
|
+
def e(self, i):
|
|
1043
|
+
r"""
|
|
1044
|
+
Return the action of `e_i` on ``self``.
|
|
1045
|
+
|
|
1046
|
+
INPUT:
|
|
1047
|
+
|
|
1048
|
+
- ``i`` -- an element of the index set
|
|
1049
|
+
|
|
1050
|
+
EXAMPLES::
|
|
1051
|
+
|
|
1052
|
+
sage: C = crystals.KleshchevPartitions(3, [0,2], convention="left regular")
|
|
1053
|
+
sage: x = C([[5,4,1],[3,2,1,1]])
|
|
1054
|
+
sage: x.e(0)
|
|
1055
|
+
sage: x.e(1)
|
|
1056
|
+
([5, 4, 1], [2, 2, 1, 1])
|
|
1057
|
+
"""
|
|
1058
|
+
P = self.parent()
|
|
1059
|
+
cell = self.good_cells(i)
|
|
1060
|
+
if cell is None:
|
|
1061
|
+
return None
|
|
1062
|
+
k, r, _ = cell
|
|
1063
|
+
mu = self.to_list()
|
|
1064
|
+
mu[k][r] -= 1
|
|
1065
|
+
return type(self)(P, mu)
|
|
1066
|
+
|
|
1067
|
+
def f(self, i):
|
|
1068
|
+
r"""
|
|
1069
|
+
Return the action of `f_i` on ``self``.
|
|
1070
|
+
|
|
1071
|
+
INPUT:
|
|
1072
|
+
|
|
1073
|
+
- ``i`` -- an element of the index set
|
|
1074
|
+
|
|
1075
|
+
EXAMPLES::
|
|
1076
|
+
|
|
1077
|
+
sage: C = crystals.KleshchevPartitions(3, [0,2], convention="left regular")
|
|
1078
|
+
sage: x = C([[5,4,1],[3,2,1,1]])
|
|
1079
|
+
sage: x.f(0)
|
|
1080
|
+
([5, 5, 1], [3, 2, 1, 1])
|
|
1081
|
+
sage: x.f(1)
|
|
1082
|
+
([5, 4, 1], [3, 2, 2, 1])
|
|
1083
|
+
sage: x.f(2)
|
|
1084
|
+
"""
|
|
1085
|
+
P = self.parent()
|
|
1086
|
+
cell = self.cogood_cells(i)
|
|
1087
|
+
if cell is None:
|
|
1088
|
+
return None
|
|
1089
|
+
k,r,c = cell
|
|
1090
|
+
mu = self.to_list()
|
|
1091
|
+
if c == 0:
|
|
1092
|
+
mu[k].append(1)
|
|
1093
|
+
else:
|
|
1094
|
+
mu[k][r] += 1
|
|
1095
|
+
return type(self)(P, mu)
|
|
1096
|
+
|
|
1097
|
+
#--------------------------------------------------
|
|
1098
|
+
# Kleshchev partitions - parent classes
|
|
1099
|
+
#--------------------------------------------------
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
class KleshchevPartitions(PartitionTuples):
|
|
1103
|
+
r"""
|
|
1104
|
+
Kleshchev partitions.
|
|
1105
|
+
|
|
1106
|
+
A partition (tuple) `\mu` is Kleshchev if it can be recursively
|
|
1107
|
+
obtained by adding a sequence of good nodes to the empty
|
|
1108
|
+
:class:`PartitionTuple` of the same :meth:`~PartitionTuple.level`
|
|
1109
|
+
and multicharge.
|
|
1110
|
+
|
|
1111
|
+
There are four different conventions that are used in the literature for
|
|
1112
|
+
Kleshchev partitions, depending on whether we read partitions from top
|
|
1113
|
+
to bottom (regular) or bottom to top (restricted) and whether we read
|
|
1114
|
+
partition tuples from left to right or right to left. All of these
|
|
1115
|
+
conventions are supported::
|
|
1116
|
+
|
|
1117
|
+
sage: KleshchevPartitions(2, [0,0], size=2, convention='left regular')[:]
|
|
1118
|
+
[([1], [1]), ([2], [])]
|
|
1119
|
+
sage: KleshchevPartitions(2, [0,0], size=2, convention='left restricted')[:]
|
|
1120
|
+
[([1], [1]), ([], [1, 1])]
|
|
1121
|
+
sage: KleshchevPartitions(2, [0,0], size=2, convention='right regular')[:]
|
|
1122
|
+
[([1], [1]), ([], [2])]
|
|
1123
|
+
sage: KleshchevPartitions(2, [0,0], size=2, convention='right restricted')[:]
|
|
1124
|
+
[([1], [1]), ([1, 1], [])]
|
|
1125
|
+
|
|
1126
|
+
By default, the ``left restricted`` convention is used. As a shorthand,
|
|
1127
|
+
``LG``, ``LS``, ``RG`` and ``RS``, respectively, can be used to specify
|
|
1128
|
+
the ``convention``. With the ``left`` convention the partition tuples
|
|
1129
|
+
should be ordered with the most dominant partitions in the partition
|
|
1130
|
+
tuple on the left and with the ``right`` convention the most dominant
|
|
1131
|
+
partition is on the right.
|
|
1132
|
+
|
|
1133
|
+
The :class:`~KleshchevPartitions` class will automatically convert
|
|
1134
|
+
between these four different conventions::
|
|
1135
|
+
|
|
1136
|
+
sage: KPlg = KleshchevPartitions(2, [0,0], size=2, convention='left regular')
|
|
1137
|
+
sage: KPls = KleshchevPartitions(2, [0,0], size=2, convention='left restricted')
|
|
1138
|
+
sage: [KPlg(mu) for mu in KPls]
|
|
1139
|
+
[([1], [1]), ([2], [])]
|
|
1140
|
+
|
|
1141
|
+
EXAMPLES::
|
|
1142
|
+
|
|
1143
|
+
sage: sorted(KleshchevPartitions(5,[3,2,1],1, convention='RS'))
|
|
1144
|
+
[([], [], [1]), ([], [1], []), ([1], [], [])]
|
|
1145
|
+
sage: sorted(KleshchevPartitions(5, [3,2,1], 1, convention='LS'))
|
|
1146
|
+
[([], [], [1]), ([], [1], []), ([1], [], [])]
|
|
1147
|
+
sage: sorted(KleshchevPartitions(5, [3,2,1], 3))
|
|
1148
|
+
[([], [], [1, 1, 1]),
|
|
1149
|
+
([], [], [2, 1]),
|
|
1150
|
+
([], [], [3]),
|
|
1151
|
+
([], [1], [1, 1]),
|
|
1152
|
+
([], [1], [2]),
|
|
1153
|
+
([], [1, 1], [1]),
|
|
1154
|
+
([], [2], [1]),
|
|
1155
|
+
([], [3], []),
|
|
1156
|
+
([1], [], [1, 1]),
|
|
1157
|
+
([1], [], [2]),
|
|
1158
|
+
([1], [1], [1]),
|
|
1159
|
+
([1], [2], []),
|
|
1160
|
+
([1, 1], [1], []),
|
|
1161
|
+
([2], [], [1]),
|
|
1162
|
+
([2], [1], []),
|
|
1163
|
+
([3], [], [])]
|
|
1164
|
+
sage: sorted(KleshchevPartitions(5, [3,2,1], 3, convention="left regular"))
|
|
1165
|
+
[([], [], [1, 1, 1]),
|
|
1166
|
+
([], [1], [1, 1]),
|
|
1167
|
+
([], [1], [2]),
|
|
1168
|
+
([], [1, 1], [1]),
|
|
1169
|
+
([], [1, 1, 1], []),
|
|
1170
|
+
([1], [], [1, 1]),
|
|
1171
|
+
([1], [1], [1]),
|
|
1172
|
+
([1], [1, 1], []),
|
|
1173
|
+
([1], [2], []),
|
|
1174
|
+
([1, 1], [], [1]),
|
|
1175
|
+
([1, 1], [1], []),
|
|
1176
|
+
([1, 1, 1], [], []),
|
|
1177
|
+
([2], [], [1]),
|
|
1178
|
+
([2], [1], []),
|
|
1179
|
+
([2, 1], [], []),
|
|
1180
|
+
([3], [], [])]
|
|
1181
|
+
|
|
1182
|
+
REFERENCES:
|
|
1183
|
+
|
|
1184
|
+
- [AM2000]_
|
|
1185
|
+
- [Ariki2001]_
|
|
1186
|
+
- [BK2009]_
|
|
1187
|
+
- [Kle2009]_
|
|
1188
|
+
"""
|
|
1189
|
+
@staticmethod
|
|
1190
|
+
def __classcall_private__(cls, e, multicharge=(0,), size=None,
|
|
1191
|
+
convention="left restricted"):
|
|
1192
|
+
r"""
|
|
1193
|
+
This is a factory class which returns the appropriate parent based on
|
|
1194
|
+
the values of `level` and `size`.
|
|
1195
|
+
|
|
1196
|
+
EXAMPLES::
|
|
1197
|
+
|
|
1198
|
+
sage: sorted(KleshchevPartitions(5, [3,2,1], 1, convention='RS'))
|
|
1199
|
+
[([], [], [1]), ([], [1], []), ([1], [], [])]
|
|
1200
|
+
sage: sorted(KleshchevPartitions(5, [3,2,1], 1, convention='LS'))
|
|
1201
|
+
[([], [], [1]), ([], [1], []), ([1], [], [])]
|
|
1202
|
+
"""
|
|
1203
|
+
if size is None and multicharge in ZZ:
|
|
1204
|
+
size = ZZ(multicharge)
|
|
1205
|
+
multicharge = (0,)
|
|
1206
|
+
|
|
1207
|
+
I = IntegerModRing(e)
|
|
1208
|
+
multicharge = tuple([I(x) for x in multicharge])
|
|
1209
|
+
|
|
1210
|
+
convention = convention.upper()
|
|
1211
|
+
if 'S' in convention:
|
|
1212
|
+
convention = convention[0] + 'S'
|
|
1213
|
+
elif 'G' in convention:
|
|
1214
|
+
convention = convention[0] + 'G'
|
|
1215
|
+
if convention not in ['RG','LG', 'RS', 'LS']:
|
|
1216
|
+
raise ValueError('invalid convention')
|
|
1217
|
+
|
|
1218
|
+
if size is None:
|
|
1219
|
+
return KleshchevPartitions_all(e, multicharge, convention)
|
|
1220
|
+
|
|
1221
|
+
return KleshchevPartitions_size(e, multicharge, size, convention)
|
|
1222
|
+
|
|
1223
|
+
def multicharge(self):
|
|
1224
|
+
"""
|
|
1225
|
+
Return the multicharge of ``self``.
|
|
1226
|
+
|
|
1227
|
+
EXAMPLES::
|
|
1228
|
+
|
|
1229
|
+
sage: KP = KleshchevPartitions(6, [2])
|
|
1230
|
+
sage: KP.multicharge()
|
|
1231
|
+
(2,)
|
|
1232
|
+
sage: KP = KleshchevPartitions(5, [3,0,1], 1, convention='LS')
|
|
1233
|
+
sage: KP.multicharge()
|
|
1234
|
+
(3, 0, 1)
|
|
1235
|
+
"""
|
|
1236
|
+
return self._multicharge
|
|
1237
|
+
|
|
1238
|
+
def convention(self):
|
|
1239
|
+
"""
|
|
1240
|
+
Return the convention of ``self``.
|
|
1241
|
+
|
|
1242
|
+
EXAMPLES::
|
|
1243
|
+
|
|
1244
|
+
sage: KP = KleshchevPartitions(4)
|
|
1245
|
+
sage: KP.convention()
|
|
1246
|
+
'restricted'
|
|
1247
|
+
sage: KP = KleshchevPartitions(6, [4], 3, convention="right regular")
|
|
1248
|
+
sage: KP.convention()
|
|
1249
|
+
'regular'
|
|
1250
|
+
sage: KP = KleshchevPartitions(5, [3,0,1], 1)
|
|
1251
|
+
sage: KP.convention()
|
|
1252
|
+
'left restricted'
|
|
1253
|
+
sage: KP = KleshchevPartitions(5, [3,0,1], 1, convention='right regular')
|
|
1254
|
+
sage: KP.convention()
|
|
1255
|
+
'right regular'
|
|
1256
|
+
"""
|
|
1257
|
+
if self._convention[1] == 'S':
|
|
1258
|
+
convention = "restricted"
|
|
1259
|
+
else:
|
|
1260
|
+
convention = "regular"
|
|
1261
|
+
|
|
1262
|
+
if self._level == 1:
|
|
1263
|
+
return convention
|
|
1264
|
+
|
|
1265
|
+
if self._convention[0] == 'R':
|
|
1266
|
+
return "right " + convention
|
|
1267
|
+
|
|
1268
|
+
return "left " + convention
|
|
1269
|
+
|
|
1270
|
+
def _element_constructor_(self, mu):
|
|
1271
|
+
r"""
|
|
1272
|
+
Return ``mu`` as an element of :class:`~KleshchevPartitions`, or
|
|
1273
|
+
or raise an error if ``mu`` is not a Kleshchev partition (tuple).
|
|
1274
|
+
|
|
1275
|
+
The main purpose of the element constructor code is to allow automatic
|
|
1276
|
+
conversion between the four possible conventions for Kleshchev
|
|
1277
|
+
partitions.
|
|
1278
|
+
|
|
1279
|
+
EXAMPLES::
|
|
1280
|
+
|
|
1281
|
+
sage: KPlg = KleshchevPartitions(2, [0,0], size=2, convention='left regular')
|
|
1282
|
+
sage: KPls = KleshchevPartitions(2, [0,0], size=2, convention='left restricted')
|
|
1283
|
+
sage: [KPlg(mu) for mu in KPls] # indirect doc test
|
|
1284
|
+
[([1], [1]), ([2], [])]
|
|
1285
|
+
"""
|
|
1286
|
+
if isinstance(mu, (KleshchevPartition, KleshchevPartitionTuple)):
|
|
1287
|
+
KPmu = mu.parent()
|
|
1288
|
+
if KPmu == self:
|
|
1289
|
+
return mu
|
|
1290
|
+
|
|
1291
|
+
if KPmu._level != self._level or KPmu._e != self._e:
|
|
1292
|
+
raise ValueError('%s is not an element of %s' % (mu, self))
|
|
1293
|
+
|
|
1294
|
+
if KPmu._convention[1] != self._convention[1]:
|
|
1295
|
+
mu = [nu.conjugate() for nu in mu]
|
|
1296
|
+
if self._level > 1 and KPmu._convention[0] == self._convention[0]:
|
|
1297
|
+
mu = mu[::-1]
|
|
1298
|
+
|
|
1299
|
+
return super()._element_constructor_(mu)
|
|
1300
|
+
|
|
1301
|
+
|
|
1302
|
+
class KleshchevPartitions_all(KleshchevPartitions):
|
|
1303
|
+
r"""
|
|
1304
|
+
Class of all Kleshchev partitions.
|
|
1305
|
+
|
|
1306
|
+
.. RUBRIC:: Crystal structure
|
|
1307
|
+
|
|
1308
|
+
We consider type `A_{e-1}^{(1)}` crystals, and let `r = (r_i |
|
|
1309
|
+
r_i \in \ZZ / e \ZZ)` be a finite sequence of length `k`, which
|
|
1310
|
+
is the *level*, and `\lambda = \sum_i \Lambda_{r_i}`. We will
|
|
1311
|
+
model the highest weight `U_q(\mathfrak{g})`-crystal `B(\lambda)`
|
|
1312
|
+
by a particular subset of partition tuples of level `k`.
|
|
1313
|
+
|
|
1314
|
+
Consider a partition tuple `\mu` with multicharge `r`.
|
|
1315
|
+
We define `e_i(\mu)` as the partition tuple obtained after the
|
|
1316
|
+
deletion of the `i`-:meth:`good cell
|
|
1317
|
+
<~sage.combinat.partition_kleshchev.KleshchevPartitionTuple.good_cell>`
|
|
1318
|
+
to `\mu` and `0` if there is no `i`-good cell. We define `f_i(\mu)` as
|
|
1319
|
+
the partition tuple obtained by the addition of the `i`-:meth:`cogood cell
|
|
1320
|
+
<~sage.combinat.partition_kleshchev.KleshchevPartitionTuple.cogood_cell>`
|
|
1321
|
+
to `\mu` and `0` if there is no `i`-good cell.
|
|
1322
|
+
|
|
1323
|
+
The crystal `B(\lambda)` is the crystal generated by the empty
|
|
1324
|
+
partition tuple. We can compute the weight of an element `\mu` by taking
|
|
1325
|
+
`\lambda - \sum_{i=0}^n c_i \alpha_i` where `c_i` is the number of cells
|
|
1326
|
+
of `n`-residue `i` in `\mu`. Partition tuples in the crystal are known
|
|
1327
|
+
as *Kleshchev partitions*.
|
|
1328
|
+
|
|
1329
|
+
.. NOTE::
|
|
1330
|
+
|
|
1331
|
+
We can describe normal (not restricted) Kleshchev partition tuples
|
|
1332
|
+
in `B(\lambda)` as partition tuples `\mu` such that
|
|
1333
|
+
`\mu^{(t)}_{r_t - r_{t+1} + x} < \mu^{(t+1)}_x`
|
|
1334
|
+
for all `x \geq 1` and `1 \leq t \leq k - 1`.
|
|
1335
|
+
|
|
1336
|
+
INPUT:
|
|
1337
|
+
|
|
1338
|
+
- ``e`` -- for type `A_{e-1}^{(1)}` or `0`
|
|
1339
|
+
- ``multicharge`` -- the multicharge sequence `r`
|
|
1340
|
+
- ``convention`` -- (default: ``'LS'``) the reading convention
|
|
1341
|
+
|
|
1342
|
+
EXAMPLES:
|
|
1343
|
+
|
|
1344
|
+
We first do an example of a level 1 crystal::
|
|
1345
|
+
|
|
1346
|
+
sage: C = crystals.KleshchevPartitions(3, [0], convention="left restricted")
|
|
1347
|
+
sage: C
|
|
1348
|
+
Kleshchev partitions with e=3
|
|
1349
|
+
sage: mg = C.highest_weight_vector()
|
|
1350
|
+
sage: mg
|
|
1351
|
+
[]
|
|
1352
|
+
sage: mg.f(0)
|
|
1353
|
+
[1]
|
|
1354
|
+
sage: mg.f(1)
|
|
1355
|
+
sage: mg.f(2)
|
|
1356
|
+
sage: mg.f_string([0,2,1,0])
|
|
1357
|
+
[1, 1, 1, 1]
|
|
1358
|
+
sage: mg.f_string([0,1,2,0])
|
|
1359
|
+
[2, 2]
|
|
1360
|
+
sage: GC = C.subcrystal(max_depth=5).digraph() # needs sage.graphs
|
|
1361
|
+
sage: B = crystals.LSPaths(['A',2,1], [1,0,0]) # needs sage.graphs
|
|
1362
|
+
sage: GB = B.subcrystal(max_depth=5).digraph() # needs sage.graphs
|
|
1363
|
+
sage: GC.is_isomorphic(GB, edge_labels=True) # needs sage.graphs
|
|
1364
|
+
True
|
|
1365
|
+
|
|
1366
|
+
Now a higher level crystal::
|
|
1367
|
+
|
|
1368
|
+
sage: C = crystals.KleshchevPartitions(3, [0,2], convention="right restricted")
|
|
1369
|
+
sage: mg = C.highest_weight_vector()
|
|
1370
|
+
sage: mg
|
|
1371
|
+
([], [])
|
|
1372
|
+
sage: mg.f(0)
|
|
1373
|
+
([1], [])
|
|
1374
|
+
sage: mg.f(2)
|
|
1375
|
+
([], [1])
|
|
1376
|
+
sage: mg.f_string([0,1,2,0])
|
|
1377
|
+
([2, 2], [])
|
|
1378
|
+
sage: mg.f_string([0,2,1,0])
|
|
1379
|
+
([1, 1, 1, 1], [])
|
|
1380
|
+
sage: mg.f_string([2,0,1,0])
|
|
1381
|
+
([2], [2])
|
|
1382
|
+
sage: GC = C.subcrystal(max_depth=5).digraph() # needs sage.graphs
|
|
1383
|
+
sage: B = crystals.LSPaths(['A',2,1], [1,0,1]) # needs sage.graphs
|
|
1384
|
+
sage: GB = B.subcrystal(max_depth=5).digraph() # needs sage.graphs
|
|
1385
|
+
sage: GC.is_isomorphic(GB, edge_labels=True) # needs sage.graphs
|
|
1386
|
+
True
|
|
1387
|
+
|
|
1388
|
+
The ordering of the residues gives a different representation of the
|
|
1389
|
+
higher level crystals (but it is still isomorphic)::
|
|
1390
|
+
|
|
1391
|
+
sage: C2 = crystals.KleshchevPartitions(3, [2,0], convention="right restricted")
|
|
1392
|
+
sage: mg2 = C2.highest_weight_vector()
|
|
1393
|
+
sage: mg2.f_string([0,1,2,0])
|
|
1394
|
+
([2], [2])
|
|
1395
|
+
sage: mg2.f_string([0,2,1,0])
|
|
1396
|
+
([1, 1, 1], [1])
|
|
1397
|
+
sage: mg2.f_string([2,0,1,0])
|
|
1398
|
+
([2, 1], [1])
|
|
1399
|
+
sage: GC2 = C2.subcrystal(max_depth=5).digraph() # needs sage.graphs
|
|
1400
|
+
sage: GC.is_isomorphic(GC2, edge_labels=True) # needs sage.graphs
|
|
1401
|
+
True
|
|
1402
|
+
|
|
1403
|
+
TESTS:
|
|
1404
|
+
|
|
1405
|
+
We check that all conventions give isomorphic crystals::
|
|
1406
|
+
|
|
1407
|
+
sage: CLS = crystals.KleshchevPartitions(3, [2,0], convention="left restricted")
|
|
1408
|
+
sage: CRS = crystals.KleshchevPartitions(3, [2,0], convention="right restricted")
|
|
1409
|
+
sage: CLG = crystals.KleshchevPartitions(3, [2,0], convention="left regular")
|
|
1410
|
+
sage: CRG = crystals.KleshchevPartitions(3, [2,0], convention="right regular")
|
|
1411
|
+
sage: C = [CLS, CRS, CLG, CRG]
|
|
1412
|
+
sage: G = [B.subcrystal(max_depth=6).digraph() for B in C] # needs sage.graphs
|
|
1413
|
+
sage: G[0].is_isomorphic(G[1], edge_labels=True) # needs sage.graphs
|
|
1414
|
+
True
|
|
1415
|
+
sage: G[0].is_isomorphic(G[2], edge_labels=True) # needs sage.graphs
|
|
1416
|
+
True
|
|
1417
|
+
sage: G[0].is_isomorphic(G[3], edge_labels=True) # needs sage.graphs
|
|
1418
|
+
True
|
|
1419
|
+
|
|
1420
|
+
REFERENCES:
|
|
1421
|
+
|
|
1422
|
+
- [Ariki1996]_
|
|
1423
|
+
- [Ariki2001]_
|
|
1424
|
+
- [Tingley2007]_
|
|
1425
|
+
- [TingleyLN]_
|
|
1426
|
+
- [Vazirani2002]_
|
|
1427
|
+
"""
|
|
1428
|
+
|
|
1429
|
+
def __init__(self, e, multicharge, convention):
|
|
1430
|
+
r"""
|
|
1431
|
+
Initialize ``self``.
|
|
1432
|
+
|
|
1433
|
+
EXAMPLES::
|
|
1434
|
+
|
|
1435
|
+
sage: K = KleshchevPartitions(4, [2])
|
|
1436
|
+
sage: TestSuite(K).run() # long time
|
|
1437
|
+
sage: K = KleshchevPartitions(4, [0,2,1])
|
|
1438
|
+
sage: TestSuite(K).run() # long time
|
|
1439
|
+
|
|
1440
|
+
sage: K = KleshchevPartitions(0, [2])
|
|
1441
|
+
sage: TestSuite(K).run()
|
|
1442
|
+
sage: K = KleshchevPartitions(0, [0,2,1])
|
|
1443
|
+
sage: TestSuite(K).run() # long time
|
|
1444
|
+
"""
|
|
1445
|
+
if e not in NN or e == 1:
|
|
1446
|
+
raise ValueError('e must belong to {0,2,3,4,5,6,...}')
|
|
1447
|
+
if e > 0:
|
|
1448
|
+
from sage.combinat.root_system.cartan_type import CartanType
|
|
1449
|
+
from sage.categories.highest_weight_crystals import HighestWeightCrystals
|
|
1450
|
+
from sage.categories.regular_crystals import RegularCrystals
|
|
1451
|
+
self._cartan_type = CartanType(['A', e-1, 1])
|
|
1452
|
+
cat = (HighestWeightCrystals(), RegularCrystals().Infinite())
|
|
1453
|
+
else:
|
|
1454
|
+
cat = InfiniteEnumeratedSets()
|
|
1455
|
+
|
|
1456
|
+
self._level = len(multicharge)
|
|
1457
|
+
if self._level == 1:
|
|
1458
|
+
self.Element = KleshchevPartitionCrystal
|
|
1459
|
+
self._element_constructor_ = getattr_from_other_class(self, Partitions, '_element_constructor_')
|
|
1460
|
+
else:
|
|
1461
|
+
self.Element = KleshchevPartitionTupleCrystal
|
|
1462
|
+
|
|
1463
|
+
super().__init__(category=cat)
|
|
1464
|
+
self._e = e # for printing
|
|
1465
|
+
self._index_set = IntegerModRing(e)
|
|
1466
|
+
self._multicharge = multicharge
|
|
1467
|
+
self._convention = convention
|
|
1468
|
+
if e > 0:
|
|
1469
|
+
if self._level == 1:
|
|
1470
|
+
self.module_generators = (self.element_class(self, []),)
|
|
1471
|
+
else:
|
|
1472
|
+
self.module_generators = (self.element_class(self, [[]]*self._level),)
|
|
1473
|
+
|
|
1474
|
+
def _repr_(self):
|
|
1475
|
+
"""
|
|
1476
|
+
EXAMPLES::
|
|
1477
|
+
|
|
1478
|
+
sage: KleshchevPartitions(4, [2])
|
|
1479
|
+
Kleshchev partitions with e=4
|
|
1480
|
+
sage: KleshchevPartitions(3,[0,0,0])
|
|
1481
|
+
Kleshchev partitions with e=3 and multicharge=(0,0,0)
|
|
1482
|
+
sage: KleshchevPartitions(3,[0,0,1])
|
|
1483
|
+
Kleshchev partitions with e=3 and multicharge=(0,0,1)
|
|
1484
|
+
"""
|
|
1485
|
+
if self._level == 1:
|
|
1486
|
+
return 'Kleshchev partitions with e=%s' % (self._e)
|
|
1487
|
+
|
|
1488
|
+
return 'Kleshchev partitions with e=%s and multicharge=(%s)' % (
|
|
1489
|
+
self._e,','.join('%s' % m for m in self._multicharge))
|
|
1490
|
+
|
|
1491
|
+
def __contains__(self, mu):
|
|
1492
|
+
"""
|
|
1493
|
+
Containment test for Kleshchev partitions.
|
|
1494
|
+
|
|
1495
|
+
EXAMPLES::
|
|
1496
|
+
|
|
1497
|
+
sage: PartitionTuple([[3,2],[2]]) in KleshchevPartitions(2, [0,0], 7)
|
|
1498
|
+
False
|
|
1499
|
+
sage: PartitionTuple([[],[2,1],[3,2]]) in KleshchevPartitions(5, [0,0,1], 7)
|
|
1500
|
+
False
|
|
1501
|
+
sage: PartitionTuple([[],[2,1],[3,2]]) in KleshchevPartitions(5, [0,1,1], 7)
|
|
1502
|
+
False
|
|
1503
|
+
sage: PartitionTuple([[],[2,1],[3,2]]) in KleshchevPartitions(5, [0,1,1], 8)
|
|
1504
|
+
True
|
|
1505
|
+
sage: all(mu in PartitionTuples(3,8) for mu in KleshchevPartitions(2, [0,0,0], 8))
|
|
1506
|
+
True
|
|
1507
|
+
"""
|
|
1508
|
+
if isinstance(mu, (KleshchevPartition, KleshchevPartitionTuple)):
|
|
1509
|
+
if mu.level() != self._level:
|
|
1510
|
+
return False
|
|
1511
|
+
mu = self.element_class(self, list(mu))
|
|
1512
|
+
if self._convention[1] == 'G':
|
|
1513
|
+
return mu.is_regular()
|
|
1514
|
+
|
|
1515
|
+
return mu.is_restricted()
|
|
1516
|
+
|
|
1517
|
+
try:
|
|
1518
|
+
mu = self.element_class(self, mu)
|
|
1519
|
+
except ValueError:
|
|
1520
|
+
return False
|
|
1521
|
+
return mu in self
|
|
1522
|
+
|
|
1523
|
+
def __iter__(self):
|
|
1524
|
+
r"""
|
|
1525
|
+
Iterate over ``self``.
|
|
1526
|
+
|
|
1527
|
+
EXAMPLES::
|
|
1528
|
+
|
|
1529
|
+
sage: it = iter(KleshchevPartitions(2))
|
|
1530
|
+
sage: [next(it) for _ in range(10)]
|
|
1531
|
+
[[], [1], [1, 1], [2, 1], [1, 1, 1], [2, 1, 1],
|
|
1532
|
+
[1, 1, 1, 1], [2, 2, 1], [2, 1, 1, 1], [1, 1, 1, 1, 1]]
|
|
1533
|
+
sage: it = iter(KleshchevPartitions(2, convention='LG'))
|
|
1534
|
+
sage: [next(it) for _ in range(10)]
|
|
1535
|
+
[[], [1], [2], [3], [2, 1], [4], [3, 1], [5], [4, 1], [3, 2]]
|
|
1536
|
+
|
|
1537
|
+
sage: it = iter(KleshchevPartitions(2, [0,1], convention='LS'))
|
|
1538
|
+
sage: [next(it) for _ in range(10)]
|
|
1539
|
+
[([], []),
|
|
1540
|
+
([1], []),
|
|
1541
|
+
([], [1]),
|
|
1542
|
+
([1], [1]),
|
|
1543
|
+
([], [1, 1]),
|
|
1544
|
+
([1, 1], [1]),
|
|
1545
|
+
([1], [1, 1]),
|
|
1546
|
+
([], [2, 1]),
|
|
1547
|
+
([], [1, 1, 1]),
|
|
1548
|
+
([2, 1], [1])]
|
|
1549
|
+
sage: it = iter(KleshchevPartitions(2, [0,1], convention='RS'))
|
|
1550
|
+
sage: [next(it) for _ in range(10)]
|
|
1551
|
+
[([], []),
|
|
1552
|
+
([1], []),
|
|
1553
|
+
([], [1]),
|
|
1554
|
+
([1, 1], []),
|
|
1555
|
+
([1], [1]),
|
|
1556
|
+
([2, 1], []),
|
|
1557
|
+
([1, 1, 1], []),
|
|
1558
|
+
([1, 1], [1]),
|
|
1559
|
+
([1], [1, 1]),
|
|
1560
|
+
([2, 1, 1], [])]
|
|
1561
|
+
sage: it = iter(KleshchevPartitions(2, [0,1], convention='LG'))
|
|
1562
|
+
sage: [next(it) for _ in range(10)]
|
|
1563
|
+
[([], []),
|
|
1564
|
+
([1], []),
|
|
1565
|
+
([], [1]),
|
|
1566
|
+
([2], []),
|
|
1567
|
+
([1], [1]),
|
|
1568
|
+
([3], []),
|
|
1569
|
+
([2, 1], []),
|
|
1570
|
+
([2], [1]),
|
|
1571
|
+
([1], [2]),
|
|
1572
|
+
([4], [])]
|
|
1573
|
+
sage: it = iter(KleshchevPartitions(2, [0,1], convention='RG'))
|
|
1574
|
+
sage: [next(it) for _ in range(10)]
|
|
1575
|
+
[([], []),
|
|
1576
|
+
([1], []),
|
|
1577
|
+
([], [1]),
|
|
1578
|
+
([1], [1]),
|
|
1579
|
+
([], [2]),
|
|
1580
|
+
([2], [1]),
|
|
1581
|
+
([1], [2]),
|
|
1582
|
+
([], [3]),
|
|
1583
|
+
([], [2, 1]),
|
|
1584
|
+
([2, 1], [1])]
|
|
1585
|
+
|
|
1586
|
+
sage: it = iter(KleshchevPartitions(3, [0,1,2]))
|
|
1587
|
+
sage: [next(it) for _ in range(10)]
|
|
1588
|
+
[([], [], []), ([1], [], []), ([], [1], []), ([], [], [1]),
|
|
1589
|
+
([1], [1], []), ([1], [], [1]), ([], [1, 1], []),
|
|
1590
|
+
([], [1], [1]), ([], [], [2]), ([], [], [1, 1])]
|
|
1591
|
+
"""
|
|
1592
|
+
# This is a modified form of what appears in the fixed size code
|
|
1593
|
+
if self._level == 1:
|
|
1594
|
+
if self._e == 0:
|
|
1595
|
+
P = Partitions()
|
|
1596
|
+
elif self._convention[1] == 'G':
|
|
1597
|
+
P = Partitions(regular=self._e)
|
|
1598
|
+
else:
|
|
1599
|
+
P = Partitions(restricted=self._e)
|
|
1600
|
+
|
|
1601
|
+
for mu in P:
|
|
1602
|
+
yield self.element_class(self, list(mu))
|
|
1603
|
+
else:
|
|
1604
|
+
next_level = [self.element_class(self, [[]]*len(self._multicharge))]
|
|
1605
|
+
while True:
|
|
1606
|
+
cur = next_level
|
|
1607
|
+
next_level = []
|
|
1608
|
+
for mu in cur:
|
|
1609
|
+
yield mu
|
|
1610
|
+
mu_list = mu.to_list()
|
|
1611
|
+
for cell in sorted(mu.cogood_cells().values()):
|
|
1612
|
+
data = [list(p) for p in mu_list]
|
|
1613
|
+
k, r, c = cell
|
|
1614
|
+
if c == 0:
|
|
1615
|
+
data[k].append(1)
|
|
1616
|
+
else:
|
|
1617
|
+
data[k][r] += 1
|
|
1618
|
+
nu = self.element_class(self, data)
|
|
1619
|
+
good_cells = nu.good_cells().values()
|
|
1620
|
+
if self._convention[1] == "S":
|
|
1621
|
+
if all(cell >= c for c in good_cells):
|
|
1622
|
+
next_level.append(nu)
|
|
1623
|
+
else:
|
|
1624
|
+
if all(cell <= c for c in good_cells):
|
|
1625
|
+
next_level.append(nu)
|
|
1626
|
+
|
|
1627
|
+
def _an_element_(self):
|
|
1628
|
+
"""
|
|
1629
|
+
Return a generic element.
|
|
1630
|
+
|
|
1631
|
+
EXAMPLES::
|
|
1632
|
+
|
|
1633
|
+
sage: KleshchevPartitions(3, [0,0,0,0], size=4).an_element()
|
|
1634
|
+
([1], [1], [1], [1])
|
|
1635
|
+
"""
|
|
1636
|
+
return self[12]
|
|
1637
|
+
|
|
1638
|
+
|
|
1639
|
+
class KleshchevPartitions_size(KleshchevPartitions):
|
|
1640
|
+
"""
|
|
1641
|
+
Kleshchev partitions of a fixed size.
|
|
1642
|
+
"""
|
|
1643
|
+
|
|
1644
|
+
def __init__(self, e, multicharge=(0,), size=0, convention='RS'):
|
|
1645
|
+
r"""
|
|
1646
|
+
Initialize ``self``.
|
|
1647
|
+
|
|
1648
|
+
EXAMPLES::
|
|
1649
|
+
|
|
1650
|
+
sage: K = KleshchevPartitions(4, 2)
|
|
1651
|
+
sage: TestSuite(K).run()
|
|
1652
|
+
sage: K = KleshchevPartitions(4, 4, convention='left regular')
|
|
1653
|
+
sage: TestSuite(K).run()
|
|
1654
|
+
sage: K = KleshchevPartitions(4, 4, convention='left restricted')
|
|
1655
|
+
sage: TestSuite(K).run()
|
|
1656
|
+
sage: K = KleshchevPartitions(4, [0,2,1], 4, convention='left regular')
|
|
1657
|
+
sage: TestSuite(K).run()
|
|
1658
|
+
sage: K = KleshchevPartitions(0, 2, convention='right restricted')
|
|
1659
|
+
sage: TestSuite(K).run()
|
|
1660
|
+
sage: K = KleshchevPartitions(0, [0,2,1], 4, convention='left restricted')
|
|
1661
|
+
sage: TestSuite(K).run()
|
|
1662
|
+
sage: K = KleshchevPartitions(0, [0,2,1], 4, convention='left regular')
|
|
1663
|
+
sage: TestSuite(K).run()
|
|
1664
|
+
|
|
1665
|
+
We verify that we obtain the same size for all conventions
|
|
1666
|
+
and that the result is equal to the number of elements in
|
|
1667
|
+
the crystal at the corresponding depth::
|
|
1668
|
+
|
|
1669
|
+
sage: # needs sage.graphs
|
|
1670
|
+
sage: B = crystals.LSPaths(['A',2,1], [1,0,1])
|
|
1671
|
+
sage: nd4 = (B.subcrystal(max_depth=4).cardinality()
|
|
1672
|
+
....: - B.subcrystal(max_depth=3).cardinality())
|
|
1673
|
+
sage: K = KleshchevPartitions(3, [0,2], 4, convention='RS')
|
|
1674
|
+
sage: K.cardinality() == nd4
|
|
1675
|
+
True
|
|
1676
|
+
sage: K = KleshchevPartitions(3, [0,2], 4, convention='RG')
|
|
1677
|
+
sage: K.cardinality() == nd4
|
|
1678
|
+
True
|
|
1679
|
+
sage: K = KleshchevPartitions(3, [0,2], 4, convention='LS')
|
|
1680
|
+
sage: K.cardinality() == nd4
|
|
1681
|
+
True
|
|
1682
|
+
sage: K = KleshchevPartitions(3, [0,2], 4, convention='LG')
|
|
1683
|
+
sage: K.cardinality() == nd4
|
|
1684
|
+
True
|
|
1685
|
+
"""
|
|
1686
|
+
self._level = len(multicharge)
|
|
1687
|
+
if self._level == 1:
|
|
1688
|
+
self.Element = KleshchevPartition
|
|
1689
|
+
self._element_constructor_ = getattr_from_other_class(self, Partitions, '_element_constructor_')
|
|
1690
|
+
else:
|
|
1691
|
+
self.Element = KleshchevPartitionTuple
|
|
1692
|
+
super().__init__(category=FiniteEnumeratedSets())
|
|
1693
|
+
self._size = size
|
|
1694
|
+
# As lists do not take negative indices the case e=0 needs to be handled
|
|
1695
|
+
# differently. Rather than doing this we set e equal to a "really big"
|
|
1696
|
+
# number. Mathematically, this is equivalent and it means that we don't
|
|
1697
|
+
# have an exception to cater for.
|
|
1698
|
+
self._e = e
|
|
1699
|
+
self._I = IntegerModRing(e)
|
|
1700
|
+
self._multicharge = tuple(self._I(m) for m in multicharge)
|
|
1701
|
+
self._convention = convention
|
|
1702
|
+
|
|
1703
|
+
def _repr_(self):
|
|
1704
|
+
"""
|
|
1705
|
+
EXAMPLES::
|
|
1706
|
+
|
|
1707
|
+
sage: KleshchevPartitions(4, [0,0], 3)
|
|
1708
|
+
Kleshchev partitions with e=4 and multicharge=(0,0) and size 3
|
|
1709
|
+
"""
|
|
1710
|
+
if self._level == 1:
|
|
1711
|
+
return 'Kleshchev partitions with e=%s and size %s' % (self._e, self._size)
|
|
1712
|
+
|
|
1713
|
+
return 'Kleshchev partitions with e=%s and multicharge=(%s) and size %s' % (
|
|
1714
|
+
self._e,','.join('%s' % m for m in self._multicharge), self._size
|
|
1715
|
+
)
|
|
1716
|
+
|
|
1717
|
+
def __contains__(self, mu):
|
|
1718
|
+
"""
|
|
1719
|
+
Check if ``mu`` is in ``self``.
|
|
1720
|
+
|
|
1721
|
+
TESTS::
|
|
1722
|
+
|
|
1723
|
+
sage: PartitionTuple([[3,2],[2]]) in KleshchevPartitions(2,[0,0],7)
|
|
1724
|
+
False
|
|
1725
|
+
sage: PartitionTuple([[3,2],[],[],[],[2]]) in KleshchevPartitions(5,[0,0,0,0,0],7)
|
|
1726
|
+
False
|
|
1727
|
+
sage: PartitionTuple([[2,1],[],[1,1],[],[2]]) in KleshchevPartitions(5,[0,0,0,0,0],7, convention='RG')
|
|
1728
|
+
False
|
|
1729
|
+
sage: PartitionTuple([[2,1],[],[1,1],[],[3]]) in KleshchevPartitions(2,[0,0,0,0,0],9, convention='RS')
|
|
1730
|
+
False
|
|
1731
|
+
sage: all(mu in PartitionTuples(3,8) for mu in KleshchevPartitions(0,[0,0,0],8))
|
|
1732
|
+
True
|
|
1733
|
+
"""
|
|
1734
|
+
if isinstance(mu, (KleshchevPartition, KleshchevPartitionTuple)):
|
|
1735
|
+
if not (mu.level() == self._level and mu.size() == self._size):
|
|
1736
|
+
return False
|
|
1737
|
+
mu = self.element_class(self, list(mu))
|
|
1738
|
+
if self._convention[1] == 'G':
|
|
1739
|
+
return mu.is_regular()
|
|
1740
|
+
|
|
1741
|
+
return mu.is_restricted()
|
|
1742
|
+
|
|
1743
|
+
try:
|
|
1744
|
+
mu = self.element_class(self, mu)
|
|
1745
|
+
except ValueError:
|
|
1746
|
+
return False
|
|
1747
|
+
return mu in self
|
|
1748
|
+
|
|
1749
|
+
def __iter__level_one(self):
|
|
1750
|
+
r"""
|
|
1751
|
+
Iterate over all Kleshchev partitions of level one and a fixed size.
|
|
1752
|
+
|
|
1753
|
+
EXAMPLES::
|
|
1754
|
+
|
|
1755
|
+
sage: KleshchevPartitions(2,0)[:] # indirect doctest
|
|
1756
|
+
[[]]
|
|
1757
|
+
sage: KleshchevPartitions(2,1)[:] # indirect doctest
|
|
1758
|
+
[[1]]
|
|
1759
|
+
sage: KleshchevPartitions(2,2)[:] # indirect doctest
|
|
1760
|
+
[[1, 1]]
|
|
1761
|
+
sage: KleshchevPartitions(3,2)[:] # indirect doctest
|
|
1762
|
+
[[2], [1, 1]]
|
|
1763
|
+
"""
|
|
1764
|
+
if self._size == 0:
|
|
1765
|
+
yield self.element_class(self, [])
|
|
1766
|
+
else:
|
|
1767
|
+
if self._e == 0:
|
|
1768
|
+
P = Partitions(self._size)
|
|
1769
|
+
elif self._convention[1] == 'G':
|
|
1770
|
+
P = Partitions(self._size, regular=self._e)
|
|
1771
|
+
else:
|
|
1772
|
+
P = Partitions(self._size, restricted=self._e)
|
|
1773
|
+
|
|
1774
|
+
for mu in P:
|
|
1775
|
+
yield self.element_class(self, list(mu))
|
|
1776
|
+
|
|
1777
|
+
def __iter__higher_levels(self):
|
|
1778
|
+
r"""
|
|
1779
|
+
Iterate over all KleshchevPartitions of a fixed level greater than 1
|
|
1780
|
+
and a fixed size.
|
|
1781
|
+
|
|
1782
|
+
EXAMPLES::
|
|
1783
|
+
|
|
1784
|
+
sage: KleshchevPartitions(2,[0,0],1)[:] # indirect doctest
|
|
1785
|
+
[([], [1])]
|
|
1786
|
+
sage: KleshchevPartitions(2,[0,0],2)[:] # indirect doctest
|
|
1787
|
+
[([1], [1]), ([], [1, 1])]
|
|
1788
|
+
sage: KleshchevPartitions(3,[0,0],2)[:] # indirect doctest
|
|
1789
|
+
[([1], [1]), ([], [2]), ([], [1, 1])]
|
|
1790
|
+
"""
|
|
1791
|
+
if self._size == 0:
|
|
1792
|
+
yield self.element_class(self, [[]]*len(self._multicharge))
|
|
1793
|
+
return
|
|
1794
|
+
|
|
1795
|
+
# For higher levels we have to recursively construct the restricted partitions
|
|
1796
|
+
# by adding on co-good nodes to smaller restricted partition. To avoid over
|
|
1797
|
+
# counting we return a new restricted partition only if we added on its lowest
|
|
1798
|
+
# good node.
|
|
1799
|
+
for mu in KleshchevPartitions_size(self._e, self._multicharge,
|
|
1800
|
+
size=self._size-1,
|
|
1801
|
+
convention=self._convention):
|
|
1802
|
+
mu_list = mu.to_list()
|
|
1803
|
+
for cell in mu.cogood_cells().values():
|
|
1804
|
+
data = [list(p) for p in mu_list]
|
|
1805
|
+
k,r,c = cell
|
|
1806
|
+
if c == 0:
|
|
1807
|
+
data[k].append(1)
|
|
1808
|
+
else:
|
|
1809
|
+
data[k][r] += 1
|
|
1810
|
+
nu = self.element_class(self, data)
|
|
1811
|
+
good_cells = nu.good_cells().values()
|
|
1812
|
+
if self._convention[1] == "S":
|
|
1813
|
+
if all(cell >= c for c in good_cells):
|
|
1814
|
+
yield nu
|
|
1815
|
+
else:
|
|
1816
|
+
if all(cell <= c for c in good_cells):
|
|
1817
|
+
yield nu
|
|
1818
|
+
|
|
1819
|
+
@lazy_attribute
|
|
1820
|
+
def __iter__(self):
|
|
1821
|
+
"""
|
|
1822
|
+
Wrapper to return the correct iterator which is different for
|
|
1823
|
+
:class:`Partitions` (level 1) and for :class:PartitionTuples`
|
|
1824
|
+
(higher levels).
|
|
1825
|
+
|
|
1826
|
+
EXAMPLES::
|
|
1827
|
+
|
|
1828
|
+
sage: KleshchevPartitions(3, 3, convention='RS')[:]
|
|
1829
|
+
[[2, 1], [1, 1, 1]]
|
|
1830
|
+
sage: KleshchevPartitions(3, 3, convention='RG')[:]
|
|
1831
|
+
[[3], [2, 1]]
|
|
1832
|
+
sage: KleshchevPartitions(3, [0], 3)[:]
|
|
1833
|
+
[[2, 1], [1, 1, 1]]
|
|
1834
|
+
sage: KleshchevPartitions(3, [0,0], 3)[:]
|
|
1835
|
+
[([1], [2]), ([1], [1, 1]), ([], [2, 1]), ([], [1, 1, 1])]
|
|
1836
|
+
sage: KleshchevPartitions(2, [0,1], size=0)[:]
|
|
1837
|
+
[([], [])]
|
|
1838
|
+
sage: KleshchevPartitions(2, [0,1], size=1)[:]
|
|
1839
|
+
[([1], []), ([], [1])]
|
|
1840
|
+
sage: KleshchevPartitions(2, [0,1], size=2)[:]
|
|
1841
|
+
[([1], [1]), ([], [1, 1])]
|
|
1842
|
+
sage: KleshchevPartitions(3, [0,1,2], size=2)[:]
|
|
1843
|
+
[([1], [1], []), ([1], [], [1]), ([], [1, 1], []),
|
|
1844
|
+
([], [1], [1]), ([], [], [2]), ([], [], [1, 1])]
|
|
1845
|
+
"""
|
|
1846
|
+
if self.level() == 1:
|
|
1847
|
+
return self.__iter__level_one
|
|
1848
|
+
|
|
1849
|
+
return self.__iter__higher_levels
|
|
1850
|
+
|
|
1851
|
+
def _an_element_(self):
|
|
1852
|
+
"""
|
|
1853
|
+
Return a generic element.
|
|
1854
|
+
|
|
1855
|
+
EXAMPLES::
|
|
1856
|
+
|
|
1857
|
+
sage: KleshchevPartitions(4, [0,0,0,0], 4).an_element()
|
|
1858
|
+
([1], [1], [1], [1])
|
|
1859
|
+
sage: KleshchevPartitions(4, [2], 4).an_element()
|
|
1860
|
+
[3, 1]
|
|
1861
|
+
"""
|
|
1862
|
+
return self[0]
|
|
1863
|
+
|
|
1864
|
+
Element = KleshchevPartitionTuple
|
|
1865
|
+
|
|
1866
|
+
#--------------------------------------------------
|
|
1867
|
+
# helper functions
|
|
1868
|
+
#--------------------------------------------------
|
|
1869
|
+
|
|
1870
|
+
|
|
1871
|
+
def _a_good_cell(kpt, multicharge, convention):
|
|
1872
|
+
"""
|
|
1873
|
+
Return a good cell from ``kpt`` considered as a Kleshchev partition
|
|
1874
|
+
with ``multicharge`` under ``convention``.
|
|
1875
|
+
|
|
1876
|
+
EXAMPLES::
|
|
1877
|
+
|
|
1878
|
+
sage: from sage.combinat.partition_kleshchev import _a_good_cell
|
|
1879
|
+
sage: I2 = IntegerModRing(2)
|
|
1880
|
+
sage: _a_good_cell([[3,2,1], [3,1,1]], [I2(0),I2(2)], 'RS')
|
|
1881
|
+
(1, 2, 0)
|
|
1882
|
+
sage: _a_good_cell([[3,1,1], [3,2]], [I2(0),I2(2)], 'LG')
|
|
1883
|
+
(1, 1, 1)
|
|
1884
|
+
sage: I3 = IntegerModRing(3)
|
|
1885
|
+
sage: _a_good_cell([[3,2,1], [3,1,1]], [I3(0),I3(2)], 'RS')
|
|
1886
|
+
(0, 2, 0)
|
|
1887
|
+
sage: _a_good_cell([[3,1,1], [3,2]], [I3(0),I3(2)], 'LG')
|
|
1888
|
+
(1, 0, 2)
|
|
1889
|
+
sage: _a_good_cell([[], []], [I3(0),I3(2)], 'RS') is None
|
|
1890
|
+
True
|
|
1891
|
+
sage: _a_good_cell([[1,1], []], [I3(0),I3(2)], 'LS') is None
|
|
1892
|
+
True
|
|
1893
|
+
"""
|
|
1894
|
+
# We use a dictionary for the normal nodes as the indexing set is Z when e=0
|
|
1895
|
+
carry = defaultdict(int) # a tally of #(removable cells)-#(addable cells)
|
|
1896
|
+
ret = None
|
|
1897
|
+
|
|
1898
|
+
if convention[0] == 'L':
|
|
1899
|
+
rows = [(k,r) for k,part in enumerate(kpt) for r in range(len(part)+1)]
|
|
1900
|
+
else:
|
|
1901
|
+
rows = [(k,r) for k,part in reversed(list(enumerate(kpt))) for r in range(len(part)+1)]
|
|
1902
|
+
if convention[1] == 'S':
|
|
1903
|
+
rows.reverse()
|
|
1904
|
+
|
|
1905
|
+
for row in rows:
|
|
1906
|
+
k,r = row
|
|
1907
|
+
if r == len(kpt[k]): # addable cell at bottom of a component
|
|
1908
|
+
carry[multicharge[k]-r] += 1
|
|
1909
|
+
else:
|
|
1910
|
+
res = multicharge[k] + kpt[k][r] - r - 1
|
|
1911
|
+
if r == len(kpt[k])-1 or kpt[k][r] > kpt[k][r+1]: # removable cell
|
|
1912
|
+
if carry[res] == 0:
|
|
1913
|
+
ret = (k, r, kpt[k][r]-1)
|
|
1914
|
+
else:
|
|
1915
|
+
carry[res] -= 1
|
|
1916
|
+
if r == 0 or kpt[k][r-1] > kpt[k][r]: # addable cell
|
|
1917
|
+
carry[res+1] += 1
|
|
1918
|
+
|
|
1919
|
+
# finally return the result
|
|
1920
|
+
return ret
|
|
1921
|
+
|
|
1922
|
+
|
|
1923
|
+
def _is_regular(kpt, multicharge, convention):
|
|
1924
|
+
"""
|
|
1925
|
+
Return ``True`` if ``kpt`` is a ``multicharge``-regular
|
|
1926
|
+
Kleshchev partition.
|
|
1927
|
+
|
|
1928
|
+
EXAMPLES::
|
|
1929
|
+
|
|
1930
|
+
sage: from sage.combinat.partition_kleshchev import _is_regular
|
|
1931
|
+
sage: I2 = IntegerModRing(2)
|
|
1932
|
+
sage: _is_regular([[3,1,1], [3,2]], [I2(0),I2(2)], 'LS')
|
|
1933
|
+
False
|
|
1934
|
+
sage: I3 = IntegerModRing(3)
|
|
1935
|
+
sage: _is_regular([[3,1,1], [3,2]], [I3(0),I3(2)], 'LS')
|
|
1936
|
+
True
|
|
1937
|
+
sage: _is_regular([[], []], [I3(0),I3(2)], 'LS')
|
|
1938
|
+
True
|
|
1939
|
+
"""
|
|
1940
|
+
if all(part == [] for part in kpt):
|
|
1941
|
+
return True
|
|
1942
|
+
convention = convention[0] + 'G'
|
|
1943
|
+
cell = _a_good_cell(kpt, multicharge, convention)
|
|
1944
|
+
while cell is not None:
|
|
1945
|
+
k, r, _ = cell
|
|
1946
|
+
if kpt[k][r] == 1:
|
|
1947
|
+
kpt[k].pop()
|
|
1948
|
+
else:
|
|
1949
|
+
kpt[k][r] -= 1
|
|
1950
|
+
cell = _a_good_cell(kpt, multicharge, convention)
|
|
1951
|
+
return all(part == [] for part in kpt)
|
|
1952
|
+
|
|
1953
|
+
|
|
1954
|
+
def _is_restricted(kpt, multicharge, convention):
|
|
1955
|
+
"""
|
|
1956
|
+
Return ``True`` if ``kpt`` is an ``multicharge``-restricted
|
|
1957
|
+
Kleshchev partition.
|
|
1958
|
+
|
|
1959
|
+
EXAMPLES::
|
|
1960
|
+
|
|
1961
|
+
sage: from sage.combinat.partition_kleshchev import _is_restricted
|
|
1962
|
+
sage: I2 = IntegerModRing(2)
|
|
1963
|
+
sage: _is_restricted([[3,2,1], [3,1,1]], [I2(0),I2(2)], 'RG')
|
|
1964
|
+
False
|
|
1965
|
+
sage: I3 = IntegerModRing(3)
|
|
1966
|
+
sage: _is_restricted([[3,2,1], [3,1,1]], [I3(0),I3(2)], 'RG')
|
|
1967
|
+
True
|
|
1968
|
+
sage: _is_restricted([[], []], [I3(0),I3(2)], 'RG')
|
|
1969
|
+
True
|
|
1970
|
+
"""
|
|
1971
|
+
if all(not part for part in kpt):
|
|
1972
|
+
return True
|
|
1973
|
+
convention = convention[0] + 'S'
|
|
1974
|
+
cell = _a_good_cell(kpt, multicharge, convention)
|
|
1975
|
+
while cell is not None:
|
|
1976
|
+
k, r, _ = cell
|
|
1977
|
+
if kpt[k][r] == 1:
|
|
1978
|
+
kpt[k].pop()
|
|
1979
|
+
else:
|
|
1980
|
+
kpt[k][r] -= 1
|
|
1981
|
+
cell = _a_good_cell(kpt, multicharge, convention)
|
|
1982
|
+
return all(not part for part in kpt)
|