passagemath-combinat 10.6.42__cp314-cp314-musllinux_1_2_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_combinat/__init__.py +3 -0
- passagemath_combinat-10.6.42.dist-info/METADATA +160 -0
- passagemath_combinat-10.6.42.dist-info/RECORD +400 -0
- passagemath_combinat-10.6.42.dist-info/WHEEL +5 -0
- passagemath_combinat-10.6.42.dist-info/top_level.txt +3 -0
- passagemath_combinat.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
- passagemath_combinat.libs/libsymmetrica-81fe8739.so.3.0.0 +0 -0
- sage/algebras/affine_nil_temperley_lieb.py +263 -0
- sage/algebras/all.py +24 -0
- sage/algebras/all__sagemath_combinat.py +35 -0
- sage/algebras/askey_wilson.py +935 -0
- sage/algebras/associated_graded.py +345 -0
- sage/algebras/cellular_basis.py +350 -0
- sage/algebras/cluster_algebra.py +2766 -0
- sage/algebras/down_up_algebra.py +860 -0
- sage/algebras/free_algebra.py +1698 -0
- sage/algebras/free_algebra_element.py +345 -0
- sage/algebras/free_algebra_quotient.py +405 -0
- sage/algebras/free_algebra_quotient_element.py +295 -0
- sage/algebras/free_zinbiel_algebra.py +885 -0
- sage/algebras/hall_algebra.py +783 -0
- sage/algebras/hecke_algebras/all.py +4 -0
- sage/algebras/hecke_algebras/ariki_koike_algebra.py +1796 -0
- sage/algebras/hecke_algebras/ariki_koike_specht_modules.py +475 -0
- sage/algebras/hecke_algebras/cubic_hecke_algebra.py +3520 -0
- sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +1473 -0
- sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py +1079 -0
- sage/algebras/iwahori_hecke_algebra.py +3095 -0
- sage/algebras/jordan_algebra.py +1773 -0
- sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py +113 -0
- sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py +156 -0
- sage/algebras/lie_conformal_algebras/all.py +18 -0
- sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py +134 -0
- sage/algebras/lie_conformal_algebras/examples.py +43 -0
- sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py +131 -0
- sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py +139 -0
- sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py +174 -0
- sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +167 -0
- sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py +107 -0
- sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py +135 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +353 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py +236 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py +78 -0
- sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +328 -0
- sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py +117 -0
- sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py +86 -0
- sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py +82 -0
- sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py +205 -0
- sage/algebras/nil_coxeter_algebra.py +191 -0
- sage/algebras/q_commuting_polynomials.py +673 -0
- sage/algebras/q_system.py +608 -0
- sage/algebras/quantum_clifford.py +959 -0
- sage/algebras/quantum_groups/ace_quantum_onsager.py +693 -0
- sage/algebras/quantum_groups/all.py +9 -0
- sage/algebras/quantum_groups/fock_space.py +2219 -0
- sage/algebras/quantum_groups/q_numbers.py +207 -0
- sage/algebras/quantum_groups/quantum_group_gap.py +2695 -0
- sage/algebras/quantum_groups/representations.py +591 -0
- sage/algebras/quantum_matrix_coordinate_algebra.py +1006 -0
- sage/algebras/quantum_oscillator.py +623 -0
- sage/algebras/quaternion_algebra.py +20 -0
- sage/algebras/quaternion_algebra_element.py +55 -0
- sage/algebras/rational_cherednik_algebra.py +525 -0
- sage/algebras/schur_algebra.py +670 -0
- sage/algebras/shuffle_algebra.py +1011 -0
- sage/algebras/splitting_algebra.py +779 -0
- sage/algebras/tensor_algebra.py +709 -0
- sage/algebras/yangian.py +1082 -0
- sage/algebras/yokonuma_hecke_algebra.py +1018 -0
- sage/all__sagemath_combinat.py +35 -0
- sage/combinat/SJT.py +255 -0
- sage/combinat/affine_permutation.py +2405 -0
- sage/combinat/algebraic_combinatorics.py +55 -0
- sage/combinat/all.py +53 -0
- sage/combinat/all__sagemath_combinat.py +195 -0
- sage/combinat/alternating_sign_matrix.py +2063 -0
- sage/combinat/baxter_permutations.py +346 -0
- sage/combinat/bijectionist.py +3220 -0
- sage/combinat/binary_recurrence_sequences.py +1180 -0
- sage/combinat/blob_algebra.py +685 -0
- sage/combinat/catalog_partitions.py +27 -0
- sage/combinat/chas/all.py +23 -0
- sage/combinat/chas/fsym.py +1180 -0
- sage/combinat/chas/wqsym.py +2601 -0
- sage/combinat/cluster_complex.py +326 -0
- sage/combinat/colored_permutations.py +2039 -0
- sage/combinat/colored_permutations_representations.py +964 -0
- sage/combinat/composition_signed.py +142 -0
- sage/combinat/composition_tableau.py +855 -0
- sage/combinat/constellation.py +1729 -0
- sage/combinat/core.py +751 -0
- sage/combinat/counting.py +12 -0
- sage/combinat/crystals/affine.py +742 -0
- sage/combinat/crystals/affine_factorization.py +518 -0
- sage/combinat/crystals/affinization.py +331 -0
- sage/combinat/crystals/alcove_path.py +2013 -0
- sage/combinat/crystals/all.py +22 -0
- sage/combinat/crystals/bkk_crystals.py +141 -0
- sage/combinat/crystals/catalog.py +115 -0
- sage/combinat/crystals/catalog_elementary_crystals.py +18 -0
- sage/combinat/crystals/catalog_infinity_crystals.py +33 -0
- sage/combinat/crystals/catalog_kirillov_reshetikhin.py +18 -0
- sage/combinat/crystals/crystals.py +257 -0
- sage/combinat/crystals/direct_sum.py +260 -0
- sage/combinat/crystals/elementary_crystals.py +1251 -0
- sage/combinat/crystals/fast_crystals.py +441 -0
- sage/combinat/crystals/fully_commutative_stable_grothendieck.py +1205 -0
- sage/combinat/crystals/generalized_young_walls.py +1076 -0
- sage/combinat/crystals/highest_weight_crystals.py +436 -0
- sage/combinat/crystals/induced_structure.py +695 -0
- sage/combinat/crystals/infinity_crystals.py +730 -0
- sage/combinat/crystals/kac_modules.py +863 -0
- sage/combinat/crystals/kirillov_reshetikhin.py +4196 -0
- sage/combinat/crystals/kyoto_path_model.py +497 -0
- sage/combinat/crystals/letters.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/letters.pxd +79 -0
- sage/combinat/crystals/letters.pyx +3056 -0
- sage/combinat/crystals/littelmann_path.py +1518 -0
- sage/combinat/crystals/monomial_crystals.py +1262 -0
- sage/combinat/crystals/multisegments.py +462 -0
- sage/combinat/crystals/mv_polytopes.py +467 -0
- sage/combinat/crystals/pbw_crystal.py +511 -0
- sage/combinat/crystals/pbw_datum.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/pbw_datum.pxd +4 -0
- sage/combinat/crystals/pbw_datum.pyx +487 -0
- sage/combinat/crystals/polyhedral_realization.py +372 -0
- sage/combinat/crystals/spins.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/spins.pxd +21 -0
- sage/combinat/crystals/spins.pyx +756 -0
- sage/combinat/crystals/star_crystal.py +290 -0
- sage/combinat/crystals/subcrystal.py +464 -0
- sage/combinat/crystals/tensor_product.py +1177 -0
- sage/combinat/crystals/tensor_product_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/crystals/tensor_product_element.pxd +35 -0
- sage/combinat/crystals/tensor_product_element.pyx +1870 -0
- sage/combinat/crystals/virtual_crystal.py +420 -0
- sage/combinat/cyclic_sieving_phenomenon.py +204 -0
- sage/combinat/debruijn_sequence.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/debruijn_sequence.pyx +355 -0
- sage/combinat/decorated_permutation.py +270 -0
- sage/combinat/degree_sequences.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/degree_sequences.pyx +588 -0
- sage/combinat/derangements.py +527 -0
- sage/combinat/descent_algebra.py +1008 -0
- sage/combinat/diagram.py +1551 -0
- sage/combinat/diagram_algebras.py +5886 -0
- sage/combinat/dyck_word.py +4349 -0
- sage/combinat/e_one_star.py +1623 -0
- sage/combinat/enumerated_sets.py +123 -0
- sage/combinat/expnums.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/expnums.pyx +148 -0
- sage/combinat/fast_vector_partitions.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/fast_vector_partitions.pyx +346 -0
- sage/combinat/fqsym.py +1977 -0
- sage/combinat/free_dendriform_algebra.py +954 -0
- sage/combinat/free_prelie_algebra.py +1141 -0
- sage/combinat/fully_commutative_elements.py +1077 -0
- sage/combinat/fully_packed_loop.py +1523 -0
- sage/combinat/gelfand_tsetlin_patterns.py +1409 -0
- sage/combinat/gray_codes.py +311 -0
- sage/combinat/grossman_larson_algebras.py +667 -0
- sage/combinat/growth.py +4352 -0
- sage/combinat/hall_polynomial.py +188 -0
- sage/combinat/hillman_grassl.py +866 -0
- sage/combinat/integer_matrices.py +329 -0
- sage/combinat/integer_vectors_mod_permgroup.py +1238 -0
- sage/combinat/k_tableau.py +4564 -0
- sage/combinat/kazhdan_lusztig.py +215 -0
- sage/combinat/key_polynomial.py +885 -0
- sage/combinat/knutson_tao_puzzles.py +2286 -0
- sage/combinat/lr_tableau.py +311 -0
- sage/combinat/matrices/all.py +24 -0
- sage/combinat/matrices/hadamard_matrix.py +3790 -0
- sage/combinat/matrices/latin.py +2912 -0
- sage/combinat/misc.py +401 -0
- sage/combinat/multiset_partition_into_sets_ordered.py +3541 -0
- sage/combinat/ncsf_qsym/all.py +21 -0
- sage/combinat/ncsf_qsym/combinatorics.py +317 -0
- sage/combinat/ncsf_qsym/generic_basis_code.py +1427 -0
- sage/combinat/ncsf_qsym/ncsf.py +5637 -0
- sage/combinat/ncsf_qsym/qsym.py +4053 -0
- sage/combinat/ncsf_qsym/tutorial.py +447 -0
- sage/combinat/ncsym/all.py +21 -0
- sage/combinat/ncsym/bases.py +855 -0
- sage/combinat/ncsym/dual.py +593 -0
- sage/combinat/ncsym/ncsym.py +2076 -0
- sage/combinat/necklace.py +551 -0
- sage/combinat/non_decreasing_parking_function.py +634 -0
- sage/combinat/nu_dyck_word.py +1474 -0
- sage/combinat/output.py +861 -0
- sage/combinat/parallelogram_polyomino.py +4326 -0
- sage/combinat/parking_functions.py +1602 -0
- sage/combinat/partition_algebra.py +1998 -0
- sage/combinat/partition_kleshchev.py +1982 -0
- sage/combinat/partition_shifting_algebras.py +584 -0
- sage/combinat/partition_tuple.py +3114 -0
- sage/combinat/path_tableaux/all.py +13 -0
- sage/combinat/path_tableaux/catalog.py +29 -0
- sage/combinat/path_tableaux/dyck_path.py +380 -0
- sage/combinat/path_tableaux/frieze.py +476 -0
- sage/combinat/path_tableaux/path_tableau.py +728 -0
- sage/combinat/path_tableaux/semistandard.py +510 -0
- sage/combinat/perfect_matching.py +779 -0
- sage/combinat/plane_partition.py +3300 -0
- sage/combinat/q_bernoulli.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/q_bernoulli.pyx +128 -0
- sage/combinat/quickref.py +81 -0
- sage/combinat/recognizable_series.py +2051 -0
- sage/combinat/regular_sequence.py +4316 -0
- sage/combinat/regular_sequence_bounded.py +543 -0
- sage/combinat/restricted_growth.py +81 -0
- sage/combinat/ribbon.py +20 -0
- sage/combinat/ribbon_shaped_tableau.py +489 -0
- sage/combinat/ribbon_tableau.py +1180 -0
- sage/combinat/rigged_configurations/all.py +46 -0
- sage/combinat/rigged_configurations/bij_abstract_class.py +548 -0
- sage/combinat/rigged_configurations/bij_infinity.py +370 -0
- sage/combinat/rigged_configurations/bij_type_A.py +163 -0
- sage/combinat/rigged_configurations/bij_type_A2_dual.py +338 -0
- sage/combinat/rigged_configurations/bij_type_A2_even.py +218 -0
- sage/combinat/rigged_configurations/bij_type_A2_odd.py +199 -0
- sage/combinat/rigged_configurations/bij_type_B.py +900 -0
- sage/combinat/rigged_configurations/bij_type_C.py +267 -0
- sage/combinat/rigged_configurations/bij_type_D.py +771 -0
- sage/combinat/rigged_configurations/bij_type_D_tri.py +392 -0
- sage/combinat/rigged_configurations/bij_type_D_twisted.py +576 -0
- sage/combinat/rigged_configurations/bij_type_E67.py +402 -0
- sage/combinat/rigged_configurations/bijection.py +143 -0
- sage/combinat/rigged_configurations/kleber_tree.py +1475 -0
- sage/combinat/rigged_configurations/kr_tableaux.py +1898 -0
- sage/combinat/rigged_configurations/rc_crystal.py +461 -0
- sage/combinat/rigged_configurations/rc_infinity.py +540 -0
- sage/combinat/rigged_configurations/rigged_configuration_element.py +2403 -0
- sage/combinat/rigged_configurations/rigged_configurations.py +1918 -0
- sage/combinat/rigged_configurations/rigged_partition.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/rigged_configurations/rigged_partition.pxd +15 -0
- sage/combinat/rigged_configurations/rigged_partition.pyx +680 -0
- sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +499 -0
- sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py +428 -0
- sage/combinat/rsk.py +3438 -0
- sage/combinat/schubert_polynomial.py +508 -0
- sage/combinat/set_partition.py +3318 -0
- sage/combinat/set_partition_iterator.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/set_partition_iterator.pyx +136 -0
- sage/combinat/set_partition_ordered.py +1590 -0
- sage/combinat/sf/abreu_nigro.py +346 -0
- sage/combinat/sf/all.py +52 -0
- sage/combinat/sf/character.py +576 -0
- sage/combinat/sf/classical.py +319 -0
- sage/combinat/sf/dual.py +996 -0
- sage/combinat/sf/elementary.py +549 -0
- sage/combinat/sf/hall_littlewood.py +1028 -0
- sage/combinat/sf/hecke.py +336 -0
- sage/combinat/sf/homogeneous.py +464 -0
- sage/combinat/sf/jack.py +1428 -0
- sage/combinat/sf/k_dual.py +1458 -0
- sage/combinat/sf/kfpoly.py +447 -0
- sage/combinat/sf/llt.py +789 -0
- sage/combinat/sf/macdonald.py +2019 -0
- sage/combinat/sf/monomial.py +525 -0
- sage/combinat/sf/multiplicative.py +113 -0
- sage/combinat/sf/new_kschur.py +1786 -0
- sage/combinat/sf/ns_macdonald.py +964 -0
- sage/combinat/sf/orthogonal.py +246 -0
- sage/combinat/sf/orthotriang.py +355 -0
- sage/combinat/sf/powersum.py +963 -0
- sage/combinat/sf/schur.py +880 -0
- sage/combinat/sf/sf.py +1653 -0
- sage/combinat/sf/sfa.py +7053 -0
- sage/combinat/sf/symplectic.py +253 -0
- sage/combinat/sf/witt.py +721 -0
- sage/combinat/shifted_primed_tableau.py +2735 -0
- sage/combinat/shuffle.py +830 -0
- sage/combinat/sidon_sets.py +146 -0
- sage/combinat/similarity_class_type.py +1721 -0
- sage/combinat/sine_gordon.py +618 -0
- sage/combinat/six_vertex_model.py +784 -0
- sage/combinat/skew_partition.py +2053 -0
- sage/combinat/skew_tableau.py +2989 -0
- sage/combinat/sloane_functions.py +8935 -0
- sage/combinat/specht_module.py +1403 -0
- sage/combinat/species/all.py +48 -0
- sage/combinat/species/characteristic_species.py +321 -0
- sage/combinat/species/composition_species.py +273 -0
- sage/combinat/species/cycle_species.py +284 -0
- sage/combinat/species/empty_species.py +155 -0
- sage/combinat/species/functorial_composition_species.py +148 -0
- sage/combinat/species/generating_series.py +673 -0
- sage/combinat/species/library.py +148 -0
- sage/combinat/species/linear_order_species.py +169 -0
- sage/combinat/species/misc.py +83 -0
- sage/combinat/species/partition_species.py +290 -0
- sage/combinat/species/permutation_species.py +268 -0
- sage/combinat/species/product_species.py +423 -0
- sage/combinat/species/recursive_species.py +476 -0
- sage/combinat/species/set_species.py +192 -0
- sage/combinat/species/species.py +820 -0
- sage/combinat/species/structure.py +539 -0
- sage/combinat/species/subset_species.py +243 -0
- sage/combinat/species/sum_species.py +225 -0
- sage/combinat/subword.py +564 -0
- sage/combinat/subword_complex.py +2122 -0
- sage/combinat/subword_complex_c.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/subword_complex_c.pyx +119 -0
- sage/combinat/super_tableau.py +821 -0
- sage/combinat/superpartition.py +1154 -0
- sage/combinat/symmetric_group_algebra.py +3774 -0
- sage/combinat/symmetric_group_representations.py +1830 -0
- sage/combinat/t_sequences.py +877 -0
- sage/combinat/tableau.py +9506 -0
- sage/combinat/tableau_residues.py +860 -0
- sage/combinat/tableau_tuple.py +5353 -0
- sage/combinat/tiling.py +2432 -0
- sage/combinat/triangles_FHM.py +777 -0
- sage/combinat/tutorial.py +1857 -0
- sage/combinat/vector_partition.py +337 -0
- sage/combinat/words/abstract_word.py +1722 -0
- sage/combinat/words/all.py +59 -0
- sage/combinat/words/alphabet.py +268 -0
- sage/combinat/words/finite_word.py +7201 -0
- sage/combinat/words/infinite_word.py +113 -0
- sage/combinat/words/lyndon_word.py +652 -0
- sage/combinat/words/morphic.py +351 -0
- sage/combinat/words/morphism.py +3878 -0
- sage/combinat/words/paths.py +2932 -0
- sage/combinat/words/shuffle_product.py +278 -0
- sage/combinat/words/suffix_trees.py +1873 -0
- sage/combinat/words/word.py +769 -0
- sage/combinat/words/word_char.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/words/word_char.pyx +847 -0
- sage/combinat/words/word_datatypes.cpython-314-x86_64-linux-musl.so +0 -0
- sage/combinat/words/word_datatypes.pxd +4 -0
- sage/combinat/words/word_datatypes.pyx +1067 -0
- sage/combinat/words/word_generators.py +2026 -0
- sage/combinat/words/word_infinite_datatypes.py +1218 -0
- sage/combinat/words/word_options.py +99 -0
- sage/combinat/words/words.py +2396 -0
- sage/data_structures/all__sagemath_combinat.py +1 -0
- sage/databases/all__sagemath_combinat.py +13 -0
- sage/databases/findstat.py +4897 -0
- sage/databases/oeis.py +2058 -0
- sage/databases/sloane.py +393 -0
- sage/dynamics/all__sagemath_combinat.py +14 -0
- sage/dynamics/cellular_automata/all.py +7 -0
- sage/dynamics/cellular_automata/catalog.py +34 -0
- sage/dynamics/cellular_automata/elementary.py +612 -0
- sage/dynamics/cellular_automata/glca.py +477 -0
- sage/dynamics/cellular_automata/solitons.py +1463 -0
- sage/dynamics/finite_dynamical_system.py +1249 -0
- sage/dynamics/finite_dynamical_system_catalog.py +382 -0
- sage/games/all.py +7 -0
- sage/games/hexad.py +704 -0
- sage/games/quantumino.py +591 -0
- sage/games/sudoku.py +889 -0
- sage/games/sudoku_backtrack.cpython-314-x86_64-linux-musl.so +0 -0
- sage/games/sudoku_backtrack.pyx +189 -0
- sage/groups/all__sagemath_combinat.py +1 -0
- sage/groups/indexed_free_group.py +489 -0
- sage/libs/all__sagemath_combinat.py +6 -0
- sage/libs/lrcalc/__init__.py +1 -0
- sage/libs/lrcalc/lrcalc.py +525 -0
- sage/libs/symmetrica/__init__.py +7 -0
- sage/libs/symmetrica/all.py +101 -0
- sage/libs/symmetrica/kostka.pxi +168 -0
- sage/libs/symmetrica/part.pxi +193 -0
- sage/libs/symmetrica/plet.pxi +42 -0
- sage/libs/symmetrica/sab.pxi +196 -0
- sage/libs/symmetrica/sb.pxi +332 -0
- sage/libs/symmetrica/sc.pxi +192 -0
- sage/libs/symmetrica/schur.pxi +956 -0
- sage/libs/symmetrica/symmetrica.cpython-314-x86_64-linux-musl.so +0 -0
- sage/libs/symmetrica/symmetrica.pxi +1172 -0
- sage/libs/symmetrica/symmetrica.pyx +39 -0
- sage/monoids/all.py +13 -0
- sage/monoids/automatic_semigroup.py +1054 -0
- sage/monoids/free_abelian_monoid.py +315 -0
- sage/monoids/free_abelian_monoid_element.cpython-314-x86_64-linux-musl.so +0 -0
- sage/monoids/free_abelian_monoid_element.pxd +16 -0
- sage/monoids/free_abelian_monoid_element.pyx +397 -0
- sage/monoids/free_monoid.py +335 -0
- sage/monoids/free_monoid_element.py +431 -0
- sage/monoids/hecke_monoid.py +65 -0
- sage/monoids/string_monoid.py +817 -0
- sage/monoids/string_monoid_element.py +547 -0
- sage/monoids/string_ops.py +143 -0
- sage/monoids/trace_monoid.py +972 -0
- sage/rings/all__sagemath_combinat.py +2 -0
- sage/sat/all.py +4 -0
- sage/sat/boolean_polynomials.py +405 -0
- sage/sat/converters/__init__.py +6 -0
- sage/sat/converters/anf2cnf.py +14 -0
- sage/sat/converters/polybori.py +611 -0
- sage/sat/solvers/__init__.py +5 -0
- sage/sat/solvers/cryptominisat.py +287 -0
- sage/sat/solvers/dimacs.py +783 -0
- sage/sat/solvers/picosat.py +228 -0
- sage/sat/solvers/sat_lp.py +156 -0
- sage/sat/solvers/satsolver.cpython-314-x86_64-linux-musl.so +0 -0
- sage/sat/solvers/satsolver.pxd +3 -0
- sage/sat/solvers/satsolver.pyx +405 -0
|
@@ -0,0 +1,1590 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
r"""
|
|
3
|
+
Ordered set partitions
|
|
4
|
+
|
|
5
|
+
AUTHORS:
|
|
6
|
+
|
|
7
|
+
- Mike Hansen
|
|
8
|
+
- MuPAD-Combinat developers (for algorithms and design inspiration)
|
|
9
|
+
- Travis Scrimshaw (2013-02-28): Removed ``CombinatorialClass`` and added
|
|
10
|
+
entry point through :class:`OrderedSetPartition`.
|
|
11
|
+
"""
|
|
12
|
+
# ****************************************************************************
|
|
13
|
+
# Copyright (C) 2007 Mike Hansen <mhansen@gmail.com>,
|
|
14
|
+
#
|
|
15
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
16
|
+
#
|
|
17
|
+
# This code is distributed in the hope that it will be useful,
|
|
18
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
19
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
20
|
+
# General Public License for more details.
|
|
21
|
+
#
|
|
22
|
+
# The full text of the GPL is available at:
|
|
23
|
+
#
|
|
24
|
+
# https://www.gnu.org/licenses/
|
|
25
|
+
# ****************************************************************************
|
|
26
|
+
from itertools import product
|
|
27
|
+
|
|
28
|
+
from sage.arith.misc import factorial, multinomial
|
|
29
|
+
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
|
|
30
|
+
from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
|
|
31
|
+
from sage.combinat.combinat import stirling_number2
|
|
32
|
+
from sage.combinat.combinatorial_map import combinatorial_map
|
|
33
|
+
from sage.combinat.composition import Composition, Compositions
|
|
34
|
+
from sage.combinat.words.finite_word import FiniteWord_class
|
|
35
|
+
from sage.combinat.words.words import Words
|
|
36
|
+
from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass
|
|
37
|
+
from sage.misc.persist import register_unpickle_override
|
|
38
|
+
from sage.rings.integer import Integer
|
|
39
|
+
from sage.rings.integer_ring import ZZ
|
|
40
|
+
from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
|
|
41
|
+
from sage.sets.set import Set, Set_generic
|
|
42
|
+
from sage.structure.list_clone import ClonableArray
|
|
43
|
+
from sage.structure.element import parent
|
|
44
|
+
from sage.structure.parent import Parent
|
|
45
|
+
from sage.structure.richcmp import richcmp
|
|
46
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class OrderedSetPartition(ClonableArray,
|
|
50
|
+
metaclass=InheritComparisonClasscallMetaclass):
|
|
51
|
+
r"""
|
|
52
|
+
An ordered partition of a set.
|
|
53
|
+
|
|
54
|
+
An ordered set partition `p` of a set `s` is a list of pairwise
|
|
55
|
+
disjoint nonempty subsets of `s` such that the union of these
|
|
56
|
+
subsets is `s`. These subsets are called the parts of the partition.
|
|
57
|
+
|
|
58
|
+
We represent an ordered set partition as a list of sets. By
|
|
59
|
+
extension, an ordered set partition of a nonnegative integer `n` is
|
|
60
|
+
the set partition of the integers from `1` to `n`. The number of
|
|
61
|
+
ordered set partitions of `n` is called the `n`-th ordered Bell
|
|
62
|
+
number.
|
|
63
|
+
|
|
64
|
+
There is a natural integer composition associated with an ordered
|
|
65
|
+
set partition, that is the sequence of sizes of all its parts in
|
|
66
|
+
order.
|
|
67
|
+
|
|
68
|
+
The number `T_n` of ordered set partitions of
|
|
69
|
+
`\{ 1, 2, \ldots, n \}` is the so-called `n`-th *Fubini number*
|
|
70
|
+
(also known as the `n`-th ordered Bell number; see
|
|
71
|
+
:wikipedia:`Ordered Bell number`). Its exponential generating
|
|
72
|
+
function is
|
|
73
|
+
|
|
74
|
+
.. MATH::
|
|
75
|
+
|
|
76
|
+
\sum_n \frac{T_n}{n!} x^n = \frac{1}{2-e^x}.
|
|
77
|
+
|
|
78
|
+
(See sequence :oeis:`A000670` in OEIS.)
|
|
79
|
+
|
|
80
|
+
INPUT:
|
|
81
|
+
|
|
82
|
+
- ``parts`` -- an object or iterable that defines an ordered set partition
|
|
83
|
+
(e.g., a list of pairwise disjoint sets) or a packed word (e.g., a list
|
|
84
|
+
of letters on some alphabet). If there is ambiguity and if the input should
|
|
85
|
+
be treated as a packed word, the keyword ``from_word`` should be used.
|
|
86
|
+
|
|
87
|
+
EXAMPLES:
|
|
88
|
+
|
|
89
|
+
There are 13 ordered set partitions of `\{1,2,3\}`::
|
|
90
|
+
|
|
91
|
+
sage: OrderedSetPartitions(3).cardinality()
|
|
92
|
+
13
|
|
93
|
+
|
|
94
|
+
Here is the list of them::
|
|
95
|
+
|
|
96
|
+
sage: OrderedSetPartitions(3).list()
|
|
97
|
+
[[{1}, {2}, {3}],
|
|
98
|
+
[{1}, {3}, {2}],
|
|
99
|
+
[{2}, {1}, {3}],
|
|
100
|
+
[{3}, {1}, {2}],
|
|
101
|
+
[{2}, {3}, {1}],
|
|
102
|
+
[{3}, {2}, {1}],
|
|
103
|
+
[{1}, {2, 3}],
|
|
104
|
+
[{2}, {1, 3}],
|
|
105
|
+
[{3}, {1, 2}],
|
|
106
|
+
[{1, 2}, {3}],
|
|
107
|
+
[{1, 3}, {2}],
|
|
108
|
+
[{2, 3}, {1}],
|
|
109
|
+
[{1, 2, 3}]]
|
|
110
|
+
|
|
111
|
+
There are 12 ordered set partitions of `\{1,2,3,4\}` whose underlying
|
|
112
|
+
composition is `[1,2,1]`::
|
|
113
|
+
|
|
114
|
+
sage: OrderedSetPartitions(4,[1,2,1]).list()
|
|
115
|
+
[[{1}, {2, 3}, {4}],
|
|
116
|
+
[{1}, {2, 4}, {3}],
|
|
117
|
+
[{1}, {3, 4}, {2}],
|
|
118
|
+
[{2}, {1, 3}, {4}],
|
|
119
|
+
[{2}, {1, 4}, {3}],
|
|
120
|
+
[{3}, {1, 2}, {4}],
|
|
121
|
+
[{4}, {1, 2}, {3}],
|
|
122
|
+
[{3}, {1, 4}, {2}],
|
|
123
|
+
[{4}, {1, 3}, {2}],
|
|
124
|
+
[{2}, {3, 4}, {1}],
|
|
125
|
+
[{3}, {2, 4}, {1}],
|
|
126
|
+
[{4}, {2, 3}, {1}]]
|
|
127
|
+
|
|
128
|
+
Since :issue:`14140`, we can create an ordered set partition directly by
|
|
129
|
+
:class:`OrderedSetPartition` which creates the parent object by taking the
|
|
130
|
+
union of the partitions passed in. However it is recommended and
|
|
131
|
+
(marginally) faster to create the parent first and then create the ordered
|
|
132
|
+
set partition from that. ::
|
|
133
|
+
|
|
134
|
+
sage: s = OrderedSetPartition([[1,3],[2,4]]); s
|
|
135
|
+
[{1, 3}, {2, 4}]
|
|
136
|
+
sage: s.parent()
|
|
137
|
+
Ordered set partitions of {1, 2, 3, 4}
|
|
138
|
+
|
|
139
|
+
We can construct the ordered set partition from a word,
|
|
140
|
+
which we consider as packed::
|
|
141
|
+
|
|
142
|
+
sage: OrderedSetPartition([2,4,1,2])
|
|
143
|
+
[{3}, {1, 4}, {2}]
|
|
144
|
+
sage: OrderedSetPartition(from_word=[2,4,1,2])
|
|
145
|
+
[{3}, {1, 4}, {2}]
|
|
146
|
+
sage: OrderedSetPartition(from_word='bdab')
|
|
147
|
+
[{3}, {1, 4}, {2}]
|
|
148
|
+
|
|
149
|
+
.. WARNING::
|
|
150
|
+
|
|
151
|
+
The elements of the underlying set should be hashable.
|
|
152
|
+
|
|
153
|
+
REFERENCES:
|
|
154
|
+
|
|
155
|
+
:wikipedia:`Ordered_partition_of_a_set`
|
|
156
|
+
"""
|
|
157
|
+
@staticmethod
|
|
158
|
+
def __classcall_private__(cls, parts=None, from_word=None, check=True):
|
|
159
|
+
"""
|
|
160
|
+
Create a set partition from ``parts`` with the appropriate parent.
|
|
161
|
+
|
|
162
|
+
EXAMPLES::
|
|
163
|
+
|
|
164
|
+
sage: s = OrderedSetPartition([[1,3],[2,4]]); s
|
|
165
|
+
[{1, 3}, {2, 4}]
|
|
166
|
+
sage: s.parent()
|
|
167
|
+
Ordered set partitions of {1, 2, 3, 4}
|
|
168
|
+
sage: t = OrderedSetPartition([[2,4],[1,3]]); t
|
|
169
|
+
[{2, 4}, {1, 3}]
|
|
170
|
+
sage: s != t
|
|
171
|
+
True
|
|
172
|
+
sage: OrderedSetPartition()
|
|
173
|
+
[]
|
|
174
|
+
sage: OrderedSetPartition([])
|
|
175
|
+
[]
|
|
176
|
+
sage: OrderedSetPartition('')
|
|
177
|
+
[]
|
|
178
|
+
sage: OrderedSetPartition('bdab') == OrderedSetPartition(from_word='bdab')
|
|
179
|
+
True
|
|
180
|
+
sage: OrderedSetPartition('bdab') == OrderedSetPartition(Word('bdab'))
|
|
181
|
+
True
|
|
182
|
+
"""
|
|
183
|
+
if parts is None and from_word is None:
|
|
184
|
+
P = OrderedSetPartitions([])
|
|
185
|
+
return P.element_class(P, [])
|
|
186
|
+
W = Words(infinite=False)
|
|
187
|
+
if from_word:
|
|
188
|
+
return OrderedSetPartitions().from_finite_word(W(from_word))
|
|
189
|
+
# if `parts` looks like a sequence of "letters" then treat it like a word.
|
|
190
|
+
if parts in W or (parts and (parts[0] in ZZ or isinstance(parts[0], str))):
|
|
191
|
+
return OrderedSetPartitions().from_finite_word(W(parts))
|
|
192
|
+
P = OrderedSetPartitions(set(x for p in parts for x in p))
|
|
193
|
+
return P.element_class(P, parts, check=check)
|
|
194
|
+
|
|
195
|
+
def __init__(self, parent, s, check=True):
|
|
196
|
+
"""
|
|
197
|
+
Initialize ``self``.
|
|
198
|
+
|
|
199
|
+
EXAMPLES::
|
|
200
|
+
|
|
201
|
+
sage: OS = OrderedSetPartitions(4)
|
|
202
|
+
sage: s = OS([[1, 3], [2, 4]])
|
|
203
|
+
sage: TestSuite(s).run()
|
|
204
|
+
"""
|
|
205
|
+
ClonableArray.__init__(self, parent,
|
|
206
|
+
[frozenset(part) for part in s], check=check)
|
|
207
|
+
|
|
208
|
+
def _repr_(self):
|
|
209
|
+
"""
|
|
210
|
+
Return a string representation of ``self``.
|
|
211
|
+
|
|
212
|
+
.. TODO::
|
|
213
|
+
|
|
214
|
+
Sort the repr output of Sage's :class:`Set` and remove
|
|
215
|
+
this method.
|
|
216
|
+
|
|
217
|
+
EXAMPLES::
|
|
218
|
+
|
|
219
|
+
sage: OrderedSetPartition([[1,3],[2,4]])
|
|
220
|
+
[{1, 3}, {2, 4}]
|
|
221
|
+
"""
|
|
222
|
+
return '[' + ', '.join('{' + repr(sorted(x))[1:-1] + '}' for x in self) + ']'
|
|
223
|
+
|
|
224
|
+
def check(self):
|
|
225
|
+
"""
|
|
226
|
+
Check that we are a valid ordered set partition.
|
|
227
|
+
|
|
228
|
+
EXAMPLES::
|
|
229
|
+
|
|
230
|
+
sage: OS = OrderedSetPartitions(4)
|
|
231
|
+
sage: s = OS([[1, 3], [2, 4]])
|
|
232
|
+
sage: s.check()
|
|
233
|
+
"""
|
|
234
|
+
par = parent(self)
|
|
235
|
+
assert self in par, "%s not in %s" % (self, par)
|
|
236
|
+
|
|
237
|
+
def base_set(self):
|
|
238
|
+
"""
|
|
239
|
+
Return the base set of ``self``.
|
|
240
|
+
|
|
241
|
+
This is the union of all parts of ``self``.
|
|
242
|
+
|
|
243
|
+
EXAMPLES::
|
|
244
|
+
|
|
245
|
+
sage: OrderedSetPartition([[1], [2,3], [4]]).base_set()
|
|
246
|
+
frozenset({1, 2, 3, 4})
|
|
247
|
+
sage: OrderedSetPartition([[1,2,3,4]]).base_set()
|
|
248
|
+
frozenset({1, 2, 3, 4})
|
|
249
|
+
sage: OrderedSetPartition([]).base_set()
|
|
250
|
+
frozenset()
|
|
251
|
+
|
|
252
|
+
TESTS::
|
|
253
|
+
|
|
254
|
+
sage: S = OrderedSetPartitions()
|
|
255
|
+
sage: x = S([['a', 'c', 'e'], ['b', 'd']])
|
|
256
|
+
sage: x.base_set()
|
|
257
|
+
frozenset({'a', 'b', 'c', 'd', 'e'})
|
|
258
|
+
"""
|
|
259
|
+
try:
|
|
260
|
+
return parent(self)._set
|
|
261
|
+
except AttributeError: # in OrderedSetPartitions_all
|
|
262
|
+
return frozenset(x for part in self for x in part)
|
|
263
|
+
|
|
264
|
+
def base_set_cardinality(self):
|
|
265
|
+
"""
|
|
266
|
+
Return the cardinality of the base set of ``self``.
|
|
267
|
+
|
|
268
|
+
This is the sum of the sizes of the parts of ``self``.
|
|
269
|
+
|
|
270
|
+
This is also known as the *size* (sometimes the *weight*) of
|
|
271
|
+
an ordered set partition.
|
|
272
|
+
|
|
273
|
+
EXAMPLES::
|
|
274
|
+
|
|
275
|
+
sage: OrderedSetPartition([[1], [2,3], [4]]).base_set_cardinality()
|
|
276
|
+
4
|
|
277
|
+
sage: OrderedSetPartition([[1,2,3,4]]).base_set_cardinality()
|
|
278
|
+
4
|
|
279
|
+
|
|
280
|
+
TESTS::
|
|
281
|
+
|
|
282
|
+
sage: S = OrderedSetPartitions()
|
|
283
|
+
sage: S([[1,4],[3],[2]]).base_set_cardinality()
|
|
284
|
+
4
|
|
285
|
+
"""
|
|
286
|
+
try:
|
|
287
|
+
return len(parent(self)._set)
|
|
288
|
+
except AttributeError: # in OrderedSetPartitions_all
|
|
289
|
+
return sum(len(part) for part in self)
|
|
290
|
+
|
|
291
|
+
size = base_set_cardinality
|
|
292
|
+
|
|
293
|
+
def length(self):
|
|
294
|
+
r"""
|
|
295
|
+
Return the number of parts of ``self``.
|
|
296
|
+
|
|
297
|
+
EXAMPLES::
|
|
298
|
+
|
|
299
|
+
sage: OS = OrderedSetPartitions(4)
|
|
300
|
+
sage: s = OS([[1, 3], [2, 4]])
|
|
301
|
+
sage: s.length()
|
|
302
|
+
2
|
|
303
|
+
"""
|
|
304
|
+
return len(self)
|
|
305
|
+
|
|
306
|
+
@combinatorial_map(name='to composition')
|
|
307
|
+
def to_composition(self):
|
|
308
|
+
r"""
|
|
309
|
+
Return the integer composition whose parts are the sizes of the sets
|
|
310
|
+
in ``self``.
|
|
311
|
+
|
|
312
|
+
EXAMPLES::
|
|
313
|
+
|
|
314
|
+
sage: S = OrderedSetPartitions(5)
|
|
315
|
+
sage: x = S([[3,5,4], [1, 2]])
|
|
316
|
+
sage: x.to_composition()
|
|
317
|
+
[3, 2]
|
|
318
|
+
sage: y = S([[3,1], [2], [5,4]])
|
|
319
|
+
sage: y.to_composition()
|
|
320
|
+
[2, 1, 2]
|
|
321
|
+
"""
|
|
322
|
+
return Composition([len(p) for p in self])
|
|
323
|
+
|
|
324
|
+
@staticmethod
|
|
325
|
+
def sum(osps):
|
|
326
|
+
"""
|
|
327
|
+
Return the concatenation of the given ordered set partitions
|
|
328
|
+
``osps`` (provided they have no elements in common).
|
|
329
|
+
|
|
330
|
+
INPUT:
|
|
331
|
+
|
|
332
|
+
- ``osps`` -- list (or iterable) of ordered set partitions
|
|
333
|
+
|
|
334
|
+
EXAMPLES::
|
|
335
|
+
|
|
336
|
+
sage: OrderedSetPartition.sum([OrderedSetPartition([[4, 1], [3]]), OrderedSetPartition([[7], [2]]), OrderedSetPartition([[5, 6]])])
|
|
337
|
+
[{1, 4}, {3}, {7}, {2}, {5, 6}]
|
|
338
|
+
|
|
339
|
+
Any iterable can be provided as input::
|
|
340
|
+
|
|
341
|
+
sage: OrderedSetPartition.sum([OrderedSetPartition([[2*i,2*i+1]]) for i in [4,1,3]])
|
|
342
|
+
[{8, 9}, {2, 3}, {6, 7}]
|
|
343
|
+
|
|
344
|
+
Empty inputs are handled gracefully::
|
|
345
|
+
|
|
346
|
+
sage: OrderedSetPartition.sum([]) == OrderedSetPartition([])
|
|
347
|
+
True
|
|
348
|
+
|
|
349
|
+
TESTS::
|
|
350
|
+
|
|
351
|
+
sage: A = OrderedSetPartitions(3)([[2], [1, 3]])
|
|
352
|
+
sage: B = OrderedSetPartitions([5])([[5]])
|
|
353
|
+
sage: C = OrderedSetPartition.sum([A, B]); C
|
|
354
|
+
[{2}, {1, 3}, {5}]
|
|
355
|
+
sage: C.parent()
|
|
356
|
+
Ordered set partitions of {1, 2, 3, 5}
|
|
357
|
+
"""
|
|
358
|
+
lset = set(x for osp in osps for x in osp.base_set())
|
|
359
|
+
return OrderedSetPartitions(lset)(sum((list(i) for i in osps), []))
|
|
360
|
+
|
|
361
|
+
def reversed(self):
|
|
362
|
+
r"""
|
|
363
|
+
Return the reversal of the ordered set partition ``self``.
|
|
364
|
+
|
|
365
|
+
The *reversal* of an ordered set partition
|
|
366
|
+
`(P_1, P_2, \ldots, P_k)` is defined to be the ordered
|
|
367
|
+
set partition `(P_k, P_{k-1}, \ldots, P_1)`.
|
|
368
|
+
|
|
369
|
+
EXAMPLES::
|
|
370
|
+
|
|
371
|
+
sage: OrderedSetPartition([[1, 3], [2]]).reversed()
|
|
372
|
+
[{2}, {1, 3}]
|
|
373
|
+
sage: OrderedSetPartition([[1, 5], [2, 4]]).reversed()
|
|
374
|
+
[{2, 4}, {1, 5}]
|
|
375
|
+
sage: OrderedSetPartition([[-1], [-2], [3, 4], [0]]).reversed()
|
|
376
|
+
[{0}, {3, 4}, {-2}, {-1}]
|
|
377
|
+
sage: OrderedSetPartition([]).reversed()
|
|
378
|
+
[]
|
|
379
|
+
"""
|
|
380
|
+
par = parent(self)
|
|
381
|
+
return par(list(reversed(self)))
|
|
382
|
+
|
|
383
|
+
def complement(self):
|
|
384
|
+
r"""
|
|
385
|
+
Return the complement of the ordered set partition ``self``.
|
|
386
|
+
|
|
387
|
+
This assumes that ``self`` is an ordered set partition of
|
|
388
|
+
an interval of `\ZZ`.
|
|
389
|
+
|
|
390
|
+
Let `(P_1, P_2, \ldots, P_k)` be an ordered set partition
|
|
391
|
+
of some interval `I` of `\ZZ`. Let `\omega` be the unique
|
|
392
|
+
strictly decreasing bijection `I \to I`. Then, the
|
|
393
|
+
*complement* of `(P_1, P_2, \ldots, P_k)` is defined to be
|
|
394
|
+
the ordered set partition
|
|
395
|
+
`(\omega(P_1), \omega(P_2), \ldots, \omega(P_k))`.
|
|
396
|
+
|
|
397
|
+
EXAMPLES::
|
|
398
|
+
|
|
399
|
+
sage: OrderedSetPartition([[1, 2], [3]]).complement()
|
|
400
|
+
[{2, 3}, {1}]
|
|
401
|
+
sage: OrderedSetPartition([[1, 3], [2]]).complement()
|
|
402
|
+
[{1, 3}, {2}]
|
|
403
|
+
sage: OrderedSetPartition([[2, 3]]).complement()
|
|
404
|
+
[{2, 3}]
|
|
405
|
+
sage: OrderedSetPartition([[1, 5], [2, 3], [4]]).complement()
|
|
406
|
+
[{1, 5}, {3, 4}, {2}]
|
|
407
|
+
sage: OrderedSetPartition([[-1], [-2], [1, 2], [0]]).complement()
|
|
408
|
+
[{1}, {2}, {-2, -1}, {0}]
|
|
409
|
+
sage: OrderedSetPartition([]).complement()
|
|
410
|
+
[]
|
|
411
|
+
"""
|
|
412
|
+
if len(self) <= 1:
|
|
413
|
+
return self
|
|
414
|
+
base_set = self.base_set()
|
|
415
|
+
m = min(base_set)
|
|
416
|
+
M = max(base_set)
|
|
417
|
+
mM = m + M
|
|
418
|
+
par = parent(self)
|
|
419
|
+
return par([[mM - i for i in part] for part in self])
|
|
420
|
+
|
|
421
|
+
def finer(self):
|
|
422
|
+
"""
|
|
423
|
+
Return the set of ordered set partitions which are finer
|
|
424
|
+
than ``self``.
|
|
425
|
+
|
|
426
|
+
See :meth:`is_finer` for the definition of "finer".
|
|
427
|
+
|
|
428
|
+
EXAMPLES::
|
|
429
|
+
|
|
430
|
+
sage: C = OrderedSetPartition([[1, 3], [2]]).finer()
|
|
431
|
+
sage: C.cardinality()
|
|
432
|
+
3
|
|
433
|
+
sage: C.list()
|
|
434
|
+
[[{1}, {3}, {2}], [{3}, {1}, {2}], [{1, 3}, {2}]]
|
|
435
|
+
|
|
436
|
+
sage: OrderedSetPartition([]).finer()
|
|
437
|
+
{[]}
|
|
438
|
+
|
|
439
|
+
sage: W = OrderedSetPartition([[4, 9], [-1, 2]])
|
|
440
|
+
sage: W.finer().list()
|
|
441
|
+
[[{9}, {4}, {2}, {-1}],
|
|
442
|
+
[{9}, {4}, {-1}, {2}],
|
|
443
|
+
[{9}, {4}, {-1, 2}],
|
|
444
|
+
[{4}, {9}, {2}, {-1}],
|
|
445
|
+
[{4}, {9}, {-1}, {2}],
|
|
446
|
+
[{4}, {9}, {-1, 2}],
|
|
447
|
+
[{4, 9}, {2}, {-1}],
|
|
448
|
+
[{4, 9}, {-1}, {2}],
|
|
449
|
+
[{4, 9}, {-1, 2}]]
|
|
450
|
+
"""
|
|
451
|
+
par = parent(self)
|
|
452
|
+
if not self:
|
|
453
|
+
return FiniteEnumeratedSet([self])
|
|
454
|
+
return FiniteEnumeratedSet([par(sum((list(i) for i in C), []))
|
|
455
|
+
for C in product(*[OrderedSetPartitions(X) for X in self])])
|
|
456
|
+
|
|
457
|
+
def is_finer(self, co2):
|
|
458
|
+
"""
|
|
459
|
+
Return ``True`` if the ordered set partition ``self`` is finer
|
|
460
|
+
than the ordered set partition ``co2``; otherwise, return ``False``.
|
|
461
|
+
|
|
462
|
+
If `A` and `B` are two ordered set partitions of the same set,
|
|
463
|
+
then `A` is said to be *finer* than `B` if `B` can be obtained
|
|
464
|
+
from `A` by (repeatedly) merging consecutive parts.
|
|
465
|
+
In this case, we say that `B` is *fatter* than `A`.
|
|
466
|
+
|
|
467
|
+
EXAMPLES::
|
|
468
|
+
|
|
469
|
+
sage: A = OrderedSetPartition([[1, 3], [2]])
|
|
470
|
+
sage: B = OrderedSetPartition([[1], [3], [2]])
|
|
471
|
+
sage: A.is_finer(B)
|
|
472
|
+
False
|
|
473
|
+
sage: B.is_finer(A)
|
|
474
|
+
True
|
|
475
|
+
sage: C = OrderedSetPartition([[3], [1], [2]])
|
|
476
|
+
sage: A.is_finer(C)
|
|
477
|
+
False
|
|
478
|
+
sage: C.is_finer(A)
|
|
479
|
+
True
|
|
480
|
+
sage: OrderedSetPartition([[2], [5], [1], [4]]).is_finer(OrderedSetPartition([[2, 5], [1, 4]]))
|
|
481
|
+
True
|
|
482
|
+
sage: OrderedSetPartition([[5], [2], [1], [4]]).is_finer(OrderedSetPartition([[2, 5], [1, 4]]))
|
|
483
|
+
True
|
|
484
|
+
sage: OrderedSetPartition([[2], [1], [5], [4]]).is_finer(OrderedSetPartition([[2, 5], [1, 4]]))
|
|
485
|
+
False
|
|
486
|
+
sage: OrderedSetPartition([[2, 5, 1], [4]]).is_finer(OrderedSetPartition([[2, 5], [1, 4]]))
|
|
487
|
+
False
|
|
488
|
+
"""
|
|
489
|
+
co1 = self
|
|
490
|
+
if co1.base_set() != co2.base_set():
|
|
491
|
+
raise ValueError("ordered set partitions self (= %s) and co2 (= %s) must be of the same set" % (self, co2))
|
|
492
|
+
|
|
493
|
+
i1 = 0
|
|
494
|
+
for j2 in co2:
|
|
495
|
+
sum1 = set()
|
|
496
|
+
while len(sum1) < len(j2):
|
|
497
|
+
sum1 = sum1.union(co1[i1])
|
|
498
|
+
i1 += 1
|
|
499
|
+
if not sum1.issubset(j2):
|
|
500
|
+
return False
|
|
501
|
+
|
|
502
|
+
return True
|
|
503
|
+
|
|
504
|
+
def fatten(self, grouping):
|
|
505
|
+
r"""
|
|
506
|
+
Return the ordered set partition fatter than ``self``, obtained
|
|
507
|
+
by grouping together consecutive parts according to the integer
|
|
508
|
+
composition ``grouping``.
|
|
509
|
+
|
|
510
|
+
See :meth:`finer` for the definition of "fatter".
|
|
511
|
+
|
|
512
|
+
INPUT:
|
|
513
|
+
|
|
514
|
+
- ``grouping`` -- a composition whose sum is the length of ``self``
|
|
515
|
+
|
|
516
|
+
EXAMPLES:
|
|
517
|
+
|
|
518
|
+
Let us start with the ordered set partition::
|
|
519
|
+
|
|
520
|
+
sage: c = OrderedSetPartition([[2, 5], [1], [3, 4]])
|
|
521
|
+
|
|
522
|
+
With ``grouping`` equal to `(1, \ldots, 1)`, `c` is left unchanged::
|
|
523
|
+
|
|
524
|
+
sage: c.fatten(Composition([1,1,1]))
|
|
525
|
+
[{2, 5}, {1}, {3, 4}]
|
|
526
|
+
|
|
527
|
+
With ``grouping`` equal to `(\ell)` where `\ell` is the length of
|
|
528
|
+
`c`, this yields the coarsest ordered set partition above `c`::
|
|
529
|
+
|
|
530
|
+
sage: c.fatten(Composition([3]))
|
|
531
|
+
[{1, 2, 3, 4, 5}]
|
|
532
|
+
|
|
533
|
+
Other values for ``grouping`` yield (all the) other ordered
|
|
534
|
+
set partitions coarser than `c`::
|
|
535
|
+
|
|
536
|
+
sage: c.fatten(Composition([2,1]))
|
|
537
|
+
[{1, 2, 5}, {3, 4}]
|
|
538
|
+
sage: c.fatten(Composition([1,2]))
|
|
539
|
+
[{2, 5}, {1, 3, 4}]
|
|
540
|
+
|
|
541
|
+
TESTS::
|
|
542
|
+
|
|
543
|
+
sage: OrderedSetPartition([]).fatten(Composition([]))
|
|
544
|
+
[]
|
|
545
|
+
sage: c.fatten(Composition([2,1])).__class__ == c.__class__
|
|
546
|
+
True
|
|
547
|
+
"""
|
|
548
|
+
result = [None] * len(grouping)
|
|
549
|
+
j = 0
|
|
550
|
+
for i in range(len(grouping)):
|
|
551
|
+
result[i] = set().union(*self[j:j + grouping[i]])
|
|
552
|
+
j += grouping[i]
|
|
553
|
+
return parent(self)(result)
|
|
554
|
+
|
|
555
|
+
def fatter(self):
|
|
556
|
+
"""
|
|
557
|
+
Return the set of ordered set partitions which are fatter
|
|
558
|
+
than ``self``.
|
|
559
|
+
|
|
560
|
+
See :meth:`finer` for the definition of "fatter".
|
|
561
|
+
|
|
562
|
+
EXAMPLES::
|
|
563
|
+
|
|
564
|
+
sage: C = OrderedSetPartition([[2, 5], [1], [3, 4]]).fatter()
|
|
565
|
+
sage: C.cardinality()
|
|
566
|
+
4
|
|
567
|
+
sage: sorted(C)
|
|
568
|
+
[[{2, 5}, {1}, {3, 4}],
|
|
569
|
+
[{2, 5}, {1, 3, 4}],
|
|
570
|
+
[{1, 2, 5}, {3, 4}],
|
|
571
|
+
[{1, 2, 3, 4, 5}]]
|
|
572
|
+
|
|
573
|
+
sage: OrderedSetPartition([[4, 9], [-1, 2]]).fatter().list()
|
|
574
|
+
[[{4, 9}, {-1, 2}], [{-1, 2, 4, 9}]]
|
|
575
|
+
|
|
576
|
+
Some extreme cases::
|
|
577
|
+
|
|
578
|
+
sage: list(OrderedSetPartition([[5]]).fatter())
|
|
579
|
+
[[{5}]]
|
|
580
|
+
sage: list(Composition([]).fatter())
|
|
581
|
+
[[]]
|
|
582
|
+
sage: sorted(OrderedSetPartition([[1], [2], [3], [4]]).fatter())
|
|
583
|
+
[[{1}, {2}, {3}, {4}],
|
|
584
|
+
[{1}, {2}, {3, 4}],
|
|
585
|
+
[{1}, {2, 3}, {4}],
|
|
586
|
+
[{1}, {2, 3, 4}],
|
|
587
|
+
[{1, 2}, {3}, {4}],
|
|
588
|
+
[{1, 2}, {3, 4}],
|
|
589
|
+
[{1, 2, 3}, {4}],
|
|
590
|
+
[{1, 2, 3, 4}]]
|
|
591
|
+
"""
|
|
592
|
+
return Compositions(len(self)).map(self.fatten)
|
|
593
|
+
|
|
594
|
+
@staticmethod
|
|
595
|
+
def bottom_up_osp(X, comp):
|
|
596
|
+
r"""
|
|
597
|
+
Return the ordered set partition obtained by listing the
|
|
598
|
+
elements of the set ``X`` in increasing order, and
|
|
599
|
+
placing bars between some of them according to the
|
|
600
|
+
integer composition ``comp`` (namely, the bars are placed
|
|
601
|
+
in such a way that the lengths of the resulting blocks are
|
|
602
|
+
exactly the entries of ``comp``).
|
|
603
|
+
|
|
604
|
+
INPUT:
|
|
605
|
+
|
|
606
|
+
- ``X`` -- a finite set (or list or tuple)
|
|
607
|
+
|
|
608
|
+
- ``comp`` -- a composition whose sum is the size of ``X``
|
|
609
|
+
(can be given as a list or tuple or composition)
|
|
610
|
+
|
|
611
|
+
EXAMPLES::
|
|
612
|
+
|
|
613
|
+
sage: buo = OrderedSetPartition.bottom_up_osp
|
|
614
|
+
sage: buo(Set([1, 4, 7, 9]), [2, 1, 1])
|
|
615
|
+
[{1, 4}, {7}, {9}]
|
|
616
|
+
sage: buo(Set([1, 4, 7, 9]), [1, 3])
|
|
617
|
+
[{1}, {4, 7, 9}]
|
|
618
|
+
sage: buo(Set([1, 4, 7, 9]), [1, 1, 1, 1])
|
|
619
|
+
[{1}, {4}, {7}, {9}]
|
|
620
|
+
sage: buo(range(8), [1, 4, 2, 1])
|
|
621
|
+
[{0}, {1, 2, 3, 4}, {5, 6}, {7}]
|
|
622
|
+
sage: buo([], [])
|
|
623
|
+
[]
|
|
624
|
+
|
|
625
|
+
TESTS::
|
|
626
|
+
|
|
627
|
+
sage: buo = OrderedSetPartition.bottom_up_osp
|
|
628
|
+
sage: parent(buo(Set([1, 4, 7, 9]), [2, 1, 1]))
|
|
629
|
+
Ordered set partitions of {1, 4, 9, 7}
|
|
630
|
+
sage: buo((3, 5, 6), (2, 1))
|
|
631
|
+
[{3, 5}, {6}]
|
|
632
|
+
sage: buo([3, 5, 6], Composition([1, 2]))
|
|
633
|
+
[{3}, {5, 6}]
|
|
634
|
+
"""
|
|
635
|
+
xs = sorted(X)
|
|
636
|
+
result = [None] * len(comp)
|
|
637
|
+
j = 0
|
|
638
|
+
for i in range(len(comp)):
|
|
639
|
+
result[i] = set(xs[j:j + comp[i]])
|
|
640
|
+
j += comp[i]
|
|
641
|
+
return OrderedSetPartitions(X)(result)
|
|
642
|
+
|
|
643
|
+
def strongly_finer(self):
|
|
644
|
+
"""
|
|
645
|
+
Return the set of ordered set partitions which are strongly
|
|
646
|
+
finer than ``self``.
|
|
647
|
+
|
|
648
|
+
See :meth:`is_strongly_finer` for the definition of "strongly
|
|
649
|
+
finer".
|
|
650
|
+
|
|
651
|
+
EXAMPLES::
|
|
652
|
+
|
|
653
|
+
sage: C = OrderedSetPartition([[1, 3], [2]]).strongly_finer()
|
|
654
|
+
sage: C.cardinality()
|
|
655
|
+
2
|
|
656
|
+
sage: C.list()
|
|
657
|
+
[[{1}, {3}, {2}], [{1, 3}, {2}]]
|
|
658
|
+
|
|
659
|
+
sage: OrderedSetPartition([]).strongly_finer()
|
|
660
|
+
{[]}
|
|
661
|
+
|
|
662
|
+
sage: W = OrderedSetPartition([[4, 9], [-1, 2]])
|
|
663
|
+
sage: W.strongly_finer().list()
|
|
664
|
+
[[{4}, {9}, {-1}, {2}],
|
|
665
|
+
[{4}, {9}, {-1, 2}],
|
|
666
|
+
[{4, 9}, {-1}, {2}],
|
|
667
|
+
[{4, 9}, {-1, 2}]]
|
|
668
|
+
"""
|
|
669
|
+
par = parent(self)
|
|
670
|
+
if not self:
|
|
671
|
+
return FiniteEnumeratedSet([self])
|
|
672
|
+
buo = OrderedSetPartition.bottom_up_osp
|
|
673
|
+
return FiniteEnumeratedSet([par(sum((list(P) for P in C), []))
|
|
674
|
+
for C in product(*[[buo(X, comp) for comp in Compositions(len(X))] for X in self])])
|
|
675
|
+
|
|
676
|
+
def is_strongly_finer(self, co2):
|
|
677
|
+
r"""
|
|
678
|
+
Return ``True`` if the ordered set partition ``self`` is strongly
|
|
679
|
+
finer than the ordered set partition ``co2``; otherwise, return
|
|
680
|
+
``False``.
|
|
681
|
+
|
|
682
|
+
If `A` and `B` are two ordered set partitions of the same set,
|
|
683
|
+
then `A` is said to be *strongly finer* than `B` if `B` can be
|
|
684
|
+
obtained from `A` by (repeatedly) merging consecutive parts,
|
|
685
|
+
provided that every time we merge two consecutive parts `C_i`
|
|
686
|
+
and `C_{i+1}`, we have `\max C_i < \min C_{i+1}`.
|
|
687
|
+
In this case, we say that `B` is *strongly fatter* than `A`.
|
|
688
|
+
|
|
689
|
+
EXAMPLES::
|
|
690
|
+
|
|
691
|
+
sage: A = OrderedSetPartition([[1, 3], [2]])
|
|
692
|
+
sage: B = OrderedSetPartition([[1], [3], [2]])
|
|
693
|
+
sage: A.is_strongly_finer(B)
|
|
694
|
+
False
|
|
695
|
+
sage: B.is_strongly_finer(A)
|
|
696
|
+
True
|
|
697
|
+
sage: C = OrderedSetPartition([[3], [1], [2]])
|
|
698
|
+
sage: A.is_strongly_finer(C)
|
|
699
|
+
False
|
|
700
|
+
sage: C.is_strongly_finer(A)
|
|
701
|
+
False
|
|
702
|
+
sage: OrderedSetPartition([[2], [5], [1], [4]]).is_strongly_finer(OrderedSetPartition([[2, 5], [1, 4]]))
|
|
703
|
+
True
|
|
704
|
+
sage: OrderedSetPartition([[5], [2], [1], [4]]).is_strongly_finer(OrderedSetPartition([[2, 5], [1, 4]]))
|
|
705
|
+
False
|
|
706
|
+
sage: OrderedSetPartition([[2], [1], [5], [4]]).is_strongly_finer(OrderedSetPartition([[2, 5], [1, 4]]))
|
|
707
|
+
False
|
|
708
|
+
sage: OrderedSetPartition([[2, 5, 1], [4]]).is_strongly_finer(OrderedSetPartition([[2, 5], [1, 4]]))
|
|
709
|
+
False
|
|
710
|
+
"""
|
|
711
|
+
co1 = self
|
|
712
|
+
if co1.base_set() != co2.base_set():
|
|
713
|
+
raise ValueError("ordered set partitions self (= %s) and co2 (= %s) must be of the same set" % (self, co2))
|
|
714
|
+
|
|
715
|
+
i1 = 0
|
|
716
|
+
for j2 in co2:
|
|
717
|
+
sum1 = set()
|
|
718
|
+
while len(sum1) < len(j2):
|
|
719
|
+
next = co1[i1]
|
|
720
|
+
if sum1 and max(sum1) >= min(next):
|
|
721
|
+
return False
|
|
722
|
+
sum1 = sum1.union(next)
|
|
723
|
+
i1 += 1
|
|
724
|
+
if not sum1.issubset(j2):
|
|
725
|
+
return False
|
|
726
|
+
|
|
727
|
+
return True
|
|
728
|
+
|
|
729
|
+
def strongly_fatter(self):
|
|
730
|
+
"""
|
|
731
|
+
Return the set of ordered set partitions which are strongly fatter
|
|
732
|
+
than ``self``.
|
|
733
|
+
|
|
734
|
+
See :meth:`strongly_finer` for the definition of "strongly fatter".
|
|
735
|
+
|
|
736
|
+
EXAMPLES::
|
|
737
|
+
|
|
738
|
+
sage: C = OrderedSetPartition([[2, 5], [1], [3, 4]]).strongly_fatter()
|
|
739
|
+
sage: C.cardinality()
|
|
740
|
+
2
|
|
741
|
+
sage: sorted(C)
|
|
742
|
+
[[{2, 5}, {1}, {3, 4}], [{2, 5}, {1, 3, 4}]]
|
|
743
|
+
|
|
744
|
+
sage: OrderedSetPartition([[4, 9], [-1, 2]]).strongly_fatter().list()
|
|
745
|
+
[[{4, 9}, {-1, 2}]]
|
|
746
|
+
|
|
747
|
+
Some extreme cases::
|
|
748
|
+
|
|
749
|
+
sage: list(OrderedSetPartition([[5]]).strongly_fatter())
|
|
750
|
+
[[{5}]]
|
|
751
|
+
sage: list(OrderedSetPartition([]).strongly_fatter())
|
|
752
|
+
[[]]
|
|
753
|
+
sage: sorted(OrderedSetPartition([[1], [2], [3], [4]]).strongly_fatter())
|
|
754
|
+
[[{1}, {2}, {3}, {4}],
|
|
755
|
+
[{1}, {2}, {3, 4}],
|
|
756
|
+
[{1}, {2, 3}, {4}],
|
|
757
|
+
[{1}, {2, 3, 4}],
|
|
758
|
+
[{1, 2}, {3}, {4}],
|
|
759
|
+
[{1, 2}, {3, 4}],
|
|
760
|
+
[{1, 2, 3}, {4}],
|
|
761
|
+
[{1, 2, 3, 4}]]
|
|
762
|
+
sage: sorted(OrderedSetPartition([[1], [3], [2], [4]]).strongly_fatter())
|
|
763
|
+
[[{1}, {3}, {2}, {4}],
|
|
764
|
+
[{1}, {3}, {2, 4}],
|
|
765
|
+
[{1, 3}, {2}, {4}],
|
|
766
|
+
[{1, 3}, {2, 4}]]
|
|
767
|
+
sage: sorted(OrderedSetPartition([[4], [1], [5], [3]]).strongly_fatter())
|
|
768
|
+
[[{4}, {1}, {5}, {3}], [{4}, {1, 5}, {3}]]
|
|
769
|
+
"""
|
|
770
|
+
c = [sorted(X) for X in self]
|
|
771
|
+
l = len(c) - 1
|
|
772
|
+
g = [-1] + [i for i in range(l) if c[i][-1] > c[i + 1][0]] + [l]
|
|
773
|
+
# g lists the positions of the blocks that cannot be merged
|
|
774
|
+
# with their right neighbors.
|
|
775
|
+
subcomps = [OrderedSetPartition(c[g[i] + 1: g[i + 1] + 1])
|
|
776
|
+
for i in range(len(g) - 1)]
|
|
777
|
+
# Now, self is the concatenation of the entries of subcomps.
|
|
778
|
+
# We can fatten each of the ordered set partitions setcomps
|
|
779
|
+
# arbitrarily, and then concatenate the results.
|
|
780
|
+
fattenings = [list(subcomp.fatter()) for subcomp in subcomps]
|
|
781
|
+
return FiniteEnumeratedSet([OrderedSetPartition(sum([list(gg) for gg in fattening], []))
|
|
782
|
+
for fattening in product(*fattenings)])
|
|
783
|
+
|
|
784
|
+
@combinatorial_map(name='to packed word')
|
|
785
|
+
def to_packed_word(self):
|
|
786
|
+
r"""
|
|
787
|
+
Return the packed word on alphabet `\{1,2,3,\ldots\}`
|
|
788
|
+
corresponding to ``self``.
|
|
789
|
+
|
|
790
|
+
A *packed word* on alphabet `\{1,2,3,\ldots\}` is any word whose
|
|
791
|
+
maximum letter is the same as its total number of distinct letters.
|
|
792
|
+
Let `P` be an ordered set partition of a set `X`.
|
|
793
|
+
The corresponding packed word `w_1 w_2 \cdots w_n` is constructed
|
|
794
|
+
by having letter `w_i = j` if the `i`-th smallest entry in `X`
|
|
795
|
+
occurs in the `j`-th block of `P`.
|
|
796
|
+
|
|
797
|
+
.. SEEALSO::
|
|
798
|
+
|
|
799
|
+
:meth:`Word.to_ordered_set_partition`
|
|
800
|
+
|
|
801
|
+
.. WARNING::
|
|
802
|
+
|
|
803
|
+
This assumes there is a total order on the underlying
|
|
804
|
+
set.
|
|
805
|
+
|
|
806
|
+
EXAMPLES::
|
|
807
|
+
|
|
808
|
+
sage: S = OrderedSetPartitions()
|
|
809
|
+
sage: x = S([[3,5], [2], [1,4,6]])
|
|
810
|
+
sage: x.to_packed_word()
|
|
811
|
+
word: 321313
|
|
812
|
+
|
|
813
|
+
sage: x = S([['a', 'c', 'e'], ['b', 'd']])
|
|
814
|
+
sage: x.to_packed_word()
|
|
815
|
+
word: 12121
|
|
816
|
+
"""
|
|
817
|
+
X = sorted(self.base_set())
|
|
818
|
+
out = {}
|
|
819
|
+
for i in range(len(self)):
|
|
820
|
+
for letter in self[i]:
|
|
821
|
+
out[letter] = i
|
|
822
|
+
W = Words(infinite=False)
|
|
823
|
+
return W([out[letter] + 1 for letter in X])
|
|
824
|
+
|
|
825
|
+
def number_of_inversions(self):
|
|
826
|
+
r"""
|
|
827
|
+
Return the number of inversions in ``self``.
|
|
828
|
+
|
|
829
|
+
An inversion of an ordered set partition with blocks
|
|
830
|
+
`[B_1,B_2, \ldots, B_k]` is a pair of letters `i` and `j` with `i < j`
|
|
831
|
+
such that `i` is minimal in `B_m`, `j \in B_l`, and `l < m`.
|
|
832
|
+
|
|
833
|
+
REFERENCES:
|
|
834
|
+
|
|
835
|
+
- [Wilson2016]_
|
|
836
|
+
|
|
837
|
+
EXAMPLES::
|
|
838
|
+
|
|
839
|
+
sage: OrderedSetPartition([{2,5},{4,6},{1,3}]).number_of_inversions()
|
|
840
|
+
5
|
|
841
|
+
sage: OrderedSetPartition([{1,3,8},{2,4},{5,6,7}]).number_of_inversions()
|
|
842
|
+
3
|
|
843
|
+
|
|
844
|
+
TESTS::
|
|
845
|
+
|
|
846
|
+
sage: OrderedSetPartition([{1,3,8},{2,4},{5,6,7}]).number_of_inversions().parent()
|
|
847
|
+
Integer Ring
|
|
848
|
+
"""
|
|
849
|
+
num_invs = 0
|
|
850
|
+
for m, part in enumerate(self):
|
|
851
|
+
i = min(part)
|
|
852
|
+
for ell in range(m):
|
|
853
|
+
num_invs += sum(1 for j in self[ell] if i < j)
|
|
854
|
+
return ZZ(num_invs)
|
|
855
|
+
|
|
856
|
+
|
|
857
|
+
class OrderedSetPartitions(UniqueRepresentation, Parent):
|
|
858
|
+
"""
|
|
859
|
+
Return the combinatorial class of ordered set partitions of ``s``.
|
|
860
|
+
|
|
861
|
+
The optional argument ``c``, if specified, restricts the parts of
|
|
862
|
+
the partition to have certain sizes (the entries of ``c``).
|
|
863
|
+
|
|
864
|
+
EXAMPLES::
|
|
865
|
+
|
|
866
|
+
sage: OS = OrderedSetPartitions([1,2,3,4]); OS
|
|
867
|
+
Ordered set partitions of {1, 2, 3, 4}
|
|
868
|
+
sage: OS.cardinality()
|
|
869
|
+
75
|
|
870
|
+
sage: OS.first()
|
|
871
|
+
[{1}, {2}, {3}, {4}]
|
|
872
|
+
sage: OS.last()
|
|
873
|
+
[{1, 2, 3, 4}]
|
|
874
|
+
sage: OS.random_element().parent() is OS
|
|
875
|
+
True
|
|
876
|
+
|
|
877
|
+
::
|
|
878
|
+
|
|
879
|
+
sage: OS = OrderedSetPartitions([1,2,3,4], [2,2]); OS
|
|
880
|
+
Ordered set partitions of {1, 2, 3, 4} into parts of size [2, 2]
|
|
881
|
+
sage: OS.cardinality()
|
|
882
|
+
6
|
|
883
|
+
sage: OS.first()
|
|
884
|
+
[{1, 2}, {3, 4}]
|
|
885
|
+
sage: OS.last()
|
|
886
|
+
[{3, 4}, {1, 2}]
|
|
887
|
+
sage: OS.list()
|
|
888
|
+
[[{1, 2}, {3, 4}],
|
|
889
|
+
[{1, 3}, {2, 4}],
|
|
890
|
+
[{1, 4}, {2, 3}],
|
|
891
|
+
[{2, 3}, {1, 4}],
|
|
892
|
+
[{2, 4}, {1, 3}],
|
|
893
|
+
[{3, 4}, {1, 2}]]
|
|
894
|
+
|
|
895
|
+
::
|
|
896
|
+
|
|
897
|
+
sage: OS = OrderedSetPartitions("cat")
|
|
898
|
+
sage: OS # random
|
|
899
|
+
Ordered set partitions of {'a', 't', 'c'}
|
|
900
|
+
sage: sorted(OS.list(), key=str)
|
|
901
|
+
[[{'a', 'c', 't'}],
|
|
902
|
+
[{'a', 'c'}, {'t'}],
|
|
903
|
+
[{'a', 't'}, {'c'}],
|
|
904
|
+
[{'a'}, {'c', 't'}],
|
|
905
|
+
[{'a'}, {'c'}, {'t'}],
|
|
906
|
+
[{'a'}, {'t'}, {'c'}],
|
|
907
|
+
[{'c', 't'}, {'a'}],
|
|
908
|
+
[{'c'}, {'a', 't'}],
|
|
909
|
+
[{'c'}, {'a'}, {'t'}],
|
|
910
|
+
[{'c'}, {'t'}, {'a'}],
|
|
911
|
+
[{'t'}, {'a', 'c'}],
|
|
912
|
+
[{'t'}, {'a'}, {'c'}],
|
|
913
|
+
[{'t'}, {'c'}, {'a'}]]
|
|
914
|
+
|
|
915
|
+
TESTS::
|
|
916
|
+
|
|
917
|
+
sage: S = OrderedSetPartitions()
|
|
918
|
+
sage: x = S([[3,5], [2], [1,4,6]])
|
|
919
|
+
sage: x.parent()
|
|
920
|
+
Ordered set partitions
|
|
921
|
+
"""
|
|
922
|
+
@staticmethod
|
|
923
|
+
def __classcall_private__(cls, s=None, c=None):
|
|
924
|
+
"""
|
|
925
|
+
Choose the correct parent based upon input.
|
|
926
|
+
|
|
927
|
+
EXAMPLES::
|
|
928
|
+
|
|
929
|
+
sage: OrderedSetPartitions(4)
|
|
930
|
+
Ordered set partitions of {1, 2, 3, 4}
|
|
931
|
+
sage: OrderedSetPartitions(4, [1, 2, 1])
|
|
932
|
+
Ordered set partitions of {1, 2, 3, 4} into parts of size [1, 2, 1]
|
|
933
|
+
"""
|
|
934
|
+
if s is None:
|
|
935
|
+
if c is not None:
|
|
936
|
+
raise NotImplementedError("cannot specify 'c' without specifying 's'")
|
|
937
|
+
return OrderedSetPartitions_all()
|
|
938
|
+
if isinstance(s, (int, Integer)):
|
|
939
|
+
if s < 0:
|
|
940
|
+
raise ValueError("s must be nonnegative")
|
|
941
|
+
s = frozenset(range(1, s + 1))
|
|
942
|
+
else:
|
|
943
|
+
s = frozenset(s)
|
|
944
|
+
|
|
945
|
+
if c is None:
|
|
946
|
+
return OrderedSetPartitions_s(s)
|
|
947
|
+
|
|
948
|
+
if isinstance(c, (int, Integer)):
|
|
949
|
+
return OrderedSetPartitions_sn(s, c)
|
|
950
|
+
if c not in Compositions(len(s)):
|
|
951
|
+
raise ValueError("c must be a composition of %s" % len(s))
|
|
952
|
+
return OrderedSetPartitions_scomp(s, Composition(c))
|
|
953
|
+
|
|
954
|
+
def __init__(self, s):
|
|
955
|
+
"""
|
|
956
|
+
Initialize ``self``.
|
|
957
|
+
|
|
958
|
+
EXAMPLES::
|
|
959
|
+
|
|
960
|
+
sage: OS = OrderedSetPartitions(4)
|
|
961
|
+
sage: TestSuite(OS).run()
|
|
962
|
+
"""
|
|
963
|
+
self._set = s
|
|
964
|
+
Parent.__init__(self, category=FiniteEnumeratedSets())
|
|
965
|
+
|
|
966
|
+
def _element_constructor_(self, s):
|
|
967
|
+
"""
|
|
968
|
+
Construct an element of ``self`` from ``s``.
|
|
969
|
+
|
|
970
|
+
EXAMPLES::
|
|
971
|
+
|
|
972
|
+
sage: OS = OrderedSetPartitions(4)
|
|
973
|
+
sage: x = OS([[1,3],[2,4]]); x
|
|
974
|
+
[{1, 3}, {2, 4}]
|
|
975
|
+
sage: x.parent()
|
|
976
|
+
Ordered set partitions of {1, 2, 3, 4}
|
|
977
|
+
"""
|
|
978
|
+
if isinstance(s, OrderedSetPartition):
|
|
979
|
+
raise ValueError("cannot convert %s into an element of %s" % (s, self))
|
|
980
|
+
return self.element_class(self, list(s)) # HERE the parent "self" is not good
|
|
981
|
+
|
|
982
|
+
Element = OrderedSetPartition
|
|
983
|
+
|
|
984
|
+
def __contains__(self, x):
|
|
985
|
+
"""
|
|
986
|
+
TESTS::
|
|
987
|
+
|
|
988
|
+
sage: OS = OrderedSetPartitions([1,2,3,4])
|
|
989
|
+
sage: all(sp in OS for sp in OS)
|
|
990
|
+
True
|
|
991
|
+
sage: [[1,2], [], [3,4]] in OS
|
|
992
|
+
False
|
|
993
|
+
sage: [Set([1,2]), Set([3,4])] in OS
|
|
994
|
+
True
|
|
995
|
+
sage: [set([1,2]), set([3,4])] in OS
|
|
996
|
+
True
|
|
997
|
+
|
|
998
|
+
Make sure the set really matches::
|
|
999
|
+
|
|
1000
|
+
sage: [set([5,6]), set([3,4])] in OS
|
|
1001
|
+
False
|
|
1002
|
+
"""
|
|
1003
|
+
# x must be a list
|
|
1004
|
+
if not isinstance(x, (OrderedSetPartition, list, tuple)):
|
|
1005
|
+
return False
|
|
1006
|
+
|
|
1007
|
+
# The total number of elements in the list
|
|
1008
|
+
# should be the same as the number is self._set
|
|
1009
|
+
if sum(map(len, x)) != len(self._set):
|
|
1010
|
+
return False
|
|
1011
|
+
|
|
1012
|
+
# Check to make sure each element of the list
|
|
1013
|
+
# is a nonempty set
|
|
1014
|
+
u = set()
|
|
1015
|
+
for s in x:
|
|
1016
|
+
if not s or not isinstance(s, (set, frozenset, Set_generic)):
|
|
1017
|
+
return False
|
|
1018
|
+
u = u.union(s)
|
|
1019
|
+
|
|
1020
|
+
# Make sure that the union of all the
|
|
1021
|
+
# sets is the original set
|
|
1022
|
+
if len(u) != len(self._set):
|
|
1023
|
+
return False
|
|
1024
|
+
return frozenset(u) == self._set
|
|
1025
|
+
|
|
1026
|
+
def from_finite_word(self, w, check=True):
|
|
1027
|
+
r"""
|
|
1028
|
+
Return the unique ordered set partition of `\{1, 2, \ldots, n\}` corresponding
|
|
1029
|
+
to a word `w` of length `n`.
|
|
1030
|
+
|
|
1031
|
+
.. SEEALSO::
|
|
1032
|
+
|
|
1033
|
+
:meth:`Word.to_ordered_set_partition`
|
|
1034
|
+
|
|
1035
|
+
EXAMPLES::
|
|
1036
|
+
|
|
1037
|
+
sage: A = OrderedSetPartitions().from_finite_word('abcabcabd'); A
|
|
1038
|
+
[{1, 4, 7}, {2, 5, 8}, {3, 6}, {9}]
|
|
1039
|
+
sage: B = OrderedSetPartitions().from_finite_word([1,2,3,1,2,3,1,2,4])
|
|
1040
|
+
sage: A == B
|
|
1041
|
+
True
|
|
1042
|
+
|
|
1043
|
+
TESTS::
|
|
1044
|
+
|
|
1045
|
+
sage: A = OrderedSetPartitions().from_finite_word('abcabca')
|
|
1046
|
+
sage: A.parent()
|
|
1047
|
+
Ordered set partitions
|
|
1048
|
+
|
|
1049
|
+
sage: A = OrderedSetPartitions(7).from_finite_word('abcabca')
|
|
1050
|
+
sage: A.parent()
|
|
1051
|
+
Ordered set partitions of {1, 2, 3, 4, 5, 6, 7}
|
|
1052
|
+
"""
|
|
1053
|
+
# TODO: fix this if statement.
|
|
1054
|
+
# In fact, what we need is for the underlying alphabet to be sortable.
|
|
1055
|
+
if isinstance(w, (list, tuple, str, FiniteWord_class)):
|
|
1056
|
+
W = Words(infinite=False)
|
|
1057
|
+
if check:
|
|
1058
|
+
try:
|
|
1059
|
+
X = self._set
|
|
1060
|
+
if len(X) != len(w) or X != frozenset(range(1, len(w) + 1)):
|
|
1061
|
+
raise ValueError(f"result not in {self}")
|
|
1062
|
+
except AttributeError:
|
|
1063
|
+
pass
|
|
1064
|
+
return self.element_class(self, W(w).to_ordered_set_partition())
|
|
1065
|
+
raise TypeError(f"`from_finite_word` expects an object of type list/tuple/str/Word "
|
|
1066
|
+
f"representing a finite word, received {w}")
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
class OrderedSetPartitions_s(OrderedSetPartitions):
|
|
1070
|
+
"""
|
|
1071
|
+
Class of ordered partitions of a set `S`.
|
|
1072
|
+
"""
|
|
1073
|
+
|
|
1074
|
+
def _repr_(self):
|
|
1075
|
+
"""
|
|
1076
|
+
TESTS::
|
|
1077
|
+
|
|
1078
|
+
sage: OrderedSetPartitions([1,2,3,4])
|
|
1079
|
+
Ordered set partitions of {1, 2, 3, 4}
|
|
1080
|
+
"""
|
|
1081
|
+
return "Ordered set partitions of %s" % Set(self._set)
|
|
1082
|
+
|
|
1083
|
+
def cardinality(self):
|
|
1084
|
+
"""
|
|
1085
|
+
EXAMPLES::
|
|
1086
|
+
|
|
1087
|
+
sage: OrderedSetPartitions(0).cardinality()
|
|
1088
|
+
1
|
|
1089
|
+
sage: OrderedSetPartitions(1).cardinality()
|
|
1090
|
+
1
|
|
1091
|
+
sage: OrderedSetPartitions(2).cardinality()
|
|
1092
|
+
3
|
|
1093
|
+
sage: OrderedSetPartitions(3).cardinality()
|
|
1094
|
+
13
|
|
1095
|
+
sage: OrderedSetPartitions([1,2,3]).cardinality()
|
|
1096
|
+
13
|
|
1097
|
+
sage: OrderedSetPartitions(4).cardinality()
|
|
1098
|
+
75
|
|
1099
|
+
sage: OrderedSetPartitions(5).cardinality()
|
|
1100
|
+
541
|
|
1101
|
+
"""
|
|
1102
|
+
N = len(self._set)
|
|
1103
|
+
return sum(factorial(k) * stirling_number2(N, k)
|
|
1104
|
+
for k in range(N + 1))
|
|
1105
|
+
|
|
1106
|
+
def __iter__(self):
|
|
1107
|
+
"""
|
|
1108
|
+
EXAMPLES::
|
|
1109
|
+
|
|
1110
|
+
sage: list(OrderedSetPartitions([1,2,3]))
|
|
1111
|
+
[[{1}, {2}, {3}],
|
|
1112
|
+
[{1}, {3}, {2}],
|
|
1113
|
+
[{2}, {1}, {3}],
|
|
1114
|
+
[{3}, {1}, {2}],
|
|
1115
|
+
[{2}, {3}, {1}],
|
|
1116
|
+
[{3}, {2}, {1}],
|
|
1117
|
+
[{1}, {2, 3}],
|
|
1118
|
+
[{2}, {1, 3}],
|
|
1119
|
+
[{3}, {1, 2}],
|
|
1120
|
+
[{1, 2}, {3}],
|
|
1121
|
+
[{1, 3}, {2}],
|
|
1122
|
+
[{2, 3}, {1}],
|
|
1123
|
+
[{1, 2, 3}]]
|
|
1124
|
+
|
|
1125
|
+
TESTS:
|
|
1126
|
+
|
|
1127
|
+
Test for :issue:`35654`::
|
|
1128
|
+
|
|
1129
|
+
sage: OrderedSetPartitions(set(),[0,0,0]).list()
|
|
1130
|
+
[[{}, {}, {}]]
|
|
1131
|
+
"""
|
|
1132
|
+
for x in Compositions(len(self._set)):
|
|
1133
|
+
for z in OrderedSetPartitions(self._set, x):
|
|
1134
|
+
yield self.element_class(self, z, check=False)
|
|
1135
|
+
|
|
1136
|
+
|
|
1137
|
+
class OrderedSetPartitions_sn(OrderedSetPartitions):
|
|
1138
|
+
def __init__(self, s, n):
|
|
1139
|
+
"""
|
|
1140
|
+
TESTS::
|
|
1141
|
+
|
|
1142
|
+
sage: OS = OrderedSetPartitions([1,2,3,4], 2)
|
|
1143
|
+
sage: OS == loads(dumps(OS))
|
|
1144
|
+
True
|
|
1145
|
+
"""
|
|
1146
|
+
OrderedSetPartitions.__init__(self, s)
|
|
1147
|
+
self.n = n
|
|
1148
|
+
|
|
1149
|
+
def __contains__(self, x):
|
|
1150
|
+
"""
|
|
1151
|
+
TESTS::
|
|
1152
|
+
|
|
1153
|
+
sage: OS = OrderedSetPartitions([1,2,3,4], 2)
|
|
1154
|
+
sage: all(sp in OS for sp in OS)
|
|
1155
|
+
True
|
|
1156
|
+
sage: OS.cardinality()
|
|
1157
|
+
14
|
|
1158
|
+
sage: len([x for x in OrderedSetPartitions([1,2,3,4]) if x in OS])
|
|
1159
|
+
14
|
|
1160
|
+
"""
|
|
1161
|
+
return OrderedSetPartitions.__contains__(self, x) and len(x) == self.n
|
|
1162
|
+
|
|
1163
|
+
def __repr__(self):
|
|
1164
|
+
"""
|
|
1165
|
+
TESTS::
|
|
1166
|
+
|
|
1167
|
+
sage: OrderedSetPartitions([1,2,3,4], 2)
|
|
1168
|
+
Ordered set partitions of {1, 2, 3, 4} into 2 parts
|
|
1169
|
+
"""
|
|
1170
|
+
return "Ordered set partitions of %s into %s parts" % (Set(self._set),
|
|
1171
|
+
self.n)
|
|
1172
|
+
|
|
1173
|
+
def cardinality(self):
|
|
1174
|
+
"""
|
|
1175
|
+
Return the cardinality of ``self``.
|
|
1176
|
+
|
|
1177
|
+
The number of ordered partitions of a set of size `n` into `k`
|
|
1178
|
+
parts is equal to `k! S(n,k)` where `S(n,k)` denotes the Stirling
|
|
1179
|
+
number of the second kind.
|
|
1180
|
+
|
|
1181
|
+
EXAMPLES::
|
|
1182
|
+
|
|
1183
|
+
sage: OrderedSetPartitions(4,2).cardinality()
|
|
1184
|
+
14
|
|
1185
|
+
sage: OrderedSetPartitions(4,1).cardinality()
|
|
1186
|
+
1
|
|
1187
|
+
"""
|
|
1188
|
+
return factorial(self.n) * stirling_number2(len(self._set), self.n)
|
|
1189
|
+
|
|
1190
|
+
def __iter__(self):
|
|
1191
|
+
"""
|
|
1192
|
+
EXAMPLES::
|
|
1193
|
+
|
|
1194
|
+
sage: [ p for p in OrderedSetPartitions([1,2,3,4], 2) ]
|
|
1195
|
+
[[{1, 2, 3}, {4}],
|
|
1196
|
+
[{1, 2, 4}, {3}],
|
|
1197
|
+
[{1, 3, 4}, {2}],
|
|
1198
|
+
[{2, 3, 4}, {1}],
|
|
1199
|
+
[{1, 2}, {3, 4}],
|
|
1200
|
+
[{1, 3}, {2, 4}],
|
|
1201
|
+
[{1, 4}, {2, 3}],
|
|
1202
|
+
[{2, 3}, {1, 4}],
|
|
1203
|
+
[{2, 4}, {1, 3}],
|
|
1204
|
+
[{3, 4}, {1, 2}],
|
|
1205
|
+
[{1}, {2, 3, 4}],
|
|
1206
|
+
[{2}, {1, 3, 4}],
|
|
1207
|
+
[{3}, {1, 2, 4}],
|
|
1208
|
+
[{4}, {1, 2, 3}]]
|
|
1209
|
+
"""
|
|
1210
|
+
for x in Compositions(len(self._set), length=self.n):
|
|
1211
|
+
for z in OrderedSetPartitions_scomp(self._set, x):
|
|
1212
|
+
yield self.element_class(self, z, check=False)
|
|
1213
|
+
|
|
1214
|
+
|
|
1215
|
+
class OrderedSetPartitions_scomp(OrderedSetPartitions):
|
|
1216
|
+
def __init__(self, s, comp):
|
|
1217
|
+
"""
|
|
1218
|
+
TESTS::
|
|
1219
|
+
|
|
1220
|
+
sage: OS = OrderedSetPartitions([1,2,3,4], [2,1,1])
|
|
1221
|
+
sage: OS == loads(dumps(OS))
|
|
1222
|
+
True
|
|
1223
|
+
"""
|
|
1224
|
+
OrderedSetPartitions.__init__(self, s)
|
|
1225
|
+
self.c = Composition(comp)
|
|
1226
|
+
|
|
1227
|
+
def __repr__(self):
|
|
1228
|
+
"""
|
|
1229
|
+
TESTS::
|
|
1230
|
+
|
|
1231
|
+
sage: OrderedSetPartitions([1,2,3,4], [2,1,1])
|
|
1232
|
+
Ordered set partitions of {1, 2, 3, 4} into parts of size [2, 1, 1]
|
|
1233
|
+
"""
|
|
1234
|
+
return "Ordered set partitions of %s into parts of size %s" % (Set(self._set), self.c)
|
|
1235
|
+
|
|
1236
|
+
def __contains__(self, x):
|
|
1237
|
+
"""
|
|
1238
|
+
TESTS::
|
|
1239
|
+
|
|
1240
|
+
sage: OS = OrderedSetPartitions([1,2,3,4], [2,1,1])
|
|
1241
|
+
sage: all(sp in OS for sp in OS)
|
|
1242
|
+
True
|
|
1243
|
+
sage: OS.cardinality()
|
|
1244
|
+
12
|
|
1245
|
+
sage: len([x for x in OrderedSetPartitions([1,2,3,4]) if x in OS])
|
|
1246
|
+
12
|
|
1247
|
+
"""
|
|
1248
|
+
return OrderedSetPartitions.__contains__(self, x) and [len(z) for z in x] == self.c
|
|
1249
|
+
|
|
1250
|
+
def cardinality(self):
|
|
1251
|
+
r"""
|
|
1252
|
+
Return the cardinality of ``self``.
|
|
1253
|
+
|
|
1254
|
+
The number of ordered set partitions of a set of length `k` with
|
|
1255
|
+
composition shape `\mu` is equal to
|
|
1256
|
+
|
|
1257
|
+
.. MATH::
|
|
1258
|
+
|
|
1259
|
+
\frac{k!}{\prod_{\mu_i \neq 0} \mu_i!}.
|
|
1260
|
+
|
|
1261
|
+
EXAMPLES::
|
|
1262
|
+
|
|
1263
|
+
sage: OrderedSetPartitions(5,[2,3]).cardinality()
|
|
1264
|
+
10
|
|
1265
|
+
sage: OrderedSetPartitions(0, []).cardinality()
|
|
1266
|
+
1
|
|
1267
|
+
sage: OrderedSetPartitions(0, [0]).cardinality()
|
|
1268
|
+
1
|
|
1269
|
+
sage: OrderedSetPartitions(0, [0,0]).cardinality()
|
|
1270
|
+
1
|
|
1271
|
+
sage: OrderedSetPartitions(5, [2,0,3]).cardinality()
|
|
1272
|
+
10
|
|
1273
|
+
"""
|
|
1274
|
+
return multinomial(self.c)
|
|
1275
|
+
|
|
1276
|
+
def __iter__(self):
|
|
1277
|
+
"""
|
|
1278
|
+
TESTS::
|
|
1279
|
+
|
|
1280
|
+
sage: [ p for p in OrderedSetPartitions([1,2,3,4], [2,1,1]) ]
|
|
1281
|
+
[[{1, 2}, {3}, {4}],
|
|
1282
|
+
[{1, 2}, {4}, {3}],
|
|
1283
|
+
[{1, 3}, {2}, {4}],
|
|
1284
|
+
[{1, 4}, {2}, {3}],
|
|
1285
|
+
[{1, 3}, {4}, {2}],
|
|
1286
|
+
[{1, 4}, {3}, {2}],
|
|
1287
|
+
[{2, 3}, {1}, {4}],
|
|
1288
|
+
[{2, 4}, {1}, {3}],
|
|
1289
|
+
[{3, 4}, {1}, {2}],
|
|
1290
|
+
[{2, 3}, {4}, {1}],
|
|
1291
|
+
[{2, 4}, {3}, {1}],
|
|
1292
|
+
[{3, 4}, {2}, {1}]]
|
|
1293
|
+
|
|
1294
|
+
sage: len(OrderedSetPartitions([1,2,3,4], [1,1,1,1]))
|
|
1295
|
+
24
|
|
1296
|
+
|
|
1297
|
+
sage: [ x for x in OrderedSetPartitions([1,4,7], [3]) ]
|
|
1298
|
+
[[{1, 4, 7}]]
|
|
1299
|
+
|
|
1300
|
+
sage: [ x for x in OrderedSetPartitions([1,4,7], [1,2]) ]
|
|
1301
|
+
[[{1}, {4, 7}], [{4}, {1, 7}], [{7}, {1, 4}]]
|
|
1302
|
+
|
|
1303
|
+
sage: [ p for p in OrderedSetPartitions([], []) ]
|
|
1304
|
+
[[]]
|
|
1305
|
+
|
|
1306
|
+
sage: [ p for p in OrderedSetPartitions([1], [1]) ]
|
|
1307
|
+
[[{1}]]
|
|
1308
|
+
|
|
1309
|
+
Let us check that it works for large size (:issue:`16646`)::
|
|
1310
|
+
|
|
1311
|
+
sage: OrderedSetPartitions(42).first()
|
|
1312
|
+
[{1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12},
|
|
1313
|
+
{13}, {14}, {15}, {16}, {17}, {18}, {19}, {20}, {21}, {22}, {23},
|
|
1314
|
+
{24}, {25}, {26}, {27}, {28}, {29}, {30}, {31}, {32}, {33}, {34},
|
|
1315
|
+
{35}, {36}, {37}, {38}, {39}, {40}, {41}, {42}]
|
|
1316
|
+
|
|
1317
|
+
EXAMPLES::
|
|
1318
|
+
|
|
1319
|
+
sage: list(OrderedSetPartitions(range(5), [2,1,2]))
|
|
1320
|
+
[[{0, 1}, {2}, {3, 4}],
|
|
1321
|
+
[{0, 1}, {3}, {2, 4}],
|
|
1322
|
+
...
|
|
1323
|
+
[{2, 4}, {3}, {0, 1}],
|
|
1324
|
+
[{3, 4}, {2}, {0, 1}]]
|
|
1325
|
+
"""
|
|
1326
|
+
part_sizes = self.c
|
|
1327
|
+
N = len(part_sizes)
|
|
1328
|
+
if not N:
|
|
1329
|
+
yield self.element_class(self, [], check=False)
|
|
1330
|
+
return
|
|
1331
|
+
|
|
1332
|
+
l = []
|
|
1333
|
+
lset = list(self._set)
|
|
1334
|
+
for i, j in enumerate(part_sizes):
|
|
1335
|
+
l.extend([i] * j)
|
|
1336
|
+
|
|
1337
|
+
pi = multiset_permutation_to_ordered_set_partition(l, N)
|
|
1338
|
+
converted = [frozenset(lset[i] for i in part) for part in pi]
|
|
1339
|
+
yield self.element_class(self, converted, check=False)
|
|
1340
|
+
|
|
1341
|
+
while multiset_permutation_next_lex(l):
|
|
1342
|
+
pi = multiset_permutation_to_ordered_set_partition(l, N)
|
|
1343
|
+
converted = [frozenset(lset[i] for i in part) for part in pi]
|
|
1344
|
+
yield self.element_class(self, converted, check=False)
|
|
1345
|
+
|
|
1346
|
+
|
|
1347
|
+
def multiset_permutation_to_ordered_set_partition(l, m):
|
|
1348
|
+
r"""
|
|
1349
|
+
Convert a multiset permutation to an ordered set partition.
|
|
1350
|
+
|
|
1351
|
+
INPUT:
|
|
1352
|
+
|
|
1353
|
+
- ``l`` -- a multiset permutation
|
|
1354
|
+
- ``m`` -- number of parts
|
|
1355
|
+
|
|
1356
|
+
EXAMPLES::
|
|
1357
|
+
|
|
1358
|
+
sage: from sage.combinat.set_partition_ordered import multiset_permutation_to_ordered_set_partition
|
|
1359
|
+
sage: l = [0, 0, 1, 1, 2]
|
|
1360
|
+
sage: multiset_permutation_to_ordered_set_partition(l, 3)
|
|
1361
|
+
[[0, 1], [2, 3], [4]]
|
|
1362
|
+
"""
|
|
1363
|
+
p = [[] for _ in range(m)]
|
|
1364
|
+
for i, j in enumerate(l):
|
|
1365
|
+
p[j].append(i)
|
|
1366
|
+
return p
|
|
1367
|
+
|
|
1368
|
+
|
|
1369
|
+
def multiset_permutation_next_lex(l):
|
|
1370
|
+
r"""
|
|
1371
|
+
Return the next multiset permutation after ``l``.
|
|
1372
|
+
|
|
1373
|
+
EXAMPLES::
|
|
1374
|
+
|
|
1375
|
+
sage: from sage.combinat.set_partition_ordered import multiset_permutation_next_lex
|
|
1376
|
+
sage: l = [0, 0, 1, 1, 2]
|
|
1377
|
+
sage: while multiset_permutation_next_lex(l):
|
|
1378
|
+
....: print(l)
|
|
1379
|
+
[0, 0, 1, 2, 1]
|
|
1380
|
+
[0, 0, 2, 1, 1]
|
|
1381
|
+
[0, 1, 0, 1, 2]
|
|
1382
|
+
[0, 1, 0, 2, 1]
|
|
1383
|
+
[0, 1, 1, 0, 2]
|
|
1384
|
+
[0, 1, 1, 2, 0]
|
|
1385
|
+
...
|
|
1386
|
+
[1, 1, 2, 0, 0]
|
|
1387
|
+
[1, 2, 0, 0, 1]
|
|
1388
|
+
[1, 2, 0, 1, 0]
|
|
1389
|
+
[1, 2, 1, 0, 0]
|
|
1390
|
+
[2, 0, 0, 1, 1]
|
|
1391
|
+
[2, 0, 1, 0, 1]
|
|
1392
|
+
[2, 0, 1, 1, 0]
|
|
1393
|
+
[2, 1, 0, 0, 1]
|
|
1394
|
+
[2, 1, 0, 1, 0]
|
|
1395
|
+
[2, 1, 1, 0, 0]
|
|
1396
|
+
|
|
1397
|
+
TESTS:
|
|
1398
|
+
|
|
1399
|
+
Test for :issue:`35654`::
|
|
1400
|
+
|
|
1401
|
+
sage: multiset_permutation_next_lex([])
|
|
1402
|
+
0
|
|
1403
|
+
"""
|
|
1404
|
+
i = len(l) - 2
|
|
1405
|
+
while i >= 0 and l[i] >= l[i + 1]:
|
|
1406
|
+
i -= 1
|
|
1407
|
+
if i <= -1:
|
|
1408
|
+
return 0
|
|
1409
|
+
j = len(l) - 1
|
|
1410
|
+
while l[j] <= l[i]:
|
|
1411
|
+
j -= 1
|
|
1412
|
+
l[i], l[j] = l[j], l[i]
|
|
1413
|
+
l[i + 1:] = l[:i:-1]
|
|
1414
|
+
return 1
|
|
1415
|
+
|
|
1416
|
+
|
|
1417
|
+
class OrderedSetPartitions_all(OrderedSetPartitions):
|
|
1418
|
+
r"""
|
|
1419
|
+
Ordered set partitions of `\{1, \ldots, n\}` for all
|
|
1420
|
+
`n \in \ZZ_{\geq 0}`.
|
|
1421
|
+
"""
|
|
1422
|
+
|
|
1423
|
+
def __init__(self):
|
|
1424
|
+
"""
|
|
1425
|
+
Initialize ``self``.
|
|
1426
|
+
|
|
1427
|
+
EXAMPLES::
|
|
1428
|
+
|
|
1429
|
+
sage: OS = OrderedSetPartitions()
|
|
1430
|
+
sage: TestSuite(OS).run() # long time
|
|
1431
|
+
"""
|
|
1432
|
+
Parent.__init__(self, category=InfiniteEnumeratedSets())
|
|
1433
|
+
|
|
1434
|
+
def subset(self, size=None, **kwargs):
|
|
1435
|
+
"""
|
|
1436
|
+
Return the subset of ordered set partitions of a given
|
|
1437
|
+
size and additional keyword arguments.
|
|
1438
|
+
|
|
1439
|
+
EXAMPLES::
|
|
1440
|
+
|
|
1441
|
+
sage: P = OrderedSetPartitions()
|
|
1442
|
+
sage: P.subset(4)
|
|
1443
|
+
Ordered set partitions of {1, 2, 3, 4}
|
|
1444
|
+
"""
|
|
1445
|
+
if size is None:
|
|
1446
|
+
return self
|
|
1447
|
+
return OrderedSetPartitions(size, **kwargs)
|
|
1448
|
+
|
|
1449
|
+
def __iter__(self):
|
|
1450
|
+
"""
|
|
1451
|
+
Iterate over ``self``.
|
|
1452
|
+
|
|
1453
|
+
EXAMPLES::
|
|
1454
|
+
|
|
1455
|
+
sage: it = iter(OrderedSetPartitions())
|
|
1456
|
+
sage: [next(it) for _ in range(10)]
|
|
1457
|
+
[[], [{1}], [{1}, {2}], [{2}, {1}], [{1, 2}],
|
|
1458
|
+
[{1}, {2}, {3}], [{1}, {3}, {2}], [{2}, {1}, {3}],
|
|
1459
|
+
[{3}, {1}, {2}], [{2}, {3}, {1}]]
|
|
1460
|
+
"""
|
|
1461
|
+
n = 0
|
|
1462
|
+
while True:
|
|
1463
|
+
for X in OrderedSetPartitions(n):
|
|
1464
|
+
yield self.element_class(self, list(X), check=False)
|
|
1465
|
+
n += 1
|
|
1466
|
+
|
|
1467
|
+
def _element_constructor_(self, s):
|
|
1468
|
+
"""
|
|
1469
|
+
Construct an element of ``self`` from ``s``.
|
|
1470
|
+
|
|
1471
|
+
EXAMPLES::
|
|
1472
|
+
|
|
1473
|
+
sage: OS = OrderedSetPartitions()
|
|
1474
|
+
sage: OS([[1,3],[2,4]])
|
|
1475
|
+
[{1, 3}, {2, 4}]
|
|
1476
|
+
"""
|
|
1477
|
+
if isinstance(s, OrderedSetPartition):
|
|
1478
|
+
gset = s.parent()._set
|
|
1479
|
+
if gset == frozenset(range(1, len(gset) + 1)):
|
|
1480
|
+
return self.element_class(self, list(s))
|
|
1481
|
+
raise ValueError("cannot convert %s into an element of %s" % (s, self))
|
|
1482
|
+
return self.element_class(self, list(s))
|
|
1483
|
+
|
|
1484
|
+
def __contains__(self, x):
|
|
1485
|
+
"""
|
|
1486
|
+
TESTS::
|
|
1487
|
+
|
|
1488
|
+
sage: OS = OrderedSetPartitions([1,2,3,4])
|
|
1489
|
+
sage: AOS = OrderedSetPartitions()
|
|
1490
|
+
sage: all(sp in AOS for sp in OS)
|
|
1491
|
+
True
|
|
1492
|
+
sage: AOS.__contains__([[1,3], [4], [5,2]])
|
|
1493
|
+
True
|
|
1494
|
+
sage: AOS.__contains__([Set([1,3]), Set([4]), Set([5,2])])
|
|
1495
|
+
True
|
|
1496
|
+
sage: [Set([1,4]), Set([3])] in AOS
|
|
1497
|
+
False
|
|
1498
|
+
sage: [Set([1,3]), Set([4,2]), Set([2,5])] in AOS
|
|
1499
|
+
False
|
|
1500
|
+
sage: [Set([1,2]), Set()] in AOS
|
|
1501
|
+
False
|
|
1502
|
+
"""
|
|
1503
|
+
if isinstance(x, OrderedSetPartition):
|
|
1504
|
+
if x.parent() is self:
|
|
1505
|
+
return True
|
|
1506
|
+
gset = x.parent()._set
|
|
1507
|
+
return gset == frozenset(range(1, len(gset) + 1))
|
|
1508
|
+
|
|
1509
|
+
# x must be a list or a tuple
|
|
1510
|
+
if not isinstance(x, (list, tuple)):
|
|
1511
|
+
return False
|
|
1512
|
+
|
|
1513
|
+
# Check to make sure each element of the list is a nonempty set
|
|
1514
|
+
if not all(s and isinstance(s, (set, frozenset, list, tuple, Set_generic)) for s in x):
|
|
1515
|
+
return False
|
|
1516
|
+
|
|
1517
|
+
if not all(isinstance(s, (set, frozenset, Set_generic)) or len(s) == len(set(s)) for s in x):
|
|
1518
|
+
return False
|
|
1519
|
+
X = set(y for p in x for y in p)
|
|
1520
|
+
return len(X) == sum(len(s) for s in x) and X == frozenset(range(1, len(X) + 1))
|
|
1521
|
+
|
|
1522
|
+
def _coerce_map_from_(self, X):
|
|
1523
|
+
"""
|
|
1524
|
+
Return ``True`` if there is a coercion map from ``X``.
|
|
1525
|
+
|
|
1526
|
+
EXAMPLES::
|
|
1527
|
+
|
|
1528
|
+
sage: OSP = OrderedSetPartitions()
|
|
1529
|
+
sage: OSP._coerce_map_from_(OrderedSetPartitions(3))
|
|
1530
|
+
True
|
|
1531
|
+
sage: OSP._coerce_map_from_(OrderedSetPartitions(['a','b']))
|
|
1532
|
+
False
|
|
1533
|
+
"""
|
|
1534
|
+
if X is self:
|
|
1535
|
+
return True
|
|
1536
|
+
if isinstance(X, OrderedSetPartitions):
|
|
1537
|
+
return X._set == frozenset(range(1, len(X._set) + 1))
|
|
1538
|
+
return super()._coerce_map_from_(X)
|
|
1539
|
+
|
|
1540
|
+
def _repr_(self):
|
|
1541
|
+
"""
|
|
1542
|
+
TESTS::
|
|
1543
|
+
|
|
1544
|
+
sage: OrderedSetPartitions()
|
|
1545
|
+
Ordered set partitions
|
|
1546
|
+
"""
|
|
1547
|
+
return "Ordered set partitions"
|
|
1548
|
+
|
|
1549
|
+
class Element(OrderedSetPartition):
|
|
1550
|
+
def _richcmp_(self, other, op):
|
|
1551
|
+
"""
|
|
1552
|
+
TESTS::
|
|
1553
|
+
|
|
1554
|
+
sage: OSP = OrderedSetPartitions()
|
|
1555
|
+
sage: el1 = OSP([[1,3], [4], [2]])
|
|
1556
|
+
sage: el2 = OSP([[3,1], [2], [4]])
|
|
1557
|
+
sage: el1 == el1, el2 == el2, el1 == el2 # indirect doctest
|
|
1558
|
+
(True, True, False)
|
|
1559
|
+
sage: el1 <= el2, el1 >= el2, el2 <= el1 # indirect doctest
|
|
1560
|
+
(False, True, True)
|
|
1561
|
+
"""
|
|
1562
|
+
return richcmp([sorted(s) for s in self],
|
|
1563
|
+
[sorted(s) for s in other], op)
|
|
1564
|
+
|
|
1565
|
+
##########################################################
|
|
1566
|
+
# Deprecations
|
|
1567
|
+
|
|
1568
|
+
|
|
1569
|
+
class SplitNK(OrderedSetPartitions_scomp):
|
|
1570
|
+
def __setstate__(self, state):
|
|
1571
|
+
r"""
|
|
1572
|
+
For unpickling old ``SplitNK`` objects.
|
|
1573
|
+
|
|
1574
|
+
TESTS::
|
|
1575
|
+
|
|
1576
|
+
sage: loads(b"x\x9ck`J.NLO\xd5K\xce\xcfM\xca\xccK,\xd1+.\xc8\xc9,"
|
|
1577
|
+
....: b"\x89\xcf\xcb\xe6\n\x061\xfc\xbcA\xccBF\xcd\xc6B\xa6\xda"
|
|
1578
|
+
....: b"Bf\x8dP\xa6\xf8\xbcB\x16\x88\x96\xa2\xcc\xbc\xf4b\xbd\xcc"
|
|
1579
|
+
....: b"\xbc\x92\xd4\xf4\xd4\"\xae\xdc\xc4\xec\xd4x\x18\xa7\x905"
|
|
1580
|
+
....: b"\x94\xd1\xb45\xa8\x90\r\xa8>\xbb\x90=\x03\xc85\x02r9J\x93"
|
|
1581
|
+
....: b"\xf4\x00\xb4\xc6%f")
|
|
1582
|
+
Ordered set partitions of {0, 1, 2, 3, 4} into parts of size [2, 3]
|
|
1583
|
+
"""
|
|
1584
|
+
self.__class__ = OrderedSetPartitions_scomp
|
|
1585
|
+
n = state['_n']
|
|
1586
|
+
k = state['_k']
|
|
1587
|
+
OrderedSetPartitions_scomp.__init__(self, range(state['_n']), (k, n - k))
|
|
1588
|
+
|
|
1589
|
+
|
|
1590
|
+
register_unpickle_override("sage.combinat.split_nk", "SplitNK_nk", SplitNK)
|