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,1218 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-combinat
|
|
2
|
+
r"""
|
|
3
|
+
Datatypes for words defined by iterators and callables
|
|
4
|
+
"""
|
|
5
|
+
# ****************************************************************************
|
|
6
|
+
# Copyright (C) 2009 Franco Saliola <saliola@gmail.com>
|
|
7
|
+
# Vincent Delecroix <20100.delecroix@gmail.com>
|
|
8
|
+
#
|
|
9
|
+
# This program is free software: you can redistribute it and/or modify
|
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
|
11
|
+
# the Free Software Foundation, either version 2 of the License, or
|
|
12
|
+
# (at your option) any later version.
|
|
13
|
+
# https://www.gnu.org/licenses/
|
|
14
|
+
# ****************************************************************************
|
|
15
|
+
|
|
16
|
+
from sage.combinat.words.word_datatypes import WordDatatype
|
|
17
|
+
from sage.rings.infinity import Infinity
|
|
18
|
+
from math import ceil
|
|
19
|
+
import itertools
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class WordDatatype_callable(WordDatatype):
|
|
23
|
+
r"""
|
|
24
|
+
Datatype for a word defined by a callable.
|
|
25
|
+
"""
|
|
26
|
+
def __init__(self, parent, callable, length=None):
|
|
27
|
+
r"""
|
|
28
|
+
INPUT:
|
|
29
|
+
|
|
30
|
+
- ``parent`` -- a parent
|
|
31
|
+
- ``callable`` -- a callable defined on ``range(stop=length)``
|
|
32
|
+
- ``length`` -- (default: ``None``) nonnegative integer or ``None``
|
|
33
|
+
|
|
34
|
+
EXAMPLES::
|
|
35
|
+
|
|
36
|
+
sage: f = lambda n : 'x' if n % 2 == 0 else 'y'
|
|
37
|
+
sage: w = Word(f, length=9, caching=False); w
|
|
38
|
+
word: xyxyxyxyx
|
|
39
|
+
sage: type(w)
|
|
40
|
+
<class 'sage.combinat.words.word.FiniteWord_callable'>
|
|
41
|
+
sage: w.length()
|
|
42
|
+
9
|
|
43
|
+
|
|
44
|
+
::
|
|
45
|
+
|
|
46
|
+
sage: w = Word(f, caching=False); w
|
|
47
|
+
word: xyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxy...
|
|
48
|
+
sage: type(w)
|
|
49
|
+
<class 'sage.combinat.words.word.InfiniteWord_callable'>
|
|
50
|
+
sage: w.length() is None
|
|
51
|
+
False
|
|
52
|
+
sage: w.length()
|
|
53
|
+
+Infinity
|
|
54
|
+
|
|
55
|
+
TESTS::
|
|
56
|
+
|
|
57
|
+
sage: from sage.combinat.words.word_infinite_datatypes import WordDatatype_callable
|
|
58
|
+
sage: WordDatatype_callable(Words(),lambda n:n%3)
|
|
59
|
+
<sage.combinat.words.word_infinite_datatypes.WordDatatype_callable object at ...>
|
|
60
|
+
sage: WordDatatype_callable(Words([0,1,2]),lambda n:n%3)
|
|
61
|
+
<sage.combinat.words.word_infinite_datatypes.WordDatatype_callable object at ...>
|
|
62
|
+
"""
|
|
63
|
+
self._len = Infinity if length is None else length
|
|
64
|
+
self._func = callable
|
|
65
|
+
self._parent = parent
|
|
66
|
+
# for hashing
|
|
67
|
+
self._hash = None
|
|
68
|
+
|
|
69
|
+
def __iter__(self):
|
|
70
|
+
r"""
|
|
71
|
+
EXAMPLES::
|
|
72
|
+
|
|
73
|
+
sage: w = Word(lambda x : x % 2)
|
|
74
|
+
sage: it = iter(w)
|
|
75
|
+
sage: [next(it) for _ in range(10)]
|
|
76
|
+
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
|
|
77
|
+
|
|
78
|
+
TESTS::
|
|
79
|
+
|
|
80
|
+
sage: from sage.combinat.words.word_infinite_datatypes import WordDatatype_callable
|
|
81
|
+
sage: s = WordDatatype_callable(Words(), lambda n:n%3+10, length=10); s
|
|
82
|
+
<sage.combinat.words.word_infinite_datatypes.WordDatatype_callable object at ...>
|
|
83
|
+
sage: it = iter(s)
|
|
84
|
+
sage: [next(it) for _ in range(10)]
|
|
85
|
+
[10, 11, 12, 10, 11, 12, 10, 11, 12, 10]
|
|
86
|
+
"""
|
|
87
|
+
if self._len is Infinity:
|
|
88
|
+
domain = itertools.count()
|
|
89
|
+
else:
|
|
90
|
+
domain = range(self._len)
|
|
91
|
+
for x in domain:
|
|
92
|
+
yield self._func(x)
|
|
93
|
+
|
|
94
|
+
def __getitem__(self, key):
|
|
95
|
+
r"""
|
|
96
|
+
EXAMPLES::
|
|
97
|
+
|
|
98
|
+
sage: f = lambda n : "abbabaabbaab"[n]
|
|
99
|
+
sage: w = Word(f, length=12, caching=False); w
|
|
100
|
+
word: abbabaabbaab
|
|
101
|
+
sage: w.length()
|
|
102
|
+
12
|
|
103
|
+
|
|
104
|
+
Test getitems with indexes::
|
|
105
|
+
|
|
106
|
+
sage: w[0]
|
|
107
|
+
'a'
|
|
108
|
+
sage: w[4]
|
|
109
|
+
'b'
|
|
110
|
+
sage: w[-1]
|
|
111
|
+
'b'
|
|
112
|
+
sage: w[-2]
|
|
113
|
+
'a'
|
|
114
|
+
sage: [w[i] for i in range(12)]
|
|
115
|
+
['a', 'b', 'b', 'a', 'b', 'a', 'a', 'b', 'b', 'a', 'a', 'b']
|
|
116
|
+
|
|
117
|
+
Slicing::
|
|
118
|
+
|
|
119
|
+
sage: w[:]
|
|
120
|
+
word: abbabaabbaab
|
|
121
|
+
|
|
122
|
+
Prefixes::
|
|
123
|
+
|
|
124
|
+
sage: w[0:]
|
|
125
|
+
word: abbabaabbaab
|
|
126
|
+
sage: w[1:]
|
|
127
|
+
word: bbabaabbaab
|
|
128
|
+
|
|
129
|
+
Suffixes::
|
|
130
|
+
|
|
131
|
+
sage: w[:0]
|
|
132
|
+
word:
|
|
133
|
+
sage: w[:5]
|
|
134
|
+
word: abbab
|
|
135
|
+
|
|
136
|
+
With positive steps::
|
|
137
|
+
|
|
138
|
+
sage: w[::2]
|
|
139
|
+
word: abbaba
|
|
140
|
+
|
|
141
|
+
With a negative start position::
|
|
142
|
+
|
|
143
|
+
sage: w[-2:]
|
|
144
|
+
word: ab
|
|
145
|
+
sage: w[-20:]
|
|
146
|
+
word: abbabaabbaab
|
|
147
|
+
|
|
148
|
+
With a negative stop position::
|
|
149
|
+
|
|
150
|
+
sage: w[:-1]
|
|
151
|
+
word: abbabaabbaa
|
|
152
|
+
sage: w[:-10]
|
|
153
|
+
word: ab
|
|
154
|
+
|
|
155
|
+
With a negative step::
|
|
156
|
+
|
|
157
|
+
sage: w[::-2]
|
|
158
|
+
word: babaab
|
|
159
|
+
sage: w[10:1:-2]
|
|
160
|
+
word: ababb
|
|
161
|
+
sage: w[10:0:-2]
|
|
162
|
+
word: ababb
|
|
163
|
+
sage: w[:1:-3]
|
|
164
|
+
word: bbab
|
|
165
|
+
|
|
166
|
+
TESTS:
|
|
167
|
+
|
|
168
|
+
For infinite words::
|
|
169
|
+
|
|
170
|
+
sage: f = lambda n : add(Integer(n).digits(2)) % 2
|
|
171
|
+
sage: tm = Word(f, caching=False); tm
|
|
172
|
+
word: 0110100110010110100101100110100110010110...
|
|
173
|
+
sage: tm.length()
|
|
174
|
+
+Infinity
|
|
175
|
+
|
|
176
|
+
Test getitems with indexes::
|
|
177
|
+
|
|
178
|
+
sage: tm[0]
|
|
179
|
+
0
|
|
180
|
+
sage: tm[4]
|
|
181
|
+
1
|
|
182
|
+
sage: [tm[i] for i in range(12)]
|
|
183
|
+
[0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1]
|
|
184
|
+
sage: tm[-1]
|
|
185
|
+
Traceback (most recent call last):
|
|
186
|
+
...
|
|
187
|
+
IndexError: cannot use a negative index with an infinite word
|
|
188
|
+
|
|
189
|
+
Slicing::
|
|
190
|
+
|
|
191
|
+
sage: tm[:]
|
|
192
|
+
word: 0110100110010110100101100110100110010110...
|
|
193
|
+
|
|
194
|
+
Prefixes::
|
|
195
|
+
|
|
196
|
+
sage: tm[:0]
|
|
197
|
+
word:
|
|
198
|
+
sage: tm[:5]
|
|
199
|
+
word: 01101
|
|
200
|
+
|
|
201
|
+
Suffixes::
|
|
202
|
+
|
|
203
|
+
sage: tm[0:]
|
|
204
|
+
word: 0110100110010110100101100110100110010110...
|
|
205
|
+
sage: tm[1:]
|
|
206
|
+
word: 1101001100101101001011001101001100101100...
|
|
207
|
+
|
|
208
|
+
With positive steps::
|
|
209
|
+
|
|
210
|
+
sage: tm[::2]
|
|
211
|
+
word: 0110100110010110100101100110100110010110...
|
|
212
|
+
|
|
213
|
+
With a negative step::
|
|
214
|
+
|
|
215
|
+
sage: tm[20:1:-3]
|
|
216
|
+
word: 0011101
|
|
217
|
+
sage: tm[10:1:-2]
|
|
218
|
+
word: 01011
|
|
219
|
+
sage: tm[10:0:-2]
|
|
220
|
+
word: 01011
|
|
221
|
+
sage: tm[::-2]
|
|
222
|
+
Traceback (most recent call last):
|
|
223
|
+
...
|
|
224
|
+
ValueError: start value must be nonnegative for negative step values
|
|
225
|
+
sage: tm[-17::-2]
|
|
226
|
+
Traceback (most recent call last):
|
|
227
|
+
...
|
|
228
|
+
ValueError: for infinite words, start and stop values cannot be negative
|
|
229
|
+
|
|
230
|
+
Out of range index (:issue:`8673`)::
|
|
231
|
+
|
|
232
|
+
sage: w = Word(lambda n:n^2, length=23)
|
|
233
|
+
sage: w[100]
|
|
234
|
+
Traceback (most recent call last):
|
|
235
|
+
...
|
|
236
|
+
IndexError: word index out of range
|
|
237
|
+
"""
|
|
238
|
+
if isinstance(key, slice):
|
|
239
|
+
# Infinite words
|
|
240
|
+
if self._len is Infinity or self._len is None:
|
|
241
|
+
if key.start is not None and key.start < 0 or \
|
|
242
|
+
key.stop is not None and key.stop < 0:
|
|
243
|
+
raise ValueError("for infinite words, start and stop values cannot be negative")
|
|
244
|
+
step = 1 if key.step is None else key.step
|
|
245
|
+
if step > 0:
|
|
246
|
+
start = 0 if key.start is None else key.start
|
|
247
|
+
length = self._len if key.stop is None else \
|
|
248
|
+
int(max(0, ceil((key.stop-start)/float(step))))
|
|
249
|
+
else:
|
|
250
|
+
if key.start is None or key.start < 0:
|
|
251
|
+
raise ValueError("start value must be nonnegative for negative step values")
|
|
252
|
+
start = key.start
|
|
253
|
+
stop = 0 if key.stop is None else key.stop
|
|
254
|
+
length = int(max(0, ceil((key.stop-start)/float(step))))
|
|
255
|
+
fcn = lambda x: self._func(start + x*step)
|
|
256
|
+
if length is None:
|
|
257
|
+
return self._parent(fcn, length=length)
|
|
258
|
+
elif length is Infinity:
|
|
259
|
+
return self._parent.shift()(fcn)
|
|
260
|
+
else:
|
|
261
|
+
return self._parent.factors()(fcn, length=length)
|
|
262
|
+
# Finite words
|
|
263
|
+
else:
|
|
264
|
+
## For testing: expand as a list and slice it
|
|
265
|
+
#return self._parent(map(self._func, range(self._len))[key])
|
|
266
|
+
step = 1 if key.step is None else key.step
|
|
267
|
+
if step > 0:
|
|
268
|
+
start, stop, step = slice(key.start, key.stop,
|
|
269
|
+
step).indices(self._len)
|
|
270
|
+
length = int((stop-start)/float(step))
|
|
271
|
+
else:
|
|
272
|
+
start, stop, step = slice(key.start, key.stop,
|
|
273
|
+
step).indices(self._len)
|
|
274
|
+
length = int(max(0, ceil((stop-start)/float(step))))
|
|
275
|
+
fcn = lambda x: self._func(start + x*step)
|
|
276
|
+
return self._parent(fcn, length=length)
|
|
277
|
+
else:
|
|
278
|
+
if key < 0:
|
|
279
|
+
if self._len is Infinity:
|
|
280
|
+
raise IndexError("cannot use a negative index with an infinite word")
|
|
281
|
+
else:
|
|
282
|
+
key = self._len + key
|
|
283
|
+
elif key >= self._len:
|
|
284
|
+
raise IndexError("word index out of range")
|
|
285
|
+
return self._func(key)
|
|
286
|
+
|
|
287
|
+
def __reduce__(self):
|
|
288
|
+
r"""
|
|
289
|
+
EXAMPLES::
|
|
290
|
+
|
|
291
|
+
sage: w = Word(lambda n : n%3+10, caching=False)
|
|
292
|
+
sage: w.__reduce__()
|
|
293
|
+
(Infinite words over Set of Python objects of class 'object',
|
|
294
|
+
(...sage.misc.fpickle...<lambda>..., 'pickled_function', False))
|
|
295
|
+
|
|
296
|
+
::
|
|
297
|
+
|
|
298
|
+
sage: w = Word(lambda n : n%3+10, caching=False, length=8)
|
|
299
|
+
sage: w.__reduce__()
|
|
300
|
+
(Finite words over Set of Python objects of class 'object',
|
|
301
|
+
(...sage.misc.fpickle...<lambda>..., 8, 'pickled_function', False))
|
|
302
|
+
"""
|
|
303
|
+
from sage.misc.fpickle import pickle_function
|
|
304
|
+
try:
|
|
305
|
+
s = pickle_function(self._func)
|
|
306
|
+
except Exception:
|
|
307
|
+
if self.is_finite():
|
|
308
|
+
return self._parent, (list(self),)
|
|
309
|
+
else:
|
|
310
|
+
return self._parent, (self._func, 'callable', False)
|
|
311
|
+
else:
|
|
312
|
+
if self.is_finite():
|
|
313
|
+
return self._parent, (s, self._len, 'pickled_function', False)
|
|
314
|
+
else:
|
|
315
|
+
return self._parent, (s, 'pickled_function', False)
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
class WordDatatype_callable_with_caching(WordDatatype_callable):
|
|
319
|
+
r"""
|
|
320
|
+
Datatype for a word defined by a callable.
|
|
321
|
+
"""
|
|
322
|
+
def __init__(self, parent, callable, length=None):
|
|
323
|
+
r"""
|
|
324
|
+
INPUT:
|
|
325
|
+
|
|
326
|
+
- ``parent`` -- a parent
|
|
327
|
+
- ``callable`` -- a callable defined on ``range(stop=length)``
|
|
328
|
+
- ``length`` -- (default: ``None``) nonnegative integer or ``None``
|
|
329
|
+
|
|
330
|
+
EXAMPLES::
|
|
331
|
+
|
|
332
|
+
sage: f = lambda n : 'x' if n % 2 == 0 else 'y'
|
|
333
|
+
sage: w = Word(f, length=9, caching=True); w
|
|
334
|
+
word: xyxyxyxyx
|
|
335
|
+
sage: type(w)
|
|
336
|
+
<class 'sage.combinat.words.word.FiniteWord_callable_with_caching'>
|
|
337
|
+
sage: w.length()
|
|
338
|
+
9
|
|
339
|
+
|
|
340
|
+
::
|
|
341
|
+
|
|
342
|
+
sage: w = Word(f, caching=True); w
|
|
343
|
+
word: xyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxyxy...
|
|
344
|
+
sage: type(w)
|
|
345
|
+
<class 'sage.combinat.words.word.InfiniteWord_callable_with_caching'>
|
|
346
|
+
sage: w.length() is None
|
|
347
|
+
False
|
|
348
|
+
sage: w.length()
|
|
349
|
+
+Infinity
|
|
350
|
+
"""
|
|
351
|
+
super().__init__(parent, callable, length)
|
|
352
|
+
# for caching
|
|
353
|
+
self._letter_cache = {}
|
|
354
|
+
|
|
355
|
+
def __iter__(self):
|
|
356
|
+
r"""
|
|
357
|
+
Iterate through the letters of the word, in order.
|
|
358
|
+
|
|
359
|
+
EXAMPLES::
|
|
360
|
+
|
|
361
|
+
sage: w = Word(lambda x : x % 2)
|
|
362
|
+
sage: it = iter(w)
|
|
363
|
+
sage: [next(it) for _ in range(10)]
|
|
364
|
+
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
|
|
365
|
+
"""
|
|
366
|
+
if self._len is Infinity:
|
|
367
|
+
domain = itertools.count()
|
|
368
|
+
else:
|
|
369
|
+
domain = range(self._len)
|
|
370
|
+
letter_cache = self._letter_cache
|
|
371
|
+
func = self._func
|
|
372
|
+
for x in domain:
|
|
373
|
+
if x not in letter_cache:
|
|
374
|
+
letter_cache[x] = func(x)
|
|
375
|
+
yield letter_cache[x]
|
|
376
|
+
|
|
377
|
+
def __getitem__(self, key):
|
|
378
|
+
r"""
|
|
379
|
+
EXAMPLES::
|
|
380
|
+
|
|
381
|
+
sage: f = lambda n : "abbabaabbaab"[n]
|
|
382
|
+
sage: w = Word(f, length=12); w
|
|
383
|
+
word: abbabaabbaab
|
|
384
|
+
sage: w.length()
|
|
385
|
+
12
|
|
386
|
+
|
|
387
|
+
Test getitems with indexes::
|
|
388
|
+
|
|
389
|
+
sage: w[0]
|
|
390
|
+
'a'
|
|
391
|
+
sage: w[4]
|
|
392
|
+
'b'
|
|
393
|
+
sage: w[-1]
|
|
394
|
+
'b'
|
|
395
|
+
sage: w[-2]
|
|
396
|
+
'a'
|
|
397
|
+
sage: [w[i] for i in range(12)]
|
|
398
|
+
['a', 'b', 'b', 'a', 'b', 'a', 'a', 'b', 'b', 'a', 'a', 'b']
|
|
399
|
+
|
|
400
|
+
Slicing::
|
|
401
|
+
|
|
402
|
+
sage: w[:]
|
|
403
|
+
word: abbabaabbaab
|
|
404
|
+
|
|
405
|
+
Prefixes::
|
|
406
|
+
|
|
407
|
+
sage: w[0:]
|
|
408
|
+
word: abbabaabbaab
|
|
409
|
+
|
|
410
|
+
sage: w[1:]
|
|
411
|
+
word: bbabaabbaab
|
|
412
|
+
|
|
413
|
+
Suffixes::
|
|
414
|
+
|
|
415
|
+
sage: w[:0]
|
|
416
|
+
word:
|
|
417
|
+
|
|
418
|
+
sage: w[:5]
|
|
419
|
+
word: abbab
|
|
420
|
+
|
|
421
|
+
With positive steps::
|
|
422
|
+
|
|
423
|
+
sage: w[::2]
|
|
424
|
+
word: abbaba
|
|
425
|
+
|
|
426
|
+
With a negative start position::
|
|
427
|
+
|
|
428
|
+
sage: w[-2:]
|
|
429
|
+
word: ab
|
|
430
|
+
sage: w[-20:]
|
|
431
|
+
word: abbabaabbaab
|
|
432
|
+
|
|
433
|
+
With a negative stop position::
|
|
434
|
+
|
|
435
|
+
sage: w[:-1]
|
|
436
|
+
word: abbabaabbaa
|
|
437
|
+
sage: w[:-10]
|
|
438
|
+
word: ab
|
|
439
|
+
|
|
440
|
+
With a negative step::
|
|
441
|
+
|
|
442
|
+
sage: w[::-2]
|
|
443
|
+
word: babaab
|
|
444
|
+
|
|
445
|
+
sage: w[10:1:-2]
|
|
446
|
+
word: ababb
|
|
447
|
+
sage: w[10:0:-2]
|
|
448
|
+
word: ababb
|
|
449
|
+
sage: w[:1:-3]
|
|
450
|
+
word: bbab
|
|
451
|
+
|
|
452
|
+
TESTS:
|
|
453
|
+
|
|
454
|
+
For infinite words::
|
|
455
|
+
|
|
456
|
+
sage: f = lambda n : add(Integer(n).digits(2)) % 2
|
|
457
|
+
sage: tm = Word(f); tm
|
|
458
|
+
word: 0110100110010110100101100110100110010110...
|
|
459
|
+
|
|
460
|
+
sage: tm.length()
|
|
461
|
+
+Infinity
|
|
462
|
+
|
|
463
|
+
Test getitems with indexes::
|
|
464
|
+
|
|
465
|
+
sage: tm[0]
|
|
466
|
+
0
|
|
467
|
+
sage: tm[4]
|
|
468
|
+
1
|
|
469
|
+
sage: [tm[i] for i in range(12)]
|
|
470
|
+
[0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1]
|
|
471
|
+
sage: tm[-1]
|
|
472
|
+
Traceback (most recent call last):
|
|
473
|
+
...
|
|
474
|
+
IndexError: cannot use a negative index with an infinite word
|
|
475
|
+
|
|
476
|
+
Slicing::
|
|
477
|
+
|
|
478
|
+
sage: tm[:]
|
|
479
|
+
word: 0110100110010110100101100110100110010110...
|
|
480
|
+
|
|
481
|
+
Prefixes::
|
|
482
|
+
|
|
483
|
+
sage: tm[:0]
|
|
484
|
+
word:
|
|
485
|
+
|
|
486
|
+
sage: tm[:5]
|
|
487
|
+
word: 01101
|
|
488
|
+
|
|
489
|
+
Suffixes::
|
|
490
|
+
|
|
491
|
+
sage: tm[0:]
|
|
492
|
+
word: 0110100110010110100101100110100110010110...
|
|
493
|
+
|
|
494
|
+
sage: tm[1:]
|
|
495
|
+
word: 1101001100101101001011001101001100101100...
|
|
496
|
+
|
|
497
|
+
With positive steps::
|
|
498
|
+
|
|
499
|
+
sage: tm[::2]
|
|
500
|
+
word: 0110100110010110100101100110100110010110...
|
|
501
|
+
|
|
502
|
+
With a negative step::
|
|
503
|
+
|
|
504
|
+
sage: tm[20:1:-3]
|
|
505
|
+
word: 0011101
|
|
506
|
+
sage: tm[10:1:-2]
|
|
507
|
+
word: 01011
|
|
508
|
+
sage: tm[10:0:-2]
|
|
509
|
+
word: 01011
|
|
510
|
+
sage: tm[::-2]
|
|
511
|
+
Traceback (most recent call last):
|
|
512
|
+
...
|
|
513
|
+
ValueError: start value must be nonnegative for negative step values
|
|
514
|
+
sage: tm[-17::-2]
|
|
515
|
+
Traceback (most recent call last):
|
|
516
|
+
...
|
|
517
|
+
ValueError: for infinite words, start and stop values cannot be negative
|
|
518
|
+
"""
|
|
519
|
+
if isinstance(key, slice):
|
|
520
|
+
return super().__getitem__(key)
|
|
521
|
+
else:
|
|
522
|
+
if key not in self._letter_cache:
|
|
523
|
+
self._letter_cache[key] = \
|
|
524
|
+
super().__getitem__(key)
|
|
525
|
+
return self._letter_cache[key]
|
|
526
|
+
|
|
527
|
+
def __reduce__(self):
|
|
528
|
+
r"""
|
|
529
|
+
EXAMPLES::
|
|
530
|
+
|
|
531
|
+
sage: w = Word(lambda n : n%3+10, caching=True)
|
|
532
|
+
sage: w.__reduce__()
|
|
533
|
+
(Infinite words over Set of Python objects of class 'object',
|
|
534
|
+
(...sage.misc.fpickle...<lambda>..., 'pickled_function', True))
|
|
535
|
+
|
|
536
|
+
::
|
|
537
|
+
|
|
538
|
+
sage: w = Word(lambda n : n%3+10, caching=True, length=8)
|
|
539
|
+
sage: w.__reduce__()
|
|
540
|
+
(Finite words over Set of Python objects of class 'object',
|
|
541
|
+
(...sage.misc.fpickle...<lambda>..., 8, 'pickled_function', True))
|
|
542
|
+
|
|
543
|
+
Because ``pickle_function`` fails on CallableFromListOfWords,
|
|
544
|
+
then concatenation of words are expanded as a list::
|
|
545
|
+
|
|
546
|
+
sage: w = Word(range(5)) + Word('abcde')
|
|
547
|
+
sage: w.__reduce__()
|
|
548
|
+
(Finite words over Set of Python objects of class 'object', ([0, 1, 2, 3, 4, 'a', 'b', 'c', 'd', 'e'],))
|
|
549
|
+
"""
|
|
550
|
+
from sage.misc.fpickle import pickle_function
|
|
551
|
+
try:
|
|
552
|
+
s = pickle_function(self._func)
|
|
553
|
+
except Exception:
|
|
554
|
+
if self.is_finite():
|
|
555
|
+
return self._parent, (list(self),)
|
|
556
|
+
else:
|
|
557
|
+
return self._parent, (self._func, 'callable', True)
|
|
558
|
+
else:
|
|
559
|
+
if self.is_finite():
|
|
560
|
+
return self._parent, (s, self._len, 'pickled_function', True)
|
|
561
|
+
else:
|
|
562
|
+
return self._parent, (s, 'pickled_function', True)
|
|
563
|
+
|
|
564
|
+
def flush(self):
|
|
565
|
+
r"""
|
|
566
|
+
Empty the associated cache of letters.
|
|
567
|
+
|
|
568
|
+
EXAMPLES:
|
|
569
|
+
|
|
570
|
+
The first 40 (by default) values are always cached::
|
|
571
|
+
|
|
572
|
+
sage: w = words.ThueMorseWord()
|
|
573
|
+
sage: w._letter_cache
|
|
574
|
+
{0: 0, 1: 1, 2: 1, 3: 0, 4: 1, 5: 0, 6: 0, 7: 1, 8: 1, 9: 0, 10: 0, 11: 1, 12: 0, 13: 1, 14: 1, 15: 0, 16: 1, 17: 0, 18: 0, 19: 1, 20: 0, 21: 1, 22: 1, 23: 0, 24: 0, 25: 1, 26: 1, 27: 0, 28: 1, 29: 0, 30: 0, 31: 1, 32: 1, 33: 0, 34: 0, 35: 1, 36: 0, 37: 1, 38: 1, 39: 0}
|
|
575
|
+
sage: w[100]
|
|
576
|
+
1
|
|
577
|
+
sage: w._letter_cache
|
|
578
|
+
{0: 0, 1: 1, 2: 1, 3: 0, 4: 1, 5: 0, 6: 0, 7: 1, 8: 1, 9: 0, 10: 0, 11: 1, 12: 0, 13: 1, 14: 1, 15: 0, 16: 1, 17: 0, 18: 0, 19: 1, 20: 0, 21: 1, 22: 1, 23: 0, 24: 0, 25: 1, 26: 1, 27: 0, 28: 1, 29: 0, 30: 0, 31: 1, 32: 1, 33: 0, 34: 0, 35: 1, 36: 0, 37: 1, 38: 1, 39: 0, 100: 1}
|
|
579
|
+
sage: w.flush()
|
|
580
|
+
sage: w._letter_cache
|
|
581
|
+
{}
|
|
582
|
+
"""
|
|
583
|
+
self._letter_cache = {}
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
class WordDatatype_iter(WordDatatype):
|
|
587
|
+
# NOTE: The constructor callable should do all the slicing (see islice)
|
|
588
|
+
def __init__(self, parent, iter, length=None):
|
|
589
|
+
r"""
|
|
590
|
+
INPUT:
|
|
591
|
+
|
|
592
|
+
- ``parent`` -- a parent
|
|
593
|
+
- ``iter`` -- an iterator
|
|
594
|
+
- ``length`` -- (default: ``None``) the length of the word
|
|
595
|
+
|
|
596
|
+
EXAMPLES::
|
|
597
|
+
|
|
598
|
+
sage: w = Word(iter("abbabaab"), length='unknown', caching=False); w
|
|
599
|
+
word: abbabaab
|
|
600
|
+
sage: isinstance(w, sage.combinat.words.word_infinite_datatypes.WordDatatype_iter)
|
|
601
|
+
True
|
|
602
|
+
sage: w.length() is None
|
|
603
|
+
False
|
|
604
|
+
sage: w.length()
|
|
605
|
+
8
|
|
606
|
+
sage: s = "abbabaabbaababbabaababbaabbabaabbaababbaabbabaabab"
|
|
607
|
+
sage: w = Word(iter(s), length='unknown', caching=False); w
|
|
608
|
+
word: abbabaabbaababbabaababbaabbabaabbaababba...
|
|
609
|
+
sage: w.length() is None
|
|
610
|
+
True
|
|
611
|
+
|
|
612
|
+
::
|
|
613
|
+
|
|
614
|
+
sage: w = Word(iter("abbabaab"), length='finite', caching=False); w
|
|
615
|
+
word: abbabaab
|
|
616
|
+
sage: isinstance(w, sage.combinat.words.word_infinite_datatypes.WordDatatype_iter)
|
|
617
|
+
True
|
|
618
|
+
sage: w.length()
|
|
619
|
+
8
|
|
620
|
+
sage: w = Word(iter("abbabaab"), length=8, caching=False); w
|
|
621
|
+
word: abbabaab
|
|
622
|
+
sage: isinstance(w, sage.combinat.words.word_infinite_datatypes.WordDatatype_iter)
|
|
623
|
+
True
|
|
624
|
+
sage: w.length()
|
|
625
|
+
8
|
|
626
|
+
"""
|
|
627
|
+
if length is Infinity:
|
|
628
|
+
self._len = Infinity
|
|
629
|
+
self._data = iter
|
|
630
|
+
elif length is None or length == 'unknown' or length == 'finite':
|
|
631
|
+
self._len = None
|
|
632
|
+
self._data = iter
|
|
633
|
+
else:
|
|
634
|
+
self._len = length
|
|
635
|
+
self._data = itertools.islice(iter, int(length))
|
|
636
|
+
|
|
637
|
+
self._parent = parent
|
|
638
|
+
self._hash = None
|
|
639
|
+
|
|
640
|
+
def __iter__(self):
|
|
641
|
+
r"""
|
|
642
|
+
EXAMPLES::
|
|
643
|
+
|
|
644
|
+
sage: it = iter(range(9))
|
|
645
|
+
sage: w = Word(it, length='unknown', caching=False)
|
|
646
|
+
sage: [a for a in iter(w)]
|
|
647
|
+
[0, 1, 2, 3, 4, 5, 6, 7, 8]
|
|
648
|
+
"""
|
|
649
|
+
self._data, it = itertools.tee(self._data)
|
|
650
|
+
counter = 0
|
|
651
|
+
for a in it:
|
|
652
|
+
counter += 1
|
|
653
|
+
yield a
|
|
654
|
+
# If we reach this point, then we know the length of the word,
|
|
655
|
+
# and that the word is finite.
|
|
656
|
+
if self._len is None:
|
|
657
|
+
self._len = counter
|
|
658
|
+
parent = self.parent().factors()
|
|
659
|
+
self.__class__ = parent._element_classes['iter']
|
|
660
|
+
self._parent = parent
|
|
661
|
+
|
|
662
|
+
def __getitem__(self, key):
|
|
663
|
+
r"""
|
|
664
|
+
There is some support for negative stops and steps, but if the
|
|
665
|
+
iterator does not terminate, then neither will this method.
|
|
666
|
+
|
|
667
|
+
TESTS FOR FINITE WORDS.
|
|
668
|
+
|
|
669
|
+
A word from an iterator without a length specified::
|
|
670
|
+
|
|
671
|
+
sage: w = Word(iter("abbabaabbaab"), length='finite', caching=False); w
|
|
672
|
+
word: abbabaabbaab
|
|
673
|
+
|
|
674
|
+
Test getitems with indexes::
|
|
675
|
+
|
|
676
|
+
sage: w[0]
|
|
677
|
+
'a'
|
|
678
|
+
sage: w[4]
|
|
679
|
+
'b'
|
|
680
|
+
sage: w[-1]
|
|
681
|
+
'b'
|
|
682
|
+
sage: w[-2]
|
|
683
|
+
'a'
|
|
684
|
+
sage: [w[i] for i in range(12)]
|
|
685
|
+
['a', 'b', 'b', 'a', 'b', 'a', 'a', 'b', 'b', 'a', 'a', 'b']
|
|
686
|
+
|
|
687
|
+
The previous command exhausts the iterator, so we now know the
|
|
688
|
+
length of the word::
|
|
689
|
+
|
|
690
|
+
sage: w.length()
|
|
691
|
+
12
|
|
692
|
+
|
|
693
|
+
Slicing::
|
|
694
|
+
|
|
695
|
+
sage: w[:]
|
|
696
|
+
word: abbabaabbaab
|
|
697
|
+
|
|
698
|
+
Suffixes::
|
|
699
|
+
|
|
700
|
+
sage: w[0:]
|
|
701
|
+
word: abbabaabbaab
|
|
702
|
+
sage: w[1:]
|
|
703
|
+
word: bbabaabbaab
|
|
704
|
+
|
|
705
|
+
Prefixes::
|
|
706
|
+
|
|
707
|
+
sage: w[:0]
|
|
708
|
+
word:
|
|
709
|
+
sage: w[:5]
|
|
710
|
+
word: abbab
|
|
711
|
+
|
|
712
|
+
With positive steps::
|
|
713
|
+
|
|
714
|
+
sage: w[::2]
|
|
715
|
+
word: abbaba
|
|
716
|
+
|
|
717
|
+
With a negative start position, the word must be expanded! ::
|
|
718
|
+
|
|
719
|
+
sage: w[-2:]
|
|
720
|
+
word: ab
|
|
721
|
+
sage: w[-20:]
|
|
722
|
+
word: abbabaabbaab
|
|
723
|
+
|
|
724
|
+
With a negative stop position, the word must be expanded! ::
|
|
725
|
+
|
|
726
|
+
sage: w[:-1]
|
|
727
|
+
word: abbabaabbaa
|
|
728
|
+
sage: w[:-10]
|
|
729
|
+
word: ab
|
|
730
|
+
|
|
731
|
+
With a negative step, the word may or may not be expanded;
|
|
732
|
+
it depends on the slice::
|
|
733
|
+
|
|
734
|
+
sage: w[::-2]
|
|
735
|
+
word: babaab
|
|
736
|
+
sage: w[10:1:-2]
|
|
737
|
+
word: ababb
|
|
738
|
+
sage: list(w[10:1:-2])
|
|
739
|
+
['a', 'b', 'a', 'b', 'b']
|
|
740
|
+
sage: list(w[20:1:-2])
|
|
741
|
+
['b', 'a', 'b', 'a', 'a']
|
|
742
|
+
sage: list(w[10:1:-3])
|
|
743
|
+
['a', 'b', 'b']
|
|
744
|
+
sage: w[::0]
|
|
745
|
+
Traceback (most recent call last):
|
|
746
|
+
...
|
|
747
|
+
ValueError: Step for islice() must be a positive integer or None.
|
|
748
|
+
|
|
749
|
+
TESTS FOR INFINITE WORDS::
|
|
750
|
+
|
|
751
|
+
sage: from itertools import count
|
|
752
|
+
sage: c = Word(count()); c
|
|
753
|
+
word: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,...
|
|
754
|
+
|
|
755
|
+
Test getitems with indexes::
|
|
756
|
+
|
|
757
|
+
sage: c[0]
|
|
758
|
+
0
|
|
759
|
+
sage: c[4]
|
|
760
|
+
4
|
|
761
|
+
sage: [c[i] for i in range(12)]
|
|
762
|
+
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
|
763
|
+
sage: c[-1]
|
|
764
|
+
Traceback (most recent call last):
|
|
765
|
+
...
|
|
766
|
+
IndexError: cannot use negative indices with words of unknown length
|
|
767
|
+
sage: c[-2]
|
|
768
|
+
Traceback (most recent call last):
|
|
769
|
+
...
|
|
770
|
+
IndexError: cannot use negative indices with words of unknown length
|
|
771
|
+
|
|
772
|
+
Slicing::
|
|
773
|
+
|
|
774
|
+
sage: c[:]
|
|
775
|
+
word: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,...
|
|
776
|
+
|
|
777
|
+
Prefixes::
|
|
778
|
+
|
|
779
|
+
sage: c[:0]
|
|
780
|
+
word:
|
|
781
|
+
sage: c[:5]
|
|
782
|
+
word: 01234
|
|
783
|
+
|
|
784
|
+
Suffixes::
|
|
785
|
+
|
|
786
|
+
sage: c[0:]
|
|
787
|
+
word: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,...
|
|
788
|
+
sage: c[1:]
|
|
789
|
+
word: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,...
|
|
790
|
+
|
|
791
|
+
With positive steps::
|
|
792
|
+
|
|
793
|
+
sage: c[::2]
|
|
794
|
+
word: 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,...
|
|
795
|
+
|
|
796
|
+
Cannot have negative start or stop positions::
|
|
797
|
+
|
|
798
|
+
sage: c[-2:]
|
|
799
|
+
Traceback (most recent call last):
|
|
800
|
+
...
|
|
801
|
+
ValueError: for infinite words, start and stop values cannot be negative
|
|
802
|
+
sage: c[-20:]
|
|
803
|
+
Traceback (most recent call last):
|
|
804
|
+
...
|
|
805
|
+
ValueError: for infinite words, start and stop values cannot be negative
|
|
806
|
+
sage: c[:-1]
|
|
807
|
+
Traceback (most recent call last):
|
|
808
|
+
...
|
|
809
|
+
ValueError: for infinite words, start and stop values cannot be negative
|
|
810
|
+
sage: c[:-10]
|
|
811
|
+
Traceback (most recent call last):
|
|
812
|
+
...
|
|
813
|
+
ValueError: for infinite words, start and stop values cannot be negative
|
|
814
|
+
|
|
815
|
+
With a negative step, start must be nonnegative::
|
|
816
|
+
|
|
817
|
+
sage: c[10:1:-2]
|
|
818
|
+
word: 10,8,6,4,2
|
|
819
|
+
sage: c[10:1:-3]
|
|
820
|
+
word: 10,7,4
|
|
821
|
+
sage: c[20:1:-3]
|
|
822
|
+
word: 20,17,14,11,8,5,2
|
|
823
|
+
sage: c[::-2]
|
|
824
|
+
Traceback (most recent call last):
|
|
825
|
+
...
|
|
826
|
+
ValueError: start value must be nonnegative for negative step values
|
|
827
|
+
sage: c[::0]
|
|
828
|
+
Traceback (most recent call last):
|
|
829
|
+
...
|
|
830
|
+
ValueError: Step for islice() must be a positive integer or None.
|
|
831
|
+
"""
|
|
832
|
+
if isinstance(key, slice):
|
|
833
|
+
if self._len is Infinity or self._len is None:
|
|
834
|
+
if key.start is not None and key.start < 0 or \
|
|
835
|
+
key.stop is not None and key.stop < 0:
|
|
836
|
+
raise ValueError("for infinite words, start and stop values cannot be negative")
|
|
837
|
+
step = 1 if key.step is None else int(key.step)
|
|
838
|
+
if step >= 0:
|
|
839
|
+
start = 0 if key.start is None else int(key.start)
|
|
840
|
+
if key.stop is None:
|
|
841
|
+
length = Infinity
|
|
842
|
+
stop = None
|
|
843
|
+
else: # key.stop > 0
|
|
844
|
+
length = int(max(0, ceil((key.stop-start)/float(step))))
|
|
845
|
+
stop = int(key.stop)
|
|
846
|
+
data = itertools.islice(self, start, stop, step)
|
|
847
|
+
else:
|
|
848
|
+
if key.start is None or key.start < 0:
|
|
849
|
+
raise ValueError("start value must be nonnegative for negative step values")
|
|
850
|
+
start = int(key.start)
|
|
851
|
+
stop = 0 if key.stop is None else int(key.stop)
|
|
852
|
+
length = int(max(0, ceil((stop-start)/float(step))))
|
|
853
|
+
data = list(itertools.islice(self, start+1))[key]
|
|
854
|
+
|
|
855
|
+
if length is None or length is Infinity:
|
|
856
|
+
return self._parent(data)
|
|
857
|
+
else:
|
|
858
|
+
return self._parent.factors()(data, length=length)
|
|
859
|
+
else:
|
|
860
|
+
start = 0 if key.start is None else int(key.start)
|
|
861
|
+
stop = int(self._len) if key.stop is None else int(key.stop)
|
|
862
|
+
step = 1 if key.step is None else int(key.step)
|
|
863
|
+
# If either key.start or key.stop is negative,
|
|
864
|
+
# then we need to expand the word.
|
|
865
|
+
if start < 0 or (stop is not None and stop < 0):
|
|
866
|
+
data = list(self)[key]
|
|
867
|
+
length = None
|
|
868
|
+
# If key.step is negative, then we need to expand a prefix.
|
|
869
|
+
elif step < 0:
|
|
870
|
+
if key.start is None:
|
|
871
|
+
data = list(self)[key]
|
|
872
|
+
else:
|
|
873
|
+
data = list(itertools.islice(self, int(start+1)))[start:stop:step]
|
|
874
|
+
length = None
|
|
875
|
+
else: # start >= 0, step >= 1, stop >= 0 or None
|
|
876
|
+
data = itertools.islice(self, start, stop, step)
|
|
877
|
+
length = "unknown" if stop is None else int(max(0, ((stop-start)/float(step))))
|
|
878
|
+
|
|
879
|
+
return self._parent.factors()(data, length=length)
|
|
880
|
+
else:
|
|
881
|
+
if key < 0:
|
|
882
|
+
if self._len is Infinity:
|
|
883
|
+
raise IndexError("cannot use negative indices with infinite words")
|
|
884
|
+
elif self._len is None:
|
|
885
|
+
raise IndexError("cannot use negative indices with words of unknown length")
|
|
886
|
+
else:
|
|
887
|
+
key = self.length() + key
|
|
888
|
+
it = iter(self)
|
|
889
|
+
a = next(it)
|
|
890
|
+
counter = 0
|
|
891
|
+
while counter < key:
|
|
892
|
+
try:
|
|
893
|
+
a = next(it)
|
|
894
|
+
counter += 1
|
|
895
|
+
except StopIteration:
|
|
896
|
+
raise IndexError("word index out of range")
|
|
897
|
+
return a
|
|
898
|
+
|
|
899
|
+
def __reduce__(self):
|
|
900
|
+
r"""
|
|
901
|
+
If finite, it expands the iterator in a list.
|
|
902
|
+
|
|
903
|
+
EXAMPLES::
|
|
904
|
+
|
|
905
|
+
sage: w = Word(iter('ab'), caching=False, length='unknown')
|
|
906
|
+
sage: w.__reduce__()
|
|
907
|
+
(Finite words over Set of Python objects of class 'object', (['a', 'b'],))
|
|
908
|
+
|
|
909
|
+
::
|
|
910
|
+
|
|
911
|
+
sage: w = Word(iter('ab'*10000), caching=False, length='unknown')
|
|
912
|
+
sage: w.__reduce__()
|
|
913
|
+
(Finite and infinite words over Set of Python objects of class 'object', (<generator object ...__iter__ at ...>, 'iter', False))
|
|
914
|
+
"""
|
|
915
|
+
if self.is_finite():
|
|
916
|
+
return self._parent, (list(self),)
|
|
917
|
+
return self._parent, (iter(self), 'iter', False)
|
|
918
|
+
|
|
919
|
+
|
|
920
|
+
class WordDatatype_iter_with_caching(WordDatatype_iter):
|
|
921
|
+
def __init__(self, parent, iter, length=None):
|
|
922
|
+
r"""
|
|
923
|
+
INPUT:
|
|
924
|
+
|
|
925
|
+
- ``parent`` -- a parent
|
|
926
|
+
- ``iter`` -- an iterator
|
|
927
|
+
- ``length`` -- (default: ``None``) the length of the word
|
|
928
|
+
|
|
929
|
+
EXAMPLES::
|
|
930
|
+
|
|
931
|
+
sage: import itertools
|
|
932
|
+
sage: Word(itertools.cycle("abbabaab"))
|
|
933
|
+
word: abbabaababbabaababbabaababbabaababbabaab...
|
|
934
|
+
sage: w = Word(iter("abbabaab"), length='finite'); w
|
|
935
|
+
word: abbabaab
|
|
936
|
+
sage: w.length()
|
|
937
|
+
8
|
|
938
|
+
sage: w = Word(iter("abbabaab"), length='unknown'); w
|
|
939
|
+
word: abbabaab
|
|
940
|
+
sage: w.length()
|
|
941
|
+
8
|
|
942
|
+
sage: list(w)
|
|
943
|
+
['a', 'b', 'b', 'a', 'b', 'a', 'a', 'b']
|
|
944
|
+
sage: w.length()
|
|
945
|
+
8
|
|
946
|
+
sage: w = Word(iter("abbabaab"), length=8)
|
|
947
|
+
sage: w._len
|
|
948
|
+
8
|
|
949
|
+
"""
|
|
950
|
+
super().__init__(parent, iter, length)
|
|
951
|
+
# we use self._data for returning an iterator through __iter__;
|
|
952
|
+
# we use self._gen for caching
|
|
953
|
+
self._data, self._gen = itertools.tee(self._data)
|
|
954
|
+
self._list = []
|
|
955
|
+
self._last_index = -1
|
|
956
|
+
|
|
957
|
+
def __iter__(self):
|
|
958
|
+
r"""
|
|
959
|
+
Iterate through the letters of the word, in order.
|
|
960
|
+
|
|
961
|
+
EXAMPLES::
|
|
962
|
+
|
|
963
|
+
sage: w = Word(iter([0,1,0,0,1,0,1,0,0,1,0,1,0]))
|
|
964
|
+
sage: it = iter(w)
|
|
965
|
+
sage: [next(it) for _ in range(10)]
|
|
966
|
+
[0, 1, 0, 0, 1, 0, 1, 0, 0, 1]
|
|
967
|
+
"""
|
|
968
|
+
# first iterator through the cached values
|
|
969
|
+
# then continue through the self._gen
|
|
970
|
+
for a in self._list:
|
|
971
|
+
yield a
|
|
972
|
+
for a in self._gen:
|
|
973
|
+
self._list.append(a)
|
|
974
|
+
self._last_index += 1
|
|
975
|
+
yield a
|
|
976
|
+
# If we reach this point, then we know the length of the word,
|
|
977
|
+
# and that the word is finite.
|
|
978
|
+
if self._len is None:
|
|
979
|
+
self._len = len(self._list)
|
|
980
|
+
parent = self.parent().factors()
|
|
981
|
+
self.__class__ = parent._element_classes['iter_with_caching']
|
|
982
|
+
self._parent = parent
|
|
983
|
+
|
|
984
|
+
def __getitem__(self, key):
|
|
985
|
+
r"""
|
|
986
|
+
There is some support for negative stops and steps, but if the
|
|
987
|
+
iterator does not terminate, then neither will this method.
|
|
988
|
+
|
|
989
|
+
TESTS FOR FINITE WORDS.
|
|
990
|
+
|
|
991
|
+
A word from an iterator without a length specified::
|
|
992
|
+
|
|
993
|
+
sage: w = Word(iter("abbabaabbaab"), length='unknown'); w
|
|
994
|
+
word: abbabaabbaab
|
|
995
|
+
|
|
996
|
+
Test getitems with indexes::
|
|
997
|
+
|
|
998
|
+
sage: w[0]
|
|
999
|
+
'a'
|
|
1000
|
+
sage: w[4]
|
|
1001
|
+
'b'
|
|
1002
|
+
sage: w[-1]
|
|
1003
|
+
'b'
|
|
1004
|
+
sage: w[-2]
|
|
1005
|
+
'a'
|
|
1006
|
+
sage: [w[i] for i in range(12)]
|
|
1007
|
+
['a', 'b', 'b', 'a', 'b', 'a', 'a', 'b', 'b', 'a', 'a', 'b']
|
|
1008
|
+
|
|
1009
|
+
Copying via slicing::
|
|
1010
|
+
|
|
1011
|
+
sage: w = Word(iter("abbabaabbaab")); w
|
|
1012
|
+
word: abbabaabbaab
|
|
1013
|
+
sage: w[:]
|
|
1014
|
+
word: abbabaabbaab
|
|
1015
|
+
|
|
1016
|
+
Suffixes::
|
|
1017
|
+
|
|
1018
|
+
sage: w = Word(iter("abbabaabbaab"), length='finite')
|
|
1019
|
+
sage: w[0:]
|
|
1020
|
+
word: abbabaabbaab
|
|
1021
|
+
sage: w = Word(iter("abbabaabbaab"), length='finite')
|
|
1022
|
+
sage: w[1:]
|
|
1023
|
+
word: bbabaabbaab
|
|
1024
|
+
|
|
1025
|
+
Prefixes::
|
|
1026
|
+
|
|
1027
|
+
sage: w = Word(iter("abbabaabbaab"), length='finite')
|
|
1028
|
+
sage: w[:0]
|
|
1029
|
+
word:
|
|
1030
|
+
sage: w = Word(iter("abbabaabbaab"), length='finite')
|
|
1031
|
+
sage: w[:5]
|
|
1032
|
+
word: abbab
|
|
1033
|
+
|
|
1034
|
+
With positive steps::
|
|
1035
|
+
|
|
1036
|
+
sage: w = Word(iter("abbabaabbaab"), length='unknown')
|
|
1037
|
+
sage: w[::2]
|
|
1038
|
+
word: abbaba
|
|
1039
|
+
|
|
1040
|
+
With a negative start position, the word must be expanded! ::
|
|
1041
|
+
|
|
1042
|
+
sage: w = Word(iter("abbabaabbaab"), length='finite')
|
|
1043
|
+
sage: w[-2:]
|
|
1044
|
+
word: ab
|
|
1045
|
+
sage: w = Word(iter("abbabaabbaab"), length='finite')
|
|
1046
|
+
sage: w[-20:]
|
|
1047
|
+
word: abbabaabbaab
|
|
1048
|
+
|
|
1049
|
+
With a negative stop position, the word must be expanded! ::
|
|
1050
|
+
|
|
1051
|
+
sage: w = Word(iter("abbabaabbaab"), length='finite')
|
|
1052
|
+
sage: w[:-1]
|
|
1053
|
+
word: abbabaabbaa
|
|
1054
|
+
sage: w = Word(iter("abbabaabbaab"), length='unknown')
|
|
1055
|
+
sage: w[:-10]
|
|
1056
|
+
word: ab
|
|
1057
|
+
|
|
1058
|
+
With a negative step, the word may or may not be expanded;
|
|
1059
|
+
it depends on the slice::
|
|
1060
|
+
|
|
1061
|
+
sage: w = Word(iter("abbabaabbaab"), length='finite')
|
|
1062
|
+
sage: w[::-2]
|
|
1063
|
+
word: babaab
|
|
1064
|
+
sage: w = Word(iter("abbabaabbaab"))
|
|
1065
|
+
sage: w[10:1:-2]
|
|
1066
|
+
word: ababb
|
|
1067
|
+
sage: list(w[10:1:-2])
|
|
1068
|
+
['a', 'b', 'a', 'b', 'b']
|
|
1069
|
+
sage: list(w[20:1:-2])
|
|
1070
|
+
['b', 'a', 'b', 'a', 'a']
|
|
1071
|
+
sage: list(w[10:1:-3])
|
|
1072
|
+
['a', 'b', 'b']
|
|
1073
|
+
sage: w = Word(iter("abbabaabbaab"))
|
|
1074
|
+
sage: w[::0]
|
|
1075
|
+
Traceback (most recent call last):
|
|
1076
|
+
...
|
|
1077
|
+
ValueError: Step for islice() must be a positive integer or None.
|
|
1078
|
+
|
|
1079
|
+
TESTS FOR INFINITE WORDS::
|
|
1080
|
+
|
|
1081
|
+
sage: from itertools import count
|
|
1082
|
+
sage: c = Word(count()); c
|
|
1083
|
+
word: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,...
|
|
1084
|
+
|
|
1085
|
+
Test getitems with indexes::
|
|
1086
|
+
|
|
1087
|
+
sage: c[0]
|
|
1088
|
+
0
|
|
1089
|
+
sage: c[4]
|
|
1090
|
+
4
|
|
1091
|
+
sage: [c[i] for i in range(12)]
|
|
1092
|
+
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
|
1093
|
+
sage: c[-1]
|
|
1094
|
+
Traceback (most recent call last):
|
|
1095
|
+
...
|
|
1096
|
+
IndexError: cannot use negative indices with words of unknown length
|
|
1097
|
+
sage: c[-2]
|
|
1098
|
+
Traceback (most recent call last):
|
|
1099
|
+
...
|
|
1100
|
+
IndexError: cannot use negative indices with words of unknown length
|
|
1101
|
+
|
|
1102
|
+
Slicing::
|
|
1103
|
+
|
|
1104
|
+
sage: c[:]
|
|
1105
|
+
word: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,...
|
|
1106
|
+
|
|
1107
|
+
Prefixes::
|
|
1108
|
+
|
|
1109
|
+
sage: c[:0]
|
|
1110
|
+
word:
|
|
1111
|
+
sage: c[:5]
|
|
1112
|
+
word: 01234
|
|
1113
|
+
|
|
1114
|
+
Suffixes::
|
|
1115
|
+
|
|
1116
|
+
sage: c[0:]
|
|
1117
|
+
word: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,...
|
|
1118
|
+
sage: c[1:]
|
|
1119
|
+
word: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,...
|
|
1120
|
+
|
|
1121
|
+
With positive steps::
|
|
1122
|
+
|
|
1123
|
+
sage: c[::2]
|
|
1124
|
+
word: 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,...
|
|
1125
|
+
|
|
1126
|
+
Cannot have negative start or stop positions::
|
|
1127
|
+
|
|
1128
|
+
sage: c[-2:]
|
|
1129
|
+
Traceback (most recent call last):
|
|
1130
|
+
...
|
|
1131
|
+
ValueError: for infinite words, start and stop values cannot be negative
|
|
1132
|
+
sage: c[-20:]
|
|
1133
|
+
Traceback (most recent call last):
|
|
1134
|
+
...
|
|
1135
|
+
ValueError: for infinite words, start and stop values cannot be negative
|
|
1136
|
+
sage: c[:-1]
|
|
1137
|
+
Traceback (most recent call last):
|
|
1138
|
+
...
|
|
1139
|
+
ValueError: for infinite words, start and stop values cannot be negative
|
|
1140
|
+
sage: c[:-10]
|
|
1141
|
+
Traceback (most recent call last):
|
|
1142
|
+
...
|
|
1143
|
+
ValueError: for infinite words, start and stop values cannot be negative
|
|
1144
|
+
|
|
1145
|
+
With a negative step, start must be nonnegative::
|
|
1146
|
+
|
|
1147
|
+
sage: c[10:1:-2]
|
|
1148
|
+
word: 10,8,6,4,2
|
|
1149
|
+
sage: c[10:1:-3]
|
|
1150
|
+
word: 10,7,4
|
|
1151
|
+
sage: c[20:1:-3]
|
|
1152
|
+
word: 20,17,14,11,8,5,2
|
|
1153
|
+
sage: c[::-2]
|
|
1154
|
+
Traceback (most recent call last):
|
|
1155
|
+
...
|
|
1156
|
+
ValueError: start value must be nonnegative for negative step values
|
|
1157
|
+
sage: c[::0]
|
|
1158
|
+
Traceback (most recent call last):
|
|
1159
|
+
...
|
|
1160
|
+
ValueError: Step for islice() must be a positive integer or None.
|
|
1161
|
+
"""
|
|
1162
|
+
if isinstance(key, slice):
|
|
1163
|
+
return super().__getitem__(key)
|
|
1164
|
+
else:
|
|
1165
|
+
if key < 0:
|
|
1166
|
+
return super().__getitem__(key)
|
|
1167
|
+
else:
|
|
1168
|
+
while self._last_index < key:
|
|
1169
|
+
try:
|
|
1170
|
+
self._list.append(next(self._gen))
|
|
1171
|
+
self._last_index += 1
|
|
1172
|
+
except StopIteration:
|
|
1173
|
+
raise IndexError("word index out of range")
|
|
1174
|
+
return self._list[key]
|
|
1175
|
+
|
|
1176
|
+
def __reduce__(self):
|
|
1177
|
+
r"""
|
|
1178
|
+
If finite, it expands the iterator in a list.
|
|
1179
|
+
|
|
1180
|
+
EXAMPLES::
|
|
1181
|
+
|
|
1182
|
+
sage: w = Word(iter('ab'), caching=True, length='unknown')
|
|
1183
|
+
sage: w.__reduce__()
|
|
1184
|
+
(Finite words over Set of Python objects of class 'object', (['a', 'b'],))
|
|
1185
|
+
|
|
1186
|
+
::
|
|
1187
|
+
|
|
1188
|
+
sage: w = Word(iter('ab'*10000), caching=True, length='unknown')
|
|
1189
|
+
sage: w.__reduce__()
|
|
1190
|
+
(Finite and infinite words over Set of Python objects of class 'object',
|
|
1191
|
+
(<generator object ...__iter__ at ...>, 'iter', True))
|
|
1192
|
+
"""
|
|
1193
|
+
if self.is_finite():
|
|
1194
|
+
return self._parent, (list(self),)
|
|
1195
|
+
else:
|
|
1196
|
+
return self._parent, (iter(self), 'iter', True)
|
|
1197
|
+
|
|
1198
|
+
def flush(self):
|
|
1199
|
+
r"""
|
|
1200
|
+
Delete the cached values.
|
|
1201
|
+
|
|
1202
|
+
EXAMPLES::
|
|
1203
|
+
|
|
1204
|
+
sage: from itertools import count
|
|
1205
|
+
sage: w = Word(count())
|
|
1206
|
+
sage: w._last_index, len(w._list)
|
|
1207
|
+
(39, 40)
|
|
1208
|
+
sage: w[43]
|
|
1209
|
+
43
|
|
1210
|
+
sage: w._last_index, len(w._list)
|
|
1211
|
+
(43, 44)
|
|
1212
|
+
sage: w.flush()
|
|
1213
|
+
sage: w._last_index, w._list
|
|
1214
|
+
(-1, [])
|
|
1215
|
+
"""
|
|
1216
|
+
self._gen = iter(self)
|
|
1217
|
+
self._list = []
|
|
1218
|
+
self._last_index = -1
|