passagemath-combinat 10.6.42__cp314-cp314t-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_combinat/__init__.py +3 -0
- passagemath_combinat-10.6.42.dist-info/DELVEWHEEL +2 -0
- passagemath_combinat-10.6.42.dist-info/METADATA +160 -0
- passagemath_combinat-10.6.42.dist-info/RECORD +401 -0
- passagemath_combinat-10.6.42.dist-info/WHEEL +5 -0
- passagemath_combinat-10.6.42.dist-info/top_level.txt +3 -0
- passagemath_combinat.libs/libgmp-10-3a5f019e2510aeaad918cab2b57a689d.dll +0 -0
- passagemath_combinat.libs/libsymmetrica-3-7dcf900932804d0df5fd0919b4668720.dll +0 -0
- sage/algebras/affine_nil_temperley_lieb.py +263 -0
- sage/algebras/all.py +24 -0
- sage/algebras/all__sagemath_combinat.py +35 -0
- sage/algebras/askey_wilson.py +935 -0
- sage/algebras/associated_graded.py +345 -0
- sage/algebras/cellular_basis.py +350 -0
- sage/algebras/cluster_algebra.py +2766 -0
- sage/algebras/down_up_algebra.py +860 -0
- sage/algebras/free_algebra.py +1698 -0
- sage/algebras/free_algebra_element.py +345 -0
- sage/algebras/free_algebra_quotient.py +405 -0
- sage/algebras/free_algebra_quotient_element.py +295 -0
- sage/algebras/free_zinbiel_algebra.py +885 -0
- sage/algebras/hall_algebra.py +783 -0
- sage/algebras/hecke_algebras/all.py +4 -0
- sage/algebras/hecke_algebras/ariki_koike_algebra.py +1796 -0
- sage/algebras/hecke_algebras/ariki_koike_specht_modules.py +475 -0
- sage/algebras/hecke_algebras/cubic_hecke_algebra.py +3520 -0
- sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +1473 -0
- sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py +1079 -0
- sage/algebras/iwahori_hecke_algebra.py +3095 -0
- sage/algebras/jordan_algebra.py +1773 -0
- sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py +113 -0
- sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py +156 -0
- sage/algebras/lie_conformal_algebras/all.py +18 -0
- sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py +134 -0
- sage/algebras/lie_conformal_algebras/examples.py +43 -0
- sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py +131 -0
- sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py +139 -0
- sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py +174 -0
- sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +167 -0
- sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py +107 -0
- sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py +135 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +353 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py +236 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py +78 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +328 -0
- sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py +117 -0
- sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py +86 -0
- sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py +82 -0
- sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py +205 -0
- sage/algebras/nil_coxeter_algebra.py +191 -0
- sage/algebras/q_commuting_polynomials.py +673 -0
- sage/algebras/q_system.py +608 -0
- sage/algebras/quantum_clifford.py +959 -0
- sage/algebras/quantum_groups/ace_quantum_onsager.py +693 -0
- sage/algebras/quantum_groups/all.py +9 -0
- sage/algebras/quantum_groups/fock_space.py +2219 -0
- sage/algebras/quantum_groups/q_numbers.py +207 -0
- sage/algebras/quantum_groups/quantum_group_gap.py +2695 -0
- sage/algebras/quantum_groups/representations.py +591 -0
- sage/algebras/quantum_matrix_coordinate_algebra.py +1006 -0
- sage/algebras/quantum_oscillator.py +623 -0
- sage/algebras/quaternion_algebra.py +20 -0
- sage/algebras/quaternion_algebra_element.py +55 -0
- sage/algebras/rational_cherednik_algebra.py +525 -0
- sage/algebras/schur_algebra.py +670 -0
- sage/algebras/shuffle_algebra.py +1011 -0
- sage/algebras/splitting_algebra.py +779 -0
- sage/algebras/tensor_algebra.py +709 -0
- sage/algebras/yangian.py +1082 -0
- sage/algebras/yokonuma_hecke_algebra.py +1018 -0
- sage/all__sagemath_combinat.py +44 -0
- sage/combinat/SJT.py +255 -0
- sage/combinat/affine_permutation.py +2405 -0
- sage/combinat/algebraic_combinatorics.py +55 -0
- sage/combinat/all.py +53 -0
- sage/combinat/all__sagemath_combinat.py +195 -0
- sage/combinat/alternating_sign_matrix.py +2063 -0
- sage/combinat/baxter_permutations.py +346 -0
- sage/combinat/bijectionist.py +3220 -0
- sage/combinat/binary_recurrence_sequences.py +1180 -0
- sage/combinat/blob_algebra.py +685 -0
- sage/combinat/catalog_partitions.py +27 -0
- sage/combinat/chas/all.py +23 -0
- sage/combinat/chas/fsym.py +1180 -0
- sage/combinat/chas/wqsym.py +2601 -0
- sage/combinat/cluster_complex.py +326 -0
- sage/combinat/colored_permutations.py +2039 -0
- sage/combinat/colored_permutations_representations.py +964 -0
- sage/combinat/composition_signed.py +142 -0
- sage/combinat/composition_tableau.py +855 -0
- sage/combinat/constellation.py +1729 -0
- sage/combinat/core.py +751 -0
- sage/combinat/counting.py +12 -0
- sage/combinat/crystals/affine.py +742 -0
- sage/combinat/crystals/affine_factorization.py +518 -0
- sage/combinat/crystals/affinization.py +331 -0
- sage/combinat/crystals/alcove_path.py +2013 -0
- sage/combinat/crystals/all.py +22 -0
- sage/combinat/crystals/bkk_crystals.py +141 -0
- sage/combinat/crystals/catalog.py +115 -0
- sage/combinat/crystals/catalog_elementary_crystals.py +18 -0
- sage/combinat/crystals/catalog_infinity_crystals.py +33 -0
- sage/combinat/crystals/catalog_kirillov_reshetikhin.py +18 -0
- sage/combinat/crystals/crystals.py +257 -0
- sage/combinat/crystals/direct_sum.py +260 -0
- sage/combinat/crystals/elementary_crystals.py +1251 -0
- sage/combinat/crystals/fast_crystals.py +441 -0
- sage/combinat/crystals/fully_commutative_stable_grothendieck.py +1205 -0
- sage/combinat/crystals/generalized_young_walls.py +1076 -0
- sage/combinat/crystals/highest_weight_crystals.py +436 -0
- sage/combinat/crystals/induced_structure.py +695 -0
- sage/combinat/crystals/infinity_crystals.py +730 -0
- sage/combinat/crystals/kac_modules.py +863 -0
- sage/combinat/crystals/kirillov_reshetikhin.py +4196 -0
- sage/combinat/crystals/kyoto_path_model.py +497 -0
- sage/combinat/crystals/letters.cp314t-win_amd64.pyd +0 -0
- sage/combinat/crystals/letters.pxd +79 -0
- sage/combinat/crystals/letters.pyx +3056 -0
- sage/combinat/crystals/littelmann_path.py +1518 -0
- sage/combinat/crystals/monomial_crystals.py +1262 -0
- sage/combinat/crystals/multisegments.py +462 -0
- sage/combinat/crystals/mv_polytopes.py +467 -0
- sage/combinat/crystals/pbw_crystal.py +511 -0
- sage/combinat/crystals/pbw_datum.cp314t-win_amd64.pyd +0 -0
- sage/combinat/crystals/pbw_datum.pxd +4 -0
- sage/combinat/crystals/pbw_datum.pyx +487 -0
- sage/combinat/crystals/polyhedral_realization.py +372 -0
- sage/combinat/crystals/spins.cp314t-win_amd64.pyd +0 -0
- sage/combinat/crystals/spins.pxd +21 -0
- sage/combinat/crystals/spins.pyx +756 -0
- sage/combinat/crystals/star_crystal.py +290 -0
- sage/combinat/crystals/subcrystal.py +464 -0
- sage/combinat/crystals/tensor_product.py +1177 -0
- sage/combinat/crystals/tensor_product_element.cp314t-win_amd64.pyd +0 -0
- sage/combinat/crystals/tensor_product_element.pxd +35 -0
- sage/combinat/crystals/tensor_product_element.pyx +1870 -0
- sage/combinat/crystals/virtual_crystal.py +420 -0
- sage/combinat/cyclic_sieving_phenomenon.py +204 -0
- sage/combinat/debruijn_sequence.cp314t-win_amd64.pyd +0 -0
- sage/combinat/debruijn_sequence.pyx +355 -0
- sage/combinat/decorated_permutation.py +270 -0
- sage/combinat/degree_sequences.cp314t-win_amd64.pyd +0 -0
- sage/combinat/degree_sequences.pyx +588 -0
- sage/combinat/derangements.py +527 -0
- sage/combinat/descent_algebra.py +1008 -0
- sage/combinat/diagram.py +1551 -0
- sage/combinat/diagram_algebras.py +5886 -0
- sage/combinat/dyck_word.py +4349 -0
- sage/combinat/e_one_star.py +1623 -0
- sage/combinat/enumerated_sets.py +123 -0
- sage/combinat/expnums.cp314t-win_amd64.pyd +0 -0
- sage/combinat/expnums.pyx +148 -0
- sage/combinat/fast_vector_partitions.cp314t-win_amd64.pyd +0 -0
- sage/combinat/fast_vector_partitions.pyx +346 -0
- sage/combinat/fqsym.py +1977 -0
- sage/combinat/free_dendriform_algebra.py +954 -0
- sage/combinat/free_prelie_algebra.py +1141 -0
- sage/combinat/fully_commutative_elements.py +1077 -0
- sage/combinat/fully_packed_loop.py +1523 -0
- sage/combinat/gelfand_tsetlin_patterns.py +1409 -0
- sage/combinat/gray_codes.py +311 -0
- sage/combinat/grossman_larson_algebras.py +667 -0
- sage/combinat/growth.py +4352 -0
- sage/combinat/hall_polynomial.py +188 -0
- sage/combinat/hillman_grassl.py +866 -0
- sage/combinat/integer_matrices.py +329 -0
- sage/combinat/integer_vectors_mod_permgroup.py +1238 -0
- sage/combinat/k_tableau.py +4564 -0
- sage/combinat/kazhdan_lusztig.py +215 -0
- sage/combinat/key_polynomial.py +885 -0
- sage/combinat/knutson_tao_puzzles.py +2286 -0
- sage/combinat/lr_tableau.py +311 -0
- sage/combinat/matrices/all.py +24 -0
- sage/combinat/matrices/hadamard_matrix.py +3790 -0
- sage/combinat/matrices/latin.py +2912 -0
- sage/combinat/misc.py +401 -0
- sage/combinat/multiset_partition_into_sets_ordered.py +3541 -0
- sage/combinat/ncsf_qsym/all.py +21 -0
- sage/combinat/ncsf_qsym/combinatorics.py +317 -0
- sage/combinat/ncsf_qsym/generic_basis_code.py +1427 -0
- sage/combinat/ncsf_qsym/ncsf.py +5637 -0
- sage/combinat/ncsf_qsym/qsym.py +4053 -0
- sage/combinat/ncsf_qsym/tutorial.py +447 -0
- sage/combinat/ncsym/all.py +21 -0
- sage/combinat/ncsym/bases.py +855 -0
- sage/combinat/ncsym/dual.py +593 -0
- sage/combinat/ncsym/ncsym.py +2076 -0
- sage/combinat/necklace.py +551 -0
- sage/combinat/non_decreasing_parking_function.py +634 -0
- sage/combinat/nu_dyck_word.py +1474 -0
- sage/combinat/output.py +861 -0
- sage/combinat/parallelogram_polyomino.py +4326 -0
- sage/combinat/parking_functions.py +1602 -0
- sage/combinat/partition_algebra.py +1998 -0
- sage/combinat/partition_kleshchev.py +1982 -0
- sage/combinat/partition_shifting_algebras.py +584 -0
- sage/combinat/partition_tuple.py +3114 -0
- sage/combinat/path_tableaux/all.py +13 -0
- sage/combinat/path_tableaux/catalog.py +29 -0
- sage/combinat/path_tableaux/dyck_path.py +380 -0
- sage/combinat/path_tableaux/frieze.py +476 -0
- sage/combinat/path_tableaux/path_tableau.py +728 -0
- sage/combinat/path_tableaux/semistandard.py +510 -0
- sage/combinat/perfect_matching.py +779 -0
- sage/combinat/plane_partition.py +3300 -0
- sage/combinat/q_bernoulli.cp314t-win_amd64.pyd +0 -0
- sage/combinat/q_bernoulli.pyx +128 -0
- sage/combinat/quickref.py +81 -0
- sage/combinat/recognizable_series.py +2051 -0
- sage/combinat/regular_sequence.py +4316 -0
- sage/combinat/regular_sequence_bounded.py +543 -0
- sage/combinat/restricted_growth.py +81 -0
- sage/combinat/ribbon.py +20 -0
- sage/combinat/ribbon_shaped_tableau.py +489 -0
- sage/combinat/ribbon_tableau.py +1180 -0
- sage/combinat/rigged_configurations/all.py +46 -0
- sage/combinat/rigged_configurations/bij_abstract_class.py +548 -0
- sage/combinat/rigged_configurations/bij_infinity.py +370 -0
- sage/combinat/rigged_configurations/bij_type_A.py +163 -0
- sage/combinat/rigged_configurations/bij_type_A2_dual.py +338 -0
- sage/combinat/rigged_configurations/bij_type_A2_even.py +218 -0
- sage/combinat/rigged_configurations/bij_type_A2_odd.py +199 -0
- sage/combinat/rigged_configurations/bij_type_B.py +900 -0
- sage/combinat/rigged_configurations/bij_type_C.py +267 -0
- sage/combinat/rigged_configurations/bij_type_D.py +771 -0
- sage/combinat/rigged_configurations/bij_type_D_tri.py +392 -0
- sage/combinat/rigged_configurations/bij_type_D_twisted.py +576 -0
- sage/combinat/rigged_configurations/bij_type_E67.py +402 -0
- sage/combinat/rigged_configurations/bijection.py +143 -0
- sage/combinat/rigged_configurations/kleber_tree.py +1475 -0
- sage/combinat/rigged_configurations/kr_tableaux.py +1898 -0
- sage/combinat/rigged_configurations/rc_crystal.py +461 -0
- sage/combinat/rigged_configurations/rc_infinity.py +540 -0
- sage/combinat/rigged_configurations/rigged_configuration_element.py +2403 -0
- sage/combinat/rigged_configurations/rigged_configurations.py +1918 -0
- sage/combinat/rigged_configurations/rigged_partition.cp314t-win_amd64.pyd +0 -0
- sage/combinat/rigged_configurations/rigged_partition.pxd +15 -0
- sage/combinat/rigged_configurations/rigged_partition.pyx +680 -0
- sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +499 -0
- sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py +428 -0
- sage/combinat/rsk.py +3438 -0
- sage/combinat/schubert_polynomial.py +508 -0
- sage/combinat/set_partition.py +3318 -0
- sage/combinat/set_partition_iterator.cp314t-win_amd64.pyd +0 -0
- sage/combinat/set_partition_iterator.pyx +136 -0
- sage/combinat/set_partition_ordered.py +1590 -0
- sage/combinat/sf/abreu_nigro.py +346 -0
- sage/combinat/sf/all.py +52 -0
- sage/combinat/sf/character.py +576 -0
- sage/combinat/sf/classical.py +319 -0
- sage/combinat/sf/dual.py +996 -0
- sage/combinat/sf/elementary.py +549 -0
- sage/combinat/sf/hall_littlewood.py +1028 -0
- sage/combinat/sf/hecke.py +336 -0
- sage/combinat/sf/homogeneous.py +464 -0
- sage/combinat/sf/jack.py +1428 -0
- sage/combinat/sf/k_dual.py +1458 -0
- sage/combinat/sf/kfpoly.py +447 -0
- sage/combinat/sf/llt.py +789 -0
- sage/combinat/sf/macdonald.py +2019 -0
- sage/combinat/sf/monomial.py +525 -0
- sage/combinat/sf/multiplicative.py +113 -0
- sage/combinat/sf/new_kschur.py +1786 -0
- sage/combinat/sf/ns_macdonald.py +964 -0
- sage/combinat/sf/orthogonal.py +246 -0
- sage/combinat/sf/orthotriang.py +355 -0
- sage/combinat/sf/powersum.py +963 -0
- sage/combinat/sf/schur.py +880 -0
- sage/combinat/sf/sf.py +1653 -0
- sage/combinat/sf/sfa.py +7053 -0
- sage/combinat/sf/symplectic.py +253 -0
- sage/combinat/sf/witt.py +721 -0
- sage/combinat/shifted_primed_tableau.py +2735 -0
- sage/combinat/shuffle.py +830 -0
- sage/combinat/sidon_sets.py +146 -0
- sage/combinat/similarity_class_type.py +1721 -0
- sage/combinat/sine_gordon.py +618 -0
- sage/combinat/six_vertex_model.py +784 -0
- sage/combinat/skew_partition.py +2053 -0
- sage/combinat/skew_tableau.py +2989 -0
- sage/combinat/sloane_functions.py +8935 -0
- sage/combinat/specht_module.py +1403 -0
- sage/combinat/species/all.py +48 -0
- sage/combinat/species/characteristic_species.py +321 -0
- sage/combinat/species/composition_species.py +273 -0
- sage/combinat/species/cycle_species.py +284 -0
- sage/combinat/species/empty_species.py +155 -0
- sage/combinat/species/functorial_composition_species.py +148 -0
- sage/combinat/species/generating_series.py +673 -0
- sage/combinat/species/library.py +148 -0
- sage/combinat/species/linear_order_species.py +169 -0
- sage/combinat/species/misc.py +83 -0
- sage/combinat/species/partition_species.py +290 -0
- sage/combinat/species/permutation_species.py +268 -0
- sage/combinat/species/product_species.py +423 -0
- sage/combinat/species/recursive_species.py +476 -0
- sage/combinat/species/set_species.py +192 -0
- sage/combinat/species/species.py +820 -0
- sage/combinat/species/structure.py +539 -0
- sage/combinat/species/subset_species.py +243 -0
- sage/combinat/species/sum_species.py +225 -0
- sage/combinat/subword.py +564 -0
- sage/combinat/subword_complex.py +2122 -0
- sage/combinat/subword_complex_c.cp314t-win_amd64.pyd +0 -0
- sage/combinat/subword_complex_c.pyx +119 -0
- sage/combinat/super_tableau.py +821 -0
- sage/combinat/superpartition.py +1154 -0
- sage/combinat/symmetric_group_algebra.py +3774 -0
- sage/combinat/symmetric_group_representations.py +1830 -0
- sage/combinat/t_sequences.py +877 -0
- sage/combinat/tableau.py +9506 -0
- sage/combinat/tableau_residues.py +860 -0
- sage/combinat/tableau_tuple.py +5353 -0
- sage/combinat/tiling.py +2432 -0
- sage/combinat/triangles_FHM.py +777 -0
- sage/combinat/tutorial.py +1857 -0
- sage/combinat/vector_partition.py +337 -0
- sage/combinat/words/abstract_word.py +1722 -0
- sage/combinat/words/all.py +59 -0
- sage/combinat/words/alphabet.py +268 -0
- sage/combinat/words/finite_word.py +7201 -0
- sage/combinat/words/infinite_word.py +113 -0
- sage/combinat/words/lyndon_word.py +652 -0
- sage/combinat/words/morphic.py +351 -0
- sage/combinat/words/morphism.py +3878 -0
- sage/combinat/words/paths.py +2932 -0
- sage/combinat/words/shuffle_product.py +278 -0
- sage/combinat/words/suffix_trees.py +1873 -0
- sage/combinat/words/word.py +769 -0
- sage/combinat/words/word_char.cp314t-win_amd64.pyd +0 -0
- sage/combinat/words/word_char.pyx +847 -0
- sage/combinat/words/word_datatypes.cp314t-win_amd64.pyd +0 -0
- sage/combinat/words/word_datatypes.pxd +4 -0
- sage/combinat/words/word_datatypes.pyx +1067 -0
- sage/combinat/words/word_generators.py +2026 -0
- sage/combinat/words/word_infinite_datatypes.py +1218 -0
- sage/combinat/words/word_options.py +99 -0
- sage/combinat/words/words.py +2396 -0
- sage/data_structures/all__sagemath_combinat.py +1 -0
- sage/databases/all__sagemath_combinat.py +13 -0
- sage/databases/findstat.py +4897 -0
- sage/databases/oeis.py +2058 -0
- sage/databases/sloane.py +393 -0
- sage/dynamics/all__sagemath_combinat.py +14 -0
- sage/dynamics/cellular_automata/all.py +7 -0
- sage/dynamics/cellular_automata/catalog.py +34 -0
- sage/dynamics/cellular_automata/elementary.py +612 -0
- sage/dynamics/cellular_automata/glca.py +477 -0
- sage/dynamics/cellular_automata/solitons.py +1463 -0
- sage/dynamics/finite_dynamical_system.py +1249 -0
- sage/dynamics/finite_dynamical_system_catalog.py +382 -0
- sage/games/all.py +7 -0
- sage/games/hexad.py +704 -0
- sage/games/quantumino.py +591 -0
- sage/games/sudoku.py +889 -0
- sage/games/sudoku_backtrack.cp314t-win_amd64.pyd +0 -0
- sage/games/sudoku_backtrack.pyx +189 -0
- sage/groups/all__sagemath_combinat.py +1 -0
- sage/groups/indexed_free_group.py +489 -0
- sage/libs/all__sagemath_combinat.py +6 -0
- sage/libs/lrcalc/__init__.py +1 -0
- sage/libs/lrcalc/lrcalc.py +525 -0
- sage/libs/symmetrica/__init__.py +7 -0
- sage/libs/symmetrica/all.py +101 -0
- sage/libs/symmetrica/kostka.pxi +168 -0
- sage/libs/symmetrica/part.pxi +193 -0
- sage/libs/symmetrica/plet.pxi +42 -0
- sage/libs/symmetrica/sab.pxi +196 -0
- sage/libs/symmetrica/sb.pxi +332 -0
- sage/libs/symmetrica/sc.pxi +192 -0
- sage/libs/symmetrica/schur.pxi +956 -0
- sage/libs/symmetrica/symmetrica.cp314t-win_amd64.pyd +0 -0
- sage/libs/symmetrica/symmetrica.pxi +1172 -0
- sage/libs/symmetrica/symmetrica.pyx +39 -0
- sage/monoids/all.py +13 -0
- sage/monoids/automatic_semigroup.py +1054 -0
- sage/monoids/free_abelian_monoid.py +315 -0
- sage/monoids/free_abelian_monoid_element.cp314t-win_amd64.pyd +0 -0
- sage/monoids/free_abelian_monoid_element.pxd +16 -0
- sage/monoids/free_abelian_monoid_element.pyx +397 -0
- sage/monoids/free_monoid.py +335 -0
- sage/monoids/free_monoid_element.py +431 -0
- sage/monoids/hecke_monoid.py +65 -0
- sage/monoids/string_monoid.py +817 -0
- sage/monoids/string_monoid_element.py +547 -0
- sage/monoids/string_ops.py +143 -0
- sage/monoids/trace_monoid.py +972 -0
- sage/rings/all__sagemath_combinat.py +2 -0
- sage/sat/all.py +4 -0
- sage/sat/boolean_polynomials.py +405 -0
- sage/sat/converters/__init__.py +6 -0
- sage/sat/converters/anf2cnf.py +14 -0
- sage/sat/converters/polybori.py +611 -0
- sage/sat/solvers/__init__.py +5 -0
- sage/sat/solvers/cryptominisat.py +287 -0
- sage/sat/solvers/dimacs.py +783 -0
- sage/sat/solvers/picosat.py +228 -0
- sage/sat/solvers/sat_lp.py +156 -0
- sage/sat/solvers/satsolver.cp314t-win_amd64.pyd +0 -0
- sage/sat/solvers/satsolver.pxd +3 -0
- sage/sat/solvers/satsolver.pyx +405 -0
|
@@ -0,0 +1,2053 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
r"""
|
|
3
|
+
Skew partitions
|
|
4
|
+
|
|
5
|
+
A skew partition ``skp`` of size `n` is a pair of
|
|
6
|
+
partitions `[p_1, p_2]` where `p_1` is a
|
|
7
|
+
partition of the integer `n_1`, `p_2` is a
|
|
8
|
+
partition of the integer `n_2`, `p_2` is an inner
|
|
9
|
+
partition of `p_1`, and `n = n_1 - n_2`. We say
|
|
10
|
+
that `p_1` and `p_2` are respectively the *inner*
|
|
11
|
+
and *outer* partitions of ``skp``.
|
|
12
|
+
|
|
13
|
+
A skew partition can be depicted by a diagram made of rows of
|
|
14
|
+
cells, in the same way as a partition. Only the cells of the outer
|
|
15
|
+
partition `p_1` which are not in the inner partition
|
|
16
|
+
`p_2` appear in the picture. For example, this is the
|
|
17
|
+
diagram of the skew partition [[5,4,3,1],[3,3,1]].
|
|
18
|
+
|
|
19
|
+
::
|
|
20
|
+
|
|
21
|
+
sage: print(SkewPartition([[5,4,3,1],[3,3,1]]).diagram())
|
|
22
|
+
**
|
|
23
|
+
*
|
|
24
|
+
**
|
|
25
|
+
*
|
|
26
|
+
|
|
27
|
+
A skew partition can be *connected*, which can easily be described
|
|
28
|
+
in graphic terms: for each pair of consecutive rows, there are at
|
|
29
|
+
least two cells (one in each row) which have a common edge. This is
|
|
30
|
+
the diagram of the connected skew partition ``[[5,4,3,1],[3,1]]``::
|
|
31
|
+
|
|
32
|
+
sage: print(SkewPartition([[5,4,3,1],[3,1]]).diagram())
|
|
33
|
+
**
|
|
34
|
+
***
|
|
35
|
+
***
|
|
36
|
+
*
|
|
37
|
+
sage: SkewPartition([[5,4,3,1],[3,1]]).is_connected()
|
|
38
|
+
True
|
|
39
|
+
|
|
40
|
+
The first example of a skew partition is not a connected one.
|
|
41
|
+
|
|
42
|
+
Applying a reflection with respect to the main diagonal yields the
|
|
43
|
+
diagram of the *conjugate skew partition*, here
|
|
44
|
+
``[[4,3,3,2,1],[3,3,2]]``::
|
|
45
|
+
|
|
46
|
+
sage: SkewPartition([[5,4,3,1],[3,3,1]]).conjugate()
|
|
47
|
+
[4, 3, 3, 2, 1] / [3, 2, 2]
|
|
48
|
+
sage: print(SkewPartition([[5,4,3,1],[3,3,1]]).conjugate().diagram())
|
|
49
|
+
*
|
|
50
|
+
*
|
|
51
|
+
*
|
|
52
|
+
**
|
|
53
|
+
*
|
|
54
|
+
|
|
55
|
+
The *outer corners* of a skew partition are the corners of its
|
|
56
|
+
outer partition. The *inner corners* are the internal corners of
|
|
57
|
+
the outer partition when the inner partition is taken off. Shown
|
|
58
|
+
below are the coordinates of the inner and outer corners.
|
|
59
|
+
|
|
60
|
+
::
|
|
61
|
+
|
|
62
|
+
sage: SkewPartition([[5,4,3,1],[3,3,1]]).outer_corners()
|
|
63
|
+
[(0, 4), (1, 3), (2, 2), (3, 0)]
|
|
64
|
+
sage: SkewPartition([[5,4,3,1],[3,3,1]]).inner_corners()
|
|
65
|
+
[(0, 3), (2, 1), (3, 0)]
|
|
66
|
+
|
|
67
|
+
EXAMPLES:
|
|
68
|
+
|
|
69
|
+
There are 9 skew partitions of size 3, with no empty row nor empty
|
|
70
|
+
column::
|
|
71
|
+
|
|
72
|
+
sage: SkewPartitions(3).cardinality()
|
|
73
|
+
9
|
|
74
|
+
sage: SkewPartitions(3).list()
|
|
75
|
+
[[3] / [],
|
|
76
|
+
[2, 1] / [],
|
|
77
|
+
[3, 1] / [1],
|
|
78
|
+
[2, 2] / [1],
|
|
79
|
+
[3, 2] / [2],
|
|
80
|
+
[1, 1, 1] / [],
|
|
81
|
+
[2, 2, 1] / [1, 1],
|
|
82
|
+
[2, 1, 1] / [1],
|
|
83
|
+
[3, 2, 1] / [2, 1]]
|
|
84
|
+
|
|
85
|
+
There are 4 connected skew partitions of size 3::
|
|
86
|
+
|
|
87
|
+
sage: SkewPartitions(3, overlap=1).cardinality()
|
|
88
|
+
4
|
|
89
|
+
sage: SkewPartitions(3, overlap=1).list()
|
|
90
|
+
[[3] / [], [2, 1] / [], [2, 2] / [1], [1, 1, 1] / []]
|
|
91
|
+
|
|
92
|
+
This is the conjugate of the skew partition ``[[4,3,1], [2]]``
|
|
93
|
+
|
|
94
|
+
::
|
|
95
|
+
|
|
96
|
+
sage: SkewPartition([[4,3,1], [2]]).conjugate()
|
|
97
|
+
[3, 2, 2, 1] / [1, 1]
|
|
98
|
+
|
|
99
|
+
Geometrically, we just applied a reflection with respect to the main
|
|
100
|
+
diagonal on the diagram of the partition. Of course, this operation
|
|
101
|
+
is an involution::
|
|
102
|
+
|
|
103
|
+
sage: SkewPartition([[4,3,1],[2]]).conjugate().conjugate()
|
|
104
|
+
[4, 3, 1] / [2]
|
|
105
|
+
|
|
106
|
+
The :meth:`jacobi_trudi()` method computes the Jacobi-Trudi matrix. See
|
|
107
|
+
[Mac1995]_ for a definition and discussion.
|
|
108
|
+
|
|
109
|
+
::
|
|
110
|
+
|
|
111
|
+
sage: SkewPartition([[4,3,1],[2]]).jacobi_trudi() # needs sage.modules
|
|
112
|
+
[h[2] h[] 0]
|
|
113
|
+
[h[5] h[3] h[]]
|
|
114
|
+
[h[6] h[4] h[1]]
|
|
115
|
+
|
|
116
|
+
This example shows how to compute the corners of a skew partition.
|
|
117
|
+
|
|
118
|
+
::
|
|
119
|
+
|
|
120
|
+
sage: SkewPartition([[4,3,1],[2]]).inner_corners()
|
|
121
|
+
[(0, 2), (1, 0)]
|
|
122
|
+
sage: SkewPartition([[4,3,1],[2]]).outer_corners()
|
|
123
|
+
[(0, 3), (1, 2), (2, 0)]
|
|
124
|
+
|
|
125
|
+
AUTHORS:
|
|
126
|
+
|
|
127
|
+
- Mike Hansen: Initial version
|
|
128
|
+
- Travis Scrimshaw (2013-02-11): Factored out ``CombinatorialClass``
|
|
129
|
+
- Trevor K. Karn (2022-08-03): Add ``outside_corners``
|
|
130
|
+
"""
|
|
131
|
+
#*****************************************************************************
|
|
132
|
+
# Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
|
|
133
|
+
#
|
|
134
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
135
|
+
#
|
|
136
|
+
# This code is distributed in the hope that it will be useful,
|
|
137
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
138
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
139
|
+
# General Public License for more details.
|
|
140
|
+
#
|
|
141
|
+
# The full text of the GPL is available at:
|
|
142
|
+
#
|
|
143
|
+
# http://www.gnu.org/licenses/
|
|
144
|
+
#*****************************************************************************
|
|
145
|
+
|
|
146
|
+
from sage.structure.global_options import GlobalOptions
|
|
147
|
+
from sage.structure.parent import Parent
|
|
148
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
149
|
+
from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
|
|
150
|
+
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
|
|
151
|
+
|
|
152
|
+
from sage.rings.integer_ring import ZZ
|
|
153
|
+
from sage.rings.rational_field import QQ
|
|
154
|
+
from sage.sets.set import Set
|
|
155
|
+
from sage.misc.lazy_import import lazy_import
|
|
156
|
+
|
|
157
|
+
from sage.combinat.combinat import CombinatorialElement
|
|
158
|
+
from sage.combinat.partition import Partitions, _Partitions
|
|
159
|
+
from sage.combinat.tableau import Tableaux
|
|
160
|
+
from sage.combinat.composition import Compositions
|
|
161
|
+
|
|
162
|
+
lazy_import('sage.graphs.digraph', 'DiGraph')
|
|
163
|
+
lazy_import('sage.matrix.matrix_space', 'MatrixSpace')
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class SkewPartition(CombinatorialElement):
|
|
167
|
+
r"""
|
|
168
|
+
A skew partition.
|
|
169
|
+
|
|
170
|
+
A skew partition of shape `\lambda / \mu` is the Young diagram from the
|
|
171
|
+
partition `\lambda` and removing the partition `\mu` from the upper-left
|
|
172
|
+
corner in English convention.
|
|
173
|
+
"""
|
|
174
|
+
@staticmethod
|
|
175
|
+
def __classcall_private__(cls, skp):
|
|
176
|
+
"""
|
|
177
|
+
Return the skew partition object corresponding to ``skp``.
|
|
178
|
+
|
|
179
|
+
EXAMPLES::
|
|
180
|
+
|
|
181
|
+
sage: skp = SkewPartition([[3,2,1],[2,1]]); skp
|
|
182
|
+
[3, 2, 1] / [2, 1]
|
|
183
|
+
sage: skp.inner()
|
|
184
|
+
[2, 1]
|
|
185
|
+
sage: skp.outer()
|
|
186
|
+
[3, 2, 1]
|
|
187
|
+
"""
|
|
188
|
+
skp = [_Partitions(p) for p in skp]
|
|
189
|
+
if skp not in SkewPartitions():
|
|
190
|
+
raise ValueError("invalid skew partition: %s" % skp)
|
|
191
|
+
return SkewPartitions()(skp)
|
|
192
|
+
|
|
193
|
+
def __init__(self, parent, skp):
|
|
194
|
+
"""
|
|
195
|
+
TESTS::
|
|
196
|
+
|
|
197
|
+
sage: skp = SkewPartition([[3,2,1],[2,1]])
|
|
198
|
+
sage: TestSuite(skp).run()
|
|
199
|
+
"""
|
|
200
|
+
CombinatorialElement.__init__(self, parent,
|
|
201
|
+
[_Partitions(skp[0]), _Partitions(skp[1])])
|
|
202
|
+
|
|
203
|
+
def _repr_(self):
|
|
204
|
+
"""
|
|
205
|
+
Return a string representation of ``self``.
|
|
206
|
+
|
|
207
|
+
For more on the display options, see
|
|
208
|
+
:obj:`SkewPartitions.options`.
|
|
209
|
+
|
|
210
|
+
EXAMPLES::
|
|
211
|
+
|
|
212
|
+
sage: SkewPartition([[3,2,1],[2,1]])
|
|
213
|
+
[3, 2, 1] / [2, 1]
|
|
214
|
+
"""
|
|
215
|
+
return self.parent().options._dispatch(self, '_repr_', 'display')
|
|
216
|
+
|
|
217
|
+
def _repr_quotient(self):
|
|
218
|
+
"""
|
|
219
|
+
Return a string representation of ``self``.
|
|
220
|
+
|
|
221
|
+
EXAMPLES::
|
|
222
|
+
|
|
223
|
+
sage: print(SkewPartition([[3,2,1],[2,1]])._repr_quotient())
|
|
224
|
+
[3, 2, 1] / [2, 1]
|
|
225
|
+
"""
|
|
226
|
+
return "%s / %s" % (self[0], self[1])
|
|
227
|
+
|
|
228
|
+
def _repr_lists(self):
|
|
229
|
+
"""
|
|
230
|
+
Return a string representation of ``self`` as a pair of lists.
|
|
231
|
+
|
|
232
|
+
EXAMPLES::
|
|
233
|
+
|
|
234
|
+
sage: print(SkewPartition([[3,2,1],[2,1]])._repr_lists())
|
|
235
|
+
[[3, 2, 1], [2, 1]]
|
|
236
|
+
"""
|
|
237
|
+
return repr([list(r) for r in self])
|
|
238
|
+
|
|
239
|
+
def _latex_(self):
|
|
240
|
+
r"""
|
|
241
|
+
Return a `\LaTeX` representation of ``self``.
|
|
242
|
+
|
|
243
|
+
For more on the latex options, see
|
|
244
|
+
:obj:`SkewPartitions.options`.
|
|
245
|
+
|
|
246
|
+
EXAMPLES::
|
|
247
|
+
|
|
248
|
+
sage: s = SkewPartition([[5,4,3],[3,1,1]])
|
|
249
|
+
sage: latex(s)
|
|
250
|
+
{\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
|
|
251
|
+
\raisebox{-.6ex}{$\begin{array}[b]{*{5}c}\cline{4-5}
|
|
252
|
+
&&&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{2-5}
|
|
253
|
+
&\lr{\phantom{x}}&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{2-4}
|
|
254
|
+
&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{2-3}
|
|
255
|
+
\end{array}$}
|
|
256
|
+
}
|
|
257
|
+
"""
|
|
258
|
+
return self.parent().options._dispatch(self, '_latex_', 'latex')
|
|
259
|
+
|
|
260
|
+
def _latex_diagram(self):
|
|
261
|
+
r"""
|
|
262
|
+
Return a `\LaTeX` representation as a young diagram.
|
|
263
|
+
|
|
264
|
+
EXAMPLES::
|
|
265
|
+
|
|
266
|
+
sage: print(SkewPartition([[5,4,3],[3,1,1]])._latex_diagram())
|
|
267
|
+
{\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
|
|
268
|
+
\raisebox{-.6ex}{$\begin{array}[b]{*{5}c}\cline{4-5}
|
|
269
|
+
&&&\lr{\ast}&\lr{\ast}\\\cline{2-5}
|
|
270
|
+
&\lr{\ast}&\lr{\ast}&\lr{\ast}\\\cline{2-4}
|
|
271
|
+
&\lr{\ast}&\lr{\ast}\\\cline{2-3}
|
|
272
|
+
\end{array}$}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
TESTS:
|
|
276
|
+
|
|
277
|
+
Check that :issue:`34760` is fixed::
|
|
278
|
+
|
|
279
|
+
sage: print(SkewPartition([[],[]])._latex_diagram())
|
|
280
|
+
{\emptyset}
|
|
281
|
+
"""
|
|
282
|
+
if not any(self._list):
|
|
283
|
+
return "{\\emptyset}"
|
|
284
|
+
|
|
285
|
+
char = self.parent().options.latex_diagram_str
|
|
286
|
+
|
|
287
|
+
from sage.combinat.output import tex_from_array
|
|
288
|
+
arr = [[char]*row_size for row_size in self[0]]
|
|
289
|
+
for i, skew_size in enumerate(self[1]): # This is always smaller by containment
|
|
290
|
+
for j in range(skew_size):
|
|
291
|
+
arr[i][j] = None
|
|
292
|
+
return tex_from_array(arr)
|
|
293
|
+
|
|
294
|
+
def _latex_young_diagram(self):
|
|
295
|
+
r"""
|
|
296
|
+
Return a `\LaTeX` representation of ``self`` as a young diagram.
|
|
297
|
+
|
|
298
|
+
EXAMPLES::
|
|
299
|
+
|
|
300
|
+
sage: print(SkewPartition([[5,4,3],[3,1,1]])._latex_young_diagram())
|
|
301
|
+
{\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
|
|
302
|
+
\raisebox{-.6ex}{$\begin{array}[b]{*{5}c}\cline{4-5}
|
|
303
|
+
&&&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{2-5}
|
|
304
|
+
&\lr{\phantom{x}}&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{2-4}
|
|
305
|
+
&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{2-3}
|
|
306
|
+
\end{array}$}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
TESTS:
|
|
310
|
+
|
|
311
|
+
Check that :issue:`34760` is fixed::
|
|
312
|
+
|
|
313
|
+
sage: print(SkewPartition([[],[]])._latex_young_diagram())
|
|
314
|
+
{\emptyset}
|
|
315
|
+
"""
|
|
316
|
+
if not any(self._list):
|
|
317
|
+
return "{\\emptyset}"
|
|
318
|
+
|
|
319
|
+
from sage.combinat.output import tex_from_array
|
|
320
|
+
arr = [["\\phantom{x}"]*row_size for row_size in self[0]]
|
|
321
|
+
for i, skew_size in enumerate(self[1]): # This is always smaller by containment
|
|
322
|
+
for j in range(skew_size):
|
|
323
|
+
arr[i][j] = None
|
|
324
|
+
return tex_from_array(arr)
|
|
325
|
+
|
|
326
|
+
def _latex_marked(self):
|
|
327
|
+
r"""
|
|
328
|
+
Return a `\LaTeX` representation as a marked partition.
|
|
329
|
+
|
|
330
|
+
EXAMPLES::
|
|
331
|
+
|
|
332
|
+
sage: print(SkewPartition([[5,4,3],[3,1,1]])._latex_marked())
|
|
333
|
+
{\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
|
|
334
|
+
\raisebox{-.6ex}{$\begin{array}[b]{*{5}c}\cline{1-5}
|
|
335
|
+
\lr{X}&\lr{X}&\lr{X}&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{1-5}
|
|
336
|
+
\lr{X}&\lr{\phantom{x}}&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{1-4}
|
|
337
|
+
\lr{X}&\lr{\phantom{x}}&\lr{\phantom{x}}\\\cline{1-3}
|
|
338
|
+
\end{array}$}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
TESTS:
|
|
342
|
+
|
|
343
|
+
Check that :issue:`34760` is fixed::
|
|
344
|
+
|
|
345
|
+
sage: print(SkewPartition([[],[]])._latex_marked())
|
|
346
|
+
{\emptyset}
|
|
347
|
+
"""
|
|
348
|
+
if not any(self._list):
|
|
349
|
+
return "{\\emptyset}"
|
|
350
|
+
|
|
351
|
+
from sage.combinat.output import tex_from_array
|
|
352
|
+
char = self.parent().options.latex_marking_str
|
|
353
|
+
arr = [["\\phantom{x}"]*row_size for row_size in self[0]]
|
|
354
|
+
for i, skew_size in enumerate(self[1]): # This is always smaller by containment
|
|
355
|
+
for j in range(skew_size):
|
|
356
|
+
arr[i][j] = char
|
|
357
|
+
return tex_from_array(arr)
|
|
358
|
+
|
|
359
|
+
def __setstate__(self, state):
|
|
360
|
+
r"""
|
|
361
|
+
In order to maintain backwards compatibility and be able to unpickle
|
|
362
|
+
a old pickle from ``SkewPartition_class`` we have to override the
|
|
363
|
+
default ``__setstate__``.
|
|
364
|
+
|
|
365
|
+
EXAMPLES::
|
|
366
|
+
|
|
367
|
+
sage: loads(b'x\x9c\x85P\xcbN\xc2@\x14\r\x08>\x06\xf1\xfd~\xbb+.\x9a\xa8\xdf\xe0\xc2McJ\xba4\x93i\xb9v&\xb4\x03w\x1e!,Ht!\xfe\xb6Sh1\xb0qw\xce}\x9c{\xee\xf9\xac\'\x9a\xa5\xe0\'\x83<\x16\x92\x19_\xf7aD\x87L\x19a\xc4@\x92\xae\xa3o\x15\xa3I\xc6\xb4&X\xeb|a}\x82k^\xd4\xa4\x9ci\x8e\x8d\xc0\xa1Lh\x83\xcdw\\\xf7\xe6\x92\xda(\x9b\x18\xab\xc0\xef\x8d%\xcbER\xae/3\xdc\xf0\xa2\x87\xc5\x05MY\x96\xd1\x910\x9c&\xcc@:Pc\x1f2\xc8A\x9a\xf9<n\xae\xf8\xfd\xb3\xba\x10!\xb8\x95P\x1a[\x91\x19!)%)\x18f\x8c"HV\x8dY)\xd0\x02U0T\xa0\xdd\r6[\xb7RA\xcf&@\xb0U\x1e\x9b[\x11\xa0}!?\x84\x14\x06(H\x9b\x83r\x8d\x1e\xd5`4y-\x1b/\x8bz\xb7(\xe3vg\xf2\x83\xed\x10w\xa2\xf6\xf2#\xbb\xd3\x10\xf7\xa6\xb8\x1f\x04\x81\t\xf1\xc0Ez\xc8[\xff?7K\x88\xe0Q!{\x1c\xe2\xc9\x04O=\xde\x08\xb8\x0b\xfe\xac\x0c^\t\x99\x16N\x9diP$g}\xa0\x15\xc1\xf3\xa8\xf6\xfc\x1d\xe2\x05w\xe0\xc9\x81\xcb\x02<:p\x05v\x1a\xf3\xc2\xc65w\xa27\x95\xe8\xadWM\xdcU\xe0\xbe\x18\x05\x1b\xfb\xbf\x8e\x7f\xcc\xbb')
|
|
368
|
+
[3, 2, 1] / [1, 1]
|
|
369
|
+
sage: loads(dumps( SkewPartition([[3,2,1], [1,1]]) ))
|
|
370
|
+
[3, 2, 1] / [1, 1]
|
|
371
|
+
"""
|
|
372
|
+
if isinstance(state, dict): # for old pickles from SkewPartition_class
|
|
373
|
+
self._set_parent(SkewPartitions())
|
|
374
|
+
self.__dict__ = state
|
|
375
|
+
else:
|
|
376
|
+
self._set_parent(state[0])
|
|
377
|
+
self.__dict__ = state[1]
|
|
378
|
+
|
|
379
|
+
def ferrers_diagram(self):
|
|
380
|
+
"""
|
|
381
|
+
Return the Ferrers diagram of ``self``.
|
|
382
|
+
|
|
383
|
+
EXAMPLES::
|
|
384
|
+
|
|
385
|
+
sage: print(SkewPartition([[5,4,3,1],[3,3,1]]).ferrers_diagram())
|
|
386
|
+
**
|
|
387
|
+
*
|
|
388
|
+
**
|
|
389
|
+
*
|
|
390
|
+
sage: print(SkewPartition([[5,4,3,1],[3,1]]).diagram())
|
|
391
|
+
**
|
|
392
|
+
***
|
|
393
|
+
***
|
|
394
|
+
*
|
|
395
|
+
sage: SkewPartitions.options(diagram_str='#', convention='French')
|
|
396
|
+
sage: print(SkewPartition([[5,4,3,1],[3,1]]).diagram())
|
|
397
|
+
#
|
|
398
|
+
###
|
|
399
|
+
###
|
|
400
|
+
##
|
|
401
|
+
sage: SkewPartitions.options._reset()
|
|
402
|
+
"""
|
|
403
|
+
char, convention = self.parent().options('diagram_str', 'convention')
|
|
404
|
+
|
|
405
|
+
if convention == "English":
|
|
406
|
+
L = range(len(self[0]))
|
|
407
|
+
else:
|
|
408
|
+
L = reversed(range(len(self[0])))
|
|
409
|
+
s = ""
|
|
410
|
+
for i in L:
|
|
411
|
+
if len(self[1]) > i:
|
|
412
|
+
s += " "*self[1][i]
|
|
413
|
+
s += char*(self[0][i]-self[1][i])
|
|
414
|
+
else:
|
|
415
|
+
s += char*self[0][i]
|
|
416
|
+
s += "\n"
|
|
417
|
+
return s[:-1]
|
|
418
|
+
|
|
419
|
+
diagram = ferrers_diagram
|
|
420
|
+
_repr_diagram = ferrers_diagram
|
|
421
|
+
|
|
422
|
+
def pp(self):
|
|
423
|
+
"""
|
|
424
|
+
Pretty-print ``self``.
|
|
425
|
+
|
|
426
|
+
EXAMPLES::
|
|
427
|
+
|
|
428
|
+
sage: SkewPartition([[5,4,3,1],[3,3,1]]).pp()
|
|
429
|
+
**
|
|
430
|
+
*
|
|
431
|
+
**
|
|
432
|
+
*
|
|
433
|
+
"""
|
|
434
|
+
print(self.ferrers_diagram())
|
|
435
|
+
|
|
436
|
+
def _ascii_art_(self):
|
|
437
|
+
"""
|
|
438
|
+
TESTS::
|
|
439
|
+
|
|
440
|
+
sage: ascii_art(SkewPartitions(3).list())
|
|
441
|
+
[ * * * * ]
|
|
442
|
+
[ ** ** * * * * * * ]
|
|
443
|
+
[ ***, * , * , **, ** , *, * , * , * ]
|
|
444
|
+
sage: SkewPartitions.options(diagram_str='#', convention='French')
|
|
445
|
+
sage: ascii_art(SkewPartitions(3).list())
|
|
446
|
+
[ # # # # ]
|
|
447
|
+
[ # # ## ## # # # # ]
|
|
448
|
+
[ ###, ##, ##, #, #, #, #, #, # ]
|
|
449
|
+
sage: SkewPartitions.options._reset()
|
|
450
|
+
"""
|
|
451
|
+
from sage.typeset.ascii_art import AsciiArt
|
|
452
|
+
return AsciiArt(self.diagram().splitlines())
|
|
453
|
+
|
|
454
|
+
def _unicode_art_(self):
|
|
455
|
+
"""
|
|
456
|
+
.. WARNING::
|
|
457
|
+
|
|
458
|
+
not working in presence of empty lines
|
|
459
|
+
|
|
460
|
+
TESTS::
|
|
461
|
+
|
|
462
|
+
sage: unicode_art(SkewPartitions(3).list())
|
|
463
|
+
⎡ ┌┐ ┌┐ ┌┐ ┌┐ ⎤
|
|
464
|
+
⎢ ┌┬┐ ┌┬┐ ┌┐ ┌┐ ├┤ ├┤ ┌┼┘ ┌┼┘ ⎥
|
|
465
|
+
⎢ ┌┬┬┐ ├┼┘ ┌┼┴┘ ┌┼┤ ┌┬┼┘ ├┤ ┌┼┘ ├┤ ┌┼┘ ⎥
|
|
466
|
+
⎣ └┴┴┘, └┘ , └┘ , └┴┘, └┴┘ , └┘, └┘ , └┘ , └┘ ⎦
|
|
467
|
+
sage: SkewPartitions.options.convention = "French"
|
|
468
|
+
sage: unicode_art(SkewPartitions(3).list())
|
|
469
|
+
⎡ ┌┐ ┌┐ ┌┐ ┌┐ ⎤
|
|
470
|
+
⎢ ┌┐ ┌┐ ┌┬┐ ┌┬┐ ├┤ └┼┐ ├┤ └┼┐ ⎥
|
|
471
|
+
⎢ ┌┬┬┐ ├┼┐ └┼┬┐ └┼┤ └┴┼┐ ├┤ ├┤ └┼┐ └┼┐ ⎥
|
|
472
|
+
⎣ └┴┴┘, └┴┘, └┴┘, └┘, └┘, └┘, └┘, └┘, └┘ ⎦
|
|
473
|
+
sage: SkewPartitions.options._reset()
|
|
474
|
+
|
|
475
|
+
sage: unicode_art(SkewPartition([[3,1],[2]]))
|
|
476
|
+
┌┐
|
|
477
|
+
┌┬┴┘
|
|
478
|
+
└┘
|
|
479
|
+
|
|
480
|
+
TESTS::
|
|
481
|
+
|
|
482
|
+
sage: unicode_art(SkewPartition([[],[]]))
|
|
483
|
+
∅
|
|
484
|
+
"""
|
|
485
|
+
from sage.typeset.unicode_art import UnicodeArt
|
|
486
|
+
out, inn = self
|
|
487
|
+
inn = inn + [0] * (len(out) - len(inn))
|
|
488
|
+
if not any(self._list):
|
|
489
|
+
return UnicodeArt('∅')
|
|
490
|
+
if self.parent().options.convention == "French":
|
|
491
|
+
s, t, b, l, r, tr, tl, br, bl, x, h = list(' ┴┬├┤┘└┐┌┼─')
|
|
492
|
+
else:
|
|
493
|
+
s, t, b, l, r, tr, tl, br, bl, x, h = list(' ┬┴├┤┐┌┘└┼─')
|
|
494
|
+
|
|
495
|
+
# working with English conventions
|
|
496
|
+
txt = [s * inn[0] + tl + t * (out[0] - inn[0] - 1) + tr]
|
|
497
|
+
for i in range(len(out) - 1):
|
|
498
|
+
o0 = out[i]
|
|
499
|
+
o1 = out[i + 1]
|
|
500
|
+
i0 = inn[i]
|
|
501
|
+
i1 = inn[i + 1]
|
|
502
|
+
|
|
503
|
+
if i0 == i1:
|
|
504
|
+
start = ' ' * i1 + l
|
|
505
|
+
d0 = 1
|
|
506
|
+
else:
|
|
507
|
+
start = ' ' * i1 + tl
|
|
508
|
+
d0 = 0
|
|
509
|
+
|
|
510
|
+
if o0 == o1:
|
|
511
|
+
end = r
|
|
512
|
+
d1 = 1
|
|
513
|
+
else:
|
|
514
|
+
end = br
|
|
515
|
+
d1 = 0
|
|
516
|
+
|
|
517
|
+
if i0 <= o1:
|
|
518
|
+
middle = t * (i0 - i1 - 1 + d0)
|
|
519
|
+
middle += x * (o1 - i0 + 1 - d0 - d1)
|
|
520
|
+
middle += b * (o0 - o1 - 1 + d1)
|
|
521
|
+
else:
|
|
522
|
+
middle = t * (i0 - i1 - 1)
|
|
523
|
+
middle += h * (i0 - o1 - 1)
|
|
524
|
+
middle += b * (o0 - o1 - 1)
|
|
525
|
+
|
|
526
|
+
txt += [start + middle + end]
|
|
527
|
+
txt += [s * inn[-1] + bl + b * (out[-1] - inn[-1] - 1) + br]
|
|
528
|
+
|
|
529
|
+
if self.parent().options.convention == "French":
|
|
530
|
+
txt = list(reversed(txt))
|
|
531
|
+
return UnicodeArt(txt, baseline=0)
|
|
532
|
+
|
|
533
|
+
def inner(self):
|
|
534
|
+
"""
|
|
535
|
+
Return the inner partition of ``self``.
|
|
536
|
+
|
|
537
|
+
EXAMPLES::
|
|
538
|
+
|
|
539
|
+
sage: SkewPartition([[3,2,1],[1,1]]).inner()
|
|
540
|
+
[1, 1]
|
|
541
|
+
"""
|
|
542
|
+
return self[1]
|
|
543
|
+
|
|
544
|
+
def outer(self):
|
|
545
|
+
"""
|
|
546
|
+
Return the outer partition of ``self``.
|
|
547
|
+
|
|
548
|
+
EXAMPLES::
|
|
549
|
+
|
|
550
|
+
sage: SkewPartition([[3,2,1],[1,1]]).outer()
|
|
551
|
+
[3, 2, 1]
|
|
552
|
+
"""
|
|
553
|
+
return self[0]
|
|
554
|
+
|
|
555
|
+
def column_lengths(self):
|
|
556
|
+
"""
|
|
557
|
+
Return the column lengths of ``self``.
|
|
558
|
+
|
|
559
|
+
EXAMPLES::
|
|
560
|
+
|
|
561
|
+
sage: SkewPartition([[3,2,1],[1,1]]).column_lengths()
|
|
562
|
+
[1, 2, 1]
|
|
563
|
+
sage: SkewPartition([[5,2,2,2],[2,1]]).column_lengths()
|
|
564
|
+
[2, 3, 1, 1, 1]
|
|
565
|
+
"""
|
|
566
|
+
return self.conjugate().row_lengths()
|
|
567
|
+
|
|
568
|
+
def row_lengths(self):
|
|
569
|
+
"""
|
|
570
|
+
Return the row lengths of ``self``.
|
|
571
|
+
|
|
572
|
+
EXAMPLES::
|
|
573
|
+
|
|
574
|
+
sage: SkewPartition([[3,2,1],[1,1]]).row_lengths()
|
|
575
|
+
[2, 1, 1]
|
|
576
|
+
"""
|
|
577
|
+
skp = self
|
|
578
|
+
o = skp[0]
|
|
579
|
+
i = skp[1]+[0]*(len(skp[0])-len(skp[1]))
|
|
580
|
+
return [x[0]-x[1] for x in zip(o,i)]
|
|
581
|
+
|
|
582
|
+
def size(self):
|
|
583
|
+
"""
|
|
584
|
+
Return the size of ``self``.
|
|
585
|
+
|
|
586
|
+
EXAMPLES::
|
|
587
|
+
|
|
588
|
+
sage: SkewPartition([[3,2,1],[1,1]]).size()
|
|
589
|
+
4
|
|
590
|
+
"""
|
|
591
|
+
return sum(self.row_lengths())
|
|
592
|
+
|
|
593
|
+
def is_connected(self):
|
|
594
|
+
"""
|
|
595
|
+
Return ``True`` if ``self`` is a connected skew partition.
|
|
596
|
+
|
|
597
|
+
A skew partition is said to be *connected* if for each pair of
|
|
598
|
+
consecutive rows, there are at least two cells (one in each row)
|
|
599
|
+
which have a common edge.
|
|
600
|
+
|
|
601
|
+
EXAMPLES::
|
|
602
|
+
|
|
603
|
+
sage: SkewPartition([[5,4,3,1],[3,3,1]]).is_connected()
|
|
604
|
+
False
|
|
605
|
+
sage: SkewPartition([[5,4,3,1],[3,1]]).is_connected()
|
|
606
|
+
True
|
|
607
|
+
"""
|
|
608
|
+
return self.is_overlap(1)
|
|
609
|
+
|
|
610
|
+
def overlap(self):
|
|
611
|
+
"""
|
|
612
|
+
Return the overlap of ``self``.
|
|
613
|
+
|
|
614
|
+
The overlap of two consecutive rows in a skew partition is the
|
|
615
|
+
number of pairs of cells (one in each row) that share a common
|
|
616
|
+
edge. This number can be positive, zero, or negative.
|
|
617
|
+
|
|
618
|
+
The overlap of a skew partition is the minimum of the overlap of
|
|
619
|
+
the consecutive rows, or infinity in the case of at most one row.
|
|
620
|
+
If the overlap is positive, then the skew partition is called
|
|
621
|
+
*connected*.
|
|
622
|
+
|
|
623
|
+
EXAMPLES::
|
|
624
|
+
|
|
625
|
+
sage: SkewPartition([[],[]]).overlap()
|
|
626
|
+
+Infinity
|
|
627
|
+
sage: SkewPartition([[1],[]]).overlap()
|
|
628
|
+
+Infinity
|
|
629
|
+
sage: SkewPartition([[10],[]]).overlap()
|
|
630
|
+
+Infinity
|
|
631
|
+
sage: SkewPartition([[10],[2]]).overlap()
|
|
632
|
+
+Infinity
|
|
633
|
+
sage: SkewPartition([[10,1],[2]]).overlap()
|
|
634
|
+
-1
|
|
635
|
+
sage: SkewPartition([[10,10],[1]]).overlap()
|
|
636
|
+
9
|
|
637
|
+
"""
|
|
638
|
+
p,q = self
|
|
639
|
+
if len(p) <= 1:
|
|
640
|
+
from sage.rings.infinity import PlusInfinity
|
|
641
|
+
return PlusInfinity()
|
|
642
|
+
if len(q) == 0:
|
|
643
|
+
return min(p)
|
|
644
|
+
q = [q[0]] + list(q)
|
|
645
|
+
return min(row_lengths_aux([p,q]))
|
|
646
|
+
|
|
647
|
+
def is_overlap(self, n):
|
|
648
|
+
r"""
|
|
649
|
+
Return ``True`` if the overlap of ``self`` is at most ``n``.
|
|
650
|
+
|
|
651
|
+
.. SEEALSO::
|
|
652
|
+
|
|
653
|
+
:meth:`overlap`
|
|
654
|
+
|
|
655
|
+
EXAMPLES::
|
|
656
|
+
|
|
657
|
+
sage: SkewPartition([[5,4,3,1],[3,1]]).is_overlap(1)
|
|
658
|
+
True
|
|
659
|
+
"""
|
|
660
|
+
return n <= self.overlap()
|
|
661
|
+
|
|
662
|
+
def is_ribbon(self):
|
|
663
|
+
r"""
|
|
664
|
+
Return ``True`` if and only if ``self`` is a ribbon.
|
|
665
|
+
|
|
666
|
+
This means that if it has exactly one cell in each of `q`
|
|
667
|
+
consecutive diagonals for some nonnegative integer `q`.
|
|
668
|
+
|
|
669
|
+
EXAMPLES::
|
|
670
|
+
|
|
671
|
+
sage: P = SkewPartition([[4,4,3,3],[3,2,2]])
|
|
672
|
+
sage: P.pp()
|
|
673
|
+
*
|
|
674
|
+
**
|
|
675
|
+
*
|
|
676
|
+
***
|
|
677
|
+
sage: P.is_ribbon()
|
|
678
|
+
True
|
|
679
|
+
|
|
680
|
+
sage: P = SkewPartition([[4,3,3],[1,1]])
|
|
681
|
+
sage: P.pp()
|
|
682
|
+
***
|
|
683
|
+
**
|
|
684
|
+
***
|
|
685
|
+
sage: P.is_ribbon()
|
|
686
|
+
False
|
|
687
|
+
|
|
688
|
+
sage: P = SkewPartition([[4,4,3,2],[3,2,2]])
|
|
689
|
+
sage: P.pp()
|
|
690
|
+
*
|
|
691
|
+
**
|
|
692
|
+
*
|
|
693
|
+
**
|
|
694
|
+
sage: P.is_ribbon()
|
|
695
|
+
False
|
|
696
|
+
|
|
697
|
+
sage: P = SkewPartition([[4,4,3,3],[4,2,2,1]])
|
|
698
|
+
sage: P.pp()
|
|
699
|
+
<BLANKLINE>
|
|
700
|
+
**
|
|
701
|
+
*
|
|
702
|
+
**
|
|
703
|
+
sage: P.is_ribbon()
|
|
704
|
+
True
|
|
705
|
+
|
|
706
|
+
sage: P = SkewPartition([[4,4,3,3],[4,2,2]])
|
|
707
|
+
sage: P.pp()
|
|
708
|
+
<BLANKLINE>
|
|
709
|
+
**
|
|
710
|
+
*
|
|
711
|
+
***
|
|
712
|
+
sage: P.is_ribbon()
|
|
713
|
+
True
|
|
714
|
+
|
|
715
|
+
sage: SkewPartition([[2,2,1],[2,2,1]]).is_ribbon()
|
|
716
|
+
True
|
|
717
|
+
"""
|
|
718
|
+
lam = self[0]
|
|
719
|
+
mu = self[1]
|
|
720
|
+
l_out = len(lam)
|
|
721
|
+
l_in = len(mu)
|
|
722
|
+
mu += [0]*(l_out-l_in)
|
|
723
|
+
|
|
724
|
+
if l_out == 0:
|
|
725
|
+
return True
|
|
726
|
+
else:
|
|
727
|
+
# Find the least u for which lam[u]>mu[u], if it exists
|
|
728
|
+
# If it does not exist then u will equal l_out
|
|
729
|
+
u = 0
|
|
730
|
+
u_test = True
|
|
731
|
+
while u_test:
|
|
732
|
+
if u >= l_out or lam[u] > mu[u]:
|
|
733
|
+
u_test = False
|
|
734
|
+
else:
|
|
735
|
+
u += 1
|
|
736
|
+
|
|
737
|
+
# Find the least v strictly greater than u for which
|
|
738
|
+
# lam[v] != mu[v-1]+1
|
|
739
|
+
v = u + 1
|
|
740
|
+
v_test = True
|
|
741
|
+
while v_test:
|
|
742
|
+
if v >= l_out or lam[v] != mu[v-1] + 1:
|
|
743
|
+
v_test = False
|
|
744
|
+
else:
|
|
745
|
+
v += 1
|
|
746
|
+
|
|
747
|
+
# Check if lam[i]==mu[i] for all i >= v
|
|
748
|
+
for i in range(v, l_out):
|
|
749
|
+
if lam[i] != mu[i]:
|
|
750
|
+
return False
|
|
751
|
+
|
|
752
|
+
return True
|
|
753
|
+
|
|
754
|
+
def conjugate(self):
|
|
755
|
+
"""
|
|
756
|
+
Return the conjugate of the skew partition skp.
|
|
757
|
+
|
|
758
|
+
EXAMPLES::
|
|
759
|
+
|
|
760
|
+
sage: SkewPartition([[3,2,1],[2]]).conjugate()
|
|
761
|
+
[3, 2, 1] / [1, 1]
|
|
762
|
+
"""
|
|
763
|
+
return SkewPartition([x.conjugate() for x in self])
|
|
764
|
+
|
|
765
|
+
def outer_corners(self):
|
|
766
|
+
"""
|
|
767
|
+
Return a list of the outer corners of ``self``.
|
|
768
|
+
|
|
769
|
+
These are corners that are contained inside of the shape.
|
|
770
|
+
For the corners which are outside of the shape,
|
|
771
|
+
use :meth:`outside_corners`.
|
|
772
|
+
|
|
773
|
+
.. WARNING::
|
|
774
|
+
|
|
775
|
+
In the case that ``self`` is an honest (rather than skew) partition,
|
|
776
|
+
these are the :meth:`~sage.combinat.partition.Partition.corners`
|
|
777
|
+
of the outer partition. In the language of [Sag2001]_ these would
|
|
778
|
+
be the "inner corners" of the outer partition.
|
|
779
|
+
|
|
780
|
+
.. SEEALSO::
|
|
781
|
+
|
|
782
|
+
- :meth:`sage.combinat.skew_partition.SkewPartition.outside_corners`
|
|
783
|
+
- :meth:`sage.combinat.partition.Partition.outside_corners`
|
|
784
|
+
|
|
785
|
+
EXAMPLES::
|
|
786
|
+
|
|
787
|
+
sage: SkewPartition([[4, 3, 1], [2]]).outer_corners()
|
|
788
|
+
[(0, 3), (1, 2), (2, 0)]
|
|
789
|
+
"""
|
|
790
|
+
return self.outer().corners()
|
|
791
|
+
|
|
792
|
+
def inner_corners(self):
|
|
793
|
+
"""
|
|
794
|
+
Return a list of the inner corners of ``self``.
|
|
795
|
+
|
|
796
|
+
EXAMPLES::
|
|
797
|
+
|
|
798
|
+
sage: SkewPartition([[4, 3, 1], [2]]).inner_corners()
|
|
799
|
+
[(0, 2), (1, 0)]
|
|
800
|
+
sage: SkewPartition([[4, 3, 1], []]).inner_corners()
|
|
801
|
+
[(0, 0)]
|
|
802
|
+
"""
|
|
803
|
+
inner = self.inner()
|
|
804
|
+
outer = self.outer()
|
|
805
|
+
if inner == []:
|
|
806
|
+
if outer == []:
|
|
807
|
+
return []
|
|
808
|
+
else:
|
|
809
|
+
return [(0,0)]
|
|
810
|
+
icorners = [(0, inner[0])]
|
|
811
|
+
nn = len(inner)
|
|
812
|
+
for i in range(1,nn):
|
|
813
|
+
if inner[i] != inner[i-1]:
|
|
814
|
+
icorners += [ (i, inner[i]) ]
|
|
815
|
+
|
|
816
|
+
icorners += [(nn, 0)]
|
|
817
|
+
return icorners
|
|
818
|
+
|
|
819
|
+
def cell_poset(self, orientation='SE'):
|
|
820
|
+
"""
|
|
821
|
+
Return the Young diagram of ``self`` as a poset. The optional
|
|
822
|
+
keyword variable ``orientation`` determines the order relation
|
|
823
|
+
of the poset.
|
|
824
|
+
|
|
825
|
+
The poset always uses the set of cells of the Young diagram
|
|
826
|
+
of ``self`` as its ground set. The order relation of the poset
|
|
827
|
+
depends on the ``orientation`` variable (which defaults to
|
|
828
|
+
``'SE'``). Concretely, ``orientation`` has to be specified to
|
|
829
|
+
one of the strings ``'NW'``, ``'NE'``, ``'SW'``, and ``'SE'``,
|
|
830
|
+
standing for "northwest", "northeast", "southwest" and
|
|
831
|
+
"southeast", respectively. If ``orientation`` is ``'SE'``, then
|
|
832
|
+
the order relation of the poset is such that a cell `u` is
|
|
833
|
+
greater or equal to a cell `v` in the poset if and only if `u`
|
|
834
|
+
lies weakly southeast of `v` (this means that `u` can be
|
|
835
|
+
reached from `v` by a sequence of south and east steps; the
|
|
836
|
+
sequence is allowed to consist of south steps only, or of east
|
|
837
|
+
steps only, or even be empty). Similarly the order relation is
|
|
838
|
+
defined for the other three orientations. The Young diagram is
|
|
839
|
+
supposed to be drawn in English notation.
|
|
840
|
+
|
|
841
|
+
The elements of the poset are the cells of the Young diagram
|
|
842
|
+
of ``self``, written as tuples of zero-based coordinates (so
|
|
843
|
+
that `(3, 7)` stands for the `8`-th cell of the `4`-th row,
|
|
844
|
+
etc.).
|
|
845
|
+
|
|
846
|
+
EXAMPLES::
|
|
847
|
+
|
|
848
|
+
sage: # needs sage.graphs
|
|
849
|
+
sage: p = SkewPartition([[3,3,1], [2,1]])
|
|
850
|
+
sage: Q = p.cell_poset(); Q
|
|
851
|
+
Finite poset containing 4 elements
|
|
852
|
+
sage: sorted(Q)
|
|
853
|
+
[(0, 2), (1, 1), (1, 2), (2, 0)]
|
|
854
|
+
sage: sorted(Q.maximal_elements())
|
|
855
|
+
[(1, 2), (2, 0)]
|
|
856
|
+
sage: sorted(Q.minimal_elements())
|
|
857
|
+
[(0, 2), (1, 1), (2, 0)]
|
|
858
|
+
sage: sorted(Q.upper_covers((1, 1)))
|
|
859
|
+
[(1, 2)]
|
|
860
|
+
sage: sorted(Q.upper_covers((0, 2)))
|
|
861
|
+
[(1, 2)]
|
|
862
|
+
|
|
863
|
+
sage: # needs sage.graphs
|
|
864
|
+
sage: P = p.cell_poset(orientation="NW"); P
|
|
865
|
+
Finite poset containing 4 elements
|
|
866
|
+
sage: sorted(P)
|
|
867
|
+
[(0, 2), (1, 1), (1, 2), (2, 0)]
|
|
868
|
+
sage: sorted(P.minimal_elements())
|
|
869
|
+
[(1, 2), (2, 0)]
|
|
870
|
+
sage: sorted(P.maximal_elements())
|
|
871
|
+
[(0, 2), (1, 1), (2, 0)]
|
|
872
|
+
sage: sorted(P.upper_covers((1, 2)))
|
|
873
|
+
[(0, 2), (1, 1)]
|
|
874
|
+
|
|
875
|
+
sage: # needs sage.graphs
|
|
876
|
+
sage: R = p.cell_poset(orientation="NE"); R
|
|
877
|
+
Finite poset containing 4 elements
|
|
878
|
+
sage: sorted(R)
|
|
879
|
+
[(0, 2), (1, 1), (1, 2), (2, 0)]
|
|
880
|
+
sage: R.maximal_elements()
|
|
881
|
+
[(0, 2)]
|
|
882
|
+
sage: R.minimal_elements()
|
|
883
|
+
[(2, 0)]
|
|
884
|
+
sage: R.upper_covers((2, 0))
|
|
885
|
+
[(1, 1)]
|
|
886
|
+
sage: sorted([len(R.upper_covers(v)) for v in R])
|
|
887
|
+
[0, 1, 1, 1]
|
|
888
|
+
|
|
889
|
+
TESTS:
|
|
890
|
+
|
|
891
|
+
We check that the posets are really what they should be for size
|
|
892
|
+
up to `6`::
|
|
893
|
+
|
|
894
|
+
sage: def check_NW(n):
|
|
895
|
+
....: for p in SkewPartitions(n):
|
|
896
|
+
....: P = p.cell_poset(orientation="NW")
|
|
897
|
+
....: for c in p.cells():
|
|
898
|
+
....: for d in p.cells():
|
|
899
|
+
....: if P.le(c, d) != (c[0] >= d[0]
|
|
900
|
+
....: and c[1] >= d[1]):
|
|
901
|
+
....: return False
|
|
902
|
+
....: return True
|
|
903
|
+
sage: all( check_NW(n) for n in range(7) ) # needs sage.graphs
|
|
904
|
+
True
|
|
905
|
+
|
|
906
|
+
sage: def check_NE(n):
|
|
907
|
+
....: for p in SkewPartitions(n):
|
|
908
|
+
....: P = p.cell_poset(orientation="NE")
|
|
909
|
+
....: for c in p.cells():
|
|
910
|
+
....: for d in p.cells():
|
|
911
|
+
....: if P.le(c, d) != (c[0] >= d[0]
|
|
912
|
+
....: and c[1] <= d[1]):
|
|
913
|
+
....: return False
|
|
914
|
+
....: return True
|
|
915
|
+
sage: all( check_NE(n) for n in range(7) ) # needs sage.graphs
|
|
916
|
+
True
|
|
917
|
+
|
|
918
|
+
sage: def test_duality(n, ori1, ori2):
|
|
919
|
+
....: for p in SkewPartitions(n):
|
|
920
|
+
....: P = p.cell_poset(orientation=ori1)
|
|
921
|
+
....: Q = p.cell_poset(orientation=ori2)
|
|
922
|
+
....: for c in p.cells():
|
|
923
|
+
....: for d in p.cells():
|
|
924
|
+
....: if P.lt(c, d) != Q.lt(d, c):
|
|
925
|
+
....: return False
|
|
926
|
+
....: return True
|
|
927
|
+
sage: all( test_duality(n, "NW", "SE") for n in range(7) ) # needs sage.graphs
|
|
928
|
+
True
|
|
929
|
+
sage: all( test_duality(n, "NE", "SW") for n in range(7) ) # needs sage.graphs
|
|
930
|
+
True
|
|
931
|
+
sage: all( test_duality(n, "NE", "SE") for n in range(4) ) # needs sage.graphs
|
|
932
|
+
False
|
|
933
|
+
"""
|
|
934
|
+
from sage.combinat.posets.posets import Poset
|
|
935
|
+
# Getting the cover relations seems hard, so let's just compute
|
|
936
|
+
# the comparison function.
|
|
937
|
+
if orientation == "NW":
|
|
938
|
+
def poset_le(u, v):
|
|
939
|
+
return u[0] >= v[0] and u[1] >= v[1]
|
|
940
|
+
elif orientation == "NE":
|
|
941
|
+
def poset_le(u, v):
|
|
942
|
+
return u[0] >= v[0] and u[1] <= v[1]
|
|
943
|
+
elif orientation == "SE":
|
|
944
|
+
def poset_le(u, v):
|
|
945
|
+
return u[0] <= v[0] and u[1] <= v[1]
|
|
946
|
+
elif orientation == "SW":
|
|
947
|
+
def poset_le(u, v):
|
|
948
|
+
return u[0] <= v[0] and u[1] >= v[1]
|
|
949
|
+
return Poset((self.cells(), poset_le))
|
|
950
|
+
|
|
951
|
+
def frobenius_rank(self):
|
|
952
|
+
r"""
|
|
953
|
+
Return the Frobenius rank of the skew partition ``self``.
|
|
954
|
+
|
|
955
|
+
The Frobenius rank of a skew partition `\lambda / \mu` can be
|
|
956
|
+
defined in various ways. The quickest one is probably the
|
|
957
|
+
following: Writing `\lambda` as
|
|
958
|
+
`(\lambda_1, \lambda_2, \cdots , \lambda_N)`, and writing `\mu`
|
|
959
|
+
as `(\mu_1, \mu_2, \cdots , \mu_N)`, we define the Frobenius
|
|
960
|
+
rank of `\lambda / \mu` to be the number of all
|
|
961
|
+
`1 \leq i \leq N` such that
|
|
962
|
+
|
|
963
|
+
.. MATH::
|
|
964
|
+
|
|
965
|
+
\lambda_i - i
|
|
966
|
+
\not\in \{ \mu_1 - 1, \mu_2 - 2, \cdots , \mu_N - N \}.
|
|
967
|
+
|
|
968
|
+
In other words, the Frobenius rank of `\lambda / \mu` is the
|
|
969
|
+
number of rows in the Jacobi-Trudi matrix of `\lambda / \mu`
|
|
970
|
+
which don't contain `h_0`. Further definitions have been
|
|
971
|
+
considered in [Sta2002]_ (where Frobenius rank is just being
|
|
972
|
+
called rank).
|
|
973
|
+
|
|
974
|
+
If `\mu` is the empty shape, then the Frobenius rank of
|
|
975
|
+
`\lambda / \mu` is just the usual Frobenius rank of the
|
|
976
|
+
partition `\lambda` (see
|
|
977
|
+
:meth:`~sage.combinat.partition.Partition.frobenius_rank()`).
|
|
978
|
+
|
|
979
|
+
EXAMPLES::
|
|
980
|
+
|
|
981
|
+
sage: SkewPartition([[8,8,7,4], [4,1,1]]).frobenius_rank()
|
|
982
|
+
4
|
|
983
|
+
sage: SkewPartition([[2,1], [1]]).frobenius_rank()
|
|
984
|
+
2
|
|
985
|
+
sage: SkewPartition([[2,1,1], [1]]).frobenius_rank()
|
|
986
|
+
2
|
|
987
|
+
sage: SkewPartition([[2,1,1], [1,1]]).frobenius_rank()
|
|
988
|
+
2
|
|
989
|
+
sage: SkewPartition([[5,4,3,2], [2,1,1]]).frobenius_rank()
|
|
990
|
+
3
|
|
991
|
+
sage: SkewPartition([[4,2,1], [3,1,1]]).frobenius_rank()
|
|
992
|
+
2
|
|
993
|
+
sage: SkewPartition([[4,2,1], [3,2,1]]).frobenius_rank()
|
|
994
|
+
1
|
|
995
|
+
|
|
996
|
+
If the inner shape is empty, then the Frobenius rank of the skew
|
|
997
|
+
partition is just the standard Frobenius rank of the partition::
|
|
998
|
+
|
|
999
|
+
sage: all( SkewPartition([lam, Partition([])]).frobenius_rank()
|
|
1000
|
+
....: == lam.frobenius_rank() for i in range(6)
|
|
1001
|
+
....: for lam in Partitions(i) )
|
|
1002
|
+
True
|
|
1003
|
+
|
|
1004
|
+
If the inner and outer shapes are equal, then the Frobenius rank
|
|
1005
|
+
is zero::
|
|
1006
|
+
|
|
1007
|
+
sage: all( SkewPartition([lam, lam]).frobenius_rank() == 0
|
|
1008
|
+
....: for i in range(6) for lam in Partitions(i) )
|
|
1009
|
+
True
|
|
1010
|
+
"""
|
|
1011
|
+
N = len(self[0])
|
|
1012
|
+
mu_betas = [x - j for j, x in enumerate(self[1])]
|
|
1013
|
+
mu_betas.extend(- j for j in range(len(self[1]), N))
|
|
1014
|
+
return sum(1 for i, x in enumerate(self[0])
|
|
1015
|
+
if (x - i) not in mu_betas)
|
|
1016
|
+
|
|
1017
|
+
def cells(self):
|
|
1018
|
+
"""
|
|
1019
|
+
Return the coordinates of the cells of ``self``. Coordinates are
|
|
1020
|
+
given as ``(row-index, column-index)`` and are 0 based.
|
|
1021
|
+
|
|
1022
|
+
EXAMPLES::
|
|
1023
|
+
|
|
1024
|
+
sage: SkewPartition([[4, 3, 1], [2]]).cells()
|
|
1025
|
+
[(0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (2, 0)]
|
|
1026
|
+
sage: SkewPartition([[4, 3, 1], []]).cells()
|
|
1027
|
+
[(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (2, 0)]
|
|
1028
|
+
sage: SkewPartition([[2], []]).cells()
|
|
1029
|
+
[(0, 0), (0, 1)]
|
|
1030
|
+
"""
|
|
1031
|
+
outer = self.outer()
|
|
1032
|
+
inner = self.inner()[:]
|
|
1033
|
+
inner += [0] * (len(outer) - len(inner))
|
|
1034
|
+
return [(i, j) for i, outi in enumerate(outer)
|
|
1035
|
+
for j in range(inner[i], outi)]
|
|
1036
|
+
|
|
1037
|
+
def to_list(self):
|
|
1038
|
+
"""
|
|
1039
|
+
Return ``self`` as a list of lists.
|
|
1040
|
+
|
|
1041
|
+
EXAMPLES::
|
|
1042
|
+
|
|
1043
|
+
sage: s = SkewPartition([[4,3,1],[2]])
|
|
1044
|
+
sage: s.to_list()
|
|
1045
|
+
[[4, 3, 1], [2]]
|
|
1046
|
+
sage: type(s.to_list())
|
|
1047
|
+
<class 'list'>
|
|
1048
|
+
"""
|
|
1049
|
+
return [list(r) for r in list(self)]
|
|
1050
|
+
|
|
1051
|
+
def to_dag(self, format='string'):
|
|
1052
|
+
"""
|
|
1053
|
+
Return a directed acyclic graph corresponding to the skew
|
|
1054
|
+
partition ``self``.
|
|
1055
|
+
|
|
1056
|
+
The directed acyclic graph corresponding to a skew partition
|
|
1057
|
+
`p` is the digraph whose vertices are the cells of `p`, and
|
|
1058
|
+
whose edges go from each cell to its lower and right
|
|
1059
|
+
neighbors (in English notation).
|
|
1060
|
+
|
|
1061
|
+
INPUT:
|
|
1062
|
+
|
|
1063
|
+
- ``format`` -- either ``'string'`` or ``'tuple'`` (default:
|
|
1064
|
+
``'string'``); determines whether the vertices of the
|
|
1065
|
+
resulting dag will be strings or 2-tuples of coordinates
|
|
1066
|
+
|
|
1067
|
+
EXAMPLES::
|
|
1068
|
+
|
|
1069
|
+
sage: # needs sage.graphs
|
|
1070
|
+
sage: dag = SkewPartition([[3, 3, 1], [1, 1]]).to_dag()
|
|
1071
|
+
sage: dag.edges(sort=True)
|
|
1072
|
+
[('0,1', '0,2', None),
|
|
1073
|
+
('0,1', '1,1', None),
|
|
1074
|
+
('0,2', '1,2', None),
|
|
1075
|
+
('1,1', '1,2', None)]
|
|
1076
|
+
sage: dag.vertices(sort=True)
|
|
1077
|
+
['0,1', '0,2', '1,1', '1,2', '2,0']
|
|
1078
|
+
sage: dag = SkewPartition([[3, 2, 1], [1, 1]]).to_dag(format='tuple')
|
|
1079
|
+
sage: dag.edges(sort=True)
|
|
1080
|
+
[((0, 1), (0, 2), None), ((0, 1), (1, 1), None)]
|
|
1081
|
+
sage: dag.vertices(sort=True)
|
|
1082
|
+
[(0, 1), (0, 2), (1, 1), (2, 0)]
|
|
1083
|
+
"""
|
|
1084
|
+
outer = list(self.outer())
|
|
1085
|
+
inner = list(self.inner())
|
|
1086
|
+
inner += [0] * (len(outer) - len(inner))
|
|
1087
|
+
|
|
1088
|
+
G = DiGraph()
|
|
1089
|
+
for i, outer_i in enumerate(outer):
|
|
1090
|
+
for j in range(inner[i], outer_i):
|
|
1091
|
+
if format == "string":
|
|
1092
|
+
string = "%d,%d" % (i, j)
|
|
1093
|
+
else:
|
|
1094
|
+
string = (i, j)
|
|
1095
|
+
G.add_vertex(string)
|
|
1096
|
+
#Check to see if there is a node to the right
|
|
1097
|
+
if j != outer_i - 1:
|
|
1098
|
+
if format == "string":
|
|
1099
|
+
newstring = "%d,%d" % (i, j + 1)
|
|
1100
|
+
else:
|
|
1101
|
+
newstring = (i, j + 1)
|
|
1102
|
+
G.add_edge(string, newstring)
|
|
1103
|
+
|
|
1104
|
+
#Check to see if there is anything below
|
|
1105
|
+
if i != len(outer) - 1:
|
|
1106
|
+
if outer[i+1] > j:
|
|
1107
|
+
if format == "string":
|
|
1108
|
+
newstring = "%d,%d" % (i + 1, j)
|
|
1109
|
+
else:
|
|
1110
|
+
newstring = (i + 1, j)
|
|
1111
|
+
G.add_edge(string, newstring)
|
|
1112
|
+
return G
|
|
1113
|
+
|
|
1114
|
+
def quotient(self, k):
|
|
1115
|
+
"""
|
|
1116
|
+
The quotient map extended to skew partitions.
|
|
1117
|
+
|
|
1118
|
+
EXAMPLES::
|
|
1119
|
+
|
|
1120
|
+
sage: SkewPartition([[3, 3, 2, 1], [2, 1]]).quotient(2)
|
|
1121
|
+
[[3] / [], [] / []]
|
|
1122
|
+
"""
|
|
1123
|
+
## k-th element is the skew partition built using the k-th partition of the
|
|
1124
|
+
## k-quotient of the outer and the inner partition.
|
|
1125
|
+
## This bijection is only defined if the inner and the outer partition
|
|
1126
|
+
## have the same core
|
|
1127
|
+
if self.inner().core(k) == self.outer().core(k):
|
|
1128
|
+
rqinner = self.inner().quotient(k)
|
|
1129
|
+
rqouter = self.outer().quotient(k)
|
|
1130
|
+
return [ SkewPartitions()([rqouter[i],rqinner[i]]) for i in range(k) ]
|
|
1131
|
+
else:
|
|
1132
|
+
raise ValueError("quotient map is only defined for skew partitions with inner and outer partitions having the same core")
|
|
1133
|
+
|
|
1134
|
+
def rows_intersection_set(self):
|
|
1135
|
+
r"""
|
|
1136
|
+
Return the set of cells in the rows of the outer shape of
|
|
1137
|
+
``self`` which rows intersect the skew diagram of ``self``.
|
|
1138
|
+
|
|
1139
|
+
EXAMPLES::
|
|
1140
|
+
|
|
1141
|
+
sage: skp = SkewPartition([[3,2,1],[2,1]])
|
|
1142
|
+
sage: cells = Set([ (0,0), (0, 1), (0,2), (1, 0), (1, 1), (2, 0)])
|
|
1143
|
+
sage: skp.rows_intersection_set() == cells
|
|
1144
|
+
True
|
|
1145
|
+
"""
|
|
1146
|
+
outer = self.outer()
|
|
1147
|
+
inner = self.inner()
|
|
1148
|
+
inner += [0] * (len(outer) - len(inner))
|
|
1149
|
+
|
|
1150
|
+
res = [(i, j) for i, outi in enumerate(outer)
|
|
1151
|
+
for j in range(outi)
|
|
1152
|
+
if outi != inner[i]]
|
|
1153
|
+
return Set(res)
|
|
1154
|
+
|
|
1155
|
+
def columns_intersection_set(self):
|
|
1156
|
+
"""
|
|
1157
|
+
Return the set of cells in the columns of the outer shape of
|
|
1158
|
+
``self`` which columns intersect the skew diagram of ``self``.
|
|
1159
|
+
|
|
1160
|
+
EXAMPLES::
|
|
1161
|
+
|
|
1162
|
+
sage: skp = SkewPartition([[3,2,1],[2,1]])
|
|
1163
|
+
sage: cells = Set([ (0,0), (0, 1), (0,2), (1, 0), (1, 1), (2, 0)])
|
|
1164
|
+
sage: skp.columns_intersection_set() == cells
|
|
1165
|
+
True
|
|
1166
|
+
"""
|
|
1167
|
+
res = [ (x[1], x[0]) for x in self.conjugate().rows_intersection_set()]
|
|
1168
|
+
return Set(res)
|
|
1169
|
+
|
|
1170
|
+
def pieri_macdonald_coeffs(self):
|
|
1171
|
+
"""
|
|
1172
|
+
Computation of the coefficients which appear in the Pieri formula
|
|
1173
|
+
for Macdonald polynomials given in his book ( Chapter 6.6 formula
|
|
1174
|
+
6.24(ii) )
|
|
1175
|
+
|
|
1176
|
+
EXAMPLES::
|
|
1177
|
+
|
|
1178
|
+
sage: SkewPartition([[3,2,1],[2,1]]).pieri_macdonald_coeffs()
|
|
1179
|
+
1
|
|
1180
|
+
sage: SkewPartition([[3,2,1],[2,2]]).pieri_macdonald_coeffs()
|
|
1181
|
+
(q^2*t^3 - q^2*t - t^2 + 1)/(q^2*t^3 - q*t^2 - q*t + 1)
|
|
1182
|
+
sage: SkewPartition([[3,2,1],[2,2,1]]).pieri_macdonald_coeffs()
|
|
1183
|
+
(q^6*t^8 - q^6*t^6 - q^4*t^7 - q^5*t^5 + q^4*t^5 - q^3*t^6 + q^5*t^3 + 2*q^3*t^4 + q*t^5 - q^3*t^2 + q^2*t^3 - q*t^3 - q^2*t - t^2 + 1)/(q^6*t^8 - q^5*t^7 - q^5*t^6 - q^4*t^6 + q^3*t^5 + 2*q^3*t^4 + q^3*t^3 - q^2*t^2 - q*t^2 - q*t + 1)
|
|
1184
|
+
sage: SkewPartition([[3,3,2,2],[3,2,2,1]]).pieri_macdonald_coeffs()
|
|
1185
|
+
(q^5*t^6 - q^5*t^5 + q^4*t^6 - q^4*t^5 - q^4*t^3 + q^4*t^2 - q^3*t^3 - q^2*t^4 + q^3*t^2 + q^2*t^3 - q*t^4 + q*t^3 + q*t - q + t - 1)/(q^5*t^6 - q^4*t^5 - q^3*t^4 - q^3*t^3 + q^2*t^3 + q^2*t^2 + q*t - 1)
|
|
1186
|
+
"""
|
|
1187
|
+
|
|
1188
|
+
set_prod = self.rows_intersection_set() - self.columns_intersection_set()
|
|
1189
|
+
res = 1
|
|
1190
|
+
for s in set_prod:
|
|
1191
|
+
res *= self.inner().arms_legs_coeff(s[0],s[1])
|
|
1192
|
+
res /= self.outer().arms_legs_coeff(s[0],s[1])
|
|
1193
|
+
return res
|
|
1194
|
+
|
|
1195
|
+
def k_conjugate(self, k):
|
|
1196
|
+
"""
|
|
1197
|
+
Return the `k`-conjugate of the skew partition.
|
|
1198
|
+
|
|
1199
|
+
EXAMPLES::
|
|
1200
|
+
|
|
1201
|
+
sage: SkewPartition([[3,2,1],[2,1]]).k_conjugate(3)
|
|
1202
|
+
[2, 1, 1, 1, 1] / [2, 1]
|
|
1203
|
+
sage: SkewPartition([[3,2,1],[2,1]]).k_conjugate(4)
|
|
1204
|
+
[2, 2, 1, 1] / [2, 1]
|
|
1205
|
+
sage: SkewPartition([[3,2,1],[2,1]]).k_conjugate(5)
|
|
1206
|
+
[3, 2, 1] / [2, 1]
|
|
1207
|
+
"""
|
|
1208
|
+
return SkewPartition([ self.outer().k_conjugate(k), self.inner().k_conjugate(k) ])
|
|
1209
|
+
|
|
1210
|
+
def jacobi_trudi(self):
|
|
1211
|
+
"""
|
|
1212
|
+
Return the Jacobi-Trudi matrix of ``self``.
|
|
1213
|
+
|
|
1214
|
+
EXAMPLES::
|
|
1215
|
+
|
|
1216
|
+
sage: SkewPartition([[3,2,1],[2,1]]).jacobi_trudi() # needs sage.modules
|
|
1217
|
+
[h[1] 0 0]
|
|
1218
|
+
[h[3] h[1] 0]
|
|
1219
|
+
[h[5] h[3] h[1]]
|
|
1220
|
+
sage: SkewPartition([[4,3,2],[2,1]]).jacobi_trudi() # needs sage.modules
|
|
1221
|
+
[h[2] h[] 0]
|
|
1222
|
+
[h[4] h[2] h[]]
|
|
1223
|
+
[h[6] h[4] h[2]]
|
|
1224
|
+
"""
|
|
1225
|
+
p = self.outer()
|
|
1226
|
+
q = self.inner()
|
|
1227
|
+
from sage.combinat.sf.sf import SymmetricFunctions
|
|
1228
|
+
nn = len(p)
|
|
1229
|
+
if nn == 0:
|
|
1230
|
+
return MatrixSpace(SymmetricFunctions(QQ).homogeneous(), 0)(0)
|
|
1231
|
+
h = SymmetricFunctions(QQ).homogeneous()
|
|
1232
|
+
H = MatrixSpace(h, nn)
|
|
1233
|
+
|
|
1234
|
+
q = q + [0] * (nn - len(q))
|
|
1235
|
+
m = []
|
|
1236
|
+
for i in range(1,nn+1):
|
|
1237
|
+
row = []
|
|
1238
|
+
for j in range(1,nn+1):
|
|
1239
|
+
v = p[j-1]-q[i-1]-j+i
|
|
1240
|
+
if v < 0:
|
|
1241
|
+
row.append(h.zero())
|
|
1242
|
+
elif v == 0:
|
|
1243
|
+
row.append(h([]))
|
|
1244
|
+
else:
|
|
1245
|
+
row.append(h([v]))
|
|
1246
|
+
m.append(row)
|
|
1247
|
+
return H(m)
|
|
1248
|
+
|
|
1249
|
+
def outside_corners(self):
|
|
1250
|
+
r"""
|
|
1251
|
+
Return the outside corners of ``self``.
|
|
1252
|
+
|
|
1253
|
+
The outside corners are corners which are outside of the shape. This
|
|
1254
|
+
should not be confused with :meth:`outer_corners` which consists of
|
|
1255
|
+
corners inside the shape. It returns a result analogous to the
|
|
1256
|
+
``.outside_corners()`` method on (non-skew) ``Partitions``.
|
|
1257
|
+
|
|
1258
|
+
.. SEEALSO::
|
|
1259
|
+
|
|
1260
|
+
- :meth:`sage.combinat.skew_partition.SkewPartition.outer_corners`
|
|
1261
|
+
- :meth:`sage.combinat.partition.Partition.outside_corners`
|
|
1262
|
+
|
|
1263
|
+
EXAMPLES::
|
|
1264
|
+
|
|
1265
|
+
sage: mu = SkewPartition([[3,2,1],[2,1]])
|
|
1266
|
+
sage: mu.pp()
|
|
1267
|
+
*
|
|
1268
|
+
*
|
|
1269
|
+
*
|
|
1270
|
+
sage: mu.outside_corners()
|
|
1271
|
+
[(0, 3), (1, 2), (2, 1), (3, 0)]
|
|
1272
|
+
"""
|
|
1273
|
+
return self.outer().outside_corners()
|
|
1274
|
+
|
|
1275
|
+
def specht_module(self, base_ring=None):
|
|
1276
|
+
r"""
|
|
1277
|
+
Return the Specht module corresponding to ``self``.
|
|
1278
|
+
|
|
1279
|
+
EXAMPLES::
|
|
1280
|
+
|
|
1281
|
+
sage: mu = SkewPartition([[3,2,1], [2]])
|
|
1282
|
+
sage: SM = mu.specht_module(QQ) # needs sage.modules
|
|
1283
|
+
sage: s = SymmetricFunctions(QQ).s() # needs sage.modules
|
|
1284
|
+
sage: s(SM.frobenius_image()) # needs sage.libs.flint sage.modules
|
|
1285
|
+
s[2, 1, 1] + s[2, 2] + s[3, 1]
|
|
1286
|
+
|
|
1287
|
+
We verify that the Frobenius image is the corresponding
|
|
1288
|
+
skew Schur function::
|
|
1289
|
+
|
|
1290
|
+
sage: s[3,2,1].skew_by(s[2]) # needs lrcalc_python sage.modules
|
|
1291
|
+
s[2, 1, 1] + s[2, 2] + s[3, 1]
|
|
1292
|
+
|
|
1293
|
+
::
|
|
1294
|
+
|
|
1295
|
+
sage: mu = SkewPartition([[4,2,1], [2,1]])
|
|
1296
|
+
sage: SM = mu.specht_module(QQ) # needs sage.modules
|
|
1297
|
+
sage: s(SM.frobenius_image()) # needs sage.libs.flint sage.modules
|
|
1298
|
+
s[2, 1, 1] + s[2, 2] + 2*s[3, 1] + s[4]
|
|
1299
|
+
sage: s(mu) # needs lrcalc_python sage.modules
|
|
1300
|
+
s[2, 1, 1] + s[2, 2] + 2*s[3, 1] + s[4]
|
|
1301
|
+
"""
|
|
1302
|
+
from sage.combinat.specht_module import SpechtModule
|
|
1303
|
+
from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra
|
|
1304
|
+
if base_ring is None:
|
|
1305
|
+
from sage.rings.rational_field import QQ
|
|
1306
|
+
base_ring = QQ
|
|
1307
|
+
R = SymmetricGroupAlgebra(base_ring, self.size())
|
|
1308
|
+
return SpechtModule(R, self.cells())
|
|
1309
|
+
|
|
1310
|
+
def specht_module_dimension(self, base_ring=None):
|
|
1311
|
+
r"""
|
|
1312
|
+
Return the dimension of the Specht module corresponding to ``self``.
|
|
1313
|
+
|
|
1314
|
+
This is equal to the number of standard (skew) tableaux of
|
|
1315
|
+
shape ``self``.
|
|
1316
|
+
|
|
1317
|
+
EXAMPLES::
|
|
1318
|
+
|
|
1319
|
+
sage: mu = SkewPartition([[3,2,1], [2]])
|
|
1320
|
+
sage: mu.specht_module_dimension() # needs sage.modules
|
|
1321
|
+
8
|
|
1322
|
+
sage: mu.specht_module_dimension(GF(2)) # needs sage.modules sage.rings.finite_rings
|
|
1323
|
+
8
|
|
1324
|
+
"""
|
|
1325
|
+
from sage.categories.fields import Fields
|
|
1326
|
+
if base_ring is None or (base_ring in Fields() and base_ring.characteristic() == 0):
|
|
1327
|
+
from sage.combinat.skew_tableau import StandardSkewTableaux
|
|
1328
|
+
return StandardSkewTableaux(self).cardinality()
|
|
1329
|
+
from sage.combinat.specht_module import specht_module_rank
|
|
1330
|
+
return specht_module_rank(self, base_ring)
|
|
1331
|
+
|
|
1332
|
+
|
|
1333
|
+
def row_lengths_aux(skp):
|
|
1334
|
+
"""
|
|
1335
|
+
EXAMPLES::
|
|
1336
|
+
|
|
1337
|
+
sage: from sage.combinat.skew_partition import row_lengths_aux
|
|
1338
|
+
sage: row_lengths_aux([[5,4,3,1],[3,3,1]])
|
|
1339
|
+
[2, 1, 2]
|
|
1340
|
+
sage: row_lengths_aux([[5,4,3,1],[3,1]])
|
|
1341
|
+
[2, 3]
|
|
1342
|
+
"""
|
|
1343
|
+
if skp[0] == []:
|
|
1344
|
+
return []
|
|
1345
|
+
else:
|
|
1346
|
+
return [x[0] - x[1] for x in zip(skp[0], skp[1])]
|
|
1347
|
+
|
|
1348
|
+
|
|
1349
|
+
class SkewPartitions(UniqueRepresentation, Parent):
|
|
1350
|
+
"""
|
|
1351
|
+
Skew partitions.
|
|
1352
|
+
|
|
1353
|
+
.. WARNING::
|
|
1354
|
+
|
|
1355
|
+
The iterator of this class only yields skew partitions which
|
|
1356
|
+
are reduced, in the sense that there are no empty rows
|
|
1357
|
+
before the last nonempty row, and there are no empty columns
|
|
1358
|
+
before the last nonempty column.
|
|
1359
|
+
|
|
1360
|
+
EXAMPLES::
|
|
1361
|
+
|
|
1362
|
+
sage: SkewPartitions(4)
|
|
1363
|
+
Skew partitions of 4
|
|
1364
|
+
sage: SkewPartitions(4).cardinality()
|
|
1365
|
+
28
|
|
1366
|
+
sage: SkewPartitions(row_lengths=[2,1,2])
|
|
1367
|
+
Skew partitions with row lengths [2, 1, 2]
|
|
1368
|
+
sage: SkewPartitions(4, overlap=2)
|
|
1369
|
+
Skew partitions of 4 with a minimum overlap of 2
|
|
1370
|
+
sage: SkewPartitions(4, overlap=2).list()
|
|
1371
|
+
[[4] / [], [2, 2] / []]
|
|
1372
|
+
"""
|
|
1373
|
+
@staticmethod
|
|
1374
|
+
def __classcall_private__(self, n=None, row_lengths=None, overlap=0):
|
|
1375
|
+
"""
|
|
1376
|
+
Return the correct parent based upon the input.
|
|
1377
|
+
|
|
1378
|
+
EXAMPLES::
|
|
1379
|
+
|
|
1380
|
+
sage: SP1 = SkewPartitions(row_lengths=(2,1,2))
|
|
1381
|
+
sage: SP2 = SkewPartitions(row_lengths=[2,1,2])
|
|
1382
|
+
sage: SP1 is SP2
|
|
1383
|
+
True
|
|
1384
|
+
"""
|
|
1385
|
+
if n is not None:
|
|
1386
|
+
if row_lengths is not None:
|
|
1387
|
+
raise ValueError("you can only specify one of n or row_lengths")
|
|
1388
|
+
return SkewPartitions_n(n, overlap)
|
|
1389
|
+
elif row_lengths is not None:
|
|
1390
|
+
return SkewPartitions_rowlengths(row_lengths, overlap)
|
|
1391
|
+
else:
|
|
1392
|
+
return SkewPartitions_all()
|
|
1393
|
+
|
|
1394
|
+
def __init__(self, is_infinite=False):
|
|
1395
|
+
"""
|
|
1396
|
+
TESTS::
|
|
1397
|
+
|
|
1398
|
+
sage: S = SkewPartitions()
|
|
1399
|
+
sage: TestSuite(S).run()
|
|
1400
|
+
"""
|
|
1401
|
+
if is_infinite:
|
|
1402
|
+
Parent.__init__(self, category=InfiniteEnumeratedSets())
|
|
1403
|
+
else:
|
|
1404
|
+
Parent.__init__(self, category=FiniteEnumeratedSets())
|
|
1405
|
+
|
|
1406
|
+
# add options to class
|
|
1407
|
+
class options(GlobalOptions):
|
|
1408
|
+
"""
|
|
1409
|
+
Set and display the options for elements of the skew partition
|
|
1410
|
+
classes. If no parameters are set, then the function returns a copy of
|
|
1411
|
+
the options dictionary.
|
|
1412
|
+
|
|
1413
|
+
The ``options`` to skew partitions can be accessed as the method
|
|
1414
|
+
:obj:`SkewPartitions.options` of :class:`SkewPartitions` and
|
|
1415
|
+
related parent classes.
|
|
1416
|
+
|
|
1417
|
+
@OPTIONS@
|
|
1418
|
+
|
|
1419
|
+
EXAMPLES::
|
|
1420
|
+
|
|
1421
|
+
sage: SP = SkewPartition([[4,2,2,1], [3, 1, 1]])
|
|
1422
|
+
sage: SP
|
|
1423
|
+
[4, 2, 2, 1] / [3, 1, 1]
|
|
1424
|
+
sage: SkewPartitions.options.display="lists"
|
|
1425
|
+
sage: SP
|
|
1426
|
+
[[4, 2, 2, 1], [3, 1, 1]]
|
|
1427
|
+
|
|
1428
|
+
Changing the ``convention`` for skew partitions also changes the
|
|
1429
|
+
``convention`` option for partitions and tableaux and vice versa::
|
|
1430
|
+
|
|
1431
|
+
sage: SkewPartitions.options(display='diagram', convention='French')
|
|
1432
|
+
sage: SP
|
|
1433
|
+
*
|
|
1434
|
+
*
|
|
1435
|
+
*
|
|
1436
|
+
*
|
|
1437
|
+
sage: T = Tableau([[1,2,3],[4,5]])
|
|
1438
|
+
sage: T.pp()
|
|
1439
|
+
4 5
|
|
1440
|
+
1 2 3
|
|
1441
|
+
sage: P = Partition([4, 2, 2, 1])
|
|
1442
|
+
sage: P.pp()
|
|
1443
|
+
*
|
|
1444
|
+
**
|
|
1445
|
+
**
|
|
1446
|
+
****
|
|
1447
|
+
sage: Tableaux.options.convention="english"
|
|
1448
|
+
sage: SP
|
|
1449
|
+
*
|
|
1450
|
+
*
|
|
1451
|
+
*
|
|
1452
|
+
*
|
|
1453
|
+
sage: T.pp()
|
|
1454
|
+
1 2 3
|
|
1455
|
+
4 5
|
|
1456
|
+
sage: SkewPartitions.options._reset()
|
|
1457
|
+
"""
|
|
1458
|
+
NAME = 'SkewPartitions'
|
|
1459
|
+
module = 'sage.combinat.skew_partition'
|
|
1460
|
+
display = dict(default='quotient',
|
|
1461
|
+
description='Specifies how skew partitions should be printed',
|
|
1462
|
+
values=dict(lists='displayed as a pair of lists',
|
|
1463
|
+
quotient='displayed as a quotient of partitions',
|
|
1464
|
+
diagram='as a skew Ferrers diagram'),
|
|
1465
|
+
alias=dict(array='diagram', ferrers_diagram='diagram',
|
|
1466
|
+
young_diagram='diagram', pair='lists'),
|
|
1467
|
+
case_sensitive=False)
|
|
1468
|
+
latex = dict(default='young_diagram',
|
|
1469
|
+
description='Specifies how skew partitions should be latexed',
|
|
1470
|
+
values=dict(diagram='latex as a skew Ferrers diagram',
|
|
1471
|
+
young_diagram='latex as a skew Young diagram',
|
|
1472
|
+
marked='latex as a partition where the skew shape is marked'),
|
|
1473
|
+
alias=dict(array='diagram', ferrers_diagram='diagram'),
|
|
1474
|
+
case_sensitive=False)
|
|
1475
|
+
diagram_str = dict(link_to=(Partitions.options,'diagram_str'))
|
|
1476
|
+
latex_diagram_str = dict(link_to=(Partitions.options,'latex_diagram_str'))
|
|
1477
|
+
latex_marking_str = dict(default='X',
|
|
1478
|
+
description='The character used to marked the deleted cells when latexing marked partitions',
|
|
1479
|
+
checker=lambda char: isinstance(char, str))
|
|
1480
|
+
convention = dict(link_to=(Tableaux.options,'convention'))
|
|
1481
|
+
notation = dict(alt_name='convention')
|
|
1482
|
+
|
|
1483
|
+
Element = SkewPartition
|
|
1484
|
+
|
|
1485
|
+
def _element_constructor_(self, skp):
|
|
1486
|
+
"""
|
|
1487
|
+
Construct an element of ``self``.
|
|
1488
|
+
|
|
1489
|
+
EXAMPLES::
|
|
1490
|
+
|
|
1491
|
+
sage: S = SkewPartitions()
|
|
1492
|
+
sage: S([[3,1], [1]])
|
|
1493
|
+
[3, 1] / [1]
|
|
1494
|
+
"""
|
|
1495
|
+
return self.element_class(self, skp)
|
|
1496
|
+
|
|
1497
|
+
def __contains__(self, x):
|
|
1498
|
+
"""
|
|
1499
|
+
TESTS::
|
|
1500
|
+
|
|
1501
|
+
sage: [[], []] in SkewPartitions()
|
|
1502
|
+
True
|
|
1503
|
+
sage: [[], [1]] in SkewPartitions()
|
|
1504
|
+
False
|
|
1505
|
+
sage: [[], [-1]] in SkewPartitions()
|
|
1506
|
+
False
|
|
1507
|
+
sage: [[], [0]] in SkewPartitions()
|
|
1508
|
+
True
|
|
1509
|
+
sage: [[3,2,1],[]] in SkewPartitions()
|
|
1510
|
+
True
|
|
1511
|
+
sage: [[3,2,1],[1]] in SkewPartitions()
|
|
1512
|
+
True
|
|
1513
|
+
sage: [[3,2,1],[2]] in SkewPartitions()
|
|
1514
|
+
True
|
|
1515
|
+
sage: [[3,2,1],[3]] in SkewPartitions()
|
|
1516
|
+
True
|
|
1517
|
+
sage: [[3,2,1],[4]] in SkewPartitions()
|
|
1518
|
+
False
|
|
1519
|
+
sage: [[3,2,1],[1,1]] in SkewPartitions()
|
|
1520
|
+
True
|
|
1521
|
+
sage: [[3,2,1],[1,2]] in SkewPartitions()
|
|
1522
|
+
False
|
|
1523
|
+
sage: [[3,2,1],[2,1]] in SkewPartitions()
|
|
1524
|
+
True
|
|
1525
|
+
sage: [[3,2,1],[2,2]] in SkewPartitions()
|
|
1526
|
+
True
|
|
1527
|
+
sage: [[3,2,1],[3,2]] in SkewPartitions()
|
|
1528
|
+
True
|
|
1529
|
+
sage: [[3,2,1],[1,1,1]] in SkewPartitions()
|
|
1530
|
+
True
|
|
1531
|
+
sage: [[7, 4, 3, 2], [8, 2, 1]] in SkewPartitions()
|
|
1532
|
+
False
|
|
1533
|
+
sage: [[7, 4, 3, 2], [5, 2, 1]] in SkewPartitions()
|
|
1534
|
+
True
|
|
1535
|
+
sage: [[4,2,1],[1,1,1,1]] in SkewPartitions()
|
|
1536
|
+
False
|
|
1537
|
+
sage: [[1,1,1,0],[1,1,0,0]] in SkewPartitions()
|
|
1538
|
+
True
|
|
1539
|
+
"""
|
|
1540
|
+
if isinstance(x, SkewPartition):
|
|
1541
|
+
return True
|
|
1542
|
+
|
|
1543
|
+
try:
|
|
1544
|
+
if len(x) != 2:
|
|
1545
|
+
return False
|
|
1546
|
+
except TypeError:
|
|
1547
|
+
return False
|
|
1548
|
+
|
|
1549
|
+
p = _Partitions
|
|
1550
|
+
if x[0] not in p:
|
|
1551
|
+
return False
|
|
1552
|
+
if x[1] not in p:
|
|
1553
|
+
return False
|
|
1554
|
+
|
|
1555
|
+
if not p(x[0]).contains(p(x[1])):
|
|
1556
|
+
return False
|
|
1557
|
+
|
|
1558
|
+
return True
|
|
1559
|
+
|
|
1560
|
+
def from_row_and_column_length(self, rowL, colL):
|
|
1561
|
+
"""
|
|
1562
|
+
Construct a partition from its row lengths and column lengths.
|
|
1563
|
+
|
|
1564
|
+
INPUT:
|
|
1565
|
+
|
|
1566
|
+
- ``rowL`` -- a composition or a list of positive integers
|
|
1567
|
+
|
|
1568
|
+
- ``colL`` -- a composition or a list of positive integers
|
|
1569
|
+
|
|
1570
|
+
OUTPUT:
|
|
1571
|
+
|
|
1572
|
+
- If it exists the unique skew-partitions with row lengths ``rowL``
|
|
1573
|
+
and column lengths ``colL``.
|
|
1574
|
+
- Raise a :exc:`ValueError` if ``rowL`` and ``colL`` are not compatible.
|
|
1575
|
+
|
|
1576
|
+
EXAMPLES::
|
|
1577
|
+
|
|
1578
|
+
sage: S = SkewPartitions()
|
|
1579
|
+
sage: print(S.from_row_and_column_length([3,1,2,2],[2,3,1,1,1]).diagram())
|
|
1580
|
+
***
|
|
1581
|
+
*
|
|
1582
|
+
**
|
|
1583
|
+
**
|
|
1584
|
+
sage: S.from_row_and_column_length([],[])
|
|
1585
|
+
[] / []
|
|
1586
|
+
sage: S.from_row_and_column_length([1],[1])
|
|
1587
|
+
[1] / []
|
|
1588
|
+
sage: S.from_row_and_column_length([2,1],[2,1])
|
|
1589
|
+
[2, 1] / []
|
|
1590
|
+
sage: S.from_row_and_column_length([1,2],[1,2])
|
|
1591
|
+
[2, 2] / [1]
|
|
1592
|
+
sage: S.from_row_and_column_length([1,2],[1,3])
|
|
1593
|
+
Traceback (most recent call last):
|
|
1594
|
+
...
|
|
1595
|
+
ValueError: sum mismatch: [1, 2] and [1, 3]
|
|
1596
|
+
sage: S.from_row_and_column_length([3,2,1,2],[2,3,1,1,1])
|
|
1597
|
+
Traceback (most recent call last):
|
|
1598
|
+
...
|
|
1599
|
+
ValueError: incompatible row and column length : [3, 2, 1, 2] and [2, 3, 1, 1, 1]
|
|
1600
|
+
|
|
1601
|
+
.. WARNING::
|
|
1602
|
+
|
|
1603
|
+
If some rows and columns have length zero, there is no way to retrieve
|
|
1604
|
+
unambiguously the skew partition. We therefore raise
|
|
1605
|
+
a :exc:`ValueError`.
|
|
1606
|
+
For examples here are two skew partitions with the same row and column
|
|
1607
|
+
lengths::
|
|
1608
|
+
|
|
1609
|
+
sage: skp1 = SkewPartition([[2,2],[2,2]])
|
|
1610
|
+
sage: skp2 = SkewPartition([[2,1],[2,1]])
|
|
1611
|
+
sage: skp1.row_lengths(), skp1.column_lengths()
|
|
1612
|
+
([0, 0], [0, 0])
|
|
1613
|
+
sage: skp2.row_lengths(), skp2.column_lengths()
|
|
1614
|
+
([0, 0], [0, 0])
|
|
1615
|
+
sage: SkewPartitions().from_row_and_column_length([0,0], [0,0])
|
|
1616
|
+
Traceback (most recent call last):
|
|
1617
|
+
...
|
|
1618
|
+
ValueError: row and column length must be positive
|
|
1619
|
+
|
|
1620
|
+
TESTS::
|
|
1621
|
+
|
|
1622
|
+
sage: all(SkewPartitions().from_row_and_column_length(p.row_lengths(), p.column_lengths()) == p
|
|
1623
|
+
....: for i in range(7) for p in SkewPartitions(i))
|
|
1624
|
+
True
|
|
1625
|
+
"""
|
|
1626
|
+
if sum(rowL) != sum(colL):
|
|
1627
|
+
raise ValueError(f"sum mismatch: {rowL} and {colL}")
|
|
1628
|
+
if not all(i > 0 for i in rowL) or not all(i > 0 for i in colL):
|
|
1629
|
+
raise ValueError("row and column length must be positive")
|
|
1630
|
+
if not rowL:
|
|
1631
|
+
return self.element_class(self, [[], []])
|
|
1632
|
+
colL_new = colL[:]
|
|
1633
|
+
resIn = []
|
|
1634
|
+
resOut = []
|
|
1635
|
+
inPOld = len(colL)
|
|
1636
|
+
for row in rowL:
|
|
1637
|
+
inP = len(colL_new) - row
|
|
1638
|
+
if inP < 0 or inP > inPOld:
|
|
1639
|
+
raise ValueError("incompatible row and column length : %s and %s" % (rowL, colL))
|
|
1640
|
+
inPOld = inP
|
|
1641
|
+
resIn.append(inP)
|
|
1642
|
+
resOut.append(len(colL_new))
|
|
1643
|
+
for iCol in range(inP, len(colL_new)):
|
|
1644
|
+
colL_new[iCol] -= 1
|
|
1645
|
+
if colL_new[iCol] < 0:
|
|
1646
|
+
raise ValueError("incompatible row and column length : %s and %s" % (rowL, colL))
|
|
1647
|
+
while colL_new and colL_new[-1] == 0:
|
|
1648
|
+
colL_new.pop()
|
|
1649
|
+
return self.element_class(self, [resOut, [x for x in resIn if x]])
|
|
1650
|
+
|
|
1651
|
+
|
|
1652
|
+
class SkewPartitions_all(SkewPartitions):
|
|
1653
|
+
"""
|
|
1654
|
+
Class of all skew partitions.
|
|
1655
|
+
"""
|
|
1656
|
+
|
|
1657
|
+
def __init__(self):
|
|
1658
|
+
"""
|
|
1659
|
+
Initialize ``self``.
|
|
1660
|
+
|
|
1661
|
+
EXAMPLES::
|
|
1662
|
+
|
|
1663
|
+
sage: S = SkewPartitions()
|
|
1664
|
+
sage: TestSuite(S).run()
|
|
1665
|
+
"""
|
|
1666
|
+
SkewPartitions.__init__(self, True)
|
|
1667
|
+
|
|
1668
|
+
def _repr_(self):
|
|
1669
|
+
"""
|
|
1670
|
+
TESTS::
|
|
1671
|
+
|
|
1672
|
+
sage: SkewPartitions()
|
|
1673
|
+
Skew partitions
|
|
1674
|
+
"""
|
|
1675
|
+
return "Skew partitions"
|
|
1676
|
+
|
|
1677
|
+
def __iter__(self):
|
|
1678
|
+
"""
|
|
1679
|
+
Iterate over ``self``.
|
|
1680
|
+
|
|
1681
|
+
EXAMPLES::
|
|
1682
|
+
|
|
1683
|
+
sage: SP = SkewPartitions()
|
|
1684
|
+
sage: it = SP.__iter__()
|
|
1685
|
+
sage: [next(it) for x in range(10)]
|
|
1686
|
+
[[] / [],
|
|
1687
|
+
[1] / [],
|
|
1688
|
+
[2] / [],
|
|
1689
|
+
[1, 1] / [],
|
|
1690
|
+
[2, 1] / [1],
|
|
1691
|
+
[3] / [],
|
|
1692
|
+
[2, 1] / [],
|
|
1693
|
+
[3, 1] / [1],
|
|
1694
|
+
[2, 2] / [1],
|
|
1695
|
+
[3, 2] / [2]]
|
|
1696
|
+
"""
|
|
1697
|
+
n = 0
|
|
1698
|
+
while True:
|
|
1699
|
+
for p in SkewPartitions_n(n):
|
|
1700
|
+
yield self.element_class(self, p)
|
|
1701
|
+
n += 1
|
|
1702
|
+
|
|
1703
|
+
|
|
1704
|
+
class SkewPartitions_n(SkewPartitions):
|
|
1705
|
+
"""
|
|
1706
|
+
The set of skew partitions of ``n`` with overlap at least
|
|
1707
|
+
``overlap`` and no empty row.
|
|
1708
|
+
|
|
1709
|
+
INPUT:
|
|
1710
|
+
|
|
1711
|
+
- ``n`` -- nonnegative integer
|
|
1712
|
+
|
|
1713
|
+
- ``overlap`` -- integer (default: `0`)
|
|
1714
|
+
|
|
1715
|
+
Caveat: this set is stable under conjugation only for ``overlap`` equal
|
|
1716
|
+
to 0 or 1. What exactly happens for negative overlaps is not yet
|
|
1717
|
+
well specified and subject to change (we may want to
|
|
1718
|
+
introduce vertical overlap constraints as well).
|
|
1719
|
+
|
|
1720
|
+
.. TODO::
|
|
1721
|
+
|
|
1722
|
+
As is, this set is essentially the composition of
|
|
1723
|
+
``Compositions(n)`` (which give the row lengths) and
|
|
1724
|
+
``SkewPartition(n, row_lengths=...)``, and one would want to
|
|
1725
|
+
"inherit" list and cardinality from this composition.
|
|
1726
|
+
"""
|
|
1727
|
+
@staticmethod
|
|
1728
|
+
def __classcall_private__(cls, n, overlap=0):
|
|
1729
|
+
"""
|
|
1730
|
+
Normalize input so we have a unique representation.
|
|
1731
|
+
|
|
1732
|
+
EXAMPLES::
|
|
1733
|
+
|
|
1734
|
+
sage: S = SkewPartitions(3, overlap=1)
|
|
1735
|
+
sage: S2 = SkewPartitions(int(3), overlap='connected')
|
|
1736
|
+
sage: S is S2
|
|
1737
|
+
True
|
|
1738
|
+
"""
|
|
1739
|
+
if overlap == 'connected':
|
|
1740
|
+
overlap = 1
|
|
1741
|
+
return super().__classcall__(cls, n, overlap)
|
|
1742
|
+
|
|
1743
|
+
def __init__(self, n, overlap):
|
|
1744
|
+
"""
|
|
1745
|
+
Return the set of the skew partitions of ``n`` with overlap
|
|
1746
|
+
at least ``overlap``, and no empty row.
|
|
1747
|
+
|
|
1748
|
+
The iteration order is not specified yet.
|
|
1749
|
+
|
|
1750
|
+
Caveat: this set is stable under conjugation only for overlap=
|
|
1751
|
+
0 or 1. What exactly happens for negative overlaps is not yet
|
|
1752
|
+
well specified, and subject to change (we may want to
|
|
1753
|
+
introduce vertical overlap constraints as well). ``overlap`` would
|
|
1754
|
+
also better be named ``min_overlap``.
|
|
1755
|
+
|
|
1756
|
+
Todo: as is, this set is essentially the composition of
|
|
1757
|
+
``Compositions(n)`` (which give the row lengths) and
|
|
1758
|
+
``SkewPartition(n, row_lengths=...)``, and one would want to
|
|
1759
|
+
"inherit" list and cardinality from this composition.
|
|
1760
|
+
|
|
1761
|
+
INPUT:
|
|
1762
|
+
|
|
1763
|
+
- ``n`` -- nonnegative integer
|
|
1764
|
+
- ``overlap`` -- integer
|
|
1765
|
+
|
|
1766
|
+
TESTS::
|
|
1767
|
+
|
|
1768
|
+
sage: S = SkewPartitions(3)
|
|
1769
|
+
sage: TestSuite(S).run()
|
|
1770
|
+
sage: S = SkewPartitions(3, overlap=1)
|
|
1771
|
+
sage: TestSuite(S).run()
|
|
1772
|
+
"""
|
|
1773
|
+
self.n = n
|
|
1774
|
+
self.overlap = overlap
|
|
1775
|
+
SkewPartitions.__init__(self, False)
|
|
1776
|
+
|
|
1777
|
+
def __contains__(self, x):
|
|
1778
|
+
"""
|
|
1779
|
+
TESTS::
|
|
1780
|
+
|
|
1781
|
+
sage: [[],[]] in SkewPartitions(0)
|
|
1782
|
+
True
|
|
1783
|
+
sage: [[3,2,1], []] in SkewPartitions(6)
|
|
1784
|
+
True
|
|
1785
|
+
sage: [[3,2,1], []] in SkewPartitions(7)
|
|
1786
|
+
False
|
|
1787
|
+
sage: [[3,2,1], []] in SkewPartitions(5)
|
|
1788
|
+
False
|
|
1789
|
+
sage: [[7, 4, 3, 2], [8, 2, 1]] in SkewPartitions(8)
|
|
1790
|
+
False
|
|
1791
|
+
sage: [[7, 4, 3, 2], [5, 2, 1]] in SkewPartitions(8)
|
|
1792
|
+
False
|
|
1793
|
+
sage: [[7, 4, 3, 2], [5, 2, 1]] in SkewPartitions(5)
|
|
1794
|
+
False
|
|
1795
|
+
sage: [[7, 4, 3, 2], [5, 2, 1]] in SkewPartitions(5, overlap=-1)
|
|
1796
|
+
False
|
|
1797
|
+
sage: [[7, 4, 3, 2], [5, 2, 1]] in SkewPartitions(8, overlap=-1)
|
|
1798
|
+
True
|
|
1799
|
+
sage: [[7, 4, 3, 2], [5, 2, 1]] in SkewPartitions(8, overlap=0)
|
|
1800
|
+
False
|
|
1801
|
+
sage: [[7, 4, 3, 2], [5, 2, 1]] in SkewPartitions(8, overlap='connected')
|
|
1802
|
+
False
|
|
1803
|
+
sage: [[7, 4, 3, 2], [5, 2, 1]] in SkewPartitions(8, overlap=-2)
|
|
1804
|
+
True
|
|
1805
|
+
"""
|
|
1806
|
+
return x in SkewPartitions() \
|
|
1807
|
+
and sum(x[0])-sum(x[1]) == self.n \
|
|
1808
|
+
and self.overlap <= SkewPartition(x).overlap()
|
|
1809
|
+
|
|
1810
|
+
def _repr_(self):
|
|
1811
|
+
"""
|
|
1812
|
+
TESTS::
|
|
1813
|
+
|
|
1814
|
+
sage: SkewPartitions(3)
|
|
1815
|
+
Skew partitions of 3
|
|
1816
|
+
sage: SkewPartitions(3, overlap=1)
|
|
1817
|
+
Skew partitions of 3 with a minimum overlap of 1
|
|
1818
|
+
"""
|
|
1819
|
+
string = "Skew partitions of %s" % self.n
|
|
1820
|
+
if self.overlap:
|
|
1821
|
+
string += " with a minimum overlap of %s" % self.overlap
|
|
1822
|
+
return string
|
|
1823
|
+
|
|
1824
|
+
def _count_slide(self, co, overlap=0):
|
|
1825
|
+
"""
|
|
1826
|
+
Return the number of skew partitions related to the composition
|
|
1827
|
+
``co`` by 'sliding'. The composition ``co`` is the list of row
|
|
1828
|
+
lengths of the skew partition.
|
|
1829
|
+
|
|
1830
|
+
EXAMPLES::
|
|
1831
|
+
|
|
1832
|
+
sage: s = SkewPartitions(3)
|
|
1833
|
+
sage: s._count_slide([2,1])
|
|
1834
|
+
2
|
|
1835
|
+
sage: [ sp for sp in s if sp.row_lengths() == [2,1] ]
|
|
1836
|
+
[[2, 1] / [], [3, 1] / [1]]
|
|
1837
|
+
sage: s = SkewPartitions(3, overlap=1)
|
|
1838
|
+
sage: s._count_slide([2,1], overlap=1)
|
|
1839
|
+
1
|
|
1840
|
+
sage: [ sp for sp in s if sp.row_lengths() == [2,1] ]
|
|
1841
|
+
[[2, 1] / []]
|
|
1842
|
+
"""
|
|
1843
|
+
result = 1
|
|
1844
|
+
shift = 1 - overlap
|
|
1845
|
+
for i in range(len(co) - 1):
|
|
1846
|
+
result *= min(co[i], co[i + 1]) + shift
|
|
1847
|
+
return result
|
|
1848
|
+
|
|
1849
|
+
def cardinality(self):
|
|
1850
|
+
"""
|
|
1851
|
+
Return the number of skew partitions of the integer `n`
|
|
1852
|
+
(with given overlap, if specified; and with no empty rows before
|
|
1853
|
+
the last row).
|
|
1854
|
+
|
|
1855
|
+
EXAMPLES::
|
|
1856
|
+
|
|
1857
|
+
sage: SkewPartitions(0).cardinality()
|
|
1858
|
+
1
|
|
1859
|
+
sage: SkewPartitions(4).cardinality()
|
|
1860
|
+
28
|
|
1861
|
+
sage: SkewPartitions(5).cardinality()
|
|
1862
|
+
87
|
|
1863
|
+
sage: SkewPartitions(4, overlap=1).cardinality()
|
|
1864
|
+
9
|
|
1865
|
+
sage: SkewPartitions(5, overlap=1).cardinality()
|
|
1866
|
+
20
|
|
1867
|
+
sage: s = SkewPartitions(5, overlap=-1)
|
|
1868
|
+
sage: s.cardinality() == len(s.list())
|
|
1869
|
+
True
|
|
1870
|
+
"""
|
|
1871
|
+
if self.n == 0:
|
|
1872
|
+
return ZZ.one()
|
|
1873
|
+
|
|
1874
|
+
if self.overlap > 0:
|
|
1875
|
+
gg = Compositions(self.n, min_part=max(1, self.overlap))
|
|
1876
|
+
else:
|
|
1877
|
+
gg = Compositions(self.n)
|
|
1878
|
+
|
|
1879
|
+
sum_a = 0
|
|
1880
|
+
for co in gg:
|
|
1881
|
+
sum_a += self._count_slide(co, overlap=self.overlap)
|
|
1882
|
+
|
|
1883
|
+
return ZZ(sum_a)
|
|
1884
|
+
|
|
1885
|
+
def __iter__(self):
|
|
1886
|
+
"""
|
|
1887
|
+
Iterate through the skew partitions of `n`
|
|
1888
|
+
(with given overlap, if specified; and with no empty rows before
|
|
1889
|
+
the last row).
|
|
1890
|
+
|
|
1891
|
+
EXAMPLES::
|
|
1892
|
+
|
|
1893
|
+
sage: SkewPartitions(3).list()
|
|
1894
|
+
[[3] / [],
|
|
1895
|
+
[2, 1] / [],
|
|
1896
|
+
[3, 1] / [1],
|
|
1897
|
+
[2, 2] / [1],
|
|
1898
|
+
[3, 2] / [2],
|
|
1899
|
+
[1, 1, 1] / [],
|
|
1900
|
+
[2, 2, 1] / [1, 1],
|
|
1901
|
+
[2, 1, 1] / [1],
|
|
1902
|
+
[3, 2, 1] / [2, 1]]
|
|
1903
|
+
|
|
1904
|
+
sage: SkewPartitions(3, overlap=0).list()
|
|
1905
|
+
[[3] / [],
|
|
1906
|
+
[2, 1] / [],
|
|
1907
|
+
[3, 1] / [1],
|
|
1908
|
+
[2, 2] / [1],
|
|
1909
|
+
[3, 2] / [2],
|
|
1910
|
+
[1, 1, 1] / [],
|
|
1911
|
+
[2, 2, 1] / [1, 1],
|
|
1912
|
+
[2, 1, 1] / [1],
|
|
1913
|
+
[3, 2, 1] / [2, 1]]
|
|
1914
|
+
sage: SkewPartitions(3, overlap=1).list()
|
|
1915
|
+
[[3] / [],
|
|
1916
|
+
[2, 1] / [],
|
|
1917
|
+
[2, 2] / [1],
|
|
1918
|
+
[1, 1, 1] / []]
|
|
1919
|
+
sage: SkewPartitions(3, overlap=2).list()
|
|
1920
|
+
[[3] / []]
|
|
1921
|
+
sage: SkewPartitions(3, overlap=3).list()
|
|
1922
|
+
[[3] / []]
|
|
1923
|
+
sage: SkewPartitions(3, overlap=4).list()
|
|
1924
|
+
[]
|
|
1925
|
+
"""
|
|
1926
|
+
for co in Compositions(self.n, min_part=max(1, self.overlap)):
|
|
1927
|
+
for sp in SkewPartitions(row_lengths=co, overlap=self.overlap):
|
|
1928
|
+
yield self.element_class(self, sp)
|
|
1929
|
+
|
|
1930
|
+
######################################
|
|
1931
|
+
# Skew Partitions (from row lengths) #
|
|
1932
|
+
######################################
|
|
1933
|
+
|
|
1934
|
+
|
|
1935
|
+
class SkewPartitions_rowlengths(SkewPartitions):
|
|
1936
|
+
"""
|
|
1937
|
+
All skew partitions with given row lengths.
|
|
1938
|
+
"""
|
|
1939
|
+
@staticmethod
|
|
1940
|
+
def __classcall_private__(cls, co, overlap=0):
|
|
1941
|
+
"""
|
|
1942
|
+
Normalize input to ensure a unique representation.
|
|
1943
|
+
|
|
1944
|
+
EXAMPLES::
|
|
1945
|
+
|
|
1946
|
+
sage: S = SkewPartitions(row_lengths=[2,1], overlap=1)
|
|
1947
|
+
sage: S2 = SkewPartitions(row_lengths=(2,1), overlap='connected')
|
|
1948
|
+
sage: S is S2
|
|
1949
|
+
True
|
|
1950
|
+
"""
|
|
1951
|
+
co = Compositions()(co)
|
|
1952
|
+
if overlap == 'connected':
|
|
1953
|
+
overlap = 1
|
|
1954
|
+
return super().__classcall__(cls, co, overlap)
|
|
1955
|
+
|
|
1956
|
+
def __init__(self, co, overlap):
|
|
1957
|
+
"""
|
|
1958
|
+
TESTS::
|
|
1959
|
+
|
|
1960
|
+
sage: S = SkewPartitions(row_lengths=[2,1])
|
|
1961
|
+
sage: TestSuite(S).run()
|
|
1962
|
+
"""
|
|
1963
|
+
self.co = co
|
|
1964
|
+
self.overlap = overlap
|
|
1965
|
+
SkewPartitions.__init__(self, False)
|
|
1966
|
+
|
|
1967
|
+
def __contains__(self, x):
|
|
1968
|
+
"""
|
|
1969
|
+
EXAMPLES::
|
|
1970
|
+
|
|
1971
|
+
sage: [[4,3,1],[2]] in SkewPartitions(row_lengths=[2,3,1])
|
|
1972
|
+
True
|
|
1973
|
+
sage: [[4,3,1],[2]] in SkewPartitions(row_lengths=[2,1,3])
|
|
1974
|
+
False
|
|
1975
|
+
sage: [[5,4,3,1],[3,3,1]] in SkewPartitions(row_lengths=[2,1,1,2])
|
|
1976
|
+
False
|
|
1977
|
+
sage: [[5,4,3,1],[3,3,1]] in SkewPartitions(row_lengths=[2,1,2,1])
|
|
1978
|
+
True
|
|
1979
|
+
"""
|
|
1980
|
+
if x in SkewPartitions():
|
|
1981
|
+
o = x[0]
|
|
1982
|
+
i = x[1]+[0]*(len(x[0])-len(x[1]))
|
|
1983
|
+
return [u[0]-u[1] for u in zip(o,i)] == self.co
|
|
1984
|
+
return False
|
|
1985
|
+
|
|
1986
|
+
def _repr_(self):
|
|
1987
|
+
"""
|
|
1988
|
+
TESTS::
|
|
1989
|
+
|
|
1990
|
+
sage: SkewPartitions(row_lengths=[2,1])
|
|
1991
|
+
Skew partitions with row lengths [2, 1]
|
|
1992
|
+
"""
|
|
1993
|
+
return "Skew partitions with row lengths %s" % self.co
|
|
1994
|
+
|
|
1995
|
+
def _from_row_lengths_aux(self, sskp, ck_1, ck, overlap=0):
|
|
1996
|
+
"""
|
|
1997
|
+
EXAMPLES::
|
|
1998
|
+
|
|
1999
|
+
sage: s = SkewPartitions(row_lengths=[2,1])
|
|
2000
|
+
sage: list(s._from_row_lengths_aux([[1], []], 1, 1, overlap=0))
|
|
2001
|
+
[[1, 1] / [], [2, 1] / [1]]
|
|
2002
|
+
sage: list(s._from_row_lengths_aux([[1, 1], []], 1, 1, overlap=0))
|
|
2003
|
+
[[1, 1, 1] / [], [2, 2, 1] / [1, 1]]
|
|
2004
|
+
sage: list(s._from_row_lengths_aux([[2, 1], [1]], 1, 1, overlap=0))
|
|
2005
|
+
[[2, 1, 1] / [1], [3, 2, 1] / [2, 1]]
|
|
2006
|
+
sage: list(s._from_row_lengths_aux([[1], []], 1, 2, overlap=0))
|
|
2007
|
+
[[2, 2] / [1], [3, 2] / [2]]
|
|
2008
|
+
sage: list(s._from_row_lengths_aux([[2], []], 2, 1, overlap=0))
|
|
2009
|
+
[[2, 1] / [], [3, 1] / [1]]
|
|
2010
|
+
"""
|
|
2011
|
+
nn = min(ck_1, ck)
|
|
2012
|
+
mm = max(0, ck-ck_1)
|
|
2013
|
+
# nn should be >= 0. In the case of the positive overlap,
|
|
2014
|
+
# the min_part condition insures ck>=overlap for all k
|
|
2015
|
+
|
|
2016
|
+
nn -= overlap
|
|
2017
|
+
for i in range(nn+1):
|
|
2018
|
+
skp1, skp2 = sskp
|
|
2019
|
+
skp2 += [0]*(len(skp1)-len(skp2))
|
|
2020
|
+
skp1 = [x + i + mm for x in skp1]
|
|
2021
|
+
skp1 += [ck]
|
|
2022
|
+
skp2 = [x + i + mm for x in skp2]
|
|
2023
|
+
skp2 = [x for x in skp2 if x != 0]
|
|
2024
|
+
yield SkewPartition([skp1, skp2])
|
|
2025
|
+
|
|
2026
|
+
def __iter__(self):
|
|
2027
|
+
"""
|
|
2028
|
+
Iterate through all the skew partitions that have row lengths
|
|
2029
|
+
given by the composition ``self.co``.
|
|
2030
|
+
|
|
2031
|
+
EXAMPLES::
|
|
2032
|
+
|
|
2033
|
+
sage: SkewPartitions(row_lengths=[2,2]).list()
|
|
2034
|
+
[[2, 2] / [], [3, 2] / [1], [4, 2] / [2]]
|
|
2035
|
+
sage: SkewPartitions(row_lengths=[2,2], overlap=1).list()
|
|
2036
|
+
[[2, 2] / [], [3, 2] / [1]]
|
|
2037
|
+
"""
|
|
2038
|
+
if self.co == []:
|
|
2039
|
+
yield self.element_class(self, [[],[]])
|
|
2040
|
+
return
|
|
2041
|
+
|
|
2042
|
+
nn = len(self.co)
|
|
2043
|
+
if nn == 1:
|
|
2044
|
+
yield self.element_class(self, [[self.co[0]],[]])
|
|
2045
|
+
return
|
|
2046
|
+
|
|
2047
|
+
for sskp in SkewPartitions(row_lengths=self.co[:-1], overlap=self.overlap):
|
|
2048
|
+
for sp in self._from_row_lengths_aux(sskp, self.co[-2], self.co[-1], self.overlap):
|
|
2049
|
+
yield self.element_class(self, sp)
|
|
2050
|
+
|
|
2051
|
+
|
|
2052
|
+
from sage.misc.persist import register_unpickle_override
|
|
2053
|
+
register_unpickle_override('sage.combinat.skew_partition', 'SkewPartition_class', SkewPartition)
|