passagemath-combinat 10.6.42__cp314-cp314-musllinux_1_2_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_combinat/__init__.py +3 -0
- passagemath_combinat-10.6.42.dist-info/METADATA +160 -0
- passagemath_combinat-10.6.42.dist-info/RECORD +400 -0
- passagemath_combinat-10.6.42.dist-info/WHEEL +5 -0
- passagemath_combinat-10.6.42.dist-info/top_level.txt +3 -0
- passagemath_combinat.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_combinat.libs/libsymmetrica-81fe8739.so.3.0.0 +0 -0
- sage/algebras/affine_nil_temperley_lieb.py +263 -0
- sage/algebras/all.py +24 -0
- sage/algebras/all__sagemath_combinat.py +35 -0
- sage/algebras/askey_wilson.py +935 -0
- sage/algebras/associated_graded.py +345 -0
- sage/algebras/cellular_basis.py +350 -0
- sage/algebras/cluster_algebra.py +2766 -0
- sage/algebras/down_up_algebra.py +860 -0
- sage/algebras/free_algebra.py +1698 -0
- sage/algebras/free_algebra_element.py +345 -0
- sage/algebras/free_algebra_quotient.py +405 -0
- sage/algebras/free_algebra_quotient_element.py +295 -0
- sage/algebras/free_zinbiel_algebra.py +885 -0
- sage/algebras/hall_algebra.py +783 -0
- sage/algebras/hecke_algebras/all.py +4 -0
- sage/algebras/hecke_algebras/ariki_koike_algebra.py +1796 -0
- sage/algebras/hecke_algebras/ariki_koike_specht_modules.py +475 -0
- sage/algebras/hecke_algebras/cubic_hecke_algebra.py +3520 -0
- sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +1473 -0
- sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py +1079 -0
- sage/algebras/iwahori_hecke_algebra.py +3095 -0
- sage/algebras/jordan_algebra.py +1773 -0
- sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py +113 -0
- sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py +156 -0
- sage/algebras/lie_conformal_algebras/all.py +18 -0
- sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py +134 -0
- sage/algebras/lie_conformal_algebras/examples.py +43 -0
- sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py +131 -0
- sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py +139 -0
- sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py +174 -0
- sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +167 -0
- sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py +107 -0
- sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py +135 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +353 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py +236 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py +78 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +328 -0
- sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py +117 -0
- sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py +86 -0
- sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py +82 -0
- sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py +205 -0
- sage/algebras/nil_coxeter_algebra.py +191 -0
- sage/algebras/q_commuting_polynomials.py +673 -0
- sage/algebras/q_system.py +608 -0
- sage/algebras/quantum_clifford.py +959 -0
- sage/algebras/quantum_groups/ace_quantum_onsager.py +693 -0
- sage/algebras/quantum_groups/all.py +9 -0
- sage/algebras/quantum_groups/fock_space.py +2219 -0
- sage/algebras/quantum_groups/q_numbers.py +207 -0
- sage/algebras/quantum_groups/quantum_group_gap.py +2695 -0
- sage/algebras/quantum_groups/representations.py +591 -0
- sage/algebras/quantum_matrix_coordinate_algebra.py +1006 -0
- sage/algebras/quantum_oscillator.py +623 -0
- sage/algebras/quaternion_algebra.py +20 -0
- sage/algebras/quaternion_algebra_element.py +55 -0
- sage/algebras/rational_cherednik_algebra.py +525 -0
- sage/algebras/schur_algebra.py +670 -0
- sage/algebras/shuffle_algebra.py +1011 -0
- sage/algebras/splitting_algebra.py +779 -0
- sage/algebras/tensor_algebra.py +709 -0
- sage/algebras/yangian.py +1082 -0
- sage/algebras/yokonuma_hecke_algebra.py +1018 -0
- sage/all__sagemath_combinat.py +35 -0
- sage/combinat/SJT.py +255 -0
- sage/combinat/affine_permutation.py +2405 -0
- sage/combinat/algebraic_combinatorics.py +55 -0
- sage/combinat/all.py +53 -0
- sage/combinat/all__sagemath_combinat.py +195 -0
- sage/combinat/alternating_sign_matrix.py +2063 -0
- sage/combinat/baxter_permutations.py +346 -0
- sage/combinat/bijectionist.py +3220 -0
- sage/combinat/binary_recurrence_sequences.py +1180 -0
- sage/combinat/blob_algebra.py +685 -0
- sage/combinat/catalog_partitions.py +27 -0
- sage/combinat/chas/all.py +23 -0
- sage/combinat/chas/fsym.py +1180 -0
- sage/combinat/chas/wqsym.py +2601 -0
- sage/combinat/cluster_complex.py +326 -0
- sage/combinat/colored_permutations.py +2039 -0
- sage/combinat/colored_permutations_representations.py +964 -0
- sage/combinat/composition_signed.py +142 -0
- sage/combinat/composition_tableau.py +855 -0
- sage/combinat/constellation.py +1729 -0
- sage/combinat/core.py +751 -0
- sage/combinat/counting.py +12 -0
- sage/combinat/crystals/affine.py +742 -0
- sage/combinat/crystals/affine_factorization.py +518 -0
- sage/combinat/crystals/affinization.py +331 -0
- sage/combinat/crystals/alcove_path.py +2013 -0
- sage/combinat/crystals/all.py +22 -0
- sage/combinat/crystals/bkk_crystals.py +141 -0
- sage/combinat/crystals/catalog.py +115 -0
- sage/combinat/crystals/catalog_elementary_crystals.py +18 -0
- sage/combinat/crystals/catalog_infinity_crystals.py +33 -0
- sage/combinat/crystals/catalog_kirillov_reshetikhin.py +18 -0
- sage/combinat/crystals/crystals.py +257 -0
- sage/combinat/crystals/direct_sum.py +260 -0
- sage/combinat/crystals/elementary_crystals.py +1251 -0
- sage/combinat/crystals/fast_crystals.py +441 -0
- sage/combinat/crystals/fully_commutative_stable_grothendieck.py +1205 -0
- sage/combinat/crystals/generalized_young_walls.py +1076 -0
- sage/combinat/crystals/highest_weight_crystals.py +436 -0
- sage/combinat/crystals/induced_structure.py +695 -0
- sage/combinat/crystals/infinity_crystals.py +730 -0
- sage/combinat/crystals/kac_modules.py +863 -0
- sage/combinat/crystals/kirillov_reshetikhin.py +4196 -0
- sage/combinat/crystals/kyoto_path_model.py +497 -0
- sage/combinat/crystals/letters.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/letters.pxd +79 -0
- sage/combinat/crystals/letters.pyx +3056 -0
- sage/combinat/crystals/littelmann_path.py +1518 -0
- sage/combinat/crystals/monomial_crystals.py +1262 -0
- sage/combinat/crystals/multisegments.py +462 -0
- sage/combinat/crystals/mv_polytopes.py +467 -0
- sage/combinat/crystals/pbw_crystal.py +511 -0
- sage/combinat/crystals/pbw_datum.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/pbw_datum.pxd +4 -0
- sage/combinat/crystals/pbw_datum.pyx +487 -0
- sage/combinat/crystals/polyhedral_realization.py +372 -0
- sage/combinat/crystals/spins.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/spins.pxd +21 -0
- sage/combinat/crystals/spins.pyx +756 -0
- sage/combinat/crystals/star_crystal.py +290 -0
- sage/combinat/crystals/subcrystal.py +464 -0
- sage/combinat/crystals/tensor_product.py +1177 -0
- sage/combinat/crystals/tensor_product_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/tensor_product_element.pxd +35 -0
- sage/combinat/crystals/tensor_product_element.pyx +1870 -0
- sage/combinat/crystals/virtual_crystal.py +420 -0
- sage/combinat/cyclic_sieving_phenomenon.py +204 -0
- sage/combinat/debruijn_sequence.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/debruijn_sequence.pyx +355 -0
- sage/combinat/decorated_permutation.py +270 -0
- sage/combinat/degree_sequences.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/degree_sequences.pyx +588 -0
- sage/combinat/derangements.py +527 -0
- sage/combinat/descent_algebra.py +1008 -0
- sage/combinat/diagram.py +1551 -0
- sage/combinat/diagram_algebras.py +5886 -0
- sage/combinat/dyck_word.py +4349 -0
- sage/combinat/e_one_star.py +1623 -0
- sage/combinat/enumerated_sets.py +123 -0
- sage/combinat/expnums.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/expnums.pyx +148 -0
- sage/combinat/fast_vector_partitions.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/fast_vector_partitions.pyx +346 -0
- sage/combinat/fqsym.py +1977 -0
- sage/combinat/free_dendriform_algebra.py +954 -0
- sage/combinat/free_prelie_algebra.py +1141 -0
- sage/combinat/fully_commutative_elements.py +1077 -0
- sage/combinat/fully_packed_loop.py +1523 -0
- sage/combinat/gelfand_tsetlin_patterns.py +1409 -0
- sage/combinat/gray_codes.py +311 -0
- sage/combinat/grossman_larson_algebras.py +667 -0
- sage/combinat/growth.py +4352 -0
- sage/combinat/hall_polynomial.py +188 -0
- sage/combinat/hillman_grassl.py +866 -0
- sage/combinat/integer_matrices.py +329 -0
- sage/combinat/integer_vectors_mod_permgroup.py +1238 -0
- sage/combinat/k_tableau.py +4564 -0
- sage/combinat/kazhdan_lusztig.py +215 -0
- sage/combinat/key_polynomial.py +885 -0
- sage/combinat/knutson_tao_puzzles.py +2286 -0
- sage/combinat/lr_tableau.py +311 -0
- sage/combinat/matrices/all.py +24 -0
- sage/combinat/matrices/hadamard_matrix.py +3790 -0
- sage/combinat/matrices/latin.py +2912 -0
- sage/combinat/misc.py +401 -0
- sage/combinat/multiset_partition_into_sets_ordered.py +3541 -0
- sage/combinat/ncsf_qsym/all.py +21 -0
- sage/combinat/ncsf_qsym/combinatorics.py +317 -0
- sage/combinat/ncsf_qsym/generic_basis_code.py +1427 -0
- sage/combinat/ncsf_qsym/ncsf.py +5637 -0
- sage/combinat/ncsf_qsym/qsym.py +4053 -0
- sage/combinat/ncsf_qsym/tutorial.py +447 -0
- sage/combinat/ncsym/all.py +21 -0
- sage/combinat/ncsym/bases.py +855 -0
- sage/combinat/ncsym/dual.py +593 -0
- sage/combinat/ncsym/ncsym.py +2076 -0
- sage/combinat/necklace.py +551 -0
- sage/combinat/non_decreasing_parking_function.py +634 -0
- sage/combinat/nu_dyck_word.py +1474 -0
- sage/combinat/output.py +861 -0
- sage/combinat/parallelogram_polyomino.py +4326 -0
- sage/combinat/parking_functions.py +1602 -0
- sage/combinat/partition_algebra.py +1998 -0
- sage/combinat/partition_kleshchev.py +1982 -0
- sage/combinat/partition_shifting_algebras.py +584 -0
- sage/combinat/partition_tuple.py +3114 -0
- sage/combinat/path_tableaux/all.py +13 -0
- sage/combinat/path_tableaux/catalog.py +29 -0
- sage/combinat/path_tableaux/dyck_path.py +380 -0
- sage/combinat/path_tableaux/frieze.py +476 -0
- sage/combinat/path_tableaux/path_tableau.py +728 -0
- sage/combinat/path_tableaux/semistandard.py +510 -0
- sage/combinat/perfect_matching.py +779 -0
- sage/combinat/plane_partition.py +3300 -0
- sage/combinat/q_bernoulli.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/q_bernoulli.pyx +128 -0
- sage/combinat/quickref.py +81 -0
- sage/combinat/recognizable_series.py +2051 -0
- sage/combinat/regular_sequence.py +4316 -0
- sage/combinat/regular_sequence_bounded.py +543 -0
- sage/combinat/restricted_growth.py +81 -0
- sage/combinat/ribbon.py +20 -0
- sage/combinat/ribbon_shaped_tableau.py +489 -0
- sage/combinat/ribbon_tableau.py +1180 -0
- sage/combinat/rigged_configurations/all.py +46 -0
- sage/combinat/rigged_configurations/bij_abstract_class.py +548 -0
- sage/combinat/rigged_configurations/bij_infinity.py +370 -0
- sage/combinat/rigged_configurations/bij_type_A.py +163 -0
- sage/combinat/rigged_configurations/bij_type_A2_dual.py +338 -0
- sage/combinat/rigged_configurations/bij_type_A2_even.py +218 -0
- sage/combinat/rigged_configurations/bij_type_A2_odd.py +199 -0
- sage/combinat/rigged_configurations/bij_type_B.py +900 -0
- sage/combinat/rigged_configurations/bij_type_C.py +267 -0
- sage/combinat/rigged_configurations/bij_type_D.py +771 -0
- sage/combinat/rigged_configurations/bij_type_D_tri.py +392 -0
- sage/combinat/rigged_configurations/bij_type_D_twisted.py +576 -0
- sage/combinat/rigged_configurations/bij_type_E67.py +402 -0
- sage/combinat/rigged_configurations/bijection.py +143 -0
- sage/combinat/rigged_configurations/kleber_tree.py +1475 -0
- sage/combinat/rigged_configurations/kr_tableaux.py +1898 -0
- sage/combinat/rigged_configurations/rc_crystal.py +461 -0
- sage/combinat/rigged_configurations/rc_infinity.py +540 -0
- sage/combinat/rigged_configurations/rigged_configuration_element.py +2403 -0
- sage/combinat/rigged_configurations/rigged_configurations.py +1918 -0
- sage/combinat/rigged_configurations/rigged_partition.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/rigged_configurations/rigged_partition.pxd +15 -0
- sage/combinat/rigged_configurations/rigged_partition.pyx +680 -0
- sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +499 -0
- sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py +428 -0
- sage/combinat/rsk.py +3438 -0
- sage/combinat/schubert_polynomial.py +508 -0
- sage/combinat/set_partition.py +3318 -0
- sage/combinat/set_partition_iterator.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/set_partition_iterator.pyx +136 -0
- sage/combinat/set_partition_ordered.py +1590 -0
- sage/combinat/sf/abreu_nigro.py +346 -0
- sage/combinat/sf/all.py +52 -0
- sage/combinat/sf/character.py +576 -0
- sage/combinat/sf/classical.py +319 -0
- sage/combinat/sf/dual.py +996 -0
- sage/combinat/sf/elementary.py +549 -0
- sage/combinat/sf/hall_littlewood.py +1028 -0
- sage/combinat/sf/hecke.py +336 -0
- sage/combinat/sf/homogeneous.py +464 -0
- sage/combinat/sf/jack.py +1428 -0
- sage/combinat/sf/k_dual.py +1458 -0
- sage/combinat/sf/kfpoly.py +447 -0
- sage/combinat/sf/llt.py +789 -0
- sage/combinat/sf/macdonald.py +2019 -0
- sage/combinat/sf/monomial.py +525 -0
- sage/combinat/sf/multiplicative.py +113 -0
- sage/combinat/sf/new_kschur.py +1786 -0
- sage/combinat/sf/ns_macdonald.py +964 -0
- sage/combinat/sf/orthogonal.py +246 -0
- sage/combinat/sf/orthotriang.py +355 -0
- sage/combinat/sf/powersum.py +963 -0
- sage/combinat/sf/schur.py +880 -0
- sage/combinat/sf/sf.py +1653 -0
- sage/combinat/sf/sfa.py +7053 -0
- sage/combinat/sf/symplectic.py +253 -0
- sage/combinat/sf/witt.py +721 -0
- sage/combinat/shifted_primed_tableau.py +2735 -0
- sage/combinat/shuffle.py +830 -0
- sage/combinat/sidon_sets.py +146 -0
- sage/combinat/similarity_class_type.py +1721 -0
- sage/combinat/sine_gordon.py +618 -0
- sage/combinat/six_vertex_model.py +784 -0
- sage/combinat/skew_partition.py +2053 -0
- sage/combinat/skew_tableau.py +2989 -0
- sage/combinat/sloane_functions.py +8935 -0
- sage/combinat/specht_module.py +1403 -0
- sage/combinat/species/all.py +48 -0
- sage/combinat/species/characteristic_species.py +321 -0
- sage/combinat/species/composition_species.py +273 -0
- sage/combinat/species/cycle_species.py +284 -0
- sage/combinat/species/empty_species.py +155 -0
- sage/combinat/species/functorial_composition_species.py +148 -0
- sage/combinat/species/generating_series.py +673 -0
- sage/combinat/species/library.py +148 -0
- sage/combinat/species/linear_order_species.py +169 -0
- sage/combinat/species/misc.py +83 -0
- sage/combinat/species/partition_species.py +290 -0
- sage/combinat/species/permutation_species.py +268 -0
- sage/combinat/species/product_species.py +423 -0
- sage/combinat/species/recursive_species.py +476 -0
- sage/combinat/species/set_species.py +192 -0
- sage/combinat/species/species.py +820 -0
- sage/combinat/species/structure.py +539 -0
- sage/combinat/species/subset_species.py +243 -0
- sage/combinat/species/sum_species.py +225 -0
- sage/combinat/subword.py +564 -0
- sage/combinat/subword_complex.py +2122 -0
- sage/combinat/subword_complex_c.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/subword_complex_c.pyx +119 -0
- sage/combinat/super_tableau.py +821 -0
- sage/combinat/superpartition.py +1154 -0
- sage/combinat/symmetric_group_algebra.py +3774 -0
- sage/combinat/symmetric_group_representations.py +1830 -0
- sage/combinat/t_sequences.py +877 -0
- sage/combinat/tableau.py +9506 -0
- sage/combinat/tableau_residues.py +860 -0
- sage/combinat/tableau_tuple.py +5353 -0
- sage/combinat/tiling.py +2432 -0
- sage/combinat/triangles_FHM.py +777 -0
- sage/combinat/tutorial.py +1857 -0
- sage/combinat/vector_partition.py +337 -0
- sage/combinat/words/abstract_word.py +1722 -0
- sage/combinat/words/all.py +59 -0
- sage/combinat/words/alphabet.py +268 -0
- sage/combinat/words/finite_word.py +7201 -0
- sage/combinat/words/infinite_word.py +113 -0
- sage/combinat/words/lyndon_word.py +652 -0
- sage/combinat/words/morphic.py +351 -0
- sage/combinat/words/morphism.py +3878 -0
- sage/combinat/words/paths.py +2932 -0
- sage/combinat/words/shuffle_product.py +278 -0
- sage/combinat/words/suffix_trees.py +1873 -0
- sage/combinat/words/word.py +769 -0
- sage/combinat/words/word_char.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/words/word_char.pyx +847 -0
- sage/combinat/words/word_datatypes.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/words/word_datatypes.pxd +4 -0
- sage/combinat/words/word_datatypes.pyx +1067 -0
- sage/combinat/words/word_generators.py +2026 -0
- sage/combinat/words/word_infinite_datatypes.py +1218 -0
- sage/combinat/words/word_options.py +99 -0
- sage/combinat/words/words.py +2396 -0
- sage/data_structures/all__sagemath_combinat.py +1 -0
- sage/databases/all__sagemath_combinat.py +13 -0
- sage/databases/findstat.py +4897 -0
- sage/databases/oeis.py +2058 -0
- sage/databases/sloane.py +393 -0
- sage/dynamics/all__sagemath_combinat.py +14 -0
- sage/dynamics/cellular_automata/all.py +7 -0
- sage/dynamics/cellular_automata/catalog.py +34 -0
- sage/dynamics/cellular_automata/elementary.py +612 -0
- sage/dynamics/cellular_automata/glca.py +477 -0
- sage/dynamics/cellular_automata/solitons.py +1463 -0
- sage/dynamics/finite_dynamical_system.py +1249 -0
- sage/dynamics/finite_dynamical_system_catalog.py +382 -0
- sage/games/all.py +7 -0
- sage/games/hexad.py +704 -0
- sage/games/quantumino.py +591 -0
- sage/games/sudoku.py +889 -0
- sage/games/sudoku_backtrack.cpython-314-x86_64-linux-musl.so +0 -0
- sage/games/sudoku_backtrack.pyx +189 -0
- sage/groups/all__sagemath_combinat.py +1 -0
- sage/groups/indexed_free_group.py +489 -0
- sage/libs/all__sagemath_combinat.py +6 -0
- sage/libs/lrcalc/__init__.py +1 -0
- sage/libs/lrcalc/lrcalc.py +525 -0
- sage/libs/symmetrica/__init__.py +7 -0
- sage/libs/symmetrica/all.py +101 -0
- sage/libs/symmetrica/kostka.pxi +168 -0
- sage/libs/symmetrica/part.pxi +193 -0
- sage/libs/symmetrica/plet.pxi +42 -0
- sage/libs/symmetrica/sab.pxi +196 -0
- sage/libs/symmetrica/sb.pxi +332 -0
- sage/libs/symmetrica/sc.pxi +192 -0
- sage/libs/symmetrica/schur.pxi +956 -0
- sage/libs/symmetrica/symmetrica.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/symmetrica/symmetrica.pxi +1172 -0
- sage/libs/symmetrica/symmetrica.pyx +39 -0
- sage/monoids/all.py +13 -0
- sage/monoids/automatic_semigroup.py +1054 -0
- sage/monoids/free_abelian_monoid.py +315 -0
- sage/monoids/free_abelian_monoid_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/monoids/free_abelian_monoid_element.pxd +16 -0
- sage/monoids/free_abelian_monoid_element.pyx +397 -0
- sage/monoids/free_monoid.py +335 -0
- sage/monoids/free_monoid_element.py +431 -0
- sage/monoids/hecke_monoid.py +65 -0
- sage/monoids/string_monoid.py +817 -0
- sage/monoids/string_monoid_element.py +547 -0
- sage/monoids/string_ops.py +143 -0
- sage/monoids/trace_monoid.py +972 -0
- sage/rings/all__sagemath_combinat.py +2 -0
- sage/sat/all.py +4 -0
- sage/sat/boolean_polynomials.py +405 -0
- sage/sat/converters/__init__.py +6 -0
- sage/sat/converters/anf2cnf.py +14 -0
- sage/sat/converters/polybori.py +611 -0
- sage/sat/solvers/__init__.py +5 -0
- sage/sat/solvers/cryptominisat.py +287 -0
- sage/sat/solvers/dimacs.py +783 -0
- sage/sat/solvers/picosat.py +228 -0
- sage/sat/solvers/sat_lp.py +156 -0
- sage/sat/solvers/satsolver.cpython-314-x86_64-linux-musl.so +0 -0
- sage/sat/solvers/satsolver.pxd +3 -0
- sage/sat/solvers/satsolver.pyx +405 -0
sage/combinat/diagram.py
ADDED
|
@@ -0,0 +1,1551 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
r"""
|
|
3
|
+
Combinatorial diagrams
|
|
4
|
+
|
|
5
|
+
A combinatorial diagram is a collection of cells `(i,j)` indexed by pairs of
|
|
6
|
+
natural numbers.
|
|
7
|
+
|
|
8
|
+
For arbitrary diagrams, see :class:`Diagram`. There are also two other specific
|
|
9
|
+
types of diagrams implemented here. They are northwest diagrams
|
|
10
|
+
(:class:`NorthwestDiagram`) and Rothe diagrams (:func:`RotheDiagram`, a special
|
|
11
|
+
kind of northwest diagram).
|
|
12
|
+
|
|
13
|
+
AUTHORS:
|
|
14
|
+
|
|
15
|
+
- Trevor K. Karn (2022-08-01): initial version
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
# ****************************************************************************
|
|
19
|
+
# Copyright (C) 2022 Trevor K. Karn <karnx018 (at) umn.edu>
|
|
20
|
+
#
|
|
21
|
+
# This program is free software: you can redistribute it and/or modify
|
|
22
|
+
# it under the terms of the GNU General Public License as published by
|
|
23
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
24
|
+
# (at your option) any later version.
|
|
25
|
+
# https://www.gnu.org/licenses/
|
|
26
|
+
# ****************************************************************************
|
|
27
|
+
from itertools import product
|
|
28
|
+
|
|
29
|
+
from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
|
|
30
|
+
from sage.combinat.composition import Composition
|
|
31
|
+
from sage.combinat.partition import Partition
|
|
32
|
+
from sage.combinat.permutation import Permutations
|
|
33
|
+
from sage.combinat.skew_partition import SkewPartition
|
|
34
|
+
from sage.combinat.skew_tableau import SkewTableaux
|
|
35
|
+
from sage.combinat.tableau import Tableau
|
|
36
|
+
from sage.misc.cachefunc import cached_method
|
|
37
|
+
from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass
|
|
38
|
+
from sage.misc.lazy_import import lazy_import
|
|
39
|
+
from sage.structure.element import Matrix
|
|
40
|
+
from sage.structure.list_clone import ClonableArray
|
|
41
|
+
from sage.structure.parent import Parent
|
|
42
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
43
|
+
|
|
44
|
+
lazy_import('sage.combinat.tiling', 'Polyomino')
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Diagram(ClonableArray, metaclass=InheritComparisonClasscallMetaclass):
|
|
48
|
+
r"""
|
|
49
|
+
Combinatorial diagrams with positions indexed by rows and columns.
|
|
50
|
+
|
|
51
|
+
The positions are indexed by rows and columns as in a matrix. For example,
|
|
52
|
+
a Ferrers diagram is a diagram obtained from a partition
|
|
53
|
+
`\lambda = (\lambda_0, \lambda_1, \ldots, \lambda_{\ell})`, where the
|
|
54
|
+
cells are in rows `i` for `0 \leq i \leq \ell` and the cells in row `i`
|
|
55
|
+
consist of `(i,j)` for `0 \leq j < \lambda_i`. In English notation, the
|
|
56
|
+
indices are read from top left to bottom right as in a matrix.
|
|
57
|
+
|
|
58
|
+
Indexing conventions are the same as
|
|
59
|
+
:class:`~sage.combinat.partition.Partition`. Printing the diagram of a
|
|
60
|
+
partition, however, will always be in English notation.
|
|
61
|
+
|
|
62
|
+
EXAMPLES:
|
|
63
|
+
|
|
64
|
+
To create an arbitrary diagram, pass a list of all cells::
|
|
65
|
+
|
|
66
|
+
sage: from sage.combinat.diagram import Diagram
|
|
67
|
+
sage: cells = [(0,0), (0,1), (1,0), (1,1), (4,4), (4,5), (4,6), (5,4), (7, 6)]
|
|
68
|
+
sage: D = Diagram(cells); D
|
|
69
|
+
[(0, 0), (0, 1), (1, 0), (1, 1), (4, 4), (4, 5), (4, 6), (5, 4), (7, 6)]
|
|
70
|
+
|
|
71
|
+
We can visualize the diagram by printing ``O``'s and ``.``'s. ``O``'s are
|
|
72
|
+
present in the cells which are present in the diagram and a ``.`` represents
|
|
73
|
+
the absence of a cell in the diagram::
|
|
74
|
+
|
|
75
|
+
sage: D.pp()
|
|
76
|
+
O O . . . . .
|
|
77
|
+
O O . . . . .
|
|
78
|
+
. . . . . . .
|
|
79
|
+
. . . . . . .
|
|
80
|
+
. . . . O O O
|
|
81
|
+
. . . . O . .
|
|
82
|
+
. . . . . . .
|
|
83
|
+
. . . . . . O
|
|
84
|
+
|
|
85
|
+
We can also check if certain cells are contained in a given diagram::
|
|
86
|
+
|
|
87
|
+
sage: (1, 0) in D
|
|
88
|
+
True
|
|
89
|
+
sage: (2, 2) in D
|
|
90
|
+
False
|
|
91
|
+
|
|
92
|
+
If you know that there are entire empty rows or columns at the end of the
|
|
93
|
+
diagram, you can manually pass them with keyword arguments ``n_rows=`` or
|
|
94
|
+
``n_cols=``::
|
|
95
|
+
|
|
96
|
+
sage: Diagram([(0,0), (0,3), (2,2), (2,4)]).pp()
|
|
97
|
+
O . . O .
|
|
98
|
+
. . . . .
|
|
99
|
+
. . O . O
|
|
100
|
+
sage: Diagram([(0,0), (0,3), (2,2), (2,4)], n_rows=6, n_cols=6).pp()
|
|
101
|
+
O . . O . .
|
|
102
|
+
. . . . . .
|
|
103
|
+
. . O . O .
|
|
104
|
+
. . . . . .
|
|
105
|
+
. . . . . .
|
|
106
|
+
. . . . . .
|
|
107
|
+
"""
|
|
108
|
+
@staticmethod
|
|
109
|
+
def __classcall_private__(self, cells, n_rows=None, n_cols=None, check=True):
|
|
110
|
+
r"""
|
|
111
|
+
Normalize the input so that it lives in the correct parent.
|
|
112
|
+
|
|
113
|
+
EXAMPLES::
|
|
114
|
+
|
|
115
|
+
sage: from sage.combinat.diagram import Diagram
|
|
116
|
+
sage: D = Diagram([(0,0), (0,3), (2,2), (2,4)])
|
|
117
|
+
sage: D.parent()
|
|
118
|
+
Combinatorial diagrams
|
|
119
|
+
"""
|
|
120
|
+
return Diagrams()(cells, n_rows, n_cols, check)
|
|
121
|
+
|
|
122
|
+
def __init__(self, parent, cells, n_rows=None, n_cols=None, check=True):
|
|
123
|
+
r"""
|
|
124
|
+
Initialize ``self``.
|
|
125
|
+
|
|
126
|
+
EXAMPLES::
|
|
127
|
+
|
|
128
|
+
sage: from sage.combinat.diagram import Diagram
|
|
129
|
+
sage: D1 = Diagram([(0,2),(0,3),(1,1),(3,2)])
|
|
130
|
+
sage: D1.cells()
|
|
131
|
+
[(0, 2), (0, 3), (1, 1), (3, 2)]
|
|
132
|
+
sage: D1.nrows()
|
|
133
|
+
4
|
|
134
|
+
sage: D1.ncols()
|
|
135
|
+
4
|
|
136
|
+
sage: TestSuite(D1).run()
|
|
137
|
+
|
|
138
|
+
We can specify the number of rows and columns explicitly,
|
|
139
|
+
in case they are supposed to be empty::
|
|
140
|
+
|
|
141
|
+
sage: D2 = Diagram([(0,2),(0,3),(1,1),(3,2)], n_cols=5)
|
|
142
|
+
sage: D2.cells()
|
|
143
|
+
[(0, 2), (0, 3), (1, 1), (3, 2)]
|
|
144
|
+
sage: D2.ncols()
|
|
145
|
+
5
|
|
146
|
+
sage: D2.pp()
|
|
147
|
+
. . O O .
|
|
148
|
+
. O . . .
|
|
149
|
+
. . . . .
|
|
150
|
+
. . O . .
|
|
151
|
+
sage: TestSuite(D2).run()
|
|
152
|
+
"""
|
|
153
|
+
self._cells = frozenset(cells)
|
|
154
|
+
|
|
155
|
+
if self._cells:
|
|
156
|
+
# minimum possible number of rows/cols
|
|
157
|
+
N_rows = max(c[0] for c in self._cells)
|
|
158
|
+
N_cols = max(c[1] for c in self._cells)
|
|
159
|
+
else: # if there are no cells
|
|
160
|
+
N_rows = -1
|
|
161
|
+
N_cols = -1
|
|
162
|
+
|
|
163
|
+
if n_rows is not None:
|
|
164
|
+
if n_rows <= N_rows:
|
|
165
|
+
raise ValueError('n_rows is too small')
|
|
166
|
+
self._n_rows = n_rows
|
|
167
|
+
else:
|
|
168
|
+
self._n_rows = N_rows + 1
|
|
169
|
+
if n_cols is not None:
|
|
170
|
+
if n_cols <= N_cols:
|
|
171
|
+
raise ValueError('n_cols is too small')
|
|
172
|
+
self._n_cols = n_cols
|
|
173
|
+
else:
|
|
174
|
+
self._n_cols = N_cols + 1
|
|
175
|
+
|
|
176
|
+
self._n_nonempty_rows = len(set(i for i, j in self._cells))
|
|
177
|
+
self._n_nonempty_cols = len(set(j for i, j in self._cells))
|
|
178
|
+
|
|
179
|
+
ClonableArray.__init__(self, parent, sorted(cells), check)
|
|
180
|
+
|
|
181
|
+
def pp(self):
|
|
182
|
+
r"""
|
|
183
|
+
Return a visualization of the diagram.
|
|
184
|
+
|
|
185
|
+
Cells which are present in the
|
|
186
|
+
diagram are filled with a ``O``. Cells which are not present in the
|
|
187
|
+
diagram are filled with a ``.``.
|
|
188
|
+
|
|
189
|
+
EXAMPLES::
|
|
190
|
+
|
|
191
|
+
sage: from sage.combinat.diagram import Diagram
|
|
192
|
+
sage: Diagram([(0,0), (0,3), (2,2), (2,4)]).pp()
|
|
193
|
+
O . . O .
|
|
194
|
+
. . . . .
|
|
195
|
+
. . O . O
|
|
196
|
+
sage: Diagram([(0,0), (0,3), (2,2), (2,4)], n_rows=6, n_cols=6).pp()
|
|
197
|
+
O . . O . .
|
|
198
|
+
. . . . . .
|
|
199
|
+
. . O . O .
|
|
200
|
+
. . . . . .
|
|
201
|
+
. . . . . .
|
|
202
|
+
. . . . . .
|
|
203
|
+
sage: Diagram([]).pp()
|
|
204
|
+
-
|
|
205
|
+
"""
|
|
206
|
+
if self._n_rows == 0 or self._n_cols == 0:
|
|
207
|
+
print('-')
|
|
208
|
+
return
|
|
209
|
+
print("\n".join(self._pretty_print()))
|
|
210
|
+
|
|
211
|
+
def _ascii_art_(self):
|
|
212
|
+
r"""
|
|
213
|
+
Return a visualization of the diagram.
|
|
214
|
+
|
|
215
|
+
Cells which are present in the
|
|
216
|
+
diagram are filled with a ``O``. Cells which are not present in the
|
|
217
|
+
diagram are filled with a ``.``.
|
|
218
|
+
|
|
219
|
+
EXAMPLES::
|
|
220
|
+
|
|
221
|
+
sage: from sage.combinat.diagram import Diagram
|
|
222
|
+
sage: ascii_art(Diagram([(0,0), (0,3), (2,2), (2,4)]))
|
|
223
|
+
O . . O .
|
|
224
|
+
. . . . .
|
|
225
|
+
. . O . O
|
|
226
|
+
sage: ascii_art(Diagram([(0,0), (0,3), (2,2), (2,4)], n_rows=6, n_cols=6))
|
|
227
|
+
O . . O . .
|
|
228
|
+
. . . . . .
|
|
229
|
+
. . O . O .
|
|
230
|
+
. . . . . .
|
|
231
|
+
. . . . . .
|
|
232
|
+
. . . . . .
|
|
233
|
+
sage: ascii_art(Diagram([]))
|
|
234
|
+
-
|
|
235
|
+
"""
|
|
236
|
+
from sage.typeset.ascii_art import ascii_art
|
|
237
|
+
if self._n_rows == 0 or self._n_cols == 0:
|
|
238
|
+
return ascii_art("-")
|
|
239
|
+
return ascii_art("\n".join(self._pretty_print()))
|
|
240
|
+
|
|
241
|
+
def _unicode_art_(self):
|
|
242
|
+
r"""
|
|
243
|
+
Return a unicode visualization of the diagram.
|
|
244
|
+
|
|
245
|
+
Cells which are present in the
|
|
246
|
+
diagram are filled with a crossed box. Cells which are not present in the
|
|
247
|
+
diagram are filled with an empty box.
|
|
248
|
+
|
|
249
|
+
EXAMPLES::
|
|
250
|
+
|
|
251
|
+
sage: from sage.combinat.diagram import Diagram
|
|
252
|
+
sage: unicode_art(Diagram([(0,0), (0,3), (2,2), (2,4)]))
|
|
253
|
+
┌─┬─┬─┬─┬─┐
|
|
254
|
+
│X│ │ │X│ │
|
|
255
|
+
├─┼─┼─┼─┼─┤
|
|
256
|
+
│ │ │ │ │ │
|
|
257
|
+
├─┼─┼─┼─┼─┤
|
|
258
|
+
│ │ │X│ │X│
|
|
259
|
+
└─┴─┴─┴─┴─┘
|
|
260
|
+
sage: unicode_art(Diagram([(0,0), (0,3), (2,2), (2,4)], n_rows=6, n_cols=6))
|
|
261
|
+
┌─┬─┬─┬─┬─┬─┐
|
|
262
|
+
│X│ │ │X│ │ │
|
|
263
|
+
├─┼─┼─┼─┼─┼─┤
|
|
264
|
+
│ │ │ │ │ │ │
|
|
265
|
+
├─┼─┼─┼─┼─┼─┤
|
|
266
|
+
│ │ │X│ │X│ │
|
|
267
|
+
├─┼─┼─┼─┼─┼─┤
|
|
268
|
+
│ │ │ │ │ │ │
|
|
269
|
+
├─┼─┼─┼─┼─┼─┤
|
|
270
|
+
│ │ │ │ │ │ │
|
|
271
|
+
├─┼─┼─┼─┼─┼─┤
|
|
272
|
+
│ │ │ │ │ │ │
|
|
273
|
+
└─┴─┴─┴─┴─┴─┘
|
|
274
|
+
sage: unicode_art(Diagram([]))
|
|
275
|
+
∅
|
|
276
|
+
"""
|
|
277
|
+
from sage.typeset.unicode_art import unicode_art
|
|
278
|
+
if self._n_rows == 0 or self._n_cols == 0:
|
|
279
|
+
return unicode_art("∅")
|
|
280
|
+
|
|
281
|
+
ndivs = self._n_cols - 1
|
|
282
|
+
cell = "│X"
|
|
283
|
+
empty = "│ "
|
|
284
|
+
it = self._pretty_print(cell, empty)
|
|
285
|
+
ret = "┌─" + "┬─"*ndivs + "┐"
|
|
286
|
+
ret += "\n" + next(it) + "│"
|
|
287
|
+
for row in it:
|
|
288
|
+
ret += "\n├─" + "┼─"*ndivs + "┤"
|
|
289
|
+
ret += "\n" + row + "│"
|
|
290
|
+
ret += "\n└─" + "┴─"*ndivs + "┘"
|
|
291
|
+
return unicode_art(ret)
|
|
292
|
+
|
|
293
|
+
def _pretty_print(self, cell='O ', empty='. '):
|
|
294
|
+
r"""
|
|
295
|
+
Return a visualization of the diagram.
|
|
296
|
+
|
|
297
|
+
Cells which are present in the
|
|
298
|
+
diagram are filled with ``cell``. Cells which are not present in the
|
|
299
|
+
diagram are filled with ``empty``.
|
|
300
|
+
|
|
301
|
+
EXAMPLES::
|
|
302
|
+
|
|
303
|
+
sage: from sage.combinat.diagram import Diagram
|
|
304
|
+
sage: "\n".join(Diagram([(0,0), (0,3), (2,2), (2,4)])._pretty_print('x ','. '))
|
|
305
|
+
'x . . x . \n. . . . . \n. . x . x '
|
|
306
|
+
sage: "\n".join(Diagram([(0,0), (0,3), (2,2), (2,4)], n_rows=6, n_cols=6)._pretty_print('x ','. '))
|
|
307
|
+
'x . . x . . \n. . . . . . \n. . x . x . \n. . . . . . \n. . . . . . \n. . . . . . '
|
|
308
|
+
"""
|
|
309
|
+
for i in range(self._n_rows):
|
|
310
|
+
output_str = ''
|
|
311
|
+
for j in range(self._n_cols):
|
|
312
|
+
if (i, j) in self:
|
|
313
|
+
output_str += cell
|
|
314
|
+
else:
|
|
315
|
+
output_str += empty
|
|
316
|
+
yield output_str
|
|
317
|
+
|
|
318
|
+
def _latex_(self):
|
|
319
|
+
r"""
|
|
320
|
+
Return a latex representation of ``self``.
|
|
321
|
+
|
|
322
|
+
EXAMPLES::
|
|
323
|
+
|
|
324
|
+
sage: from sage.combinat.diagram import Diagram
|
|
325
|
+
sage: latex(Diagram([]))
|
|
326
|
+
{\emptyset}
|
|
327
|
+
sage: latex(Diagram([(0,0), (0,3), (2,2), (2,4)]))
|
|
328
|
+
{\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}
|
|
329
|
+
\raisebox{-.6ex}{$\begin{array}[b]{*{5}{p{0.6ex}}}\cline{1-1}\cline{4-4}
|
|
330
|
+
\lr{\phantom{x}}&&&\lr{\phantom{x}}&\\\cline{1-1}\cline{4-4}
|
|
331
|
+
&&&&\\\cline{3-3}\cline{5-5}
|
|
332
|
+
&&\lr{\phantom{x}}&&\lr{\phantom{x}}\\\cline{3-3}\cline{5-5}
|
|
333
|
+
\end{array}$}
|
|
334
|
+
}
|
|
335
|
+
"""
|
|
336
|
+
if self._n_rows == 0 or self._n_cols == 0:
|
|
337
|
+
return "{\\emptyset}"
|
|
338
|
+
|
|
339
|
+
lr = r'\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}}'
|
|
340
|
+
|
|
341
|
+
array = [[("\\phantom{x}" if (i, j) in self else None)
|
|
342
|
+
for j in range(self._n_cols)]
|
|
343
|
+
for i in range(self._n_rows)]
|
|
344
|
+
|
|
345
|
+
def end_line(r):
|
|
346
|
+
# give the line ending to row ``r``
|
|
347
|
+
if r == 0:
|
|
348
|
+
return "".join(r'\cline{%s-%s}' % (i+1, i+1)
|
|
349
|
+
for i, j in enumerate(array[0]) if j is not None)
|
|
350
|
+
elif r == len(array):
|
|
351
|
+
return r"\\" + "".join(r'\cline{%s-%s}' % (i+1, i+1)
|
|
352
|
+
for i, j in enumerate(array[r-1]) if j is not None)
|
|
353
|
+
else:
|
|
354
|
+
out = r"\\" + "".join(r'\cline{%s-%s}' % (i+1, i+1)
|
|
355
|
+
for i, j in enumerate(array[r-1]) if j is not None)
|
|
356
|
+
out += "".join(r'\cline{%s-%s}' % (i+1, i+1)
|
|
357
|
+
for i, j in enumerate(array[r]) if j is not None)
|
|
358
|
+
return out
|
|
359
|
+
|
|
360
|
+
tex = r'\raisebox{-.6ex}{$\begin{array}[b]{*{%s}{p{0.6ex}}}' % (max(map(len, array)))
|
|
361
|
+
tex += end_line(0)+'\n'
|
|
362
|
+
for r in range(len(array)):
|
|
363
|
+
tex += '&'.join('' if c is None else r'\lr{%s}' % (c,) for c in array[r])
|
|
364
|
+
tex += end_line(r+1)+'\n'
|
|
365
|
+
return '{%s\n%s\n}' % (lr, tex+r'\end{array}$}')
|
|
366
|
+
|
|
367
|
+
def number_of_rows(self):
|
|
368
|
+
r"""
|
|
369
|
+
Return the total number of rows of ``self``.
|
|
370
|
+
|
|
371
|
+
EXAMPLES:
|
|
372
|
+
|
|
373
|
+
The following example has three rows which are filled, but they
|
|
374
|
+
are contained in rows 0 to 3 (for a total of four)::
|
|
375
|
+
|
|
376
|
+
sage: from sage.combinat.diagram import Diagram
|
|
377
|
+
sage: D1 = Diagram([(0,2),(0,3),(1,1),(3,2)])
|
|
378
|
+
sage: D1.number_of_rows()
|
|
379
|
+
4
|
|
380
|
+
sage: D1.nrows()
|
|
381
|
+
4
|
|
382
|
+
|
|
383
|
+
The total number of rows includes including those which are empty.
|
|
384
|
+
We can also include empty rows at the end::
|
|
385
|
+
|
|
386
|
+
sage: from sage.combinat.diagram import Diagram
|
|
387
|
+
sage: D = Diagram([(0,2),(0,3),(1,1),(3,2)], n_rows=6)
|
|
388
|
+
sage: D.number_of_rows()
|
|
389
|
+
6
|
|
390
|
+
sage: D.pp()
|
|
391
|
+
. . O O
|
|
392
|
+
. O . .
|
|
393
|
+
. . . .
|
|
394
|
+
. . O .
|
|
395
|
+
. . . .
|
|
396
|
+
. . . .
|
|
397
|
+
"""
|
|
398
|
+
return self._n_rows
|
|
399
|
+
|
|
400
|
+
nrows = number_of_rows
|
|
401
|
+
|
|
402
|
+
def number_of_cols(self):
|
|
403
|
+
r"""
|
|
404
|
+
Return the total number of rows of ``self``.
|
|
405
|
+
|
|
406
|
+
EXAMPLES:
|
|
407
|
+
|
|
408
|
+
The following example has three columns which are filled, but they
|
|
409
|
+
are contained in rows 0 to 3 (for a total of four)::
|
|
410
|
+
|
|
411
|
+
sage: from sage.combinat.diagram import Diagram
|
|
412
|
+
sage: D = Diagram([(0,2),(0,3),(1,1),(3,2)])
|
|
413
|
+
sage: D.number_of_cols()
|
|
414
|
+
4
|
|
415
|
+
sage: D.ncols()
|
|
416
|
+
4
|
|
417
|
+
|
|
418
|
+
We can also include empty columns at the end::
|
|
419
|
+
|
|
420
|
+
sage: from sage.combinat.diagram import Diagram
|
|
421
|
+
sage: D = Diagram([(0,2),(0,3),(1,1),(3,2)], n_cols=6)
|
|
422
|
+
sage: D.number_of_cols()
|
|
423
|
+
6
|
|
424
|
+
sage: D.pp()
|
|
425
|
+
. . O O . .
|
|
426
|
+
. O . . . .
|
|
427
|
+
. . . . . .
|
|
428
|
+
. . O . . .
|
|
429
|
+
"""
|
|
430
|
+
return self._n_cols
|
|
431
|
+
|
|
432
|
+
ncols = number_of_cols
|
|
433
|
+
|
|
434
|
+
def cells(self):
|
|
435
|
+
r"""
|
|
436
|
+
Return a ``list`` of the cells contained in the diagram ``self``.
|
|
437
|
+
|
|
438
|
+
EXAMPLES::
|
|
439
|
+
|
|
440
|
+
sage: from sage.combinat.diagram import Diagram
|
|
441
|
+
sage: D1 = Diagram([(0,2),(0,3),(1,1),(3,2)])
|
|
442
|
+
sage: D1.cells()
|
|
443
|
+
[(0, 2), (0, 3), (1, 1), (3, 2)]
|
|
444
|
+
"""
|
|
445
|
+
return sorted(self._cells)
|
|
446
|
+
|
|
447
|
+
def number_of_cells(self):
|
|
448
|
+
r"""
|
|
449
|
+
Return the total number of cells contained in the diagram ``self``.
|
|
450
|
+
|
|
451
|
+
EXAMPLES::
|
|
452
|
+
|
|
453
|
+
sage: from sage.combinat.diagram import Diagram
|
|
454
|
+
sage: D1 = Diagram([(0,2),(0,3),(1,1),(3,2)])
|
|
455
|
+
sage: D1.number_of_cells()
|
|
456
|
+
4
|
|
457
|
+
sage: D1.n_cells()
|
|
458
|
+
4
|
|
459
|
+
"""
|
|
460
|
+
return len(self._cells)
|
|
461
|
+
|
|
462
|
+
n_cells = number_of_cells
|
|
463
|
+
|
|
464
|
+
size = number_of_cells
|
|
465
|
+
|
|
466
|
+
def check(self):
|
|
467
|
+
r"""
|
|
468
|
+
Check that this is a valid diagram.
|
|
469
|
+
|
|
470
|
+
EXAMPLES::
|
|
471
|
+
|
|
472
|
+
sage: from sage.combinat.diagram import Diagram
|
|
473
|
+
sage: D = Diagram([(0,0), (0,3), (2,2), (2,4)])
|
|
474
|
+
sage: D.check()
|
|
475
|
+
|
|
476
|
+
In the next two examples, a bad diagram is passed.
|
|
477
|
+
The first example fails because one cell is indexed by negative
|
|
478
|
+
integers::
|
|
479
|
+
|
|
480
|
+
sage: D = Diagram([(0,0), (0,-3), (2,2), (2,4)])
|
|
481
|
+
Traceback (most recent call last):
|
|
482
|
+
...
|
|
483
|
+
ValueError: diagrams must be indexed by nonnegative integers
|
|
484
|
+
|
|
485
|
+
The next example fails because one cell is indexed by rational
|
|
486
|
+
numbers::
|
|
487
|
+
|
|
488
|
+
sage: D = Diagram([(0,0), (0,3), (2/3,2), (2,4)])
|
|
489
|
+
Traceback (most recent call last):
|
|
490
|
+
...
|
|
491
|
+
ValueError: diagrams must be indexed by nonnegative integers
|
|
492
|
+
"""
|
|
493
|
+
from sage.sets.non_negative_integers import NonNegativeIntegers
|
|
494
|
+
NN = NonNegativeIntegers()
|
|
495
|
+
if not all(i in NN for c in self._cells for i in c):
|
|
496
|
+
raise ValueError("diagrams must be indexed by nonnegative integers")
|
|
497
|
+
|
|
498
|
+
def specht_module(self, base_ring=None):
|
|
499
|
+
r"""
|
|
500
|
+
Return the Specht module corresponding to ``self``.
|
|
501
|
+
|
|
502
|
+
EXAMPLES::
|
|
503
|
+
|
|
504
|
+
sage: from sage.combinat.diagram import Diagram
|
|
505
|
+
sage: D = Diagram([(0,0), (1,1), (2,2), (2,3)])
|
|
506
|
+
sage: SM = D.specht_module(QQ) # needs sage.modules
|
|
507
|
+
sage: s = SymmetricFunctions(QQ).s() # needs sage.modules
|
|
508
|
+
sage: s(SM.frobenius_image()) # needs sage.modules
|
|
509
|
+
s[2, 1, 1] + s[2, 2] + 2*s[3, 1] + s[4]
|
|
510
|
+
"""
|
|
511
|
+
from sage.combinat.specht_module import SpechtModule
|
|
512
|
+
from sage.combinat.symmetric_group_algebra import SymmetricGroupAlgebra
|
|
513
|
+
if base_ring is None:
|
|
514
|
+
from sage.rings.rational_field import QQ
|
|
515
|
+
base_ring = QQ
|
|
516
|
+
R = SymmetricGroupAlgebra(base_ring, len(self))
|
|
517
|
+
return SpechtModule(R, self)
|
|
518
|
+
|
|
519
|
+
def specht_module_dimension(self, base_ring=None):
|
|
520
|
+
r"""
|
|
521
|
+
Return the dimension of the Specht module corresponding to ``self``.
|
|
522
|
+
|
|
523
|
+
INPUT:
|
|
524
|
+
|
|
525
|
+
- ``base_ring`` -- (default: `\QQ`) the base ring
|
|
526
|
+
|
|
527
|
+
EXAMPLES::
|
|
528
|
+
|
|
529
|
+
sage: from sage.combinat.diagram import Diagram
|
|
530
|
+
sage: D = Diagram([(0,0), (1,1), (2,2), (2,3)])
|
|
531
|
+
sage: D.specht_module_dimension() # needs sage.modules
|
|
532
|
+
12
|
|
533
|
+
sage: D.specht_module(QQ).dimension() # needs sage.modules
|
|
534
|
+
12
|
|
535
|
+
"""
|
|
536
|
+
from sage.combinat.specht_module import specht_module_rank
|
|
537
|
+
return specht_module_rank(self, base_ring)
|
|
538
|
+
|
|
539
|
+
@cached_method
|
|
540
|
+
def essential_set(self):
|
|
541
|
+
r"""
|
|
542
|
+
Return the essential set of ``self`` as defined by Fulton.
|
|
543
|
+
|
|
544
|
+
Let `D` be a diagram. Then the *essential set* of `D` are the
|
|
545
|
+
cells `(i, j) \in D` such that `(i+1, j) \notin D` and
|
|
546
|
+
`(i, j+1) \notin D`; that is, the maximally southwest elements
|
|
547
|
+
in each connected component of `D`.
|
|
548
|
+
|
|
549
|
+
EXAMPLES::
|
|
550
|
+
|
|
551
|
+
sage: w = Permutation([2, 1, 5, 4, 3])
|
|
552
|
+
sage: D = w.rothe_diagram()
|
|
553
|
+
sage: D.essential_set()
|
|
554
|
+
((0, 0), (2, 3), (3, 2))
|
|
555
|
+
"""
|
|
556
|
+
ret = [c for c in self._cells if (c[0]+1, c[1]) not in self._cells
|
|
557
|
+
and (c[0], c[1]+1) not in self._cells]
|
|
558
|
+
ret.sort()
|
|
559
|
+
return tuple(ret)
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
class Diagrams(UniqueRepresentation, Parent):
|
|
563
|
+
r"""
|
|
564
|
+
The class of combinatorial diagrams.
|
|
565
|
+
|
|
566
|
+
A *combinatorial diagram* is a set of cells indexed by pairs of natural
|
|
567
|
+
numbers. Calling an instance of :class:`Diagrams` is one way to construct
|
|
568
|
+
diagrams.
|
|
569
|
+
|
|
570
|
+
EXAMPLES::
|
|
571
|
+
|
|
572
|
+
sage: from sage.combinat.diagram import Diagrams
|
|
573
|
+
sage: Dgms = Diagrams()
|
|
574
|
+
sage: D = Dgms([(0,0), (0,3), (2,2), (2,4)])
|
|
575
|
+
sage: D.parent()
|
|
576
|
+
Combinatorial diagrams
|
|
577
|
+
"""
|
|
578
|
+
|
|
579
|
+
def __init__(self, category=None):
|
|
580
|
+
r"""
|
|
581
|
+
Initialize ``self``.
|
|
582
|
+
|
|
583
|
+
EXAMPLES::
|
|
584
|
+
|
|
585
|
+
sage: from sage.combinat.diagram import Diagrams
|
|
586
|
+
sage: Dgms = Diagrams(); Dgms
|
|
587
|
+
Combinatorial diagrams
|
|
588
|
+
|
|
589
|
+
TESTS::
|
|
590
|
+
|
|
591
|
+
sage: TestSuite(Dgms).run()
|
|
592
|
+
"""
|
|
593
|
+
Parent.__init__(self, category=InfiniteEnumeratedSets().or_subcategory(category))
|
|
594
|
+
|
|
595
|
+
def __iter__(self):
|
|
596
|
+
r"""
|
|
597
|
+
Iterate over ``self``.
|
|
598
|
+
|
|
599
|
+
EXAMPLES::
|
|
600
|
+
|
|
601
|
+
sage: from sage.combinat.diagram import Diagrams
|
|
602
|
+
sage: I = iter(Diagrams())
|
|
603
|
+
sage: for i in range(10):
|
|
604
|
+
....: print(next(I))
|
|
605
|
+
[]
|
|
606
|
+
[(0, 0)]
|
|
607
|
+
[(1, 0)]
|
|
608
|
+
[(0, 0), (1, 0)]
|
|
609
|
+
[(0, 1)]
|
|
610
|
+
[(0, 0), (0, 1)]
|
|
611
|
+
[(0, 1), (1, 0)]
|
|
612
|
+
[(0, 0), (0, 1), (1, 0)]
|
|
613
|
+
[(2, 0)]
|
|
614
|
+
[(0, 0), (2, 0)]
|
|
615
|
+
sage: next(I).parent()
|
|
616
|
+
Combinatorial diagrams
|
|
617
|
+
|
|
618
|
+
sage: from sage.combinat.diagram import NorthwestDiagrams
|
|
619
|
+
sage: I = iter(NorthwestDiagrams())
|
|
620
|
+
sage: for i in range(20):
|
|
621
|
+
....: print(next(I))
|
|
622
|
+
[]
|
|
623
|
+
[(0, 0)]
|
|
624
|
+
[(1, 0)]
|
|
625
|
+
[(0, 0), (1, 0)]
|
|
626
|
+
[(0, 1)]
|
|
627
|
+
[(0, 0), (0, 1)]
|
|
628
|
+
[(0, 0), (0, 1), (1, 0)]
|
|
629
|
+
[(2, 0)]
|
|
630
|
+
[(0, 0), (2, 0)]
|
|
631
|
+
[(1, 0), (2, 0)]
|
|
632
|
+
[(0, 0), (1, 0), (2, 0)]
|
|
633
|
+
[(0, 0), (0, 1), (2, 0)]
|
|
634
|
+
[(0, 0), (0, 1), (1, 0), (2, 0)]
|
|
635
|
+
[(1, 1)]
|
|
636
|
+
[(0, 0), (1, 1)]
|
|
637
|
+
[(1, 0), (1, 1)]
|
|
638
|
+
[(0, 0), (1, 0), (1, 1)]
|
|
639
|
+
[(0, 1), (1, 1)]
|
|
640
|
+
[(0, 0), (0, 1), (1, 1)]
|
|
641
|
+
[(0, 0), (0, 1), (1, 0), (1, 1)]
|
|
642
|
+
"""
|
|
643
|
+
from sage.sets.non_negative_integers import NonNegativeIntegers
|
|
644
|
+
from sage.categories.cartesian_product import cartesian_product
|
|
645
|
+
from sage.combinat.subset import subsets
|
|
646
|
+
# the product of positive integers automatically implements an
|
|
647
|
+
# an enumeration which allows us to get out of the first column
|
|
648
|
+
N = NonNegativeIntegers()
|
|
649
|
+
NxN = cartesian_product([N, N])
|
|
650
|
+
X = subsets(NxN)
|
|
651
|
+
while True:
|
|
652
|
+
cells = next(X)
|
|
653
|
+
try:
|
|
654
|
+
yield self.element_class(self, tuple((i, j) for i, j in cells))
|
|
655
|
+
except ValueError:
|
|
656
|
+
# if cells causes the .check method of a
|
|
657
|
+
# subclass to fail, just go to the next one
|
|
658
|
+
pass
|
|
659
|
+
|
|
660
|
+
def _repr_(self):
|
|
661
|
+
r"""
|
|
662
|
+
Return a string representation of ``self``.
|
|
663
|
+
|
|
664
|
+
EXAMPLES::
|
|
665
|
+
|
|
666
|
+
sage: from sage.combinat.diagram import Diagrams
|
|
667
|
+
sage: Dgms = Diagrams(); Dgms
|
|
668
|
+
Combinatorial diagrams
|
|
669
|
+
"""
|
|
670
|
+
return 'Combinatorial diagrams'
|
|
671
|
+
|
|
672
|
+
def _element_constructor_(self, cells, n_rows=None, n_cols=None, check=True):
|
|
673
|
+
r"""
|
|
674
|
+
Construct an element of ``self``.
|
|
675
|
+
|
|
676
|
+
EXAMPLES::
|
|
677
|
+
|
|
678
|
+
sage: from sage.combinat.diagram import Diagrams
|
|
679
|
+
sage: Dgms = Diagrams()
|
|
680
|
+
sage: Dgms([(0,1),(2,2)]).pp()
|
|
681
|
+
. O .
|
|
682
|
+
. . .
|
|
683
|
+
. . O
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
sage: from sage.combinat.tiling import Polyomino # needs sage.modules
|
|
687
|
+
sage: p = Polyomino([(0,0),(1,0),(1,1),(1,2)]) # needs sage.modules
|
|
688
|
+
sage: Dgms(p).pp() # needs sage.modules
|
|
689
|
+
O . .
|
|
690
|
+
O O O
|
|
691
|
+
|
|
692
|
+
sage: from sage.combinat.composition import Composition
|
|
693
|
+
sage: a = Composition([4,2,0,2,4])
|
|
694
|
+
sage: Dgms(a).pp()
|
|
695
|
+
O O O O
|
|
696
|
+
O O . .
|
|
697
|
+
. . . .
|
|
698
|
+
O O . .
|
|
699
|
+
O O O O
|
|
700
|
+
|
|
701
|
+
sage: M = Matrix([[1,1,1,1],[1,1,0,0],[0,0,0,0],[1,1,0,0],[1,1,1,1]]) # needs sage.modules
|
|
702
|
+
sage: Dgms(M).pp() # needs sage.modules
|
|
703
|
+
O O O O
|
|
704
|
+
O O . .
|
|
705
|
+
. . . .
|
|
706
|
+
O O . .
|
|
707
|
+
O O O O
|
|
708
|
+
|
|
709
|
+
TESTS::
|
|
710
|
+
|
|
711
|
+
sage: TestSuite(Dgms).run()
|
|
712
|
+
"""
|
|
713
|
+
if isinstance(cells, Polyomino):
|
|
714
|
+
return self.from_polyomino(cells)
|
|
715
|
+
if isinstance(cells, Composition):
|
|
716
|
+
return self.from_composition(cells)
|
|
717
|
+
if isinstance(cells, Matrix):
|
|
718
|
+
return self.from_zero_one_matrix(cells)
|
|
719
|
+
|
|
720
|
+
return self.element_class(self, cells, n_rows, n_cols, check)
|
|
721
|
+
|
|
722
|
+
def _an_element_(self):
|
|
723
|
+
r"""
|
|
724
|
+
Return an element of ``self``.
|
|
725
|
+
|
|
726
|
+
EXAMPLES::
|
|
727
|
+
|
|
728
|
+
sage: from sage.combinat.diagram import Diagrams
|
|
729
|
+
sage: Dgms = Diagrams()
|
|
730
|
+
sage: D = Dgms.an_element(); D
|
|
731
|
+
[(0, 2), (1, 1), (2, 3)]
|
|
732
|
+
sage: D.pp()
|
|
733
|
+
. . O .
|
|
734
|
+
. O . .
|
|
735
|
+
. . . O
|
|
736
|
+
"""
|
|
737
|
+
return self([(0, 2), (1, 1), (2, 3)])
|
|
738
|
+
|
|
739
|
+
def from_polyomino(self, p):
|
|
740
|
+
r"""
|
|
741
|
+
Create the diagram corresponding to a 2d
|
|
742
|
+
:class:`~sage.combinat.tiling.Polyomino`
|
|
743
|
+
|
|
744
|
+
EXAMPLES::
|
|
745
|
+
|
|
746
|
+
sage: from sage.combinat.tiling import Polyomino # needs sage.modules
|
|
747
|
+
sage: p = Polyomino([(0,0),(1,0),(1,1),(1,2)]) # needs sage.modules
|
|
748
|
+
sage: from sage.combinat.diagram import Diagrams
|
|
749
|
+
sage: Diagrams()(p).pp() # needs sage.modules
|
|
750
|
+
O . .
|
|
751
|
+
O O O
|
|
752
|
+
|
|
753
|
+
We can also call this method directly::
|
|
754
|
+
|
|
755
|
+
sage: Diagrams().from_polyomino(p).pp() # needs sage.modules
|
|
756
|
+
O . .
|
|
757
|
+
O O O
|
|
758
|
+
|
|
759
|
+
This only works for a 2d :class:`~sage.combinat.tiling.Polyomino`::
|
|
760
|
+
|
|
761
|
+
sage: p = Polyomino([(0,0,0), (0,1,0), (1,1,0), (1,1,1)], color='blue') # needs sage.modules
|
|
762
|
+
sage: Diagrams().from_polyomino(p) # needs sage.modules
|
|
763
|
+
Traceback (most recent call last):
|
|
764
|
+
...
|
|
765
|
+
ValueError: the polyomino must be 2 dimensional
|
|
766
|
+
"""
|
|
767
|
+
if not p._dimension == 2:
|
|
768
|
+
raise ValueError("the polyomino must be 2 dimensional")
|
|
769
|
+
cells = list(map(tuple, p))
|
|
770
|
+
return self.element_class(self, cells)
|
|
771
|
+
|
|
772
|
+
def from_composition(self, alpha):
|
|
773
|
+
r"""
|
|
774
|
+
Create the diagram corresponding to a weak composition `\alpha \vDash n`.
|
|
775
|
+
|
|
776
|
+
EXAMPLES::
|
|
777
|
+
|
|
778
|
+
sage: alpha = Composition([3,0,2,1,4,4])
|
|
779
|
+
sage: from sage.combinat.diagram import Diagrams
|
|
780
|
+
sage: Diagrams()(alpha).pp()
|
|
781
|
+
O O O .
|
|
782
|
+
. . . .
|
|
783
|
+
O O . .
|
|
784
|
+
O . . .
|
|
785
|
+
O O O O
|
|
786
|
+
O O O O
|
|
787
|
+
sage: Diagrams().from_composition(alpha).pp()
|
|
788
|
+
O O O .
|
|
789
|
+
. . . .
|
|
790
|
+
O O . .
|
|
791
|
+
O . . .
|
|
792
|
+
O O O O
|
|
793
|
+
O O O O
|
|
794
|
+
"""
|
|
795
|
+
cells = []
|
|
796
|
+
for i, n in enumerate(alpha):
|
|
797
|
+
cells.extend((i, j) for j in range(n))
|
|
798
|
+
return self.element_class(self, cells, check=False)
|
|
799
|
+
|
|
800
|
+
def from_zero_one_matrix(self, M, check=True):
|
|
801
|
+
r"""
|
|
802
|
+
Get a diagram from a matrix with entries in `\{0, 1\}`, where
|
|
803
|
+
positions of cells are indicated by the `1`'s.
|
|
804
|
+
|
|
805
|
+
EXAMPLES::
|
|
806
|
+
|
|
807
|
+
sage: M = matrix([[1,0,1,1],[0,1,1,0]]) # needs sage.modules
|
|
808
|
+
sage: from sage.combinat.diagram import Diagrams
|
|
809
|
+
sage: Diagrams()(M).pp() # needs sage.modules
|
|
810
|
+
O . O O
|
|
811
|
+
. O O .
|
|
812
|
+
sage: Diagrams().from_zero_one_matrix(M).pp() # needs sage.modules
|
|
813
|
+
O . O O
|
|
814
|
+
. O O .
|
|
815
|
+
|
|
816
|
+
sage: M = matrix([[1, 0, 0], [1, 0, 0], [0, 0, 0]]) # needs sage.modules
|
|
817
|
+
sage: Diagrams()(M).pp() # needs sage.modules
|
|
818
|
+
O . .
|
|
819
|
+
O . .
|
|
820
|
+
. . .
|
|
821
|
+
"""
|
|
822
|
+
# check matrix is zero-one
|
|
823
|
+
n_rows, n_cols = M.dimensions()
|
|
824
|
+
|
|
825
|
+
if check:
|
|
826
|
+
zero = M.base_ring().zero()
|
|
827
|
+
one = M.base_ring().one()
|
|
828
|
+
for i in range(n_rows):
|
|
829
|
+
for j in range(n_cols):
|
|
830
|
+
if not (M[i, j] == zero or M[i, j] == one):
|
|
831
|
+
raise ValueError("matrix entries must be 0 or 1")
|
|
832
|
+
cells = [(i, j) for i in range(n_rows) for j in range(n_cols) if M[i, j]]
|
|
833
|
+
|
|
834
|
+
return self.element_class(self, cells, n_rows, n_cols, check=False)
|
|
835
|
+
|
|
836
|
+
Element = Diagram
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
####################
|
|
840
|
+
# Northwest diagrams
|
|
841
|
+
####################
|
|
842
|
+
|
|
843
|
+
class NorthwestDiagram(Diagram, metaclass=InheritComparisonClasscallMetaclass):
|
|
844
|
+
r"""
|
|
845
|
+
Diagrams with the northwest property.
|
|
846
|
+
|
|
847
|
+
A diagram is a set of cells indexed by natural numbers. Such a diagram
|
|
848
|
+
has the *northwest property* if the presence of cells `(i1, j1)` and
|
|
849
|
+
`(i2, j2)` implies the presence of the cell
|
|
850
|
+
`(\min(i1, i2), \min(j1, j2))`. Diagrams with the northwest property are
|
|
851
|
+
called *northwest diagrams*.
|
|
852
|
+
|
|
853
|
+
For general diagrams see :class:`Diagram`.
|
|
854
|
+
|
|
855
|
+
EXAMPLES::
|
|
856
|
+
|
|
857
|
+
sage: from sage.combinat.diagram import NorthwestDiagram
|
|
858
|
+
sage: N = NorthwestDiagram([(0,0), (0, 2), (2,0)])
|
|
859
|
+
|
|
860
|
+
To visualize them, use the ``.pp()`` method::
|
|
861
|
+
|
|
862
|
+
sage: N.pp()
|
|
863
|
+
O . O
|
|
864
|
+
. . .
|
|
865
|
+
O . .
|
|
866
|
+
"""
|
|
867
|
+
@staticmethod
|
|
868
|
+
def __classcall_private__(self, cells, n_rows=None, n_cols=None, check=True):
|
|
869
|
+
"""
|
|
870
|
+
Normalize input to ensure a correct parent. This method also allows
|
|
871
|
+
one to specify whether or not to check the northwest property for the
|
|
872
|
+
provided cells.
|
|
873
|
+
|
|
874
|
+
EXAMPLES::
|
|
875
|
+
|
|
876
|
+
sage: from sage.combinat.diagram import NorthwestDiagram, NorthwestDiagrams
|
|
877
|
+
sage: N1 = NorthwestDiagram([(0,1), (0,2)])
|
|
878
|
+
sage: N2 = NorthwestDiagram([(0,1), (0,3)])
|
|
879
|
+
sage: N1.parent() is N2.parent()
|
|
880
|
+
True
|
|
881
|
+
sage: N3 = NorthwestDiagrams()([(0,1), (0,2)])
|
|
882
|
+
sage: N3.parent() is NorthwestDiagrams()
|
|
883
|
+
True
|
|
884
|
+
sage: N1.parent() is NorthwestDiagrams()
|
|
885
|
+
True
|
|
886
|
+
"""
|
|
887
|
+
return NorthwestDiagrams()(cells, n_rows, n_cols, check)
|
|
888
|
+
|
|
889
|
+
def check(self):
|
|
890
|
+
r"""
|
|
891
|
+
A diagram has the northwest property if the presence of cells
|
|
892
|
+
`(i1, j1)` and `(i2, j2)` implies the presence of the cell
|
|
893
|
+
`(min(i1, i2), min(j1, j2))`. This method checks if the northwest
|
|
894
|
+
property is satisfied for ``self``
|
|
895
|
+
|
|
896
|
+
EXAMPLES::
|
|
897
|
+
|
|
898
|
+
sage: from sage.combinat.diagram import NorthwestDiagram
|
|
899
|
+
sage: N = NorthwestDiagram([(0,0), (0,3), (3,0)])
|
|
900
|
+
sage: N.check()
|
|
901
|
+
|
|
902
|
+
Here is a non-example::
|
|
903
|
+
|
|
904
|
+
sage: notN = NorthwestDiagram([(0,1), (1,0)]) #.check() is implicit
|
|
905
|
+
Traceback (most recent call last):
|
|
906
|
+
...
|
|
907
|
+
ValueError: diagram is not northwest
|
|
908
|
+
|
|
909
|
+
TESTS::
|
|
910
|
+
|
|
911
|
+
sage: NorthwestDiagram([(0,1/2)])
|
|
912
|
+
Traceback (most recent call last):
|
|
913
|
+
...
|
|
914
|
+
ValueError: diagrams must be indexed by nonnegative integers
|
|
915
|
+
"""
|
|
916
|
+
from itertools import combinations
|
|
917
|
+
Diagram.check(self)
|
|
918
|
+
if not all((min(i1, i2), min(j1, j2)) in self
|
|
919
|
+
for (i1, j1), (i2, j2) in combinations(self._cells, 2)):
|
|
920
|
+
raise ValueError("diagram is not northwest")
|
|
921
|
+
|
|
922
|
+
def peelable_tableaux(self):
|
|
923
|
+
r"""
|
|
924
|
+
Return the set of peelable tableaux whose diagram is ``self``.
|
|
925
|
+
|
|
926
|
+
For a fixed northwest diagram `D`, we say that a Young tableau `T` is
|
|
927
|
+
`D`-peelable if:
|
|
928
|
+
|
|
929
|
+
1. the row indices of the cells in the first column of `D` are
|
|
930
|
+
the entries in an initial segment in the first column of `T` and
|
|
931
|
+
2. the tableau `Q` obtained by removing those cells from `T` and playing
|
|
932
|
+
jeu de taquin is `(D-C)`-peelable, where `D-C` is the diagram formed
|
|
933
|
+
by forgetting the first column of `D`.
|
|
934
|
+
|
|
935
|
+
Reiner and Shimozono [RS1995]_ showed that the number
|
|
936
|
+
`\operatorname{red}(w)` of reduced words of a permutation `w` may be
|
|
937
|
+
computed using the peelable tableaux of the Rothe diagram `D(w)`.
|
|
938
|
+
Explicitly,
|
|
939
|
+
|
|
940
|
+
.. MATH::
|
|
941
|
+
|
|
942
|
+
\operatorname{red}(w) = \sum_{T} f_{\operatorname{shape} T},
|
|
943
|
+
|
|
944
|
+
where the sum runs over the `D(w)`-peelable tableaux `T` and `f_\lambda`
|
|
945
|
+
is the number of standard Young tableaux of shape `\lambda` (which may
|
|
946
|
+
be computed using the hook-length formula).
|
|
947
|
+
|
|
948
|
+
EXAMPLES:
|
|
949
|
+
|
|
950
|
+
We can compute the `D`-peelable diagrams for a northwest diagram `D`::
|
|
951
|
+
|
|
952
|
+
sage: from sage.combinat.diagram import NorthwestDiagram
|
|
953
|
+
sage: cells = [(0,0), (0,1), (0,2), (1,0), (2,0), (2,2), (2,4),
|
|
954
|
+
....: (4,0), (4,2)]
|
|
955
|
+
sage: D = NorthwestDiagram(cells); D.pp()
|
|
956
|
+
O O O . .
|
|
957
|
+
O . . . .
|
|
958
|
+
O . O . O
|
|
959
|
+
. . . . .
|
|
960
|
+
O . O . .
|
|
961
|
+
sage: D.peelable_tableaux()
|
|
962
|
+
{[[1, 1, 1], [2, 3, 3], [3, 5], [5]],
|
|
963
|
+
[[1, 1, 1, 3], [2, 3], [3, 5], [5]]}
|
|
964
|
+
|
|
965
|
+
EXAMPLES:
|
|
966
|
+
|
|
967
|
+
If the diagram is only one column, there is only one peelable tableau::
|
|
968
|
+
|
|
969
|
+
sage: from sage.combinat.diagram import NorthwestDiagram
|
|
970
|
+
sage: NWD = NorthwestDiagram([(0,0), (2,0)])
|
|
971
|
+
sage: NWD.peelable_tableaux()
|
|
972
|
+
{[[1], [3]]}
|
|
973
|
+
|
|
974
|
+
From [RS1995]_, we know that there is only one peelable tableau for the
|
|
975
|
+
Rothe diagram of the permutation (in one line notation) `251643`::
|
|
976
|
+
|
|
977
|
+
sage: D = NorthwestDiagram([(1, 2), (1, 3), (3, 2), (3, 3), (4, 2)])
|
|
978
|
+
sage: D.pp()
|
|
979
|
+
. . . .
|
|
980
|
+
. . O O
|
|
981
|
+
. . . .
|
|
982
|
+
. . O O
|
|
983
|
+
. . O .
|
|
984
|
+
|
|
985
|
+
sage: D.peelable_tableaux()
|
|
986
|
+
{[[2, 2], [4, 4], [5]]}
|
|
987
|
+
|
|
988
|
+
Here are all the intermediate steps to compute the peelables for the
|
|
989
|
+
Rothe diagram of (in one-line notation) `64817235`. They are listed from
|
|
990
|
+
deepest in the recursion to the final step. The recursion has depth five
|
|
991
|
+
in this case so we will label the intermediate tableaux by `D_i` where
|
|
992
|
+
`i` is the step in the recursion at which they appear.
|
|
993
|
+
|
|
994
|
+
Start with the one that has a single column::
|
|
995
|
+
|
|
996
|
+
sage: D5 = NorthwestDiagram([(2,0)]); D5.pp()
|
|
997
|
+
.
|
|
998
|
+
.
|
|
999
|
+
O
|
|
1000
|
+
sage: D5.peelable_tableaux()
|
|
1001
|
+
{[[3]]}
|
|
1002
|
+
|
|
1003
|
+
Now we know all of the `D_5` peelables, so we can compute the `D_4`
|
|
1004
|
+
peelables::
|
|
1005
|
+
|
|
1006
|
+
sage: D4 = NorthwestDiagram([(0, 0), (2,0), (4, 0), (2, 2)])
|
|
1007
|
+
sage: D4.pp()
|
|
1008
|
+
O . .
|
|
1009
|
+
. . .
|
|
1010
|
+
O . O
|
|
1011
|
+
. . .
|
|
1012
|
+
O . .
|
|
1013
|
+
|
|
1014
|
+
sage: D4.peelable_tableaux()
|
|
1015
|
+
{[[1, 3], [3], [5]]}
|
|
1016
|
+
|
|
1017
|
+
There is only one `D_4` peelable, so we can compute the `D_3`
|
|
1018
|
+
peelables::
|
|
1019
|
+
|
|
1020
|
+
sage: D3 = NorthwestDiagram([(0,0), (0,1), (2, 1), (2, 3), (4,1)])
|
|
1021
|
+
sage: D3.pp()
|
|
1022
|
+
O O . .
|
|
1023
|
+
. . . .
|
|
1024
|
+
. O . O
|
|
1025
|
+
. . . .
|
|
1026
|
+
. O . .
|
|
1027
|
+
|
|
1028
|
+
sage: D3.peelable_tableaux()
|
|
1029
|
+
{[[1, 1], [3, 3], [5]], [[1, 1, 3], [3], [5]]}
|
|
1030
|
+
|
|
1031
|
+
Now compute the `D_2` peelables::
|
|
1032
|
+
|
|
1033
|
+
sage: cells = [(0,0), (0,1), (0,2), (1,0), (2,0), (2,2), (2,4),
|
|
1034
|
+
....: (4,0), (4,2)]
|
|
1035
|
+
sage: D2 = NorthwestDiagram(cells); D2.pp()
|
|
1036
|
+
O O O . .
|
|
1037
|
+
O . . . .
|
|
1038
|
+
O . O . O
|
|
1039
|
+
. . . . .
|
|
1040
|
+
O . O . .
|
|
1041
|
+
|
|
1042
|
+
sage: D2.peelable_tableaux()
|
|
1043
|
+
{[[1, 1, 1], [2, 3, 3], [3, 5], [5]],
|
|
1044
|
+
[[1, 1, 1, 3], [2, 3], [3, 5], [5]]}
|
|
1045
|
+
|
|
1046
|
+
And the `D_1` peelables::
|
|
1047
|
+
|
|
1048
|
+
sage: cells = [(0,0), (0,1), (0,2), (0,3), (1,0), (1,1), (2,0),
|
|
1049
|
+
....: (2,1), (2,3), (2,5), (4,0), (4,1), (4,3)]
|
|
1050
|
+
sage: D1 = NorthwestDiagram(cells); D1.pp()
|
|
1051
|
+
O O O O . .
|
|
1052
|
+
O O . . . .
|
|
1053
|
+
O O . O . O
|
|
1054
|
+
. . . . . .
|
|
1055
|
+
O O . O . .
|
|
1056
|
+
|
|
1057
|
+
sage: D1.peelable_tableaux()
|
|
1058
|
+
{[[1, 1, 1, 1], [2, 2, 3, 3], [3, 3, 5], [5, 5]],
|
|
1059
|
+
[[1, 1, 1, 1, 3], [2, 2, 3], [3, 3, 5], [5, 5]]}
|
|
1060
|
+
|
|
1061
|
+
Which we can use to get the `D` peelables::
|
|
1062
|
+
|
|
1063
|
+
sage: cells = [(0,0), (0,1), (0,2), (0,3), (0,4),
|
|
1064
|
+
....: (1,0), (1,1), (1,2),
|
|
1065
|
+
....: (2,0), (2,1), (2,2), (2,4), (2,6),
|
|
1066
|
+
....: (4,1), (4,2), (4,4)]
|
|
1067
|
+
sage: D = NorthwestDiagram(cells); D.pp()
|
|
1068
|
+
O O O O O . .
|
|
1069
|
+
O O O . . . .
|
|
1070
|
+
O O O . O . O
|
|
1071
|
+
. . . . . . .
|
|
1072
|
+
. O O . O . .
|
|
1073
|
+
sage: D.peelable_tableaux()
|
|
1074
|
+
{[[1, 1, 1, 1, 1], [2, 2, 2, 3, 3], [3, 3, 3], [5, 5, 5]],
|
|
1075
|
+
[[1, 1, 1, 1, 1], [2, 2, 2, 3, 3], [3, 3, 3, 5], [5, 5]],
|
|
1076
|
+
[[1, 1, 1, 1, 1, 3], [2, 2, 2, 3], [3, 3, 3], [5, 5, 5]],
|
|
1077
|
+
[[1, 1, 1, 1, 1, 3], [2, 2, 2, 3], [3, 3, 3, 5], [5, 5]]}
|
|
1078
|
+
|
|
1079
|
+
ALGORITHM:
|
|
1080
|
+
|
|
1081
|
+
This implementation uses the algorithm suggested in Remark 25
|
|
1082
|
+
of [RS1995]_.
|
|
1083
|
+
|
|
1084
|
+
TESTS:
|
|
1085
|
+
|
|
1086
|
+
Corner case::
|
|
1087
|
+
|
|
1088
|
+
sage: from sage.combinat.diagram import NorthwestDiagram
|
|
1089
|
+
sage: D = NorthwestDiagram([])
|
|
1090
|
+
sage: D.peelable_tableaux()
|
|
1091
|
+
{[]}
|
|
1092
|
+
"""
|
|
1093
|
+
# TODO: There is a condition on the first column (if the rows in Dhat
|
|
1094
|
+
# are a subset of the rows in the first column) which simplifies the
|
|
1095
|
+
# description without performing JDT, so we should implement that
|
|
1096
|
+
|
|
1097
|
+
# empty diagram case
|
|
1098
|
+
if not self:
|
|
1099
|
+
return set([Tableau([])])
|
|
1100
|
+
|
|
1101
|
+
# if there is a single column in the diagram then there is only
|
|
1102
|
+
# one posslbe peelable tableau.
|
|
1103
|
+
if self._n_nonempty_cols == 1:
|
|
1104
|
+
return set([Tableau([[i+1] for i, j in self.cells()])])
|
|
1105
|
+
|
|
1106
|
+
first_col = min(j for i, j in self._cells)
|
|
1107
|
+
|
|
1108
|
+
dhat_cells = []
|
|
1109
|
+
new_vals_cells = []
|
|
1110
|
+
for i, j in self._cells:
|
|
1111
|
+
if j != first_col:
|
|
1112
|
+
dhat_cells.append((i, j))
|
|
1113
|
+
else:
|
|
1114
|
+
new_vals_cells.append(i + 1)
|
|
1115
|
+
|
|
1116
|
+
new_vals = sorted(new_vals_cells)
|
|
1117
|
+
|
|
1118
|
+
Dhat = NorthwestDiagram(dhat_cells)
|
|
1119
|
+
k = self.n_cells() - Dhat.n_cells()
|
|
1120
|
+
|
|
1121
|
+
peelables = set()
|
|
1122
|
+
|
|
1123
|
+
for Q in Dhat.peelable_tableaux():
|
|
1124
|
+
# get the vertical strips
|
|
1125
|
+
mu = Q.shape()
|
|
1126
|
+
vertical_strip_cells = mu.vertical_border_strip_cells(k)
|
|
1127
|
+
for s in vertical_strip_cells:
|
|
1128
|
+
sQ = SkewTableaux()(Q) # sQ is skew - get it?
|
|
1129
|
+
# perform the jeu de taquin slides
|
|
1130
|
+
for c in s:
|
|
1131
|
+
sQ = sQ.backward_slide(c)
|
|
1132
|
+
# create the new tableau by filling the columns
|
|
1133
|
+
sQ_new = sQ.to_list()
|
|
1134
|
+
for n in range(k):
|
|
1135
|
+
sQ_new[n][0] = new_vals[n]
|
|
1136
|
+
|
|
1137
|
+
T = Tableau(sQ_new)
|
|
1138
|
+
if T.is_column_strict():
|
|
1139
|
+
peelables.add(T)
|
|
1140
|
+
|
|
1141
|
+
return peelables
|
|
1142
|
+
|
|
1143
|
+
|
|
1144
|
+
class NorthwestDiagrams(Diagrams):
|
|
1145
|
+
r"""
|
|
1146
|
+
Diagrams satisfying the northwest property.
|
|
1147
|
+
|
|
1148
|
+
A diagram `D` is a *northwest diagram* if for every two cells `(i_1, j_1)`
|
|
1149
|
+
and `(i_2, j_2)` in `D` then there exists the cell
|
|
1150
|
+
`(\min(i_1, i_2), \min(j_1, j_2)) \in D`.
|
|
1151
|
+
|
|
1152
|
+
EXAMPLES::
|
|
1153
|
+
|
|
1154
|
+
sage: from sage.combinat.diagram import NorthwestDiagram
|
|
1155
|
+
sage: N = NorthwestDiagram([(0,0), (0, 10), (5,0)]); N.pp()
|
|
1156
|
+
O . . . . . . . . . O
|
|
1157
|
+
. . . . . . . . . . .
|
|
1158
|
+
. . . . . . . . . . .
|
|
1159
|
+
. . . . . . . . . . .
|
|
1160
|
+
. . . . . . . . . . .
|
|
1161
|
+
O . . . . . . . . . .
|
|
1162
|
+
|
|
1163
|
+
Note that checking whether or not the northwest property is satisfied is
|
|
1164
|
+
automatically checked. The diagram found by adding the cell `(1,1)` to the
|
|
1165
|
+
diagram above is *not* a northwest diagram. The cell `(1,0)` should be
|
|
1166
|
+
present due to the presence of `(5,0)` and `(1,1)`::
|
|
1167
|
+
|
|
1168
|
+
sage: from sage.combinat.diagram import Diagram
|
|
1169
|
+
sage: Diagram([(0, 0), (0, 10), (5, 0), (1, 1)]).pp()
|
|
1170
|
+
O . . . . . . . . . O
|
|
1171
|
+
. O . . . . . . . . .
|
|
1172
|
+
. . . . . . . . . . .
|
|
1173
|
+
. . . . . . . . . . .
|
|
1174
|
+
. . . . . . . . . . .
|
|
1175
|
+
O . . . . . . . . . .
|
|
1176
|
+
sage: NorthwestDiagram([(0, 0), (0, 10), (5, 0), (1, 1)])
|
|
1177
|
+
Traceback (most recent call last):
|
|
1178
|
+
...
|
|
1179
|
+
ValueError: diagram is not northwest
|
|
1180
|
+
|
|
1181
|
+
However, this behavior can be turned off if you are confident that
|
|
1182
|
+
you are providing a northwest diagram::
|
|
1183
|
+
|
|
1184
|
+
sage: N = NorthwestDiagram([(0, 0), (0, 10), (5, 0),
|
|
1185
|
+
....: (1, 1), (0, 1), (1, 0)],
|
|
1186
|
+
....: check=False)
|
|
1187
|
+
sage: N.pp()
|
|
1188
|
+
O O . . . . . . . . O
|
|
1189
|
+
O O . . . . . . . . .
|
|
1190
|
+
. . . . . . . . . . .
|
|
1191
|
+
. . . . . . . . . . .
|
|
1192
|
+
. . . . . . . . . . .
|
|
1193
|
+
O . . . . . . . . . .
|
|
1194
|
+
|
|
1195
|
+
Note that arbitrary diagrams which happen to be northwest diagrams
|
|
1196
|
+
only live in the parent of :class:`Diagrams`::
|
|
1197
|
+
|
|
1198
|
+
sage: D = Diagram([(0, 0), (0, 10), (5, 0), (1, 1), (0, 1), (1, 0)])
|
|
1199
|
+
sage: D.pp()
|
|
1200
|
+
O O . . . . . . . . O
|
|
1201
|
+
O O . . . . . . . . .
|
|
1202
|
+
. . . . . . . . . . .
|
|
1203
|
+
. . . . . . . . . . .
|
|
1204
|
+
. . . . . . . . . . .
|
|
1205
|
+
O . . . . . . . . . .
|
|
1206
|
+
sage: from sage.combinat.diagram import NorthwestDiagrams
|
|
1207
|
+
sage: D in NorthwestDiagrams()
|
|
1208
|
+
False
|
|
1209
|
+
|
|
1210
|
+
Here are some more examples::
|
|
1211
|
+
|
|
1212
|
+
sage: from sage.combinat.diagram import NorthwestDiagram, NorthwestDiagrams
|
|
1213
|
+
sage: D = NorthwestDiagram([(0,1), (0,2), (1,1)]); D.pp()
|
|
1214
|
+
. O O
|
|
1215
|
+
. O .
|
|
1216
|
+
sage: NWDgms = NorthwestDiagrams()
|
|
1217
|
+
sage: D = NWDgms([(1,1), (1,2), (2,1)]); D.pp()
|
|
1218
|
+
. . .
|
|
1219
|
+
. O O
|
|
1220
|
+
. O .
|
|
1221
|
+
sage: D.parent()
|
|
1222
|
+
Combinatorial northwest diagrams
|
|
1223
|
+
|
|
1224
|
+
Additionally, there are natural constructions of a northwest diagram
|
|
1225
|
+
given the data of a permutation (Rothe diagrams are the prototypical example
|
|
1226
|
+
of northwest diagrams), or the data of a partition of an integer, or a
|
|
1227
|
+
skew partition.
|
|
1228
|
+
|
|
1229
|
+
The Rothe diagram `D(\omega)` of a permutation `\omega` is specified by
|
|
1230
|
+
the cells
|
|
1231
|
+
|
|
1232
|
+
.. MATH::
|
|
1233
|
+
|
|
1234
|
+
D(\omega) = \{(\omega_j, i) : i<j,\, \omega_i > \omega_j \}.
|
|
1235
|
+
|
|
1236
|
+
We can construct one by calling :meth:`rothe_diagram` method on the set
|
|
1237
|
+
of all :class:`~sage.combinat.diagram.NorthwestDiagrams`::
|
|
1238
|
+
|
|
1239
|
+
sage: w = Permutations(4)([4,3,2,1])
|
|
1240
|
+
sage: NorthwestDiagrams().rothe_diagram(w).pp()
|
|
1241
|
+
O O O .
|
|
1242
|
+
O O . .
|
|
1243
|
+
O . . .
|
|
1244
|
+
. . . .
|
|
1245
|
+
|
|
1246
|
+
To turn a Ferrers diagram into a northwest diagram, we may call
|
|
1247
|
+
:meth:`from_partition`. This will return a Ferrer's diagram in the
|
|
1248
|
+
set of all northwest diagrams. For many use-cases it is probably better
|
|
1249
|
+
to get Ferrer's diagrams by the corresponding method on partitions, namely
|
|
1250
|
+
:meth:`sage.combinat.partitions.Partitions.ferrers_diagram`::
|
|
1251
|
+
|
|
1252
|
+
sage: mu = Partition([7,3,1,1])
|
|
1253
|
+
sage: mu.pp()
|
|
1254
|
+
*******
|
|
1255
|
+
***
|
|
1256
|
+
*
|
|
1257
|
+
*
|
|
1258
|
+
sage: NorthwestDiagrams().from_partition(mu).pp()
|
|
1259
|
+
O O O O O O O
|
|
1260
|
+
O O O . . . .
|
|
1261
|
+
O . . . . . .
|
|
1262
|
+
O . . . . . .
|
|
1263
|
+
|
|
1264
|
+
It is also possible to turn a Ferrers diagram of a skew partition into a
|
|
1265
|
+
northwest diagram, although it is more subtle than just using the skew
|
|
1266
|
+
diagram itself. One must first reflect the partition about a vertical axis
|
|
1267
|
+
so that the skew partition looks "backwards"::
|
|
1268
|
+
|
|
1269
|
+
sage: mu, nu = Partition([5,4,3,2,1]), Partition([3,2,1])
|
|
1270
|
+
sage: s = mu/nu; s.pp()
|
|
1271
|
+
**
|
|
1272
|
+
**
|
|
1273
|
+
**
|
|
1274
|
+
**
|
|
1275
|
+
*
|
|
1276
|
+
sage: NorthwestDiagrams().from_skew_partition(s).pp()
|
|
1277
|
+
O O . . .
|
|
1278
|
+
. O O . .
|
|
1279
|
+
. . O O .
|
|
1280
|
+
. . . O O
|
|
1281
|
+
. . . . O
|
|
1282
|
+
"""
|
|
1283
|
+
|
|
1284
|
+
def _repr_(self):
|
|
1285
|
+
r"""
|
|
1286
|
+
Return a string representation of ``self``.
|
|
1287
|
+
|
|
1288
|
+
EXAMPLES::
|
|
1289
|
+
|
|
1290
|
+
sage: from sage.combinat.diagram import NorthwestDiagrams
|
|
1291
|
+
sage: NWDgms = NorthwestDiagrams(); NWDgms
|
|
1292
|
+
Combinatorial northwest diagrams
|
|
1293
|
+
"""
|
|
1294
|
+
return 'Combinatorial northwest diagrams'
|
|
1295
|
+
|
|
1296
|
+
def _an_element_(self):
|
|
1297
|
+
r"""
|
|
1298
|
+
Return an element of ``self``.
|
|
1299
|
+
|
|
1300
|
+
EXAMPLES::
|
|
1301
|
+
|
|
1302
|
+
sage: from sage.combinat.diagram import NorthwestDiagrams
|
|
1303
|
+
sage: NWDgms = NorthwestDiagrams()
|
|
1304
|
+
sage: NWD = NWDgms.an_element(); NWD
|
|
1305
|
+
[(0, 1), (0, 2), (1, 1), (2, 3)]
|
|
1306
|
+
sage: NWD.pp()
|
|
1307
|
+
. O O .
|
|
1308
|
+
. O . .
|
|
1309
|
+
. . . O
|
|
1310
|
+
sage: NWD.parent() is NWDgms
|
|
1311
|
+
True
|
|
1312
|
+
"""
|
|
1313
|
+
return self([(0, 1), (0, 2), (1, 1), (2, 3)])
|
|
1314
|
+
|
|
1315
|
+
def rothe_diagram(self, w):
|
|
1316
|
+
r"""
|
|
1317
|
+
Return the Rothe diagram of ``w``.
|
|
1318
|
+
|
|
1319
|
+
We construct a northwest diagram from a permutation by
|
|
1320
|
+
constructing its Rothe diagram. Formally, if `\omega` is
|
|
1321
|
+
a :class:`~sage.combinat.permutation.Permutation`
|
|
1322
|
+
then the Rothe diagram `D(\omega)` is the diagram whose cells are
|
|
1323
|
+
|
|
1324
|
+
.. MATH::
|
|
1325
|
+
|
|
1326
|
+
D(\omega) = \{(\omega_j, i) : i<j,\, \omega_i > \omega_j \}.
|
|
1327
|
+
|
|
1328
|
+
Informally, one can construct the Rothe diagram by starting with all
|
|
1329
|
+
`n^2` possible cells, and then deleting the cells `(i, \omega(i))` as
|
|
1330
|
+
well as all cells to the right and below. (These are sometimes called
|
|
1331
|
+
"death rays".)
|
|
1332
|
+
|
|
1333
|
+
.. SEEALSO::
|
|
1334
|
+
|
|
1335
|
+
:func:`~sage.combinat.diagram.RotheDiagram`
|
|
1336
|
+
|
|
1337
|
+
EXAMPLES::
|
|
1338
|
+
|
|
1339
|
+
sage: from sage.combinat.diagram import NorthwestDiagrams
|
|
1340
|
+
sage: w = Permutations(3)([2,1,3])
|
|
1341
|
+
sage: NorthwestDiagrams().rothe_diagram(w).pp()
|
|
1342
|
+
O . .
|
|
1343
|
+
. . .
|
|
1344
|
+
. . .
|
|
1345
|
+
sage: NorthwestDiagrams().from_permutation(w).pp()
|
|
1346
|
+
O . .
|
|
1347
|
+
. . .
|
|
1348
|
+
. . .
|
|
1349
|
+
|
|
1350
|
+
sage: w = Permutations(8)([2,5,4,1,3,6,7,8])
|
|
1351
|
+
sage: NorthwestDiagrams().rothe_diagram(w).pp()
|
|
1352
|
+
O . . . . . . .
|
|
1353
|
+
O . O O . . . .
|
|
1354
|
+
O . O . . . . .
|
|
1355
|
+
. . . . . . . .
|
|
1356
|
+
. . . . . . . .
|
|
1357
|
+
. . . . . . . .
|
|
1358
|
+
. . . . . . . .
|
|
1359
|
+
. . . . . . . .
|
|
1360
|
+
"""
|
|
1361
|
+
return RotheDiagram(w)
|
|
1362
|
+
|
|
1363
|
+
from_permutation = rothe_diagram
|
|
1364
|
+
|
|
1365
|
+
def from_partition(self, mu):
|
|
1366
|
+
r"""
|
|
1367
|
+
Return the Ferrer's diagram of ``mu`` as a northwest diagram.
|
|
1368
|
+
|
|
1369
|
+
EXAMPLES::
|
|
1370
|
+
|
|
1371
|
+
sage: mu = Partition([5,2,1]); mu.pp()
|
|
1372
|
+
*****
|
|
1373
|
+
**
|
|
1374
|
+
*
|
|
1375
|
+
sage: mu.parent()
|
|
1376
|
+
Partitions
|
|
1377
|
+
sage: from sage.combinat.diagram import NorthwestDiagrams
|
|
1378
|
+
sage: D = NorthwestDiagrams().from_partition(mu)
|
|
1379
|
+
sage: D.pp()
|
|
1380
|
+
O O O O O
|
|
1381
|
+
O O . . .
|
|
1382
|
+
O . . . .
|
|
1383
|
+
sage: D.parent()
|
|
1384
|
+
Combinatorial northwest diagrams
|
|
1385
|
+
|
|
1386
|
+
This will print in English notation even if the notation is set to
|
|
1387
|
+
French for the partition::
|
|
1388
|
+
|
|
1389
|
+
sage: Partitions.options.convention="french"
|
|
1390
|
+
sage: mu.pp()
|
|
1391
|
+
*
|
|
1392
|
+
**
|
|
1393
|
+
*****
|
|
1394
|
+
sage: D.pp()
|
|
1395
|
+
O O O O O
|
|
1396
|
+
O O . . .
|
|
1397
|
+
O . . . .
|
|
1398
|
+
|
|
1399
|
+
TESTS::
|
|
1400
|
+
|
|
1401
|
+
sage: from sage.combinat.diagram import NorthwestDiagrams
|
|
1402
|
+
sage: mu = [5, 2, 1]
|
|
1403
|
+
sage: D = NorthwestDiagrams().from_partition(mu)
|
|
1404
|
+
Traceback (most recent call last):
|
|
1405
|
+
...
|
|
1406
|
+
ValueError: mu must be a Partition
|
|
1407
|
+
"""
|
|
1408
|
+
if not isinstance(mu, Partition):
|
|
1409
|
+
raise ValueError("mu must be a Partition")
|
|
1410
|
+
return self.element_class(self, mu.cells(), check=False)
|
|
1411
|
+
|
|
1412
|
+
def from_skew_partition(self, s):
|
|
1413
|
+
r"""
|
|
1414
|
+
Get the northwest diagram found by reflecting a skew shape across
|
|
1415
|
+
a vertical plane.
|
|
1416
|
+
|
|
1417
|
+
EXAMPLES::
|
|
1418
|
+
|
|
1419
|
+
sage: mu, nu = Partition([3,2,1]), Partition([2,1])
|
|
1420
|
+
sage: s = mu/nu; s.pp()
|
|
1421
|
+
*
|
|
1422
|
+
*
|
|
1423
|
+
*
|
|
1424
|
+
sage: from sage.combinat.diagram import NorthwestDiagrams
|
|
1425
|
+
sage: D = NorthwestDiagrams().from_skew_partition(s)
|
|
1426
|
+
sage: D.pp()
|
|
1427
|
+
O . .
|
|
1428
|
+
. O .
|
|
1429
|
+
. . O
|
|
1430
|
+
|
|
1431
|
+
sage: mu, nu = Partition([3,3,2]), Partition([2,2,2])
|
|
1432
|
+
sage: s = mu/nu; s.pp()
|
|
1433
|
+
*
|
|
1434
|
+
*
|
|
1435
|
+
sage: NorthwestDiagrams().from_skew_partition(s).pp()
|
|
1436
|
+
O . .
|
|
1437
|
+
O . .
|
|
1438
|
+
. . .
|
|
1439
|
+
|
|
1440
|
+
TESTS::
|
|
1441
|
+
|
|
1442
|
+
sage: mu = Partition([3,2,1])
|
|
1443
|
+
sage: NorthwestDiagrams().from_skew_partition(mu)
|
|
1444
|
+
Traceback (most recent call last):
|
|
1445
|
+
...
|
|
1446
|
+
ValueError: mu must be a SkewPartition
|
|
1447
|
+
"""
|
|
1448
|
+
if not isinstance(s, SkewPartition):
|
|
1449
|
+
raise ValueError("mu must be a SkewPartition")
|
|
1450
|
+
|
|
1451
|
+
n_cols = s.outer()[0]
|
|
1452
|
+
n_rows = len(s.outer())
|
|
1453
|
+
|
|
1454
|
+
cells = [(i, n_cols - 1 - j) for i, j in s.cells()]
|
|
1455
|
+
|
|
1456
|
+
return self.element_class(self, cells, n_rows, n_cols, check=False)
|
|
1457
|
+
|
|
1458
|
+
def from_parallelogram_polyomino(self, p):
|
|
1459
|
+
r"""
|
|
1460
|
+
Create the diagram corresponding to a
|
|
1461
|
+
:class:`~sage.combinat.parallelogram_polyomino.ParallelogramPolyomino`.
|
|
1462
|
+
|
|
1463
|
+
EXAMPLES::
|
|
1464
|
+
|
|
1465
|
+
sage: p = ParallelogramPolyomino([[0, 0, 1, 0, 0, 0, 1, 1], # needs sage.modules
|
|
1466
|
+
....: [1, 1, 0, 1, 0, 0, 0, 0]])
|
|
1467
|
+
sage: from sage.combinat.diagram import NorthwestDiagrams
|
|
1468
|
+
sage: NorthwestDiagrams().from_parallelogram_polyomino(p).pp() # needs sage.modules
|
|
1469
|
+
O O .
|
|
1470
|
+
O O O
|
|
1471
|
+
. O O
|
|
1472
|
+
. O O
|
|
1473
|
+
. O O
|
|
1474
|
+
"""
|
|
1475
|
+
from sage.matrix.constructor import Matrix
|
|
1476
|
+
M = Matrix(p.get_array())
|
|
1477
|
+
return self.from_zero_one_matrix(M)
|
|
1478
|
+
|
|
1479
|
+
Element = NorthwestDiagram
|
|
1480
|
+
|
|
1481
|
+
|
|
1482
|
+
def RotheDiagram(w):
|
|
1483
|
+
r"""
|
|
1484
|
+
The Rothe diagram of a permutation ``w``.
|
|
1485
|
+
|
|
1486
|
+
EXAMPLES::
|
|
1487
|
+
|
|
1488
|
+
sage: w = Permutations(9)([1, 7, 4, 5, 9, 3, 2, 8, 6])
|
|
1489
|
+
sage: from sage.combinat.diagram import RotheDiagram
|
|
1490
|
+
sage: D = RotheDiagram(w); D.pp()
|
|
1491
|
+
. . . . . . . . .
|
|
1492
|
+
. O O O O O . . .
|
|
1493
|
+
. O O . . . . . .
|
|
1494
|
+
. O O . . . . . .
|
|
1495
|
+
. O O . . O . O .
|
|
1496
|
+
. O . . . . . . .
|
|
1497
|
+
. . . . . . . . .
|
|
1498
|
+
. . . . . O . . .
|
|
1499
|
+
. . . . . . . . .
|
|
1500
|
+
|
|
1501
|
+
The Rothe diagram is a northwest diagram::
|
|
1502
|
+
|
|
1503
|
+
sage: D.parent()
|
|
1504
|
+
Combinatorial northwest diagrams
|
|
1505
|
+
|
|
1506
|
+
Some other examples::
|
|
1507
|
+
|
|
1508
|
+
sage: RotheDiagram([2, 1, 4, 3]).pp()
|
|
1509
|
+
O . . .
|
|
1510
|
+
. . . .
|
|
1511
|
+
. . O .
|
|
1512
|
+
. . . .
|
|
1513
|
+
|
|
1514
|
+
sage: RotheDiagram([4, 1, 3, 2]).pp()
|
|
1515
|
+
O O O .
|
|
1516
|
+
. . . .
|
|
1517
|
+
. O . .
|
|
1518
|
+
. . . .
|
|
1519
|
+
|
|
1520
|
+
Currently, only elements of the set of
|
|
1521
|
+
:class:`sage.combinat.permutations.Permutations` are supported. In
|
|
1522
|
+
particular, elements of permutation groups are not supported::
|
|
1523
|
+
|
|
1524
|
+
sage: w = SymmetricGroup(9).an_element() # needs sage.groups
|
|
1525
|
+
sage: RotheDiagram(w) # needs sage.groups
|
|
1526
|
+
Traceback (most recent call last):
|
|
1527
|
+
...
|
|
1528
|
+
ValueError: w must be a permutation
|
|
1529
|
+
|
|
1530
|
+
TESTS::
|
|
1531
|
+
|
|
1532
|
+
sage: w = Permutations(5)([1,2,3,4,5])
|
|
1533
|
+
sage: from sage.combinat.diagram import RotheDiagram
|
|
1534
|
+
sage: RotheDiagram(w).pp()
|
|
1535
|
+
. . . . .
|
|
1536
|
+
. . . . .
|
|
1537
|
+
. . . . .
|
|
1538
|
+
. . . . .
|
|
1539
|
+
. . . . .
|
|
1540
|
+
"""
|
|
1541
|
+
P = Permutations()
|
|
1542
|
+
if w not in P:
|
|
1543
|
+
raise ValueError('w must be a permutation')
|
|
1544
|
+
w = P(w)
|
|
1545
|
+
|
|
1546
|
+
N = w.size()
|
|
1547
|
+
winv = w.inverse()
|
|
1548
|
+
cells = [c for c in product(range(N), range(N))
|
|
1549
|
+
if c[0] + 1 < winv(c[1] + 1) and c[1] + 1 < w(c[0] + 1)]
|
|
1550
|
+
|
|
1551
|
+
return NorthwestDiagram(cells, n_rows=N, n_cols=N, check=False)
|