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,3114 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
r"""
|
|
3
|
+
Partition tuples
|
|
4
|
+
|
|
5
|
+
A :class:`PartitionTuple` is a tuple of partitions. That is, an ordered
|
|
6
|
+
`k`-tuple of partitions `\mu=(\mu^{(1)},\mu^{(2)},...,\mu^{(k)})`. If
|
|
7
|
+
|
|
8
|
+
.. MATH::
|
|
9
|
+
|
|
10
|
+
n = \lvert \mu \rvert = \lvert \mu^{(1)} \rvert +
|
|
11
|
+
\lvert \mu^{(2)} \rvert + \cdots + \lvert \mu^{(k)} \rvert
|
|
12
|
+
|
|
13
|
+
then we say that `\mu` is a `k`-partition of `n`.
|
|
14
|
+
|
|
15
|
+
In representation theory partition tuples arise as the natural indexing
|
|
16
|
+
set for the ordinary irreducible representations of:
|
|
17
|
+
|
|
18
|
+
- the wreath products of cyclic groups with symmetric groups,
|
|
19
|
+
- the Ariki-Koike algebras, or the cyclotomic Hecke algebras of
|
|
20
|
+
the complex reflection groups of type `G(r,1,n)`,
|
|
21
|
+
- the degenerate cyclotomic Hecke algebras of type `G(r,1,n)`.
|
|
22
|
+
|
|
23
|
+
When these algebras are not semisimple, partition tuples index an important
|
|
24
|
+
class of modules for the algebras, which are generalisations of the Specht
|
|
25
|
+
modules of the symmetric groups.
|
|
26
|
+
|
|
27
|
+
Tuples of partitions also index the standard basis of the higher level
|
|
28
|
+
combinatorial Fock spaces. As a consequence, the combinatorics of partition
|
|
29
|
+
tuples encapsulates the canonical bases of crystal graphs for the irreducible
|
|
30
|
+
integrable highest weight modules of the (quantized) affine special linear
|
|
31
|
+
groups and the (quantized) affine general linear groups. By the
|
|
32
|
+
categorification theorems of Ariki, Varagnolo-Vasserot, Stroppel-Webster and
|
|
33
|
+
others, in characteristic zero the degenerate and non-degenerate cyclotomic
|
|
34
|
+
Hecke algebras, via their Khovanov-Lauda-Rouquier grading, categorify the
|
|
35
|
+
canonical bases of the quantum affine special and general linear groups.
|
|
36
|
+
|
|
37
|
+
Partitions are naturally in bijection with 1-tuples of partitions. Most of the
|
|
38
|
+
combinatorial operations defined on partitions extend to partition tuples in
|
|
39
|
+
a meaningful way. For example, the semisimple branching rules for the Specht
|
|
40
|
+
modules are described by adding and removing cells from partition tuples and
|
|
41
|
+
the modular branching rules correspond to adding and removing good and
|
|
42
|
+
cogood nodes, which is the underlying combinatorics for the associated
|
|
43
|
+
crystal graphs.
|
|
44
|
+
|
|
45
|
+
A :class:`PartitionTuple` belongs to :class:`PartitionTuples` and its derived
|
|
46
|
+
classes. :class:`PartitionTuples` is the parent class for all partitions
|
|
47
|
+
tuples. Four different classes of tuples of partitions are currently supported:
|
|
48
|
+
|
|
49
|
+
- ``PartitionTuples(level=k,size=n)`` are `k`-tuple of partitions of `n`.
|
|
50
|
+
- ``PartitionTuples(level=k)`` are `k`-tuple of partitions.
|
|
51
|
+
- ``PartitionTuples(size=n)`` are tuples of partitions of `n`.
|
|
52
|
+
- ``PartitionTuples()`` are tuples of partitions.
|
|
53
|
+
|
|
54
|
+
.. NOTE::
|
|
55
|
+
|
|
56
|
+
As with :class:`Partitions`, in sage the cells, or nodes, of partition
|
|
57
|
+
tuples are 0-based. For example, the (lexicographically) first cell in
|
|
58
|
+
any non-empty partition tuple is `[0,0,0]`.
|
|
59
|
+
|
|
60
|
+
EXAMPLES::
|
|
61
|
+
|
|
62
|
+
sage: PartitionTuple([[2,2],[1,1],[2]]).cells()
|
|
63
|
+
[(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 1, 0), (2, 0, 0), (2, 0, 1)]
|
|
64
|
+
|
|
65
|
+
.. NOTE::
|
|
66
|
+
|
|
67
|
+
Many :class:`PartitionTuple` methods take the individual coordinates `(k,r,c)`
|
|
68
|
+
as their arguments, here `k` is the component, `r` is the row index and `c` is
|
|
69
|
+
the column index. If your coordinates are in the form ``(k,r,c)`` then use
|
|
70
|
+
Python's \*-operator.
|
|
71
|
+
|
|
72
|
+
EXAMPLES::
|
|
73
|
+
|
|
74
|
+
sage: mu=PartitionTuple([[1,1],[2],[2,1]])
|
|
75
|
+
sage: [ mu.arm_length(*c) for c in mu.cells()]
|
|
76
|
+
[0, 0, 1, 0, 1, 0, 0]
|
|
77
|
+
|
|
78
|
+
.. WARNING::
|
|
79
|
+
|
|
80
|
+
In sage, if ``mu`` is a partition tuple then ``mu[k]`` most naturally refers
|
|
81
|
+
to the `k`-th component of ``mu``, so we use the convention of the
|
|
82
|
+
`(k,r,c)`-th cell in a partition tuple refers to the cell in component `k`,
|
|
83
|
+
row `r`, and column `c`. In the literature, the cells of a partition tuple
|
|
84
|
+
are usually written in the form `(r,c,k)`, where `r` is the row index, `c`
|
|
85
|
+
is the column index, and `k` is the component index.
|
|
86
|
+
|
|
87
|
+
REFERENCES:
|
|
88
|
+
|
|
89
|
+
- [DJM1998]_
|
|
90
|
+
- [BK2009]_
|
|
91
|
+
|
|
92
|
+
AUTHORS:
|
|
93
|
+
|
|
94
|
+
- Andrew Mathas (2012-06-01): Initial classes.
|
|
95
|
+
|
|
96
|
+
EXAMPLES:
|
|
97
|
+
|
|
98
|
+
First is a finite enumerated set and the remaining classes are infinite
|
|
99
|
+
enumerated sets::
|
|
100
|
+
|
|
101
|
+
sage: PartitionTuples().an_element()
|
|
102
|
+
([1, 1, 1, 1], [2, 1, 1], [3, 1], [4])
|
|
103
|
+
sage: PartitionTuples(4).an_element()
|
|
104
|
+
([], [1], [2], [3])
|
|
105
|
+
sage: PartitionTuples(size=5).an_element()
|
|
106
|
+
([1], [1], [1], [1], [1])
|
|
107
|
+
sage: PartitionTuples(4,5).an_element()
|
|
108
|
+
([1], [], [], [4])
|
|
109
|
+
sage: PartitionTuples(3,2)[:] # needs sage.libs.flint
|
|
110
|
+
[([2], [], []),
|
|
111
|
+
([1, 1], [], []),
|
|
112
|
+
([1], [1], []),
|
|
113
|
+
([1], [], [1]),
|
|
114
|
+
([], [2], []),
|
|
115
|
+
([], [1, 1], []),
|
|
116
|
+
([], [1], [1]),
|
|
117
|
+
([], [], [2]),
|
|
118
|
+
([], [], [1, 1])]
|
|
119
|
+
sage: PartitionTuples(2,3).list() # needs sage.libs.flint
|
|
120
|
+
[([3], []),
|
|
121
|
+
([2, 1], []),
|
|
122
|
+
([1, 1, 1], []),
|
|
123
|
+
([2], [1]),
|
|
124
|
+
([1, 1], [1]),
|
|
125
|
+
([1], [2]),
|
|
126
|
+
([1], [1, 1]),
|
|
127
|
+
([], [3]),
|
|
128
|
+
([], [2, 1]),
|
|
129
|
+
([], [1, 1, 1])]
|
|
130
|
+
|
|
131
|
+
One tuples of partitions are naturally in bijection with partitions and, as far
|
|
132
|
+
as possible, partition tuples attempts to identify one tuples with partitions::
|
|
133
|
+
|
|
134
|
+
sage: Partition([4,3]) == PartitionTuple([[4,3]])
|
|
135
|
+
True
|
|
136
|
+
sage: Partition([4,3]) == PartitionTuple([4,3])
|
|
137
|
+
True
|
|
138
|
+
sage: PartitionTuple([4,3])
|
|
139
|
+
[4, 3]
|
|
140
|
+
sage: Partition([4,3]) in PartitionTuples()
|
|
141
|
+
True
|
|
142
|
+
|
|
143
|
+
Partition tuples come equipped with many of the corresponding methods for
|
|
144
|
+
partitions. For example, it is possible to add and remove cells, to conjugate
|
|
145
|
+
partition tuples, to work with their diagrams, compare partition tuples in
|
|
146
|
+
dominance and so::
|
|
147
|
+
|
|
148
|
+
sage: PartitionTuple([[4,1],[],[2,2,1],[3]]).pp()
|
|
149
|
+
**** - ** ***
|
|
150
|
+
* **
|
|
151
|
+
*
|
|
152
|
+
sage: PartitionTuple([[4,1],[],[2,2,1],[3]]).conjugate()
|
|
153
|
+
([1, 1, 1], [3, 2], [], [2, 1, 1, 1])
|
|
154
|
+
sage: PartitionTuple([[4,1],[],[2,2,1],[3]]).conjugate().pp()
|
|
155
|
+
* *** - **
|
|
156
|
+
* ** *
|
|
157
|
+
* *
|
|
158
|
+
*
|
|
159
|
+
sage: lam = PartitionTuples(3)([[3,2],[],[1,1,1,1]]); lam
|
|
160
|
+
([3, 2], [], [1, 1, 1, 1])
|
|
161
|
+
sage: lam.level()
|
|
162
|
+
3
|
|
163
|
+
sage: lam.size()
|
|
164
|
+
9
|
|
165
|
+
sage: lam.category()
|
|
166
|
+
Category of elements of Partition tuples of level 3
|
|
167
|
+
sage: lam.parent()
|
|
168
|
+
Partition tuples of level 3
|
|
169
|
+
sage: lam[0]
|
|
170
|
+
[3, 2]
|
|
171
|
+
sage: lam[1]
|
|
172
|
+
[]
|
|
173
|
+
sage: lam[2]
|
|
174
|
+
[1, 1, 1, 1]
|
|
175
|
+
sage: lam.pp()
|
|
176
|
+
*** - *
|
|
177
|
+
** *
|
|
178
|
+
*
|
|
179
|
+
*
|
|
180
|
+
sage: lam.removable_cells()
|
|
181
|
+
[(0, 0, 2), (0, 1, 1), (2, 3, 0)]
|
|
182
|
+
sage: lam.down_list()
|
|
183
|
+
[([2, 2], [], [1, 1, 1, 1]),
|
|
184
|
+
([3, 1], [], [1, 1, 1, 1]),
|
|
185
|
+
([3, 2], [], [1, 1, 1])]
|
|
186
|
+
sage: lam.addable_cells()
|
|
187
|
+
[(0, 0, 3), (0, 1, 2), (0, 2, 0), (1, 0, 0), (2, 0, 1), (2, 4, 0)]
|
|
188
|
+
sage: lam.up_list()
|
|
189
|
+
[([4, 2], [], [1, 1, 1, 1]),
|
|
190
|
+
([3, 3], [], [1, 1, 1, 1]),
|
|
191
|
+
([3, 2, 1], [], [1, 1, 1, 1]),
|
|
192
|
+
([3, 2], [1], [1, 1, 1, 1]),
|
|
193
|
+
([3, 2], [], [2, 1, 1, 1]),
|
|
194
|
+
([3, 2], [], [1, 1, 1, 1, 1])]
|
|
195
|
+
sage: lam.conjugate()
|
|
196
|
+
([4], [], [2, 2, 1])
|
|
197
|
+
sage: lam.dominates( PartitionTuple([[3],[1],[2,2,1]]) )
|
|
198
|
+
False
|
|
199
|
+
sage: lam.dominates( PartitionTuple([[3],[2],[1,1,1]]))
|
|
200
|
+
True
|
|
201
|
+
|
|
202
|
+
Every partition tuple behaves every much like a tuple of partitions::
|
|
203
|
+
|
|
204
|
+
sage: mu = PartitionTuple([[4,1],[],[2,2,1],[3]])
|
|
205
|
+
sage: [ nu for nu in mu ]
|
|
206
|
+
[[4, 1], [], [2, 2, 1], [3]]
|
|
207
|
+
sage: Set([ type(nu) for nu in mu ])
|
|
208
|
+
{<class 'sage.combinat.partition.Partitions_all_with_category.element_class'>}
|
|
209
|
+
sage: mu[2][2]
|
|
210
|
+
1
|
|
211
|
+
sage: mu[3]
|
|
212
|
+
[3]
|
|
213
|
+
sage: mu.components()
|
|
214
|
+
[[4, 1], [], [2, 2, 1], [3]]
|
|
215
|
+
sage: mu.components() == [ nu for nu in mu ]
|
|
216
|
+
True
|
|
217
|
+
sage: mu[0]
|
|
218
|
+
[4, 1]
|
|
219
|
+
sage: mu[1]
|
|
220
|
+
[]
|
|
221
|
+
sage: mu[2]
|
|
222
|
+
[2, 2, 1]
|
|
223
|
+
sage: mu[2][0]
|
|
224
|
+
2
|
|
225
|
+
sage: mu[2][1]
|
|
226
|
+
2
|
|
227
|
+
sage: mu.level()
|
|
228
|
+
4
|
|
229
|
+
sage: len(mu)
|
|
230
|
+
4
|
|
231
|
+
sage: mu.cells()
|
|
232
|
+
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 1, 0), (2, 0, 0), (2, 0, 1),
|
|
233
|
+
(2, 1, 0), (2, 1, 1), (2, 2, 0), (3, 0, 0), (3, 0, 1), (3, 0, 2)]
|
|
234
|
+
sage: mu.addable_cells()
|
|
235
|
+
[(0, 0, 4), (0, 1, 1), (0, 2, 0), (1, 0, 0), (2, 0, 2), (2, 2, 1),
|
|
236
|
+
(2, 3, 0), (3, 0, 3), (3, 1, 0)]
|
|
237
|
+
sage: mu.removable_cells()
|
|
238
|
+
[(0, 0, 3), (0, 1, 0), (2, 1, 1), (2, 2, 0), (3, 0, 2)]
|
|
239
|
+
|
|
240
|
+
Attached to a partition tuple is the corresponding Young, or parabolic,
|
|
241
|
+
subgroup::
|
|
242
|
+
|
|
243
|
+
sage: mu.young_subgroup() # needs sage.groups
|
|
244
|
+
Permutation Group with generators
|
|
245
|
+
[(), (12,13), (11,12), (8,9), (6,7), (3,4), (2,3), (1,2)]
|
|
246
|
+
sage: mu.young_subgroup_generators() # needs sage.groups
|
|
247
|
+
[1, 2, 3, 6, 8, 11, 12]
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
# ****************************************************************************
|
|
251
|
+
# Copyright (C) 2012 Andrew Mathas <andrew.mathas@sydney.edu.au>
|
|
252
|
+
#
|
|
253
|
+
# This program is free software: you can redistribute it and/or modify
|
|
254
|
+
# it under the terms of the GNU General Public License as published by
|
|
255
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
256
|
+
# (at your option) any later version.
|
|
257
|
+
# https://www.gnu.org/licenses/
|
|
258
|
+
# ****************************************************************************
|
|
259
|
+
|
|
260
|
+
import itertools
|
|
261
|
+
|
|
262
|
+
from .combinat import CombinatorialElement
|
|
263
|
+
from .integer_vector import IntegerVectors
|
|
264
|
+
from .partition import (Partition, Partitions, Partitions_n, _Partitions,
|
|
265
|
+
RegularPartitions_all, RegularPartitions_n)
|
|
266
|
+
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
|
|
267
|
+
from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
|
|
268
|
+
from sage.misc.cachefunc import cached_method
|
|
269
|
+
from sage.misc.lazy_import import lazy_import
|
|
270
|
+
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
|
|
271
|
+
from sage.rings.integer_ring import ZZ
|
|
272
|
+
from sage.rings.semirings.non_negative_integer_semiring import NN
|
|
273
|
+
from sage.rings.integer import Integer
|
|
274
|
+
from sage.sets.positive_integers import PositiveIntegers
|
|
275
|
+
from sage.structure.parent import Parent
|
|
276
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
277
|
+
|
|
278
|
+
lazy_import('sage.groups.perm_gps.permgroup', 'PermutationGroup')
|
|
279
|
+
lazy_import('sage.libs.pari', 'pari')
|
|
280
|
+
|
|
281
|
+
# -------------------------------------------------
|
|
282
|
+
# Partition tuple - element class
|
|
283
|
+
# -------------------------------------------------
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
class PartitionTuple(CombinatorialElement):
|
|
287
|
+
r"""
|
|
288
|
+
A tuple of :class:`Partition`.
|
|
289
|
+
|
|
290
|
+
A tuple of partition comes equipped with many of methods available to
|
|
291
|
+
partitions. The ``level`` of the PartitionTuple is the length of the tuple.
|
|
292
|
+
|
|
293
|
+
This is an ordered `k`-tuple of partitions
|
|
294
|
+
`\mu=(\mu^{(1)},\mu^{(2)},...,\mu^{(k)})`. If
|
|
295
|
+
|
|
296
|
+
.. MATH::
|
|
297
|
+
|
|
298
|
+
n = \lvert \mu \rvert = \lvert \mu^{(1)} \rvert +
|
|
299
|
+
\lvert \mu^{(2)} \rvert + \cdots + \lvert \mu^{(k)} \rvert
|
|
300
|
+
|
|
301
|
+
then `\mu` is a `k`-partition of `n`.
|
|
302
|
+
|
|
303
|
+
In representation theory PartitionTuples arise as the natural indexing
|
|
304
|
+
set for the ordinary irreducible representations of:
|
|
305
|
+
|
|
306
|
+
- the wreath products of cyclic groups with symmetric groups
|
|
307
|
+
- the Ariki-Koike algebras, or the cyclotomic Hecke algebras of
|
|
308
|
+
the complex reflection groups of type `G(r,1,n)`
|
|
309
|
+
- the degenerate cyclotomic Hecke algebras of type `G(r,1,n)`
|
|
310
|
+
|
|
311
|
+
When these algebras are not semisimple, partition tuples index an important
|
|
312
|
+
class of modules for the algebras which are generalisations of the Specht
|
|
313
|
+
modules of the symmetric groups.
|
|
314
|
+
|
|
315
|
+
Tuples of partitions also index the standard basis of the higher level
|
|
316
|
+
combinatorial Fock spaces. As a consequence, the combinatorics of partition
|
|
317
|
+
tuples encapsulates the canonical bases of crystal graphs for the irreducible
|
|
318
|
+
integrable highest weight modules of the (quantized) affine special linear
|
|
319
|
+
groups and the (quantized) affine general linear groups. By the
|
|
320
|
+
categorification theorems of Ariki, Varagnolo-Vasserot, Stroppel-Webster and
|
|
321
|
+
others, in characteristic zero the degenerate and non-degenerate cyclotomic
|
|
322
|
+
Hecke algebras, via their Khovanov-Lauda-Rouquier grading, categorify the
|
|
323
|
+
canonical bases of the quantum affine special and general linear groups.
|
|
324
|
+
|
|
325
|
+
Partitions are naturally in bijection with 1-tuples of partitions. Most of the
|
|
326
|
+
combinatorial operations defined on partitions extend to PartitionTuples in
|
|
327
|
+
a meaningful way. For example, the semisimple branching rules for the Specht
|
|
328
|
+
modules are described by adding and removing cells from partition tuples and
|
|
329
|
+
the modular branching rules correspond to adding and removing good and
|
|
330
|
+
cogood nodes, which is the underlying combinatorics for the associated
|
|
331
|
+
crystal graphs.
|
|
332
|
+
|
|
333
|
+
.. WARNING::
|
|
334
|
+
|
|
335
|
+
In the literature, the cells of a partition tuple are usually written
|
|
336
|
+
in the form `(r,c,k)`, where `r` is the row index, `c` is the column
|
|
337
|
+
index, and `k` is the component index. In sage, if ``mu`` is a
|
|
338
|
+
partition tuple then ``mu[k]`` most naturally refers to the `k`-th
|
|
339
|
+
component of ``mu``, so we use the convention of the `(k,r,c)`-th cell
|
|
340
|
+
in a partition tuple refers to the cell in component `k`, row `r`, and
|
|
341
|
+
column `c`.
|
|
342
|
+
|
|
343
|
+
INPUT:
|
|
344
|
+
|
|
345
|
+
Anything which can reasonably be interpreted as a tuple of partitions.
|
|
346
|
+
That is, a list or tuple of partitions or valid input to
|
|
347
|
+
:class:`Partition`.
|
|
348
|
+
|
|
349
|
+
EXAMPLES::
|
|
350
|
+
|
|
351
|
+
sage: mu=PartitionTuple( [[3,2],[2,1],[],[1,1,1,1]] ); mu
|
|
352
|
+
([3, 2], [2, 1], [], [1, 1, 1, 1])
|
|
353
|
+
sage: nu=PartitionTuple( ([3,2],[2,1],[],[1,1,1,1]) ); nu
|
|
354
|
+
([3, 2], [2, 1], [], [1, 1, 1, 1])
|
|
355
|
+
sage: mu == nu
|
|
356
|
+
True
|
|
357
|
+
sage: mu is nu
|
|
358
|
+
False
|
|
359
|
+
sage: mu in PartitionTuples()
|
|
360
|
+
True
|
|
361
|
+
sage: mu.parent()
|
|
362
|
+
Partition tuples
|
|
363
|
+
|
|
364
|
+
sage: lam=PartitionTuples(3)([[3,2],[],[1,1,1,1]]); lam
|
|
365
|
+
([3, 2], [], [1, 1, 1, 1])
|
|
366
|
+
sage: lam.level()
|
|
367
|
+
3
|
|
368
|
+
sage: lam.size()
|
|
369
|
+
9
|
|
370
|
+
sage: lam.category()
|
|
371
|
+
Category of elements of Partition tuples of level 3
|
|
372
|
+
sage: lam.parent()
|
|
373
|
+
Partition tuples of level 3
|
|
374
|
+
sage: lam[0]
|
|
375
|
+
[3, 2]
|
|
376
|
+
sage: lam[1]
|
|
377
|
+
[]
|
|
378
|
+
sage: lam[2]
|
|
379
|
+
[1, 1, 1, 1]
|
|
380
|
+
sage: lam.pp()
|
|
381
|
+
*** - *
|
|
382
|
+
** *
|
|
383
|
+
*
|
|
384
|
+
*
|
|
385
|
+
sage: lam.removable_cells()
|
|
386
|
+
[(0, 0, 2), (0, 1, 1), (2, 3, 0)]
|
|
387
|
+
sage: lam.down_list()
|
|
388
|
+
[([2, 2], [], [1, 1, 1, 1]), ([3, 1], [], [1, 1, 1, 1]), ([3, 2], [], [1, 1, 1])]
|
|
389
|
+
sage: lam.addable_cells()
|
|
390
|
+
[(0, 0, 3), (0, 1, 2), (0, 2, 0), (1, 0, 0), (2, 0, 1), (2, 4, 0)]
|
|
391
|
+
sage: lam.up_list()
|
|
392
|
+
[([4, 2], [], [1, 1, 1, 1]), ([3, 3], [], [1, 1, 1, 1]), ([3, 2, 1], [], [1, 1, 1, 1]), ([3, 2], [1], [1, 1, 1, 1]), ([3, 2], [], [2, 1, 1, 1]), ([3, 2], [], [1, 1, 1, 1, 1])]
|
|
393
|
+
sage: lam.conjugate()
|
|
394
|
+
([4], [], [2, 2, 1])
|
|
395
|
+
sage: lam.dominates( PartitionTuple([[3],[1],[2,2,1]]) )
|
|
396
|
+
False
|
|
397
|
+
sage: lam.dominates( PartitionTuple([[3],[2],[1,1,1]]))
|
|
398
|
+
True
|
|
399
|
+
|
|
400
|
+
TESTS::
|
|
401
|
+
|
|
402
|
+
sage: TestSuite( PartitionTuple([4,3,2]) ).run()
|
|
403
|
+
sage: TestSuite( PartitionTuple([[4,3,2],[],[],[3,2,1]]) ).run()
|
|
404
|
+
|
|
405
|
+
.. SEEALSO::
|
|
406
|
+
|
|
407
|
+
- :class:`PartitionTuples`
|
|
408
|
+
- :class:`Partitions`
|
|
409
|
+
"""
|
|
410
|
+
Element = Partition
|
|
411
|
+
|
|
412
|
+
@staticmethod
|
|
413
|
+
def __classcall_private__(self, mu):
|
|
414
|
+
"""
|
|
415
|
+
This delegates the construction of a :class:`PartitionTuple` to the
|
|
416
|
+
``element_class()`` call of the appropriate
|
|
417
|
+
:class:`PartitionTuples_level`.
|
|
418
|
+
|
|
419
|
+
TESTS::
|
|
420
|
+
|
|
421
|
+
sage: mu=PartitionTuple([[1,1],[1]])
|
|
422
|
+
sage: mu.category()
|
|
423
|
+
Category of elements of Partition tuples
|
|
424
|
+
sage: type(mu)
|
|
425
|
+
<class 'sage.combinat.partition_tuple.PartitionTuples_all_with_category.element_class'>
|
|
426
|
+
"""
|
|
427
|
+
if isinstance(mu, (Partition, PartitionTuple)):
|
|
428
|
+
return mu
|
|
429
|
+
|
|
430
|
+
# one way or another these two cases need to be treated separately
|
|
431
|
+
if mu == [] or mu == [[]]:
|
|
432
|
+
return _Partitions([])
|
|
433
|
+
|
|
434
|
+
# We must check mu is a list of partitions
|
|
435
|
+
try:
|
|
436
|
+
mu = [_Partitions(mu)]
|
|
437
|
+
except ValueError:
|
|
438
|
+
try:
|
|
439
|
+
mu = [_Partitions(nu) for nu in mu]
|
|
440
|
+
except ValueError:
|
|
441
|
+
raise ValueError('%s is not a tuple of Partitions' % mu)
|
|
442
|
+
|
|
443
|
+
if len(mu) == 1:
|
|
444
|
+
return _Partitions(mu[0])
|
|
445
|
+
else:
|
|
446
|
+
return PartitionTuples_all().element_class(PartitionTuples_all(), mu)
|
|
447
|
+
|
|
448
|
+
def __init__(self, parent, mu):
|
|
449
|
+
"""
|
|
450
|
+
Initialize ``self`` and checks that the input determines a tuple of
|
|
451
|
+
partitions.
|
|
452
|
+
|
|
453
|
+
EXAMPLES::
|
|
454
|
+
|
|
455
|
+
sage: PartitionTuple([])
|
|
456
|
+
[]
|
|
457
|
+
sage: P = PartitionTuple([[2,1,1,0],[2,1]]); P
|
|
458
|
+
([2, 1, 1], [2, 1])
|
|
459
|
+
sage: TestSuite(P).run()
|
|
460
|
+
sage: PartitionTuple([[],[],[2,1,2,1]])
|
|
461
|
+
Traceback (most recent call last):
|
|
462
|
+
...
|
|
463
|
+
ValueError: [[], [], [2, 1, 2, 1]] is not a tuple of Partitions
|
|
464
|
+
"""
|
|
465
|
+
mu = [_Partitions(nu) for nu in mu]
|
|
466
|
+
CombinatorialElement.__init__(self, parent, mu)
|
|
467
|
+
|
|
468
|
+
def level(self):
|
|
469
|
+
"""
|
|
470
|
+
Return the level of this partition tuple.
|
|
471
|
+
|
|
472
|
+
The level is the length of the tuple.
|
|
473
|
+
|
|
474
|
+
EXAMPLES::
|
|
475
|
+
|
|
476
|
+
sage: PartitionTuple([[2,1,1,0],[2,1]]).level()
|
|
477
|
+
2
|
|
478
|
+
sage: PartitionTuple([[],[],[2,1,1]]).level()
|
|
479
|
+
3
|
|
480
|
+
"""
|
|
481
|
+
return len(self._list)
|
|
482
|
+
|
|
483
|
+
def __len__(self):
|
|
484
|
+
"""
|
|
485
|
+
Return the length of this partition tuple.
|
|
486
|
+
|
|
487
|
+
The length is also known as the level.
|
|
488
|
+
|
|
489
|
+
EXAMPLES::
|
|
490
|
+
|
|
491
|
+
sage: len( PartitionTuple([[2,1],[3,2],[1,1,1]]) )
|
|
492
|
+
3
|
|
493
|
+
"""
|
|
494
|
+
return self.level()
|
|
495
|
+
|
|
496
|
+
def _repr_(self, compact=None):
|
|
497
|
+
"""
|
|
498
|
+
Return a string representation of ``self`` depending on
|
|
499
|
+
:meth:`PartitionTuples.options`.
|
|
500
|
+
|
|
501
|
+
EXAMPLES::
|
|
502
|
+
|
|
503
|
+
sage: mu=PartitionTuple(([2,1],[3,2],[1,1,1])) # indirect doctest
|
|
504
|
+
|
|
505
|
+
sage: PartitionTuples.options(display='list'); mu
|
|
506
|
+
([2, 1], [3, 2], [1, 1, 1])
|
|
507
|
+
sage: PartitionTuples.options(display='diagram'); mu
|
|
508
|
+
** *** *
|
|
509
|
+
* ** *
|
|
510
|
+
*
|
|
511
|
+
sage: PartitionTuples.options(display='compact_low'); mu
|
|
512
|
+
1,2|2,3|1^3
|
|
513
|
+
sage: PartitionTuples.options(display='compact_high'); mu
|
|
514
|
+
2,1|3,2|1^3
|
|
515
|
+
sage: PartitionTuples.options(display='exp_low'); mu
|
|
516
|
+
1, 2 | 2, 3 | 1^3
|
|
517
|
+
sage: PartitionTuples.options(display='exp_high'); mu
|
|
518
|
+
2, 1 | 3, 2 | 1^3
|
|
519
|
+
sage: PartitionTuples.options._reset()
|
|
520
|
+
|
|
521
|
+
sage: Partitions.options(convention='French')
|
|
522
|
+
sage: PartitionTuples.options(display='diagram'); mu
|
|
523
|
+
*
|
|
524
|
+
* ** *
|
|
525
|
+
** *** *
|
|
526
|
+
sage: PartitionTuples.options(display='list'); mu
|
|
527
|
+
([2, 1], [3, 2], [1, 1, 1])
|
|
528
|
+
sage: PartitionTuples.options(display='compact_low'); mu
|
|
529
|
+
1,2|2,3|1^3
|
|
530
|
+
sage: PartitionTuples.options(display='compact_high'); mu
|
|
531
|
+
2,1|3,2|1^3
|
|
532
|
+
sage: PartitionTuples.options(display='exp_low'); mu
|
|
533
|
+
1, 2 | 2, 3 | 1^3
|
|
534
|
+
sage: PartitionTuples.options(display='exp_high'); mu
|
|
535
|
+
2, 1 | 3, 2 | 1^3
|
|
536
|
+
sage: PartitionTuples.options._reset()
|
|
537
|
+
"""
|
|
538
|
+
return self.parent().options._dispatch(self, '_repr_', 'display')
|
|
539
|
+
|
|
540
|
+
def _repr_diagram(self):
|
|
541
|
+
"""
|
|
542
|
+
Return a string representation of ``self`` as a Ferrers diagram.
|
|
543
|
+
|
|
544
|
+
EXAMPLES::
|
|
545
|
+
|
|
546
|
+
sage: print(PartitionTuple(([2,1],[3,2],[1,1,1]))._repr_diagram())
|
|
547
|
+
** *** *
|
|
548
|
+
* ** *
|
|
549
|
+
*
|
|
550
|
+
"""
|
|
551
|
+
return self.diagram()
|
|
552
|
+
|
|
553
|
+
def _repr_list(self):
|
|
554
|
+
"""
|
|
555
|
+
Return a string representation of ``self`` as a list.
|
|
556
|
+
|
|
557
|
+
EXAMPLES::
|
|
558
|
+
|
|
559
|
+
sage: PartitionTuple(([2,1],[3,2],[1,1,1]))._repr_list()
|
|
560
|
+
'([2, 1], [3, 2], [1, 1, 1])'
|
|
561
|
+
"""
|
|
562
|
+
return '(' + ', '.join(nu._repr_() for nu in self) + ')'
|
|
563
|
+
|
|
564
|
+
def _repr_exp_low(self):
|
|
565
|
+
"""
|
|
566
|
+
Return a string representation of ``self`` in compact form (exponential
|
|
567
|
+
form with highest first).
|
|
568
|
+
|
|
569
|
+
EXAMPLES::
|
|
570
|
+
|
|
571
|
+
sage: PartitionTuple(([2,1],[3,2],[1,1,1]))._repr_exp_low()
|
|
572
|
+
'1, 2 | 2, 3 | 1^3'
|
|
573
|
+
sage: PartitionTuple(([],[3,2],[1,1,1]))._repr_exp_low()
|
|
574
|
+
'- | 2, 3 | 1^3'
|
|
575
|
+
"""
|
|
576
|
+
return ' | '.join(nu._repr_exp_low() for nu in self)
|
|
577
|
+
|
|
578
|
+
def _repr_exp_high(self):
|
|
579
|
+
"""
|
|
580
|
+
Return a string representation of ``self`` in compact form (exponential
|
|
581
|
+
form with highest first).
|
|
582
|
+
|
|
583
|
+
EXAMPLES::
|
|
584
|
+
|
|
585
|
+
sage: PartitionTuple(([2,1],[3,2],[1,1,1,1,1,1,1,1,1,1]))._repr_exp_high()
|
|
586
|
+
'2, 1 | 3, 2 | 1^10'
|
|
587
|
+
sage: PartitionTuple(([],[3,2],[1,1,1]))._repr_exp_high()
|
|
588
|
+
'- | 3, 2 | 1^3'
|
|
589
|
+
"""
|
|
590
|
+
return ' | '.join(nu._repr_exp_high() for nu in self)
|
|
591
|
+
|
|
592
|
+
def _repr_compact_low(self):
|
|
593
|
+
"""
|
|
594
|
+
Return a string representation of ``self`` in compact form (exponential
|
|
595
|
+
form with highest first).
|
|
596
|
+
|
|
597
|
+
EXAMPLES::
|
|
598
|
+
|
|
599
|
+
sage: PartitionTuple(([2,1],[3,2],[1,1,1]))._repr_compact_low()
|
|
600
|
+
'1,2|2,3|1^3'
|
|
601
|
+
sage: PartitionTuple(([],[3,2],[1,1,1]))._repr_compact_low()
|
|
602
|
+
'-|2,3|1^3'
|
|
603
|
+
"""
|
|
604
|
+
return '%s' % '|'.join(mu._repr_compact_low() for mu in self)
|
|
605
|
+
|
|
606
|
+
def _repr_compact_high(self):
|
|
607
|
+
"""
|
|
608
|
+
Return a string representation of ``self`` in compact form (exponential
|
|
609
|
+
form with highest first).
|
|
610
|
+
|
|
611
|
+
EXAMPLES::
|
|
612
|
+
|
|
613
|
+
sage: PartitionTuple(([2,1],[3,2],[1,1,1]))._repr_compact_high()
|
|
614
|
+
'2,1|3,2|1^3'
|
|
615
|
+
sage: PartitionTuple(([],[3,2],[1,1,1]))._repr_compact_high()
|
|
616
|
+
'-|3,2|1^3'
|
|
617
|
+
"""
|
|
618
|
+
return '|'.join(mu._repr_compact_high() for mu in self)
|
|
619
|
+
|
|
620
|
+
# override default string representation which is str(self._list)
|
|
621
|
+
__str__ = lambda self: self._repr_() # type:ignore
|
|
622
|
+
|
|
623
|
+
def _latex_(self):
|
|
624
|
+
r"""
|
|
625
|
+
Return a LaTeX version of ``self``.
|
|
626
|
+
|
|
627
|
+
For more on the latex options, see :meth:`Partitions.option`.
|
|
628
|
+
|
|
629
|
+
EXAMPLES::
|
|
630
|
+
|
|
631
|
+
sage: mu = PartitionTuple([[2, 1],[1,1,1]])
|
|
632
|
+
sage: PartitionTuples.options(latex='diagram'); latex(mu) # indirect doctest
|
|
633
|
+
{\def\lr#1{\multicolumn{1}{@{\hspace{.6ex}}c@{\hspace{.6ex}}}{\raisebox{-.3ex}{$#1$}}}
|
|
634
|
+
\raisebox{-.6ex}{$\begin{array}[b]{*{2}c}\\
|
|
635
|
+
\lr{\ast}&\lr{\ast}\\
|
|
636
|
+
\lr{\ast}\\
|
|
637
|
+
\end{array}$},\raisebox{-.6ex}{$\begin{array}[b]{*{1}c}\\
|
|
638
|
+
\lr{\ast}\\
|
|
639
|
+
\lr{\ast}\\
|
|
640
|
+
\lr{\ast}\\
|
|
641
|
+
\end{array}$}
|
|
642
|
+
}
|
|
643
|
+
sage: PartitionTuples.options(latex='exp_high'); latex(mu) # indirect doctest
|
|
644
|
+
(2,1|1^{3})
|
|
645
|
+
sage: PartitionTuples.options(latex='exp_low'); latex(mu) # indirect doctest
|
|
646
|
+
(1,2|1^{3})
|
|
647
|
+
sage: PartitionTuples.options(latex='list'); latex(mu) # indirect doctest
|
|
648
|
+
[[2, 1], [1, 1, 1]]
|
|
649
|
+
sage: PartitionTuples.options(latex='young_diagram'); latex(mu) # indirect doctest
|
|
650
|
+
{\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
|
|
651
|
+
\raisebox{-.6ex}{$\begin{array}[b]{*{2}c}\cline{1-2}
|
|
652
|
+
\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{1-2}
|
|
653
|
+
\lr{\phantom{x}}\\\cline{1-1}
|
|
654
|
+
\end{array}$},\raisebox{-.6ex}{$\begin{array}[b]{*{1}c}\cline{1-1}
|
|
655
|
+
\lr{\phantom{x}}\\\cline{1-1}
|
|
656
|
+
\lr{\phantom{x}}\\\cline{1-1}
|
|
657
|
+
\lr{\phantom{x}}\\\cline{1-1}
|
|
658
|
+
\end{array}$}
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
sage: PartitionTuples.options(latex='young_diagram', convention='french')
|
|
662
|
+
sage: PartitionTuples.options(latex='exp_high'); latex(mu) # indirect doctest
|
|
663
|
+
(2,1|1^{3})
|
|
664
|
+
sage: PartitionTuples.options(latex='exp_low'); latex(mu) # indirect doctest
|
|
665
|
+
(1,2|1^{3})
|
|
666
|
+
sage: PartitionTuples.options(latex='list'); latex(mu) # indirect doctest
|
|
667
|
+
[[2, 1], [1, 1, 1]]
|
|
668
|
+
sage: PartitionTuples.options(latex='young_diagram'); latex(mu) # indirect doctest
|
|
669
|
+
{\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
|
|
670
|
+
\raisebox{-.6ex}{$\begin{array}[t]{*{2}c}\cline{1-1}
|
|
671
|
+
\lr{\phantom{x}}\\\cline{1-2}
|
|
672
|
+
\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{1-2}
|
|
673
|
+
\end{array}$},\raisebox{-.6ex}{$\begin{array}[t]{*{1}c}\cline{1-1}
|
|
674
|
+
\lr{\phantom{x}}\\\cline{1-1}
|
|
675
|
+
\lr{\phantom{x}}\\\cline{1-1}
|
|
676
|
+
\lr{\phantom{x}}\\\cline{1-1}
|
|
677
|
+
\end{array}$}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
sage: PartitionTuples.options._reset()
|
|
681
|
+
"""
|
|
682
|
+
return self.parent().options._dispatch(self, '_latex_', 'latex')
|
|
683
|
+
|
|
684
|
+
def _latex_young_diagram(self):
|
|
685
|
+
"""
|
|
686
|
+
LaTeX output as a Young diagram.
|
|
687
|
+
|
|
688
|
+
EXAMPLES::
|
|
689
|
+
|
|
690
|
+
sage: mu = PartitionTuple([[2, 1],[1,1,1]])._latex_young_diagram()
|
|
691
|
+
"""
|
|
692
|
+
from sage.combinat.output import tex_from_array_tuple
|
|
693
|
+
return tex_from_array_tuple([[["\\phantom{x}"] * row for row in mu]
|
|
694
|
+
for mu in self._list])
|
|
695
|
+
|
|
696
|
+
def _latex_diagram(self):
|
|
697
|
+
"""
|
|
698
|
+
LaTeX output as a Ferrers' diagram.
|
|
699
|
+
|
|
700
|
+
EXAMPLES::
|
|
701
|
+
|
|
702
|
+
sage: mu = PartitionTuple([[2, 1],[1,1,1]])._latex_diagram()
|
|
703
|
+
"""
|
|
704
|
+
entry = self.parent().options("latex_diagram_str")
|
|
705
|
+
from sage.combinat.output import tex_from_array_tuple
|
|
706
|
+
return tex_from_array_tuple([[[entry] * row for row in mu]
|
|
707
|
+
for mu in self._list], with_lines=False)
|
|
708
|
+
|
|
709
|
+
def _latex_list(self):
|
|
710
|
+
"""
|
|
711
|
+
LaTeX output as a list.
|
|
712
|
+
|
|
713
|
+
EXAMPLES::
|
|
714
|
+
|
|
715
|
+
sage: mu = PartitionTuple([[2, 1],[1,1,1]])._latex_list()
|
|
716
|
+
"""
|
|
717
|
+
return repr(self._list)
|
|
718
|
+
|
|
719
|
+
def _latex_exp_low(self):
|
|
720
|
+
"""
|
|
721
|
+
LaTeX output in exponential notation (lowest first).
|
|
722
|
+
|
|
723
|
+
EXAMPLES::
|
|
724
|
+
|
|
725
|
+
sage: mu = PartitionTuple([[2, 1],[1,1,1,1,1,1,1,1,1,1]])._latex_exp_low()
|
|
726
|
+
"""
|
|
727
|
+
txt = '|'.join(','.join('%s%s' % (a + 1, '' if e == 1 else '^{%s}' % e)
|
|
728
|
+
for a, e in enumerate(mu))
|
|
729
|
+
for mu in self.to_exp())
|
|
730
|
+
return '(' + txt + ')'
|
|
731
|
+
|
|
732
|
+
def _latex_exp_high(self):
|
|
733
|
+
"""
|
|
734
|
+
LaTeX output in exponential notation (highest first).
|
|
735
|
+
|
|
736
|
+
EXAMPLES::
|
|
737
|
+
|
|
738
|
+
sage: mu = PartitionTuple([[2, 1],[1,1,1,1,1,1,1,1,1,1]])._latex_exp_high()
|
|
739
|
+
"""
|
|
740
|
+
txt = '|'.join(','.join(['%s%s' % (a + 1, '' if e == 1 else '^{%s}' % e)
|
|
741
|
+
for a, e in enumerate(mu)][::-1])
|
|
742
|
+
for mu in self.to_exp())
|
|
743
|
+
return '(' + txt + ')'
|
|
744
|
+
|
|
745
|
+
def components(self):
|
|
746
|
+
r"""
|
|
747
|
+
Return a list containing the shape of this partition.
|
|
748
|
+
|
|
749
|
+
This function exists in order to give a uniform way of iterating over
|
|
750
|
+
the \"components\" of partition tuples of level 1 (partitions) and for
|
|
751
|
+
higher levels.
|
|
752
|
+
|
|
753
|
+
EXAMPLES::
|
|
754
|
+
|
|
755
|
+
sage: for t in PartitionTuple([[2,1],[3,2],[3]]).components():
|
|
756
|
+
....: print('%s\n' % t.ferrers_diagram())
|
|
757
|
+
**
|
|
758
|
+
*
|
|
759
|
+
<BLANKLINE>
|
|
760
|
+
***
|
|
761
|
+
**
|
|
762
|
+
<BLANKLINE>
|
|
763
|
+
***
|
|
764
|
+
<BLANKLINE>
|
|
765
|
+
sage: for t in PartitionTuple([3,2]).components():
|
|
766
|
+
....: print('%s\n' % t.ferrers_diagram())
|
|
767
|
+
***
|
|
768
|
+
**
|
|
769
|
+
"""
|
|
770
|
+
return list(self)
|
|
771
|
+
|
|
772
|
+
def diagram(self):
|
|
773
|
+
r"""
|
|
774
|
+
Return a string for the Ferrers diagram of ``self``.
|
|
775
|
+
|
|
776
|
+
EXAMPLES::
|
|
777
|
+
|
|
778
|
+
sage: print(PartitionTuple([[2,1],[3,2],[1,1,1]]).diagram())
|
|
779
|
+
** *** *
|
|
780
|
+
* ** *
|
|
781
|
+
*
|
|
782
|
+
sage: print(PartitionTuple([[3,2],[2,1],[],[1,1,1,1]]).diagram())
|
|
783
|
+
*** ** - *
|
|
784
|
+
** * *
|
|
785
|
+
*
|
|
786
|
+
*
|
|
787
|
+
sage: PartitionTuples.options(convention='french')
|
|
788
|
+
sage: print(PartitionTuple([[3,2],[2,1],[],[1,1,1,1]]).diagram())
|
|
789
|
+
*
|
|
790
|
+
*
|
|
791
|
+
** * *
|
|
792
|
+
*** ** - *
|
|
793
|
+
sage: PartitionTuples.options._reset()
|
|
794
|
+
"""
|
|
795
|
+
col_len = [mu and mu[0] or 1 for mu in self] # columns per component
|
|
796
|
+
row_max = max(len(mu) for mu in self) # maximum row length
|
|
797
|
+
# There should be a fancier list compression for this but I couldn't get
|
|
798
|
+
# one to work in the cases where a component was the empty partition
|
|
799
|
+
diag = []
|
|
800
|
+
diag_str = PartitionTuples.options('diagram_str')
|
|
801
|
+
for row in range(row_max):
|
|
802
|
+
line = ''
|
|
803
|
+
for c in range(len(self)):
|
|
804
|
+
if row == 0 and self[c] == []:
|
|
805
|
+
line += ' -'
|
|
806
|
+
elif row < len(self[c]):
|
|
807
|
+
line += ' {:{}}'.format(diag_str*self[c][row],col_len[c])
|
|
808
|
+
else:
|
|
809
|
+
line += ' {:{}}'.format('',col_len[c])
|
|
810
|
+
diag.append(line.rstrip())
|
|
811
|
+
if PartitionTuples.options('convention') == "English":
|
|
812
|
+
return '\n'.join(map(str, diag))
|
|
813
|
+
else:
|
|
814
|
+
return '\n'.join(map(str, diag[::-1]))
|
|
815
|
+
|
|
816
|
+
ferrers_diagram = diagram
|
|
817
|
+
|
|
818
|
+
def pp(self):
|
|
819
|
+
r"""
|
|
820
|
+
Pretty print this partition tuple. See :meth:`diagram`.
|
|
821
|
+
|
|
822
|
+
EXAMPLES::
|
|
823
|
+
|
|
824
|
+
sage: PartitionTuple([[5,5,2,1],[3,2]]).pp()
|
|
825
|
+
***** ***
|
|
826
|
+
***** **
|
|
827
|
+
**
|
|
828
|
+
*
|
|
829
|
+
"""
|
|
830
|
+
print(self.diagram())
|
|
831
|
+
|
|
832
|
+
def size(self):
|
|
833
|
+
"""
|
|
834
|
+
Return the size of a partition tuple.
|
|
835
|
+
|
|
836
|
+
EXAMPLES::
|
|
837
|
+
|
|
838
|
+
sage: PartitionTuple([[2,1],[],[2,2]]).size()
|
|
839
|
+
7
|
|
840
|
+
sage: PartitionTuple([[],[],[1],[3,2,1]]).size()
|
|
841
|
+
7
|
|
842
|
+
"""
|
|
843
|
+
return sum(mu.size() for mu in self)
|
|
844
|
+
|
|
845
|
+
def row_standard_tableaux(self):
|
|
846
|
+
"""
|
|
847
|
+
Return the :class:`row standard tableau tuples
|
|
848
|
+
<sage.combinat.tableau_tuple.RowStandardTableauTuples>`
|
|
849
|
+
of shape ``self``.
|
|
850
|
+
|
|
851
|
+
EXAMPLES::
|
|
852
|
+
|
|
853
|
+
sage: PartitionTuple([[],[3,2,2,1],[2,2,1],[3]]).row_standard_tableaux()
|
|
854
|
+
Row standard tableau tuples of shape ([], [3, 2, 2, 1], [2, 2, 1], [3])
|
|
855
|
+
"""
|
|
856
|
+
from .tableau_tuple import RowStandardTableauTuples
|
|
857
|
+
return RowStandardTableauTuples(shape=self)
|
|
858
|
+
|
|
859
|
+
def standard_tableaux(self):
|
|
860
|
+
"""
|
|
861
|
+
Return the :class:`standard tableau tuples<StandardTableauTuples>`
|
|
862
|
+
of shape ``self``.
|
|
863
|
+
|
|
864
|
+
EXAMPLES::
|
|
865
|
+
|
|
866
|
+
sage: PartitionTuple([[],[3,2,2,1],[2,2,1],[3]]).standard_tableaux()
|
|
867
|
+
Standard tableau tuples of shape ([], [3, 2, 2, 1], [2, 2, 1], [3])
|
|
868
|
+
"""
|
|
869
|
+
from .tableau_tuple import StandardTableauTuples
|
|
870
|
+
return StandardTableauTuples(shape=self)
|
|
871
|
+
|
|
872
|
+
def up(self):
|
|
873
|
+
r"""
|
|
874
|
+
Generator (iterator) for the partition tuples that are obtained from
|
|
875
|
+
``self`` by adding a cell.
|
|
876
|
+
|
|
877
|
+
EXAMPLES::
|
|
878
|
+
|
|
879
|
+
sage: [mu for mu in PartitionTuple([[],[3,1],[1,1]]).up()]
|
|
880
|
+
[([1], [3, 1], [1, 1]), ([], [4, 1], [1, 1]), ([], [3, 2], [1, 1]), ([], [3, 1, 1], [1, 1]), ([], [3, 1], [2, 1]), ([], [3, 1], [1, 1, 1])]
|
|
881
|
+
sage: [mu for mu in PartitionTuple([[],[],[],[]]).up()]
|
|
882
|
+
[([1], [], [], []), ([], [1], [], []), ([], [], [1], []), ([], [], [], [1])]
|
|
883
|
+
"""
|
|
884
|
+
for c in range(len(self)):
|
|
885
|
+
for nu in self[c].up():
|
|
886
|
+
up = list(self)
|
|
887
|
+
up[c] = nu
|
|
888
|
+
yield PartitionTuple(up)
|
|
889
|
+
|
|
890
|
+
def up_list(self):
|
|
891
|
+
"""
|
|
892
|
+
Return a list of the partition tuples that can be formed from ``self``
|
|
893
|
+
by adding a cell.
|
|
894
|
+
|
|
895
|
+
EXAMPLES::
|
|
896
|
+
|
|
897
|
+
sage: PartitionTuple([[],[3,1],[1,1]]).up_list()
|
|
898
|
+
[([1], [3, 1], [1, 1]), ([], [4, 1], [1, 1]), ([], [3, 2], [1, 1]), ([], [3, 1, 1], [1, 1]), ([], [3, 1], [2, 1]), ([], [3, 1], [1, 1, 1])]
|
|
899
|
+
sage: PartitionTuple([[],[],[],[]]).up_list()
|
|
900
|
+
[([1], [], [], []), ([], [1], [], []), ([], [], [1], []), ([], [], [], [1])]
|
|
901
|
+
"""
|
|
902
|
+
return list(self.up())
|
|
903
|
+
|
|
904
|
+
def down(self):
|
|
905
|
+
r"""
|
|
906
|
+
Generator (iterator) for the partition tuples that are obtained from
|
|
907
|
+
``self`` by removing a cell.
|
|
908
|
+
|
|
909
|
+
EXAMPLES::
|
|
910
|
+
|
|
911
|
+
sage: [mu for mu in PartitionTuple([[],[3,1],[1,1]]).down()]
|
|
912
|
+
[([], [2, 1], [1, 1]), ([], [3], [1, 1]), ([], [3, 1], [1])]
|
|
913
|
+
sage: [mu for mu in PartitionTuple([[],[],[]]).down()]
|
|
914
|
+
[]
|
|
915
|
+
"""
|
|
916
|
+
for c in range(len(self)):
|
|
917
|
+
for nu in self[c].down():
|
|
918
|
+
down = list(self)
|
|
919
|
+
down[c] = nu
|
|
920
|
+
yield PartitionTuple(down)
|
|
921
|
+
|
|
922
|
+
def down_list(self):
|
|
923
|
+
"""
|
|
924
|
+
Return a list of the partition tuples that can be formed from ``self``
|
|
925
|
+
by removing a cell.
|
|
926
|
+
|
|
927
|
+
EXAMPLES::
|
|
928
|
+
|
|
929
|
+
sage: PartitionTuple([[],[3,1],[1,1]]).down_list()
|
|
930
|
+
[([], [2, 1], [1, 1]), ([], [3], [1, 1]), ([], [3, 1], [1])]
|
|
931
|
+
sage: PartitionTuple([[],[],[]]).down_list()
|
|
932
|
+
[]
|
|
933
|
+
"""
|
|
934
|
+
return list(self.down())
|
|
935
|
+
|
|
936
|
+
def cells(self):
|
|
937
|
+
"""
|
|
938
|
+
Return the coordinates of the cells of ``self``. Coordinates are given
|
|
939
|
+
as (component index, row index, column index) and are 0 based.
|
|
940
|
+
|
|
941
|
+
EXAMPLES::
|
|
942
|
+
|
|
943
|
+
sage: PartitionTuple([[2,1],[1],[1,1,1]]).cells()
|
|
944
|
+
[(0, 0, 0), (0, 0, 1), (0, 1, 0), (1, 0, 0), (2, 0, 0), (2, 1, 0), (2, 2, 0)]
|
|
945
|
+
"""
|
|
946
|
+
return [(c,a,b) for c in range(len(self)) for (a,b) in self[c].cells()]
|
|
947
|
+
|
|
948
|
+
def content(self, k, r, c, multicharge):
|
|
949
|
+
r"""
|
|
950
|
+
Return the content of the cell.
|
|
951
|
+
|
|
952
|
+
Let `m_k =` ``multicharge[k]``, then the content of a cell is
|
|
953
|
+
`m_k + c - r`.
|
|
954
|
+
|
|
955
|
+
If the ``multicharge`` is a list of integers then it simply offsets the
|
|
956
|
+
values of the contents in each component. On the other hand, if the
|
|
957
|
+
``multicharge`` belongs to `\ZZ/e\ZZ` then the corresponding
|
|
958
|
+
`e`-residue is returned (that is, the content mod `e`).
|
|
959
|
+
|
|
960
|
+
As with the content method for partitions, the content of a cell does
|
|
961
|
+
not technically depend on the partition tuple, but this method is
|
|
962
|
+
included because it is often useful.
|
|
963
|
+
|
|
964
|
+
EXAMPLES::
|
|
965
|
+
|
|
966
|
+
sage: PartitionTuple([[2,1],[2],[1,1,1]]).content(0,1,0, [0,0,0])
|
|
967
|
+
-1
|
|
968
|
+
sage: PartitionTuple([[2,1],[2],[1,1,1]]).content(0,1,0, [1,0,0])
|
|
969
|
+
0
|
|
970
|
+
sage: PartitionTuple([[2,1],[2],[1,1,1]]).content(2,1,0, [0,0,0])
|
|
971
|
+
-1
|
|
972
|
+
|
|
973
|
+
and now we return the 3-residue of a cell::
|
|
974
|
+
|
|
975
|
+
sage: multicharge = [IntegerModRing(3)(c) for c in [0,0,0]]
|
|
976
|
+
sage: PartitionTuple([[2,1],[2],[1,1,1]]).content(0,1,0, multicharge)
|
|
977
|
+
2
|
|
978
|
+
"""
|
|
979
|
+
return multicharge[k]-r+c
|
|
980
|
+
|
|
981
|
+
def content_tableau(self, multicharge):
|
|
982
|
+
"""
|
|
983
|
+
Return the tableau which has (k,r,c)th entry equal to the content
|
|
984
|
+
``multicharge[k]-r+c`` of this cell.
|
|
985
|
+
|
|
986
|
+
As with the content function, by setting the ``multicharge``
|
|
987
|
+
appropriately the tableau containing the residues is returned.
|
|
988
|
+
|
|
989
|
+
EXAMPLES::
|
|
990
|
+
|
|
991
|
+
sage: PartitionTuple([[2,1],[2],[1,1,1]]).content_tableau([0,0,0])
|
|
992
|
+
([[0, 1], [-1]], [[0, 1]], [[0], [-1], [-2]])
|
|
993
|
+
sage: PartitionTuple([[2,1],[2],[1,1,1]]).content_tableau([0,0,1]).pp()
|
|
994
|
+
0 1 0 1 1
|
|
995
|
+
-1 0
|
|
996
|
+
-1
|
|
997
|
+
|
|
998
|
+
as with the content function the multicharge can be used to return the
|
|
999
|
+
tableau containing the residues of the cells::
|
|
1000
|
+
|
|
1001
|
+
sage: multicharge=[ IntegerModRing(3)(c) for c in [0,0,1] ]
|
|
1002
|
+
sage: PartitionTuple([[2,1],[2],[1,1,1]]).content_tableau(multicharge).pp()
|
|
1003
|
+
0 1 0 1 1
|
|
1004
|
+
2 0
|
|
1005
|
+
2
|
|
1006
|
+
"""
|
|
1007
|
+
from sage.combinat.tableau_tuple import TableauTuple
|
|
1008
|
+
return TableauTuple([[[multicharge[k] - r + c
|
|
1009
|
+
for c in range(self[k][r])]
|
|
1010
|
+
for r in range(len(self[k]))]
|
|
1011
|
+
for k in range(len(self))])
|
|
1012
|
+
|
|
1013
|
+
def conjugate(self):
|
|
1014
|
+
"""
|
|
1015
|
+
Return the conjugate partition tuple of ``self``.
|
|
1016
|
+
|
|
1017
|
+
The conjugate partition tuple is obtained by reversing the order of the
|
|
1018
|
+
components and then swapping the rows and columns in each component.
|
|
1019
|
+
|
|
1020
|
+
EXAMPLES::
|
|
1021
|
+
|
|
1022
|
+
sage: PartitionTuple([[2,1],[1],[1,1,1]]).conjugate()
|
|
1023
|
+
([3], [1], [2, 1])
|
|
1024
|
+
"""
|
|
1025
|
+
return PartitionTuple([nu.conjugate() for nu in self[::-1]])
|
|
1026
|
+
|
|
1027
|
+
def dominates(self, mu):
|
|
1028
|
+
r"""
|
|
1029
|
+
Return ``True`` if the PartitionTuple dominates or equals `\mu` and
|
|
1030
|
+
``False`` otherwise.
|
|
1031
|
+
|
|
1032
|
+
Given partition tuples `\mu=(\mu^{(1)},...,\mu^{(m)})` and `\nu=(\nu^{(1)},...,\nu^{(n)})`
|
|
1033
|
+
then `\mu` dominates `\nu` if
|
|
1034
|
+
|
|
1035
|
+
.. MATH::
|
|
1036
|
+
|
|
1037
|
+
\sum_{k=1}^{l-1} |\mu^{(k)}| +\sum_{r \geq 1} \mu^{(l)}_r
|
|
1038
|
+
\geq \sum_{k=1}^{l-1} |\nu^{(k)}| + \sum_{r \geq 1} \nu^{(l)}_r
|
|
1039
|
+
|
|
1040
|
+
EXAMPLES::
|
|
1041
|
+
|
|
1042
|
+
sage: mu=PartitionTuple([[1,1],[2],[2,1]])
|
|
1043
|
+
sage: nu=PartitionTuple([[1,1],[1,1],[2,1]])
|
|
1044
|
+
sage: mu.dominates(mu)
|
|
1045
|
+
True
|
|
1046
|
+
sage: mu.dominates(nu)
|
|
1047
|
+
True
|
|
1048
|
+
sage: nu.dominates(mu)
|
|
1049
|
+
False
|
|
1050
|
+
sage: tau=PartitionTuple([[],[2,1],[]])
|
|
1051
|
+
sage: tau.dominates([[2,1],[],[]])
|
|
1052
|
+
False
|
|
1053
|
+
sage: tau.dominates([[],[],[2,1]])
|
|
1054
|
+
True
|
|
1055
|
+
"""
|
|
1056
|
+
try:
|
|
1057
|
+
mu = PartitionTuple(mu)
|
|
1058
|
+
except ValueError:
|
|
1059
|
+
raise ValueError('%s must be a PartitionTuple' % mu)
|
|
1060
|
+
|
|
1061
|
+
if mu == self:
|
|
1062
|
+
return True
|
|
1063
|
+
level = 0
|
|
1064
|
+
ssum = 0 # sum of successive rows in self
|
|
1065
|
+
musum = 0 # sum of successive rows in self
|
|
1066
|
+
while level < self.level() and level < mu.level():
|
|
1067
|
+
row = 0
|
|
1068
|
+
while row < len(self[level]) and row < len(mu[level]):
|
|
1069
|
+
ssum += self[level][row]
|
|
1070
|
+
musum += mu[level][row]
|
|
1071
|
+
if musum > ssum:
|
|
1072
|
+
return False
|
|
1073
|
+
row += 1
|
|
1074
|
+
if row < len(self[level]):
|
|
1075
|
+
ssum += sum(self[level][row:])
|
|
1076
|
+
elif row < len(mu[level]):
|
|
1077
|
+
musum += sum(mu[level][row:])
|
|
1078
|
+
if musum > ssum:
|
|
1079
|
+
return False
|
|
1080
|
+
level += 1
|
|
1081
|
+
return True
|
|
1082
|
+
|
|
1083
|
+
@cached_method
|
|
1084
|
+
def initial_tableau(self):
|
|
1085
|
+
r"""
|
|
1086
|
+
Return the :class:`StandardTableauTuple` which has the numbers
|
|
1087
|
+
`1, 2, \ldots, n`, where `n` is the :meth:`size` of ``self``,
|
|
1088
|
+
entered in order from left to right along the rows of each component,
|
|
1089
|
+
where the components are ordered from left to right.
|
|
1090
|
+
|
|
1091
|
+
EXAMPLES::
|
|
1092
|
+
|
|
1093
|
+
sage: PartitionTuple([ [2,1],[3,2] ]).initial_tableau()
|
|
1094
|
+
([[1, 2], [3]], [[4, 5, 6], [7, 8]])
|
|
1095
|
+
"""
|
|
1096
|
+
from .tableau_tuple import StandardTableauTuples
|
|
1097
|
+
return StandardTableauTuples(self).first()
|
|
1098
|
+
|
|
1099
|
+
@cached_method
|
|
1100
|
+
def initial_column_tableau(self):
|
|
1101
|
+
r"""
|
|
1102
|
+
Return the initial column tableau of shape ``self``.
|
|
1103
|
+
|
|
1104
|
+
The initial column tableau of shape `\lambda` is the standard tableau
|
|
1105
|
+
that has the numbers `1` to `n`, where `n` is the :meth:`size`
|
|
1106
|
+
of `\lambda`, entered in order from top to bottom, and then left
|
|
1107
|
+
to right, down the columns of each component, starting from the
|
|
1108
|
+
rightmost component and working to the left.
|
|
1109
|
+
|
|
1110
|
+
EXAMPLES::
|
|
1111
|
+
|
|
1112
|
+
sage: PartitionTuple([ [3,1],[3,2] ]).initial_column_tableau()
|
|
1113
|
+
([[6, 8, 9], [7]], [[1, 3, 5], [2, 4]])
|
|
1114
|
+
"""
|
|
1115
|
+
return self.conjugate().initial_tableau().conjugate()
|
|
1116
|
+
|
|
1117
|
+
def garnir_tableau(self, *cell):
|
|
1118
|
+
r"""
|
|
1119
|
+
Return the Garnir tableau of shape ``self`` corresponding to the cell
|
|
1120
|
+
``cell``.
|
|
1121
|
+
|
|
1122
|
+
If ``cell`` `= (k,a,c)` then `(k,a+1,c)` must belong to the diagram of
|
|
1123
|
+
the :class:`PartitionTuple`. If this is not the case then we return
|
|
1124
|
+
``False``.
|
|
1125
|
+
|
|
1126
|
+
.. NOTE::
|
|
1127
|
+
|
|
1128
|
+
The function also sets ``g._garnir_cell`` equal to ``cell``
|
|
1129
|
+
which is used by some other functions.
|
|
1130
|
+
|
|
1131
|
+
The Garnir tableaux play an important role in integral and
|
|
1132
|
+
non-semisimple representation theory because they determine the
|
|
1133
|
+
"straightening" rules for the Specht modules over an arbitrary ring.
|
|
1134
|
+
|
|
1135
|
+
The Garnir tableau are the "first" non-standard tableaux which arise
|
|
1136
|
+
when you act by simple transpositions. If `(k,a,c)` is a cell in the
|
|
1137
|
+
Young diagram of a partition, which is not at the bottom of its
|
|
1138
|
+
column, then the corresponding Garnir tableau has the integers
|
|
1139
|
+
`1, 2, \ldots, n` entered in order from left to right along the rows
|
|
1140
|
+
of the diagram up to the cell `(k,a,c-1)`, then along the cells
|
|
1141
|
+
`(k,a+1,1)` to `(k,a+1,c)`, then `(k,a,c)` until the end of row `a`
|
|
1142
|
+
and then continuing from left to right in the remaining positions.
|
|
1143
|
+
The examples below probably make this clearer!
|
|
1144
|
+
|
|
1145
|
+
EXAMPLES::
|
|
1146
|
+
|
|
1147
|
+
sage: PartitionTuple([[5,3],[2,2],[4,3]]).garnir_tableau((0,0,2)).pp()
|
|
1148
|
+
1 2 6 7 8 9 10 13 14 15 16
|
|
1149
|
+
3 4 5 11 12 17 18 19
|
|
1150
|
+
sage: PartitionTuple([[5,3,3],[2,2],[4,3]]).garnir_tableau((0,0,2)).pp()
|
|
1151
|
+
1 2 6 7 8 12 13 16 17 18 19
|
|
1152
|
+
3 4 5 14 15 20 21 22
|
|
1153
|
+
9 10 11
|
|
1154
|
+
sage: PartitionTuple([[5,3,3],[2,2],[4,3]]).garnir_tableau((0,1,2)).pp()
|
|
1155
|
+
1 2 3 4 5 12 13 16 17 18 19
|
|
1156
|
+
6 7 11 14 15 20 21 22
|
|
1157
|
+
8 9 10
|
|
1158
|
+
sage: PartitionTuple([[5,3,3],[2,2],[4,3]]).garnir_tableau((1,0,0)).pp()
|
|
1159
|
+
1 2 3 4 5 13 14 16 17 18 19
|
|
1160
|
+
6 7 8 12 15 20 21 22
|
|
1161
|
+
9 10 11
|
|
1162
|
+
sage: PartitionTuple([[5,3,3],[2,2],[4,3]]).garnir_tableau((1,0,1)).pp()
|
|
1163
|
+
1 2 3 4 5 12 15 16 17 18 19
|
|
1164
|
+
6 7 8 13 14 20 21 22
|
|
1165
|
+
9 10 11
|
|
1166
|
+
sage: PartitionTuple([[5,3,3],[2,2],[4,3]]).garnir_tableau((2,0,1)).pp()
|
|
1167
|
+
1 2 3 4 5 12 13 16 19 20 21
|
|
1168
|
+
6 7 8 14 15 17 18 22
|
|
1169
|
+
9 10 11
|
|
1170
|
+
sage: PartitionTuple([[5,3,3],[2,2],[4,3]]).garnir_tableau((2,1,1)).pp()
|
|
1171
|
+
Traceback (most recent call last):
|
|
1172
|
+
...
|
|
1173
|
+
ValueError: (comp, row+1, col) must be inside the diagram
|
|
1174
|
+
|
|
1175
|
+
.. SEEALSO::
|
|
1176
|
+
|
|
1177
|
+
- :meth:`top_garnir_tableau`
|
|
1178
|
+
"""
|
|
1179
|
+
try:
|
|
1180
|
+
(comp, row,col) = cell
|
|
1181
|
+
except ValueError:
|
|
1182
|
+
(comp, row,col) = cell[0]
|
|
1183
|
+
|
|
1184
|
+
if comp >= len(self) or row+1 >= len(self[comp]) or col >= self[comp][row+1]:
|
|
1185
|
+
raise ValueError('(comp, row+1, col) must be inside the diagram')
|
|
1186
|
+
g = self.initial_tableau().to_list()
|
|
1187
|
+
a = g[comp][row][col]
|
|
1188
|
+
g[comp][row][col:] = list(range(a+col+1, g[comp][row+1][col]+1))
|
|
1189
|
+
g[comp][row+1][:col+1] = list(range(a, a+col+1))
|
|
1190
|
+
from .tableau_tuple import TableauTuple
|
|
1191
|
+
g = TableauTuple(g)
|
|
1192
|
+
g._garnir_cell = (comp,row,col)
|
|
1193
|
+
return g
|
|
1194
|
+
|
|
1195
|
+
def top_garnir_tableau(self, e, cell):
|
|
1196
|
+
r"""
|
|
1197
|
+
Return the most dominant *standard* tableau which dominates the
|
|
1198
|
+
corresponding Garnir tableau and has the same residue that has shape
|
|
1199
|
+
``self`` and is determined by ``e`` and ``cell``.
|
|
1200
|
+
|
|
1201
|
+
The Garnir tableau play an important role in integral and
|
|
1202
|
+
non-semisimple representation theory because they determine the
|
|
1203
|
+
"straightening" rules for the Specht modules over an arbitrary ring.
|
|
1204
|
+
The *top Garnir tableaux* arise in the graded representation theory of
|
|
1205
|
+
the symmetric groups and higher level Hecke algebras. They were
|
|
1206
|
+
introduced in [KMR2012]_.
|
|
1207
|
+
|
|
1208
|
+
If the Garnir node is ``cell=(k,r,c)`` and `m` and `M` are the entries
|
|
1209
|
+
in the cells ``(k,r,c)`` and ``(k,r+1,c)``, respectively, in the
|
|
1210
|
+
initial tableau then the top ``e``-Garnir tableau is obtained by
|
|
1211
|
+
inserting the numbers `m, m+1, \ldots, M` in order from left to right
|
|
1212
|
+
first in the cells in row ``r+1`` which are not in the ``e``-Garnir
|
|
1213
|
+
belt, then in the cell in rows ``r`` and ``r+1`` which are in the
|
|
1214
|
+
Garnir belt and then, finally, in the remaining cells in row ``r``
|
|
1215
|
+
which are not in the Garnir belt. All other entries in the tableau
|
|
1216
|
+
remain unchanged.
|
|
1217
|
+
|
|
1218
|
+
If ``e = 0``, or if there are no ``e``-bricks in either row ``r`` or
|
|
1219
|
+
``r+1``, then the top Garnir tableau is the corresponding Garnir
|
|
1220
|
+
tableau.
|
|
1221
|
+
|
|
1222
|
+
EXAMPLES::
|
|
1223
|
+
|
|
1224
|
+
sage: PartitionTuple([[3,3,2],[5,4,3,2]]).top_garnir_tableau(2,(1,0,2)).pp()
|
|
1225
|
+
1 2 3 9 10 12 13 16
|
|
1226
|
+
4 5 6 11 14 15 17
|
|
1227
|
+
7 8 18 19 20
|
|
1228
|
+
21 22
|
|
1229
|
+
sage: PartitionTuple([[3,3,2],[5,4,3,2]]).top_garnir_tableau(2,(1,0,1)).pp()
|
|
1230
|
+
1 2 3 9 10 11 12 13
|
|
1231
|
+
4 5 6 14 15 16 17
|
|
1232
|
+
7 8 18 19 20
|
|
1233
|
+
21 22
|
|
1234
|
+
sage: PartitionTuple([[3,3,2],[5,4,3,2]]).top_garnir_tableau(3,(1,0,1)).pp()
|
|
1235
|
+
1 2 3 9 12 13 14 15
|
|
1236
|
+
4 5 6 10 11 16 17
|
|
1237
|
+
7 8 18 19 20
|
|
1238
|
+
21 22
|
|
1239
|
+
|
|
1240
|
+
sage: PartitionTuple([[3,3,2],[5,4,3,2]]).top_garnir_tableau(3,(3,0,1)).pp()
|
|
1241
|
+
Traceback (most recent call last):
|
|
1242
|
+
...
|
|
1243
|
+
ValueError: (comp, row+1, col) must be inside the diagram
|
|
1244
|
+
|
|
1245
|
+
.. SEEALSO::
|
|
1246
|
+
|
|
1247
|
+
- :meth:`~sage.combinat.partition.Partition_tuple.garnir_tableau`
|
|
1248
|
+
"""
|
|
1249
|
+
(comp,row,col) = cell
|
|
1250
|
+
if comp >= len(self) or row+1 >= len(self[comp]) or col >= self[comp][row+1]:
|
|
1251
|
+
raise ValueError('(comp, row+1, col) must be inside the diagram')
|
|
1252
|
+
|
|
1253
|
+
g = self.garnir_tableau(cell)
|
|
1254
|
+
|
|
1255
|
+
if e == 0:
|
|
1256
|
+
return # no more dominant tableau of the same residue
|
|
1257
|
+
|
|
1258
|
+
a = e*int((self[comp][row]-col)/e) # number of cells in the e-bricks in row `row`
|
|
1259
|
+
b = e*int((col+1)/e) # number of cells in the e-bricks in row `row+1`
|
|
1260
|
+
|
|
1261
|
+
if a == 0 or b == 0:
|
|
1262
|
+
return self.garnir_tableau(cell)
|
|
1263
|
+
|
|
1264
|
+
t = g.to_list()
|
|
1265
|
+
m = t[comp][row+1][0] # smallest number of 0-Garnir belt
|
|
1266
|
+
# now we will put the number m,m+1,...,t[row+1][col] in order into t
|
|
1267
|
+
t[comp][row][col:a+col] = [m+col-b+1+i for i in range(a)]
|
|
1268
|
+
t[comp][row+1][col-b+1:col+1] = [m+a+col-b+1+i for i in range(b)]
|
|
1269
|
+
from .tableau_tuple import StandardTableauTuple
|
|
1270
|
+
return StandardTableauTuple(t)
|
|
1271
|
+
|
|
1272
|
+
def arm_length(self, k, r, c):
|
|
1273
|
+
"""
|
|
1274
|
+
Return the length of the arm of cell ``(k, r, c)`` in ``self``.
|
|
1275
|
+
|
|
1276
|
+
INPUT:
|
|
1277
|
+
|
|
1278
|
+
- ``k`` -- the component
|
|
1279
|
+
- ``r`` -- the row
|
|
1280
|
+
- ``c`` -- the cell
|
|
1281
|
+
|
|
1282
|
+
OUTPUT: the arm length as an integer
|
|
1283
|
+
|
|
1284
|
+
The arm of cell ``(k, r, c)`` is the number of cells in the ``k``-th
|
|
1285
|
+
component which are to the right of the cell in row ``r`` and column
|
|
1286
|
+
``c``.
|
|
1287
|
+
|
|
1288
|
+
EXAMPLES::
|
|
1289
|
+
|
|
1290
|
+
sage: PartitionTuple([[],[2,1],[2,2,1],[3]]).arm_length(2,0,0)
|
|
1291
|
+
1
|
|
1292
|
+
sage: PartitionTuple([[],[2,1],[2,2,1],[3]]).arm_length(2,0,1)
|
|
1293
|
+
0
|
|
1294
|
+
sage: PartitionTuple([[],[2,1],[2,2,1],[3]]).arm_length(2,2,0)
|
|
1295
|
+
0
|
|
1296
|
+
"""
|
|
1297
|
+
try:
|
|
1298
|
+
return self[k][r]-(c+1)
|
|
1299
|
+
except IndexError:
|
|
1300
|
+
raise ValueError("The cell %s is not in the diagram" % ((k,r,c),))
|
|
1301
|
+
|
|
1302
|
+
def leg_length(self, k, r, c):
|
|
1303
|
+
"""
|
|
1304
|
+
Return the length of the leg of cell ``(k, r, c)`` in ``self``.
|
|
1305
|
+
|
|
1306
|
+
INPUT:
|
|
1307
|
+
|
|
1308
|
+
- ``k`` -- the component
|
|
1309
|
+
- ``r`` -- the row
|
|
1310
|
+
- ``c`` -- the cell
|
|
1311
|
+
|
|
1312
|
+
OUTPUT: the leg length as an integer
|
|
1313
|
+
|
|
1314
|
+
The leg of cell ``(k, r, c)`` is the number of cells in the ``k``-th
|
|
1315
|
+
component which are below the node in row ``r`` and column ``c``.
|
|
1316
|
+
|
|
1317
|
+
EXAMPLES::
|
|
1318
|
+
|
|
1319
|
+
sage: PartitionTuple([[],[2,1],[2,2,1],[3]]).leg_length(2,0,0)
|
|
1320
|
+
2
|
|
1321
|
+
sage: PartitionTuple([[],[2,1],[2,2,1],[3]]).leg_length(2,0,1)
|
|
1322
|
+
1
|
|
1323
|
+
sage: PartitionTuple([[],[2,1],[2,2,1],[3]]).leg_length(2,2,0)
|
|
1324
|
+
0
|
|
1325
|
+
"""
|
|
1326
|
+
try:
|
|
1327
|
+
return self[k].leg_length(r,c)
|
|
1328
|
+
except IndexError:
|
|
1329
|
+
raise ValueError("The cell is not in the diagram")
|
|
1330
|
+
|
|
1331
|
+
def contains(self, mu):
|
|
1332
|
+
r"""
|
|
1333
|
+
Return ``True`` if this partition tuple contains `\mu`.
|
|
1334
|
+
|
|
1335
|
+
If `\lambda=(\lambda^{(1)}, \ldots, \lambda^{(l)})` and
|
|
1336
|
+
`\mu=(\mu^{(1)}, \ldots, \mu^{(m)})` are two partition tuples then
|
|
1337
|
+
`\lambda` contains `\mu` if `m \leq l` and
|
|
1338
|
+
`\mu^{(i)}_r \leq \lambda^{(i)}_r` for `1 \leq i \leq m` and `r \geq 0`.
|
|
1339
|
+
|
|
1340
|
+
EXAMPLES::
|
|
1341
|
+
|
|
1342
|
+
sage: PartitionTuple([[1,1],[2],[2,1]]).contains( PartitionTuple([[1,1],[2],[2,1]]) )
|
|
1343
|
+
True
|
|
1344
|
+
"""
|
|
1345
|
+
return mu.level() <= self.level() and all(self[c].contains(mu[c]) for c in range(len(mu)))
|
|
1346
|
+
|
|
1347
|
+
def hook_length(self, k, r, c):
|
|
1348
|
+
r"""
|
|
1349
|
+
Return the length of the hook of cell ``(k, r, c)`` in the partition.
|
|
1350
|
+
|
|
1351
|
+
The hook of cell ``(k, r, c)`` is defined as the cells to the right or
|
|
1352
|
+
below (in the English convention). If your coordinates are in the
|
|
1353
|
+
form ``(k,r,c)``, use Python's \*-operator.
|
|
1354
|
+
|
|
1355
|
+
EXAMPLES::
|
|
1356
|
+
|
|
1357
|
+
sage: mu=PartitionTuple([[1,1],[2],[2,1]])
|
|
1358
|
+
sage: [ mu.hook_length(*c) for c in mu.cells()]
|
|
1359
|
+
[2, 1, 2, 1, 3, 1, 1]
|
|
1360
|
+
"""
|
|
1361
|
+
try:
|
|
1362
|
+
return self[k].hook_length(r,c)
|
|
1363
|
+
except IndexError:
|
|
1364
|
+
raise ValueError("The cell is not in the diagram")
|
|
1365
|
+
|
|
1366
|
+
def to_exp(self, k=0):
|
|
1367
|
+
"""
|
|
1368
|
+
Return a tuple of the multiplicities of the parts of a partition.
|
|
1369
|
+
|
|
1370
|
+
Use the optional parameter ``k`` to get a return list of length at
|
|
1371
|
+
least ``k``.
|
|
1372
|
+
|
|
1373
|
+
EXAMPLES::
|
|
1374
|
+
|
|
1375
|
+
sage: PartitionTuple([[1,1],[2],[2,1]]).to_exp()
|
|
1376
|
+
([2], [0, 1], [1, 1])
|
|
1377
|
+
sage: PartitionTuple([[1,1],[2,2,2,2],[2,1]]).to_exp()
|
|
1378
|
+
([2], [0, 4], [1, 1])
|
|
1379
|
+
"""
|
|
1380
|
+
return tuple(self[c].to_exp(k) for c in range(len(self)))
|
|
1381
|
+
|
|
1382
|
+
def removable_cells(self):
|
|
1383
|
+
"""
|
|
1384
|
+
Return a list of the removable cells of this partition tuple.
|
|
1385
|
+
|
|
1386
|
+
All indices are of the form ``(k, r, c)``, where ``r`` is the
|
|
1387
|
+
row-index, ``c`` is the column index and ``k`` is the component.
|
|
1388
|
+
|
|
1389
|
+
EXAMPLES::
|
|
1390
|
+
|
|
1391
|
+
sage: PartitionTuple([[1,1],[2],[2,1]]).removable_cells()
|
|
1392
|
+
[(0, 1, 0), (1, 0, 1), (2, 0, 1), (2, 1, 0)]
|
|
1393
|
+
sage: PartitionTuple([[1,1],[4,3],[2,1,1]]).removable_cells()
|
|
1394
|
+
[(0, 1, 0), (1, 0, 3), (1, 1, 2), (2, 0, 1), (2, 2, 0)]
|
|
1395
|
+
"""
|
|
1396
|
+
return [(k,r,c) for k in range(len(self)) for (r,c) in self[k].removable_cells()]
|
|
1397
|
+
|
|
1398
|
+
corners = removable_cells # for compatibility with partitions
|
|
1399
|
+
|
|
1400
|
+
def addable_cells(self):
|
|
1401
|
+
"""
|
|
1402
|
+
Return a list of the removable cells of this partition tuple.
|
|
1403
|
+
|
|
1404
|
+
All indices are of the form ``(k, r, c)``, where ``r`` is the
|
|
1405
|
+
row-index, ``c`` is the column index and ``k`` is the component.
|
|
1406
|
+
|
|
1407
|
+
EXAMPLES::
|
|
1408
|
+
|
|
1409
|
+
sage: PartitionTuple([[1,1],[2],[2,1]]).addable_cells()
|
|
1410
|
+
[(0, 0, 1), (0, 2, 0), (1, 0, 2), (1, 1, 0), (2, 0, 2), (2, 1, 1), (2, 2, 0)]
|
|
1411
|
+
sage: PartitionTuple([[1,1],[4,3],[2,1,1]]).addable_cells()
|
|
1412
|
+
[(0, 0, 1), (0, 2, 0), (1, 0, 4), (1, 1, 3), (1, 2, 0), (2, 0, 2), (2, 1, 1), (2, 3, 0)]
|
|
1413
|
+
"""
|
|
1414
|
+
return [(k,r,c) for k in range(len(self)) for (r,c) in self[k].addable_cells()]
|
|
1415
|
+
|
|
1416
|
+
outside_corners = addable_cells # for compatibility with partitions
|
|
1417
|
+
|
|
1418
|
+
def add_cell(self, k, r, c):
|
|
1419
|
+
r"""
|
|
1420
|
+
Return the partition tuple obtained by adding a cell in row ``r``,
|
|
1421
|
+
column ``c``, and component ``k``.
|
|
1422
|
+
|
|
1423
|
+
This does not change ``self``.
|
|
1424
|
+
|
|
1425
|
+
EXAMPLES::
|
|
1426
|
+
|
|
1427
|
+
sage: PartitionTuple([[1,1],[4,3],[2,1,1]]).add_cell(0,0,1)
|
|
1428
|
+
([2, 1], [4, 3], [2, 1, 1])
|
|
1429
|
+
"""
|
|
1430
|
+
if (k, r, c) in self.addable_cells(): # an addable cell
|
|
1431
|
+
mu = self.to_list()
|
|
1432
|
+
if c == 0:
|
|
1433
|
+
mu[k].append(1)
|
|
1434
|
+
else:
|
|
1435
|
+
mu[k][r] += 1
|
|
1436
|
+
return PartitionTuple(mu)
|
|
1437
|
+
else:
|
|
1438
|
+
raise ValueError("%s is not an addable cell" % ((k, r, c),))
|
|
1439
|
+
|
|
1440
|
+
def remove_cell(self, k, r, c):
|
|
1441
|
+
"""
|
|
1442
|
+
Return the partition tuple obtained by removing a cell in row ``r``,
|
|
1443
|
+
column ``c``, and component ``k``.
|
|
1444
|
+
|
|
1445
|
+
This does not change ``self``.
|
|
1446
|
+
|
|
1447
|
+
EXAMPLES::
|
|
1448
|
+
|
|
1449
|
+
sage: PartitionTuple([[1,1],[4,3],[2,1,1]]).remove_cell(0,1,0)
|
|
1450
|
+
([1], [4, 3], [2, 1, 1])
|
|
1451
|
+
"""
|
|
1452
|
+
if (k, r, c) in self.removable_cells(): # a removable cell
|
|
1453
|
+
mu = self.to_list()
|
|
1454
|
+
mu[k][r] -= 1
|
|
1455
|
+
return PartitionTuple(mu)
|
|
1456
|
+
else:
|
|
1457
|
+
raise ValueError("%s is not a removable cell" % ((k, r, c),))
|
|
1458
|
+
|
|
1459
|
+
def to_list(self):
|
|
1460
|
+
r"""
|
|
1461
|
+
Return ``self`` as a list of lists.
|
|
1462
|
+
|
|
1463
|
+
EXAMPLES::
|
|
1464
|
+
|
|
1465
|
+
sage: PartitionTuple([[1,1],[4,3],[2,1,1]]).to_list()
|
|
1466
|
+
[[1, 1], [4, 3], [2, 1, 1]]
|
|
1467
|
+
|
|
1468
|
+
TESTS::
|
|
1469
|
+
|
|
1470
|
+
sage: all(mu==PartitionTuple(mu.to_list()) for mu in PartitionTuples(4,4)) # needs sage.libs.flint
|
|
1471
|
+
True
|
|
1472
|
+
"""
|
|
1473
|
+
return [mu.to_list() for mu in self]
|
|
1474
|
+
|
|
1475
|
+
def young_subgroup(self):
|
|
1476
|
+
"""
|
|
1477
|
+
Return the corresponding Young, or parabolic, subgroup of the
|
|
1478
|
+
symmetric group.
|
|
1479
|
+
|
|
1480
|
+
EXAMPLES::
|
|
1481
|
+
|
|
1482
|
+
sage: PartitionTuple([[2,1],[4,2],[1]]).young_subgroup() # needs sage.groups
|
|
1483
|
+
Permutation Group with generators [(), (8,9), (6,7), (5,6), (4,5), (1,2)]
|
|
1484
|
+
"""
|
|
1485
|
+
gens = []
|
|
1486
|
+
m = 0
|
|
1487
|
+
for comp in self:
|
|
1488
|
+
for row in comp:
|
|
1489
|
+
gens.extend((c, c + 1) for c in range(m + 1, m + row))
|
|
1490
|
+
m += row
|
|
1491
|
+
gens.append(list(range(1, self.size()+1))) # to ensure we get a subgroup of Sym_n
|
|
1492
|
+
return PermutationGroup(gens)
|
|
1493
|
+
|
|
1494
|
+
def young_subgroup_generators(self):
|
|
1495
|
+
"""
|
|
1496
|
+
Return an indexing set for the generators of the corresponding Young
|
|
1497
|
+
subgroup.
|
|
1498
|
+
|
|
1499
|
+
EXAMPLES::
|
|
1500
|
+
|
|
1501
|
+
sage: PartitionTuple([[2,1],[4,2],[1]]).young_subgroup_generators()
|
|
1502
|
+
[1, 4, 5, 6, 8]
|
|
1503
|
+
"""
|
|
1504
|
+
gens = []
|
|
1505
|
+
m = 0
|
|
1506
|
+
for comp in self:
|
|
1507
|
+
for row in comp:
|
|
1508
|
+
gens.extend(range(m + 1, m + row))
|
|
1509
|
+
m += row
|
|
1510
|
+
return gens
|
|
1511
|
+
|
|
1512
|
+
@cached_method
|
|
1513
|
+
def _initial_degree(self, e, multicharge):
|
|
1514
|
+
r"""
|
|
1515
|
+
Return the Brundan-Kleshchev-Wang degree of the initial tableau
|
|
1516
|
+
of shape ``self``.
|
|
1517
|
+
|
|
1518
|
+
This degree depends only the shape of the tableau and it is
|
|
1519
|
+
used as the base case for computing the degrees of all tableau of
|
|
1520
|
+
shape ``self``, which is why this method is cached. See
|
|
1521
|
+
:meth:`sage.combinat.tableau.Tableau.degree` for more information.
|
|
1522
|
+
|
|
1523
|
+
EXAMPLES::
|
|
1524
|
+
|
|
1525
|
+
sage: PartitionTuple([[2,1],[2,2]])._initial_degree(0,(0,0))
|
|
1526
|
+
1
|
|
1527
|
+
sage: PartitionTuple([[2,1],[2,2]])._initial_degree(2,(0,0))
|
|
1528
|
+
4
|
|
1529
|
+
sage: PartitionTuple([[2,1],[2,2]])._initial_degree(3,(0,0))
|
|
1530
|
+
1
|
|
1531
|
+
sage: PartitionTuple([[2,1],[2,2]])._initial_degree(4,(0,0))
|
|
1532
|
+
1
|
|
1533
|
+
"""
|
|
1534
|
+
if e == 0:
|
|
1535
|
+
deg = 0
|
|
1536
|
+
else:
|
|
1537
|
+
deg = sum(mu._initial_degree(e) for mu in self)
|
|
1538
|
+
I = IntegerModRing(e)
|
|
1539
|
+
multires = [I(k) for k in multicharge]
|
|
1540
|
+
for (k,r,c) in self.cells():
|
|
1541
|
+
res = I(multicharge[k]-r+c)
|
|
1542
|
+
for l in range(k+1, self.level()):
|
|
1543
|
+
if res == multires[l]:
|
|
1544
|
+
deg += 1
|
|
1545
|
+
return deg
|
|
1546
|
+
|
|
1547
|
+
def degree(self, e):
|
|
1548
|
+
r"""
|
|
1549
|
+
Return the ``e``-th degree of ``self``.
|
|
1550
|
+
|
|
1551
|
+
The `e`-th degree is the sum of the degrees of the standard
|
|
1552
|
+
tableaux of shape `\lambda`. The `e`-th degree is the exponent
|
|
1553
|
+
of `\Phi_e(q)` in the Gram determinant of the Specht module for a
|
|
1554
|
+
semisimple cyclotomic Hecke algebra of type `A` with parameter `q`.
|
|
1555
|
+
|
|
1556
|
+
For this calculation the multicharge `(\kappa_1, \ldots, \kappa_l)`
|
|
1557
|
+
is chosen so that `\kappa_{r+1} - \kappa_r > n`, where `n` is
|
|
1558
|
+
the :meth:`size` of `\lambda` as this ensures that the Hecke algebra
|
|
1559
|
+
is semisimple.
|
|
1560
|
+
|
|
1561
|
+
INPUT:
|
|
1562
|
+
|
|
1563
|
+
- ``e`` -- integer `e > 1`
|
|
1564
|
+
|
|
1565
|
+
OUTPUT: nonnegative integer
|
|
1566
|
+
|
|
1567
|
+
EXAMPLES::
|
|
1568
|
+
|
|
1569
|
+
sage: PartitionTuple([[2,1],[2,2]]).degree(2)
|
|
1570
|
+
532
|
|
1571
|
+
sage: PartitionTuple([[2,1],[2,2]]).degree(3)
|
|
1572
|
+
259
|
|
1573
|
+
sage: PartitionTuple([[2,1],[2,2]]).degree(4)
|
|
1574
|
+
196
|
|
1575
|
+
sage: PartitionTuple([[2,1],[2,2]]).degree(5)
|
|
1576
|
+
105
|
|
1577
|
+
sage: PartitionTuple([[2,1],[2,2]]).degree(6)
|
|
1578
|
+
105
|
|
1579
|
+
sage: PartitionTuple([[2,1],[2,2]]).degree(7)
|
|
1580
|
+
0
|
|
1581
|
+
|
|
1582
|
+
Therefore, the Gram determinant of `S(2,1|2,2)` when the Hecke parameter
|
|
1583
|
+
`q` is "generic" is
|
|
1584
|
+
|
|
1585
|
+
.. MATH::
|
|
1586
|
+
|
|
1587
|
+
q^N \Phi_2(q)^{532}\Phi_3(q)^{259}\Phi_4(q)^{196}\Phi_5(q)^{105}\Phi_6(q)^{105}
|
|
1588
|
+
|
|
1589
|
+
for some integer `N`. Compare with :meth:`prime_degree`.
|
|
1590
|
+
"""
|
|
1591
|
+
multicharge = tuple([i*self.size() for i in range(self.size())])
|
|
1592
|
+
return sum(t.degree(e, multicharge) for t in self.standard_tableaux())
|
|
1593
|
+
|
|
1594
|
+
def prime_degree(self, p):
|
|
1595
|
+
r"""
|
|
1596
|
+
Return the ``p``-th prime degree of ``self``.
|
|
1597
|
+
|
|
1598
|
+
The degree of a partition `\lambda` is the sum of the `e`-degrees`
|
|
1599
|
+
of the standard tableaux of shape `\lambda` (see :meth:`degree`),
|
|
1600
|
+
for `e` a power of the prime `p`. The prime degree gives the
|
|
1601
|
+
exponent of `p` in the Gram determinant of the integral Specht
|
|
1602
|
+
module of the symmetric group.
|
|
1603
|
+
|
|
1604
|
+
The `p`-th degree is the sum of the degrees of the standard tableaux
|
|
1605
|
+
of shape `\lambda`. The `p`-th degree is the exponent of `p` in the
|
|
1606
|
+
Gram determinant of a semisimple cyclotomic Hecke algebra of type `A`
|
|
1607
|
+
with parameter `q = 1`.
|
|
1608
|
+
|
|
1609
|
+
As with :meth:`degree`, for this calculation the multicharge
|
|
1610
|
+
`(\kappa_1, \ldots, \kappa_l)` is chosen so that
|
|
1611
|
+
`\kappa_{r+1} - \kappa_r > n`, where `n` is the :meth:`size`
|
|
1612
|
+
of `\lambda` as this ensures that the Hecke algebra is semisimple.
|
|
1613
|
+
|
|
1614
|
+
INPUT:
|
|
1615
|
+
|
|
1616
|
+
- ``e`` -- an integer `e > 1`
|
|
1617
|
+
- ``multicharge`` -- an `l`-tuple of integers, where `l` is
|
|
1618
|
+
the :meth:`level` of ``self``
|
|
1619
|
+
|
|
1620
|
+
OUTPUT: nonnegative integer
|
|
1621
|
+
|
|
1622
|
+
EXAMPLES::
|
|
1623
|
+
|
|
1624
|
+
sage: PartitionTuple([[2,1],[2,2]]).prime_degree(2)
|
|
1625
|
+
728
|
|
1626
|
+
sage: PartitionTuple([[2,1],[2,2]]).prime_degree(3)
|
|
1627
|
+
259
|
|
1628
|
+
sage: PartitionTuple([[2,1],[2,2]]).prime_degree(5)
|
|
1629
|
+
105
|
|
1630
|
+
sage: PartitionTuple([[2,1],[2,2]]).prime_degree(7)
|
|
1631
|
+
0
|
|
1632
|
+
|
|
1633
|
+
Therefore, the Gram determinant of `S(2,1|2,2)` when `q=1` is
|
|
1634
|
+
`2^{728} 3^{259}5^{105}`. Compare with :meth:`degree`.
|
|
1635
|
+
"""
|
|
1636
|
+
ps = [p]
|
|
1637
|
+
|
|
1638
|
+
while ps[-1]*p < self.size():
|
|
1639
|
+
ps.append(ps[-1] * p)
|
|
1640
|
+
multicharge = tuple([i*self.size() for i in range(self.size())])
|
|
1641
|
+
return sum(t.degree(pk, multicharge) for pk in ps for t in self.standard_tableaux())
|
|
1642
|
+
|
|
1643
|
+
@cached_method
|
|
1644
|
+
def block(self, e, multicharge):
|
|
1645
|
+
r"""
|
|
1646
|
+
Return a dictionary `\beta` that determines the block associated to
|
|
1647
|
+
the partition ``self`` and the
|
|
1648
|
+
:meth:`~sage.combinat.tableau_residues.ResidueSequence.quantum_characteristic` ``e``.
|
|
1649
|
+
|
|
1650
|
+
INPUT:
|
|
1651
|
+
|
|
1652
|
+
- ``e`` -- the quantum characteristic
|
|
1653
|
+
|
|
1654
|
+
- ``multicharge`` -- the multicharge (default: `(0,)`)
|
|
1655
|
+
|
|
1656
|
+
OUTPUT:
|
|
1657
|
+
|
|
1658
|
+
- a dictionary giving the multiplicities of the residues in the
|
|
1659
|
+
partition tuple ``self``
|
|
1660
|
+
|
|
1661
|
+
In more detail, the value ``beta[i]`` is equal to the
|
|
1662
|
+
number of nodes of residue ``i``. This corresponds to
|
|
1663
|
+
the positive root
|
|
1664
|
+
|
|
1665
|
+
.. MATH::
|
|
1666
|
+
|
|
1667
|
+
\sum_{i\in I} \beta_i \alpha_i \in Q^+,
|
|
1668
|
+
|
|
1669
|
+
a element of the positive root lattice of the corresponding
|
|
1670
|
+
Kac-Moody algebra. See [DJM1998]_ and [BK2009]_ for more details.
|
|
1671
|
+
|
|
1672
|
+
This is a useful statistics because two Specht modules for a cyclotomic
|
|
1673
|
+
Hecke algebra of type `A` belong to the same block if and only if they
|
|
1674
|
+
correspond to same element `\beta` of the root lattice, given above.
|
|
1675
|
+
|
|
1676
|
+
We return a dictionary because when the quantum characteristic is `0`,
|
|
1677
|
+
the Cartan type is `A_{\infty}`, in which case the simple roots are
|
|
1678
|
+
indexed by the integers.
|
|
1679
|
+
|
|
1680
|
+
EXAMPLES::
|
|
1681
|
+
|
|
1682
|
+
sage: PartitionTuple([[2,2],[2,2]]).block(0,(0,0))
|
|
1683
|
+
{-1: 2, 0: 4, 1: 2}
|
|
1684
|
+
sage: PartitionTuple([[2,2],[2,2]]).block(2,(0,0))
|
|
1685
|
+
{0: 4, 1: 4}
|
|
1686
|
+
sage: PartitionTuple([[2,2],[2,2]]).block(2,(0,1))
|
|
1687
|
+
{0: 4, 1: 4}
|
|
1688
|
+
sage: PartitionTuple([[2,2],[2,2]]).block(3,(0,2))
|
|
1689
|
+
{0: 3, 1: 2, 2: 3}
|
|
1690
|
+
sage: PartitionTuple([[2,2],[2,2]]).block(3,(0,2))
|
|
1691
|
+
{0: 3, 1: 2, 2: 3}
|
|
1692
|
+
sage: PartitionTuple([[2,2],[2,2]]).block(3,(3,2))
|
|
1693
|
+
{0: 3, 1: 2, 2: 3}
|
|
1694
|
+
sage: PartitionTuple([[2,2],[2,2]]).block(4,(0,0))
|
|
1695
|
+
{0: 4, 1: 2, 3: 2}
|
|
1696
|
+
"""
|
|
1697
|
+
block = {}
|
|
1698
|
+
Ie = IntegerModRing(e)
|
|
1699
|
+
for (k,r,c) in self.cells():
|
|
1700
|
+
i = Ie(multicharge[k] + c - r)
|
|
1701
|
+
block[i] = block.get(i, 0) + 1
|
|
1702
|
+
return block
|
|
1703
|
+
|
|
1704
|
+
def defect(self, e, multicharge):
|
|
1705
|
+
r"""
|
|
1706
|
+
Return the ``e``-defect or the ``e``-weight ``self``.
|
|
1707
|
+
|
|
1708
|
+
The `e`-defect is the number of (connected) `e`-rim hooks
|
|
1709
|
+
that can be removed from the partition.
|
|
1710
|
+
|
|
1711
|
+
The defect of a partition tuple is given by
|
|
1712
|
+
|
|
1713
|
+
.. MATH::
|
|
1714
|
+
|
|
1715
|
+
\text{defect}(\beta) = (\Lambda, \beta) - \tfrac12(\beta, \beta),
|
|
1716
|
+
|
|
1717
|
+
where `\Lambda = \sum_r \Lambda_{\kappa_r}` for the multicharge
|
|
1718
|
+
`(\kappa_1, \ldots, \kappa_{\ell})` and
|
|
1719
|
+
`\beta = \sum_{(r,c)} \alpha_{(c-r) \pmod e}`, with the sum
|
|
1720
|
+
being over the cells in the partition.
|
|
1721
|
+
|
|
1722
|
+
INPUT:
|
|
1723
|
+
|
|
1724
|
+
- ``e`` -- the quantum characteristic
|
|
1725
|
+
|
|
1726
|
+
- ``multicharge`` -- the multicharge (default: `(0,)`)
|
|
1727
|
+
|
|
1728
|
+
OUTPUT: a nonnegative integer, which is the defect of the block
|
|
1729
|
+
containing the partition tuple ``self``
|
|
1730
|
+
|
|
1731
|
+
EXAMPLES::
|
|
1732
|
+
|
|
1733
|
+
sage: PartitionTuple([[2,2],[2,2]]).defect(0,(0,0))
|
|
1734
|
+
0
|
|
1735
|
+
sage: PartitionTuple([[2,2],[2,2]]).defect(2,(0,0))
|
|
1736
|
+
8
|
|
1737
|
+
sage: PartitionTuple([[2,2],[2,2]]).defect(2,(0,1))
|
|
1738
|
+
8
|
|
1739
|
+
sage: PartitionTuple([[2,2],[2,2]]).defect(3,(0,2))
|
|
1740
|
+
5
|
|
1741
|
+
sage: PartitionTuple([[2,2],[2,2]]).defect(3,(0,2))
|
|
1742
|
+
5
|
|
1743
|
+
sage: PartitionTuple([[2,2],[2,2]]).defect(3,(3,2))
|
|
1744
|
+
2
|
|
1745
|
+
sage: PartitionTuple([[2,2],[2,2]]).defect(4,(0,0))
|
|
1746
|
+
0
|
|
1747
|
+
"""
|
|
1748
|
+
# Will correspond to an element of the positive root lattice
|
|
1749
|
+
# corresponding to the block.
|
|
1750
|
+
# We use a dictionary to cover the case when e = 0.
|
|
1751
|
+
beta = self.block(e, multicharge)
|
|
1752
|
+
Ie = IntegerModRing(e)
|
|
1753
|
+
return (sum(beta.get(r, 0) for r in multicharge)
|
|
1754
|
+
- sum(beta[r]**2 - beta[r] * beta.get(Ie(r+1), 0) for r in beta))
|
|
1755
|
+
|
|
1756
|
+
# -------------------------------------------------
|
|
1757
|
+
# Partition tuples - parent classes
|
|
1758
|
+
# -------------------------------------------------
|
|
1759
|
+
|
|
1760
|
+
|
|
1761
|
+
class PartitionTuples(UniqueRepresentation, Parent):
|
|
1762
|
+
r"""
|
|
1763
|
+
Class of all partition tuples.
|
|
1764
|
+
|
|
1765
|
+
For more information about partition tuples, see :class:`PartitionTuple`.
|
|
1766
|
+
|
|
1767
|
+
This is a factory class which returns the appropriate parent based on
|
|
1768
|
+
the values of ``level``, ``size``, and ``regular``
|
|
1769
|
+
|
|
1770
|
+
INPUT:
|
|
1771
|
+
|
|
1772
|
+
- ``level`` -- the length of the tuple
|
|
1773
|
+
|
|
1774
|
+
- ``size`` -- the total number of cells
|
|
1775
|
+
|
|
1776
|
+
- ``regular`` -- positive integer or a tuple of nonnegative
|
|
1777
|
+
integers; if an integer, the highest multiplicity an entry may
|
|
1778
|
+
have in a component plus `1`
|
|
1779
|
+
|
|
1780
|
+
If a level `k` is specified and ``regular`` is a tuple of integers
|
|
1781
|
+
`\ell_1, \ldots, \ell_k`, then this specifies partition tuples `\mu`
|
|
1782
|
+
such that `\mu_i` is `\ell_i`-regular, where `0` here
|
|
1783
|
+
represents `\infty`-regular partitions (equivalently, partitions
|
|
1784
|
+
without restrictions). If ``regular`` is an integer `\ell`, then
|
|
1785
|
+
we set `\ell_i = \ell` for all `i`.
|
|
1786
|
+
|
|
1787
|
+
TESTS::
|
|
1788
|
+
|
|
1789
|
+
sage: [ [2,1],[],[3] ] in PartitionTuples()
|
|
1790
|
+
True
|
|
1791
|
+
sage: ( [2,1],[],[3] ) in PartitionTuples()
|
|
1792
|
+
True
|
|
1793
|
+
sage: ( [] ) in PartitionTuples()
|
|
1794
|
+
True
|
|
1795
|
+
sage: PartitionTuples(level=1, regular=(0,))
|
|
1796
|
+
Partitions
|
|
1797
|
+
sage: PartitionTuples(level=1, size=3, regular=(0,))
|
|
1798
|
+
Partitions of the integer 3
|
|
1799
|
+
|
|
1800
|
+
Check that :issue:`14145` has been fixed::
|
|
1801
|
+
|
|
1802
|
+
sage: 1 in PartitionTuples()
|
|
1803
|
+
False
|
|
1804
|
+
"""
|
|
1805
|
+
|
|
1806
|
+
@staticmethod
|
|
1807
|
+
def __classcall_private__(klass, level=None, size=None, regular=None):
|
|
1808
|
+
r"""
|
|
1809
|
+
Return the correct parent object based upon the input.
|
|
1810
|
+
|
|
1811
|
+
TESTS::
|
|
1812
|
+
|
|
1813
|
+
sage: PartitionTuples()
|
|
1814
|
+
Partition tuples
|
|
1815
|
+
sage: PartitionTuples(3)
|
|
1816
|
+
Partition tuples of level 3
|
|
1817
|
+
sage: PartitionTuples(size=3)
|
|
1818
|
+
Partition tuples of size 3
|
|
1819
|
+
sage: PartitionTuples(3,8)
|
|
1820
|
+
Partition tuples of level 3 and size 8
|
|
1821
|
+
sage: PartitionTuples(level=3, regular=(0,2,4))
|
|
1822
|
+
(0, 2, 4)-Regular partition tuples of level 3
|
|
1823
|
+
sage: PartitionTuples(level=1,regular=(4,)) is PartitionTuples(level=1, regular=4)
|
|
1824
|
+
True
|
|
1825
|
+
"""
|
|
1826
|
+
# sanity testing
|
|
1827
|
+
if level is not None and (not isinstance(level, (int, Integer)) or level < 1):
|
|
1828
|
+
raise ValueError('the level must be a positive integer')
|
|
1829
|
+
|
|
1830
|
+
if size is not None and (not isinstance(size, (int, Integer)) or size < 0):
|
|
1831
|
+
raise ValueError('the size must be a nonnegative integer')
|
|
1832
|
+
|
|
1833
|
+
if isinstance(regular, (list, tuple)):
|
|
1834
|
+
if level is None:
|
|
1835
|
+
raise ValueError("When no level is specified, regular must be "
|
|
1836
|
+
"a positive integer")
|
|
1837
|
+
if len(regular) != level:
|
|
1838
|
+
raise ValueError("regular must be a list of length {}, got {}".format(
|
|
1839
|
+
level, regular))
|
|
1840
|
+
if regular == 0:
|
|
1841
|
+
raise ValueError("regular must be a positive integer or a tuple "
|
|
1842
|
+
"of nonnegative integers")
|
|
1843
|
+
if level is None:
|
|
1844
|
+
if size is None:
|
|
1845
|
+
if regular is None:
|
|
1846
|
+
return PartitionTuples_all()
|
|
1847
|
+
return RegularPartitionTuples_all(regular)
|
|
1848
|
+
|
|
1849
|
+
if regular is None:
|
|
1850
|
+
return PartitionTuples_size(size)
|
|
1851
|
+
return RegularPartitionTuples_size(size, regular)
|
|
1852
|
+
|
|
1853
|
+
elif level == 1:
|
|
1854
|
+
if isinstance(regular, (list, tuple)):
|
|
1855
|
+
regular = regular[0]
|
|
1856
|
+
if size is None:
|
|
1857
|
+
if regular is None or regular == 0:
|
|
1858
|
+
return _Partitions
|
|
1859
|
+
return RegularPartitions_all(regular)
|
|
1860
|
+
|
|
1861
|
+
if regular is None or regular == 0:
|
|
1862
|
+
return Partitions_n(size)
|
|
1863
|
+
return RegularPartitions_n(size, regular)
|
|
1864
|
+
|
|
1865
|
+
# Higher level
|
|
1866
|
+
if regular is not None:
|
|
1867
|
+
if not isinstance(regular, (list, tuple)):
|
|
1868
|
+
regular = (regular,) * level
|
|
1869
|
+
else:
|
|
1870
|
+
regular = tuple(regular)
|
|
1871
|
+
if size is None:
|
|
1872
|
+
if regular is None:
|
|
1873
|
+
return PartitionTuples_level(level)
|
|
1874
|
+
return RegularPartitionTuples_level(level, regular)
|
|
1875
|
+
if regular is None:
|
|
1876
|
+
return PartitionTuples_level_size(level, size)
|
|
1877
|
+
return RegularPartitionTuples_level_size(level, size, regular)
|
|
1878
|
+
|
|
1879
|
+
Element = PartitionTuple
|
|
1880
|
+
options = Partitions.options
|
|
1881
|
+
|
|
1882
|
+
# default for level
|
|
1883
|
+
_level = None
|
|
1884
|
+
_size = None
|
|
1885
|
+
|
|
1886
|
+
def _element_constructor_(self, mu):
|
|
1887
|
+
r"""
|
|
1888
|
+
Construct an element of :class:`PartitionTuple`.
|
|
1889
|
+
|
|
1890
|
+
INPUT:
|
|
1891
|
+
|
|
1892
|
+
- ``mu`` -- tuple of partitions
|
|
1893
|
+
|
|
1894
|
+
OUTPUT: the corresponding :class:`PartitionTuple` object
|
|
1895
|
+
|
|
1896
|
+
TESTS::
|
|
1897
|
+
|
|
1898
|
+
sage: PartitionTuple([[2],[2],[]]).parent()
|
|
1899
|
+
Partition tuples
|
|
1900
|
+
sage: parts = PartitionTuples(3)
|
|
1901
|
+
sage: parts([[2,1],[1],[2,2,2]]).parent() is parts
|
|
1902
|
+
True
|
|
1903
|
+
sage: PartitionTuples._element_constructor_(PartitionTuples(), [[2,1],[3,2],[1,1,1]])
|
|
1904
|
+
([2, 1], [3, 2], [1, 1, 1])
|
|
1905
|
+
sage: parts([[1,2]])
|
|
1906
|
+
Traceback (most recent call last):
|
|
1907
|
+
...
|
|
1908
|
+
ValueError: [[1, 2]] is not a Partition tuples of level 3
|
|
1909
|
+
"""
|
|
1910
|
+
# one way or another these two cases need to be treated separately
|
|
1911
|
+
if mu == [] or mu == () or mu == [[]]:
|
|
1912
|
+
if mu not in self:
|
|
1913
|
+
raise ValueError('{} is not a {}'.format(mu, self))
|
|
1914
|
+
return self.element_class(self, [_Partitions([])])
|
|
1915
|
+
|
|
1916
|
+
# As partitions are 1-tuples of partitions we need to treat them separately
|
|
1917
|
+
try:
|
|
1918
|
+
mu = [_Partitions(mu)]
|
|
1919
|
+
except ValueError:
|
|
1920
|
+
try:
|
|
1921
|
+
mu = [_Partitions(nu) for nu in mu]
|
|
1922
|
+
except ValueError:
|
|
1923
|
+
raise ValueError('{} is not a {}'.format(mu, self))
|
|
1924
|
+
|
|
1925
|
+
if mu not in self:
|
|
1926
|
+
raise ValueError('{} is not a {}'.format(mu, self))
|
|
1927
|
+
return self.element_class(self, mu)
|
|
1928
|
+
|
|
1929
|
+
def __contains__(self, mu):
|
|
1930
|
+
r"""
|
|
1931
|
+
Return ``True`` if `\mu` is in ``self``.
|
|
1932
|
+
|
|
1933
|
+
TESTS::
|
|
1934
|
+
|
|
1935
|
+
sage: PartitionTuple([[3,2],[2]]) in PartitionTuples()
|
|
1936
|
+
True
|
|
1937
|
+
sage: PartitionTuple([[3,2],[],[],[],[2]]) in PartitionTuples()
|
|
1938
|
+
True
|
|
1939
|
+
sage: PartitionTuple([[2,1],[],[1,1],[],[2]]) in PartitionTuples()
|
|
1940
|
+
True
|
|
1941
|
+
sage: PartitionTuple([[2,1],[],[1,1],[],[3]]) in PartitionTuples()
|
|
1942
|
+
True
|
|
1943
|
+
sage: all(mu in PartitionTuples() for mu in PartitionTuples(3,8)) # needs sage.libs.flint
|
|
1944
|
+
True
|
|
1945
|
+
sage: [5,1,1] in PartitionTuples()
|
|
1946
|
+
True
|
|
1947
|
+
sage: [[5,1,1]] in PartitionTuples()
|
|
1948
|
+
True
|
|
1949
|
+
sage: la = Partition([3,3,1])
|
|
1950
|
+
sage: PT = PartitionTuples()
|
|
1951
|
+
sage: la in PT
|
|
1952
|
+
True
|
|
1953
|
+
sage: PT(la)
|
|
1954
|
+
([3, 3, 1])
|
|
1955
|
+
|
|
1956
|
+
Check that :issue:`14145` is fixed::
|
|
1957
|
+
|
|
1958
|
+
sage: 1 in PartitionTuples()
|
|
1959
|
+
False
|
|
1960
|
+
"""
|
|
1961
|
+
if isinstance(mu, (PartitionTuple, Partition)):
|
|
1962
|
+
return True
|
|
1963
|
+
if isinstance(mu, (tuple, list)):
|
|
1964
|
+
if not mu:
|
|
1965
|
+
return True
|
|
1966
|
+
if mu[0] in ZZ:
|
|
1967
|
+
return mu in _Partitions
|
|
1968
|
+
return all(m in _Partitions for m in mu)
|
|
1969
|
+
return False
|
|
1970
|
+
|
|
1971
|
+
def __getitem__(self, r):
|
|
1972
|
+
r"""
|
|
1973
|
+
The default implementation of ``__getitem__()`` for enumerated sets
|
|
1974
|
+
does not allow slices, so we override it.
|
|
1975
|
+
|
|
1976
|
+
EXAMPLES::
|
|
1977
|
+
|
|
1978
|
+
sage: PartitionTuples()[10:20] # needs sage.libs.flint
|
|
1979
|
+
[([1, 1, 1]),
|
|
1980
|
+
([2], []),
|
|
1981
|
+
([1, 1], []),
|
|
1982
|
+
([1], [1]),
|
|
1983
|
+
([], [2]),
|
|
1984
|
+
([], [1, 1]),
|
|
1985
|
+
([1], [], []),
|
|
1986
|
+
([], [1], []),
|
|
1987
|
+
([], [], [1]),
|
|
1988
|
+
([], [], [], [])]
|
|
1989
|
+
"""
|
|
1990
|
+
if isinstance(r,(int,Integer)):
|
|
1991
|
+
return self.unrank(r)
|
|
1992
|
+
elif isinstance(r,slice):
|
|
1993
|
+
start = 0 if r.start is None else r.start
|
|
1994
|
+
stop = r.stop
|
|
1995
|
+
if stop is None and not self.is_finite():
|
|
1996
|
+
raise ValueError('infinite set')
|
|
1997
|
+
else:
|
|
1998
|
+
raise ValueError('r must be an integer or a slice')
|
|
1999
|
+
count = 0
|
|
2000
|
+
parts = []
|
|
2001
|
+
for t in self:
|
|
2002
|
+
if count == stop:
|
|
2003
|
+
break
|
|
2004
|
+
if count >= start:
|
|
2005
|
+
parts.append(t)
|
|
2006
|
+
count += 1
|
|
2007
|
+
|
|
2008
|
+
# this is to cope with empty slice endpoints like [6:] or [:]
|
|
2009
|
+
if count == stop or stop is None:
|
|
2010
|
+
return parts
|
|
2011
|
+
raise IndexError('value out of range')
|
|
2012
|
+
|
|
2013
|
+
def level(self):
|
|
2014
|
+
"""
|
|
2015
|
+
Return the level or ``None`` if it is not defined.
|
|
2016
|
+
|
|
2017
|
+
EXAMPLES::
|
|
2018
|
+
|
|
2019
|
+
sage: PartitionTuples().level() is None
|
|
2020
|
+
True
|
|
2021
|
+
sage: PartitionTuples(7).level()
|
|
2022
|
+
7
|
|
2023
|
+
"""
|
|
2024
|
+
return self._level
|
|
2025
|
+
|
|
2026
|
+
def size(self):
|
|
2027
|
+
"""
|
|
2028
|
+
Return the size or ``None`` if it is not defined.
|
|
2029
|
+
|
|
2030
|
+
EXAMPLES::
|
|
2031
|
+
|
|
2032
|
+
sage: PartitionTuples().size() is None
|
|
2033
|
+
True
|
|
2034
|
+
sage: PartitionTuples(size=7).size()
|
|
2035
|
+
7
|
|
2036
|
+
"""
|
|
2037
|
+
return self._size
|
|
2038
|
+
|
|
2039
|
+
def _an_element_(self):
|
|
2040
|
+
"""
|
|
2041
|
+
Return a generic element.
|
|
2042
|
+
|
|
2043
|
+
EXAMPLES::
|
|
2044
|
+
|
|
2045
|
+
sage: PartitionTuples().an_element()
|
|
2046
|
+
([1, 1, 1, 1], [2, 1, 1], [3, 1], [4])
|
|
2047
|
+
"""
|
|
2048
|
+
return PartitionTuple(([1, 1, 1, 1], [2, 1, 1], [3, 1], [4]))
|
|
2049
|
+
|
|
2050
|
+
|
|
2051
|
+
class PartitionTuples_all(PartitionTuples):
|
|
2052
|
+
"""
|
|
2053
|
+
Class of partition tuples of a arbitrary level and arbitrary sum.
|
|
2054
|
+
"""
|
|
2055
|
+
|
|
2056
|
+
def __init__(self):
|
|
2057
|
+
r"""
|
|
2058
|
+
Initialize the class.
|
|
2059
|
+
|
|
2060
|
+
EXAMPLES::
|
|
2061
|
+
|
|
2062
|
+
sage: TestSuite( PartitionTuples() ).run() # needs sage.libs.flint
|
|
2063
|
+
"""
|
|
2064
|
+
super().__init__(category=InfiniteEnumeratedSets())
|
|
2065
|
+
|
|
2066
|
+
def _repr_(self):
|
|
2067
|
+
r"""
|
|
2068
|
+
Return a string representation of ``self``.
|
|
2069
|
+
|
|
2070
|
+
EXAMPLES::
|
|
2071
|
+
|
|
2072
|
+
sage: PartitionTuples()
|
|
2073
|
+
Partition tuples
|
|
2074
|
+
"""
|
|
2075
|
+
return 'Partition tuples'
|
|
2076
|
+
|
|
2077
|
+
def __iter__(self):
|
|
2078
|
+
r"""
|
|
2079
|
+
Iterate through the infinite class of partition tuples of arbitrary
|
|
2080
|
+
level and size.
|
|
2081
|
+
|
|
2082
|
+
EXAMPLES::
|
|
2083
|
+
|
|
2084
|
+
sage: PartitionTuples()[:20] # needs sage.libs.flint
|
|
2085
|
+
[([]),
|
|
2086
|
+
([1]),
|
|
2087
|
+
([], []),
|
|
2088
|
+
([2]),
|
|
2089
|
+
([1, 1]),
|
|
2090
|
+
([1], []),
|
|
2091
|
+
([], [1]),
|
|
2092
|
+
([], [], []),
|
|
2093
|
+
([3]),
|
|
2094
|
+
([2, 1]),
|
|
2095
|
+
([1, 1, 1]),
|
|
2096
|
+
([2], []),
|
|
2097
|
+
([1, 1], []),
|
|
2098
|
+
([1], [1]),
|
|
2099
|
+
([], [2]),
|
|
2100
|
+
([], [1, 1]),
|
|
2101
|
+
([1], [], []),
|
|
2102
|
+
([], [1], []),
|
|
2103
|
+
([], [], [1]),
|
|
2104
|
+
([], [], [], [])]
|
|
2105
|
+
"""
|
|
2106
|
+
for size in NN:
|
|
2107
|
+
for level in range(size+1):
|
|
2108
|
+
for mu in PartitionTuples_level_size(level+1,size-level):
|
|
2109
|
+
yield self._element_constructor_(mu)
|
|
2110
|
+
|
|
2111
|
+
def _an_element_(self):
|
|
2112
|
+
"""
|
|
2113
|
+
Return a generic element.
|
|
2114
|
+
|
|
2115
|
+
EXAMPLES::
|
|
2116
|
+
|
|
2117
|
+
sage: PartitionTuples().an_element()
|
|
2118
|
+
([1, 1, 1, 1], [2, 1, 1], [3, 1], [4])
|
|
2119
|
+
"""
|
|
2120
|
+
return self.element_class(self,([1,1,1,1],[2,1,1],[3,1],[4]))
|
|
2121
|
+
|
|
2122
|
+
|
|
2123
|
+
class PartitionTuples_level(PartitionTuples):
|
|
2124
|
+
"""
|
|
2125
|
+
Class of partition tuples of a fixed level, but summing to an arbitrary
|
|
2126
|
+
integer.
|
|
2127
|
+
"""
|
|
2128
|
+
|
|
2129
|
+
def __init__(self, level, category=None):
|
|
2130
|
+
r"""
|
|
2131
|
+
Initialize this class.
|
|
2132
|
+
|
|
2133
|
+
EXAMPLES::
|
|
2134
|
+
|
|
2135
|
+
sage: PartitionTuples(4)
|
|
2136
|
+
Partition tuples of level 4
|
|
2137
|
+
sage: PartitionTuples(level=6)
|
|
2138
|
+
Partition tuples of level 6
|
|
2139
|
+
sage: TestSuite( PartitionTuples(level=4) ).run() # needs sage.libs.flint
|
|
2140
|
+
"""
|
|
2141
|
+
if level not in NN:
|
|
2142
|
+
raise ValueError('level must be a nonnegative integer')
|
|
2143
|
+
if category is None:
|
|
2144
|
+
category = InfiniteEnumeratedSets()
|
|
2145
|
+
super().__init__(category=category)
|
|
2146
|
+
self._level = level
|
|
2147
|
+
|
|
2148
|
+
def _repr_(self):
|
|
2149
|
+
"""
|
|
2150
|
+
Return a string representation of ``self``.
|
|
2151
|
+
|
|
2152
|
+
EXAMPLES::
|
|
2153
|
+
|
|
2154
|
+
sage: PartitionTuples(2)
|
|
2155
|
+
Partition tuples of level 2
|
|
2156
|
+
"""
|
|
2157
|
+
return 'Partition tuples of level {}'.format(self._level)
|
|
2158
|
+
|
|
2159
|
+
def __contains__(self, mu):
|
|
2160
|
+
r"""
|
|
2161
|
+
Return ``True`` if `\mu` is in ``self``.
|
|
2162
|
+
|
|
2163
|
+
TESTS::
|
|
2164
|
+
|
|
2165
|
+
sage: PartitionTuple([[3,2],[2]]) in PartitionTuples(2)
|
|
2166
|
+
True
|
|
2167
|
+
sage: PartitionTuple([[3,2],[2]]) in PartitionTuples(level=2)
|
|
2168
|
+
True
|
|
2169
|
+
sage: PartitionTuple([[2,2,1],[2]]) in PartitionTuples(level=2)
|
|
2170
|
+
True
|
|
2171
|
+
sage: PartitionTuple([[2,2,1],[],[2]]) in PartitionTuples(level=2)
|
|
2172
|
+
False
|
|
2173
|
+
sage: all(mu in PartitionTuples(3) for mu in PartitionTuples(3,8)) # needs sage.libs.flint
|
|
2174
|
+
True
|
|
2175
|
+
|
|
2176
|
+
Check that :issue:`14145` is fixed::
|
|
2177
|
+
|
|
2178
|
+
sage: 1 in PartitionTuples(level=2)
|
|
2179
|
+
False
|
|
2180
|
+
"""
|
|
2181
|
+
# Note that self._level > 1
|
|
2182
|
+
return PartitionTuples.__contains__(self, mu) and len(mu) == self._level
|
|
2183
|
+
|
|
2184
|
+
def __iter__(self):
|
|
2185
|
+
r"""
|
|
2186
|
+
Iterate through the infinite class of partition tuples of fixed level.
|
|
2187
|
+
|
|
2188
|
+
EXAMPLES::
|
|
2189
|
+
|
|
2190
|
+
sage: parts = PartitionTuples(3)
|
|
2191
|
+
sage: [parts[k] for k in range(20)] # needs sage.libs.flint
|
|
2192
|
+
[([], [], []),
|
|
2193
|
+
([1], [], []),
|
|
2194
|
+
([], [1], []),
|
|
2195
|
+
([], [], [1]),
|
|
2196
|
+
([2], [], []),
|
|
2197
|
+
([1, 1], [], []),
|
|
2198
|
+
([1], [1], []),
|
|
2199
|
+
([1], [], [1]),
|
|
2200
|
+
([], [2], []),
|
|
2201
|
+
([], [1, 1], []),
|
|
2202
|
+
([], [1], [1]),
|
|
2203
|
+
([], [], [2]),
|
|
2204
|
+
([], [], [1, 1]),
|
|
2205
|
+
([3], [], []),
|
|
2206
|
+
([2, 1], [], []),
|
|
2207
|
+
([1, 1, 1], [], []),
|
|
2208
|
+
([2], [1], []),
|
|
2209
|
+
([1, 1], [1], []),
|
|
2210
|
+
([2], [], [1]),
|
|
2211
|
+
([1, 1], [], [1])]
|
|
2212
|
+
"""
|
|
2213
|
+
for size in NN:
|
|
2214
|
+
for mu in PartitionTuples_level_size(self._level, size):
|
|
2215
|
+
yield self.element_class(self, list(mu))
|
|
2216
|
+
|
|
2217
|
+
def _an_element_(self):
|
|
2218
|
+
"""
|
|
2219
|
+
Return a generic element.
|
|
2220
|
+
|
|
2221
|
+
EXAMPLES::
|
|
2222
|
+
|
|
2223
|
+
sage: PartitionTuples(level=4).an_element()
|
|
2224
|
+
([], [1], [2], [3])
|
|
2225
|
+
"""
|
|
2226
|
+
return self.element_class(self, tuple([l] for l in range(self.level())))
|
|
2227
|
+
|
|
2228
|
+
|
|
2229
|
+
class PartitionTuples_size(PartitionTuples):
|
|
2230
|
+
"""
|
|
2231
|
+
Class of partition tuples of a fixed size, but arbitrary level.
|
|
2232
|
+
"""
|
|
2233
|
+
|
|
2234
|
+
def __init__(self, size):
|
|
2235
|
+
r"""
|
|
2236
|
+
Initialize this class.
|
|
2237
|
+
|
|
2238
|
+
EXAMPLES::
|
|
2239
|
+
|
|
2240
|
+
sage: PartitionTuples(size=4)
|
|
2241
|
+
Partition tuples of size 4
|
|
2242
|
+
sage: PartitionTuples(size=6)
|
|
2243
|
+
Partition tuples of size 6
|
|
2244
|
+
|
|
2245
|
+
sage: TestSuite( PartitionTuples(size=6) ).run() # needs sage.libs.flint
|
|
2246
|
+
"""
|
|
2247
|
+
if size not in NN:
|
|
2248
|
+
raise ValueError('size must be a nonnegative integer')
|
|
2249
|
+
super().__init__(category=InfiniteEnumeratedSets())
|
|
2250
|
+
self._size = size
|
|
2251
|
+
|
|
2252
|
+
def _repr_(self):
|
|
2253
|
+
"""
|
|
2254
|
+
Return a string representation of ``self``.
|
|
2255
|
+
|
|
2256
|
+
EXAMPLES::
|
|
2257
|
+
|
|
2258
|
+
sage: PartitionTuples(size=4) # indirect doctest
|
|
2259
|
+
Partition tuples of size 4
|
|
2260
|
+
"""
|
|
2261
|
+
return 'Partition tuples of size {}'.format(self._size)
|
|
2262
|
+
|
|
2263
|
+
def __contains__(self, mu):
|
|
2264
|
+
r"""
|
|
2265
|
+
Return ``True`` if `\mu` is in ``self``.
|
|
2266
|
+
|
|
2267
|
+
TESTS::
|
|
2268
|
+
|
|
2269
|
+
sage: PartitionTuple([[3,2],[2]]) in PartitionTuples(size=7)
|
|
2270
|
+
True
|
|
2271
|
+
sage: PartitionTuple([[3,2],[],[],[],[2]]) in PartitionTuples(size=7)
|
|
2272
|
+
True
|
|
2273
|
+
sage: PartitionTuple([[2,1],[],[1,1],[],[2]]) in PartitionTuples(size=7)
|
|
2274
|
+
True
|
|
2275
|
+
sage: PartitionTuple([[2,1],[],[1,1],[],[3]]) in PartitionTuples(size=7)
|
|
2276
|
+
False
|
|
2277
|
+
sage: all(mu in PartitionTuples(size=8) for mu in PartitionTuples(3,8)) # needs sage.libs.flint
|
|
2278
|
+
True
|
|
2279
|
+
sage: [3, 2, 1] in PartitionTuples(size=7)
|
|
2280
|
+
False
|
|
2281
|
+
|
|
2282
|
+
Check that :issue:`14145` is fixed::
|
|
2283
|
+
|
|
2284
|
+
sage: 1 in PartitionTuples(size=7)
|
|
2285
|
+
False
|
|
2286
|
+
"""
|
|
2287
|
+
if mu in _Partitions:
|
|
2288
|
+
return self._size == sum(mu)
|
|
2289
|
+
return PartitionTuples.__contains__(self, mu) and self._size == sum(map(sum, mu))
|
|
2290
|
+
|
|
2291
|
+
def __iter__(self):
|
|
2292
|
+
r"""
|
|
2293
|
+
Iterate through the infinite class of partition tuples of a fixed size.
|
|
2294
|
+
|
|
2295
|
+
EXAMPLES::
|
|
2296
|
+
|
|
2297
|
+
sage: PartitionTuples(size=3)[:20] # needs sage.libs.flint
|
|
2298
|
+
[([3]),
|
|
2299
|
+
([2, 1]),
|
|
2300
|
+
([1, 1, 1]),
|
|
2301
|
+
([3], []),
|
|
2302
|
+
([2, 1], []),
|
|
2303
|
+
([1, 1, 1], []),
|
|
2304
|
+
([2], [1]),
|
|
2305
|
+
([1, 1], [1]),
|
|
2306
|
+
([1], [2]),
|
|
2307
|
+
([1], [1, 1]),
|
|
2308
|
+
([], [3]),
|
|
2309
|
+
([], [2, 1]),
|
|
2310
|
+
([], [1, 1, 1]),
|
|
2311
|
+
([3], [], []),
|
|
2312
|
+
([2, 1], [], []),
|
|
2313
|
+
([1, 1, 1], [], []),
|
|
2314
|
+
([2], [1], []),
|
|
2315
|
+
([1, 1], [1], []),
|
|
2316
|
+
([2], [], [1]),
|
|
2317
|
+
([1, 1], [], [1])]
|
|
2318
|
+
"""
|
|
2319
|
+
for level in NN:
|
|
2320
|
+
for mu in PartitionTuples_level_size(level, self._size):
|
|
2321
|
+
yield self.element_class(self, list(mu))
|
|
2322
|
+
|
|
2323
|
+
def _an_element_(self):
|
|
2324
|
+
"""
|
|
2325
|
+
Return a generic element.
|
|
2326
|
+
|
|
2327
|
+
EXAMPLES::
|
|
2328
|
+
|
|
2329
|
+
sage: PartitionTuples(size=4).an_element()
|
|
2330
|
+
([1], [1], [1], [1])
|
|
2331
|
+
"""
|
|
2332
|
+
return self.element_class(self, tuple([1] for l in range(self._size)))
|
|
2333
|
+
|
|
2334
|
+
|
|
2335
|
+
class PartitionTuples_level_size(PartitionTuples):
|
|
2336
|
+
"""
|
|
2337
|
+
Class of partition tuples with a fixed level and a fixed size.
|
|
2338
|
+
"""
|
|
2339
|
+
|
|
2340
|
+
def __init__(self, level, size):
|
|
2341
|
+
r"""
|
|
2342
|
+
Initialize this class.
|
|
2343
|
+
|
|
2344
|
+
EXAMPLES::
|
|
2345
|
+
|
|
2346
|
+
sage: TestSuite( PartitionTuples(4,2) ).run() # needs sage.libs.flint sage.libs.pari
|
|
2347
|
+
sage: TestSuite( PartitionTuples(level=4, size=5) ).run() # needs sage.libs.flint sage.libs.pari
|
|
2348
|
+
"""
|
|
2349
|
+
if not (level in NN and size in NN):
|
|
2350
|
+
raise ValueError('n and level must be nonnegative integers')
|
|
2351
|
+
super().__init__(category=FiniteEnumeratedSets())
|
|
2352
|
+
self._level = level
|
|
2353
|
+
self._size = size
|
|
2354
|
+
|
|
2355
|
+
def _repr_(self):
|
|
2356
|
+
"""
|
|
2357
|
+
Return a string representation of ``self``.
|
|
2358
|
+
|
|
2359
|
+
EXAMPLES::
|
|
2360
|
+
|
|
2361
|
+
sage: PartitionTuples(4,2)
|
|
2362
|
+
Partition tuples of level 4 and size 2
|
|
2363
|
+
sage: PartitionTuples(size=2, level=4)
|
|
2364
|
+
Partition tuples of level 4 and size 2
|
|
2365
|
+
"""
|
|
2366
|
+
return 'Partition tuples of level {} and size {}'.format(self._level, self._size)
|
|
2367
|
+
|
|
2368
|
+
def __contains__(self, mu):
|
|
2369
|
+
r"""
|
|
2370
|
+
Return ``True`` if ``mu`` is in ``self``.
|
|
2371
|
+
|
|
2372
|
+
TESTS::
|
|
2373
|
+
|
|
2374
|
+
sage: PartitionTuple([[3,2],[2]]) in PartitionTuples(2,7)
|
|
2375
|
+
True
|
|
2376
|
+
sage: PartitionTuple([[3,2],[],[],[],[2]]) in PartitionTuples(5,7)
|
|
2377
|
+
True
|
|
2378
|
+
sage: PartitionTuple([[2,1],[],[1,1],[],[2]]) in PartitionTuples(5,7)
|
|
2379
|
+
True
|
|
2380
|
+
sage: PartitionTuple([[2,1],[],[1,1],[],[3]]) in PartitionTuples(2,8)
|
|
2381
|
+
False
|
|
2382
|
+
sage: all(mu in PartitionTuples(3,8) for mu in PartitionTuples(3,8)) # needs sage.libs.flint
|
|
2383
|
+
True
|
|
2384
|
+
|
|
2385
|
+
Check that :issue:`14145` is fixed::
|
|
2386
|
+
|
|
2387
|
+
sage: 1 in PartitionTuples(5,7)
|
|
2388
|
+
False
|
|
2389
|
+
"""
|
|
2390
|
+
if self._level == 1 and mu in _Partitions:
|
|
2391
|
+
return self._size == sum(mu)
|
|
2392
|
+
return (PartitionTuples.__contains__(self, mu)
|
|
2393
|
+
and self._level == len(mu)
|
|
2394
|
+
and self._size == sum(map(sum,mu)))
|
|
2395
|
+
|
|
2396
|
+
def __iter__(self):
|
|
2397
|
+
r"""
|
|
2398
|
+
Iterate through the finite class of partition tuples of a fixed level
|
|
2399
|
+
and a fixed size.
|
|
2400
|
+
|
|
2401
|
+
EXAMPLES::
|
|
2402
|
+
|
|
2403
|
+
sage: # needs sage.libs.flint
|
|
2404
|
+
sage: PartitionTuples(2,0).list() #indirect doctest
|
|
2405
|
+
[([], [])]
|
|
2406
|
+
sage: PartitionTuples(2,1).list() #indirect doctest
|
|
2407
|
+
[([1], []), ([], [1])]
|
|
2408
|
+
sage: PartitionTuples(2,2).list() #indirect doctest
|
|
2409
|
+
[([2], []), ([1, 1], []), ([1], [1]), ([], [2]), ([], [1, 1])]
|
|
2410
|
+
sage: PartitionTuples(3,2).list() #indirect doctest
|
|
2411
|
+
[([2], [], []),
|
|
2412
|
+
([1, 1], [], []),
|
|
2413
|
+
([1], [1], []),
|
|
2414
|
+
([1], [], [1]),
|
|
2415
|
+
([], [2], []),
|
|
2416
|
+
([], [1, 1], []),
|
|
2417
|
+
([], [1], [1]),
|
|
2418
|
+
([], [], [2]),
|
|
2419
|
+
([], [], [1, 1])]
|
|
2420
|
+
"""
|
|
2421
|
+
p = [Partitions_n(i) for i in range(self._size+1)]
|
|
2422
|
+
for iv in IntegerVectors(self._size, self._level):
|
|
2423
|
+
for cp in itertools.product(*[p[i] for i in iv]):
|
|
2424
|
+
yield self._element_constructor_(cp)
|
|
2425
|
+
|
|
2426
|
+
def _an_element_(self):
|
|
2427
|
+
"""
|
|
2428
|
+
Return a generic element.
|
|
2429
|
+
|
|
2430
|
+
EXAMPLES::
|
|
2431
|
+
|
|
2432
|
+
sage: PartitionTuples(level=4,size=4).an_element()
|
|
2433
|
+
([1], [], [], [3])
|
|
2434
|
+
"""
|
|
2435
|
+
mu = [[] for _ in itertools.repeat(None, self._level)]
|
|
2436
|
+
if self._size > 0:
|
|
2437
|
+
if self._level == 1:
|
|
2438
|
+
mu = [self._size-1,1]
|
|
2439
|
+
else:
|
|
2440
|
+
mu[0] = [1]
|
|
2441
|
+
mu[-1] = [self._size-1]
|
|
2442
|
+
return self.element_class(self, mu)
|
|
2443
|
+
|
|
2444
|
+
def cardinality(self):
|
|
2445
|
+
r"""
|
|
2446
|
+
Return the number of ``level``-tuples of partitions of size ``n``.
|
|
2447
|
+
|
|
2448
|
+
Wraps a pari function call using :pari:`eta`.
|
|
2449
|
+
|
|
2450
|
+
EXAMPLES::
|
|
2451
|
+
|
|
2452
|
+
sage: PartitionTuples(2,3).cardinality() # needs sage.libs.pari
|
|
2453
|
+
10
|
|
2454
|
+
sage: PartitionTuples(2,8).cardinality() # needs sage.libs.pari
|
|
2455
|
+
185
|
|
2456
|
+
|
|
2457
|
+
TESTS:
|
|
2458
|
+
|
|
2459
|
+
The following calls used to fail (:issue:`11476`)::
|
|
2460
|
+
|
|
2461
|
+
sage: # needs sage.libs.pari
|
|
2462
|
+
sage: PartitionTuples(17,2).cardinality()
|
|
2463
|
+
170
|
|
2464
|
+
sage: PartitionTuples(2,17).cardinality()
|
|
2465
|
+
8470
|
|
2466
|
+
sage: PartitionTuples(100,13).cardinality()
|
|
2467
|
+
110320020147886800
|
|
2468
|
+
sage: PartitionTuples(13,90).cardinality()
|
|
2469
|
+
91506473741200186152352843611
|
|
2470
|
+
|
|
2471
|
+
These answers were checked against Gap4 (the last of which takes an
|
|
2472
|
+
awful long time for gap to compute).
|
|
2473
|
+
"""
|
|
2474
|
+
eta = pari(f'Ser(x,x,{self.size()})').eta()
|
|
2475
|
+
return ZZ((1 / eta**self.level()).polcoef(self.size(), pari('x')))
|
|
2476
|
+
|
|
2477
|
+
def __setstate__(self, state):
|
|
2478
|
+
r"""
|
|
2479
|
+
In order to maintain backwards compatibility and be able to unpickle a
|
|
2480
|
+
old pickle from PartitionTuples_nk we have to override the default
|
|
2481
|
+
``__setstate__``.
|
|
2482
|
+
|
|
2483
|
+
TESTS::
|
|
2484
|
+
|
|
2485
|
+
sage: loads(b"x\x9cM\x90\xcdN\xc30\x0c\x80\xd5\xc1\x06\xeb\x80\xf1{\xe0\r\xe0\xd2\x0b\x07\x1e\x02)B\x88\x9c-7\xb5\xba\xa8MR')\x12\x07$8p\xe0\xadq\x996q\xb1b\xfb\xb3\xf59\x9f3\x93\xb0\xa5\xca\x04W[\x8f\xb9\x1a0f\x9bm\xf0\xe5\xf3\xee\xf5:\x0e=%\xf0]\xc9\xc5\xfd\x17\xcf>\xf8\xe0N_\x83\xf5\xd2\xc5\x1e\xd0L\x10\xf46e>T\xba\x04r55\x8d\xf5-\xcf\x95p&\xf87\x8a\x19\x1c\xe5Mh\xc0\xa3#^(\xbd\x00\xd3`F>Rz\t\x063\xb5!\xbe\xf3\xf1\xd4\x98\x90\xc4K\xa5\x0b\xbf\xb5\x8b\xb2,U\xd6\x0bD\xb1t\xd8\x11\xec\x12.u\xf1\xf0\xfd\xc2+\xbd\x82\x96<E\xcc!&>Qz\x0e5&\xe2S\xa5\xd70X\xd3\xf5\x04\xe2\x91\xc4\x95\xcf\x9e\n\x11\xa3\x9e\x1c\xf9<\t\xa6\x1cG#\x83\xbcV\xfaf\x7f\xd9\xce\xfc\xef\xb4s\xa5o\xf7#\x13\x01\x03\xa6$!J\x81/~t\xd1m\xc4\xe5Q\\.\xff\xfd\x8e\t\x14\rmW\\\xa9\xb1\xae~\x01/\x8f\x85\x02")
|
|
2486
|
+
Partition tuples of level 7 and size 3
|
|
2487
|
+
sage: loads(dumps( PartitionTuples(7,3) )) # indirect doctest for unpickling a Tableau element
|
|
2488
|
+
Partition tuples of level 7 and size 3
|
|
2489
|
+
"""
|
|
2490
|
+
if isinstance(state, dict): # for old pickles from Tableau_class
|
|
2491
|
+
parts = PartitionTuples(state['k'], state['n'])
|
|
2492
|
+
self.__class__ = parts.__class__
|
|
2493
|
+
self.__dict__ = parts.__dict__
|
|
2494
|
+
else:
|
|
2495
|
+
super().__setstate__(state)
|
|
2496
|
+
|
|
2497
|
+
###############################################################################
|
|
2498
|
+
# Regular partition tuples
|
|
2499
|
+
|
|
2500
|
+
|
|
2501
|
+
class RegularPartitionTuples(PartitionTuples):
|
|
2502
|
+
r"""
|
|
2503
|
+
Abstract base class for `\ell`-regular partition tuples.
|
|
2504
|
+
"""
|
|
2505
|
+
|
|
2506
|
+
def __init__(self, regular, **kwds):
|
|
2507
|
+
"""
|
|
2508
|
+
Initialize ``self``.
|
|
2509
|
+
|
|
2510
|
+
TESTS::
|
|
2511
|
+
|
|
2512
|
+
sage: RPT = PartitionTuples(regular=3)
|
|
2513
|
+
sage: TestSuite(RPT).run() # needs sage.libs.flint
|
|
2514
|
+
"""
|
|
2515
|
+
if regular not in ZZ or regular < 1:
|
|
2516
|
+
raise ValueError("regular must be an integer greater than 1")
|
|
2517
|
+
self._ell = regular
|
|
2518
|
+
PartitionTuples.__init__(self, **kwds)
|
|
2519
|
+
|
|
2520
|
+
def __contains__(self, mu):
|
|
2521
|
+
r"""
|
|
2522
|
+
Check if ``mu`` is an `\ell`-regular partition tuple.
|
|
2523
|
+
|
|
2524
|
+
TESTS::
|
|
2525
|
+
|
|
2526
|
+
sage: RPT = PartitionTuples(regular=2)
|
|
2527
|
+
sage: [[11,1], [2]] in RPT
|
|
2528
|
+
True
|
|
2529
|
+
sage: Partition([4,1]) in RPT
|
|
2530
|
+
True
|
|
2531
|
+
sage: [5,4,3,2,1] in RPT
|
|
2532
|
+
True
|
|
2533
|
+
sage: [[6,3,1], [], [], [3,1], [1], [1], [1]] in RPT
|
|
2534
|
+
True
|
|
2535
|
+
sage: [[10], [1], [1,1], [4,2]] in RPT
|
|
2536
|
+
False
|
|
2537
|
+
sage: [[5,2], [17, 1], [], [3,3,1], [1,1]] in RPT
|
|
2538
|
+
False
|
|
2539
|
+
sage: RPT = PartitionTuples(4,2,3)
|
|
2540
|
+
sage: elt = RPT([[1], [], [], [1]])
|
|
2541
|
+
sage: elt in RPT
|
|
2542
|
+
True
|
|
2543
|
+
"""
|
|
2544
|
+
if not PartitionTuples.__contains__(self, mu):
|
|
2545
|
+
return False
|
|
2546
|
+
if isinstance(mu, Partition):
|
|
2547
|
+
return max(mu.to_exp() + [0]) < self._ell
|
|
2548
|
+
if isinstance(mu, PartitionTuple):
|
|
2549
|
+
return all(max(nu.to_exp() + [0]) < self._ell for nu in mu)
|
|
2550
|
+
if not mu:
|
|
2551
|
+
return True
|
|
2552
|
+
if mu in _Partitions:
|
|
2553
|
+
return all(mu.count(i) < self._ell for i in set(mu) if i > 0)
|
|
2554
|
+
return all(list(nu).count(i) < self._ell for nu in mu for i in set(nu) if i > 0)
|
|
2555
|
+
|
|
2556
|
+
def _an_element_(self):
|
|
2557
|
+
"""
|
|
2558
|
+
Return a generic element.
|
|
2559
|
+
|
|
2560
|
+
EXAMPLES::
|
|
2561
|
+
|
|
2562
|
+
sage: PartitionTuples(regular=2).an_element()
|
|
2563
|
+
([1], [], [], [2])
|
|
2564
|
+
"""
|
|
2565
|
+
if self._level is None:
|
|
2566
|
+
lvl = 4
|
|
2567
|
+
else:
|
|
2568
|
+
lvl = self._level
|
|
2569
|
+
if self._size is None:
|
|
2570
|
+
size = 3
|
|
2571
|
+
else:
|
|
2572
|
+
size = self._size
|
|
2573
|
+
elt = RegularPartitionTuples_level_size(lvl, size, self._ell).an_element()
|
|
2574
|
+
return self.element_class(self, list(elt))
|
|
2575
|
+
|
|
2576
|
+
|
|
2577
|
+
class RegularPartitionTuples_all(RegularPartitionTuples):
|
|
2578
|
+
r"""
|
|
2579
|
+
Class of `\ell`-regular partition tuples.
|
|
2580
|
+
"""
|
|
2581
|
+
|
|
2582
|
+
def __init__(self, regular):
|
|
2583
|
+
r"""
|
|
2584
|
+
Initialize ``self``.
|
|
2585
|
+
|
|
2586
|
+
EXAMPLES::
|
|
2587
|
+
|
|
2588
|
+
sage: RPT = PartitionTuples(regular=3)
|
|
2589
|
+
sage: TestSuite(RPT).run() # needs sage.libs.flint
|
|
2590
|
+
"""
|
|
2591
|
+
RegularPartitionTuples.__init__(self, regular, category=InfiniteEnumeratedSets())
|
|
2592
|
+
|
|
2593
|
+
def _repr_(self):
|
|
2594
|
+
"""
|
|
2595
|
+
Return a string representation of ``self``.
|
|
2596
|
+
|
|
2597
|
+
EXAMPLES::
|
|
2598
|
+
|
|
2599
|
+
sage: PartitionTuples(regular=3)
|
|
2600
|
+
3-Regular partition tuples
|
|
2601
|
+
"""
|
|
2602
|
+
return '{}-Regular partition tuples'.format(self._ell)
|
|
2603
|
+
|
|
2604
|
+
def __iter__(self):
|
|
2605
|
+
r"""
|
|
2606
|
+
Iterate through the class of `\ell`-regular partition tuples.
|
|
2607
|
+
|
|
2608
|
+
EXAMPLES::
|
|
2609
|
+
|
|
2610
|
+
sage: PartitionTuples(regular=2)[:20] # needs sage.libs.flint
|
|
2611
|
+
[([]),
|
|
2612
|
+
([], []),
|
|
2613
|
+
([1]),
|
|
2614
|
+
([], [], []),
|
|
2615
|
+
([1], []),
|
|
2616
|
+
([], [1]),
|
|
2617
|
+
([2]),
|
|
2618
|
+
([], [], [], []),
|
|
2619
|
+
([1], [], []),
|
|
2620
|
+
([], [1], []),
|
|
2621
|
+
([], [], [1]),
|
|
2622
|
+
([2], []),
|
|
2623
|
+
([1], [1]),
|
|
2624
|
+
([], [2]),
|
|
2625
|
+
([3]),
|
|
2626
|
+
([2, 1]),
|
|
2627
|
+
([], [], [], [], []),
|
|
2628
|
+
([1], [], [], []),
|
|
2629
|
+
([], [1], [], []),
|
|
2630
|
+
([], [], [1], [])]
|
|
2631
|
+
"""
|
|
2632
|
+
for N in NN:
|
|
2633
|
+
for size in range(N+1):
|
|
2634
|
+
for mu in RegularPartitionTuples_level_size(N-size+1, size, self._ell):
|
|
2635
|
+
yield self.element_class(self, list(mu))
|
|
2636
|
+
|
|
2637
|
+
|
|
2638
|
+
class RegularPartitionTuples_level(PartitionTuples_level):
|
|
2639
|
+
r"""
|
|
2640
|
+
Regular Partition tuples of a fixed level.
|
|
2641
|
+
|
|
2642
|
+
INPUT:
|
|
2643
|
+
|
|
2644
|
+
- ``level`` -- nonnegative integer; the level
|
|
2645
|
+
- ``regular`` -- positive integer or a tuple of nonnegative
|
|
2646
|
+
integers; if an integer, the highest multiplicity an entry may
|
|
2647
|
+
have in a component plus `1` with `0` representing `\infty`-regular
|
|
2648
|
+
(equivalently, partitions without restrictions)
|
|
2649
|
+
|
|
2650
|
+
``regular`` is a tuple of integers `(\ell_1, \ldots, \ell_k)` that
|
|
2651
|
+
specifies partition tuples `\mu` such that `\mu_i` is `\ell_i`-regular.
|
|
2652
|
+
If ``regular`` is an integer `\ell`, then we set `\ell_i = \ell` for
|
|
2653
|
+
all `i`.
|
|
2654
|
+
|
|
2655
|
+
EXAMPLES::
|
|
2656
|
+
|
|
2657
|
+
sage: RPT = PartitionTuples(level=4, regular=(2,3,0,2))
|
|
2658
|
+
sage: RPT[:24] # needs sage.libs.flint
|
|
2659
|
+
[([], [], [], []),
|
|
2660
|
+
([1], [], [], []),
|
|
2661
|
+
([], [1], [], []),
|
|
2662
|
+
([], [], [1], []),
|
|
2663
|
+
([], [], [], [1]),
|
|
2664
|
+
([2], [], [], []),
|
|
2665
|
+
([1], [1], [], []),
|
|
2666
|
+
([1], [], [1], []),
|
|
2667
|
+
([1], [], [], [1]),
|
|
2668
|
+
([], [2], [], []),
|
|
2669
|
+
([], [1, 1], [], []),
|
|
2670
|
+
([], [1], [1], []),
|
|
2671
|
+
([], [1], [], [1]),
|
|
2672
|
+
([], [], [2], []),
|
|
2673
|
+
([], [], [1, 1], []),
|
|
2674
|
+
([], [], [1], [1]),
|
|
2675
|
+
([], [], [], [2]),
|
|
2676
|
+
([3], [], [], []),
|
|
2677
|
+
([2, 1], [], [], []),
|
|
2678
|
+
([2], [1], [], []),
|
|
2679
|
+
([2], [], [1], []),
|
|
2680
|
+
([2], [], [], [1]),
|
|
2681
|
+
([1], [2], [], []),
|
|
2682
|
+
([1], [1, 1], [], [])]
|
|
2683
|
+
sage: [[1,1],[3],[5,5,5],[7,2]] in RPT
|
|
2684
|
+
False
|
|
2685
|
+
sage: [[3,1],[3],[5,5,5],[7,2]] in RPT
|
|
2686
|
+
True
|
|
2687
|
+
sage: [[3,1],[3],[5,5,5]] in RPT
|
|
2688
|
+
False
|
|
2689
|
+
"""
|
|
2690
|
+
|
|
2691
|
+
def __init__(self, level, regular):
|
|
2692
|
+
r"""
|
|
2693
|
+
Initialize ``self``.
|
|
2694
|
+
|
|
2695
|
+
TESTS::
|
|
2696
|
+
|
|
2697
|
+
sage: RPT = PartitionTuples(level=2, regular=(0,0))
|
|
2698
|
+
sage: RPT.category()
|
|
2699
|
+
Category of infinite enumerated sets
|
|
2700
|
+
sage: RPT = PartitionTuples(level=4, regular=3)
|
|
2701
|
+
sage: TestSuite(RPT).run() # needs sage.libs.flint
|
|
2702
|
+
"""
|
|
2703
|
+
if level not in NN:
|
|
2704
|
+
raise ValueError('level must be a nonnegative integer')
|
|
2705
|
+
if not isinstance(regular, tuple):
|
|
2706
|
+
# This should not happen if called from RegularPartitionTuples
|
|
2707
|
+
regular = (regular,) * level
|
|
2708
|
+
if any(r != 1 for r in regular):
|
|
2709
|
+
category = InfiniteEnumeratedSets()
|
|
2710
|
+
else:
|
|
2711
|
+
category = FiniteEnumeratedSets()
|
|
2712
|
+
if any(r not in NN for r in regular):
|
|
2713
|
+
raise ValueError('regular must be a tuple of nonnegative integers')
|
|
2714
|
+
if len(regular) != level:
|
|
2715
|
+
raise ValueError("regular must be a tuple with length {}".format(level))
|
|
2716
|
+
PartitionTuples_level.__init__(self, level, category=category)
|
|
2717
|
+
self._ell = regular
|
|
2718
|
+
|
|
2719
|
+
def _repr_(self):
|
|
2720
|
+
"""
|
|
2721
|
+
Return a string representation of ``self``.
|
|
2722
|
+
|
|
2723
|
+
EXAMPLES::
|
|
2724
|
+
|
|
2725
|
+
sage: PartitionTuples(level=4, regular=3)
|
|
2726
|
+
3-Regular partition tuples of level 4
|
|
2727
|
+
sage: PartitionTuples(level=4, regular=(2,3,0,2))
|
|
2728
|
+
(2, 3, 0, 2)-Regular partition tuples of level 4
|
|
2729
|
+
"""
|
|
2730
|
+
if self._ell[1:] == self._ell[:-1]:
|
|
2731
|
+
return '{}-Regular partition tuples of level {}'.format(self._ell[0],
|
|
2732
|
+
self._level)
|
|
2733
|
+
return '{}-Regular partition tuples of level {}'.format(self._ell,
|
|
2734
|
+
self._level)
|
|
2735
|
+
|
|
2736
|
+
def __contains__(self, mu):
|
|
2737
|
+
r"""
|
|
2738
|
+
Return ``True`` if ``mu`` is in ``self``.
|
|
2739
|
+
|
|
2740
|
+
TESTS::
|
|
2741
|
+
|
|
2742
|
+
sage: RPT = PartitionTuples(level=4, regular=2)
|
|
2743
|
+
sage: [[4,2,1], [], [2], [2]] in RPT
|
|
2744
|
+
True
|
|
2745
|
+
sage: [[10], [1], [1,1], [4,2]] in RPT
|
|
2746
|
+
False
|
|
2747
|
+
sage: [[5,2], [], [3,3,1], [1,1]] in RPT
|
|
2748
|
+
False
|
|
2749
|
+
sage: [4, 3, 2] in RPT
|
|
2750
|
+
False
|
|
2751
|
+
|
|
2752
|
+
sage: RPT = PartitionTuples(level=3, regular=(2,1,4))
|
|
2753
|
+
sage: [[4], [2], [5]] in RPT
|
|
2754
|
+
False
|
|
2755
|
+
sage: [[4], [], [5]] in RPT
|
|
2756
|
+
True
|
|
2757
|
+
sage: [[4,3], [], [5]] in RPT
|
|
2758
|
+
True
|
|
2759
|
+
sage: [[4,4], [], [5]] in RPT
|
|
2760
|
+
False
|
|
2761
|
+
sage: [[4,3], [5]] in RPT
|
|
2762
|
+
False
|
|
2763
|
+
sage: [5, 4, 3] in RPT
|
|
2764
|
+
False
|
|
2765
|
+
sage: [] in RPT
|
|
2766
|
+
False
|
|
2767
|
+
sage: [[], [], []] in RPT
|
|
2768
|
+
True
|
|
2769
|
+
sage: [[], [], [], [2]] in RPT
|
|
2770
|
+
False
|
|
2771
|
+
|
|
2772
|
+
sage: from sage.combinat.partition_tuple import RegularPartitionTuples_level
|
|
2773
|
+
sage: RPT = RegularPartitionTuples_level(1, (3,)); RPT
|
|
2774
|
+
3-Regular partition tuples of level 1
|
|
2775
|
+
sage: [[2,2]] in RPT
|
|
2776
|
+
True
|
|
2777
|
+
sage: [[2,2,2]] in RPT
|
|
2778
|
+
False
|
|
2779
|
+
"""
|
|
2780
|
+
if self._level == 1:
|
|
2781
|
+
try:
|
|
2782
|
+
if mu[0] in ZZ:
|
|
2783
|
+
return mu in RegularPartitions_all(self._ell[0])
|
|
2784
|
+
except (TypeError, ValueError):
|
|
2785
|
+
return False
|
|
2786
|
+
return mu[0] in RegularPartitions_all(self._ell[0])
|
|
2787
|
+
if mu not in PartitionTuples_level(self._level):
|
|
2788
|
+
return False
|
|
2789
|
+
if isinstance(mu, Partition): # it is level 1
|
|
2790
|
+
return False
|
|
2791
|
+
if isinstance(mu, PartitionTuple):
|
|
2792
|
+
return all(max(p.to_exp() + [0]) < ell for p, ell in zip(mu, self._ell)
|
|
2793
|
+
if ell > 0)
|
|
2794
|
+
return all(p in RegularPartitions_all(ell) for p, ell in zip(mu, self._ell)
|
|
2795
|
+
if ell > 0)
|
|
2796
|
+
|
|
2797
|
+
def __iter__(self):
|
|
2798
|
+
r"""
|
|
2799
|
+
Iterate through the class of `\ell`-regular partition tuples
|
|
2800
|
+
of a fixed level.
|
|
2801
|
+
|
|
2802
|
+
EXAMPLES::
|
|
2803
|
+
|
|
2804
|
+
sage: PartitionTuples(level=3, regular=(2,1,4))[:24] # needs sage.libs.flint
|
|
2805
|
+
[([], [], []),
|
|
2806
|
+
([1], [], []),
|
|
2807
|
+
([], [], [1]),
|
|
2808
|
+
([2], [], []),
|
|
2809
|
+
([1], [], [1]),
|
|
2810
|
+
([], [], [2]),
|
|
2811
|
+
([], [], [1, 1]),
|
|
2812
|
+
([3], [], []),
|
|
2813
|
+
([2, 1], [], []),
|
|
2814
|
+
([2], [], [1]),
|
|
2815
|
+
([1], [], [2]),
|
|
2816
|
+
([1], [], [1, 1]),
|
|
2817
|
+
([], [], [3]),
|
|
2818
|
+
([], [], [2, 1]),
|
|
2819
|
+
([], [], [1, 1, 1]),
|
|
2820
|
+
([4], [], []),
|
|
2821
|
+
([3, 1], [], []),
|
|
2822
|
+
([3], [], [1]),
|
|
2823
|
+
([2, 1], [], [1]),
|
|
2824
|
+
([2], [], [2]),
|
|
2825
|
+
([2], [], [1, 1]),
|
|
2826
|
+
([1], [], [3]),
|
|
2827
|
+
([1], [], [2, 1]),
|
|
2828
|
+
([1], [], [1, 1, 1])]
|
|
2829
|
+
sage: PartitionTuples(level=4, regular=2)[:20] # needs sage.libs.flint
|
|
2830
|
+
[([], [], [], []),
|
|
2831
|
+
([1], [], [], []),
|
|
2832
|
+
([], [1], [], []),
|
|
2833
|
+
([], [], [1], []),
|
|
2834
|
+
([], [], [], [1]),
|
|
2835
|
+
([2], [], [], []),
|
|
2836
|
+
([1], [1], [], []),
|
|
2837
|
+
([1], [], [1], []),
|
|
2838
|
+
([1], [], [], [1]),
|
|
2839
|
+
([], [2], [], []),
|
|
2840
|
+
([], [1], [1], []),
|
|
2841
|
+
([], [1], [], [1]),
|
|
2842
|
+
([], [], [2], []),
|
|
2843
|
+
([], [], [1], [1]),
|
|
2844
|
+
([], [], [], [2]),
|
|
2845
|
+
([3], [], [], []),
|
|
2846
|
+
([2, 1], [], [], []),
|
|
2847
|
+
([2], [1], [], []),
|
|
2848
|
+
([2], [], [1], []),
|
|
2849
|
+
([2], [], [], [1])]
|
|
2850
|
+
"""
|
|
2851
|
+
for size in NN:
|
|
2852
|
+
for mu in RegularPartitionTuples_level_size(self._level, size, self._ell):
|
|
2853
|
+
yield self.element_class(self, list(mu))
|
|
2854
|
+
|
|
2855
|
+
|
|
2856
|
+
class RegularPartitionTuples_size(RegularPartitionTuples):
|
|
2857
|
+
r"""
|
|
2858
|
+
Class of `\ell`-regular partition tuples with a fixed size.
|
|
2859
|
+
"""
|
|
2860
|
+
|
|
2861
|
+
def __init__(self, size, regular):
|
|
2862
|
+
r"""
|
|
2863
|
+
Initialize ``self``.
|
|
2864
|
+
|
|
2865
|
+
EXAMPLES::
|
|
2866
|
+
|
|
2867
|
+
sage: RPT = PartitionTuples(size=4, regular=3)
|
|
2868
|
+
sage: TestSuite(RPT).run() # needs sage.libs.flint
|
|
2869
|
+
"""
|
|
2870
|
+
if size not in NN:
|
|
2871
|
+
raise ValueError('size must be a nonnegative integer')
|
|
2872
|
+
RegularPartitionTuples.__init__(self, regular, category=InfiniteEnumeratedSets())
|
|
2873
|
+
self._size = size
|
|
2874
|
+
|
|
2875
|
+
def _repr_(self):
|
|
2876
|
+
"""
|
|
2877
|
+
Return a string representation of ``self``.
|
|
2878
|
+
|
|
2879
|
+
EXAMPLES::
|
|
2880
|
+
|
|
2881
|
+
sage: PartitionTuples(size=4, regular=3)
|
|
2882
|
+
3-Regular partition tuples of size 4
|
|
2883
|
+
"""
|
|
2884
|
+
return '{}-Regular partition tuples of size {}'.format(self._ell, self._size)
|
|
2885
|
+
|
|
2886
|
+
def __contains__(self, mu):
|
|
2887
|
+
r"""
|
|
2888
|
+
Return ``True`` if ``mu`` is in ``self``.
|
|
2889
|
+
|
|
2890
|
+
TESTS::
|
|
2891
|
+
|
|
2892
|
+
sage: RPT = PartitionTuples(size=4, regular=2)
|
|
2893
|
+
sage: [[2, 1], [1]] in RPT
|
|
2894
|
+
True
|
|
2895
|
+
sage: [3, 1] in RPT
|
|
2896
|
+
True
|
|
2897
|
+
sage: [[1], [], [], [2,1]] in RPT
|
|
2898
|
+
True
|
|
2899
|
+
sage: [[1], [1], [1], [1]] in RPT
|
|
2900
|
+
True
|
|
2901
|
+
sage: [[1], [1,1,1]] in RPT
|
|
2902
|
+
False
|
|
2903
|
+
sage: [[2,1,1]] in RPT
|
|
2904
|
+
False
|
|
2905
|
+
sage: [2,1,1] in RPT
|
|
2906
|
+
False
|
|
2907
|
+
sage: RPT = PartitionTuples(size=7, regular=2)
|
|
2908
|
+
sage: [[], [3,2,2,1], [1], [1]] in RPT
|
|
2909
|
+
False
|
|
2910
|
+
sage: RPT = PartitionTuples(size=9, regular=2)
|
|
2911
|
+
sage: [4, 3, 2] in RPT
|
|
2912
|
+
True
|
|
2913
|
+
"""
|
|
2914
|
+
return ((mu in RegularPartitions_all(self._ell)
|
|
2915
|
+
and self._size == sum(mu))
|
|
2916
|
+
or (RegularPartitionTuples.__contains__(self, mu)
|
|
2917
|
+
and self._size == sum(map(sum, mu))))
|
|
2918
|
+
|
|
2919
|
+
def __iter__(self):
|
|
2920
|
+
r"""
|
|
2921
|
+
Iterate through the class of `\ell`-regular partition tuples
|
|
2922
|
+
of a fixed size.
|
|
2923
|
+
|
|
2924
|
+
EXAMPLES::
|
|
2925
|
+
|
|
2926
|
+
sage: PartitionTuples(size=4, regular=2)[:10] # needs sage.libs.flint
|
|
2927
|
+
[([4]),
|
|
2928
|
+
([3, 1]),
|
|
2929
|
+
([4], []),
|
|
2930
|
+
([3, 1], []),
|
|
2931
|
+
([3], [1]),
|
|
2932
|
+
([2, 1], [1]),
|
|
2933
|
+
([2], [2]),
|
|
2934
|
+
([1], [3]),
|
|
2935
|
+
([1], [2, 1]),
|
|
2936
|
+
([], [4])]
|
|
2937
|
+
"""
|
|
2938
|
+
for level in PositiveIntegers():
|
|
2939
|
+
for mu in RegularPartitionTuples_level_size(level, self._size, self._ell):
|
|
2940
|
+
yield self.element_class(self, list(mu))
|
|
2941
|
+
|
|
2942
|
+
|
|
2943
|
+
class RegularPartitionTuples_level_size(PartitionTuples_level_size):
|
|
2944
|
+
r"""
|
|
2945
|
+
Class of `\ell`-regular partition tuples with a fixed level and
|
|
2946
|
+
a fixed size.
|
|
2947
|
+
|
|
2948
|
+
INPUT:
|
|
2949
|
+
|
|
2950
|
+
- ``level`` -- nonnegative integer; the level
|
|
2951
|
+
- ``size`` -- nonnegative integer; the size
|
|
2952
|
+
- ``regular`` -- positive integer or a tuple of nonnegative
|
|
2953
|
+
integers; if an integer, the highest multiplicity an entry may
|
|
2954
|
+
have in a component plus `1` with `0` representing `\infty`-regular
|
|
2955
|
+
(equivalently, partitions without restrictions)
|
|
2956
|
+
|
|
2957
|
+
``regular`` is a tuple of integers `(\ell_1, \ldots, \ell_k)` that
|
|
2958
|
+
specifies partition tuples `\mu` such that `\mu_i` is `\ell_i`-regular.
|
|
2959
|
+
If ``regular`` is an integer `\ell`, then we set `\ell_i = \ell` for
|
|
2960
|
+
all `i`.
|
|
2961
|
+
|
|
2962
|
+
EXAMPLES::
|
|
2963
|
+
|
|
2964
|
+
sage: PartitionTuples(level=3, size=7, regular=(2,1,3))[0:24] # needs sage.libs.flint
|
|
2965
|
+
[([7], [], []),
|
|
2966
|
+
([6, 1], [], []),
|
|
2967
|
+
([5, 2], [], []),
|
|
2968
|
+
([4, 3], [], []),
|
|
2969
|
+
([4, 2, 1], [], []),
|
|
2970
|
+
([6], [], [1]),
|
|
2971
|
+
([5, 1], [], [1]),
|
|
2972
|
+
([4, 2], [], [1]),
|
|
2973
|
+
([3, 2, 1], [], [1]),
|
|
2974
|
+
([5], [], [2]),
|
|
2975
|
+
([5], [], [1, 1]),
|
|
2976
|
+
([4, 1], [], [2]),
|
|
2977
|
+
([4, 1], [], [1, 1]),
|
|
2978
|
+
([3, 2], [], [2]),
|
|
2979
|
+
([3, 2], [], [1, 1]),
|
|
2980
|
+
([4], [], [3]),
|
|
2981
|
+
([4], [], [2, 1]),
|
|
2982
|
+
([3, 1], [], [3]),
|
|
2983
|
+
([3, 1], [], [2, 1]),
|
|
2984
|
+
([3], [], [4]),
|
|
2985
|
+
([3], [], [3, 1]),
|
|
2986
|
+
([3], [], [2, 2]),
|
|
2987
|
+
([3], [], [2, 1, 1]),
|
|
2988
|
+
([2, 1], [], [4])]
|
|
2989
|
+
"""
|
|
2990
|
+
|
|
2991
|
+
def __init__(self, level, size, regular):
|
|
2992
|
+
r"""
|
|
2993
|
+
Initialize ``self``.
|
|
2994
|
+
|
|
2995
|
+
TESTS::
|
|
2996
|
+
|
|
2997
|
+
sage: RPT = PartitionTuples(4,2,3)
|
|
2998
|
+
sage: TestSuite(RPT).run() # needs sage.libs.flint sage.libs.pari
|
|
2999
|
+
"""
|
|
3000
|
+
if size not in NN:
|
|
3001
|
+
raise ValueError('size must be a nonnegative integer')
|
|
3002
|
+
if not (level in ZZ and level > 0):
|
|
3003
|
+
raise ValueError('level must be a positive integer')
|
|
3004
|
+
if not isinstance(regular, tuple):
|
|
3005
|
+
# This should not happen if called from RegularPartitionTuples
|
|
3006
|
+
regular = (regular,) * level
|
|
3007
|
+
if len(regular) != level:
|
|
3008
|
+
raise ValueError(f'regular must be a list with length {level}')
|
|
3009
|
+
if any(i not in NN for i in regular):
|
|
3010
|
+
raise ValueError('regular must be a list of nonnegative integers')
|
|
3011
|
+
PartitionTuples_level_size.__init__(self, level, size)
|
|
3012
|
+
self._ell = regular
|
|
3013
|
+
|
|
3014
|
+
def _repr_(self):
|
|
3015
|
+
"""
|
|
3016
|
+
Return a string representation of ``self``.
|
|
3017
|
+
|
|
3018
|
+
EXAMPLES::
|
|
3019
|
+
|
|
3020
|
+
sage: PartitionTuples(level=3, size=7, regular=(2,1,4))
|
|
3021
|
+
(2, 1, 4)-Regular partition tuples of level 3 and size 7
|
|
3022
|
+
sage: PartitionTuples(4,2,3)
|
|
3023
|
+
3-Regular partition tuples of level 4 and size 2
|
|
3024
|
+
sage: PartitionTuples(size=2, level=4, regular=3)
|
|
3025
|
+
3-Regular partition tuples of level 4 and size 2
|
|
3026
|
+
"""
|
|
3027
|
+
if self._ell[1:] == self._ell[:-1]:
|
|
3028
|
+
return '{}-Regular partition tuples of level {} and size {}'.format(
|
|
3029
|
+
self._ell[0], self._level, self._size)
|
|
3030
|
+
return '{}-Regular partition tuples of level {} and size {}'.format(
|
|
3031
|
+
self._ell, self._level, self._size)
|
|
3032
|
+
|
|
3033
|
+
def __contains__(self, mu):
|
|
3034
|
+
r"""
|
|
3035
|
+
Return ``True`` if `\mu` is in ``self``.
|
|
3036
|
+
|
|
3037
|
+
TESTS::
|
|
3038
|
+
|
|
3039
|
+
sage: RPT = PartitionTuples(level=3, size=7, regular=(2,1,4))
|
|
3040
|
+
sage: RPT
|
|
3041
|
+
(2, 1, 4)-Regular partition tuples of level 3 and size 7
|
|
3042
|
+
sage: [[3,1],[],[3]] in RPT
|
|
3043
|
+
True
|
|
3044
|
+
sage: [[3],[1],[3]] in RPT
|
|
3045
|
+
False
|
|
3046
|
+
sage: [[3,2],[],[3]] in RPT
|
|
3047
|
+
False
|
|
3048
|
+
sage: [[3,3],[],[1]] in RPT
|
|
3049
|
+
False
|
|
3050
|
+
sage: RPT = PartitionTuples(4,3,2)
|
|
3051
|
+
sage: [[], [], [2], [1]] in RPT
|
|
3052
|
+
True
|
|
3053
|
+
sage: [[1], [1], [], [1]] in RPT
|
|
3054
|
+
True
|
|
3055
|
+
sage: [[1,1,1], [], [], []] in RPT
|
|
3056
|
+
False
|
|
3057
|
+
sage: RPT = PartitionTuples(9, 3, 2)
|
|
3058
|
+
sage: [4, 3, 2] in RPT
|
|
3059
|
+
False
|
|
3060
|
+
"""
|
|
3061
|
+
if mu not in RegularPartitionTuples_level(self._level, self._ell):
|
|
3062
|
+
return False
|
|
3063
|
+
return self._size == sum(map(sum, mu))
|
|
3064
|
+
|
|
3065
|
+
def __iter__(self):
|
|
3066
|
+
r"""
|
|
3067
|
+
Iterate through the finite class of `\ell`-regular partition tuples
|
|
3068
|
+
of a fixed level and a fixed size.
|
|
3069
|
+
|
|
3070
|
+
EXAMPLES::
|
|
3071
|
+
|
|
3072
|
+
sage: list(PartitionTuples(3,3,2)) # needs sage.libs.pari
|
|
3073
|
+
[([3], [], []),
|
|
3074
|
+
([2, 1], [], []),
|
|
3075
|
+
([2], [1], []),
|
|
3076
|
+
([2], [], [1]),
|
|
3077
|
+
([1], [2], []),
|
|
3078
|
+
([1], [1], [1]),
|
|
3079
|
+
([1], [], [2]),
|
|
3080
|
+
([], [3], []),
|
|
3081
|
+
([], [2, 1], []),
|
|
3082
|
+
([], [2], [1]),
|
|
3083
|
+
([], [1], [2]),
|
|
3084
|
+
([], [], [3]),
|
|
3085
|
+
([], [], [2, 1])]
|
|
3086
|
+
"""
|
|
3087
|
+
for iv in IntegerVectors(self._size, self._level):
|
|
3088
|
+
p = [RegularPartitions_n(v, ell) if ell > 0 else Partitions_n(v)
|
|
3089
|
+
for v, ell in zip(iv, self._ell)]
|
|
3090
|
+
for cp in itertools.product(*[p[i] for i in range(self._level)]):
|
|
3091
|
+
yield self._element_constructor_(cp)
|
|
3092
|
+
|
|
3093
|
+
def _an_element_(self):
|
|
3094
|
+
"""
|
|
3095
|
+
Return a generic element.
|
|
3096
|
+
|
|
3097
|
+
EXAMPLES::
|
|
3098
|
+
|
|
3099
|
+
sage: PartitionTuples(level=4, size=4, regular=3).an_element()
|
|
3100
|
+
([1], [], [], [3])
|
|
3101
|
+
"""
|
|
3102
|
+
mu = [[] for _ in itertools.repeat(None, self._level)]
|
|
3103
|
+
if self._size > 0:
|
|
3104
|
+
if self._level == 1:
|
|
3105
|
+
mu = [[self._size - 1, 1]]
|
|
3106
|
+
else:
|
|
3107
|
+
mu[0] = [1]
|
|
3108
|
+
mu[-1] = [self._size - 1]
|
|
3109
|
+
return self.element_class(self, mu)
|
|
3110
|
+
|
|
3111
|
+
|
|
3112
|
+
from sage.misc.persist import register_unpickle_override
|
|
3113
|
+
|
|
3114
|
+
register_unpickle_override('sage.combinat.partition', 'PartitionTuples_nk', PartitionTuples_level_size)
|