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,847 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
r"""
|
|
3
|
+
Fast word datatype using an array of unsigned char
|
|
4
|
+
"""
|
|
5
|
+
# ****************************************************************************
|
|
6
|
+
# Copyright (C) 2014 Vincent Delecroix <20100.delecroix@gmail.com>
|
|
7
|
+
#
|
|
8
|
+
# This program is free software: you can redistribute it and/or modify
|
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
|
10
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
11
|
+
# (at your option) any later version.
|
|
12
|
+
# https://www.gnu.org/licenses/
|
|
13
|
+
# ****************************************************************************
|
|
14
|
+
|
|
15
|
+
from cysignals.memory cimport check_allocarray, sig_free
|
|
16
|
+
from cysignals.signals cimport sig_on, sig_off
|
|
17
|
+
from sage.data_structures.bitset_base cimport *
|
|
18
|
+
|
|
19
|
+
cimport cython
|
|
20
|
+
from cpython.object cimport Py_EQ, Py_NE
|
|
21
|
+
from sage.rings.integer cimport smallInteger
|
|
22
|
+
from sage.rings.rational cimport Rational
|
|
23
|
+
from libc.string cimport memcpy, memcmp
|
|
24
|
+
from sage.combinat.words.word_datatypes cimport WordDatatype
|
|
25
|
+
from sage.structure.richcmp cimport rich_to_bool_sgn
|
|
26
|
+
|
|
27
|
+
from cpython.number cimport PyIndex_Check, PyNumber_Check
|
|
28
|
+
from cpython.sequence cimport PySequence_Check
|
|
29
|
+
from cpython.slice cimport PySlice_GetIndicesEx
|
|
30
|
+
|
|
31
|
+
import itertools
|
|
32
|
+
|
|
33
|
+
# the maximum value of a size_t
|
|
34
|
+
cdef size_t SIZE_T_MAX = -(<size_t> 1)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def reversed_word_iterator(WordDatatype_char w):
|
|
38
|
+
r"""
|
|
39
|
+
This function exists only because it is not possible to use yield in the
|
|
40
|
+
special method ``__reversed__``.
|
|
41
|
+
|
|
42
|
+
EXAMPLES::
|
|
43
|
+
|
|
44
|
+
sage: W = Words([0,1,2])
|
|
45
|
+
sage: w = W([0,1,0,0,1,2])
|
|
46
|
+
sage: list(reversed(w)) # indirect doctest
|
|
47
|
+
[2, 1, 0, 0, 1, 0]
|
|
48
|
+
"""
|
|
49
|
+
cdef ssize_t i
|
|
50
|
+
for i in range(w._length-1, -1, -1):
|
|
51
|
+
yield w._data[i]
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
cdef class WordDatatype_char(WordDatatype):
|
|
55
|
+
r"""
|
|
56
|
+
A Fast class for words represented by an array ``unsigned char *``.
|
|
57
|
+
|
|
58
|
+
Currently, only handles letters in [0,255].
|
|
59
|
+
"""
|
|
60
|
+
cdef unsigned char * _data
|
|
61
|
+
cdef size_t _length
|
|
62
|
+
|
|
63
|
+
# _master is a just a reference to another Python object in case the finite
|
|
64
|
+
# word is just a slice of another one. But because Cython takes care of
|
|
65
|
+
# Python attributes *before* the call to __dealloc__ we need to duplicate
|
|
66
|
+
# the information.
|
|
67
|
+
cdef WordDatatype_char _master
|
|
68
|
+
cdef int _is_slice
|
|
69
|
+
|
|
70
|
+
def __cinit__(self):
|
|
71
|
+
r"""
|
|
72
|
+
Initialization of C attributes.
|
|
73
|
+
|
|
74
|
+
TESTS::
|
|
75
|
+
|
|
76
|
+
sage: Words([0,1])([])
|
|
77
|
+
word:
|
|
78
|
+
"""
|
|
79
|
+
self._data = NULL
|
|
80
|
+
self._length = 0
|
|
81
|
+
self._is_slice = 0
|
|
82
|
+
|
|
83
|
+
def __init__(self, parent, data):
|
|
84
|
+
r"""
|
|
85
|
+
Constructor.
|
|
86
|
+
|
|
87
|
+
TESTS::
|
|
88
|
+
|
|
89
|
+
sage: W = Words([0,1,2,3])
|
|
90
|
+
sage: W([0,1,2,3])
|
|
91
|
+
word: 0123
|
|
92
|
+
sage: W(iter([0,1,2,3]))
|
|
93
|
+
word: 0123
|
|
94
|
+
"""
|
|
95
|
+
self._parent = parent
|
|
96
|
+
|
|
97
|
+
if not PySequence_Check(data):
|
|
98
|
+
data = list(data)
|
|
99
|
+
if data:
|
|
100
|
+
self._set_data(data)
|
|
101
|
+
|
|
102
|
+
@cython.boundscheck(False) # assume that indexing will not cause any IndexErrors
|
|
103
|
+
@cython.wraparound(False) # not check not correctly handle negative indices
|
|
104
|
+
cdef _set_data(self, data):
|
|
105
|
+
r"""
|
|
106
|
+
Set the attribute ._data and ._length from the sequence data
|
|
107
|
+
(usually data is a word, a tuple or a list)
|
|
108
|
+
"""
|
|
109
|
+
cdef size_t i
|
|
110
|
+
self._length = len(data)
|
|
111
|
+
self._data = <unsigned char *>check_allocarray(self._length, sizeof(unsigned char))
|
|
112
|
+
|
|
113
|
+
for i in range(self._length):
|
|
114
|
+
self._data[i] = data[i]
|
|
115
|
+
|
|
116
|
+
def __dealloc__(self):
|
|
117
|
+
r"""
|
|
118
|
+
Deallocate memory only if ``self`` uses it own memory.
|
|
119
|
+
|
|
120
|
+
Note that ``sig_free`` will not deallocate memory if ``self`` is the
|
|
121
|
+
master of another word.
|
|
122
|
+
"""
|
|
123
|
+
# it is strictly forbidden here to access _master here! (it will be set
|
|
124
|
+
# to None most of the time)
|
|
125
|
+
if self._is_slice == 0:
|
|
126
|
+
sig_free(self._data)
|
|
127
|
+
|
|
128
|
+
def __bool__(self):
|
|
129
|
+
r"""
|
|
130
|
+
Test whether the word is not empty.
|
|
131
|
+
|
|
132
|
+
EXAMPLES::
|
|
133
|
+
|
|
134
|
+
sage: W = Words([0,3,5])
|
|
135
|
+
sage: bool(W([0,3,3,5]))
|
|
136
|
+
True
|
|
137
|
+
sage: bool(W([]))
|
|
138
|
+
False
|
|
139
|
+
"""
|
|
140
|
+
return self._length != 0
|
|
141
|
+
|
|
142
|
+
def is_empty(self):
|
|
143
|
+
r"""
|
|
144
|
+
Return whether the word is empty.
|
|
145
|
+
|
|
146
|
+
EXAMPLES::
|
|
147
|
+
|
|
148
|
+
sage: W = Words([0,1,2])
|
|
149
|
+
sage: W([0,1,2,2]).is_empty()
|
|
150
|
+
False
|
|
151
|
+
sage: W([]).is_empty()
|
|
152
|
+
True
|
|
153
|
+
"""
|
|
154
|
+
return not self
|
|
155
|
+
|
|
156
|
+
def __len__(self):
|
|
157
|
+
r"""
|
|
158
|
+
Return the length of the word as a Python integer.
|
|
159
|
+
|
|
160
|
+
TESTS::
|
|
161
|
+
|
|
162
|
+
sage: W = Words([0,1,2,3])
|
|
163
|
+
sage: w = W([0,1,2,0,3,2,1])
|
|
164
|
+
sage: len(w)
|
|
165
|
+
7
|
|
166
|
+
sage: type(len(w))
|
|
167
|
+
<class 'int'>
|
|
168
|
+
"""
|
|
169
|
+
return self._length
|
|
170
|
+
|
|
171
|
+
def length(self):
|
|
172
|
+
r"""
|
|
173
|
+
Return the length of the word as a Sage integer.
|
|
174
|
+
|
|
175
|
+
EXAMPLES::
|
|
176
|
+
|
|
177
|
+
sage: W = Words([0,1,2,3,4])
|
|
178
|
+
sage: w = W([0,1,2,0,3,2,1])
|
|
179
|
+
sage: w.length()
|
|
180
|
+
7
|
|
181
|
+
sage: type(w.length())
|
|
182
|
+
<class 'sage.rings.integer.Integer'>
|
|
183
|
+
sage: type(len(w))
|
|
184
|
+
<class 'int'>
|
|
185
|
+
"""
|
|
186
|
+
return smallInteger(self._length)
|
|
187
|
+
|
|
188
|
+
def letters(self):
|
|
189
|
+
r"""
|
|
190
|
+
Return the list of letters that appear in this word, listed in the
|
|
191
|
+
order of first appearance.
|
|
192
|
+
|
|
193
|
+
EXAMPLES::
|
|
194
|
+
|
|
195
|
+
sage: W = Words(5)
|
|
196
|
+
sage: W([1,3,1,2,2,3,1]).letters()
|
|
197
|
+
[1, 3, 2]
|
|
198
|
+
"""
|
|
199
|
+
cdef bitset_t seen
|
|
200
|
+
bitset_init(seen, 256) # allocation + initialization to 0
|
|
201
|
+
|
|
202
|
+
cdef size_t i
|
|
203
|
+
cdef list res = []
|
|
204
|
+
cdef unsigned char letter
|
|
205
|
+
for i in range(self._length):
|
|
206
|
+
letter = self._data[i]
|
|
207
|
+
if not bitset_in(seen, letter):
|
|
208
|
+
bitset_add(seen, letter)
|
|
209
|
+
res.append(letter)
|
|
210
|
+
bitset_free(seen)
|
|
211
|
+
return res
|
|
212
|
+
|
|
213
|
+
cdef _new_c(self, unsigned char * data, size_t length, WordDatatype_char master):
|
|
214
|
+
r"""
|
|
215
|
+
TO DISCUSS: in Integer (sage.rings.integer) this method is actually an
|
|
216
|
+
external function. But we might want to have several possible inheritance.
|
|
217
|
+
"""
|
|
218
|
+
cdef type t = type(self)
|
|
219
|
+
cdef WordDatatype_char other = t.__new__(t)
|
|
220
|
+
other._data = data
|
|
221
|
+
other._master = master # can be None
|
|
222
|
+
other._is_slice = 0 if master is None else 1
|
|
223
|
+
other._length = length
|
|
224
|
+
other._parent = self._parent
|
|
225
|
+
|
|
226
|
+
return other
|
|
227
|
+
|
|
228
|
+
def __hash__(self):
|
|
229
|
+
r"""
|
|
230
|
+
Return the hash value.
|
|
231
|
+
|
|
232
|
+
EXAMPLES::
|
|
233
|
+
|
|
234
|
+
sage: W = Words([0,1,2])
|
|
235
|
+
sage: W([0,1,0,1,0,0,0], datatype='list').__hash__()
|
|
236
|
+
102060647
|
|
237
|
+
sage: W([0,1,0,1,0,0,0], datatype='char').__hash__()
|
|
238
|
+
102060647
|
|
239
|
+
"""
|
|
240
|
+
cdef int res = 5381
|
|
241
|
+
cdef size_t i
|
|
242
|
+
if self._hash is None:
|
|
243
|
+
for i in range(min(<size_t>1024, self._length)):
|
|
244
|
+
res = ((res << 5) + res) + self._data[i]
|
|
245
|
+
self._hash = res
|
|
246
|
+
return self._hash
|
|
247
|
+
|
|
248
|
+
def __richcmp__(self, other, int op):
|
|
249
|
+
r"""
|
|
250
|
+
INPUT:
|
|
251
|
+
|
|
252
|
+
- ``other`` -- a word (WordDatatype_char)
|
|
253
|
+
|
|
254
|
+
- ``op`` -- integer from 0 to 5
|
|
255
|
+
|
|
256
|
+
TESTS::
|
|
257
|
+
|
|
258
|
+
sage: W = Words(range(100))
|
|
259
|
+
sage: w = W(list(range(10)) * 2)
|
|
260
|
+
sage: w == w
|
|
261
|
+
True
|
|
262
|
+
sage: w != w
|
|
263
|
+
False
|
|
264
|
+
sage: w[:-1] != w[1:]
|
|
265
|
+
True
|
|
266
|
+
sage: w < w[1:] and w[1:] > w
|
|
267
|
+
True
|
|
268
|
+
sage: w > w[1:] or w[1:] < w
|
|
269
|
+
False
|
|
270
|
+
|
|
271
|
+
Testing that :issue:`21609` is fixed::
|
|
272
|
+
|
|
273
|
+
sage: w = Word([1,2], alphabet=[1,2])
|
|
274
|
+
sage: z = Word([1,1], alphabet=[1,2])
|
|
275
|
+
sage: (w<w, z<z, w<z, z<w)
|
|
276
|
+
(False, False, False, True)
|
|
277
|
+
sage: (w<=w, z<=z, w<=z, z<=w)
|
|
278
|
+
(True, True, False, True)
|
|
279
|
+
sage: (w==w, z==z, w==z, z==w)
|
|
280
|
+
(True, True, False, False)
|
|
281
|
+
sage: (w!=w, z!=z, w!=z, z!=w)
|
|
282
|
+
(False, False, True, True)
|
|
283
|
+
sage: (w>w, z>z, w>z, z>w)
|
|
284
|
+
(False, False, True, False)
|
|
285
|
+
sage: (w>=w, z>=z, w>=z, z>=w)
|
|
286
|
+
(True, True, True, False)
|
|
287
|
+
|
|
288
|
+
Testing that :issue:`22717` is fixed::
|
|
289
|
+
|
|
290
|
+
sage: w = Word([1,2], alphabet=[1,2,3])
|
|
291
|
+
sage: z = Word([1,2,3], alphabet=[1,2,3])
|
|
292
|
+
sage: (w<w, z<z, w<z, z<w)
|
|
293
|
+
(False, False, True, False)
|
|
294
|
+
sage: (w<=w, z<=z, w<=z, z<=w)
|
|
295
|
+
(True, True, True, False)
|
|
296
|
+
sage: (w==w, z==z, w==z, z==w)
|
|
297
|
+
(True, True, False, False)
|
|
298
|
+
sage: (w!=w, z!=z, w!=z, z!=w)
|
|
299
|
+
(False, False, True, True)
|
|
300
|
+
sage: (w>w, z>z, w>z, z>w)
|
|
301
|
+
(False, False, False, True)
|
|
302
|
+
sage: (w>=w, z>=z, w>=z, z>=w)
|
|
303
|
+
(True, True, False, True)
|
|
304
|
+
|
|
305
|
+
Check that :issue:`23317` is fixed::
|
|
306
|
+
|
|
307
|
+
sage: L = [Word([2,2], (1,2)), Word([], (1,2))]
|
|
308
|
+
sage: sorted(L)
|
|
309
|
+
[word: , word: 22]
|
|
310
|
+
"""
|
|
311
|
+
if not isinstance(other, WordDatatype_char):
|
|
312
|
+
return NotImplemented
|
|
313
|
+
|
|
314
|
+
cdef WordDatatype_char a = <WordDatatype_char>self
|
|
315
|
+
cdef WordDatatype_char b = <WordDatatype_char>other
|
|
316
|
+
|
|
317
|
+
# Words of different lengths are not equal!
|
|
318
|
+
if (op == Py_EQ or op == Py_NE) and a._length != b._length:
|
|
319
|
+
return op == Py_NE
|
|
320
|
+
|
|
321
|
+
# Compare overlapping chars
|
|
322
|
+
cdef size_t l = min(a._length, b._length)
|
|
323
|
+
sig_on()
|
|
324
|
+
cdef int test = memcmp(a._data, b._data, l)
|
|
325
|
+
sig_off()
|
|
326
|
+
|
|
327
|
+
if test == 0:
|
|
328
|
+
# Equality: compare lengths
|
|
329
|
+
test = a._length - b._length
|
|
330
|
+
return rich_to_bool_sgn(op, test)
|
|
331
|
+
|
|
332
|
+
def __getitem__(self, key):
|
|
333
|
+
r"""
|
|
334
|
+
INPUT:
|
|
335
|
+
|
|
336
|
+
- ``key`` -- index
|
|
337
|
+
|
|
338
|
+
TESTS::
|
|
339
|
+
|
|
340
|
+
sage: W = Words([0,1,2,3])
|
|
341
|
+
sage: w = W([0,1,0,2,0,3,1,2,3])
|
|
342
|
+
sage: w[0]
|
|
343
|
+
0
|
|
344
|
+
sage: w[2]
|
|
345
|
+
0
|
|
346
|
+
sage: w[1:]
|
|
347
|
+
word: 10203123
|
|
348
|
+
sage: w[5::-2]
|
|
349
|
+
word: 321
|
|
350
|
+
|
|
351
|
+
sage: w = W([randint(0,3) for _ in range(20)])
|
|
352
|
+
sage: list(w) == [w[i] for i in range(len(w))]
|
|
353
|
+
True
|
|
354
|
+
|
|
355
|
+
sage: w['foo':'bar']
|
|
356
|
+
Traceback (most recent call last):
|
|
357
|
+
...
|
|
358
|
+
TypeError: slice indices must be integers or None or have an __index__ method
|
|
359
|
+
|
|
360
|
+
Check a weird behavior of PySlice_GetIndicesEx (:issue:`17056`)::
|
|
361
|
+
|
|
362
|
+
sage: w[1:0]
|
|
363
|
+
word:
|
|
364
|
+
"""
|
|
365
|
+
cdef Py_ssize_t i, start, stop, step, slicelength
|
|
366
|
+
cdef unsigned char * data
|
|
367
|
+
cdef size_t j, k
|
|
368
|
+
if isinstance(key, slice):
|
|
369
|
+
# here the key is a slice
|
|
370
|
+
PySlice_GetIndicesEx(key,
|
|
371
|
+
self._length,
|
|
372
|
+
&start, &stop, &step,
|
|
373
|
+
&slicelength)
|
|
374
|
+
if slicelength == 0:
|
|
375
|
+
return self._new_c(NULL, 0, None)
|
|
376
|
+
if step == 1:
|
|
377
|
+
return self._new_c(self._data+start, stop-start, self)
|
|
378
|
+
data = <unsigned char *>check_allocarray(slicelength, sizeof(unsigned char))
|
|
379
|
+
j = 0
|
|
380
|
+
for k in range(start, stop, step):
|
|
381
|
+
data[j] = self._data[k]
|
|
382
|
+
j += 1
|
|
383
|
+
return self._new_c(data, slicelength, None)
|
|
384
|
+
|
|
385
|
+
elif PyIndex_Check(key):
|
|
386
|
+
# here the key is an int
|
|
387
|
+
i = key # cast key into a size_t
|
|
388
|
+
if i < 0:
|
|
389
|
+
i += self._length
|
|
390
|
+
if i < 0 or <size_t>i >= self._length:
|
|
391
|
+
raise IndexError("word index out of range")
|
|
392
|
+
return self._data[i]
|
|
393
|
+
|
|
394
|
+
raise TypeError("word indices must be integers")
|
|
395
|
+
|
|
396
|
+
def __iter__(self):
|
|
397
|
+
r"""
|
|
398
|
+
Iterator over the letters of ``self``.
|
|
399
|
+
|
|
400
|
+
EXAMPLES::
|
|
401
|
+
|
|
402
|
+
sage: W = Words([0,1,2,3])
|
|
403
|
+
sage: list(W([0,0,1,0])) # indirect doctest
|
|
404
|
+
[0, 0, 1, 0]
|
|
405
|
+
"""
|
|
406
|
+
cdef size_t i
|
|
407
|
+
for i in range(self._length):
|
|
408
|
+
yield self._data[i]
|
|
409
|
+
|
|
410
|
+
def __reversed__(self):
|
|
411
|
+
r"""
|
|
412
|
+
Reversed iterator over the letters of ``self``.
|
|
413
|
+
|
|
414
|
+
EXAMPLES::
|
|
415
|
+
|
|
416
|
+
sage: W = Words([0,1,2,3])
|
|
417
|
+
sage: list(reversed(W([0,0,1,0]))) # indirect doctest
|
|
418
|
+
[0, 1, 0, 0]
|
|
419
|
+
|
|
420
|
+
TESTS::
|
|
421
|
+
|
|
422
|
+
sage: list(reversed(W([])))
|
|
423
|
+
[]
|
|
424
|
+
sage: list(reversed(W([1])))
|
|
425
|
+
[1]
|
|
426
|
+
"""
|
|
427
|
+
return reversed_word_iterator(self)
|
|
428
|
+
|
|
429
|
+
cdef _concatenate(self, WordDatatype_char other):
|
|
430
|
+
cdef unsigned char * data
|
|
431
|
+
data = <unsigned char *>check_allocarray(self._length + other._length, sizeof(unsigned char))
|
|
432
|
+
|
|
433
|
+
sig_on()
|
|
434
|
+
memcpy(data, self._data, self._length * sizeof(unsigned char))
|
|
435
|
+
memcpy(data+self._length, other._data, other._length * sizeof(unsigned char))
|
|
436
|
+
sig_off()
|
|
437
|
+
|
|
438
|
+
return self._new_c(data, self._length + other._length, None)
|
|
439
|
+
|
|
440
|
+
def __mul__(self, other):
|
|
441
|
+
r"""
|
|
442
|
+
Concatenation of ``self`` and ``other``.
|
|
443
|
+
|
|
444
|
+
TESTS:
|
|
445
|
+
|
|
446
|
+
sage: W = Words(IntegerRange(0,255))
|
|
447
|
+
sage: W([0,1]) * W([2,0])
|
|
448
|
+
word: 0120
|
|
449
|
+
|
|
450
|
+
The result is automatically converted to a WordDatatype_char. Currently we can
|
|
451
|
+
even do::
|
|
452
|
+
|
|
453
|
+
sage: w = W([0,1,2,3])
|
|
454
|
+
sage: w * [4,0,4,0]
|
|
455
|
+
word: 01234040
|
|
456
|
+
"""
|
|
457
|
+
cdef WordDatatype_char w
|
|
458
|
+
|
|
459
|
+
if isinstance(other, WordDatatype_char):
|
|
460
|
+
return (<WordDatatype_char> self)._concatenate(other)
|
|
461
|
+
|
|
462
|
+
elif PySequence_Check(other):
|
|
463
|
+
# we convert other to a WordDatatype_char and perform the concatenation
|
|
464
|
+
w = (<WordDatatype_char> self)._new_c(NULL, 0, None)
|
|
465
|
+
w._set_data(other)
|
|
466
|
+
return (<WordDatatype_char> self)._concatenate(w)
|
|
467
|
+
|
|
468
|
+
else:
|
|
469
|
+
from sage.combinat.words.finite_word import FiniteWord_class
|
|
470
|
+
return FiniteWord_class.concatenate(self, other)
|
|
471
|
+
|
|
472
|
+
def __add__(self, other):
|
|
473
|
+
r"""
|
|
474
|
+
Concatenation (alias for ``*``).
|
|
475
|
+
|
|
476
|
+
TESTS::
|
|
477
|
+
|
|
478
|
+
sage: W = Words([0,1,2])
|
|
479
|
+
sage: type(W([0]) + W([1])) is W.finite_words()._element_classes['char']
|
|
480
|
+
True
|
|
481
|
+
"""
|
|
482
|
+
return self * other
|
|
483
|
+
|
|
484
|
+
def concatenate(self, other):
|
|
485
|
+
r"""
|
|
486
|
+
Concatenation of ``self`` and ``other``.
|
|
487
|
+
|
|
488
|
+
EXAMPLES::
|
|
489
|
+
|
|
490
|
+
sage: W = Words([0,1,2])
|
|
491
|
+
sage: W([0,2,1]).concatenate([0,0,0])
|
|
492
|
+
word: 021000
|
|
493
|
+
|
|
494
|
+
TESTS::
|
|
495
|
+
|
|
496
|
+
sage: W = Words([0,1,2])
|
|
497
|
+
sage: w = W([0,2,1]).concatenate(W([0,0,0]))
|
|
498
|
+
sage: type(w) is W.finite_words()._element_classes['char']
|
|
499
|
+
True
|
|
500
|
+
"""
|
|
501
|
+
return self * other
|
|
502
|
+
|
|
503
|
+
def __pow__(self, exp, mod):
|
|
504
|
+
r"""
|
|
505
|
+
Power.
|
|
506
|
+
|
|
507
|
+
INPUT:
|
|
508
|
+
|
|
509
|
+
- ``exp`` -- integer, rational, float, or plus infinity
|
|
510
|
+
|
|
511
|
+
TESTS::
|
|
512
|
+
|
|
513
|
+
sage: W = Words(range(20))
|
|
514
|
+
sage: w = W([0,1,2,3])
|
|
515
|
+
sage: w
|
|
516
|
+
word: 0123
|
|
517
|
+
sage: w ** (1/2)
|
|
518
|
+
word: 01
|
|
519
|
+
sage: w ** 2
|
|
520
|
+
word: 01230123
|
|
521
|
+
sage: w ** 3
|
|
522
|
+
word: 012301230123
|
|
523
|
+
sage: w ** (7/2)
|
|
524
|
+
word: 01230123012301
|
|
525
|
+
sage: len(((w ** 2) ** 3) ** 5) == len(w) * 2 * 3 * 5
|
|
526
|
+
True
|
|
527
|
+
|
|
528
|
+
Infinite exponents::
|
|
529
|
+
|
|
530
|
+
sage: W([0,1]) ** Infinity
|
|
531
|
+
word: 0101010101010101010101010101010101010101...
|
|
532
|
+
"""
|
|
533
|
+
if not PyNumber_Check(exp):
|
|
534
|
+
raise ValueError("the exponent must be a number or infinity")
|
|
535
|
+
if mod is not None:
|
|
536
|
+
raise ValueError("a word cannot be taken modulo")
|
|
537
|
+
|
|
538
|
+
if exp == float('inf'):
|
|
539
|
+
|
|
540
|
+
def fcn(n):
|
|
541
|
+
return self[n % self.length()]
|
|
542
|
+
return self._parent.shift()(fcn, datatype='callable')
|
|
543
|
+
|
|
544
|
+
if exp < 0:
|
|
545
|
+
raise ValueError("cannot take negative power of a word")
|
|
546
|
+
|
|
547
|
+
cdef WordDatatype_char w = self
|
|
548
|
+
cdef size_t i, rest
|
|
549
|
+
|
|
550
|
+
if type(exp) is Rational:
|
|
551
|
+
if w._length % exp.denominator():
|
|
552
|
+
raise ValueError("undefined")
|
|
553
|
+
i = exp.floor()
|
|
554
|
+
rest = (exp - exp.floor()) * w._length
|
|
555
|
+
else:
|
|
556
|
+
i = exp
|
|
557
|
+
rest = 0
|
|
558
|
+
|
|
559
|
+
# first handle the cases (i*length + rest) <= length and return the
|
|
560
|
+
# corresponding prefix of self
|
|
561
|
+
if i == 1 and rest == 0:
|
|
562
|
+
return self
|
|
563
|
+
if w._length == 0:
|
|
564
|
+
return w._new_c(NULL, 0, None)
|
|
565
|
+
if i == 0:
|
|
566
|
+
if rest == 0:
|
|
567
|
+
return w._new_c(NULL, 0, None)
|
|
568
|
+
else:
|
|
569
|
+
return w._new_c(w._data, rest, self)
|
|
570
|
+
|
|
571
|
+
# now consider non trivial powers
|
|
572
|
+
if w._length > SIZE_T_MAX / (i+1):
|
|
573
|
+
raise OverflowError("the length of the result is too large")
|
|
574
|
+
cdef Py_ssize_t new_length = w._length * i + rest
|
|
575
|
+
cdef unsigned char * data = <unsigned char *>check_allocarray(new_length, sizeof(unsigned char))
|
|
576
|
+
|
|
577
|
+
cdef Py_ssize_t j = w._length
|
|
578
|
+
memcpy(data, w._data, j * sizeof(unsigned char))
|
|
579
|
+
while 2*j < new_length:
|
|
580
|
+
memcpy(data + j, data, j * sizeof(unsigned char))
|
|
581
|
+
j *= 2
|
|
582
|
+
memcpy(data + j, data, (new_length - j) * sizeof(unsigned char))
|
|
583
|
+
|
|
584
|
+
return w._new_c(data, new_length, None)
|
|
585
|
+
|
|
586
|
+
def has_prefix(self, other) -> bool:
|
|
587
|
+
r"""
|
|
588
|
+
Test whether ``other`` is a prefix of ``self``.
|
|
589
|
+
|
|
590
|
+
INPUT:
|
|
591
|
+
|
|
592
|
+
- ``other`` -- a word or a sequence (e.g. tuple, list)
|
|
593
|
+
|
|
594
|
+
EXAMPLES::
|
|
595
|
+
|
|
596
|
+
sage: W = Words([0,1,2])
|
|
597
|
+
sage: w = W([0,1,1,0,1,2,0])
|
|
598
|
+
sage: w.has_prefix([0,1,1])
|
|
599
|
+
True
|
|
600
|
+
sage: w.has_prefix([0,1,2])
|
|
601
|
+
False
|
|
602
|
+
sage: w.has_prefix(w)
|
|
603
|
+
True
|
|
604
|
+
sage: w.has_prefix(w[:-1])
|
|
605
|
+
True
|
|
606
|
+
sage: w.has_prefix(w[1:])
|
|
607
|
+
False
|
|
608
|
+
|
|
609
|
+
TESTS:
|
|
610
|
+
|
|
611
|
+
:issue:`19322`::
|
|
612
|
+
|
|
613
|
+
sage: W = Words([0,1,2])
|
|
614
|
+
sage: w = W([0,1,0,2])
|
|
615
|
+
sage: w.has_prefix(words.FibonacciWord())
|
|
616
|
+
False
|
|
617
|
+
|
|
618
|
+
sage: w.has_prefix([0,1,0,2,0])
|
|
619
|
+
False
|
|
620
|
+
sage: w.has_prefix([0,1,0,2])
|
|
621
|
+
True
|
|
622
|
+
sage: w.has_prefix([0,1,0])
|
|
623
|
+
True
|
|
624
|
+
"""
|
|
625
|
+
cdef Py_ssize_t i
|
|
626
|
+
cdef WordDatatype_char w
|
|
627
|
+
|
|
628
|
+
if isinstance(other, WordDatatype_char):
|
|
629
|
+
# C level
|
|
630
|
+
w = <WordDatatype_char> other
|
|
631
|
+
if w._length > self._length:
|
|
632
|
+
return False
|
|
633
|
+
return memcmp(self._data, w._data, w._length * sizeof(unsigned char)) == 0
|
|
634
|
+
|
|
635
|
+
elif PySequence_Check(other):
|
|
636
|
+
# python level
|
|
637
|
+
from sage.combinat.words.infinite_word import InfiniteWord_class
|
|
638
|
+
if isinstance(other, InfiniteWord_class) or len(other) > len(self):
|
|
639
|
+
return False
|
|
640
|
+
|
|
641
|
+
for i in range(len(other)):
|
|
642
|
+
if other[i] != self[i]:
|
|
643
|
+
return False
|
|
644
|
+
return True
|
|
645
|
+
|
|
646
|
+
raise TypeError(f"not able to initialize a word from {other}")
|
|
647
|
+
|
|
648
|
+
def is_square(self) -> bool:
|
|
649
|
+
r"""
|
|
650
|
+
Return ``True`` if ``self`` is a square, and ``False`` otherwise.
|
|
651
|
+
|
|
652
|
+
EXAMPLES::
|
|
653
|
+
|
|
654
|
+
sage: w = Word([n % 4 for n in range(48)], alphabet=[0,1,2,3])
|
|
655
|
+
sage: w.is_square()
|
|
656
|
+
True
|
|
657
|
+
|
|
658
|
+
::
|
|
659
|
+
|
|
660
|
+
sage: w = Word([n % 4 for n in range(49)], alphabet=[0,1,2,3])
|
|
661
|
+
sage: w.is_square()
|
|
662
|
+
False
|
|
663
|
+
sage: (w*w).is_square()
|
|
664
|
+
True
|
|
665
|
+
|
|
666
|
+
TESTS:
|
|
667
|
+
|
|
668
|
+
The above tests correspond to the present class (char)::
|
|
669
|
+
|
|
670
|
+
sage: type(w)
|
|
671
|
+
<class 'sage.combinat.words.word.FiniteWord_char'>
|
|
672
|
+
|
|
673
|
+
::
|
|
674
|
+
|
|
675
|
+
sage: Word([], alphabet=[0,1]).is_square()
|
|
676
|
+
True
|
|
677
|
+
sage: Word([0], alphabet=[0,1]).is_square()
|
|
678
|
+
False
|
|
679
|
+
sage: Word([0,0], alphabet=[0,1]).is_square()
|
|
680
|
+
True
|
|
681
|
+
"""
|
|
682
|
+
cdef size_t l
|
|
683
|
+
if self._length % 2:
|
|
684
|
+
return False
|
|
685
|
+
else:
|
|
686
|
+
l = self._length // 2
|
|
687
|
+
return memcmp(self._data,
|
|
688
|
+
self._data + l,
|
|
689
|
+
l * sizeof(unsigned char)) == 0
|
|
690
|
+
|
|
691
|
+
def longest_common_prefix(self, other):
|
|
692
|
+
r"""
|
|
693
|
+
Return the longest common prefix of this word and ``other``.
|
|
694
|
+
|
|
695
|
+
EXAMPLES::
|
|
696
|
+
|
|
697
|
+
sage: W = Words([0,1,2])
|
|
698
|
+
sage: W([0,1,0,2]).longest_common_prefix([0,1])
|
|
699
|
+
word: 01
|
|
700
|
+
sage: u = W([0,1,0,0,1])
|
|
701
|
+
sage: v = W([0,1,0,2])
|
|
702
|
+
sage: u.longest_common_prefix(v)
|
|
703
|
+
word: 010
|
|
704
|
+
sage: v.longest_common_prefix(u)
|
|
705
|
+
word: 010
|
|
706
|
+
|
|
707
|
+
Using infinite words is also possible (and the return type is also a
|
|
708
|
+
of the same type as ``self``)::
|
|
709
|
+
|
|
710
|
+
sage: W([0,1,0,0]).longest_common_prefix(words.FibonacciWord())
|
|
711
|
+
word: 0100
|
|
712
|
+
sage: type(_)
|
|
713
|
+
<class 'sage.combinat.words.word.FiniteWord_char'>
|
|
714
|
+
|
|
715
|
+
An example of an intensive usage::
|
|
716
|
+
|
|
717
|
+
sage: W = Words([0,1])
|
|
718
|
+
sage: w = words.FibonacciWord()
|
|
719
|
+
sage: w = W(list(w[:5000]))
|
|
720
|
+
sage: L = [[len(w[n:].longest_common_prefix(w[n+fibonacci(i):])) # needs sage.libs.pari
|
|
721
|
+
....: for i in range(5,15)] for n in range(1,1000)]
|
|
722
|
+
sage: for n,l in enumerate(L): # needs sage.libs.pari
|
|
723
|
+
....: if l.count(0) > 4:
|
|
724
|
+
....: print("{} {}".format(n+1,l))
|
|
725
|
+
375 [0, 13, 0, 34, 0, 89, 0, 233, 0, 233]
|
|
726
|
+
376 [0, 12, 0, 33, 0, 88, 0, 232, 0, 232]
|
|
727
|
+
608 [8, 0, 21, 0, 55, 0, 144, 0, 377, 0]
|
|
728
|
+
609 [7, 0, 20, 0, 54, 0, 143, 0, 376, 0]
|
|
729
|
+
985 [0, 13, 0, 34, 0, 89, 0, 233, 0, 610]
|
|
730
|
+
986 [0, 12, 0, 33, 0, 88, 0, 232, 0, 609]
|
|
731
|
+
|
|
732
|
+
TESTS::
|
|
733
|
+
|
|
734
|
+
sage: W = Words([0,1,2])
|
|
735
|
+
sage: w = W([0,2,1,0,0,1])
|
|
736
|
+
sage: w.longest_common_prefix(0)
|
|
737
|
+
Traceback (most recent call last):
|
|
738
|
+
...
|
|
739
|
+
TypeError: unsupported input 0
|
|
740
|
+
|
|
741
|
+
::
|
|
742
|
+
|
|
743
|
+
sage: Word([2,2], (1,2)).longest_common_prefix([])
|
|
744
|
+
word:
|
|
745
|
+
"""
|
|
746
|
+
cdef WordDatatype_char w
|
|
747
|
+
cdef size_t i = <size_t>(-1)
|
|
748
|
+
cdef size_t m
|
|
749
|
+
|
|
750
|
+
if isinstance(other, WordDatatype_char):
|
|
751
|
+
# C level
|
|
752
|
+
# (this can be much faster if we allow to compare larger memory
|
|
753
|
+
# zones)
|
|
754
|
+
w = other
|
|
755
|
+
m = min(self._length, w._length)
|
|
756
|
+
for i in range(m):
|
|
757
|
+
if self._data[i] != w._data[i]:
|
|
758
|
+
break
|
|
759
|
+
else:
|
|
760
|
+
if self._length <= w._length:
|
|
761
|
+
return self
|
|
762
|
+
else:
|
|
763
|
+
return other
|
|
764
|
+
|
|
765
|
+
return self._new_c(self._data, i, self)
|
|
766
|
+
|
|
767
|
+
elif PySequence_Check(other):
|
|
768
|
+
# Python level
|
|
769
|
+
# we avoid to call len(other) since it might be an infinite word
|
|
770
|
+
for i, a in enumerate(itertools.islice(other, self._length)):
|
|
771
|
+
if self._data[i] != a:
|
|
772
|
+
break
|
|
773
|
+
else:
|
|
774
|
+
i += 1
|
|
775
|
+
|
|
776
|
+
return self._new_c(self._data, i, self)
|
|
777
|
+
|
|
778
|
+
raise TypeError("unsupported input {}".format(other))
|
|
779
|
+
|
|
780
|
+
def longest_common_suffix(self, other):
|
|
781
|
+
r"""
|
|
782
|
+
Return the longest common suffix between this word and ``other``.
|
|
783
|
+
|
|
784
|
+
EXAMPLES::
|
|
785
|
+
|
|
786
|
+
sage: W = Words([0,1,2])
|
|
787
|
+
sage: W([0,1,0,2]).longest_common_suffix([2,0,2])
|
|
788
|
+
word: 02
|
|
789
|
+
sage: u = W([0,1,0,0,1])
|
|
790
|
+
sage: v = W([1,2,0,0,1])
|
|
791
|
+
sage: u.longest_common_suffix(v)
|
|
792
|
+
word: 001
|
|
793
|
+
sage: v.longest_common_suffix(u)
|
|
794
|
+
word: 001
|
|
795
|
+
|
|
796
|
+
TESTS::
|
|
797
|
+
|
|
798
|
+
sage: W = Words([0,1,2])
|
|
799
|
+
sage: w = W([0,2,1,0,0,1])
|
|
800
|
+
sage: w.longest_common_suffix(0)
|
|
801
|
+
Traceback (most recent call last):
|
|
802
|
+
...
|
|
803
|
+
TypeError: unsupported input 0
|
|
804
|
+
|
|
805
|
+
::
|
|
806
|
+
|
|
807
|
+
sage: Word([2,2], (1,2)).longest_common_suffix([])
|
|
808
|
+
word:
|
|
809
|
+
"""
|
|
810
|
+
cdef WordDatatype_char w
|
|
811
|
+
cdef size_t i = <size_t>(-1)
|
|
812
|
+
cdef size_t m
|
|
813
|
+
cdef size_t lo
|
|
814
|
+
|
|
815
|
+
if isinstance(other, WordDatatype_char):
|
|
816
|
+
# C level
|
|
817
|
+
# (this can be much faster if we could compare larger memory
|
|
818
|
+
# zones)
|
|
819
|
+
w = other
|
|
820
|
+
m = min(self._length, w._length)
|
|
821
|
+
for i in range(m):
|
|
822
|
+
if self._data[self._length-i-1] != w._data[w._length-i-1]:
|
|
823
|
+
break
|
|
824
|
+
else:
|
|
825
|
+
if self._length <= w._length:
|
|
826
|
+
return self
|
|
827
|
+
else:
|
|
828
|
+
return other
|
|
829
|
+
|
|
830
|
+
return self._new_c(self._data+self._length-i, i, self)
|
|
831
|
+
|
|
832
|
+
elif PySequence_Check(other):
|
|
833
|
+
# Python level
|
|
834
|
+
lo = len(other)
|
|
835
|
+
m = min(self._length, lo)
|
|
836
|
+
for i in range(m):
|
|
837
|
+
if self._data[self._length-i-1] != other[lo-i-1]:
|
|
838
|
+
break
|
|
839
|
+
else:
|
|
840
|
+
if self._length == m:
|
|
841
|
+
return self
|
|
842
|
+
else:
|
|
843
|
+
i += 1
|
|
844
|
+
|
|
845
|
+
return self._new_c(self._data+self._length-i, i, self)
|
|
846
|
+
|
|
847
|
+
raise TypeError("unsupported input {}".format(other))
|