passagemath-combinat 10.6.42__cp314-cp314-musllinux_1_2_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_combinat/__init__.py +3 -0
- passagemath_combinat-10.6.42.dist-info/METADATA +160 -0
- passagemath_combinat-10.6.42.dist-info/RECORD +400 -0
- passagemath_combinat-10.6.42.dist-info/WHEEL +5 -0
- passagemath_combinat-10.6.42.dist-info/top_level.txt +3 -0
- passagemath_combinat.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_combinat.libs/libsymmetrica-81fe8739.so.3.0.0 +0 -0
- sage/algebras/affine_nil_temperley_lieb.py +263 -0
- sage/algebras/all.py +24 -0
- sage/algebras/all__sagemath_combinat.py +35 -0
- sage/algebras/askey_wilson.py +935 -0
- sage/algebras/associated_graded.py +345 -0
- sage/algebras/cellular_basis.py +350 -0
- sage/algebras/cluster_algebra.py +2766 -0
- sage/algebras/down_up_algebra.py +860 -0
- sage/algebras/free_algebra.py +1698 -0
- sage/algebras/free_algebra_element.py +345 -0
- sage/algebras/free_algebra_quotient.py +405 -0
- sage/algebras/free_algebra_quotient_element.py +295 -0
- sage/algebras/free_zinbiel_algebra.py +885 -0
- sage/algebras/hall_algebra.py +783 -0
- sage/algebras/hecke_algebras/all.py +4 -0
- sage/algebras/hecke_algebras/ariki_koike_algebra.py +1796 -0
- sage/algebras/hecke_algebras/ariki_koike_specht_modules.py +475 -0
- sage/algebras/hecke_algebras/cubic_hecke_algebra.py +3520 -0
- sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +1473 -0
- sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py +1079 -0
- sage/algebras/iwahori_hecke_algebra.py +3095 -0
- sage/algebras/jordan_algebra.py +1773 -0
- sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py +113 -0
- sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py +156 -0
- sage/algebras/lie_conformal_algebras/all.py +18 -0
- sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py +134 -0
- sage/algebras/lie_conformal_algebras/examples.py +43 -0
- sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py +131 -0
- sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py +139 -0
- sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py +174 -0
- sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +167 -0
- sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py +107 -0
- sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py +135 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +353 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py +236 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py +78 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +328 -0
- sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py +117 -0
- sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py +86 -0
- sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py +82 -0
- sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py +205 -0
- sage/algebras/nil_coxeter_algebra.py +191 -0
- sage/algebras/q_commuting_polynomials.py +673 -0
- sage/algebras/q_system.py +608 -0
- sage/algebras/quantum_clifford.py +959 -0
- sage/algebras/quantum_groups/ace_quantum_onsager.py +693 -0
- sage/algebras/quantum_groups/all.py +9 -0
- sage/algebras/quantum_groups/fock_space.py +2219 -0
- sage/algebras/quantum_groups/q_numbers.py +207 -0
- sage/algebras/quantum_groups/quantum_group_gap.py +2695 -0
- sage/algebras/quantum_groups/representations.py +591 -0
- sage/algebras/quantum_matrix_coordinate_algebra.py +1006 -0
- sage/algebras/quantum_oscillator.py +623 -0
- sage/algebras/quaternion_algebra.py +20 -0
- sage/algebras/quaternion_algebra_element.py +55 -0
- sage/algebras/rational_cherednik_algebra.py +525 -0
- sage/algebras/schur_algebra.py +670 -0
- sage/algebras/shuffle_algebra.py +1011 -0
- sage/algebras/splitting_algebra.py +779 -0
- sage/algebras/tensor_algebra.py +709 -0
- sage/algebras/yangian.py +1082 -0
- sage/algebras/yokonuma_hecke_algebra.py +1018 -0
- sage/all__sagemath_combinat.py +35 -0
- sage/combinat/SJT.py +255 -0
- sage/combinat/affine_permutation.py +2405 -0
- sage/combinat/algebraic_combinatorics.py +55 -0
- sage/combinat/all.py +53 -0
- sage/combinat/all__sagemath_combinat.py +195 -0
- sage/combinat/alternating_sign_matrix.py +2063 -0
- sage/combinat/baxter_permutations.py +346 -0
- sage/combinat/bijectionist.py +3220 -0
- sage/combinat/binary_recurrence_sequences.py +1180 -0
- sage/combinat/blob_algebra.py +685 -0
- sage/combinat/catalog_partitions.py +27 -0
- sage/combinat/chas/all.py +23 -0
- sage/combinat/chas/fsym.py +1180 -0
- sage/combinat/chas/wqsym.py +2601 -0
- sage/combinat/cluster_complex.py +326 -0
- sage/combinat/colored_permutations.py +2039 -0
- sage/combinat/colored_permutations_representations.py +964 -0
- sage/combinat/composition_signed.py +142 -0
- sage/combinat/composition_tableau.py +855 -0
- sage/combinat/constellation.py +1729 -0
- sage/combinat/core.py +751 -0
- sage/combinat/counting.py +12 -0
- sage/combinat/crystals/affine.py +742 -0
- sage/combinat/crystals/affine_factorization.py +518 -0
- sage/combinat/crystals/affinization.py +331 -0
- sage/combinat/crystals/alcove_path.py +2013 -0
- sage/combinat/crystals/all.py +22 -0
- sage/combinat/crystals/bkk_crystals.py +141 -0
- sage/combinat/crystals/catalog.py +115 -0
- sage/combinat/crystals/catalog_elementary_crystals.py +18 -0
- sage/combinat/crystals/catalog_infinity_crystals.py +33 -0
- sage/combinat/crystals/catalog_kirillov_reshetikhin.py +18 -0
- sage/combinat/crystals/crystals.py +257 -0
- sage/combinat/crystals/direct_sum.py +260 -0
- sage/combinat/crystals/elementary_crystals.py +1251 -0
- sage/combinat/crystals/fast_crystals.py +441 -0
- sage/combinat/crystals/fully_commutative_stable_grothendieck.py +1205 -0
- sage/combinat/crystals/generalized_young_walls.py +1076 -0
- sage/combinat/crystals/highest_weight_crystals.py +436 -0
- sage/combinat/crystals/induced_structure.py +695 -0
- sage/combinat/crystals/infinity_crystals.py +730 -0
- sage/combinat/crystals/kac_modules.py +863 -0
- sage/combinat/crystals/kirillov_reshetikhin.py +4196 -0
- sage/combinat/crystals/kyoto_path_model.py +497 -0
- sage/combinat/crystals/letters.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/letters.pxd +79 -0
- sage/combinat/crystals/letters.pyx +3056 -0
- sage/combinat/crystals/littelmann_path.py +1518 -0
- sage/combinat/crystals/monomial_crystals.py +1262 -0
- sage/combinat/crystals/multisegments.py +462 -0
- sage/combinat/crystals/mv_polytopes.py +467 -0
- sage/combinat/crystals/pbw_crystal.py +511 -0
- sage/combinat/crystals/pbw_datum.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/pbw_datum.pxd +4 -0
- sage/combinat/crystals/pbw_datum.pyx +487 -0
- sage/combinat/crystals/polyhedral_realization.py +372 -0
- sage/combinat/crystals/spins.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/spins.pxd +21 -0
- sage/combinat/crystals/spins.pyx +756 -0
- sage/combinat/crystals/star_crystal.py +290 -0
- sage/combinat/crystals/subcrystal.py +464 -0
- sage/combinat/crystals/tensor_product.py +1177 -0
- sage/combinat/crystals/tensor_product_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/tensor_product_element.pxd +35 -0
- sage/combinat/crystals/tensor_product_element.pyx +1870 -0
- sage/combinat/crystals/virtual_crystal.py +420 -0
- sage/combinat/cyclic_sieving_phenomenon.py +204 -0
- sage/combinat/debruijn_sequence.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/debruijn_sequence.pyx +355 -0
- sage/combinat/decorated_permutation.py +270 -0
- sage/combinat/degree_sequences.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/degree_sequences.pyx +588 -0
- sage/combinat/derangements.py +527 -0
- sage/combinat/descent_algebra.py +1008 -0
- sage/combinat/diagram.py +1551 -0
- sage/combinat/diagram_algebras.py +5886 -0
- sage/combinat/dyck_word.py +4349 -0
- sage/combinat/e_one_star.py +1623 -0
- sage/combinat/enumerated_sets.py +123 -0
- sage/combinat/expnums.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/expnums.pyx +148 -0
- sage/combinat/fast_vector_partitions.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/fast_vector_partitions.pyx +346 -0
- sage/combinat/fqsym.py +1977 -0
- sage/combinat/free_dendriform_algebra.py +954 -0
- sage/combinat/free_prelie_algebra.py +1141 -0
- sage/combinat/fully_commutative_elements.py +1077 -0
- sage/combinat/fully_packed_loop.py +1523 -0
- sage/combinat/gelfand_tsetlin_patterns.py +1409 -0
- sage/combinat/gray_codes.py +311 -0
- sage/combinat/grossman_larson_algebras.py +667 -0
- sage/combinat/growth.py +4352 -0
- sage/combinat/hall_polynomial.py +188 -0
- sage/combinat/hillman_grassl.py +866 -0
- sage/combinat/integer_matrices.py +329 -0
- sage/combinat/integer_vectors_mod_permgroup.py +1238 -0
- sage/combinat/k_tableau.py +4564 -0
- sage/combinat/kazhdan_lusztig.py +215 -0
- sage/combinat/key_polynomial.py +885 -0
- sage/combinat/knutson_tao_puzzles.py +2286 -0
- sage/combinat/lr_tableau.py +311 -0
- sage/combinat/matrices/all.py +24 -0
- sage/combinat/matrices/hadamard_matrix.py +3790 -0
- sage/combinat/matrices/latin.py +2912 -0
- sage/combinat/misc.py +401 -0
- sage/combinat/multiset_partition_into_sets_ordered.py +3541 -0
- sage/combinat/ncsf_qsym/all.py +21 -0
- sage/combinat/ncsf_qsym/combinatorics.py +317 -0
- sage/combinat/ncsf_qsym/generic_basis_code.py +1427 -0
- sage/combinat/ncsf_qsym/ncsf.py +5637 -0
- sage/combinat/ncsf_qsym/qsym.py +4053 -0
- sage/combinat/ncsf_qsym/tutorial.py +447 -0
- sage/combinat/ncsym/all.py +21 -0
- sage/combinat/ncsym/bases.py +855 -0
- sage/combinat/ncsym/dual.py +593 -0
- sage/combinat/ncsym/ncsym.py +2076 -0
- sage/combinat/necklace.py +551 -0
- sage/combinat/non_decreasing_parking_function.py +634 -0
- sage/combinat/nu_dyck_word.py +1474 -0
- sage/combinat/output.py +861 -0
- sage/combinat/parallelogram_polyomino.py +4326 -0
- sage/combinat/parking_functions.py +1602 -0
- sage/combinat/partition_algebra.py +1998 -0
- sage/combinat/partition_kleshchev.py +1982 -0
- sage/combinat/partition_shifting_algebras.py +584 -0
- sage/combinat/partition_tuple.py +3114 -0
- sage/combinat/path_tableaux/all.py +13 -0
- sage/combinat/path_tableaux/catalog.py +29 -0
- sage/combinat/path_tableaux/dyck_path.py +380 -0
- sage/combinat/path_tableaux/frieze.py +476 -0
- sage/combinat/path_tableaux/path_tableau.py +728 -0
- sage/combinat/path_tableaux/semistandard.py +510 -0
- sage/combinat/perfect_matching.py +779 -0
- sage/combinat/plane_partition.py +3300 -0
- sage/combinat/q_bernoulli.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/q_bernoulli.pyx +128 -0
- sage/combinat/quickref.py +81 -0
- sage/combinat/recognizable_series.py +2051 -0
- sage/combinat/regular_sequence.py +4316 -0
- sage/combinat/regular_sequence_bounded.py +543 -0
- sage/combinat/restricted_growth.py +81 -0
- sage/combinat/ribbon.py +20 -0
- sage/combinat/ribbon_shaped_tableau.py +489 -0
- sage/combinat/ribbon_tableau.py +1180 -0
- sage/combinat/rigged_configurations/all.py +46 -0
- sage/combinat/rigged_configurations/bij_abstract_class.py +548 -0
- sage/combinat/rigged_configurations/bij_infinity.py +370 -0
- sage/combinat/rigged_configurations/bij_type_A.py +163 -0
- sage/combinat/rigged_configurations/bij_type_A2_dual.py +338 -0
- sage/combinat/rigged_configurations/bij_type_A2_even.py +218 -0
- sage/combinat/rigged_configurations/bij_type_A2_odd.py +199 -0
- sage/combinat/rigged_configurations/bij_type_B.py +900 -0
- sage/combinat/rigged_configurations/bij_type_C.py +267 -0
- sage/combinat/rigged_configurations/bij_type_D.py +771 -0
- sage/combinat/rigged_configurations/bij_type_D_tri.py +392 -0
- sage/combinat/rigged_configurations/bij_type_D_twisted.py +576 -0
- sage/combinat/rigged_configurations/bij_type_E67.py +402 -0
- sage/combinat/rigged_configurations/bijection.py +143 -0
- sage/combinat/rigged_configurations/kleber_tree.py +1475 -0
- sage/combinat/rigged_configurations/kr_tableaux.py +1898 -0
- sage/combinat/rigged_configurations/rc_crystal.py +461 -0
- sage/combinat/rigged_configurations/rc_infinity.py +540 -0
- sage/combinat/rigged_configurations/rigged_configuration_element.py +2403 -0
- sage/combinat/rigged_configurations/rigged_configurations.py +1918 -0
- sage/combinat/rigged_configurations/rigged_partition.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/rigged_configurations/rigged_partition.pxd +15 -0
- sage/combinat/rigged_configurations/rigged_partition.pyx +680 -0
- sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +499 -0
- sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py +428 -0
- sage/combinat/rsk.py +3438 -0
- sage/combinat/schubert_polynomial.py +508 -0
- sage/combinat/set_partition.py +3318 -0
- sage/combinat/set_partition_iterator.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/set_partition_iterator.pyx +136 -0
- sage/combinat/set_partition_ordered.py +1590 -0
- sage/combinat/sf/abreu_nigro.py +346 -0
- sage/combinat/sf/all.py +52 -0
- sage/combinat/sf/character.py +576 -0
- sage/combinat/sf/classical.py +319 -0
- sage/combinat/sf/dual.py +996 -0
- sage/combinat/sf/elementary.py +549 -0
- sage/combinat/sf/hall_littlewood.py +1028 -0
- sage/combinat/sf/hecke.py +336 -0
- sage/combinat/sf/homogeneous.py +464 -0
- sage/combinat/sf/jack.py +1428 -0
- sage/combinat/sf/k_dual.py +1458 -0
- sage/combinat/sf/kfpoly.py +447 -0
- sage/combinat/sf/llt.py +789 -0
- sage/combinat/sf/macdonald.py +2019 -0
- sage/combinat/sf/monomial.py +525 -0
- sage/combinat/sf/multiplicative.py +113 -0
- sage/combinat/sf/new_kschur.py +1786 -0
- sage/combinat/sf/ns_macdonald.py +964 -0
- sage/combinat/sf/orthogonal.py +246 -0
- sage/combinat/sf/orthotriang.py +355 -0
- sage/combinat/sf/powersum.py +963 -0
- sage/combinat/sf/schur.py +880 -0
- sage/combinat/sf/sf.py +1653 -0
- sage/combinat/sf/sfa.py +7053 -0
- sage/combinat/sf/symplectic.py +253 -0
- sage/combinat/sf/witt.py +721 -0
- sage/combinat/shifted_primed_tableau.py +2735 -0
- sage/combinat/shuffle.py +830 -0
- sage/combinat/sidon_sets.py +146 -0
- sage/combinat/similarity_class_type.py +1721 -0
- sage/combinat/sine_gordon.py +618 -0
- sage/combinat/six_vertex_model.py +784 -0
- sage/combinat/skew_partition.py +2053 -0
- sage/combinat/skew_tableau.py +2989 -0
- sage/combinat/sloane_functions.py +8935 -0
- sage/combinat/specht_module.py +1403 -0
- sage/combinat/species/all.py +48 -0
- sage/combinat/species/characteristic_species.py +321 -0
- sage/combinat/species/composition_species.py +273 -0
- sage/combinat/species/cycle_species.py +284 -0
- sage/combinat/species/empty_species.py +155 -0
- sage/combinat/species/functorial_composition_species.py +148 -0
- sage/combinat/species/generating_series.py +673 -0
- sage/combinat/species/library.py +148 -0
- sage/combinat/species/linear_order_species.py +169 -0
- sage/combinat/species/misc.py +83 -0
- sage/combinat/species/partition_species.py +290 -0
- sage/combinat/species/permutation_species.py +268 -0
- sage/combinat/species/product_species.py +423 -0
- sage/combinat/species/recursive_species.py +476 -0
- sage/combinat/species/set_species.py +192 -0
- sage/combinat/species/species.py +820 -0
- sage/combinat/species/structure.py +539 -0
- sage/combinat/species/subset_species.py +243 -0
- sage/combinat/species/sum_species.py +225 -0
- sage/combinat/subword.py +564 -0
- sage/combinat/subword_complex.py +2122 -0
- sage/combinat/subword_complex_c.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/subword_complex_c.pyx +119 -0
- sage/combinat/super_tableau.py +821 -0
- sage/combinat/superpartition.py +1154 -0
- sage/combinat/symmetric_group_algebra.py +3774 -0
- sage/combinat/symmetric_group_representations.py +1830 -0
- sage/combinat/t_sequences.py +877 -0
- sage/combinat/tableau.py +9506 -0
- sage/combinat/tableau_residues.py +860 -0
- sage/combinat/tableau_tuple.py +5353 -0
- sage/combinat/tiling.py +2432 -0
- sage/combinat/triangles_FHM.py +777 -0
- sage/combinat/tutorial.py +1857 -0
- sage/combinat/vector_partition.py +337 -0
- sage/combinat/words/abstract_word.py +1722 -0
- sage/combinat/words/all.py +59 -0
- sage/combinat/words/alphabet.py +268 -0
- sage/combinat/words/finite_word.py +7201 -0
- sage/combinat/words/infinite_word.py +113 -0
- sage/combinat/words/lyndon_word.py +652 -0
- sage/combinat/words/morphic.py +351 -0
- sage/combinat/words/morphism.py +3878 -0
- sage/combinat/words/paths.py +2932 -0
- sage/combinat/words/shuffle_product.py +278 -0
- sage/combinat/words/suffix_trees.py +1873 -0
- sage/combinat/words/word.py +769 -0
- sage/combinat/words/word_char.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/words/word_char.pyx +847 -0
- sage/combinat/words/word_datatypes.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/words/word_datatypes.pxd +4 -0
- sage/combinat/words/word_datatypes.pyx +1067 -0
- sage/combinat/words/word_generators.py +2026 -0
- sage/combinat/words/word_infinite_datatypes.py +1218 -0
- sage/combinat/words/word_options.py +99 -0
- sage/combinat/words/words.py +2396 -0
- sage/data_structures/all__sagemath_combinat.py +1 -0
- sage/databases/all__sagemath_combinat.py +13 -0
- sage/databases/findstat.py +4897 -0
- sage/databases/oeis.py +2058 -0
- sage/databases/sloane.py +393 -0
- sage/dynamics/all__sagemath_combinat.py +14 -0
- sage/dynamics/cellular_automata/all.py +7 -0
- sage/dynamics/cellular_automata/catalog.py +34 -0
- sage/dynamics/cellular_automata/elementary.py +612 -0
- sage/dynamics/cellular_automata/glca.py +477 -0
- sage/dynamics/cellular_automata/solitons.py +1463 -0
- sage/dynamics/finite_dynamical_system.py +1249 -0
- sage/dynamics/finite_dynamical_system_catalog.py +382 -0
- sage/games/all.py +7 -0
- sage/games/hexad.py +704 -0
- sage/games/quantumino.py +591 -0
- sage/games/sudoku.py +889 -0
- sage/games/sudoku_backtrack.cpython-314-x86_64-linux-musl.so +0 -0
- sage/games/sudoku_backtrack.pyx +189 -0
- sage/groups/all__sagemath_combinat.py +1 -0
- sage/groups/indexed_free_group.py +489 -0
- sage/libs/all__sagemath_combinat.py +6 -0
- sage/libs/lrcalc/__init__.py +1 -0
- sage/libs/lrcalc/lrcalc.py +525 -0
- sage/libs/symmetrica/__init__.py +7 -0
- sage/libs/symmetrica/all.py +101 -0
- sage/libs/symmetrica/kostka.pxi +168 -0
- sage/libs/symmetrica/part.pxi +193 -0
- sage/libs/symmetrica/plet.pxi +42 -0
- sage/libs/symmetrica/sab.pxi +196 -0
- sage/libs/symmetrica/sb.pxi +332 -0
- sage/libs/symmetrica/sc.pxi +192 -0
- sage/libs/symmetrica/schur.pxi +956 -0
- sage/libs/symmetrica/symmetrica.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/symmetrica/symmetrica.pxi +1172 -0
- sage/libs/symmetrica/symmetrica.pyx +39 -0
- sage/monoids/all.py +13 -0
- sage/monoids/automatic_semigroup.py +1054 -0
- sage/monoids/free_abelian_monoid.py +315 -0
- sage/monoids/free_abelian_monoid_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/monoids/free_abelian_monoid_element.pxd +16 -0
- sage/monoids/free_abelian_monoid_element.pyx +397 -0
- sage/monoids/free_monoid.py +335 -0
- sage/monoids/free_monoid_element.py +431 -0
- sage/monoids/hecke_monoid.py +65 -0
- sage/monoids/string_monoid.py +817 -0
- sage/monoids/string_monoid_element.py +547 -0
- sage/monoids/string_ops.py +143 -0
- sage/monoids/trace_monoid.py +972 -0
- sage/rings/all__sagemath_combinat.py +2 -0
- sage/sat/all.py +4 -0
- sage/sat/boolean_polynomials.py +405 -0
- sage/sat/converters/__init__.py +6 -0
- sage/sat/converters/anf2cnf.py +14 -0
- sage/sat/converters/polybori.py +611 -0
- sage/sat/solvers/__init__.py +5 -0
- sage/sat/solvers/cryptominisat.py +287 -0
- sage/sat/solvers/dimacs.py +783 -0
- sage/sat/solvers/picosat.py +228 -0
- sage/sat/solvers/sat_lp.py +156 -0
- sage/sat/solvers/satsolver.cpython-314-x86_64-linux-musl.so +0 -0
- sage/sat/solvers/satsolver.pxd +3 -0
- sage/sat/solvers/satsolver.pyx +405 -0
|
@@ -0,0 +1,2989 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
r"""
|
|
3
|
+
Skew tableaux
|
|
4
|
+
|
|
5
|
+
AUTHORS:
|
|
6
|
+
|
|
7
|
+
- Mike Hansen: Initial version
|
|
8
|
+
- Travis Scrimshaw, Arthur Lubovsky (2013-02-11):
|
|
9
|
+
Factored out ``CombinatorialClass``
|
|
10
|
+
- Trevor K. Karn (2022-08-03): added ``backward_slide``
|
|
11
|
+
- Joseph McDonough (2025-04-09): added ``add_entry`` and ``anti_restrict``
|
|
12
|
+
"""
|
|
13
|
+
# ****************************************************************************
|
|
14
|
+
# Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
|
|
15
|
+
# Copyright (C) 2013 Travis Scrimshaw <tcscrims at gmail.com>
|
|
16
|
+
# Copyright (C) 2013 Arthur Lubovsky
|
|
17
|
+
#
|
|
18
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
19
|
+
#
|
|
20
|
+
# This code is distributed in the hope that it will be useful,
|
|
21
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
22
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
23
|
+
# General Public License for more details.
|
|
24
|
+
#
|
|
25
|
+
# The full text of the GPL is available at:
|
|
26
|
+
#
|
|
27
|
+
# https://www.gnu.org/licenses/
|
|
28
|
+
# ****************************************************************************
|
|
29
|
+
|
|
30
|
+
from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass
|
|
31
|
+
from sage.misc.lazy_import import lazy_import
|
|
32
|
+
from sage.structure.parent import Parent
|
|
33
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
34
|
+
from sage.categories.sets_cat import Sets
|
|
35
|
+
from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
|
|
36
|
+
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
|
|
37
|
+
|
|
38
|
+
from sage.rings.integer import Integer
|
|
39
|
+
from sage.rings.integer_ring import ZZ
|
|
40
|
+
from sage.rings.rational_field import QQ
|
|
41
|
+
from sage.arith.misc import factorial
|
|
42
|
+
from sage.rings.infinity import PlusInfinity
|
|
43
|
+
|
|
44
|
+
from sage.structure.list_clone import ClonableList
|
|
45
|
+
from sage.combinat.partition import Partition
|
|
46
|
+
from sage.combinat.tableau import (Tableau, Tableaux,
|
|
47
|
+
StandardTableau, SemistandardTableau)
|
|
48
|
+
from sage.combinat.skew_partition import SkewPartition, SkewPartitions
|
|
49
|
+
from sage.combinat.integer_vector import IntegerVectors
|
|
50
|
+
from sage.combinat.words.words import Words
|
|
51
|
+
|
|
52
|
+
from sage.misc.persist import register_unpickle_override
|
|
53
|
+
|
|
54
|
+
lazy_import('sage.matrix.special', 'zero_matrix')
|
|
55
|
+
lazy_import('sage.groups.perm_gps.permgroup', 'PermutationGroup')
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class SkewTableau(ClonableList,
|
|
59
|
+
metaclass=InheritComparisonClasscallMetaclass):
|
|
60
|
+
r"""
|
|
61
|
+
A skew tableau.
|
|
62
|
+
|
|
63
|
+
Note that Sage by default uses the English convention for partitions and
|
|
64
|
+
tableaux. To change this, see :meth:`Tableaux.options`.
|
|
65
|
+
|
|
66
|
+
EXAMPLES::
|
|
67
|
+
|
|
68
|
+
sage: st = SkewTableau([[None, 1],[2,3]]); st
|
|
69
|
+
[[None, 1], [2, 3]]
|
|
70
|
+
sage: st.inner_shape()
|
|
71
|
+
[1]
|
|
72
|
+
sage: st.outer_shape()
|
|
73
|
+
[2, 2]
|
|
74
|
+
|
|
75
|
+
The ``expr`` form of a skew tableau consists of the inner partition
|
|
76
|
+
followed by a list of the entries in each row from bottom to top::
|
|
77
|
+
|
|
78
|
+
sage: SkewTableau(expr=[[1,1],[[5],[3,4],[1,2]]])
|
|
79
|
+
[[None, 1, 2], [None, 3, 4], [5]]
|
|
80
|
+
|
|
81
|
+
The ``chain`` form of a skew tableau consists of a list of
|
|
82
|
+
partitions `\lambda_1,\lambda_2,\ldots,`, such that all cells in
|
|
83
|
+
`\lambda_{i+1}` that are not in `\lambda_i` have entry `i`::
|
|
84
|
+
|
|
85
|
+
sage: SkewTableau(chain=[[2], [2, 1], [3, 1], [4, 3, 2, 1]])
|
|
86
|
+
[[None, None, 2, 3], [1, 3, 3], [3, 3], [3]]
|
|
87
|
+
"""
|
|
88
|
+
@staticmethod
|
|
89
|
+
def __classcall_private__(cls, st=None, expr=None, chain=None):
|
|
90
|
+
"""
|
|
91
|
+
Return the skew tableau object corresponding to ``st``.
|
|
92
|
+
|
|
93
|
+
EXAMPLES::
|
|
94
|
+
|
|
95
|
+
sage: SkewTableau([[None,1],[2,3]])
|
|
96
|
+
[[None, 1], [2, 3]]
|
|
97
|
+
sage: SkewTableau(expr=[[1,1],[[5],[3,4],[1,2]]])
|
|
98
|
+
[[None, 1, 2], [None, 3, 4], [5]]
|
|
99
|
+
"""
|
|
100
|
+
if isinstance(st, cls):
|
|
101
|
+
return st
|
|
102
|
+
if expr is not None:
|
|
103
|
+
return SkewTableaux().from_expr(expr)
|
|
104
|
+
if chain is not None:
|
|
105
|
+
return SkewTableaux().from_chain(chain)
|
|
106
|
+
|
|
107
|
+
return SkewTableaux()(st)
|
|
108
|
+
|
|
109
|
+
def __init__(self, parent, st):
|
|
110
|
+
"""
|
|
111
|
+
TESTS::
|
|
112
|
+
|
|
113
|
+
sage: st = SkewTableau([[None, 1],[2,3]])
|
|
114
|
+
sage: st = SkewTableau([[None,1,1],[None,2],[4]])
|
|
115
|
+
sage: TestSuite(st).run()
|
|
116
|
+
|
|
117
|
+
A skew tableau is immutable, see :issue:`15862`::
|
|
118
|
+
|
|
119
|
+
sage: T = SkewTableau([[None,2],[2]])
|
|
120
|
+
sage: t0 = T[0]
|
|
121
|
+
sage: t0[1] = 3
|
|
122
|
+
Traceback (most recent call last):
|
|
123
|
+
...
|
|
124
|
+
TypeError: 'tuple' object does not support item assignment
|
|
125
|
+
sage: T[0][1] = 5
|
|
126
|
+
Traceback (most recent call last):
|
|
127
|
+
...
|
|
128
|
+
TypeError: 'tuple' object does not support item assignment
|
|
129
|
+
"""
|
|
130
|
+
try:
|
|
131
|
+
st = [tuple(t) for t in st]
|
|
132
|
+
except TypeError:
|
|
133
|
+
raise TypeError("each element of the skew tableau must be an iterable")
|
|
134
|
+
|
|
135
|
+
ClonableList.__init__(self, parent, st)
|
|
136
|
+
|
|
137
|
+
def __eq__(self, other):
|
|
138
|
+
r"""
|
|
139
|
+
Check whether ``self`` is equal to ``other``.
|
|
140
|
+
|
|
141
|
+
.. TODO::
|
|
142
|
+
|
|
143
|
+
This overwrites the equality check of
|
|
144
|
+
:class:`~sage.structure.list_clone.ClonableList`
|
|
145
|
+
in order to circumvent the coercion framework.
|
|
146
|
+
Eventually this should be solved more elegantly,
|
|
147
|
+
for example along the lines of what was done for
|
|
148
|
+
`k`-tableaux.
|
|
149
|
+
|
|
150
|
+
For now, two elements are equal if their underlying
|
|
151
|
+
defining lists compare equal.
|
|
152
|
+
|
|
153
|
+
INPUT:
|
|
154
|
+
|
|
155
|
+
- ``other`` -- the element that ``self`` is compared to
|
|
156
|
+
|
|
157
|
+
OUTPUT: boolean
|
|
158
|
+
|
|
159
|
+
TESTS::
|
|
160
|
+
|
|
161
|
+
sage: t = SkewTableau([[None,1,2]])
|
|
162
|
+
sage: t == 0
|
|
163
|
+
False
|
|
164
|
+
sage: t == SkewTableaux()([[None,1,2]])
|
|
165
|
+
True
|
|
166
|
+
sage: t == [(None,1,2)]
|
|
167
|
+
True
|
|
168
|
+
sage: t == [[None,1,2]]
|
|
169
|
+
True
|
|
170
|
+
|
|
171
|
+
sage: s = SkewTableau([[1,2]])
|
|
172
|
+
sage: s == 0
|
|
173
|
+
False
|
|
174
|
+
sage: s == Tableau([[1,2]])
|
|
175
|
+
True
|
|
176
|
+
"""
|
|
177
|
+
if isinstance(other, (Tableau, SkewTableau)):
|
|
178
|
+
return list(self) == list(other)
|
|
179
|
+
else:
|
|
180
|
+
return list(self) == other or list(list(row) for row in self) == other
|
|
181
|
+
|
|
182
|
+
def __ne__(self, other):
|
|
183
|
+
r"""
|
|
184
|
+
Check whether ``self`` is unequal to ``other``.
|
|
185
|
+
|
|
186
|
+
See the documentation of :meth:`__eq__`.
|
|
187
|
+
|
|
188
|
+
INPUT:
|
|
189
|
+
|
|
190
|
+
- ``other`` -- the element that ``self`` is compared to
|
|
191
|
+
|
|
192
|
+
OUTPUT: boolean
|
|
193
|
+
|
|
194
|
+
TESTS::
|
|
195
|
+
|
|
196
|
+
sage: t = SkewTableau([[None,1,2]])
|
|
197
|
+
sage: t != []
|
|
198
|
+
True
|
|
199
|
+
"""
|
|
200
|
+
return not (self == other)
|
|
201
|
+
|
|
202
|
+
def __hash__(self):
|
|
203
|
+
"""
|
|
204
|
+
Return the hash of ``self``.
|
|
205
|
+
|
|
206
|
+
EXAMPLES:
|
|
207
|
+
|
|
208
|
+
Check that :issue:`35137` is fixed::
|
|
209
|
+
|
|
210
|
+
sage: t = SkewTableau([[None,1,2]])
|
|
211
|
+
sage: hash(t) == hash(tuple(t))
|
|
212
|
+
True
|
|
213
|
+
"""
|
|
214
|
+
return hash(tuple(self))
|
|
215
|
+
|
|
216
|
+
def check(self):
|
|
217
|
+
r"""
|
|
218
|
+
Check that ``self`` is a valid skew tableau. This is currently far too
|
|
219
|
+
liberal, and only checks some trivial things.
|
|
220
|
+
|
|
221
|
+
EXAMPLES::
|
|
222
|
+
|
|
223
|
+
sage: t = SkewTableau([[None,1,1],[2]])
|
|
224
|
+
sage: t.check()
|
|
225
|
+
|
|
226
|
+
sage: t = SkewTableau([[None, None, 1], [2, 4], [], [3, 4, 5]])
|
|
227
|
+
Traceback (most recent call last):
|
|
228
|
+
...
|
|
229
|
+
TypeError: a skew tableau cannot have an empty list for a row
|
|
230
|
+
|
|
231
|
+
sage: s = SkewTableau([[1, None, None],[2, None],[3]])
|
|
232
|
+
Traceback (most recent call last):
|
|
233
|
+
...
|
|
234
|
+
TypeError: not a valid skew tableau
|
|
235
|
+
"""
|
|
236
|
+
for row in self:
|
|
237
|
+
if not row:
|
|
238
|
+
raise TypeError("a skew tableau cannot have an empty list for a row")
|
|
239
|
+
inside = False
|
|
240
|
+
for x in row:
|
|
241
|
+
if x is not None:
|
|
242
|
+
inside = True
|
|
243
|
+
elif inside:
|
|
244
|
+
raise TypeError('not a valid skew tableau')
|
|
245
|
+
|
|
246
|
+
def _repr_(self):
|
|
247
|
+
"""
|
|
248
|
+
Return a string representation of ``self``.
|
|
249
|
+
|
|
250
|
+
For more on the display options, see
|
|
251
|
+
:obj:`SkewTableaux.options`.
|
|
252
|
+
|
|
253
|
+
EXAMPLES::
|
|
254
|
+
|
|
255
|
+
sage: SkewTableau([[None,2,3],[None,4],[5]])
|
|
256
|
+
[[None, 2, 3], [None, 4], [5]]
|
|
257
|
+
"""
|
|
258
|
+
return self.parent().options._dispatch(self, '_repr_', 'display')
|
|
259
|
+
|
|
260
|
+
def _repr_list(self):
|
|
261
|
+
"""
|
|
262
|
+
Return a string representation of ``self`` as a list of lists.
|
|
263
|
+
|
|
264
|
+
EXAMPLES::
|
|
265
|
+
|
|
266
|
+
sage: print(SkewTableau([[None,2,3],[None,4],[5]])._repr_list())
|
|
267
|
+
[[None, 2, 3], [None, 4], [5]]
|
|
268
|
+
"""
|
|
269
|
+
return repr(self.to_list())
|
|
270
|
+
|
|
271
|
+
# See #18024. CombinatorialObject provided __str__, though ClonableList
|
|
272
|
+
# doesn't. Emulate the old functionality. Possibly remove when
|
|
273
|
+
# CombinatorialObject is removed.
|
|
274
|
+
__str__ = _repr_list
|
|
275
|
+
|
|
276
|
+
def _repr_diagram(self):
|
|
277
|
+
"""
|
|
278
|
+
Return a string representation of ``self`` as a diagram.
|
|
279
|
+
|
|
280
|
+
EXAMPLES::
|
|
281
|
+
|
|
282
|
+
sage: print(SkewTableau([[None,2,3],[None,4],[5]])._repr_diagram())
|
|
283
|
+
. 2 3
|
|
284
|
+
. 4
|
|
285
|
+
5
|
|
286
|
+
"""
|
|
287
|
+
def none_str(x):
|
|
288
|
+
return " ." if x is None else "%3s" % str(x)
|
|
289
|
+
if self.parent().options('convention') == "French":
|
|
290
|
+
new_rows = ["".join(map(none_str, row)) for row in reversed(self)]
|
|
291
|
+
else:
|
|
292
|
+
new_rows = ["".join(map(none_str, row)) for row in self]
|
|
293
|
+
return '\n'.join(new_rows)
|
|
294
|
+
|
|
295
|
+
def _repr_compact(self):
|
|
296
|
+
"""
|
|
297
|
+
Return a compact string representation of ``self``.
|
|
298
|
+
|
|
299
|
+
EXAMPLES::
|
|
300
|
+
|
|
301
|
+
sage: SkewTableau([[None,None,3],[4,5]])._repr_compact()
|
|
302
|
+
'.,.,3/4,5'
|
|
303
|
+
sage: Tableau([])._repr_compact()
|
|
304
|
+
'-'
|
|
305
|
+
"""
|
|
306
|
+
if not self:
|
|
307
|
+
return '-'
|
|
308
|
+
|
|
309
|
+
def str_rep(x):
|
|
310
|
+
return '%s' % x if x is not None else '.'
|
|
311
|
+
return '/'.join(','.join(str_rep(r) for r in row) for row in self)
|
|
312
|
+
|
|
313
|
+
def pp(self):
|
|
314
|
+
"""
|
|
315
|
+
Return a pretty print string of the tableau.
|
|
316
|
+
|
|
317
|
+
EXAMPLES::
|
|
318
|
+
|
|
319
|
+
sage: SkewTableau([[None,2,3],[None,4],[5]]).pp()
|
|
320
|
+
. 2 3
|
|
321
|
+
. 4
|
|
322
|
+
5
|
|
323
|
+
"""
|
|
324
|
+
print(self._repr_diagram())
|
|
325
|
+
|
|
326
|
+
def _ascii_art_(self):
|
|
327
|
+
r"""
|
|
328
|
+
Return an ascii art representation of ``self``.
|
|
329
|
+
|
|
330
|
+
TESTS::
|
|
331
|
+
|
|
332
|
+
sage: T1 = SkewTableau([[None,2,3],[None,4],[5]])
|
|
333
|
+
sage: T2 = SkewTableau([[None,None,3],[4,5]])
|
|
334
|
+
sage: ascii_art([T1, T2])
|
|
335
|
+
[ . 2 3 ]
|
|
336
|
+
[ . 4 . . 3 ]
|
|
337
|
+
[ 5 , 4 5 ]
|
|
338
|
+
"""
|
|
339
|
+
from sage.typeset.ascii_art import AsciiArt
|
|
340
|
+
return AsciiArt(self._repr_diagram().splitlines())
|
|
341
|
+
|
|
342
|
+
def _unicode_art_(self):
|
|
343
|
+
"""
|
|
344
|
+
Return a unicode art representation of ``self``.
|
|
345
|
+
|
|
346
|
+
TESTS::
|
|
347
|
+
|
|
348
|
+
sage: T = SkewTableau([[None,None,1,1,2],[None,2,3],[None,4],[None,5],[6]])
|
|
349
|
+
sage: unicode_art(T)
|
|
350
|
+
┌───┬───┬───┐
|
|
351
|
+
│ 1 │ 1 │ 2 │
|
|
352
|
+
┌───┼───┼───┴───┘
|
|
353
|
+
│ 2 │ 3 │
|
|
354
|
+
├───┼───┘
|
|
355
|
+
│ 4 │
|
|
356
|
+
├───┤
|
|
357
|
+
│ 5 │
|
|
358
|
+
┌───┼───┘
|
|
359
|
+
│ 6 │
|
|
360
|
+
└───┘
|
|
361
|
+
"""
|
|
362
|
+
from sage.combinat.output import ascii_art_table
|
|
363
|
+
from sage.typeset.unicode_art import UnicodeArt
|
|
364
|
+
return UnicodeArt(ascii_art_table(self, use_unicode=True).splitlines())
|
|
365
|
+
|
|
366
|
+
def _latex_(self):
|
|
367
|
+
r"""
|
|
368
|
+
Return a `\LaTeX` representation of ``self``.
|
|
369
|
+
|
|
370
|
+
EXAMPLES::
|
|
371
|
+
|
|
372
|
+
sage: latex(SkewTableau([[None,2,3],[None,4],[5]]))
|
|
373
|
+
{\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
|
|
374
|
+
\raisebox{-.6ex}{$\begin{array}[b]{*{3}c}\cline{2-3}
|
|
375
|
+
&\lr{2}&\lr{3}\\\cline{2-3}
|
|
376
|
+
&\lr{4}\\\cline{1-2}
|
|
377
|
+
\lr{5}\\\cline{1-1}
|
|
378
|
+
\end{array}$}
|
|
379
|
+
}
|
|
380
|
+
"""
|
|
381
|
+
from sage.combinat.output import tex_from_array
|
|
382
|
+
return tex_from_array(self)
|
|
383
|
+
|
|
384
|
+
def outer_shape(self):
|
|
385
|
+
"""
|
|
386
|
+
Return the outer shape of ``self``.
|
|
387
|
+
|
|
388
|
+
EXAMPLES::
|
|
389
|
+
|
|
390
|
+
sage: SkewTableau([[None,1,2],[None,3],[4]]).outer_shape()
|
|
391
|
+
[3, 2, 1]
|
|
392
|
+
"""
|
|
393
|
+
return Partition([len(row) for row in self])
|
|
394
|
+
|
|
395
|
+
def inner_shape(self):
|
|
396
|
+
"""
|
|
397
|
+
Return the inner shape of ``self``.
|
|
398
|
+
|
|
399
|
+
EXAMPLES::
|
|
400
|
+
|
|
401
|
+
sage: SkewTableau([[None,1,2],[None,3],[4]]).inner_shape()
|
|
402
|
+
[1, 1]
|
|
403
|
+
sage: SkewTableau([[1,2],[3,4],[7]]).inner_shape()
|
|
404
|
+
[]
|
|
405
|
+
sage: SkewTableau([[None,None,None,2,3],[None,1],[None],[2]]).inner_shape()
|
|
406
|
+
[3, 1, 1]
|
|
407
|
+
"""
|
|
408
|
+
return Partition([x for x in (row.count(None) for row in self) if x != 0])
|
|
409
|
+
|
|
410
|
+
def shape(self):
|
|
411
|
+
r"""
|
|
412
|
+
Return the shape of ``self``.
|
|
413
|
+
|
|
414
|
+
EXAMPLES::
|
|
415
|
+
|
|
416
|
+
sage: SkewTableau([[None,1,2],[None,3],[4]]).shape()
|
|
417
|
+
[3, 2, 1] / [1, 1]
|
|
418
|
+
"""
|
|
419
|
+
return SkewPartition([self.outer_shape(), self.inner_shape()])
|
|
420
|
+
|
|
421
|
+
def outer_size(self):
|
|
422
|
+
"""
|
|
423
|
+
Return the size of the outer shape of ``self``.
|
|
424
|
+
|
|
425
|
+
EXAMPLES::
|
|
426
|
+
|
|
427
|
+
sage: SkewTableau([[None, 2, 4], [None, 3], [1]]).outer_size()
|
|
428
|
+
6
|
|
429
|
+
sage: SkewTableau([[None, 2], [1, 3]]).outer_size()
|
|
430
|
+
4
|
|
431
|
+
"""
|
|
432
|
+
return self.outer_shape().size()
|
|
433
|
+
|
|
434
|
+
def inner_size(self):
|
|
435
|
+
"""
|
|
436
|
+
Return the size of the inner shape of ``self``.
|
|
437
|
+
|
|
438
|
+
EXAMPLES::
|
|
439
|
+
|
|
440
|
+
sage: SkewTableau([[None, 2, 4], [None, 3], [1]]).inner_size()
|
|
441
|
+
2
|
|
442
|
+
sage: SkewTableau([[None, 2], [1, 3]]).inner_size()
|
|
443
|
+
1
|
|
444
|
+
"""
|
|
445
|
+
return self.inner_shape().size()
|
|
446
|
+
|
|
447
|
+
def size(self):
|
|
448
|
+
"""
|
|
449
|
+
Return the number of cells in ``self``.
|
|
450
|
+
|
|
451
|
+
EXAMPLES::
|
|
452
|
+
|
|
453
|
+
sage: SkewTableau([[None, 2, 4], [None, 3], [1]]).size()
|
|
454
|
+
4
|
|
455
|
+
sage: SkewTableau([[None, 2], [1, 3]]).size()
|
|
456
|
+
3
|
|
457
|
+
"""
|
|
458
|
+
one = ZZ.one()
|
|
459
|
+
return sum(one for row in self for x in row if x is not None)
|
|
460
|
+
|
|
461
|
+
def conjugate(self):
|
|
462
|
+
"""
|
|
463
|
+
Return the conjugate of ``self``.
|
|
464
|
+
|
|
465
|
+
EXAMPLES::
|
|
466
|
+
|
|
467
|
+
sage: SkewTableau([[None,1],[2,3]]).conjugate()
|
|
468
|
+
[[None, 2], [1, 3]]
|
|
469
|
+
"""
|
|
470
|
+
conj_shape = self.outer_shape().conjugate()
|
|
471
|
+
|
|
472
|
+
conj = [[None] * row_length for row_length in conj_shape]
|
|
473
|
+
|
|
474
|
+
for i in range(len(conj)):
|
|
475
|
+
for j in range(len(conj[i])):
|
|
476
|
+
conj[i][j] = self[j][i]
|
|
477
|
+
|
|
478
|
+
return SkewTableau(conj)
|
|
479
|
+
|
|
480
|
+
def to_word_by_row(self):
|
|
481
|
+
"""
|
|
482
|
+
Return a word obtained from a row reading of ``self``.
|
|
483
|
+
|
|
484
|
+
This is the word obtained by concatenating the rows from
|
|
485
|
+
the bottommost one (in English notation) to the topmost one.
|
|
486
|
+
|
|
487
|
+
EXAMPLES::
|
|
488
|
+
|
|
489
|
+
sage: s = SkewTableau([[None,1],[2,3]])
|
|
490
|
+
sage: s.pp()
|
|
491
|
+
. 1
|
|
492
|
+
2 3
|
|
493
|
+
sage: s.to_word_by_row()
|
|
494
|
+
word: 231
|
|
495
|
+
sage: s = SkewTableau([[None, 2, 4], [None, 3], [1]])
|
|
496
|
+
sage: s.pp()
|
|
497
|
+
. 2 4
|
|
498
|
+
. 3
|
|
499
|
+
1
|
|
500
|
+
sage: s.to_word_by_row()
|
|
501
|
+
word: 1324
|
|
502
|
+
|
|
503
|
+
TESTS::
|
|
504
|
+
|
|
505
|
+
sage: SkewTableau([[None, None, None], [None]]).to_word_by_row()
|
|
506
|
+
word:
|
|
507
|
+
sage: SkewTableau([]).to_word_by_row()
|
|
508
|
+
word:
|
|
509
|
+
"""
|
|
510
|
+
word = [x for row in reversed(self) for x in row if x is not None]
|
|
511
|
+
return Words("positive integers")(word)
|
|
512
|
+
|
|
513
|
+
def to_word_by_column(self):
|
|
514
|
+
"""
|
|
515
|
+
Return the word obtained from a column reading of the skew
|
|
516
|
+
tableau.
|
|
517
|
+
|
|
518
|
+
This is the word obtained by concatenating the columns from
|
|
519
|
+
the rightmost one (in English notation) to the leftmost one.
|
|
520
|
+
|
|
521
|
+
EXAMPLES::
|
|
522
|
+
|
|
523
|
+
sage: s = SkewTableau([[None,1],[2,3]])
|
|
524
|
+
sage: s.pp()
|
|
525
|
+
. 1
|
|
526
|
+
2 3
|
|
527
|
+
sage: s.to_word_by_column()
|
|
528
|
+
word: 132
|
|
529
|
+
|
|
530
|
+
::
|
|
531
|
+
|
|
532
|
+
sage: s = SkewTableau([[None, 2, 4], [None, 3], [1]])
|
|
533
|
+
sage: s.pp()
|
|
534
|
+
. 2 4
|
|
535
|
+
. 3
|
|
536
|
+
1
|
|
537
|
+
sage: s.to_word_by_column()
|
|
538
|
+
word: 4231
|
|
539
|
+
"""
|
|
540
|
+
return self.conjugate().to_word_by_row()
|
|
541
|
+
|
|
542
|
+
to_word = to_word_by_row
|
|
543
|
+
|
|
544
|
+
def to_permutation(self):
|
|
545
|
+
"""
|
|
546
|
+
Return a permutation with the entries of ``self`` obtained by reading
|
|
547
|
+
``self`` row by row, from the bottommost to the topmost row, with
|
|
548
|
+
each row being read from left to right, in English convention.
|
|
549
|
+
See :meth:`to_word_by_row()`.
|
|
550
|
+
|
|
551
|
+
EXAMPLES::
|
|
552
|
+
|
|
553
|
+
sage: SkewTableau([[None,2],[3,4],[None],[1]]).to_permutation()
|
|
554
|
+
[1, 3, 4, 2]
|
|
555
|
+
sage: SkewTableau([[None,2],[None,4],[1],[3]]).to_permutation()
|
|
556
|
+
[3, 1, 4, 2]
|
|
557
|
+
sage: SkewTableau([[None]]).to_permutation()
|
|
558
|
+
[]
|
|
559
|
+
"""
|
|
560
|
+
from sage.combinat.permutation import Permutation
|
|
561
|
+
perm = [i for row in reversed(self) for i in row if i is not None]
|
|
562
|
+
return Permutation(perm)
|
|
563
|
+
|
|
564
|
+
def weight(self):
|
|
565
|
+
r"""
|
|
566
|
+
Return the weight (aka evaluation) of the tableau ``self``.
|
|
567
|
+
Trailing zeroes are omitted when returning the weight.
|
|
568
|
+
|
|
569
|
+
The weight of a skew tableau `T` is the sequence
|
|
570
|
+
`(a_1, a_2, a_3, \ldots )`, where `a_k` is the number of
|
|
571
|
+
entries of `T` equal to `k`. This sequence contains only
|
|
572
|
+
finitely many nonzero entries.
|
|
573
|
+
|
|
574
|
+
The weight of a skew tableau `T` is the same as the weight
|
|
575
|
+
of the reading word of `T`, for any reading order.
|
|
576
|
+
|
|
577
|
+
:meth:`evaluation` is a synonym for this method.
|
|
578
|
+
|
|
579
|
+
EXAMPLES::
|
|
580
|
+
|
|
581
|
+
sage: SkewTableau([[1,2],[3,4]]).weight()
|
|
582
|
+
[1, 1, 1, 1]
|
|
583
|
+
|
|
584
|
+
sage: SkewTableau([[None,2],[None,4],[None,5],[None]]).weight()
|
|
585
|
+
[0, 1, 0, 1, 1]
|
|
586
|
+
|
|
587
|
+
sage: SkewTableau([]).weight()
|
|
588
|
+
[]
|
|
589
|
+
|
|
590
|
+
sage: SkewTableau([[None,None,None],[None]]).weight()
|
|
591
|
+
[]
|
|
592
|
+
|
|
593
|
+
sage: SkewTableau([[None,3,4],[None,6,7],[4,8],[5,13],[6],[7]]).weight()
|
|
594
|
+
[0, 0, 1, 2, 1, 2, 2, 1, 0, 0, 0, 0, 1]
|
|
595
|
+
|
|
596
|
+
TESTS:
|
|
597
|
+
|
|
598
|
+
We check that this agrees with going to the word::
|
|
599
|
+
|
|
600
|
+
sage: t = SkewTableau([[None,None,4,7,15],[6,2,16],[2,3,19],[4,5],[7]])
|
|
601
|
+
sage: def by_word(T):
|
|
602
|
+
....: ed = T.to_word().evaluation_dict()
|
|
603
|
+
....: m = max(ed) + 1
|
|
604
|
+
....: return [ed.get(k, 0) for k in range(1, m)]
|
|
605
|
+
sage: by_word(t) == t.weight()
|
|
606
|
+
True
|
|
607
|
+
sage: SST = SemistandardTableaux(shape=[3,1,1])
|
|
608
|
+
sage: all(by_word(t) == SkewTableau(t).weight() for t in SST) # needs sage.modules
|
|
609
|
+
True
|
|
610
|
+
"""
|
|
611
|
+
if (not self) or all(c is None for row in self for c in row):
|
|
612
|
+
return []
|
|
613
|
+
m = max(c for row in self for c in row if c is not None)
|
|
614
|
+
if m is None:
|
|
615
|
+
return []
|
|
616
|
+
res = [0] * m
|
|
617
|
+
for row in self:
|
|
618
|
+
for i in row:
|
|
619
|
+
if (i is not None) and i > 0:
|
|
620
|
+
res[i - 1] += 1
|
|
621
|
+
return res
|
|
622
|
+
|
|
623
|
+
evaluation = weight
|
|
624
|
+
|
|
625
|
+
def is_standard(self) -> bool:
|
|
626
|
+
"""
|
|
627
|
+
Return ``True`` if ``self`` is a standard skew tableau and ``False``
|
|
628
|
+
otherwise.
|
|
629
|
+
|
|
630
|
+
EXAMPLES::
|
|
631
|
+
|
|
632
|
+
sage: SkewTableau([[None, 2], [1, 3]]).is_standard()
|
|
633
|
+
True
|
|
634
|
+
sage: SkewTableau([[None, 2], [2, 4]]).is_standard()
|
|
635
|
+
False
|
|
636
|
+
sage: SkewTableau([[None, 3], [2, 4]]).is_standard()
|
|
637
|
+
False
|
|
638
|
+
sage: SkewTableau([[None, 2], [2, 4]]).is_standard()
|
|
639
|
+
False
|
|
640
|
+
"""
|
|
641
|
+
# Check to make sure that it is filled with 1...size
|
|
642
|
+
w = [i for row in self for i in row if i is not None]
|
|
643
|
+
return sorted(w) == list(range(1, len(w) + 1)) and self.is_semistandard()
|
|
644
|
+
|
|
645
|
+
def is_semistandard(self) -> bool:
|
|
646
|
+
"""
|
|
647
|
+
Return ``True`` if ``self`` is a semistandard skew tableau and
|
|
648
|
+
``False`` otherwise.
|
|
649
|
+
|
|
650
|
+
EXAMPLES::
|
|
651
|
+
|
|
652
|
+
sage: SkewTableau([[None, 2, 2], [1, 3]]).is_semistandard()
|
|
653
|
+
True
|
|
654
|
+
sage: SkewTableau([[None, 2], [2, 4]]).is_semistandard()
|
|
655
|
+
True
|
|
656
|
+
sage: SkewTableau([[None, 3], [2, 4]]).is_semistandard()
|
|
657
|
+
True
|
|
658
|
+
sage: SkewTableau([[None, 2], [1, 2]]).is_semistandard()
|
|
659
|
+
False
|
|
660
|
+
sage: SkewTableau([[None, 2, 3]]).is_semistandard()
|
|
661
|
+
True
|
|
662
|
+
sage: SkewTableau([[None, 3, 2]]).is_semistandard()
|
|
663
|
+
False
|
|
664
|
+
sage: SkewTableau([[None, 2, 3], [1, 4]]).is_semistandard()
|
|
665
|
+
True
|
|
666
|
+
sage: SkewTableau([[None, 2, 3], [1, 2]]).is_semistandard()
|
|
667
|
+
False
|
|
668
|
+
sage: SkewTableau([[None, 2, 3], [None, None, 4]]).is_semistandard()
|
|
669
|
+
False
|
|
670
|
+
"""
|
|
671
|
+
if not self:
|
|
672
|
+
return True
|
|
673
|
+
|
|
674
|
+
# Is it weakly increasing along the rows?
|
|
675
|
+
for row in self:
|
|
676
|
+
if any(row[c] is not None and row[c] > row[c + 1]
|
|
677
|
+
for c in range(len(row) - 1)):
|
|
678
|
+
return False
|
|
679
|
+
|
|
680
|
+
# Is it strictly increasing down columns?
|
|
681
|
+
for row, next in zip(self, self[1:]):
|
|
682
|
+
if any(row[c] is not None and row[c] >= next[c] for c in range(len(next))):
|
|
683
|
+
return False
|
|
684
|
+
|
|
685
|
+
return True
|
|
686
|
+
|
|
687
|
+
def to_tableau(self):
|
|
688
|
+
"""
|
|
689
|
+
Return a tableau with the same filling. This only works if the
|
|
690
|
+
inner shape of the skew tableau has size zero.
|
|
691
|
+
|
|
692
|
+
EXAMPLES::
|
|
693
|
+
|
|
694
|
+
sage: SkewTableau([[1,2],[3,4]]).to_tableau()
|
|
695
|
+
[[1, 2], [3, 4]]
|
|
696
|
+
"""
|
|
697
|
+
|
|
698
|
+
if self.inner_size() != 0:
|
|
699
|
+
raise ValueError("the inner size of the skew tableau must be 0")
|
|
700
|
+
from sage.combinat.tableau import Tableau
|
|
701
|
+
return Tableau(self[:])
|
|
702
|
+
|
|
703
|
+
def restrict(self, n):
|
|
704
|
+
"""
|
|
705
|
+
Return the restriction of the (semi)standard skew tableau to all
|
|
706
|
+
the numbers less than or equal to ``n``.
|
|
707
|
+
|
|
708
|
+
.. NOTE::
|
|
709
|
+
|
|
710
|
+
If only the outer shape of the restriction, rather than
|
|
711
|
+
the whole restriction, is needed, then the faster method
|
|
712
|
+
:meth:`restriction_outer_shape` is preferred. Similarly if
|
|
713
|
+
only the skew shape is needed, use :meth:`restriction_shape`.
|
|
714
|
+
|
|
715
|
+
EXAMPLES::
|
|
716
|
+
|
|
717
|
+
sage: SkewTableau([[None,1],[2],[3]]).restrict(2)
|
|
718
|
+
[[None, 1], [2]]
|
|
719
|
+
sage: SkewTableau([[None,1],[2],[3]]).restrict(1)
|
|
720
|
+
[[None, 1]]
|
|
721
|
+
sage: SkewTableau([[None,1],[1],[2]]).restrict(1)
|
|
722
|
+
[[None, 1], [1]]
|
|
723
|
+
"""
|
|
724
|
+
data = ([y for y in x if y is None or y <= n] for x in self)
|
|
725
|
+
return SkewTableau([z for z in data if z])
|
|
726
|
+
|
|
727
|
+
def restriction_outer_shape(self, n):
|
|
728
|
+
"""
|
|
729
|
+
Return the outer shape of the restriction of the semistandard skew
|
|
730
|
+
tableau ``self`` to `n`.
|
|
731
|
+
|
|
732
|
+
If `T` is a semistandard skew tableau and `n` is a nonnegative
|
|
733
|
+
integer, then the restriction of `T` to `n` is defined as the
|
|
734
|
+
(semistandard) skew tableau obtained by removing all cells filled
|
|
735
|
+
with entries greater than `n` from `T`.
|
|
736
|
+
|
|
737
|
+
This method computes merely the outer shape of the restriction.
|
|
738
|
+
For the restriction itself, use :meth:`restrict`.
|
|
739
|
+
|
|
740
|
+
EXAMPLES::
|
|
741
|
+
|
|
742
|
+
sage: SkewTableau([[None,None],[2,3],[3,4]]).restriction_outer_shape(3)
|
|
743
|
+
[2, 2, 1]
|
|
744
|
+
sage: SkewTableau([[None,2],[None],[4],[5]]).restriction_outer_shape(2)
|
|
745
|
+
[2, 1]
|
|
746
|
+
sage: T = SkewTableau([[None,None,3,5],[None,4,4],[17]])
|
|
747
|
+
sage: T.restriction_outer_shape(0)
|
|
748
|
+
[2, 1]
|
|
749
|
+
sage: T.restriction_outer_shape(2)
|
|
750
|
+
[2, 1]
|
|
751
|
+
sage: T.restriction_outer_shape(3)
|
|
752
|
+
[3, 1]
|
|
753
|
+
sage: T.restriction_outer_shape(4)
|
|
754
|
+
[3, 3]
|
|
755
|
+
sage: T.restriction_outer_shape(19)
|
|
756
|
+
[4, 3, 1]
|
|
757
|
+
"""
|
|
758
|
+
from sage.combinat.partition import _Partitions
|
|
759
|
+
one = ZZ.one()
|
|
760
|
+
res = [sum(one for y in row if y is None or y <= n) for row in self]
|
|
761
|
+
return _Partitions(res)
|
|
762
|
+
|
|
763
|
+
def restriction_shape(self, n):
|
|
764
|
+
"""
|
|
765
|
+
Return the skew shape of the restriction of the semistandard
|
|
766
|
+
skew tableau ``self`` to ``n``.
|
|
767
|
+
|
|
768
|
+
If `T` is a semistandard skew tableau and `n` is a nonnegative
|
|
769
|
+
integer, then the restriction of `T` to `n` is defined as the
|
|
770
|
+
(semistandard) skew tableau obtained by removing all cells filled
|
|
771
|
+
with entries greater than `n` from `T`.
|
|
772
|
+
|
|
773
|
+
This method computes merely the skew shape of the restriction.
|
|
774
|
+
For the restriction itself, use :meth:`restrict`.
|
|
775
|
+
|
|
776
|
+
EXAMPLES::
|
|
777
|
+
|
|
778
|
+
sage: SkewTableau([[None,None],[2,3],[3,4]]).restriction_shape(3)
|
|
779
|
+
[2, 2, 1] / [2]
|
|
780
|
+
sage: SkewTableau([[None,2],[None],[4],[5]]).restriction_shape(2)
|
|
781
|
+
[2, 1] / [1, 1]
|
|
782
|
+
sage: T = SkewTableau([[None,None,3,5],[None,4,4],[17]])
|
|
783
|
+
sage: T.restriction_shape(0)
|
|
784
|
+
[2, 1] / [2, 1]
|
|
785
|
+
sage: T.restriction_shape(2)
|
|
786
|
+
[2, 1] / [2, 1]
|
|
787
|
+
sage: T.restriction_shape(3)
|
|
788
|
+
[3, 1] / [2, 1]
|
|
789
|
+
sage: T.restriction_shape(4)
|
|
790
|
+
[3, 3] / [2, 1]
|
|
791
|
+
"""
|
|
792
|
+
return SkewPartition([self.restriction_outer_shape(n), self.inner_shape()])
|
|
793
|
+
|
|
794
|
+
def to_chain(self, max_entry=None):
|
|
795
|
+
r"""
|
|
796
|
+
Return the chain of partitions corresponding to the (semi)standard
|
|
797
|
+
skew tableau ``self``.
|
|
798
|
+
|
|
799
|
+
The optional keyword parameter ``max_entry`` can be used to
|
|
800
|
+
customize the length of the chain. Specifically, if this parameter
|
|
801
|
+
is set to a nonnegative integer ``n``, then the chain is
|
|
802
|
+
constructed from the positions of the letters `1, 2, \ldots, n`
|
|
803
|
+
in the tableau.
|
|
804
|
+
|
|
805
|
+
EXAMPLES::
|
|
806
|
+
|
|
807
|
+
sage: SkewTableau([[None,1],[2],[3]]).to_chain()
|
|
808
|
+
[[1], [2], [2, 1], [2, 1, 1]]
|
|
809
|
+
sage: SkewTableau([[None,1],[1],[2]]).to_chain()
|
|
810
|
+
[[1], [2, 1], [2, 1, 1]]
|
|
811
|
+
sage: SkewTableau([[None,1],[1],[2]]).to_chain(max_entry=2)
|
|
812
|
+
[[1], [2, 1], [2, 1, 1]]
|
|
813
|
+
sage: SkewTableau([[None,1],[1],[2]]).to_chain(max_entry=3)
|
|
814
|
+
[[1], [2, 1], [2, 1, 1], [2, 1, 1]]
|
|
815
|
+
sage: SkewTableau([[None,1],[1],[2]]).to_chain(max_entry=1)
|
|
816
|
+
[[1], [2, 1]]
|
|
817
|
+
sage: SkewTableau([[None,None,2],[None,3],[None,5]]).to_chain(max_entry=6)
|
|
818
|
+
[[2, 1, 1], [2, 1, 1], [3, 1, 1], [3, 2, 1], [3, 2, 1], [3, 2, 2], [3, 2, 2]]
|
|
819
|
+
sage: SkewTableau([]).to_chain()
|
|
820
|
+
[[]]
|
|
821
|
+
sage: SkewTableau([]).to_chain(max_entry=1)
|
|
822
|
+
[[], []]
|
|
823
|
+
|
|
824
|
+
TESTS:
|
|
825
|
+
|
|
826
|
+
Check that :meth:`to_chain()` does not skip letters::
|
|
827
|
+
|
|
828
|
+
sage: t = SkewTableau([[None, 2, 3], [3]])
|
|
829
|
+
sage: t.to_chain()
|
|
830
|
+
[[1], [1], [2], [3, 1]]
|
|
831
|
+
|
|
832
|
+
sage: T = SkewTableau([[None]])
|
|
833
|
+
sage: T.to_chain()
|
|
834
|
+
[[1]]
|
|
835
|
+
"""
|
|
836
|
+
if max_entry is None:
|
|
837
|
+
if (not self) or all(c is None for row in self for c in row):
|
|
838
|
+
max_entry = 0
|
|
839
|
+
else:
|
|
840
|
+
max_entry = max(c for row in self for c in row if c is not None)
|
|
841
|
+
return [self.restriction_outer_shape(x) for x in range(max_entry + 1)]
|
|
842
|
+
|
|
843
|
+
def slide(self, corner=None, return_vacated=False):
|
|
844
|
+
"""
|
|
845
|
+
Apply a jeu de taquin slide to ``self`` on the specified inner
|
|
846
|
+
corner and return the resulting tableau.
|
|
847
|
+
|
|
848
|
+
If no corner is given, the topmost inner corner is chosen.
|
|
849
|
+
|
|
850
|
+
The optional parameter ``return_vacated=True`` causes
|
|
851
|
+
the output to be the pair ``(t, (i, j))`` where ``t`` is the new
|
|
852
|
+
tableau and ``(i, j)`` are the coordinates of the vacated square.
|
|
853
|
+
|
|
854
|
+
See [Ful1997]_ p12-13.
|
|
855
|
+
|
|
856
|
+
EXAMPLES::
|
|
857
|
+
|
|
858
|
+
sage: st = SkewTableau([[None, None, None, None, 2], [None, None, None, None, 6], [None, 2, 4, 4], [2, 3, 6], [5, 5]])
|
|
859
|
+
sage: st.slide((2, 0))
|
|
860
|
+
[[None, None, None, None, 2], [None, None, None, None, 6], [2, 2, 4, 4], [3, 5, 6], [5]]
|
|
861
|
+
sage: st2 = SkewTableau([[None, None, 3], [None, 2, 4], [1, 5]])
|
|
862
|
+
sage: st2.slide((1, 0), True)
|
|
863
|
+
([[None, None, 3], [1, 2, 4], [5]], (2, 1))
|
|
864
|
+
|
|
865
|
+
TESTS::
|
|
866
|
+
|
|
867
|
+
sage: st
|
|
868
|
+
[[None, None, None, None, 2], [None, None, None, None, 6],
|
|
869
|
+
[None, 2, 4, 4], [2, 3, 6], [5, 5]]
|
|
870
|
+
"""
|
|
871
|
+
new_st = self.to_list()
|
|
872
|
+
inner_corners = self.inner_shape().corners()
|
|
873
|
+
outer_corners = self.outer_shape().corners()
|
|
874
|
+
if corner is not None:
|
|
875
|
+
if tuple(corner) not in inner_corners:
|
|
876
|
+
raise ValueError("corner must be an inner corner")
|
|
877
|
+
else:
|
|
878
|
+
if not inner_corners:
|
|
879
|
+
return self
|
|
880
|
+
else:
|
|
881
|
+
corner = inner_corners[0]
|
|
882
|
+
|
|
883
|
+
spotl, spotc = corner
|
|
884
|
+
while (spotl, spotc) not in outer_corners:
|
|
885
|
+
# Check to see if there is nothing to the right
|
|
886
|
+
if spotc == len(new_st[spotl]) - 1:
|
|
887
|
+
# Swap the hole with the cell below
|
|
888
|
+
new_st[spotl][spotc] = new_st[spotl + 1][spotc]
|
|
889
|
+
new_st[spotl + 1][spotc] = None
|
|
890
|
+
spotl += 1
|
|
891
|
+
continue
|
|
892
|
+
|
|
893
|
+
# Check to see if there is nothing below
|
|
894
|
+
if spotl == len(new_st) - 1 or len(new_st[spotl + 1]) <= spotc:
|
|
895
|
+
# Swap the hole with the cell to the right
|
|
896
|
+
new_st[spotl][spotc] = new_st[spotl][spotc + 1]
|
|
897
|
+
new_st[spotl][spotc + 1] = None
|
|
898
|
+
spotc += 1
|
|
899
|
+
continue
|
|
900
|
+
|
|
901
|
+
# If we get to this stage, we need to compare
|
|
902
|
+
below = new_st[spotl + 1][spotc]
|
|
903
|
+
right = new_st[spotl][spotc + 1]
|
|
904
|
+
if below <= right:
|
|
905
|
+
# Swap with the cell below
|
|
906
|
+
new_st[spotl][spotc] = new_st[spotl + 1][spotc]
|
|
907
|
+
new_st[spotl + 1][spotc] = None
|
|
908
|
+
spotl += 1
|
|
909
|
+
continue
|
|
910
|
+
|
|
911
|
+
# Otherwise swap with the cell to the right
|
|
912
|
+
new_st[spotl][spotc] = new_st[spotl][spotc + 1]
|
|
913
|
+
new_st[spotl][spotc + 1] = None
|
|
914
|
+
spotc += 1
|
|
915
|
+
|
|
916
|
+
# Clean up to remove the "None" at an outside corner
|
|
917
|
+
# Remove the last row if there is nothing left in it
|
|
918
|
+
new_st[spotl].pop()
|
|
919
|
+
if not new_st[spotl]:
|
|
920
|
+
new_st.pop()
|
|
921
|
+
|
|
922
|
+
if return_vacated:
|
|
923
|
+
return (SkewTableau(new_st), (spotl, spotc))
|
|
924
|
+
return SkewTableau(new_st)
|
|
925
|
+
|
|
926
|
+
def backward_slide(self, corner=None):
|
|
927
|
+
r"""
|
|
928
|
+
Apply a backward jeu de taquin slide on the specified outside
|
|
929
|
+
``corner`` of ``self``.
|
|
930
|
+
|
|
931
|
+
Backward jeu de taquin slides are defined in Section 3.7 of
|
|
932
|
+
[Sag2001]_.
|
|
933
|
+
|
|
934
|
+
.. WARNING::
|
|
935
|
+
|
|
936
|
+
The :meth:`inner_corners` and :meth:`outer_corners` are the
|
|
937
|
+
:meth:`sage.combinat.partition.Partition.corners` of the inner and
|
|
938
|
+
outer partitions of the skew shape. They are different from the
|
|
939
|
+
inner/outer corners defined in [Sag2001]_.
|
|
940
|
+
|
|
941
|
+
The "inner corners" of [Sag2001]_ may be found by calling
|
|
942
|
+
:meth:`outer_corners`. The "outer corners" of [Sag2001]_ may be
|
|
943
|
+
found by calling ``self.outer_shape().outside_corners()``.
|
|
944
|
+
|
|
945
|
+
EXAMPLES::
|
|
946
|
+
|
|
947
|
+
sage: T = SkewTableaux()([[2, 2], [4, 4], [5]])
|
|
948
|
+
sage: Tableaux.options.display='array'
|
|
949
|
+
sage: Q = T.backward_slide(); Q
|
|
950
|
+
. 2 2
|
|
951
|
+
4 4
|
|
952
|
+
5
|
|
953
|
+
sage: Q.backward_slide((1, 2))
|
|
954
|
+
. 2 2
|
|
955
|
+
. 4 4
|
|
956
|
+
5
|
|
957
|
+
sage: Q.reverse_slide((1, 2)) == Q.backward_slide((1, 2))
|
|
958
|
+
True
|
|
959
|
+
|
|
960
|
+
sage: T = SkewTableaux()([[1, 3],[3],[5]]); T
|
|
961
|
+
1 3
|
|
962
|
+
3
|
|
963
|
+
5
|
|
964
|
+
sage: T.reverse_slide((1,1))
|
|
965
|
+
. 1
|
|
966
|
+
3 3
|
|
967
|
+
5
|
|
968
|
+
|
|
969
|
+
TESTS::
|
|
970
|
+
|
|
971
|
+
sage: T = SkewTableaux()([[2, 2], [4, 4], [5]])
|
|
972
|
+
sage: Q = T.backward_slide((0, 2))
|
|
973
|
+
sage: Q.backward_slide((2,1))
|
|
974
|
+
. 2 2
|
|
975
|
+
. 4
|
|
976
|
+
4 5
|
|
977
|
+
sage: Q.backward_slide((3,0))
|
|
978
|
+
. 2 2
|
|
979
|
+
. 4
|
|
980
|
+
4
|
|
981
|
+
5
|
|
982
|
+
sage: Q = T.backward_slide((2,1)); Q
|
|
983
|
+
. 2
|
|
984
|
+
2 4
|
|
985
|
+
4 5
|
|
986
|
+
sage: Q.backward_slide((3,0))
|
|
987
|
+
. 2
|
|
988
|
+
. 4
|
|
989
|
+
2 5
|
|
990
|
+
4
|
|
991
|
+
sage: Q = T.backward_slide((3,0)); Q
|
|
992
|
+
. 2
|
|
993
|
+
2 4
|
|
994
|
+
4
|
|
995
|
+
5
|
|
996
|
+
sage: Q.backward_slide((4,0))
|
|
997
|
+
. 2
|
|
998
|
+
. 4
|
|
999
|
+
2
|
|
1000
|
+
4
|
|
1001
|
+
5
|
|
1002
|
+
sage: Tableaux.options.display='list'
|
|
1003
|
+
"""
|
|
1004
|
+
new_st = self.to_list()
|
|
1005
|
+
inner_outside_corners = self.inner_shape().outside_corners()
|
|
1006
|
+
outer_outisde_corners = self.outer_shape().outside_corners()
|
|
1007
|
+
if corner is not None:
|
|
1008
|
+
if tuple(corner) not in outer_outisde_corners:
|
|
1009
|
+
raise ValueError("corner must be an outside corner"
|
|
1010
|
+
" of the outer shape")
|
|
1011
|
+
else:
|
|
1012
|
+
if not outer_outisde_corners:
|
|
1013
|
+
return self
|
|
1014
|
+
else:
|
|
1015
|
+
corner = outer_outisde_corners[0]
|
|
1016
|
+
|
|
1017
|
+
i, j = corner
|
|
1018
|
+
|
|
1019
|
+
# add the empty cell
|
|
1020
|
+
# the column only matters if it is zeroth column, in which
|
|
1021
|
+
# case we need to add a new row.
|
|
1022
|
+
if not j:
|
|
1023
|
+
new_st.append(list())
|
|
1024
|
+
new_st[i].append(None)
|
|
1025
|
+
|
|
1026
|
+
while (i, j) not in inner_outside_corners:
|
|
1027
|
+
# get the value of the cell above the temporarily empty cell (if
|
|
1028
|
+
# it exists)
|
|
1029
|
+
if i > 0:
|
|
1030
|
+
P_up = new_st[i-1][j]
|
|
1031
|
+
else:
|
|
1032
|
+
P_up = -1 # a dummy value less than all positive numbers
|
|
1033
|
+
|
|
1034
|
+
# get the value of the cell to the left of the temp. empty cell
|
|
1035
|
+
# (if it exists)
|
|
1036
|
+
if j > 0:
|
|
1037
|
+
P_left = new_st[i][j-1]
|
|
1038
|
+
else:
|
|
1039
|
+
P_left = -1 # a dummy value less than all positive numbers
|
|
1040
|
+
|
|
1041
|
+
# get the next cell
|
|
1042
|
+
# p_left will always be positive, but if P_left
|
|
1043
|
+
# and P_up are both None, then it will return
|
|
1044
|
+
# -1, which doesn't trigger the conditional
|
|
1045
|
+
if P_left > P_up:
|
|
1046
|
+
new_st[i][j] = P_left
|
|
1047
|
+
j = j - 1
|
|
1048
|
+
else: # if they are equal, we slide up
|
|
1049
|
+
new_st[i][j] = P_up
|
|
1050
|
+
i = i - 1
|
|
1051
|
+
# We don't need to reset the intermediate cells inside the loop
|
|
1052
|
+
# because the conditional above will continue to overwrite it until
|
|
1053
|
+
# the while loop terminates. We do need to reset it at the end.
|
|
1054
|
+
new_st[i][j] = None
|
|
1055
|
+
|
|
1056
|
+
return SkewTableaux()(new_st)
|
|
1057
|
+
|
|
1058
|
+
reverse_slide = backward_slide
|
|
1059
|
+
|
|
1060
|
+
def rectify(self, algorithm=None):
|
|
1061
|
+
"""
|
|
1062
|
+
Return a :class:`StandardTableau`, :class:`SemistandardTableau`,
|
|
1063
|
+
or just :class:`Tableau` formed by applying the jeu de taquin
|
|
1064
|
+
process to ``self``.
|
|
1065
|
+
|
|
1066
|
+
See page 15 of [Ful1997]_.
|
|
1067
|
+
|
|
1068
|
+
INPUT:
|
|
1069
|
+
|
|
1070
|
+
- ``algorithm`` -- (optional) if set to ``'jdt'``, rectifies by jeu de
|
|
1071
|
+
taquin; if set to ``'schensted'``, rectifies by Schensted insertion
|
|
1072
|
+
of the reading word. Otherwise, guesses which will be faster.
|
|
1073
|
+
|
|
1074
|
+
EXAMPLES::
|
|
1075
|
+
|
|
1076
|
+
sage: S = SkewTableau([[None,1],[2,3]])
|
|
1077
|
+
sage: S.rectify()
|
|
1078
|
+
[[1, 3], [2]]
|
|
1079
|
+
sage: T = SkewTableau([[None, None, None, 4],[None,None,1,6],[None,None,5],[2,3]])
|
|
1080
|
+
sage: T.rectify()
|
|
1081
|
+
[[1, 3, 4, 6], [2, 5]]
|
|
1082
|
+
sage: T.rectify(algorithm='jdt')
|
|
1083
|
+
[[1, 3, 4, 6], [2, 5]]
|
|
1084
|
+
sage: T.rectify(algorithm='schensted')
|
|
1085
|
+
[[1, 3, 4, 6], [2, 5]]
|
|
1086
|
+
sage: T.rectify(algorithm='spaghetti')
|
|
1087
|
+
Traceback (most recent call last):
|
|
1088
|
+
...
|
|
1089
|
+
ValueError: algorithm must be 'jdt', 'schensted', or None
|
|
1090
|
+
|
|
1091
|
+
TESTS::
|
|
1092
|
+
|
|
1093
|
+
sage: S
|
|
1094
|
+
[[None, 1], [2, 3]]
|
|
1095
|
+
sage: T
|
|
1096
|
+
[[None, None, None, 4], [None, None, 1, 6], [None, None, 5], [2, 3]]
|
|
1097
|
+
"""
|
|
1098
|
+
mu_size = self.inner_shape().size()
|
|
1099
|
+
|
|
1100
|
+
# Roughly, use jdt with a small inner shape, Schensted with a large one
|
|
1101
|
+
if algorithm is None:
|
|
1102
|
+
la = self.outer_shape()
|
|
1103
|
+
la_size = la.size()
|
|
1104
|
+
if mu_size ** 2 < len(la) * (la_size - mu_size):
|
|
1105
|
+
algorithm = 'jdt'
|
|
1106
|
+
else:
|
|
1107
|
+
algorithm = 'schensted'
|
|
1108
|
+
|
|
1109
|
+
if algorithm == 'jdt':
|
|
1110
|
+
rect = self
|
|
1111
|
+
for _ in range(mu_size):
|
|
1112
|
+
rect = rect.slide()
|
|
1113
|
+
elif algorithm == 'schensted':
|
|
1114
|
+
w = [x for row in reversed(self) for x in row
|
|
1115
|
+
if x is not None]
|
|
1116
|
+
rect = Tableau([]).insert_word(w)
|
|
1117
|
+
else:
|
|
1118
|
+
raise ValueError("algorithm must be 'jdt', 'schensted', or None")
|
|
1119
|
+
if self in StandardSkewTableaux():
|
|
1120
|
+
return StandardTableau(rect[:])
|
|
1121
|
+
if self in SemistandardSkewTableaux():
|
|
1122
|
+
return SemistandardTableau(rect[:])
|
|
1123
|
+
return Tableau(rect)
|
|
1124
|
+
|
|
1125
|
+
def add_entry(self, cell, m):
|
|
1126
|
+
"""
|
|
1127
|
+
Return the result of setting the entry in cell ``cell`` equal to ``m`` in the skew tableau ``self``.
|
|
1128
|
+
If the cell is already part of ``self``, it replaces the current entry.
|
|
1129
|
+
Otherwise, it attempts to add the cell to the skew tableau.
|
|
1130
|
+
|
|
1131
|
+
INPUT:
|
|
1132
|
+
|
|
1133
|
+
- ``cell`` -- a pair of nonnegative integers
|
|
1134
|
+
- ``m`` -- a nonnegative integer
|
|
1135
|
+
|
|
1136
|
+
OUTPUT:
|
|
1137
|
+
|
|
1138
|
+
The skew tableau ``self`` with entry in cell ``cell`` set to ``m``.
|
|
1139
|
+
This overwrites an existing entry if ``cell`` already belongs to ``self``,
|
|
1140
|
+
otherwise it adds the cell to the shape.
|
|
1141
|
+
|
|
1142
|
+
.. NOTE::
|
|
1143
|
+
|
|
1144
|
+
Both coordinates of ``cell`` are interpreted as starting at `0`.
|
|
1145
|
+
So, ``cell == (0, 0)`` corresponds to the northwesternmost cell
|
|
1146
|
+
|
|
1147
|
+
EXAMPLES::
|
|
1148
|
+
|
|
1149
|
+
sage: S = SkewTableau([[None, None,1],[1,2,5]]); S.pp()
|
|
1150
|
+
. . 1
|
|
1151
|
+
1 2 5
|
|
1152
|
+
sage: T = S.add_entry([0,1],1); T.pp()
|
|
1153
|
+
. 1 1
|
|
1154
|
+
1 2 5
|
|
1155
|
+
sage: U = T.add_entry([2,0],3); U.pp()
|
|
1156
|
+
. 1 1
|
|
1157
|
+
1 2 5
|
|
1158
|
+
3
|
|
1159
|
+
sage: U.add_entry([1,3],4)
|
|
1160
|
+
Traceback (most recent call last):
|
|
1161
|
+
...
|
|
1162
|
+
IndexError: (1, 3) is not an addable cell of the tableau
|
|
1163
|
+
sage: U.add_entry([0,3],4).pp()
|
|
1164
|
+
. 1 1 4
|
|
1165
|
+
1 2 5
|
|
1166
|
+
3
|
|
1167
|
+
|
|
1168
|
+
TESTS::
|
|
1169
|
+
|
|
1170
|
+
sage: S = SkewTableau([[None, None, 1]])
|
|
1171
|
+
sage: S.add_entry([0,0],1)
|
|
1172
|
+
Traceback (most recent call last):
|
|
1173
|
+
...
|
|
1174
|
+
TypeError: not a valid skew tableau
|
|
1175
|
+
sage: S.add_entry([0,1],1)
|
|
1176
|
+
[[None, 1, 1]]
|
|
1177
|
+
sage: S.add_entry([1,0],1)
|
|
1178
|
+
[[None, None, 1], [1]]
|
|
1179
|
+
sage: S.add_entry([1,1],1)
|
|
1180
|
+
[[None, None, 1], [None, 1]]
|
|
1181
|
+
sage: S.add_entry([1,2],1)
|
|
1182
|
+
[[None, None, 1], [None, None, 1]]
|
|
1183
|
+
sage: S.add_entry([2,0],1)
|
|
1184
|
+
[[None, None, 1], [None], [1]]
|
|
1185
|
+
sage: S.add_entry([2,1],1)
|
|
1186
|
+
[[None, None, 1], [None, None], [None, 1]]
|
|
1187
|
+
sage: S.add_entry([2,2],1)
|
|
1188
|
+
Traceback (most recent call last):
|
|
1189
|
+
...
|
|
1190
|
+
IndexError: (2, 2) is not an addable cell of the tableau
|
|
1191
|
+
sage: S.add_entry([2,3],1)
|
|
1192
|
+
Traceback (most recent call last):
|
|
1193
|
+
...
|
|
1194
|
+
IndexError: (2, 3) is not an addable cell of the tableau
|
|
1195
|
+
sage: S.add_entry([1000,1000], 3)
|
|
1196
|
+
Traceback (most recent call last):
|
|
1197
|
+
...
|
|
1198
|
+
IndexError: (1000, 1000) is not an addable cell of the tableau
|
|
1199
|
+
sage: S.add_entry([0,1000],3)
|
|
1200
|
+
Traceback (most recent call last):
|
|
1201
|
+
...
|
|
1202
|
+
IndexError: (0, 1000) is not an addable cell of the tableau
|
|
1203
|
+
|
|
1204
|
+
"""
|
|
1205
|
+
|
|
1206
|
+
tab = self.to_list()
|
|
1207
|
+
r, c = cell
|
|
1208
|
+
try:
|
|
1209
|
+
tab[r][c] = m
|
|
1210
|
+
except IndexError:
|
|
1211
|
+
if r > len(tab):
|
|
1212
|
+
if c < len(tab[-1]) and tab[-1][c] is None:
|
|
1213
|
+
tab += [[None]*(c+1) for i in range(r - len(tab))]
|
|
1214
|
+
tab.append([None]*(c) + [m])
|
|
1215
|
+
else:
|
|
1216
|
+
raise IndexError('%s is not an addable cell of the tableau' % ((r, c),))
|
|
1217
|
+
elif r == len(tab):
|
|
1218
|
+
# a cell in the row directly below tab is addable if and only if
|
|
1219
|
+
# c = 0 or the cell directly northwest is empty
|
|
1220
|
+
if c == 0:
|
|
1221
|
+
tab.append([m])
|
|
1222
|
+
elif c < len(tab[-1]) and tab[-1][c-1] is None:
|
|
1223
|
+
tab.append([None]*(c) + [m])
|
|
1224
|
+
else:
|
|
1225
|
+
raise IndexError('%s is not an addable cell of the tableau' % ((r, c),))
|
|
1226
|
+
else:
|
|
1227
|
+
tab_r = tab[r]
|
|
1228
|
+
if c == len(tab_r) and (r == 0 or len(tab_r) < len(tab[r-1])):
|
|
1229
|
+
tab_r.append(m)
|
|
1230
|
+
else:
|
|
1231
|
+
raise IndexError('%s is not an addable cell of the tableau' % ((r, c),))
|
|
1232
|
+
|
|
1233
|
+
# attempt to return a skew tableau of the same type as self
|
|
1234
|
+
if tab in self.parent():
|
|
1235
|
+
return self.parent()(tab)
|
|
1236
|
+
else:
|
|
1237
|
+
try:
|
|
1238
|
+
return self.parent().Element(tab)
|
|
1239
|
+
except ValueError:
|
|
1240
|
+
return SkewTableau(tab)
|
|
1241
|
+
|
|
1242
|
+
def anti_restrict(self, n):
|
|
1243
|
+
"""
|
|
1244
|
+
Return the skew tableau formed by removing all of the cells from
|
|
1245
|
+
``self`` that are filled with a number at most ``n``.
|
|
1246
|
+
|
|
1247
|
+
INPUT:
|
|
1248
|
+
|
|
1249
|
+
- ``n`` -- a nonnegative integer
|
|
1250
|
+
|
|
1251
|
+
OUTPUT:
|
|
1252
|
+
|
|
1253
|
+
The skew tableau ``self`` with all entries less than or equal to ``n`` removed.
|
|
1254
|
+
|
|
1255
|
+
EXAMPLES::
|
|
1256
|
+
|
|
1257
|
+
sage: S = SkewTableau([[None,1,2,3],[4,5,6]])
|
|
1258
|
+
sage: S.anti_restrict(2)
|
|
1259
|
+
[[None, None, None, 3], [4, 5, 6]]
|
|
1260
|
+
sage: S.anti_restrict(1).anti_restrict(2) == S.anti_restrict(2)
|
|
1261
|
+
True
|
|
1262
|
+
"""
|
|
1263
|
+
t_new = [[None if g <= n else g for g in row] for row in self]
|
|
1264
|
+
return SkewTableau(t_new)
|
|
1265
|
+
|
|
1266
|
+
def to_list(self):
|
|
1267
|
+
r"""
|
|
1268
|
+
Return a (mutable) list representation of ``self``.
|
|
1269
|
+
|
|
1270
|
+
EXAMPLES::
|
|
1271
|
+
|
|
1272
|
+
sage: stlist = [[None, None, 3], [None, 1, 3], [2, 2]]
|
|
1273
|
+
sage: st = SkewTableau(stlist)
|
|
1274
|
+
sage: st.to_list()
|
|
1275
|
+
[[None, None, 3], [None, 1, 3], [2, 2]]
|
|
1276
|
+
sage: st.to_list() == stlist
|
|
1277
|
+
True
|
|
1278
|
+
"""
|
|
1279
|
+
return [list(row) for row in self]
|
|
1280
|
+
|
|
1281
|
+
def row_stabilizer(self):
|
|
1282
|
+
"""
|
|
1283
|
+
Return the :func:`PermutationGroup` corresponding to the row stabilizer of
|
|
1284
|
+
``self``.
|
|
1285
|
+
|
|
1286
|
+
This assumes that every integer from `1` to the size of ``self``
|
|
1287
|
+
appears exactly once in ``self``.
|
|
1288
|
+
|
|
1289
|
+
EXAMPLES::
|
|
1290
|
+
|
|
1291
|
+
sage: # needs sage.groups
|
|
1292
|
+
sage: rs = SkewTableau([[None,1,2,3],[4,5]]).row_stabilizer()
|
|
1293
|
+
sage: rs.order() == factorial(3) * factorial(2)
|
|
1294
|
+
True
|
|
1295
|
+
sage: PermutationGroupElement([(1,3,2),(4,5)]) in rs
|
|
1296
|
+
True
|
|
1297
|
+
sage: PermutationGroupElement([(1,4)]) in rs
|
|
1298
|
+
False
|
|
1299
|
+
sage: rs = SkewTableau([[None,1,2],[3]]).row_stabilizer()
|
|
1300
|
+
sage: PermutationGroupElement([(1,2),(3,)]) in rs
|
|
1301
|
+
True
|
|
1302
|
+
sage: rs.one().domain()
|
|
1303
|
+
[1, 2, 3]
|
|
1304
|
+
sage: rs = SkewTableau([[None,None,1],[None,2],[3]]).row_stabilizer()
|
|
1305
|
+
sage: rs.order()
|
|
1306
|
+
1
|
|
1307
|
+
sage: rs = SkewTableau([[None,None,2,4,5],[1,3]]).row_stabilizer()
|
|
1308
|
+
sage: rs.order()
|
|
1309
|
+
12
|
|
1310
|
+
sage: rs = SkewTableau([]).row_stabilizer()
|
|
1311
|
+
sage: rs.order()
|
|
1312
|
+
1
|
|
1313
|
+
"""
|
|
1314
|
+
# Ensure that the permutations involve all elements of the
|
|
1315
|
+
# tableau, by including the identity permutation on the set [1..k].
|
|
1316
|
+
k = self.size()
|
|
1317
|
+
gens = [list(range(1, k + 1))]
|
|
1318
|
+
gens.extend((row[j], row[j + 1])
|
|
1319
|
+
for row in self
|
|
1320
|
+
for j in range(len(row) - 1)
|
|
1321
|
+
if row[j] is not None)
|
|
1322
|
+
return PermutationGroup(gens)
|
|
1323
|
+
|
|
1324
|
+
def column_stabilizer(self):
|
|
1325
|
+
"""
|
|
1326
|
+
Return the :func:`PermutationGroup` corresponding to the column stabilizer
|
|
1327
|
+
of ``self``.
|
|
1328
|
+
|
|
1329
|
+
This assumes that every integer from `1` to the size of ``self``
|
|
1330
|
+
appears exactly once in ``self``.
|
|
1331
|
+
|
|
1332
|
+
EXAMPLES::
|
|
1333
|
+
|
|
1334
|
+
sage: # needs sage.groups
|
|
1335
|
+
sage: cs = SkewTableau([[None,2,3],[1,5],[4]]).column_stabilizer()
|
|
1336
|
+
sage: cs.order() == factorial(2) * factorial(2)
|
|
1337
|
+
True
|
|
1338
|
+
sage: PermutationGroupElement([(1,3,2),(4,5)]) in cs
|
|
1339
|
+
False
|
|
1340
|
+
sage: PermutationGroupElement([(1,4)]) in cs
|
|
1341
|
+
True
|
|
1342
|
+
"""
|
|
1343
|
+
# Ensure that the permutations involve all elements of the
|
|
1344
|
+
# tableau, by including the identity permutation on the set [1..k].
|
|
1345
|
+
k = self.size()
|
|
1346
|
+
gens = [list(range(1, k + 1))]
|
|
1347
|
+
ell = len(self)
|
|
1348
|
+
while ell > 1:
|
|
1349
|
+
ell -= 1
|
|
1350
|
+
for i, val in enumerate(self[ell]):
|
|
1351
|
+
top_neighbor = self[ell-1][i]
|
|
1352
|
+
if top_neighbor is not None:
|
|
1353
|
+
gens.append((val, top_neighbor))
|
|
1354
|
+
return PermutationGroup(gens)
|
|
1355
|
+
|
|
1356
|
+
def shuffle(self, t2):
|
|
1357
|
+
r"""
|
|
1358
|
+
Shuffle the standard tableaux ``self`` and ``t2``.
|
|
1359
|
+
|
|
1360
|
+
Let ``t1 = self``. The shape of ``t2`` must extend the shape of
|
|
1361
|
+
``t1``, that is, ``self.outer_shape() == t2.inner_shape()``. Then
|
|
1362
|
+
this function computes the pair of tableaux ``(t2_new, t1_new)``
|
|
1363
|
+
obtained by using jeu de taquin slides to move the boxes of ``t2``
|
|
1364
|
+
behind the boxes of ``self``.
|
|
1365
|
+
|
|
1366
|
+
The entries of ``t2_new`` are obtained by performing successive
|
|
1367
|
+
inwards jeu de taquin slides on ``t2`` in the order indicated by
|
|
1368
|
+
the entries of ``t1``, from largest to smallest. The entries of
|
|
1369
|
+
``t1`` then slide outwards one by one and land in the squares
|
|
1370
|
+
vacated successively by ``t2``, forming ``t1_new``.
|
|
1371
|
+
|
|
1372
|
+
.. NOTE::
|
|
1373
|
+
|
|
1374
|
+
Equivalently, the entries of ``t1_new`` are obtained by performing
|
|
1375
|
+
outer jeu de taquin slides on ``t1`` in the order indicated by the
|
|
1376
|
+
entries of ``t2``, from smallest to largest. In this case the
|
|
1377
|
+
entries of ``t2`` slide backwards and fill the squares
|
|
1378
|
+
successively vacated by ``t1`` and so form ``t2_new``.
|
|
1379
|
+
(This is not how the algorithm is implemented.)
|
|
1380
|
+
|
|
1381
|
+
INPUT:
|
|
1382
|
+
|
|
1383
|
+
- ``self``, ``t2`` -- a pair of standard SkewTableaux with
|
|
1384
|
+
``self.outer_shape() == t2.inner_shape()``
|
|
1385
|
+
|
|
1386
|
+
OUTPUT:
|
|
1387
|
+
|
|
1388
|
+
- ``t2_new, t1_new`` -- a pair of standard :class:`SkewTableaux`
|
|
1389
|
+
with ``t2_new.outer_shape() == t1_new.inner_shape()``
|
|
1390
|
+
|
|
1391
|
+
EXAMPLES::
|
|
1392
|
+
|
|
1393
|
+
sage: t1 = SkewTableau([[None, 1, 2], [3, 4]])
|
|
1394
|
+
sage: t2 = SkewTableau([[None, None, None, 3], [None, None, 4], [1, 2, 5]])
|
|
1395
|
+
sage: (t2_new, t1_new) = t1.shuffle(t2)
|
|
1396
|
+
sage: t1_new
|
|
1397
|
+
[[None, None, None, 2], [None, None, 1], [None, 3, 4]]
|
|
1398
|
+
sage: t2_new
|
|
1399
|
+
[[None, 2, 3], [1, 4], [5]]
|
|
1400
|
+
sage: t1_new.outer_shape() == t2.outer_shape()
|
|
1401
|
+
True
|
|
1402
|
+
sage: t2_new.inner_shape() == t1.inner_shape()
|
|
1403
|
+
True
|
|
1404
|
+
|
|
1405
|
+
Shuffling is an involution::
|
|
1406
|
+
|
|
1407
|
+
sage: t1 = SkewTableau([[None, 1, 2], [3, 4]])
|
|
1408
|
+
sage: t2 = SkewTableau([[None, None, None, 3], [None, None, 4], [1, 2, 5]])
|
|
1409
|
+
sage: sh = lambda x,y : x.shuffle(y)
|
|
1410
|
+
sage: (t1, t2) == sh(*sh(t1, t2))
|
|
1411
|
+
True
|
|
1412
|
+
|
|
1413
|
+
Both tableaux must be standard::
|
|
1414
|
+
|
|
1415
|
+
sage: t1 = SkewTableau([[None, 1, 2], [2, 4]])
|
|
1416
|
+
sage: t2 = SkewTableau([[None, None, None, 3], [None, None, 4], [1, 2, 5]])
|
|
1417
|
+
sage: t1.shuffle(t2)
|
|
1418
|
+
Traceback (most recent call last):
|
|
1419
|
+
...
|
|
1420
|
+
ValueError: the tableaux must be standard
|
|
1421
|
+
sage: t1 = SkewTableau([[None, 1, 2], [3, 4]])
|
|
1422
|
+
sage: t2 = SkewTableau([[None, None, None, 3], [None, None, 4], [1, 2, 6]])
|
|
1423
|
+
sage: t1.shuffle(t2)
|
|
1424
|
+
Traceback (most recent call last):
|
|
1425
|
+
...
|
|
1426
|
+
ValueError: the tableaux must be standard
|
|
1427
|
+
|
|
1428
|
+
The shapes (not just the nonempty cells) must be adjacent::
|
|
1429
|
+
|
|
1430
|
+
sage: t1 = SkewTableau([[None, None, None], [1]])
|
|
1431
|
+
sage: t2 = SkewTableau([[None], [None], [1]])
|
|
1432
|
+
sage: t1.shuffle(t2)
|
|
1433
|
+
Traceback (most recent call last):
|
|
1434
|
+
...
|
|
1435
|
+
ValueError: the shapes must be adjacent
|
|
1436
|
+
|
|
1437
|
+
TESTS:
|
|
1438
|
+
|
|
1439
|
+
A corner case, where one tableau has no cells::
|
|
1440
|
+
|
|
1441
|
+
sage: t1 = SkewTableau([[None]])
|
|
1442
|
+
sage: t2 = SkewTableau([[None, 1, 2], [3, 4]])
|
|
1443
|
+
sage: (t2_new, t1_new) = t1.shuffle(t2)
|
|
1444
|
+
sage: t1_new
|
|
1445
|
+
[[None, None, None], [None, None]]
|
|
1446
|
+
sage: t2_new == t2
|
|
1447
|
+
True
|
|
1448
|
+
sage: t2_new.shuffle(t1_new) == (t1, t2)
|
|
1449
|
+
True
|
|
1450
|
+
"""
|
|
1451
|
+
if self.outer_shape() != t2.inner_shape():
|
|
1452
|
+
raise ValueError("the shapes must be adjacent")
|
|
1453
|
+
if not self.is_standard() or not t2.is_standard():
|
|
1454
|
+
raise ValueError("the tableaux must be standard")
|
|
1455
|
+
|
|
1456
|
+
# start with t2_new = t2, which we will slide backwards
|
|
1457
|
+
t2_new = t2
|
|
1458
|
+
|
|
1459
|
+
# make a blank copy of t2 (to fill in iteratively), which will become t1_new
|
|
1460
|
+
t1_new = [[None] * len(x) for x in list(t2)]
|
|
1461
|
+
|
|
1462
|
+
# perform reverse slides according to the entries of t1,
|
|
1463
|
+
# from largest to smallest
|
|
1464
|
+
m = self.size()
|
|
1465
|
+
for i in range(m, 0, -1):
|
|
1466
|
+
# the square of t1 containing i
|
|
1467
|
+
corner = self.cells_containing(i)[0]
|
|
1468
|
+
|
|
1469
|
+
# slide t2_new backwards, record i in the vacated square
|
|
1470
|
+
t2_new, (x, y) = t2_new.slide(corner, True)
|
|
1471
|
+
t1_new[x][y] = i
|
|
1472
|
+
|
|
1473
|
+
t1_new = SkewTableau(t1_new)
|
|
1474
|
+
return t2_new, t1_new
|
|
1475
|
+
|
|
1476
|
+
def standardization(self, check=True):
|
|
1477
|
+
r"""
|
|
1478
|
+
Return the standardization of ``self``, assuming ``self`` is a
|
|
1479
|
+
semistandard skew tableau.
|
|
1480
|
+
|
|
1481
|
+
The standardization of a semistandard skew tableau `T` is the standard
|
|
1482
|
+
skew tableau `\mathrm{st}(T)` of the same shape as `T` whose
|
|
1483
|
+
reversed reading word is the standardization of the reversed reading
|
|
1484
|
+
word of `T`.
|
|
1485
|
+
|
|
1486
|
+
The standardization of a word `w` can be formed by replacing all `1`'s
|
|
1487
|
+
in `w` by `1, 2, \ldots, k_1` from left to right, all `2`'s in `w` by
|
|
1488
|
+
`k_1 + 1, k_1 + 2, \ldots, k_2`, and repeating for all letters that
|
|
1489
|
+
appear in `w`.
|
|
1490
|
+
See also :meth:`Word.standard_permutation()`.
|
|
1491
|
+
|
|
1492
|
+
INPUT:
|
|
1493
|
+
|
|
1494
|
+
- ``check`` -- (default: ``True``) check to make sure ``self`` is
|
|
1495
|
+
semistandard; set to ``False`` to avoid this check
|
|
1496
|
+
|
|
1497
|
+
EXAMPLES::
|
|
1498
|
+
|
|
1499
|
+
sage: t = SkewTableau([[None,None,3,4,7,19],[None,4,4,8],[None,5,16,17],[None],[2],[3]])
|
|
1500
|
+
sage: t.standardization()
|
|
1501
|
+
[[None, None, 3, 6, 8, 12], [None, 4, 5, 9], [None, 7, 10, 11], [None], [1], [2]]
|
|
1502
|
+
|
|
1503
|
+
Standard skew tableaux are fixed under standardization::
|
|
1504
|
+
|
|
1505
|
+
sage: p = Partition([4,3,3,2])
|
|
1506
|
+
sage: q = Partitions(3).random_element() # needs sage.libs.flint
|
|
1507
|
+
sage: all(t == t.standardization() # needs sage.libs.flint
|
|
1508
|
+
....: for t in StandardSkewTableaux([p, q]))
|
|
1509
|
+
True
|
|
1510
|
+
|
|
1511
|
+
The reading word of the standardization is the
|
|
1512
|
+
standardization of the reading word::
|
|
1513
|
+
|
|
1514
|
+
sage: t = SkewTableau([[None,3,4,4],[None,6,10],[7,7,11],[18]])
|
|
1515
|
+
sage: t.to_word().standard_permutation() == t.standardization().to_permutation()
|
|
1516
|
+
True
|
|
1517
|
+
|
|
1518
|
+
TESTS:
|
|
1519
|
+
|
|
1520
|
+
Some corner cases::
|
|
1521
|
+
|
|
1522
|
+
sage: t = SkewTableau([[None,None],[None]])
|
|
1523
|
+
sage: t.standardization()
|
|
1524
|
+
[[None, None], [None]]
|
|
1525
|
+
sage: t = SkewTableau([])
|
|
1526
|
+
sage: t.standardization()
|
|
1527
|
+
[]
|
|
1528
|
+
"""
|
|
1529
|
+
if check and not self.is_semistandard():
|
|
1530
|
+
raise ValueError("the skew tableau must be semistandard")
|
|
1531
|
+
# This should be a SkewStandardTableau
|
|
1532
|
+
return StandardSkewTableaux().from_shape_and_word(self.shape(), self.to_word_by_row().standard_permutation())
|
|
1533
|
+
|
|
1534
|
+
def bender_knuth_involution(self, k, rows=None, check=True):
|
|
1535
|
+
r"""
|
|
1536
|
+
Return the image of ``self`` under the `k`-th Bender--Knuth
|
|
1537
|
+
involution, assuming ``self`` is a skew semistandard tableau.
|
|
1538
|
+
|
|
1539
|
+
Let `T` be a tableau, then a *lower free `k` in `T`* means a cell of
|
|
1540
|
+
`T` which is filled with the integer `k` and whose direct lower
|
|
1541
|
+
neighbor is not filled with the integer `k + 1` (in particular,
|
|
1542
|
+
this lower neighbor might not exist at all). Let an *upper free `k + 1`
|
|
1543
|
+
in `T`* mean a cell of `T` which is filled with the integer `k + 1`
|
|
1544
|
+
and whose direct upper neighbor is not filled with the integer `k`
|
|
1545
|
+
(in particular, this neighbor might not exist at all). It is clear
|
|
1546
|
+
that for any row `r` of `T`, the lower free `k`'s and the upper
|
|
1547
|
+
free `k + 1`'s in `r` together form a contiguous interval or `r`.
|
|
1548
|
+
|
|
1549
|
+
The *`k`-th Bender--Knuth switch at row `i`* changes the entries of
|
|
1550
|
+
the cells in this interval in such a way that if it used to have
|
|
1551
|
+
`a` entries of `k` and `b` entries of `k + 1`, it will now
|
|
1552
|
+
have `b` entries of `k` and `a` entries of `k + 1`. For fixed `k`, the
|
|
1553
|
+
`k`-th Bender--Knuth switches for different `i` commute. The
|
|
1554
|
+
composition of the `k`-th Bender--Knuth switches for all rows is
|
|
1555
|
+
called the *`k`-th Bender--Knuth involution*. This is used to show that
|
|
1556
|
+
the Schur functions defined by semistandard (skew) tableaux are
|
|
1557
|
+
symmetric functions.
|
|
1558
|
+
|
|
1559
|
+
INPUT:
|
|
1560
|
+
|
|
1561
|
+
- ``k`` -- integer
|
|
1562
|
+
|
|
1563
|
+
- ``rows`` -- (default: ``None``) when set to ``None``, the method
|
|
1564
|
+
computes the `k`-th Bender--Knuth involution as defined above.
|
|
1565
|
+
When an iterable, this computes the composition of the `k`-th
|
|
1566
|
+
Bender--Knuth switches at row `i` over all `i` in ``rows``. When set
|
|
1567
|
+
to an integer `i`, the method computes the `k`-th Bender--Knuth
|
|
1568
|
+
switch at row `i`. Note the indexing of the rows starts with `1`.
|
|
1569
|
+
|
|
1570
|
+
- ``check`` -- (default: ``True``) check to make sure ``self`` is
|
|
1571
|
+
semistandard; set to ``False`` to avoid this check
|
|
1572
|
+
|
|
1573
|
+
OUTPUT:
|
|
1574
|
+
|
|
1575
|
+
The image of ``self`` under either the `k`-th Bender--Knuth
|
|
1576
|
+
involution, the `k`-th Bender--Knuth switch at a certain row, or
|
|
1577
|
+
the composition of such switches, as detailed in the INPUT section.
|
|
1578
|
+
|
|
1579
|
+
EXAMPLES::
|
|
1580
|
+
|
|
1581
|
+
sage: t = SkewTableau([[None,None,None,4,4,5,6,7],[None,2,4,6,7,7,7],
|
|
1582
|
+
....: [None,4,5,8,8,9],[None,6,7,10],[None,8,8,11],[None],[4]])
|
|
1583
|
+
sage: t
|
|
1584
|
+
[[None, None, None, 4, 4, 5, 6, 7], [None, 2, 4, 6, 7, 7, 7],
|
|
1585
|
+
[None, 4, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]]
|
|
1586
|
+
sage: t.bender_knuth_involution(1)
|
|
1587
|
+
[[None, None, None, 4, 4, 5, 6, 7], [None, 1, 4, 6, 7, 7, 7],
|
|
1588
|
+
[None, 4, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]]
|
|
1589
|
+
sage: t.bender_knuth_involution(4)
|
|
1590
|
+
[[None, None, None, 4, 5, 5, 6, 7], [None, 2, 4, 6, 7, 7, 7],
|
|
1591
|
+
[None, 5, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [5]]
|
|
1592
|
+
sage: t.bender_knuth_involution(5)
|
|
1593
|
+
[[None, None, None, 4, 4, 5, 6, 7], [None, 2, 4, 5, 7, 7, 7],
|
|
1594
|
+
[None, 4, 6, 8, 8, 9], [None, 5, 7, 10], [None, 8, 8, 11], [None], [4]]
|
|
1595
|
+
sage: t.bender_knuth_involution(6)
|
|
1596
|
+
[[None, None, None, 4, 4, 5, 6, 6], [None, 2, 4, 6, 6, 7, 7],
|
|
1597
|
+
[None, 4, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]]
|
|
1598
|
+
sage: t.bender_knuth_involution(666) == t
|
|
1599
|
+
True
|
|
1600
|
+
sage: t.bender_knuth_involution(4, 2) == t
|
|
1601
|
+
True
|
|
1602
|
+
sage: t.bender_knuth_involution(4, 3)
|
|
1603
|
+
[[None, None, None, 4, 4, 5, 6, 7], [None, 2, 4, 6, 7, 7, 7],
|
|
1604
|
+
[None, 5, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]]
|
|
1605
|
+
|
|
1606
|
+
The Bender--Knuth involution is an involution::
|
|
1607
|
+
|
|
1608
|
+
sage: t = SkewTableau([[None,3,4,4],[None,6,10],[7,7,11],[18]])
|
|
1609
|
+
sage: all(t.bender_knuth_involution(k).bender_knuth_involution(k)
|
|
1610
|
+
....: == t for k in range(1,4))
|
|
1611
|
+
True
|
|
1612
|
+
|
|
1613
|
+
The same for the single switches::
|
|
1614
|
+
|
|
1615
|
+
sage: all(t.bender_knuth_involution(k, j).bender_knuth_involution(k, j)
|
|
1616
|
+
....: == t for k in range(1,5) for j in range(1, 5))
|
|
1617
|
+
True
|
|
1618
|
+
|
|
1619
|
+
Locality of the Bender--Knuth involutions::
|
|
1620
|
+
|
|
1621
|
+
sage: all(t.bender_knuth_involution(k).bender_knuth_involution(l)
|
|
1622
|
+
....: == t.bender_knuth_involution(l).bender_knuth_involution(k)
|
|
1623
|
+
....: for k in range(1,5) for l in range(1,5) if abs(k - l) > 1)
|
|
1624
|
+
True
|
|
1625
|
+
|
|
1626
|
+
TESTS::
|
|
1627
|
+
|
|
1628
|
+
sage: t = SkewTableau([])
|
|
1629
|
+
sage: t.bender_knuth_involution(3)
|
|
1630
|
+
[]
|
|
1631
|
+
sage: t = SkewTableau([[None,None],[None]])
|
|
1632
|
+
sage: t.bender_knuth_involution(3)
|
|
1633
|
+
[[None, None], [None]]
|
|
1634
|
+
|
|
1635
|
+
The `(s_1 s_2)^6 = id` identity that holds for Bender--Knuth
|
|
1636
|
+
involutions on straight shapes does not generally hold for
|
|
1637
|
+
skew shapes::
|
|
1638
|
+
|
|
1639
|
+
sage: p = lambda t, k: t.bender_knuth_involution(k).bender_knuth_involution(k + 1)
|
|
1640
|
+
sage: t = SkewTableau([[None,1,2],[2,3]])
|
|
1641
|
+
sage: x = t
|
|
1642
|
+
sage: for i in range(6): x = p(x, 1)
|
|
1643
|
+
sage: x
|
|
1644
|
+
[[None, 2, 2], [1, 3]]
|
|
1645
|
+
sage: x == t
|
|
1646
|
+
False
|
|
1647
|
+
|
|
1648
|
+
AUTHORS:
|
|
1649
|
+
|
|
1650
|
+
- Darij Grinberg (2013-05-14)
|
|
1651
|
+
"""
|
|
1652
|
+
if check and not self.is_semistandard():
|
|
1653
|
+
raise ValueError("the skew tableau must be semistandard")
|
|
1654
|
+
l = len(self) # l is the number of rows of self.
|
|
1655
|
+
# Sanitizing the rows input so that it always becomes a list of
|
|
1656
|
+
# nonnegative integers. We also subtract 1 from these integers
|
|
1657
|
+
# because the i-th row of a tableau T is T[i - 1].
|
|
1658
|
+
if rows is None:
|
|
1659
|
+
rows = list(range(l))
|
|
1660
|
+
elif rows in ZZ:
|
|
1661
|
+
rows = [rows - 1]
|
|
1662
|
+
else:
|
|
1663
|
+
rows = [i - 1 for i in rows]
|
|
1664
|
+
# Now, rows should be iterable.
|
|
1665
|
+
|
|
1666
|
+
# result_tab is going to be the result tableau (as a list of lists);
|
|
1667
|
+
# we will build it up step by step, starting with a deep copy of self.
|
|
1668
|
+
result_tab = self.to_list()
|
|
1669
|
+
for i in rows:
|
|
1670
|
+
if i >= l:
|
|
1671
|
+
continue
|
|
1672
|
+
# Setup the previous and next rows
|
|
1673
|
+
if i == 0:
|
|
1674
|
+
prev_row = [None] * len(result_tab[i])
|
|
1675
|
+
else:
|
|
1676
|
+
prev_row = result_tab[i - 1]
|
|
1677
|
+
if i == l - 1:
|
|
1678
|
+
next_row = [None] * len(result_tab[i])
|
|
1679
|
+
else:
|
|
1680
|
+
next_row = result_tab[i + 1] + [None] * (len(result_tab[i]) - len(result_tab[i + 1]))
|
|
1681
|
+
a = 0
|
|
1682
|
+
b = 0
|
|
1683
|
+
sk = None # The first entry of k
|
|
1684
|
+
sk1 = None # The first entry of k+1
|
|
1685
|
+
for j, val in enumerate(result_tab[i]):
|
|
1686
|
+
if val == k and next_row[j] != k + 1:
|
|
1687
|
+
if sk is None:
|
|
1688
|
+
sk = j
|
|
1689
|
+
a += 1
|
|
1690
|
+
elif val == k + 1 and prev_row[j] != k:
|
|
1691
|
+
if sk1 is None:
|
|
1692
|
+
sk1 = j
|
|
1693
|
+
b += 1
|
|
1694
|
+
if sk1 is not None:
|
|
1695
|
+
if a > b:
|
|
1696
|
+
for j in range(sk1 - (a - b), sk1):
|
|
1697
|
+
result_tab[i][j] = k + 1
|
|
1698
|
+
elif a < b:
|
|
1699
|
+
for j in range(sk1, sk1 + b - a):
|
|
1700
|
+
result_tab[i][j] = k
|
|
1701
|
+
elif sk is not None:
|
|
1702
|
+
for j in range(sk, sk + a):
|
|
1703
|
+
result_tab[i][j] = k + 1
|
|
1704
|
+
|
|
1705
|
+
return SkewTableau(result_tab) # This should be a SkewSemistandardTableau
|
|
1706
|
+
|
|
1707
|
+
def to_expr(self):
|
|
1708
|
+
"""
|
|
1709
|
+
The first list in a result corresponds to the inner partition of
|
|
1710
|
+
the skew shape. The second list is a list of the rows in the skew
|
|
1711
|
+
tableau read from the bottom up.
|
|
1712
|
+
|
|
1713
|
+
Provided for compatibility with MuPAD-Combinat. In MuPAD-Combinat,
|
|
1714
|
+
if ``t`` is a skew tableau, then to_expr gives the same result as
|
|
1715
|
+
``expr(t)`` would give in MuPAD-Combinat.
|
|
1716
|
+
|
|
1717
|
+
EXAMPLES::
|
|
1718
|
+
|
|
1719
|
+
sage: SkewTableau([[None,1,1,3],[None,2,2],[1]]).to_expr()
|
|
1720
|
+
[[1, 1], [[1], [2, 2], [1, 1, 3]]]
|
|
1721
|
+
sage: SkewTableau([]).to_expr()
|
|
1722
|
+
[[], []]
|
|
1723
|
+
"""
|
|
1724
|
+
rows = self.filling()
|
|
1725
|
+
rows.reverse()
|
|
1726
|
+
return [self.inner_shape(), rows]
|
|
1727
|
+
|
|
1728
|
+
def is_ribbon(self) -> bool:
|
|
1729
|
+
r"""
|
|
1730
|
+
Return ``True`` if and only if the shape of ``self`` is a
|
|
1731
|
+
ribbon.
|
|
1732
|
+
|
|
1733
|
+
This means that it has exactly one cell in each of `q`
|
|
1734
|
+
consecutive diagonals for some nonnegative integer `q`.
|
|
1735
|
+
|
|
1736
|
+
EXAMPLES::
|
|
1737
|
+
|
|
1738
|
+
sage: S = SkewTableau([[None, None, 1, 2],[None, None, 3],[1, 3, 4]])
|
|
1739
|
+
sage: S.pp()
|
|
1740
|
+
. . 1 2
|
|
1741
|
+
. . 3
|
|
1742
|
+
1 3 4
|
|
1743
|
+
sage: S.is_ribbon()
|
|
1744
|
+
True
|
|
1745
|
+
|
|
1746
|
+
sage: S = SkewTableau([[None, 1, 1, 2],[None, 2, 3],[1, 3, 4]])
|
|
1747
|
+
sage: S.pp()
|
|
1748
|
+
. 1 1 2
|
|
1749
|
+
. 2 3
|
|
1750
|
+
1 3 4
|
|
1751
|
+
sage: S.is_ribbon()
|
|
1752
|
+
False
|
|
1753
|
+
|
|
1754
|
+
sage: S = SkewTableau([[None, None, 1, 2],[None, None, 3],[1]])
|
|
1755
|
+
sage: S.pp()
|
|
1756
|
+
. . 1 2
|
|
1757
|
+
. . 3
|
|
1758
|
+
1
|
|
1759
|
+
sage: S.is_ribbon()
|
|
1760
|
+
False
|
|
1761
|
+
|
|
1762
|
+
sage: S = SkewTableau([[None, None, None, None],[None, None, 3],[1, 2, 4]])
|
|
1763
|
+
sage: S.pp()
|
|
1764
|
+
. . . .
|
|
1765
|
+
. . 3
|
|
1766
|
+
1 2 4
|
|
1767
|
+
sage: S.is_ribbon()
|
|
1768
|
+
True
|
|
1769
|
+
|
|
1770
|
+
sage: S = SkewTableau([[None, None, None, None],[None, None, 3],[None, 2, 4]])
|
|
1771
|
+
sage: S.pp()
|
|
1772
|
+
. . . .
|
|
1773
|
+
. . 3
|
|
1774
|
+
. 2 4
|
|
1775
|
+
sage: S.is_ribbon()
|
|
1776
|
+
True
|
|
1777
|
+
|
|
1778
|
+
sage: S = SkewTableau([[None, None],[None]])
|
|
1779
|
+
sage: S.pp()
|
|
1780
|
+
. .
|
|
1781
|
+
.
|
|
1782
|
+
sage: S.is_ribbon()
|
|
1783
|
+
True
|
|
1784
|
+
"""
|
|
1785
|
+
lam = list(self.outer_shape())
|
|
1786
|
+
mu = list(self.inner_shape())
|
|
1787
|
+
l_out = len(lam)
|
|
1788
|
+
l_in = len(mu)
|
|
1789
|
+
mu += [0] * (l_out - l_in)
|
|
1790
|
+
|
|
1791
|
+
if l_out == 0:
|
|
1792
|
+
return True
|
|
1793
|
+
|
|
1794
|
+
# Find the least u for which lam[u]>mu[u], if it exists.
|
|
1795
|
+
# If it does not exist then u will equal l_out.
|
|
1796
|
+
u = 0
|
|
1797
|
+
u_test = True
|
|
1798
|
+
while u_test:
|
|
1799
|
+
if u >= l_out or lam[u] > mu[u]:
|
|
1800
|
+
u_test = False
|
|
1801
|
+
else:
|
|
1802
|
+
u += 1
|
|
1803
|
+
|
|
1804
|
+
# Find the least v strictly greater than u for which
|
|
1805
|
+
# lam[v] != mu[v-1]+1
|
|
1806
|
+
v = u + 1
|
|
1807
|
+
v_test = True
|
|
1808
|
+
while v_test:
|
|
1809
|
+
if v >= l_out or lam[v] != mu[v - 1] + 1:
|
|
1810
|
+
v_test = False
|
|
1811
|
+
else:
|
|
1812
|
+
v += 1
|
|
1813
|
+
|
|
1814
|
+
# Check if lam[i]==mu[i] for all i >= v
|
|
1815
|
+
for i in range(v, l_out):
|
|
1816
|
+
if lam[i] != mu[i]:
|
|
1817
|
+
return False
|
|
1818
|
+
|
|
1819
|
+
return True
|
|
1820
|
+
|
|
1821
|
+
def to_ribbon(self, check_input=True):
|
|
1822
|
+
"""
|
|
1823
|
+
Return ``self`` as a ribbon-shaped tableau
|
|
1824
|
+
(:class:`~sage.combinat.ribbon_shaped_tableau.RibbonShapedTableau`),
|
|
1825
|
+
provided that the shape of ``self`` is a ribbon.
|
|
1826
|
+
|
|
1827
|
+
INPUT:
|
|
1828
|
+
|
|
1829
|
+
- ``check_input`` -- boolean (default: ``True``); whether or not to
|
|
1830
|
+
check that ``self`` indeed has ribbon shape
|
|
1831
|
+
|
|
1832
|
+
EXAMPLES::
|
|
1833
|
+
|
|
1834
|
+
sage: SkewTableau([[None,1],[2,3]]).to_ribbon()
|
|
1835
|
+
[[None, 1], [2, 3]]
|
|
1836
|
+
"""
|
|
1837
|
+
if check_input and not self.is_ribbon():
|
|
1838
|
+
raise ValueError("self must be a ribbon")
|
|
1839
|
+
from sage.combinat.ribbon_shaped_tableau import RibbonShapedTableau
|
|
1840
|
+
r = [[i for i in row if i is not None] for row in self]
|
|
1841
|
+
return RibbonShapedTableau(r)
|
|
1842
|
+
|
|
1843
|
+
def filling(self):
|
|
1844
|
+
"""
|
|
1845
|
+
Return a list of the non-empty entries in ``self``.
|
|
1846
|
+
|
|
1847
|
+
EXAMPLES::
|
|
1848
|
+
|
|
1849
|
+
sage: t = SkewTableau([[None,1],[2,3]])
|
|
1850
|
+
sage: t.filling()
|
|
1851
|
+
[[1], [2, 3]]
|
|
1852
|
+
"""
|
|
1853
|
+
return [[i for i in row if i is not None] for row in self]
|
|
1854
|
+
|
|
1855
|
+
def cells_by_content(self, c):
|
|
1856
|
+
"""
|
|
1857
|
+
Return the coordinates of the cells in ``self`` with content ``c``.
|
|
1858
|
+
|
|
1859
|
+
EXAMPLES::
|
|
1860
|
+
|
|
1861
|
+
sage: s = SkewTableau([[None,1,2],[3,4,5],[6]])
|
|
1862
|
+
sage: s.cells_by_content(0)
|
|
1863
|
+
[(1, 1)]
|
|
1864
|
+
sage: s.cells_by_content(1)
|
|
1865
|
+
[(0, 1), (1, 2)]
|
|
1866
|
+
sage: s.cells_by_content(2)
|
|
1867
|
+
[(0, 2)]
|
|
1868
|
+
sage: s.cells_by_content(-1)
|
|
1869
|
+
[(1, 0)]
|
|
1870
|
+
sage: s.cells_by_content(-2)
|
|
1871
|
+
[(2, 0)]
|
|
1872
|
+
"""
|
|
1873
|
+
if not self:
|
|
1874
|
+
return []
|
|
1875
|
+
|
|
1876
|
+
if c >= 0:
|
|
1877
|
+
if c >= len(self[0]):
|
|
1878
|
+
return []
|
|
1879
|
+
i, j = 0, c
|
|
1880
|
+
else:
|
|
1881
|
+
c = -c
|
|
1882
|
+
if c >= len(self):
|
|
1883
|
+
return []
|
|
1884
|
+
i, j = c, 0
|
|
1885
|
+
|
|
1886
|
+
res = []
|
|
1887
|
+
while True:
|
|
1888
|
+
if self[i][j] is not None:
|
|
1889
|
+
res.append((i, j))
|
|
1890
|
+
i, j = i + 1, j + 1
|
|
1891
|
+
if i >= len(self) or j >= len(self[i]):
|
|
1892
|
+
break
|
|
1893
|
+
return res
|
|
1894
|
+
|
|
1895
|
+
def entries_by_content(self, c):
|
|
1896
|
+
"""
|
|
1897
|
+
Return the entries in ``self`` with content ``c``.
|
|
1898
|
+
|
|
1899
|
+
EXAMPLES::
|
|
1900
|
+
|
|
1901
|
+
sage: s = SkewTableau([[None,1,2],[3,4,5],[6]])
|
|
1902
|
+
sage: s.entries_by_content(0)
|
|
1903
|
+
[4]
|
|
1904
|
+
sage: s.entries_by_content(1)
|
|
1905
|
+
[1, 5]
|
|
1906
|
+
sage: s.entries_by_content(2)
|
|
1907
|
+
[2]
|
|
1908
|
+
sage: s.entries_by_content(-1)
|
|
1909
|
+
[3]
|
|
1910
|
+
sage: s.entries_by_content(-2)
|
|
1911
|
+
[6]
|
|
1912
|
+
"""
|
|
1913
|
+
return [self[i][j] for i, j in self.cells_by_content(c)]
|
|
1914
|
+
|
|
1915
|
+
def cells(self):
|
|
1916
|
+
"""
|
|
1917
|
+
Return the cells in ``self``.
|
|
1918
|
+
|
|
1919
|
+
EXAMPLES::
|
|
1920
|
+
|
|
1921
|
+
sage: s = SkewTableau([[None,1,2],[3],[6]])
|
|
1922
|
+
sage: s.cells()
|
|
1923
|
+
[(0, 1), (0, 2), (1, 0), (2, 0)]
|
|
1924
|
+
"""
|
|
1925
|
+
return [(i, j)
|
|
1926
|
+
for i, selfi in enumerate(self)
|
|
1927
|
+
for j in range(len(selfi))
|
|
1928
|
+
if selfi[j] is not None]
|
|
1929
|
+
|
|
1930
|
+
def cells_containing(self, i):
|
|
1931
|
+
r"""
|
|
1932
|
+
Return the list of cells in which the letter ``i`` appears in the
|
|
1933
|
+
tableau ``self``. The list is ordered with cells appearing from
|
|
1934
|
+
left to right.
|
|
1935
|
+
|
|
1936
|
+
Cells are given as pairs of coordinates `(a, b)`, where both
|
|
1937
|
+
rows and columns are counted from `0` (so `a = 0` means the cell
|
|
1938
|
+
lies in the leftmost column of the tableau, etc.).
|
|
1939
|
+
|
|
1940
|
+
EXAMPLES::
|
|
1941
|
+
|
|
1942
|
+
sage: t = SkewTableau([[None,None,3],[None,3,5],[4,5]])
|
|
1943
|
+
sage: t.cells_containing(5)
|
|
1944
|
+
[(2, 1), (1, 2)]
|
|
1945
|
+
sage: t.cells_containing(4)
|
|
1946
|
+
[(2, 0)]
|
|
1947
|
+
sage: t.cells_containing(2)
|
|
1948
|
+
[]
|
|
1949
|
+
|
|
1950
|
+
sage: t = SkewTableau([[None,None,None,None],[None,4,5],[None,5,6],[None,9],[None]])
|
|
1951
|
+
sage: t.cells_containing(2)
|
|
1952
|
+
[]
|
|
1953
|
+
sage: t.cells_containing(4)
|
|
1954
|
+
[(1, 1)]
|
|
1955
|
+
sage: t.cells_containing(5)
|
|
1956
|
+
[(2, 1), (1, 2)]
|
|
1957
|
+
|
|
1958
|
+
sage: SkewTableau([]).cells_containing(3)
|
|
1959
|
+
[]
|
|
1960
|
+
|
|
1961
|
+
sage: SkewTableau([[None,None],[None]]).cells_containing(3)
|
|
1962
|
+
[]
|
|
1963
|
+
"""
|
|
1964
|
+
cell_list = []
|
|
1965
|
+
for r in range(len(self) - 1, -1, -1):
|
|
1966
|
+
rth_row = self[r]
|
|
1967
|
+
for c, val in enumerate(rth_row):
|
|
1968
|
+
if val == i:
|
|
1969
|
+
cell_list.append((r, c))
|
|
1970
|
+
return cell_list
|
|
1971
|
+
|
|
1972
|
+
def is_k_tableau(self, k) -> bool:
|
|
1973
|
+
r"""
|
|
1974
|
+
Check whether ``self`` is a valid skew weak `k`-tableau.
|
|
1975
|
+
|
|
1976
|
+
EXAMPLES::
|
|
1977
|
+
|
|
1978
|
+
sage: t = SkewTableau([[None,2,3],[2,3],[3]])
|
|
1979
|
+
sage: t.is_k_tableau(3)
|
|
1980
|
+
True
|
|
1981
|
+
sage: t = SkewTableau([[None,1,3],[2,2],[3]])
|
|
1982
|
+
sage: t.is_k_tableau(3)
|
|
1983
|
+
False
|
|
1984
|
+
"""
|
|
1985
|
+
shapes = self.to_chain()
|
|
1986
|
+
kshapes = [la.k_conjugate(k) for la in shapes]
|
|
1987
|
+
return all(kshapes[i + 1].contains(kshapes[i])
|
|
1988
|
+
for i in range(len(shapes) - 1))
|
|
1989
|
+
|
|
1990
|
+
|
|
1991
|
+
def _label_skew(list_of_cells, sk):
|
|
1992
|
+
"""
|
|
1993
|
+
Return a filled-in standard skew tableau given an
|
|
1994
|
+
ordered list ``list_of_cells`` of the coordinates to fill in
|
|
1995
|
+
(as pairs) and an empty shape ``sk``.
|
|
1996
|
+
|
|
1997
|
+
EXAMPLES::
|
|
1998
|
+
|
|
1999
|
+
sage: import sage.combinat.skew_tableau as skew_tableau
|
|
2000
|
+
sage: l = [(0, 0), (1, 1), (1, 0), (0, 1)]
|
|
2001
|
+
sage: empty = [[None,None],[None,None]]
|
|
2002
|
+
sage: skew_tableau._label_skew(l, empty)
|
|
2003
|
+
[[1, 4], [3, 2]]
|
|
2004
|
+
"""
|
|
2005
|
+
skew = [list(row) for row in sk]
|
|
2006
|
+
for i, (row, column) in enumerate(list_of_cells, start=1):
|
|
2007
|
+
skew[row][column] = i
|
|
2008
|
+
return skew
|
|
2009
|
+
|
|
2010
|
+
|
|
2011
|
+
class SkewTableaux(UniqueRepresentation, Parent):
|
|
2012
|
+
r"""
|
|
2013
|
+
Class of all skew tableaux.
|
|
2014
|
+
"""
|
|
2015
|
+
|
|
2016
|
+
def __init__(self, category=None):
|
|
2017
|
+
"""
|
|
2018
|
+
Initialize ``self``.
|
|
2019
|
+
|
|
2020
|
+
EXAMPLES::
|
|
2021
|
+
|
|
2022
|
+
sage: S = SkewTableaux()
|
|
2023
|
+
sage: TestSuite(S).run()
|
|
2024
|
+
"""
|
|
2025
|
+
if category is None:
|
|
2026
|
+
Parent.__init__(self, category=Sets())
|
|
2027
|
+
else:
|
|
2028
|
+
Parent.__init__(self, category=category)
|
|
2029
|
+
|
|
2030
|
+
def _repr_(self):
|
|
2031
|
+
"""
|
|
2032
|
+
Return a string representation of ``self``.
|
|
2033
|
+
|
|
2034
|
+
EXAMPLES::
|
|
2035
|
+
|
|
2036
|
+
sage: SkewTableaux()
|
|
2037
|
+
Skew tableaux
|
|
2038
|
+
"""
|
|
2039
|
+
return "Skew tableaux"
|
|
2040
|
+
|
|
2041
|
+
def _element_constructor_(self, st):
|
|
2042
|
+
"""
|
|
2043
|
+
Construct an element of ``self``.
|
|
2044
|
+
|
|
2045
|
+
EXAMPLES::
|
|
2046
|
+
|
|
2047
|
+
sage: S = SkewTableaux()
|
|
2048
|
+
sage: elt = S([[None,1],[2,3]]); elt
|
|
2049
|
+
[[None, 1], [2, 3]]
|
|
2050
|
+
sage: elt.parent() is S
|
|
2051
|
+
True
|
|
2052
|
+
"""
|
|
2053
|
+
return self.element_class(self, st)
|
|
2054
|
+
|
|
2055
|
+
Element = SkewTableau
|
|
2056
|
+
options = Tableaux.options
|
|
2057
|
+
|
|
2058
|
+
def __contains__(self, x):
|
|
2059
|
+
"""
|
|
2060
|
+
Check if ``x`` is a skew tableau.
|
|
2061
|
+
|
|
2062
|
+
EXAMPLES::
|
|
2063
|
+
|
|
2064
|
+
sage: T = SkewTableau([[None, None, 1], [3], [4]])
|
|
2065
|
+
sage: T in SkewTableaux()
|
|
2066
|
+
True
|
|
2067
|
+
sage: [[None,1],[2,3]] in SkewTableaux()
|
|
2068
|
+
True
|
|
2069
|
+
"""
|
|
2070
|
+
if isinstance(x, SkewTableau):
|
|
2071
|
+
return True
|
|
2072
|
+
try:
|
|
2073
|
+
self.element_class(self, x)
|
|
2074
|
+
except Exception:
|
|
2075
|
+
return False
|
|
2076
|
+
return True
|
|
2077
|
+
|
|
2078
|
+
def from_expr(self, expr):
|
|
2079
|
+
"""
|
|
2080
|
+
Return a :class:`SkewTableau` from a MuPAD-Combinat expr for
|
|
2081
|
+
a skew tableau.
|
|
2082
|
+
|
|
2083
|
+
The first list in ``expr`` is the inner shape of the skew
|
|
2084
|
+
tableau. The second list are the entries in the rows of the skew
|
|
2085
|
+
tableau from bottom to top.
|
|
2086
|
+
|
|
2087
|
+
Provided primarily for compatibility with MuPAD-Combinat.
|
|
2088
|
+
|
|
2089
|
+
EXAMPLES::
|
|
2090
|
+
|
|
2091
|
+
sage: SkewTableaux().from_expr([[1,1],[[5],[3,4],[1,2]]])
|
|
2092
|
+
[[None, 1, 2], [None, 3, 4], [5]]
|
|
2093
|
+
"""
|
|
2094
|
+
outer = expr[1]
|
|
2095
|
+
inner = expr[0] + [0] * (len(outer) - len(expr[0]))
|
|
2096
|
+
|
|
2097
|
+
skp = [[None] * (inner[i]) + outer[-(i + 1)]
|
|
2098
|
+
for i in range(len(outer))]
|
|
2099
|
+
|
|
2100
|
+
return self.element_class(self, skp)
|
|
2101
|
+
|
|
2102
|
+
def from_chain(self, chain):
|
|
2103
|
+
"""
|
|
2104
|
+
Return the tableau corresponding to the chain of partitions.
|
|
2105
|
+
|
|
2106
|
+
EXAMPLES::
|
|
2107
|
+
|
|
2108
|
+
sage: SkewTableaux().from_chain([[1,1],[2,1],[3,1],[3,2],[3,3],[3,3,1]])
|
|
2109
|
+
[[None, 1, 2], [None, 3, 4], [5]]
|
|
2110
|
+
"""
|
|
2111
|
+
shape = chain[-1]
|
|
2112
|
+
T = [[None]*r for r in shape]
|
|
2113
|
+
for i in range(1, len(chain)):
|
|
2114
|
+
la = chain[i]
|
|
2115
|
+
mu = chain[i - 1]
|
|
2116
|
+
mu += [0] * (len(la) - len(mu))
|
|
2117
|
+
|
|
2118
|
+
for r in range(len(la)):
|
|
2119
|
+
for c in range(mu[r], la[r]):
|
|
2120
|
+
T[r][c] = i
|
|
2121
|
+
|
|
2122
|
+
return self.element_class(self, T)
|
|
2123
|
+
|
|
2124
|
+
def from_shape_and_word(self, shape, word):
|
|
2125
|
+
"""
|
|
2126
|
+
Return the skew tableau corresponding to the skew partition ``shape``
|
|
2127
|
+
and the word ``word`` obtained from the row reading.
|
|
2128
|
+
|
|
2129
|
+
EXAMPLES::
|
|
2130
|
+
|
|
2131
|
+
sage: t = SkewTableau([[None, 1, 3], [None, 2], [4]])
|
|
2132
|
+
sage: shape = t.shape()
|
|
2133
|
+
sage: word = t.to_word()
|
|
2134
|
+
sage: SkewTableaux().from_shape_and_word(shape, word)
|
|
2135
|
+
[[None, 1, 3], [None, 2], [4]]
|
|
2136
|
+
"""
|
|
2137
|
+
outer, inner = shape
|
|
2138
|
+
st = [[None] * row_length for row_length in outer]
|
|
2139
|
+
w_count = 0
|
|
2140
|
+
for i in reversed(range(len(inner), len(outer))):
|
|
2141
|
+
for j in range(outer[i]):
|
|
2142
|
+
st[i][j] = word[w_count]
|
|
2143
|
+
w_count += 1
|
|
2144
|
+
for i in reversed(range(len(inner))):
|
|
2145
|
+
for j in range(outer[i]):
|
|
2146
|
+
if j >= inner[i]:
|
|
2147
|
+
st[i][j] = word[w_count]
|
|
2148
|
+
w_count += 1
|
|
2149
|
+
return self.element_class(self, st)
|
|
2150
|
+
|
|
2151
|
+
|
|
2152
|
+
class StandardSkewTableaux(SkewTableaux):
|
|
2153
|
+
"""
|
|
2154
|
+
Standard skew tableaux.
|
|
2155
|
+
|
|
2156
|
+
EXAMPLES::
|
|
2157
|
+
|
|
2158
|
+
sage: S = StandardSkewTableaux(); S
|
|
2159
|
+
Standard skew tableaux
|
|
2160
|
+
sage: S.cardinality()
|
|
2161
|
+
+Infinity
|
|
2162
|
+
|
|
2163
|
+
::
|
|
2164
|
+
|
|
2165
|
+
sage: S = StandardSkewTableaux(2); S
|
|
2166
|
+
Standard skew tableaux of size 2
|
|
2167
|
+
sage: S.cardinality() # needs sage.modules
|
|
2168
|
+
4
|
|
2169
|
+
|
|
2170
|
+
::
|
|
2171
|
+
|
|
2172
|
+
sage: # needs sage.graphs sage.modules
|
|
2173
|
+
sage: StandardSkewTableaux([[3, 2, 1], [1, 1]]).list()
|
|
2174
|
+
[[[None, 2, 3], [None, 4], [1]],
|
|
2175
|
+
[[None, 1, 2], [None, 3], [4]],
|
|
2176
|
+
[[None, 1, 2], [None, 4], [3]],
|
|
2177
|
+
[[None, 1, 3], [None, 4], [2]],
|
|
2178
|
+
[[None, 1, 4], [None, 3], [2]],
|
|
2179
|
+
[[None, 1, 4], [None, 2], [3]],
|
|
2180
|
+
[[None, 1, 3], [None, 2], [4]],
|
|
2181
|
+
[[None, 2, 4], [None, 3], [1]]]
|
|
2182
|
+
"""
|
|
2183
|
+
@staticmethod
|
|
2184
|
+
def __classcall_private__(cls, skp=None):
|
|
2185
|
+
"""
|
|
2186
|
+
Return the class of standard skew tableaux of skew shape ``skp``.
|
|
2187
|
+
|
|
2188
|
+
EXAMPLES::
|
|
2189
|
+
|
|
2190
|
+
sage: SST1 = StandardSkewTableaux([[3, 2, 1], [1, 1]])
|
|
2191
|
+
sage: SST2 = StandardSkewTableaux(SkewPartition([[3, 2, 1], [1, 1]]))
|
|
2192
|
+
sage: SST1 is SST2
|
|
2193
|
+
True
|
|
2194
|
+
"""
|
|
2195
|
+
if skp is None:
|
|
2196
|
+
return StandardSkewTableaux_all()
|
|
2197
|
+
elif isinstance(skp, (int, Integer)):
|
|
2198
|
+
return StandardSkewTableaux_size(skp)
|
|
2199
|
+
elif skp in SkewPartitions():
|
|
2200
|
+
return StandardSkewTableaux_shape(skp)
|
|
2201
|
+
else:
|
|
2202
|
+
raise TypeError("invalid argument")
|
|
2203
|
+
|
|
2204
|
+
def __contains__(self, x):
|
|
2205
|
+
"""
|
|
2206
|
+
EXAMPLES::
|
|
2207
|
+
|
|
2208
|
+
sage: [[None, 2], [1, 3]] in StandardSkewTableaux()
|
|
2209
|
+
True
|
|
2210
|
+
sage: [[None, 2], [2, 4]] in StandardSkewTableaux()
|
|
2211
|
+
False
|
|
2212
|
+
sage: [[None, 3], [2, 4]] in StandardSkewTableaux()
|
|
2213
|
+
False
|
|
2214
|
+
sage: [[None, 2], [1, 4]] in StandardSkewTableaux()
|
|
2215
|
+
False
|
|
2216
|
+
"""
|
|
2217
|
+
if x not in SkewTableaux():
|
|
2218
|
+
return False
|
|
2219
|
+
|
|
2220
|
+
return SkewTableau(x).is_standard()
|
|
2221
|
+
|
|
2222
|
+
|
|
2223
|
+
class StandardSkewTableaux_all(StandardSkewTableaux):
|
|
2224
|
+
"""
|
|
2225
|
+
Class of all standard skew tableaux.
|
|
2226
|
+
"""
|
|
2227
|
+
|
|
2228
|
+
def __init__(self):
|
|
2229
|
+
"""
|
|
2230
|
+
EXAMPLES::
|
|
2231
|
+
|
|
2232
|
+
sage: s = StandardSkewTableaux()
|
|
2233
|
+
sage: TestSuite(s).run() # needs sage.graphs sage.modules
|
|
2234
|
+
"""
|
|
2235
|
+
StandardSkewTableaux.__init__(self, category=InfiniteEnumeratedSets())
|
|
2236
|
+
|
|
2237
|
+
def _repr_(self):
|
|
2238
|
+
"""
|
|
2239
|
+
EXAMPLES::
|
|
2240
|
+
|
|
2241
|
+
sage: StandardSkewTableaux()
|
|
2242
|
+
Standard skew tableaux
|
|
2243
|
+
"""
|
|
2244
|
+
return "Standard skew tableaux"
|
|
2245
|
+
|
|
2246
|
+
def __iter__(self):
|
|
2247
|
+
"""
|
|
2248
|
+
Iterate through all standard skew tableaux having
|
|
2249
|
+
no empty rows (before nonempty rows) and no empty columns
|
|
2250
|
+
(before nonempty columns).
|
|
2251
|
+
|
|
2252
|
+
EXAMPLES::
|
|
2253
|
+
|
|
2254
|
+
sage: # needs sage.graphs sage.modules
|
|
2255
|
+
sage: it = StandardSkewTableaux().__iter__()
|
|
2256
|
+
sage: [next(it) for x in range(10)]
|
|
2257
|
+
[[],
|
|
2258
|
+
[[1]],
|
|
2259
|
+
[[1, 2]], [[1], [2]], [[None, 2], [1]], [[None, 1], [2]],
|
|
2260
|
+
[[1, 2, 3]], [[1, 2], [3]], [[1, 3], [2]], [[None, 2, 3], [1]]]
|
|
2261
|
+
"""
|
|
2262
|
+
n = 0
|
|
2263
|
+
while True:
|
|
2264
|
+
for st in StandardSkewTableaux_size(n):
|
|
2265
|
+
yield self.element_class(self, st)
|
|
2266
|
+
n += 1
|
|
2267
|
+
|
|
2268
|
+
|
|
2269
|
+
class StandardSkewTableaux_size(StandardSkewTableaux):
|
|
2270
|
+
"""
|
|
2271
|
+
Standard skew tableaux of a fixed size `n`.
|
|
2272
|
+
"""
|
|
2273
|
+
|
|
2274
|
+
def __init__(self, n):
|
|
2275
|
+
"""
|
|
2276
|
+
EXAMPLES::
|
|
2277
|
+
|
|
2278
|
+
sage: # needs sage.graphs sage.modules
|
|
2279
|
+
sage: S = StandardSkewTableaux(3)
|
|
2280
|
+
sage: TestSuite(S).run()
|
|
2281
|
+
"""
|
|
2282
|
+
self.n = n
|
|
2283
|
+
StandardSkewTableaux.__init__(self, category=FiniteEnumeratedSets())
|
|
2284
|
+
|
|
2285
|
+
def _repr_(self):
|
|
2286
|
+
"""
|
|
2287
|
+
EXAMPLES::
|
|
2288
|
+
|
|
2289
|
+
sage: StandardSkewTableaux(3)
|
|
2290
|
+
Standard skew tableaux of size 3
|
|
2291
|
+
"""
|
|
2292
|
+
return "Standard skew tableaux of size %s" % self.n
|
|
2293
|
+
|
|
2294
|
+
def cardinality(self):
|
|
2295
|
+
"""
|
|
2296
|
+
EXAMPLES::
|
|
2297
|
+
|
|
2298
|
+
sage: # needs sage.modules
|
|
2299
|
+
sage: StandardSkewTableaux(1).cardinality()
|
|
2300
|
+
1
|
|
2301
|
+
sage: StandardSkewTableaux(2).cardinality()
|
|
2302
|
+
4
|
|
2303
|
+
sage: StandardSkewTableaux(3).cardinality()
|
|
2304
|
+
24
|
|
2305
|
+
sage: StandardSkewTableaux(4).cardinality()
|
|
2306
|
+
194
|
|
2307
|
+
"""
|
|
2308
|
+
count = 0
|
|
2309
|
+
for skp in SkewPartitions(self.n):
|
|
2310
|
+
count += StandardSkewTableaux_shape(skp).cardinality()
|
|
2311
|
+
return count
|
|
2312
|
+
|
|
2313
|
+
def __iter__(self):
|
|
2314
|
+
"""
|
|
2315
|
+
Iterate through all standard skew tableaux of size `n` having
|
|
2316
|
+
no empty rows (before nonempty rows) and no empty columns
|
|
2317
|
+
(before nonempty columns). (The last two requirements
|
|
2318
|
+
ensure that the iterator terminates after finitely many steps.)
|
|
2319
|
+
|
|
2320
|
+
EXAMPLES::
|
|
2321
|
+
|
|
2322
|
+
sage: # needs sage.graphs sage.modules
|
|
2323
|
+
sage: StandardSkewTableaux(2).list()
|
|
2324
|
+
[[[1, 2]], [[1], [2]], [[None, 2], [1]], [[None, 1], [2]]]
|
|
2325
|
+
sage: StandardSkewTableaux(3).list()
|
|
2326
|
+
[[[1, 2, 3]],
|
|
2327
|
+
[[1, 2], [3]], [[1, 3], [2]],
|
|
2328
|
+
[[None, 2, 3], [1]], [[None, 1, 2], [3]], [[None, 1, 3], [2]],
|
|
2329
|
+
[[None, 2], [1, 3]], [[None, 1], [2, 3]],
|
|
2330
|
+
[[None, None, 2], [1, 3]], [[None, None, 3], [1, 2]],
|
|
2331
|
+
[[None, None, 1], [2, 3]],
|
|
2332
|
+
[[1], [2], [3]], [[None, 2], [None, 3], [1]],
|
|
2333
|
+
[[None, 1], [None, 2], [3]], [[None, 1], [None, 3], [2]],
|
|
2334
|
+
[[None, 2], [1], [3]], [[None, 3], [1], [2]],
|
|
2335
|
+
[[None, 1], [2], [3]], [[None, None, 3], [None, 2], [1]],
|
|
2336
|
+
[[None, None, 2], [None, 3], [1]],
|
|
2337
|
+
[[None, None, 1], [None, 3], [2]],
|
|
2338
|
+
[[None, None, 1], [None, 2], [3]],
|
|
2339
|
+
[[None, None, 2], [None, 1], [3]],
|
|
2340
|
+
[[None, None, 3], [None, 1], [2]]]
|
|
2341
|
+
"""
|
|
2342
|
+
for skp in SkewPartitions(self.n):
|
|
2343
|
+
for sst in StandardSkewTableaux_shape(skp):
|
|
2344
|
+
yield self.element_class(self, sst)
|
|
2345
|
+
|
|
2346
|
+
|
|
2347
|
+
class StandardSkewTableaux_shape(StandardSkewTableaux):
|
|
2348
|
+
r"""
|
|
2349
|
+
Standard skew tableaux of a fixed skew shape `\lambda / \mu`.
|
|
2350
|
+
"""
|
|
2351
|
+
@staticmethod
|
|
2352
|
+
def __classcall_private__(cls, skp):
|
|
2353
|
+
"""
|
|
2354
|
+
Normalize input to ensure a unique representation.
|
|
2355
|
+
|
|
2356
|
+
EXAMPLES::
|
|
2357
|
+
|
|
2358
|
+
sage: S = StandardSkewTableaux([[3, 2, 1], [1, 1]])
|
|
2359
|
+
sage: S2 = StandardSkewTableaux(SkewPartition([[3, 2, 1], [1, 1]]))
|
|
2360
|
+
sage: S is S2
|
|
2361
|
+
True
|
|
2362
|
+
"""
|
|
2363
|
+
return super().__classcall__(cls, SkewPartition(skp))
|
|
2364
|
+
|
|
2365
|
+
def __init__(self, skp):
|
|
2366
|
+
"""
|
|
2367
|
+
TESTS::
|
|
2368
|
+
|
|
2369
|
+
sage: # needs sage.graphs sage.modules
|
|
2370
|
+
sage: S = StandardSkewTableaux([[3, 2, 1], [1, 1]])
|
|
2371
|
+
sage: TestSuite(S).run()
|
|
2372
|
+
"""
|
|
2373
|
+
self.skp = skp
|
|
2374
|
+
StandardSkewTableaux.__init__(self, category=FiniteEnumeratedSets())
|
|
2375
|
+
|
|
2376
|
+
def _repr_(self):
|
|
2377
|
+
"""
|
|
2378
|
+
Return a string representation of ``self``.
|
|
2379
|
+
|
|
2380
|
+
EXAMPLES::
|
|
2381
|
+
|
|
2382
|
+
sage: StandardSkewTableaux([[3, 2, 1], [1, 1]])
|
|
2383
|
+
Standard skew tableaux of shape [3, 2, 1] / [1, 1]
|
|
2384
|
+
"""
|
|
2385
|
+
return "Standard skew tableaux of shape %s" % repr(self.skp)
|
|
2386
|
+
|
|
2387
|
+
def cardinality(self):
|
|
2388
|
+
"""
|
|
2389
|
+
Return the number of standard skew tableaux with shape of the skew
|
|
2390
|
+
partition ``skp``. This uses a formula due to Aitken
|
|
2391
|
+
(see Cor. 7.16.3 of [Sta-EC2]_).
|
|
2392
|
+
|
|
2393
|
+
EXAMPLES::
|
|
2394
|
+
|
|
2395
|
+
sage: StandardSkewTableaux([[3, 2, 1], [1, 1]]).cardinality() # needs sage.modules
|
|
2396
|
+
8
|
|
2397
|
+
"""
|
|
2398
|
+
outer, inner = self.skp
|
|
2399
|
+
m = len(outer)
|
|
2400
|
+
n = sum(outer) - sum(inner)
|
|
2401
|
+
outer = list(outer)
|
|
2402
|
+
inner = list(inner) + [0] * (m - len(inner))
|
|
2403
|
+
a = zero_matrix(QQ, m)
|
|
2404
|
+
for i in range(m):
|
|
2405
|
+
for j in range(m):
|
|
2406
|
+
v = outer[i] - inner[j] - i + j
|
|
2407
|
+
if v < 0:
|
|
2408
|
+
a[i, j] = 0
|
|
2409
|
+
else:
|
|
2410
|
+
a[i, j] = 1 / factorial(v)
|
|
2411
|
+
return ZZ(factorial(n) * a.det())
|
|
2412
|
+
|
|
2413
|
+
def __iter__(self):
|
|
2414
|
+
"""
|
|
2415
|
+
An iterator for all the standard skew tableaux whose shape is
|
|
2416
|
+
the skew partition ``skp``. The standard skew tableaux are
|
|
2417
|
+
ordered lexicographically by the word obtained from their row
|
|
2418
|
+
reading.
|
|
2419
|
+
|
|
2420
|
+
EXAMPLES::
|
|
2421
|
+
|
|
2422
|
+
sage: # needs sage.graphs sage.modules
|
|
2423
|
+
sage: StandardSkewTableaux([[3, 2, 1], [1, 1]]).list()
|
|
2424
|
+
[[[None, 2, 3], [None, 4], [1]],
|
|
2425
|
+
[[None, 1, 2], [None, 3], [4]],
|
|
2426
|
+
[[None, 1, 2], [None, 4], [3]],
|
|
2427
|
+
[[None, 1, 3], [None, 4], [2]],
|
|
2428
|
+
[[None, 1, 4], [None, 3], [2]],
|
|
2429
|
+
[[None, 1, 4], [None, 2], [3]],
|
|
2430
|
+
[[None, 1, 3], [None, 2], [4]],
|
|
2431
|
+
[[None, 2, 4], [None, 3], [1]]]
|
|
2432
|
+
"""
|
|
2433
|
+
dag = self.skp.to_dag(format='tuple')
|
|
2434
|
+
le_list = list(dag.topological_sort_generator())
|
|
2435
|
+
|
|
2436
|
+
empty = [[None] * row_length for row_length in self.skp.outer()]
|
|
2437
|
+
|
|
2438
|
+
for le in le_list:
|
|
2439
|
+
yield self.element_class(self, _label_skew(le, empty))
|
|
2440
|
+
|
|
2441
|
+
|
|
2442
|
+
class SemistandardSkewTableaux(SkewTableaux):
|
|
2443
|
+
r"""
|
|
2444
|
+
Semistandard skew tableaux.
|
|
2445
|
+
|
|
2446
|
+
This class can be initialized with several optional variables:
|
|
2447
|
+
the size of the skew tableaux (as a nameless integer variable),
|
|
2448
|
+
their shape (as a nameless skew partition variable), their
|
|
2449
|
+
weight (:meth:`~sage.combinat.skew_tableau.SkewTableau.weight`,
|
|
2450
|
+
as a nameless second variable after either the size or the
|
|
2451
|
+
shape) and their maximum entry (as an optional keyword variable
|
|
2452
|
+
called ``max_entry``, unless the weight has been specified). If
|
|
2453
|
+
neither the weight nor the maximum entry is specified, the
|
|
2454
|
+
maximum entry defaults to the size of the tableau.
|
|
2455
|
+
|
|
2456
|
+
Note that "maximum entry" does not literally mean the highest
|
|
2457
|
+
entry; instead it is just an upper bound that no entry is
|
|
2458
|
+
allowed to surpass.
|
|
2459
|
+
|
|
2460
|
+
EXAMPLES:
|
|
2461
|
+
|
|
2462
|
+
The (infinite) class of all semistandard skew tableaux::
|
|
2463
|
+
|
|
2464
|
+
sage: SemistandardSkewTableaux()
|
|
2465
|
+
Semistandard skew tableaux
|
|
2466
|
+
|
|
2467
|
+
The (still infinite) class of all semistandard skew tableaux
|
|
2468
|
+
with maximum entry `2`::
|
|
2469
|
+
|
|
2470
|
+
sage: SemistandardSkewTableaux(max_entry=2)
|
|
2471
|
+
Semistandard skew tableaux with maximum entry 2
|
|
2472
|
+
|
|
2473
|
+
The class of all semistandard skew tableaux of given size `3`
|
|
2474
|
+
and maximum entry `3`::
|
|
2475
|
+
|
|
2476
|
+
sage: SemistandardSkewTableaux(3)
|
|
2477
|
+
Semistandard skew tableaux of size 3 and maximum entry 3
|
|
2478
|
+
|
|
2479
|
+
To set a different maximum entry::
|
|
2480
|
+
|
|
2481
|
+
sage: SemistandardSkewTableaux(3, max_entry = 7)
|
|
2482
|
+
Semistandard skew tableaux of size 3 and maximum entry 7
|
|
2483
|
+
|
|
2484
|
+
Specifying a shape::
|
|
2485
|
+
|
|
2486
|
+
sage: SemistandardSkewTableaux([[2,1],[]])
|
|
2487
|
+
Semistandard skew tableaux of shape [2, 1] / [] and maximum entry 3
|
|
2488
|
+
|
|
2489
|
+
Specifying both a shape and a maximum entry::
|
|
2490
|
+
|
|
2491
|
+
sage: S = SemistandardSkewTableaux([[2,1],[1]], max_entry = 3); S
|
|
2492
|
+
Semistandard skew tableaux of shape [2, 1] / [1] and maximum entry 3
|
|
2493
|
+
sage: S.list()
|
|
2494
|
+
[[[None, 1], [1]],
|
|
2495
|
+
[[None, 2], [1]],
|
|
2496
|
+
[[None, 1], [2]],
|
|
2497
|
+
[[None, 3], [1]],
|
|
2498
|
+
[[None, 1], [3]],
|
|
2499
|
+
[[None, 2], [2]],
|
|
2500
|
+
[[None, 3], [2]],
|
|
2501
|
+
[[None, 2], [3]],
|
|
2502
|
+
[[None, 3], [3]]]
|
|
2503
|
+
|
|
2504
|
+
sage: for n in range(5):
|
|
2505
|
+
....: print("{} {}".format(n, len(SemistandardSkewTableaux([[2,2,1],[1]], max_entry = n))))
|
|
2506
|
+
0 0
|
|
2507
|
+
1 0
|
|
2508
|
+
2 1
|
|
2509
|
+
3 9
|
|
2510
|
+
4 35
|
|
2511
|
+
|
|
2512
|
+
Specifying a shape and a weight::
|
|
2513
|
+
|
|
2514
|
+
sage: SemistandardSkewTableaux([[2,1],[]],[2,1])
|
|
2515
|
+
Semistandard skew tableaux of shape [2, 1] / [] and weight [2, 1]
|
|
2516
|
+
|
|
2517
|
+
(the maximum entry is redundant in this case and thus is ignored).
|
|
2518
|
+
|
|
2519
|
+
Specifying a size and a weight::
|
|
2520
|
+
|
|
2521
|
+
sage: SemistandardSkewTableaux(3, [2,1])
|
|
2522
|
+
Semistandard skew tableaux of size 3 and weight [2, 1]
|
|
2523
|
+
|
|
2524
|
+
.. WARNING::
|
|
2525
|
+
|
|
2526
|
+
If the shape is not specified, the iterator of this class
|
|
2527
|
+
yields only skew tableaux whose shape is reduced, in the
|
|
2528
|
+
sense that there are no empty rows before the last nonempty
|
|
2529
|
+
row, and there are no empty columns before the last
|
|
2530
|
+
nonempty column. (Otherwise it would go on indefinitely.)
|
|
2531
|
+
|
|
2532
|
+
.. WARNING::
|
|
2533
|
+
|
|
2534
|
+
This class acts as a factory. The resulting classes are mainly
|
|
2535
|
+
useful for iteration. Do not rely on their containment tests,
|
|
2536
|
+
as they are not correct, e. g.::
|
|
2537
|
+
|
|
2538
|
+
sage: SkewTableau([[None]]) in SemistandardSkewTableaux(2)
|
|
2539
|
+
True
|
|
2540
|
+
"""
|
|
2541
|
+
@staticmethod
|
|
2542
|
+
def __classcall_private__(cls, p=None, mu=None, max_entry=None):
|
|
2543
|
+
"""
|
|
2544
|
+
Return the correct parent based upon the input.
|
|
2545
|
+
|
|
2546
|
+
EXAMPLES::
|
|
2547
|
+
|
|
2548
|
+
sage: SSST1 = SemistandardSkewTableaux([[3, 2, 1], [1, 1]])
|
|
2549
|
+
sage: SSST2 = SemistandardSkewTableaux(SkewPartition([[3, 2, 1], [1, 1]]))
|
|
2550
|
+
sage: SSST1 is SSST2
|
|
2551
|
+
True
|
|
2552
|
+
"""
|
|
2553
|
+
if p is None:
|
|
2554
|
+
if mu is None:
|
|
2555
|
+
return SemistandardSkewTableaux_all(max_entry)
|
|
2556
|
+
raise ValueError("you must specify either a size or a shape")
|
|
2557
|
+
|
|
2558
|
+
if isinstance(p, (int, Integer)):
|
|
2559
|
+
if mu is None:
|
|
2560
|
+
return SemistandardSkewTableaux_size(p, max_entry)
|
|
2561
|
+
else:
|
|
2562
|
+
return SemistandardSkewTableaux_size_weight(p, mu)
|
|
2563
|
+
|
|
2564
|
+
if p in SkewPartitions():
|
|
2565
|
+
if mu is None:
|
|
2566
|
+
return SemistandardSkewTableaux_shape(p, max_entry)
|
|
2567
|
+
else:
|
|
2568
|
+
return SemistandardSkewTableaux_shape_weight(p, mu)
|
|
2569
|
+
|
|
2570
|
+
raise ValueError("invalid input")
|
|
2571
|
+
|
|
2572
|
+
def __contains__(self, x):
|
|
2573
|
+
"""
|
|
2574
|
+
EXAMPLES::
|
|
2575
|
+
|
|
2576
|
+
sage: [[None, 2], [1, 3]] in SemistandardSkewTableaux()
|
|
2577
|
+
True
|
|
2578
|
+
sage: [[None, 2], [2, 4]] in SemistandardSkewTableaux()
|
|
2579
|
+
True
|
|
2580
|
+
sage: [[None, 3], [2, 4]] in SemistandardSkewTableaux()
|
|
2581
|
+
True
|
|
2582
|
+
sage: [[None, 2], [2, 4]] in SemistandardSkewTableaux()
|
|
2583
|
+
True
|
|
2584
|
+
"""
|
|
2585
|
+
if x not in SkewTableaux():
|
|
2586
|
+
return False
|
|
2587
|
+
|
|
2588
|
+
try:
|
|
2589
|
+
x = self.element_class(self, x)
|
|
2590
|
+
except Exception:
|
|
2591
|
+
return False
|
|
2592
|
+
return x.is_semistandard()
|
|
2593
|
+
|
|
2594
|
+
|
|
2595
|
+
class SemistandardSkewTableaux_all(SemistandardSkewTableaux):
|
|
2596
|
+
"""
|
|
2597
|
+
Class of all semistandard skew tableaux, possibly with a given
|
|
2598
|
+
maximum entry.
|
|
2599
|
+
"""
|
|
2600
|
+
|
|
2601
|
+
def __init__(self, max_entry):
|
|
2602
|
+
"""
|
|
2603
|
+
Initialize ``self``.
|
|
2604
|
+
|
|
2605
|
+
EXAMPLES::
|
|
2606
|
+
|
|
2607
|
+
sage: S = SemistandardSkewTableaux()
|
|
2608
|
+
sage: TestSuite(S).run()
|
|
2609
|
+
|
|
2610
|
+
sage: S = SemistandardSkewTableaux(3)
|
|
2611
|
+
sage: TestSuite(S).run()
|
|
2612
|
+
"""
|
|
2613
|
+
SemistandardSkewTableaux.__init__(self, category=InfiniteEnumeratedSets())
|
|
2614
|
+
if max_entry is None:
|
|
2615
|
+
self.max_entry = PlusInfinity()
|
|
2616
|
+
else:
|
|
2617
|
+
self.max_entry = max_entry
|
|
2618
|
+
|
|
2619
|
+
def _repr_(self):
|
|
2620
|
+
"""
|
|
2621
|
+
EXAMPLES::
|
|
2622
|
+
|
|
2623
|
+
sage: SemistandardSkewTableaux()
|
|
2624
|
+
Semistandard skew tableaux
|
|
2625
|
+
"""
|
|
2626
|
+
if self.max_entry == PlusInfinity():
|
|
2627
|
+
return "Semistandard skew tableaux"
|
|
2628
|
+
return "Semistandard skew tableaux with maximum entry {}".format(self.max_entry)
|
|
2629
|
+
|
|
2630
|
+
def __iter__(self):
|
|
2631
|
+
"""
|
|
2632
|
+
Iterate over the elements of ``self``.
|
|
2633
|
+
|
|
2634
|
+
EXAMPLES::
|
|
2635
|
+
|
|
2636
|
+
sage: it = SemistandardSkewTableaux(max_entry = 5).__iter__()
|
|
2637
|
+
sage: [next(it) for x in range(12)]
|
|
2638
|
+
[[],
|
|
2639
|
+
[[1]],
|
|
2640
|
+
[[2]],
|
|
2641
|
+
[[3]],
|
|
2642
|
+
[[4]],
|
|
2643
|
+
[[5]],
|
|
2644
|
+
[[1, 1]],
|
|
2645
|
+
[[1, 2]],
|
|
2646
|
+
[[1, 3]],
|
|
2647
|
+
[[1, 4]],
|
|
2648
|
+
[[1, 5]],
|
|
2649
|
+
[[2, 2]]]
|
|
2650
|
+
|
|
2651
|
+
If no max entry is specified, the iteration goes over all
|
|
2652
|
+
semistandard skew tableaux of size `n` with max entry `n`,
|
|
2653
|
+
for all `n`::
|
|
2654
|
+
|
|
2655
|
+
sage: it = SemistandardSkewTableaux().__iter__()
|
|
2656
|
+
sage: [next(it) for x in range(10)]
|
|
2657
|
+
[[],
|
|
2658
|
+
[[1]],
|
|
2659
|
+
[[1, 1]],
|
|
2660
|
+
[[1, 2]],
|
|
2661
|
+
[[2, 2]],
|
|
2662
|
+
[[1], [2]],
|
|
2663
|
+
[[None, 1], [1]],
|
|
2664
|
+
[[None, 2], [1]],
|
|
2665
|
+
[[None, 1], [2]],
|
|
2666
|
+
[[None, 2], [2]]]
|
|
2667
|
+
"""
|
|
2668
|
+
if self.max_entry == PlusInfinity():
|
|
2669
|
+
# Old behavior, kept here for backwards compatibility.
|
|
2670
|
+
# The usefulness of this iterator is questionable.
|
|
2671
|
+
n = 0
|
|
2672
|
+
while True:
|
|
2673
|
+
for ssst in SemistandardSkewTableaux_size(n, n):
|
|
2674
|
+
yield self.element_class(self, ssst)
|
|
2675
|
+
n += 1
|
|
2676
|
+
else:
|
|
2677
|
+
n = 0
|
|
2678
|
+
while True:
|
|
2679
|
+
for ssst in SemistandardSkewTableaux_size(n, self.max_entry):
|
|
2680
|
+
yield self.element_class(self, ssst)
|
|
2681
|
+
n += 1
|
|
2682
|
+
|
|
2683
|
+
|
|
2684
|
+
class SemistandardSkewTableaux_size(SemistandardSkewTableaux):
|
|
2685
|
+
"""
|
|
2686
|
+
Class of all semistandard skew tableaux of a fixed size `n`,
|
|
2687
|
+
possibly with a given maximum entry.
|
|
2688
|
+
"""
|
|
2689
|
+
|
|
2690
|
+
def __init__(self, n, max_entry):
|
|
2691
|
+
"""
|
|
2692
|
+
EXAMPLES::
|
|
2693
|
+
|
|
2694
|
+
sage: S = SemistandardSkewTableaux(3)
|
|
2695
|
+
sage: TestSuite(S).run()
|
|
2696
|
+
"""
|
|
2697
|
+
self.n = n
|
|
2698
|
+
if max_entry is None:
|
|
2699
|
+
self.max_entry = n
|
|
2700
|
+
else:
|
|
2701
|
+
self.max_entry = max_entry
|
|
2702
|
+
SemistandardSkewTableaux.__init__(self, category=FiniteEnumeratedSets())
|
|
2703
|
+
|
|
2704
|
+
def _repr_(self):
|
|
2705
|
+
"""
|
|
2706
|
+
EXAMPLES::
|
|
2707
|
+
|
|
2708
|
+
sage: SemistandardSkewTableaux(3)
|
|
2709
|
+
Semistandard skew tableaux of size 3 and maximum entry 3
|
|
2710
|
+
sage: SemistandardSkewTableaux(3, max_entry=8)
|
|
2711
|
+
Semistandard skew tableaux of size 3 and maximum entry 8
|
|
2712
|
+
"""
|
|
2713
|
+
return "Semistandard skew tableaux of size %s and maximum entry %s" % (repr(self.n), repr(self.max_entry))
|
|
2714
|
+
|
|
2715
|
+
def cardinality(self):
|
|
2716
|
+
"""
|
|
2717
|
+
EXAMPLES::
|
|
2718
|
+
|
|
2719
|
+
sage: SemistandardSkewTableaux(2).cardinality()
|
|
2720
|
+
8
|
|
2721
|
+
"""
|
|
2722
|
+
count = 0
|
|
2723
|
+
for p in SkewPartitions(self.n):
|
|
2724
|
+
count += SemistandardSkewTableaux_shape(p, self.max_entry).cardinality()
|
|
2725
|
+
return count
|
|
2726
|
+
|
|
2727
|
+
def __iter__(self):
|
|
2728
|
+
"""
|
|
2729
|
+
EXAMPLES::
|
|
2730
|
+
|
|
2731
|
+
sage: SemistandardSkewTableaux(2).list()
|
|
2732
|
+
[[[1, 1]],
|
|
2733
|
+
[[1, 2]],
|
|
2734
|
+
[[2, 2]],
|
|
2735
|
+
[[1], [2]],
|
|
2736
|
+
[[None, 1], [1]],
|
|
2737
|
+
[[None, 2], [1]],
|
|
2738
|
+
[[None, 1], [2]],
|
|
2739
|
+
[[None, 2], [2]]]
|
|
2740
|
+
"""
|
|
2741
|
+
for p in SkewPartitions(self.n):
|
|
2742
|
+
for ssst in SemistandardSkewTableaux_shape(p, self.max_entry):
|
|
2743
|
+
yield self.element_class(self, ssst)
|
|
2744
|
+
|
|
2745
|
+
|
|
2746
|
+
class SemistandardSkewTableaux_size_weight(SemistandardSkewTableaux):
|
|
2747
|
+
r"""
|
|
2748
|
+
Class of semistandard tableaux of a fixed size `n` and weight `\mu`.
|
|
2749
|
+
"""
|
|
2750
|
+
@staticmethod
|
|
2751
|
+
def __classcall_private__(cls, n, mu):
|
|
2752
|
+
"""
|
|
2753
|
+
Normalize our input to ensure we have a unique representation.
|
|
2754
|
+
|
|
2755
|
+
EXAMPLES::
|
|
2756
|
+
|
|
2757
|
+
sage: S = SemistandardSkewTableaux(3, [2,1])
|
|
2758
|
+
sage: S2 = SemistandardSkewTableaux(int(3), (2,1))
|
|
2759
|
+
sage: S is S2
|
|
2760
|
+
True
|
|
2761
|
+
"""
|
|
2762
|
+
return super().__classcall__(cls, n, tuple(mu))
|
|
2763
|
+
|
|
2764
|
+
def __init__(self, n, mu):
|
|
2765
|
+
"""
|
|
2766
|
+
EXAMPLES::
|
|
2767
|
+
|
|
2768
|
+
sage: S = SemistandardSkewTableaux(3,[2,1])
|
|
2769
|
+
sage: TestSuite(S).run()
|
|
2770
|
+
"""
|
|
2771
|
+
self.n = n
|
|
2772
|
+
self.mu = mu
|
|
2773
|
+
SemistandardSkewTableaux.__init__(self, category=FiniteEnumeratedSets())
|
|
2774
|
+
|
|
2775
|
+
def _repr_(self):
|
|
2776
|
+
"""
|
|
2777
|
+
EXAMPLES::
|
|
2778
|
+
|
|
2779
|
+
sage: SemistandardSkewTableaux(3,[2,1])
|
|
2780
|
+
Semistandard skew tableaux of size 3 and weight [2, 1]
|
|
2781
|
+
"""
|
|
2782
|
+
return "Semistandard skew tableaux of size %s and weight %s" % (repr(self.n), list(self.mu))
|
|
2783
|
+
|
|
2784
|
+
def cardinality(self):
|
|
2785
|
+
"""
|
|
2786
|
+
EXAMPLES::
|
|
2787
|
+
|
|
2788
|
+
sage: SemistandardSkewTableaux(2,[1,1]).cardinality()
|
|
2789
|
+
4
|
|
2790
|
+
"""
|
|
2791
|
+
count = 0
|
|
2792
|
+
for p in SkewPartitions(self.n):
|
|
2793
|
+
count += SemistandardSkewTableaux_shape_weight(p, self.mu).cardinality()
|
|
2794
|
+
return count
|
|
2795
|
+
|
|
2796
|
+
def __iter__(self):
|
|
2797
|
+
"""
|
|
2798
|
+
EXAMPLES::
|
|
2799
|
+
|
|
2800
|
+
sage: SemistandardSkewTableaux(2,[1,1]).list()
|
|
2801
|
+
[[[1, 2]], [[1], [2]], [[None, 2], [1]], [[None, 1], [2]]]
|
|
2802
|
+
"""
|
|
2803
|
+
for p in SkewPartitions(self.n):
|
|
2804
|
+
for ssst in SemistandardSkewTableaux_shape_weight(p, self.mu):
|
|
2805
|
+
yield self.element_class(self, ssst)
|
|
2806
|
+
|
|
2807
|
+
|
|
2808
|
+
class SemistandardSkewTableaux_shape(SemistandardSkewTableaux):
|
|
2809
|
+
r"""
|
|
2810
|
+
Class of semistandard skew tableaux of a fixed skew shape
|
|
2811
|
+
`\lambda / \mu` with a given max entry.
|
|
2812
|
+
|
|
2813
|
+
A semistandard skew tableau with max entry `i` is required to have all
|
|
2814
|
+
its entries less or equal to `i`. It is not required to actually
|
|
2815
|
+
contain an entry `i`.
|
|
2816
|
+
|
|
2817
|
+
INPUT:
|
|
2818
|
+
|
|
2819
|
+
- ``p`` -- a skew partition
|
|
2820
|
+
|
|
2821
|
+
- ``max_entry`` -- the max entry; defaults to the size of ``p``
|
|
2822
|
+
|
|
2823
|
+
.. WARNING::
|
|
2824
|
+
|
|
2825
|
+
Input is not checked; please use :class:`SemistandardSkewTableaux` to
|
|
2826
|
+
ensure the options are properly parsed.
|
|
2827
|
+
"""
|
|
2828
|
+
@staticmethod
|
|
2829
|
+
def __classcall_private__(cls, p, max_entry=None):
|
|
2830
|
+
"""
|
|
2831
|
+
Normalize our input to ensure we have a unique representation.
|
|
2832
|
+
|
|
2833
|
+
EXAMPLES::
|
|
2834
|
+
|
|
2835
|
+
sage: S = SemistandardSkewTableaux([[2,1],[]])
|
|
2836
|
+
sage: S2 = SemistandardSkewTableaux(SkewPartition([[2,1],[]]))
|
|
2837
|
+
sage: S is S2
|
|
2838
|
+
True
|
|
2839
|
+
"""
|
|
2840
|
+
if max_entry is None:
|
|
2841
|
+
max_entry = sum(p[0]) - sum(p[1])
|
|
2842
|
+
return super().__classcall__(cls, SkewPartition(p), max_entry)
|
|
2843
|
+
|
|
2844
|
+
def __init__(self, p, max_entry):
|
|
2845
|
+
"""
|
|
2846
|
+
EXAMPLES::
|
|
2847
|
+
|
|
2848
|
+
sage: S = SemistandardSkewTableaux([[2,1],[]])
|
|
2849
|
+
sage: S == loads(dumps(S))
|
|
2850
|
+
True
|
|
2851
|
+
sage: TestSuite(S).run()
|
|
2852
|
+
"""
|
|
2853
|
+
self.p = p
|
|
2854
|
+
self.max_entry = max_entry
|
|
2855
|
+
SemistandardSkewTableaux.__init__(self, category=FiniteEnumeratedSets())
|
|
2856
|
+
|
|
2857
|
+
def _repr_(self):
|
|
2858
|
+
"""
|
|
2859
|
+
EXAMPLES::
|
|
2860
|
+
|
|
2861
|
+
sage: SemistandardSkewTableaux([[2,1],[]])
|
|
2862
|
+
Semistandard skew tableaux of shape [2, 1] / [] and maximum entry 3
|
|
2863
|
+
"""
|
|
2864
|
+
return "Semistandard skew tableaux of shape %s and maximum entry %s" % (repr(self.p), repr(self.max_entry))
|
|
2865
|
+
|
|
2866
|
+
def cardinality(self):
|
|
2867
|
+
"""
|
|
2868
|
+
EXAMPLES::
|
|
2869
|
+
|
|
2870
|
+
sage: SemistandardSkewTableaux([[2,1],[]]).cardinality()
|
|
2871
|
+
8
|
|
2872
|
+
sage: SemistandardSkewTableaux([[2,1],[]], max_entry=2).cardinality()
|
|
2873
|
+
2
|
|
2874
|
+
"""
|
|
2875
|
+
count = 0
|
|
2876
|
+
for mu in IntegerVectors(self.p.size(), self.max_entry):
|
|
2877
|
+
count += SemistandardSkewTableaux_shape_weight(self.p, mu).cardinality()
|
|
2878
|
+
return count
|
|
2879
|
+
|
|
2880
|
+
def __iter__(self):
|
|
2881
|
+
"""
|
|
2882
|
+
EXAMPLES::
|
|
2883
|
+
|
|
2884
|
+
sage: SemistandardSkewTableaux([[2,1],[]]).list()
|
|
2885
|
+
[[[1, 1], [2]],
|
|
2886
|
+
[[1, 1], [3]],
|
|
2887
|
+
[[1, 2], [2]],
|
|
2888
|
+
[[1, 3], [2]],
|
|
2889
|
+
[[1, 2], [3]],
|
|
2890
|
+
[[1, 3], [3]],
|
|
2891
|
+
[[2, 2], [3]],
|
|
2892
|
+
[[2, 3], [3]]]
|
|
2893
|
+
sage: from sage.combinat.skew_tableau import SemistandardSkewTableaux_shape
|
|
2894
|
+
sage: SemistandardSkewTableaux_shape([[2,1],[]], max_entry=2).list()
|
|
2895
|
+
[[[1, 1], [2]], [[1, 2], [2]]]
|
|
2896
|
+
"""
|
|
2897
|
+
for mu in IntegerVectors(self.p.size(), self.max_entry):
|
|
2898
|
+
for ssst in SemistandardSkewTableaux_shape_weight(self.p, mu):
|
|
2899
|
+
yield self.element_class(self, ssst)
|
|
2900
|
+
|
|
2901
|
+
|
|
2902
|
+
class SemistandardSkewTableaux_shape_weight(SemistandardSkewTableaux):
|
|
2903
|
+
r"""
|
|
2904
|
+
Class of semistandard skew tableaux of a fixed skew shape `\lambda / \nu`
|
|
2905
|
+
and weight `\mu`.
|
|
2906
|
+
"""
|
|
2907
|
+
@staticmethod
|
|
2908
|
+
def __classcall_private__(cls, p, mu):
|
|
2909
|
+
"""
|
|
2910
|
+
Normalize our input to ensure we have a unique representation.
|
|
2911
|
+
|
|
2912
|
+
EXAMPLES::
|
|
2913
|
+
|
|
2914
|
+
sage: S = SemistandardSkewTableaux([[2,1],[]], [2,1])
|
|
2915
|
+
sage: S2 = SemistandardSkewTableaux(SkewPartition([[2,1],[]]), (2,1))
|
|
2916
|
+
sage: S is S2
|
|
2917
|
+
True
|
|
2918
|
+
"""
|
|
2919
|
+
p = SkewPartition(p)
|
|
2920
|
+
mu = tuple(mu)
|
|
2921
|
+
return super().__classcall__(cls, p, mu)
|
|
2922
|
+
|
|
2923
|
+
def __init__(self, p, mu):
|
|
2924
|
+
"""
|
|
2925
|
+
EXAMPLES::
|
|
2926
|
+
|
|
2927
|
+
sage: S = SemistandardSkewTableaux([[2,1],[]],[2,1])
|
|
2928
|
+
sage: S == loads(dumps(S))
|
|
2929
|
+
True
|
|
2930
|
+
sage: TestSuite(S).run()
|
|
2931
|
+
"""
|
|
2932
|
+
self.p = p
|
|
2933
|
+
self.mu = mu
|
|
2934
|
+
SemistandardSkewTableaux.__init__(self, category=FiniteEnumeratedSets())
|
|
2935
|
+
|
|
2936
|
+
def _repr_(self):
|
|
2937
|
+
"""
|
|
2938
|
+
EXAMPLES::
|
|
2939
|
+
|
|
2940
|
+
sage: SemistandardSkewTableaux([[2,1],[]],[2,1])
|
|
2941
|
+
Semistandard skew tableaux of shape [2, 1] / [] and weight [2, 1]
|
|
2942
|
+
"""
|
|
2943
|
+
return "Semistandard skew tableaux of shape %s and weight %s" % (repr(self.p), list(self.mu))
|
|
2944
|
+
|
|
2945
|
+
def __iter__(self):
|
|
2946
|
+
"""
|
|
2947
|
+
Iterate over ``self``.
|
|
2948
|
+
|
|
2949
|
+
EXAMPLES::
|
|
2950
|
+
|
|
2951
|
+
sage: SemistandardSkewTableaux([[2,1],[]],[2,1]).list()
|
|
2952
|
+
[[[1, 1], [2]]]
|
|
2953
|
+
"""
|
|
2954
|
+
from .ribbon_tableau import RibbonTableaux_shape_weight_length
|
|
2955
|
+
for x in RibbonTableaux_shape_weight_length(self.p, self.mu, 1):
|
|
2956
|
+
yield self.element_class(self, x)
|
|
2957
|
+
|
|
2958
|
+
|
|
2959
|
+
class SkewTableau_class(SkewTableau):
|
|
2960
|
+
"""
|
|
2961
|
+
This exists solely for unpickling ``SkewTableau_class`` objects.
|
|
2962
|
+
"""
|
|
2963
|
+
|
|
2964
|
+
def __setstate__(self, state):
|
|
2965
|
+
r"""
|
|
2966
|
+
Unpickle old ``SkewTableau_class`` objects.
|
|
2967
|
+
|
|
2968
|
+
TESTS::
|
|
2969
|
+
|
|
2970
|
+
sage: loads(b'x\x9ck`J.NLO\xd5K\xce\xcfM\xca\xccK,\xd1+H,*\xc9,\xc9\xcc\xcf\xe3\n\x80\xb1\xe2\x93s\x12\x8b\x8b\xb9\n\x195\x1b\x0b\x99j\x0b\x995BY\xe33\x12\x8b3\nY\xfc\x80\xac\x9c\xcc\xe2\x92B\xd6\xd8B6\r\x88IE\x99y\xe9\xc5z\x99y%\xa9\xe9\xa9E\\\xb9\x89\xd9\xa9\xf10N!{(\xa3qkP!G\x06\x90a\x04dp\x82\x18\x86@\x06Wji\x92\x1e\x00x0.\xb5')
|
|
2971
|
+
[3, 2, 1]
|
|
2972
|
+
sage: loads(dumps( SkewTableau([[1,1], [3,2,1]]) )) # indirect doctest
|
|
2973
|
+
[[1, 1], [3, 2, 1]]
|
|
2974
|
+
"""
|
|
2975
|
+
self.__class__ = SkewTableau
|
|
2976
|
+
self.__init__(SkewTableaux(), state['_list'])
|
|
2977
|
+
|
|
2978
|
+
|
|
2979
|
+
# October 2012: fixing outdated pickles which use the classes being deprecated
|
|
2980
|
+
|
|
2981
|
+
|
|
2982
|
+
register_unpickle_override('sage.combinat.skew_tableau', 'StandardSkewTableaux_n', StandardSkewTableaux_size)
|
|
2983
|
+
register_unpickle_override('sage.combinat.skew_tableau', 'SemistandardSkewTableaux_n', SemistandardSkewTableaux_size)
|
|
2984
|
+
register_unpickle_override('sage.combinat.skew_tableau', 'SemistandardSkewTableaux_nmu', SemistandardSkewTableaux_size_weight)
|
|
2985
|
+
register_unpickle_override('sage.combinat.skew_tableau', 'SemistandardSkewTableaux_p', SemistandardSkewTableaux_shape)
|
|
2986
|
+
register_unpickle_override('sage.combinat.skew_tableau', 'SemistandardSkewTableaux_pmu', SemistandardSkewTableaux_shape_weight)
|
|
2987
|
+
# July 2013: But wait, there more!
|
|
2988
|
+
register_unpickle_override('sage.combinat.skew_tableau', 'StandardSkewTableaux_skewpartition', StandardSkewTableaux_shape)
|
|
2989
|
+
register_unpickle_override('sage.combinat.skew_tableau', 'SkewTableau_class', SkewTableau_class)
|