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,885 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
# sage.doctest: needs sage.combinat sage.modules
|
|
3
|
+
r"""
|
|
4
|
+
Key polynomials
|
|
5
|
+
|
|
6
|
+
Key polynomials (also known as type A Demazure characters) are defined by
|
|
7
|
+
applying the divided difference operator `\pi_\sigma`, where `\sigma` is
|
|
8
|
+
a permutation, to a monomial corresponding to an integer partition
|
|
9
|
+
`\mu \vdash n`.
|
|
10
|
+
|
|
11
|
+
.. SEEALSO::
|
|
12
|
+
|
|
13
|
+
For Demazure characters in other types, see
|
|
14
|
+
|
|
15
|
+
- :meth:`sage.combinat.root_system.weyl_characters.WeylCharacterRing.demazure_character`
|
|
16
|
+
- :meth:`sage.categories.classical_crystals.ClassicalCrystals.ParentMethods.demazure_character`
|
|
17
|
+
|
|
18
|
+
AUTHORS:
|
|
19
|
+
|
|
20
|
+
- Trevor K. Karn (2022-08-17): initial version
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
# ****************************************************************************
|
|
24
|
+
# Copyright (C) 2022 Trevor K. Karn <karnx018 (at) umn.edu>
|
|
25
|
+
#
|
|
26
|
+
# This program is free software: you can redistribute it and/or modify
|
|
27
|
+
# it under the terms of the GNU General Public License as published by
|
|
28
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
29
|
+
# (at your option) any later version.
|
|
30
|
+
# https://www.gnu.org/licenses/
|
|
31
|
+
# ****************************************************************************
|
|
32
|
+
from collections.abc import Collection
|
|
33
|
+
|
|
34
|
+
from sage.categories.graded_algebras_with_basis import GradedAlgebrasWithBasis
|
|
35
|
+
from sage.combinat.free_module import CombinatorialFreeModule
|
|
36
|
+
from sage.combinat.integer_vector import IntegerVectors
|
|
37
|
+
from sage.combinat.permutation import Permutation
|
|
38
|
+
from sage.misc.cachefunc import cached_method
|
|
39
|
+
from sage.rings.integer_ring import ZZ
|
|
40
|
+
from sage.rings.polynomial.infinite_polynomial_ring import InfinitePolynomialRing, InfinitePolynomialRing_sparse
|
|
41
|
+
from sage.rings.polynomial.multi_polynomial_ring_base import MPolynomialRing_base
|
|
42
|
+
from sage.rings.polynomial.polynomial_ring import PolynomialRing_commutative
|
|
43
|
+
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
|
|
44
|
+
from sage.structure.element import parent
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class KeyPolynomial(CombinatorialFreeModule.Element):
|
|
48
|
+
r"""
|
|
49
|
+
A key polynomial.
|
|
50
|
+
|
|
51
|
+
Key polynomials are polynomials that form a basis for a polynomial ring
|
|
52
|
+
and are indexed by weak compositions.
|
|
53
|
+
|
|
54
|
+
Elements should be created by first creating the basis
|
|
55
|
+
:class:`KeyPolynomialBasis` and passing a list representing the indexing
|
|
56
|
+
composition.
|
|
57
|
+
|
|
58
|
+
EXAMPLES::
|
|
59
|
+
|
|
60
|
+
sage: k = KeyPolynomials(QQ)
|
|
61
|
+
sage: f = k([4,3,2,1]) + k([1,2,3,4]); f
|
|
62
|
+
k[1, 2, 3, 4] + k[4, 3, 2, 1]
|
|
63
|
+
sage: f in k
|
|
64
|
+
True
|
|
65
|
+
"""
|
|
66
|
+
def _mul_(self, other):
|
|
67
|
+
r"""
|
|
68
|
+
Multiply the elements ``self`` and ``other``.
|
|
69
|
+
|
|
70
|
+
EXAMPLES::
|
|
71
|
+
|
|
72
|
+
sage: k = KeyPolynomials(QQ)
|
|
73
|
+
sage: k([4,3,2]) * k([1,1,1])
|
|
74
|
+
k[5, 4, 3]
|
|
75
|
+
|
|
76
|
+
sage: k = KeyPolynomials(QQ, 4)
|
|
77
|
+
sage: k([4,3,2,0]) * k([1,1,1,0])
|
|
78
|
+
k[5, 4, 3, 0]
|
|
79
|
+
"""
|
|
80
|
+
return self.parent().from_polynomial(self.expand() * other.expand())
|
|
81
|
+
|
|
82
|
+
def expand(self):
|
|
83
|
+
r"""
|
|
84
|
+
Return ``self`` written in the monomial basis (i.e., as an element
|
|
85
|
+
in the corresponding polynomial ring).
|
|
86
|
+
|
|
87
|
+
EXAMPLES::
|
|
88
|
+
|
|
89
|
+
sage: k = KeyPolynomials(QQ)
|
|
90
|
+
sage: f = k([4,3,2,1])
|
|
91
|
+
sage: f.expand()
|
|
92
|
+
z_3*z_2^2*z_1^3*z_0^4
|
|
93
|
+
|
|
94
|
+
sage: f = k([1,2,3])
|
|
95
|
+
sage: f.expand()
|
|
96
|
+
z_2^3*z_1^2*z_0 + z_2^3*z_1*z_0^2 + z_2^2*z_1^3*z_0
|
|
97
|
+
+ 2*z_2^2*z_1^2*z_0^2 + z_2^2*z_1*z_0^3 + z_2*z_1^3*z_0^2
|
|
98
|
+
+ z_2*z_1^2*z_0^3
|
|
99
|
+
"""
|
|
100
|
+
P = self.parent()
|
|
101
|
+
R = P._polynomial_ring
|
|
102
|
+
out = R.zero()
|
|
103
|
+
z = P.poly_gens()
|
|
104
|
+
|
|
105
|
+
for m, c in self.monomial_coefficients().items():
|
|
106
|
+
# find the permutation sorting mu into m
|
|
107
|
+
w, mu = sorting_word(m)
|
|
108
|
+
|
|
109
|
+
# create the monomial to apply
|
|
110
|
+
monom = R.prod(z[i] ** mi for i, mi in enumerate(mu) if mi)
|
|
111
|
+
|
|
112
|
+
out += c * isobaric_divided_difference(monom, w)
|
|
113
|
+
|
|
114
|
+
return out
|
|
115
|
+
|
|
116
|
+
to_polynomial = expand
|
|
117
|
+
|
|
118
|
+
def pi(self, w):
|
|
119
|
+
r"""
|
|
120
|
+
Apply the operator `\pi_w` to ``self``.
|
|
121
|
+
|
|
122
|
+
``w`` may be either a ``Permutation`` or a list of indices of simple
|
|
123
|
+
transpositions (1-based).
|
|
124
|
+
|
|
125
|
+
The convention is to apply from left to right so if
|
|
126
|
+
``w = [w1, w2, ..., wm]`` then we apply
|
|
127
|
+
`\pi_{w_2 \cdots w_m} \circ \pi_{w_1}`
|
|
128
|
+
|
|
129
|
+
EXAMPLES::
|
|
130
|
+
|
|
131
|
+
sage: k = KeyPolynomials(QQ)
|
|
132
|
+
sage: k([3,2,1]).pi(2)
|
|
133
|
+
k[3, 1, 2]
|
|
134
|
+
sage: k([3,2,1]).pi([2,1])
|
|
135
|
+
k[1, 3, 2]
|
|
136
|
+
sage: k([3,2,1]).pi(Permutation([3,2,1]))
|
|
137
|
+
k[1, 2, 3]
|
|
138
|
+
sage: f = k([3,2,1]) + k([3,2,1,1])
|
|
139
|
+
sage: f.pi(2)
|
|
140
|
+
k[3, 1, 2] + k[3, 1, 2, 1]
|
|
141
|
+
sage: k.one().pi(1)
|
|
142
|
+
k[]
|
|
143
|
+
|
|
144
|
+
sage: k([3,2,1,0]).pi(2).pi(2)
|
|
145
|
+
k[3, 1, 2]
|
|
146
|
+
sage: (-k([3,2,1,0]) + 4*k([3,1,2,0])).pi(2)
|
|
147
|
+
3*k[3, 1, 2]
|
|
148
|
+
|
|
149
|
+
sage: k = KeyPolynomials(QQ, 4)
|
|
150
|
+
sage: k([3,2,1,0]).pi(2)
|
|
151
|
+
k[3, 1, 2, 0]
|
|
152
|
+
sage: k([3,2,1,0]).pi([2,1])
|
|
153
|
+
k[1, 3, 2, 0]
|
|
154
|
+
sage: k([3,2,1,0]).pi(Permutation([3,2,1,4]))
|
|
155
|
+
k[1, 2, 3, 0]
|
|
156
|
+
sage: f = k([3,2,1,0]) + k([3,2,1,1])
|
|
157
|
+
sage: f.pi(2)
|
|
158
|
+
k[3, 1, 2, 0] + k[3, 1, 2, 1]
|
|
159
|
+
sage: k.one().pi(1)
|
|
160
|
+
k[0, 0, 0, 0]
|
|
161
|
+
|
|
162
|
+
TESTS:
|
|
163
|
+
|
|
164
|
+
We check that this is consistent with the definition via the
|
|
165
|
+
isobaric divided difference operators::
|
|
166
|
+
|
|
167
|
+
sage: from sage.combinat.key_polynomial import isobaric_divided_difference as idd
|
|
168
|
+
sage: k = KeyPolynomials(QQ, 4)
|
|
169
|
+
sage: S4 = Permutations(4)
|
|
170
|
+
sage: f = k([4,2,2,0])
|
|
171
|
+
sage: all(idd(f.expand(), w.reduced_word()) == f.pi(w).expand() for w in S4)
|
|
172
|
+
True
|
|
173
|
+
|
|
174
|
+
sage: f = k([4,2,0,1]) - 3 * k([2,0,1,2])
|
|
175
|
+
sage: all(idd(f.expand(), w.reduced_word()) == f.pi(w).expand() for w in S4)
|
|
176
|
+
True
|
|
177
|
+
"""
|
|
178
|
+
P = self.parent()
|
|
179
|
+
if isinstance(w, Permutation):
|
|
180
|
+
w = w.reduced_word()
|
|
181
|
+
if not isinstance(w, Collection):
|
|
182
|
+
w = [w]
|
|
183
|
+
|
|
184
|
+
if not w or not self:
|
|
185
|
+
return self
|
|
186
|
+
|
|
187
|
+
N = max(w) + 1
|
|
188
|
+
|
|
189
|
+
if P._k is not None and N > P._k:
|
|
190
|
+
raise ValueError(f"pi_{N-1} does not exist for this polynomial ring")
|
|
191
|
+
|
|
192
|
+
ret = P.element_class(P, {})
|
|
193
|
+
for m, c in self._monomial_coefficients.items():
|
|
194
|
+
m = list(m)
|
|
195
|
+
n = len(m)
|
|
196
|
+
for i in w:
|
|
197
|
+
if i > n:
|
|
198
|
+
continue
|
|
199
|
+
if i == n:
|
|
200
|
+
m += [0]
|
|
201
|
+
n += 1
|
|
202
|
+
if m[i-1] <= m[i]:
|
|
203
|
+
continue
|
|
204
|
+
m[i-1], m[i] = m[i], m[i-1]
|
|
205
|
+
m = P._indices(m)
|
|
206
|
+
if P._k is None:
|
|
207
|
+
m = m.trim()
|
|
208
|
+
if m in ret._monomial_coefficients:
|
|
209
|
+
ret._monomial_coefficients[m] += c
|
|
210
|
+
else:
|
|
211
|
+
ret._monomial_coefficients[m] = c
|
|
212
|
+
if not ret._monomial_coefficients[m]:
|
|
213
|
+
del ret._monomial_coefficients
|
|
214
|
+
return ret
|
|
215
|
+
|
|
216
|
+
isobaric_divided_difference = pi
|
|
217
|
+
|
|
218
|
+
def divided_difference(self, w):
|
|
219
|
+
r"""
|
|
220
|
+
Apply the divided difference operator `\partial_w` to ``self``.
|
|
221
|
+
|
|
222
|
+
The convention is to apply from left to right so if
|
|
223
|
+
``w = [w1, w2, ..., wm]`` then we apply
|
|
224
|
+
`\partial_{w_2 \cdots w_m} \circ \partial_{w_1}`
|
|
225
|
+
|
|
226
|
+
EXAMPLES::
|
|
227
|
+
|
|
228
|
+
sage: k = KeyPolynomials(QQ)
|
|
229
|
+
sage: k([3,2,1]).divided_difference(2)
|
|
230
|
+
k[3, 1, 1]
|
|
231
|
+
sage: k([3,2,1]).divided_difference([2,3])
|
|
232
|
+
k[3, 1]
|
|
233
|
+
|
|
234
|
+
sage: k = KeyPolynomials(QQ, 4)
|
|
235
|
+
sage: k([3,2,1,0]).divided_difference(2)
|
|
236
|
+
k[3, 1, 1, 0]
|
|
237
|
+
"""
|
|
238
|
+
if not isinstance(w, Collection):
|
|
239
|
+
w = [w]
|
|
240
|
+
f = self.expand()
|
|
241
|
+
for wi in w:
|
|
242
|
+
f = divided_difference(f, wi)
|
|
243
|
+
return self.parent().from_polynomial(f)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
class KeyPolynomialBasis(CombinatorialFreeModule):
|
|
247
|
+
r"""
|
|
248
|
+
The key polynomial basis for a polynomial ring.
|
|
249
|
+
|
|
250
|
+
For a full definition, see
|
|
251
|
+
`SymmetricFunctions.com <https://www.symmetricfunctions.com/key.htm>`_.
|
|
252
|
+
Key polynomials are indexed by weak compositions with no trailing zeros,
|
|
253
|
+
and `\sigma` is the permutation of shortest length which sorts the
|
|
254
|
+
indexing composition into a partition.
|
|
255
|
+
|
|
256
|
+
EXAMPLES:
|
|
257
|
+
|
|
258
|
+
Key polynomials are a basis, indexed by (weak) compositions,
|
|
259
|
+
for polynomial rings::
|
|
260
|
+
|
|
261
|
+
sage: k = KeyPolynomials(QQ)
|
|
262
|
+
sage: k([3,0,1,2])
|
|
263
|
+
k[3, 0, 1, 2]
|
|
264
|
+
sage: k([3,0,1,2])/2
|
|
265
|
+
1/2*k[3, 0, 1, 2]
|
|
266
|
+
sage: R = k.polynomial_ring(); R
|
|
267
|
+
Infinite polynomial ring in z over Rational Field
|
|
268
|
+
|
|
269
|
+
sage: K = KeyPolynomials(GF(5)); K
|
|
270
|
+
Key polynomial basis over Finite Field of size 5
|
|
271
|
+
sage: 2*K([3,0,1,2])
|
|
272
|
+
2*k[3, 0, 1, 2]
|
|
273
|
+
sage: 5*(K([3,0,1,2]) + K([3,1,1]))
|
|
274
|
+
0
|
|
275
|
+
|
|
276
|
+
We can expand them in the standard monomial basis::
|
|
277
|
+
|
|
278
|
+
sage: k([3,0,1,2]).expand()
|
|
279
|
+
z_3^2*z_2*z_0^3 + z_3^2*z_1*z_0^3 + z_3*z_2^2*z_0^3
|
|
280
|
+
+ 2*z_3*z_2*z_1*z_0^3 + z_3*z_1^2*z_0^3 + z_2^2*z_1*z_0^3
|
|
281
|
+
+ z_2*z_1^2*z_0^3
|
|
282
|
+
|
|
283
|
+
sage: k([0,0,2]).expand()
|
|
284
|
+
z_2^2 + z_2*z_1 + z_2*z_0 + z_1^2 + z_1*z_0 + z_0^2
|
|
285
|
+
|
|
286
|
+
If we have a polynomial, we can express it in the key basis::
|
|
287
|
+
|
|
288
|
+
sage: z = R.gen()
|
|
289
|
+
sage: k.from_polynomial(z[2]^2*z[1]*z[0])
|
|
290
|
+
k[1, 1, 2] - k[1, 2, 1]
|
|
291
|
+
|
|
292
|
+
sage: f = z[3]^2*z[2]*z[0]^3 + z[3]^2*z[1]*z[0]^3 + z[3]*z[2]^2*z[0]^3 + \
|
|
293
|
+
....: 2*z[3]*z[2]*z[1]*z[0]^3 + z[3]*z[1]^2*z[0]^3 + z[2]^2*z[1]*z[0]^3 + \
|
|
294
|
+
....: z[2]*z[1]^2*z[0]^3
|
|
295
|
+
sage: k.from_polynomial(f)
|
|
296
|
+
k[3, 0, 1, 2]
|
|
297
|
+
|
|
298
|
+
Since the ring of key polynomials may be regarded as a different choice of
|
|
299
|
+
basis for a polynomial ring, it forms an algebra, so we have
|
|
300
|
+
multiplication::
|
|
301
|
+
|
|
302
|
+
sage: k([10,5,2])*k([1,1,1])
|
|
303
|
+
k[11, 6, 3]
|
|
304
|
+
|
|
305
|
+
We can also multiply by polynomials in the monomial basis::
|
|
306
|
+
|
|
307
|
+
sage: k([10,9,1])*z[0]
|
|
308
|
+
k[11, 9, 1]
|
|
309
|
+
sage: z[0] * k([10,9,1])
|
|
310
|
+
k[11, 9, 1]
|
|
311
|
+
sage: k([10,9,1])*(z[0] + z[3])
|
|
312
|
+
k[10, 9, 1, 1] + k[11, 9, 1]
|
|
313
|
+
|
|
314
|
+
When the sorting permutation is the longest element, the key polynomial
|
|
315
|
+
agrees with the Schur polynomial::
|
|
316
|
+
|
|
317
|
+
sage: s = SymmetricFunctions(QQ).schur()
|
|
318
|
+
sage: k([1,2,3]).expand()
|
|
319
|
+
z_2^3*z_1^2*z_0 + z_2^3*z_1*z_0^2 + z_2^2*z_1^3*z_0
|
|
320
|
+
+ 2*z_2^2*z_1^2*z_0^2 + z_2^2*z_1*z_0^3 + z_2*z_1^3*z_0^2
|
|
321
|
+
+ z_2*z_1^2*z_0^3
|
|
322
|
+
sage: s[3,2,1].expand(3)
|
|
323
|
+
x0^3*x1^2*x2 + x0^2*x1^3*x2 + x0^3*x1*x2^2 + 2*x0^2*x1^2*x2^2
|
|
324
|
+
+ x0*x1^3*x2^2 + x0^2*x1*x2^3 + x0*x1^2*x2^3
|
|
325
|
+
|
|
326
|
+
The polynomial expansions can be computed using crystals and expressed in
|
|
327
|
+
terms of the key basis::
|
|
328
|
+
|
|
329
|
+
sage: T = crystals.Tableaux(['A',3],shape=[2,1])
|
|
330
|
+
sage: f = T.demazure_character([3,2,1]) # needs sage.symbolic
|
|
331
|
+
sage: k.from_polynomial(f) # needs sage.symbolic
|
|
332
|
+
k[1, 0, 0, 2]
|
|
333
|
+
|
|
334
|
+
The default behavior is to work in a polynomial ring with infinitely many
|
|
335
|
+
variables. One can work in a specicfied number of variables::
|
|
336
|
+
|
|
337
|
+
sage: k = KeyPolynomials(QQ, 4)
|
|
338
|
+
sage: k([3,0,1,2]).expand()
|
|
339
|
+
z_0^3*z_1^2*z_2 + z_0^3*z_1*z_2^2 + z_0^3*z_1^2*z_3
|
|
340
|
+
+ 2*z_0^3*z_1*z_2*z_3 + z_0^3*z_2^2*z_3 + z_0^3*z_1*z_3^2 + z_0^3*z_2*z_3^2
|
|
341
|
+
|
|
342
|
+
sage: k([0,0,2,0]).expand()
|
|
343
|
+
z_0^2 + z_0*z_1 + z_1^2 + z_0*z_2 + z_1*z_2 + z_2^2
|
|
344
|
+
|
|
345
|
+
sage: k([0,0,2,0]).expand().parent()
|
|
346
|
+
Multivariate Polynomial Ring in z_0, z_1, z_2, z_3 over Rational Field
|
|
347
|
+
|
|
348
|
+
If working in a specified number of variables, the length of the indexing
|
|
349
|
+
composition must be the same as the number of variables::
|
|
350
|
+
|
|
351
|
+
sage: k([0,0,2])
|
|
352
|
+
Traceback (most recent call last):
|
|
353
|
+
...
|
|
354
|
+
TypeError: do not know how to make x (= [0, 0, 2]) an element of self
|
|
355
|
+
(=Key polynomial basis over Rational Field)
|
|
356
|
+
|
|
357
|
+
One can also work in a specified polynomial ring::
|
|
358
|
+
|
|
359
|
+
sage: k = KeyPolynomials(QQ['x0', 'x1', 'x2', 'x3'])
|
|
360
|
+
sage: k([0,2,0,0])
|
|
361
|
+
k[0, 2, 0, 0]
|
|
362
|
+
sage: k([4,0,0,0]).expand()
|
|
363
|
+
x0^4
|
|
364
|
+
|
|
365
|
+
If one wishes to use a polynomial ring as coefficients for the key
|
|
366
|
+
polynomials, pass the keyword argument ``poly_coeffs=True``::
|
|
367
|
+
|
|
368
|
+
sage: k = KeyPolynomials(QQ['q'], poly_coeffs=True)
|
|
369
|
+
sage: R = k.base_ring(); R
|
|
370
|
+
Univariate Polynomial Ring in q over Rational Field
|
|
371
|
+
sage: R.inject_variables()
|
|
372
|
+
Defining q
|
|
373
|
+
sage: (q^2 + q + 1)*k([0,2,2,0,3,2])
|
|
374
|
+
(q^2+q+1)*k[0, 2, 2, 0, 3, 2]
|
|
375
|
+
"""
|
|
376
|
+
Element = KeyPolynomial
|
|
377
|
+
|
|
378
|
+
@staticmethod
|
|
379
|
+
def __classcall_private__(cls, R=None, k=None, poly_ring=None, poly_coeffs=False):
|
|
380
|
+
r"""
|
|
381
|
+
Normalize input.
|
|
382
|
+
|
|
383
|
+
EXAMPLES::
|
|
384
|
+
|
|
385
|
+
sage: KeyPolynomials(InfinitePolynomialRing(QQ, ['x', 'y']))
|
|
386
|
+
Traceback (most recent call last):
|
|
387
|
+
...
|
|
388
|
+
ValueError: polynomial ring has too many generators
|
|
389
|
+
|
|
390
|
+
sage: KeyPolynomials(QQ['t0','t1','t2','t3'])
|
|
391
|
+
Key polynomial basis over Rational Field
|
|
392
|
+
|
|
393
|
+
sage: KeyPolynomials(QQ['t'])
|
|
394
|
+
Key polynomial basis over Rational Field
|
|
395
|
+
|
|
396
|
+
sage: KeyPolynomials(InfinitePolynomialRing(QQ['t'], 'z'))
|
|
397
|
+
Key polynomial basis over Univariate Polynomial Ring in t over Rational Field
|
|
398
|
+
|
|
399
|
+
sage: KeyPolynomials(QQ)
|
|
400
|
+
Key polynomial basis over Rational Field
|
|
401
|
+
|
|
402
|
+
sage: KeyPolynomials(QQ, 3)
|
|
403
|
+
Key polynomial basis over Rational Field
|
|
404
|
+
"""
|
|
405
|
+
poly_type = (PolynomialRing_commutative,
|
|
406
|
+
MPolynomialRing_base,
|
|
407
|
+
InfinitePolynomialRing_sparse)
|
|
408
|
+
|
|
409
|
+
if isinstance(R, poly_type):
|
|
410
|
+
# if a polynomial ring is provided, we need to determine
|
|
411
|
+
# if it is meant to be self.polynomial_ring() or self.base_ring()
|
|
412
|
+
if isinstance(R, poly_type[0:2]):
|
|
413
|
+
k = R.ngens()
|
|
414
|
+
if isinstance(R, InfinitePolynomialRing_sparse) and R.ngens() > 1:
|
|
415
|
+
raise ValueError("polynomial ring has too many generators")
|
|
416
|
+
if isinstance(R.base_ring(), poly_type[0:2]):
|
|
417
|
+
# if R is of the form K[t_1, ..., t_n][z_*]
|
|
418
|
+
# or K[t_1, ..., t_n][z_1, ..., z_k]
|
|
419
|
+
return cls.__classcall__(cls, k=k, poly_ring=R)
|
|
420
|
+
if poly_coeffs:
|
|
421
|
+
# if R is a polynomial ring, but its base ring is not
|
|
422
|
+
# and poly_coeffs is true, then we should interpret
|
|
423
|
+
# R as the base ring
|
|
424
|
+
return cls.__classcall__(cls, R=R)
|
|
425
|
+
return cls.__classcall__(cls, k=k, poly_ring=R)
|
|
426
|
+
else:
|
|
427
|
+
# if R is not a polynomial ring, we know it is self.base_ring()
|
|
428
|
+
return cls.__classcall__(cls, R=R, k=k)
|
|
429
|
+
|
|
430
|
+
def __init__(self, R=None, k=None, poly_ring=None):
|
|
431
|
+
r"""
|
|
432
|
+
Initialize ``self``.
|
|
433
|
+
|
|
434
|
+
EXAMPLES::
|
|
435
|
+
|
|
436
|
+
sage: R = GF(3)['t'].fraction_field()
|
|
437
|
+
sage: k = KeyPolynomials(QQ)
|
|
438
|
+
sage: TestSuite(k).run()
|
|
439
|
+
sage: k = KeyPolynomials(R)
|
|
440
|
+
sage: TestSuite(k).run()
|
|
441
|
+
|
|
442
|
+
sage: k = KeyPolynomials(QQ, 4)
|
|
443
|
+
sage: TestSuite(k).run()
|
|
444
|
+
sage: k = KeyPolynomials(R, 4)
|
|
445
|
+
sage: TestSuite(k).run()
|
|
446
|
+
"""
|
|
447
|
+
self._k = k
|
|
448
|
+
|
|
449
|
+
if self._k is not None:
|
|
450
|
+
def build_index(m):
|
|
451
|
+
return self._indices(m)
|
|
452
|
+
else:
|
|
453
|
+
def build_index(m):
|
|
454
|
+
return self._indices(reversed(m)).trim()
|
|
455
|
+
|
|
456
|
+
self._build_index = build_index
|
|
457
|
+
|
|
458
|
+
if R is not None:
|
|
459
|
+
if poly_ring:
|
|
460
|
+
raise ValueError("specify only one of base_ring or poly_ring (not both)")
|
|
461
|
+
if k:
|
|
462
|
+
self._polynomial_ring = PolynomialRing(R, 'z_', k)
|
|
463
|
+
else:
|
|
464
|
+
self._polynomial_ring = InfinitePolynomialRing(R, 'z')
|
|
465
|
+
if poly_ring is not None:
|
|
466
|
+
if R is not None:
|
|
467
|
+
raise ValueError("specify only one of base_ring or poly_ring (not both)")
|
|
468
|
+
R = poly_ring.base_ring()
|
|
469
|
+
self._polynomial_ring = poly_ring
|
|
470
|
+
|
|
471
|
+
self._name = "Key polynomial basis"
|
|
472
|
+
|
|
473
|
+
CombinatorialFreeModule.__init__(self, R, IntegerVectors(k=k),
|
|
474
|
+
category=GradedAlgebrasWithBasis(R),
|
|
475
|
+
prefix='k', bracket=False)
|
|
476
|
+
|
|
477
|
+
def _coerce_map_from_(self, R):
|
|
478
|
+
r"""
|
|
479
|
+
Return the coercion map from ``R`` if it exists.
|
|
480
|
+
|
|
481
|
+
EXAMPLES::
|
|
482
|
+
|
|
483
|
+
sage: k = KeyPolynomials(QQ)
|
|
484
|
+
sage: m1 = k([3, 2, 4, 0]); m1
|
|
485
|
+
k[3, 2, 4]
|
|
486
|
+
sage: m2 = k(Composition([3, 2, 4])); m2
|
|
487
|
+
k[3, 2, 4]
|
|
488
|
+
sage: m1 == m2
|
|
489
|
+
True
|
|
490
|
+
|
|
491
|
+
sage: R = k.polynomial_ring()
|
|
492
|
+
sage: z = R.gen()
|
|
493
|
+
sage: z[0] * k([4, 3, 3, 2])
|
|
494
|
+
k[5, 3, 3, 2]
|
|
495
|
+
|
|
496
|
+
sage: X = SchubertPolynomialRing(QQ)
|
|
497
|
+
sage: k(X([4, 3, 2, 1]))
|
|
498
|
+
k[3, 2, 1]
|
|
499
|
+
"""
|
|
500
|
+
P = self._polynomial_ring
|
|
501
|
+
if R is P:
|
|
502
|
+
return self.from_polynomial
|
|
503
|
+
|
|
504
|
+
from sage.combinat.schubert_polynomial import SchubertPolynomialRing_xbasis
|
|
505
|
+
if isinstance(R, SchubertPolynomialRing_xbasis):
|
|
506
|
+
return self.from_schubert_polynomial
|
|
507
|
+
|
|
508
|
+
phi = P.coerce_map_from(R)
|
|
509
|
+
if phi is not None:
|
|
510
|
+
return self.coerce_map_from(P) * phi
|
|
511
|
+
return None
|
|
512
|
+
|
|
513
|
+
def _monomial(self, x):
|
|
514
|
+
r"""
|
|
515
|
+
EXAMPLES::
|
|
516
|
+
|
|
517
|
+
sage: k = KeyPolynomials(QQ)
|
|
518
|
+
sage: k([3, 2, 3, 4, 0])
|
|
519
|
+
k[3, 2, 3, 4]
|
|
520
|
+
sage: k = KeyPolynomials(QQ, 5)
|
|
521
|
+
sage: k([3, 2, 3, 4, 0])
|
|
522
|
+
k[3, 2, 3, 4, 0]
|
|
523
|
+
"""
|
|
524
|
+
if self._k:
|
|
525
|
+
return self._from_dict({x: self.base_ring().one()}, remove_zeros=False)
|
|
526
|
+
return self._from_dict({x.trim(): self.base_ring().one()}, remove_zeros=False)
|
|
527
|
+
|
|
528
|
+
def __getitem__(self, c):
|
|
529
|
+
"""
|
|
530
|
+
This method implements the abuses of notations ``k[2,1]``,
|
|
531
|
+
``k[[2,1]]``, etc.
|
|
532
|
+
|
|
533
|
+
INPUT:
|
|
534
|
+
|
|
535
|
+
- ``c`` -- anything that can represent an index of a basis element
|
|
536
|
+
|
|
537
|
+
EXAMPLES::
|
|
538
|
+
|
|
539
|
+
sage: k = KeyPolynomials(QQ)
|
|
540
|
+
sage: k[3]
|
|
541
|
+
k[3]
|
|
542
|
+
sage: k[3, 0, 2]
|
|
543
|
+
k[3, 0, 2]
|
|
544
|
+
sage: k[3, 1, 2, 0, 0]
|
|
545
|
+
k[3, 1, 2]
|
|
546
|
+
|
|
547
|
+
sage: k = KeyPolynomials(QQ, 4)
|
|
548
|
+
sage: k[3, 0, 1, 0]
|
|
549
|
+
k[3, 0, 1, 0]
|
|
550
|
+
sage: k[3]
|
|
551
|
+
Traceback (most recent call last):
|
|
552
|
+
...
|
|
553
|
+
ValueError: [3] doesn't satisfy correct constraints
|
|
554
|
+
"""
|
|
555
|
+
C = self._indices
|
|
556
|
+
if not isinstance(c, C.element_class):
|
|
557
|
+
if c in ZZ:
|
|
558
|
+
c = C([c])
|
|
559
|
+
else:
|
|
560
|
+
c = C(c)
|
|
561
|
+
return self._monomial(c)
|
|
562
|
+
|
|
563
|
+
@cached_method
|
|
564
|
+
def one_basis(self):
|
|
565
|
+
r"""
|
|
566
|
+
Return the basis element indexing the identity.
|
|
567
|
+
|
|
568
|
+
EXAMPLES::
|
|
569
|
+
|
|
570
|
+
sage: k = KeyPolynomials(QQ)
|
|
571
|
+
sage: k.one_basis()
|
|
572
|
+
[]
|
|
573
|
+
|
|
574
|
+
sage: k = KeyPolynomials(QQ, 4)
|
|
575
|
+
sage: k.one_basis()
|
|
576
|
+
[0, 0, 0, 0]
|
|
577
|
+
"""
|
|
578
|
+
if self._k:
|
|
579
|
+
return self._indices([0] * self._k)
|
|
580
|
+
return self._indices([])
|
|
581
|
+
|
|
582
|
+
def degree_on_basis(self, alpha):
|
|
583
|
+
"""
|
|
584
|
+
Return the degree of the basis element indexed by ``alpha``.
|
|
585
|
+
|
|
586
|
+
EXAMPLES::
|
|
587
|
+
|
|
588
|
+
sage: k = KeyPolynomials(QQ)
|
|
589
|
+
sage: k.degree_on_basis([2,1,0,2])
|
|
590
|
+
5
|
|
591
|
+
|
|
592
|
+
sage: k = KeyPolynomials(QQ, 5)
|
|
593
|
+
sage: k.degree_on_basis([2,1,0,2,0])
|
|
594
|
+
5
|
|
595
|
+
"""
|
|
596
|
+
return ZZ(sum(alpha))
|
|
597
|
+
|
|
598
|
+
def polynomial_ring(self):
|
|
599
|
+
r"""
|
|
600
|
+
Return the polynomial ring associated to ``self``.
|
|
601
|
+
|
|
602
|
+
EXAMPLES::
|
|
603
|
+
|
|
604
|
+
sage: k = KeyPolynomials(QQ)
|
|
605
|
+
sage: k.polynomial_ring()
|
|
606
|
+
Infinite polynomial ring in z over Rational Field
|
|
607
|
+
|
|
608
|
+
sage: k = KeyPolynomials(QQ, 4)
|
|
609
|
+
sage: k.polynomial_ring()
|
|
610
|
+
Multivariate Polynomial Ring in z_0, z_1, z_2, z_3 over Rational Field
|
|
611
|
+
"""
|
|
612
|
+
return self._polynomial_ring
|
|
613
|
+
|
|
614
|
+
def poly_gens(self):
|
|
615
|
+
r"""
|
|
616
|
+
Return the polynomial generators for the polynomial ring
|
|
617
|
+
associated to ``self``.
|
|
618
|
+
|
|
619
|
+
EXAMPLES::
|
|
620
|
+
|
|
621
|
+
sage: k = KeyPolynomials(QQ)
|
|
622
|
+
sage: k.poly_gens()
|
|
623
|
+
z_*
|
|
624
|
+
|
|
625
|
+
sage: k = KeyPolynomials(QQ, 4)
|
|
626
|
+
sage: k.poly_gens()
|
|
627
|
+
(z_0, z_1, z_2, z_3)
|
|
628
|
+
"""
|
|
629
|
+
if self._k:
|
|
630
|
+
return self._polynomial_ring.gens()
|
|
631
|
+
return self._polynomial_ring.gen()
|
|
632
|
+
|
|
633
|
+
def from_polynomial(self, f):
|
|
634
|
+
r"""
|
|
635
|
+
Expand a polynomial in terms of the key basis.
|
|
636
|
+
|
|
637
|
+
EXAMPLES::
|
|
638
|
+
|
|
639
|
+
sage: k = KeyPolynomials(QQ)
|
|
640
|
+
sage: z = k.poly_gens(); z
|
|
641
|
+
z_*
|
|
642
|
+
sage: p = z[0]^4*z[1]^2*z[2]*z[3] + z[0]^4*z[1]*z[2]^2*z[3]
|
|
643
|
+
sage: k.from_polynomial(p)
|
|
644
|
+
k[4, 1, 2, 1]
|
|
645
|
+
|
|
646
|
+
sage: all(k(c) == k.from_polynomial(k(c).expand()) for c in IntegerVectors(n=5, k=4))
|
|
647
|
+
True
|
|
648
|
+
|
|
649
|
+
sage: T = crystals.Tableaux(['A', 4], shape=[4,2,1,1])
|
|
650
|
+
sage: k.from_polynomial(T.demazure_character([2])) # needs sage.symbolic
|
|
651
|
+
k[4, 1, 2, 1]
|
|
652
|
+
"""
|
|
653
|
+
if f not in self._polynomial_ring:
|
|
654
|
+
try: # to accept elements of SymbolicRing
|
|
655
|
+
from sage.calculus.var import var
|
|
656
|
+
f = f.substitute([d == var(f'z_{i}')
|
|
657
|
+
for i, d in enumerate(f.variables())])
|
|
658
|
+
f = self._polynomial_ring(f)
|
|
659
|
+
except AttributeError:
|
|
660
|
+
raise ValueError(f"f must be an element of {self._polynomial_ring}")
|
|
661
|
+
|
|
662
|
+
out = self.zero()
|
|
663
|
+
|
|
664
|
+
while f:
|
|
665
|
+
M = f.monomials()[0]
|
|
666
|
+
c = f.monomial_coefficient(M)
|
|
667
|
+
|
|
668
|
+
new_term = self._from_dict({self._build_index(*M.exponents()): c})
|
|
669
|
+
|
|
670
|
+
f -= new_term.expand()
|
|
671
|
+
out += new_term
|
|
672
|
+
|
|
673
|
+
return out
|
|
674
|
+
|
|
675
|
+
def from_schubert_polynomial(self, x):
|
|
676
|
+
r"""
|
|
677
|
+
Expand a Schubert polynomial in the key basis.
|
|
678
|
+
|
|
679
|
+
EXAMPLES::
|
|
680
|
+
|
|
681
|
+
sage: k = KeyPolynomials(ZZ)
|
|
682
|
+
sage: X = SchubertPolynomialRing(ZZ)
|
|
683
|
+
sage: f = X([2,1,5,4,3])
|
|
684
|
+
sage: k.from_schubert_polynomial(f)
|
|
685
|
+
k[1, 0, 2, 1] + k[2, 0, 2] + k[3, 0, 0, 1]
|
|
686
|
+
sage: k.from_schubert_polynomial(2)
|
|
687
|
+
2*k[]
|
|
688
|
+
sage: k(f)
|
|
689
|
+
k[1, 0, 2, 1] + k[2, 0, 2] + k[3, 0, 0, 1]
|
|
690
|
+
|
|
691
|
+
sage: k = KeyPolynomials(GF(7), 4)
|
|
692
|
+
sage: k.from_schubert_polynomial(f)
|
|
693
|
+
k[1, 0, 2, 1] + k[2, 0, 2, 0] + k[3, 0, 0, 1]
|
|
694
|
+
|
|
695
|
+
TESTS::
|
|
696
|
+
|
|
697
|
+
sage: k = KeyPolynomials(ZZ)
|
|
698
|
+
sage: k.from_schubert_polynomial(k([3,2]))
|
|
699
|
+
Traceback (most recent call last):
|
|
700
|
+
...
|
|
701
|
+
ValueError: not a Schubert polynomial
|
|
702
|
+
|
|
703
|
+
sage: k = KeyPolynomials(ZZ)
|
|
704
|
+
sage: X = SchubertPolynomialRing(ZZ)
|
|
705
|
+
sage: it = iter(Compositions())
|
|
706
|
+
sage: for _ in range(50):
|
|
707
|
+
....: C = next(it)
|
|
708
|
+
....: assert k.from_schubert_polynomial(X(k[C])) == k[C], C
|
|
709
|
+
|
|
710
|
+
sage: k = KeyPolynomials(ZZ, 4)
|
|
711
|
+
sage: X = SchubertPolynomialRing(ZZ)
|
|
712
|
+
sage: it = iter(k.basis().keys())
|
|
713
|
+
sage: for _ in range(50):
|
|
714
|
+
....: C = next(it)
|
|
715
|
+
....: assert k.from_schubert_polynomial(X(k[C])) == k[C], C
|
|
716
|
+
"""
|
|
717
|
+
if x in self.base_ring():
|
|
718
|
+
return self(x)
|
|
719
|
+
|
|
720
|
+
from sage.combinat.schubert_polynomial import SchubertPolynomial_class
|
|
721
|
+
if not isinstance(x, SchubertPolynomial_class):
|
|
722
|
+
raise ValueError('not a Schubert polynomial')
|
|
723
|
+
|
|
724
|
+
from sage.combinat.diagram import RotheDiagram
|
|
725
|
+
out = self.zero()
|
|
726
|
+
if self._k is not None:
|
|
727
|
+
def build_elt(wt):
|
|
728
|
+
wt = list(wt)
|
|
729
|
+
wt += [0] * (self._k - len(wt))
|
|
730
|
+
return self[wt]
|
|
731
|
+
else:
|
|
732
|
+
def build_elt(wt):
|
|
733
|
+
return self[wt]
|
|
734
|
+
|
|
735
|
+
for m, c in x.monomial_coefficients().items():
|
|
736
|
+
D = RotheDiagram(m)
|
|
737
|
+
a = self.zero()
|
|
738
|
+
for d in D.peelable_tableaux():
|
|
739
|
+
a += build_elt(d.left_key_tableau().weight())
|
|
740
|
+
out += c * a
|
|
741
|
+
|
|
742
|
+
return out
|
|
743
|
+
|
|
744
|
+
|
|
745
|
+
def divided_difference(f, i):
|
|
746
|
+
r"""
|
|
747
|
+
Apply the ``i``-th divided difference operator to the polynomial ``f``.
|
|
748
|
+
|
|
749
|
+
EXAMPLES::
|
|
750
|
+
|
|
751
|
+
sage: from sage.combinat.key_polynomial import divided_difference
|
|
752
|
+
sage: k = KeyPolynomials(QQ)
|
|
753
|
+
sage: z = k.poly_gens()
|
|
754
|
+
sage: f = z[1]*z[2]^3 + z[1]*z[2]*z[3]
|
|
755
|
+
sage: divided_difference(f, 3)
|
|
756
|
+
z_3^2*z_1 + z_3*z_2*z_1 + z_2^2*z_1
|
|
757
|
+
|
|
758
|
+
sage: k = KeyPolynomials(QQ, 4)
|
|
759
|
+
sage: z = k.poly_gens()
|
|
760
|
+
sage: f = z[1]*z[2]^3 + z[1]*z[2]*z[3]
|
|
761
|
+
sage: divided_difference(f, 3)
|
|
762
|
+
z_1*z_2^2 + z_1*z_2*z_3 + z_1*z_3^2
|
|
763
|
+
|
|
764
|
+
sage: k = KeyPolynomials(QQ)
|
|
765
|
+
sage: R = k.polynomial_ring(); R
|
|
766
|
+
Infinite polynomial ring in z over Rational Field
|
|
767
|
+
sage: z = R.gen()
|
|
768
|
+
sage: divided_difference(z[1]*z[2]^3, 2)
|
|
769
|
+
-z_2^2*z_1 - z_2*z_1^2
|
|
770
|
+
sage: divided_difference(z[1]*z[2]*z[3], 3)
|
|
771
|
+
0
|
|
772
|
+
sage: divided_difference(z[1]*z[2]*z[3], 4)
|
|
773
|
+
z_2*z_1
|
|
774
|
+
sage: divided_difference(z[1]*z[2]*z[4], 4)
|
|
775
|
+
-z_2*z_1
|
|
776
|
+
|
|
777
|
+
sage: k = KeyPolynomials(QQ, 5)
|
|
778
|
+
sage: z = k.polynomial_ring().gens()
|
|
779
|
+
sage: divided_difference(z[1]*z[2]^3, 2)
|
|
780
|
+
-z_1^2*z_2 - z_1*z_2^2
|
|
781
|
+
sage: divided_difference(z[1]*z[2]*z[3], 3)
|
|
782
|
+
0
|
|
783
|
+
sage: divided_difference(z[1]*z[2]*z[3], 4)
|
|
784
|
+
z_1*z_2
|
|
785
|
+
sage: divided_difference(z[1]*z[2]*z[4], 4)
|
|
786
|
+
-z_1*z_2
|
|
787
|
+
"""
|
|
788
|
+
P = parent(f)
|
|
789
|
+
if isinstance(P, InfinitePolynomialRing_sparse):
|
|
790
|
+
z = P.gen()
|
|
791
|
+
else:
|
|
792
|
+
z = P.gens()
|
|
793
|
+
|
|
794
|
+
si_f = f.subs({z[i]: z[i-1], z[i-1]: z[i]})
|
|
795
|
+
return (si_f - f) // (z[i] - z[i-1])
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
def isobaric_divided_difference(f, w):
|
|
799
|
+
r"""
|
|
800
|
+
Apply the isobaric divided difference operator `\pi_w` to the
|
|
801
|
+
polynomial `f`.
|
|
802
|
+
|
|
803
|
+
``w`` may be either a single index or a list of
|
|
804
|
+
indices of simple transpositions.
|
|
805
|
+
|
|
806
|
+
.. WARNING::
|
|
807
|
+
|
|
808
|
+
The simple transpositions should be applied from left to right.
|
|
809
|
+
|
|
810
|
+
EXAMPLES::
|
|
811
|
+
|
|
812
|
+
sage: from sage.combinat.key_polynomial import isobaric_divided_difference as idd
|
|
813
|
+
sage: R.<z> = InfinitePolynomialRing(GF(3))
|
|
814
|
+
sage: idd(z[1]^4*z[2]^2*z[4], 4)
|
|
815
|
+
0
|
|
816
|
+
|
|
817
|
+
sage: idd(z[1]^4*z[2]^2*z[3]*z[4], 3)
|
|
818
|
+
z_4*z_3^2*z_2*z_1^4 + z_4*z_3*z_2^2*z_1^4
|
|
819
|
+
|
|
820
|
+
sage: idd(z[1]^4*z[2]^2*z[3]*z[4], [3, 4])
|
|
821
|
+
z_4^2*z_3*z_2*z_1^4 + z_4*z_3^2*z_2*z_1^4 + z_4*z_3*z_2^2*z_1^4
|
|
822
|
+
|
|
823
|
+
sage: idd(z[1]^4*z[2]^2*z[3]*z[4], [4, 3])
|
|
824
|
+
z_4*z_3^2*z_2*z_1^4 + z_4*z_3*z_2^2*z_1^4
|
|
825
|
+
|
|
826
|
+
sage: idd(z[1]^2*z[2], [3, 2])
|
|
827
|
+
z_3*z_2^2 + z_3*z_2*z_1 + z_3*z_1^2 + z_2^2*z_1 + z_2*z_1^2
|
|
828
|
+
"""
|
|
829
|
+
P = parent(f)
|
|
830
|
+
if isinstance(P, InfinitePolynomialRing_sparse):
|
|
831
|
+
z = P.gen()
|
|
832
|
+
else:
|
|
833
|
+
z = P.gens()
|
|
834
|
+
|
|
835
|
+
if not hasattr(w, "__iter__"): # this allows us to pass i instead of a word
|
|
836
|
+
w = [w]
|
|
837
|
+
for i in w:
|
|
838
|
+
fp = z[i-1] * f
|
|
839
|
+
si_fp = fp.subs({z[i]: z[i-1], z[i-1]: z[i]})
|
|
840
|
+
f = (si_fp - fp) // (z[i] - z[i-1])
|
|
841
|
+
return f
|
|
842
|
+
|
|
843
|
+
|
|
844
|
+
def sorting_word(alpha):
|
|
845
|
+
r"""
|
|
846
|
+
Get a reduced word for the permutation which sorts ``alpha``
|
|
847
|
+
into a partition.
|
|
848
|
+
|
|
849
|
+
The result is a list ``l = [i0, i1, i2, ...]`` where each ``ij``
|
|
850
|
+
is a positive integer such that it applies the simple
|
|
851
|
+
transposition `(i_j, i_j+1)`. The transpositions are applied
|
|
852
|
+
starting with ``i0``, then ``i1`` is applied, followed by ``i2``,
|
|
853
|
+
and so on. See :meth:`sage.combinat.permutation.Permutation.reduced_words`
|
|
854
|
+
for the convention used.
|
|
855
|
+
|
|
856
|
+
EXAMPLES::
|
|
857
|
+
|
|
858
|
+
sage: IV = IntegerVectors()
|
|
859
|
+
sage: from sage.combinat.key_polynomial import sorting_word
|
|
860
|
+
sage: list(sorting_word(IV([2,3,2]))[0])
|
|
861
|
+
[1]
|
|
862
|
+
sage: sorting_word(IV([2,3,2]))[1]
|
|
863
|
+
[3, 2, 2]
|
|
864
|
+
sage: list(sorting_word(IV([5,6,7]))[0])
|
|
865
|
+
[1, 2, 1]
|
|
866
|
+
sage: list(sorting_word(IV([0,3,2]))[0])
|
|
867
|
+
[2, 1]
|
|
868
|
+
sage: list(sorting_word(IV([0,3,0,2]))[0])
|
|
869
|
+
[2, 3, 1]
|
|
870
|
+
sage: list(sorting_word(IV([3,2,1]))[0])
|
|
871
|
+
[]
|
|
872
|
+
sage: list(sorting_word(IV([2,3,3]))[0])
|
|
873
|
+
[2, 1]
|
|
874
|
+
"""
|
|
875
|
+
w = []
|
|
876
|
+
L = list(alpha)
|
|
877
|
+
n = len(L)
|
|
878
|
+
|
|
879
|
+
# bubble sort to get the shortest sorting word
|
|
880
|
+
for i in range(n-1):
|
|
881
|
+
for j in range(n-i-1):
|
|
882
|
+
if L[j] < L[j + 1]:
|
|
883
|
+
w.append(j+1)
|
|
884
|
+
L[j], L[j + 1] = L[j + 1], L[j]
|
|
885
|
+
return reversed(w), L
|