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.
Files changed (400) hide show
  1. passagemath_combinat/__init__.py +3 -0
  2. passagemath_combinat-10.6.42.dist-info/METADATA +160 -0
  3. passagemath_combinat-10.6.42.dist-info/RECORD +400 -0
  4. passagemath_combinat-10.6.42.dist-info/WHEEL +5 -0
  5. passagemath_combinat-10.6.42.dist-info/top_level.txt +3 -0
  6. passagemath_combinat.libs/libgmp-0e7fc84e.so.10.5.0 +0 -0
  7. passagemath_combinat.libs/libsymmetrica-81fe8739.so.3.0.0 +0 -0
  8. sage/algebras/affine_nil_temperley_lieb.py +263 -0
  9. sage/algebras/all.py +24 -0
  10. sage/algebras/all__sagemath_combinat.py +35 -0
  11. sage/algebras/askey_wilson.py +935 -0
  12. sage/algebras/associated_graded.py +345 -0
  13. sage/algebras/cellular_basis.py +350 -0
  14. sage/algebras/cluster_algebra.py +2766 -0
  15. sage/algebras/down_up_algebra.py +860 -0
  16. sage/algebras/free_algebra.py +1698 -0
  17. sage/algebras/free_algebra_element.py +345 -0
  18. sage/algebras/free_algebra_quotient.py +405 -0
  19. sage/algebras/free_algebra_quotient_element.py +295 -0
  20. sage/algebras/free_zinbiel_algebra.py +885 -0
  21. sage/algebras/hall_algebra.py +783 -0
  22. sage/algebras/hecke_algebras/all.py +4 -0
  23. sage/algebras/hecke_algebras/ariki_koike_algebra.py +1796 -0
  24. sage/algebras/hecke_algebras/ariki_koike_specht_modules.py +475 -0
  25. sage/algebras/hecke_algebras/cubic_hecke_algebra.py +3520 -0
  26. sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +1473 -0
  27. sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py +1079 -0
  28. sage/algebras/iwahori_hecke_algebra.py +3095 -0
  29. sage/algebras/jordan_algebra.py +1773 -0
  30. sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py +113 -0
  31. sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py +156 -0
  32. sage/algebras/lie_conformal_algebras/all.py +18 -0
  33. sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py +134 -0
  34. sage/algebras/lie_conformal_algebras/examples.py +43 -0
  35. sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py +131 -0
  36. sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py +139 -0
  37. sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py +174 -0
  38. sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +167 -0
  39. sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py +107 -0
  40. sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py +135 -0
  41. sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +353 -0
  42. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py +236 -0
  43. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py +78 -0
  44. sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +328 -0
  45. sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py +117 -0
  46. sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py +86 -0
  47. sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py +82 -0
  48. sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py +205 -0
  49. sage/algebras/nil_coxeter_algebra.py +191 -0
  50. sage/algebras/q_commuting_polynomials.py +673 -0
  51. sage/algebras/q_system.py +608 -0
  52. sage/algebras/quantum_clifford.py +959 -0
  53. sage/algebras/quantum_groups/ace_quantum_onsager.py +693 -0
  54. sage/algebras/quantum_groups/all.py +9 -0
  55. sage/algebras/quantum_groups/fock_space.py +2219 -0
  56. sage/algebras/quantum_groups/q_numbers.py +207 -0
  57. sage/algebras/quantum_groups/quantum_group_gap.py +2695 -0
  58. sage/algebras/quantum_groups/representations.py +591 -0
  59. sage/algebras/quantum_matrix_coordinate_algebra.py +1006 -0
  60. sage/algebras/quantum_oscillator.py +623 -0
  61. sage/algebras/quaternion_algebra.py +20 -0
  62. sage/algebras/quaternion_algebra_element.py +55 -0
  63. sage/algebras/rational_cherednik_algebra.py +525 -0
  64. sage/algebras/schur_algebra.py +670 -0
  65. sage/algebras/shuffle_algebra.py +1011 -0
  66. sage/algebras/splitting_algebra.py +779 -0
  67. sage/algebras/tensor_algebra.py +709 -0
  68. sage/algebras/yangian.py +1082 -0
  69. sage/algebras/yokonuma_hecke_algebra.py +1018 -0
  70. sage/all__sagemath_combinat.py +35 -0
  71. sage/combinat/SJT.py +255 -0
  72. sage/combinat/affine_permutation.py +2405 -0
  73. sage/combinat/algebraic_combinatorics.py +55 -0
  74. sage/combinat/all.py +53 -0
  75. sage/combinat/all__sagemath_combinat.py +195 -0
  76. sage/combinat/alternating_sign_matrix.py +2063 -0
  77. sage/combinat/baxter_permutations.py +346 -0
  78. sage/combinat/bijectionist.py +3220 -0
  79. sage/combinat/binary_recurrence_sequences.py +1180 -0
  80. sage/combinat/blob_algebra.py +685 -0
  81. sage/combinat/catalog_partitions.py +27 -0
  82. sage/combinat/chas/all.py +23 -0
  83. sage/combinat/chas/fsym.py +1180 -0
  84. sage/combinat/chas/wqsym.py +2601 -0
  85. sage/combinat/cluster_complex.py +326 -0
  86. sage/combinat/colored_permutations.py +2039 -0
  87. sage/combinat/colored_permutations_representations.py +964 -0
  88. sage/combinat/composition_signed.py +142 -0
  89. sage/combinat/composition_tableau.py +855 -0
  90. sage/combinat/constellation.py +1729 -0
  91. sage/combinat/core.py +751 -0
  92. sage/combinat/counting.py +12 -0
  93. sage/combinat/crystals/affine.py +742 -0
  94. sage/combinat/crystals/affine_factorization.py +518 -0
  95. sage/combinat/crystals/affinization.py +331 -0
  96. sage/combinat/crystals/alcove_path.py +2013 -0
  97. sage/combinat/crystals/all.py +22 -0
  98. sage/combinat/crystals/bkk_crystals.py +141 -0
  99. sage/combinat/crystals/catalog.py +115 -0
  100. sage/combinat/crystals/catalog_elementary_crystals.py +18 -0
  101. sage/combinat/crystals/catalog_infinity_crystals.py +33 -0
  102. sage/combinat/crystals/catalog_kirillov_reshetikhin.py +18 -0
  103. sage/combinat/crystals/crystals.py +257 -0
  104. sage/combinat/crystals/direct_sum.py +260 -0
  105. sage/combinat/crystals/elementary_crystals.py +1251 -0
  106. sage/combinat/crystals/fast_crystals.py +441 -0
  107. sage/combinat/crystals/fully_commutative_stable_grothendieck.py +1205 -0
  108. sage/combinat/crystals/generalized_young_walls.py +1076 -0
  109. sage/combinat/crystals/highest_weight_crystals.py +436 -0
  110. sage/combinat/crystals/induced_structure.py +695 -0
  111. sage/combinat/crystals/infinity_crystals.py +730 -0
  112. sage/combinat/crystals/kac_modules.py +863 -0
  113. sage/combinat/crystals/kirillov_reshetikhin.py +4196 -0
  114. sage/combinat/crystals/kyoto_path_model.py +497 -0
  115. sage/combinat/crystals/letters.cpython-314-x86_64-linux-musl.so +0 -0
  116. sage/combinat/crystals/letters.pxd +79 -0
  117. sage/combinat/crystals/letters.pyx +3056 -0
  118. sage/combinat/crystals/littelmann_path.py +1518 -0
  119. sage/combinat/crystals/monomial_crystals.py +1262 -0
  120. sage/combinat/crystals/multisegments.py +462 -0
  121. sage/combinat/crystals/mv_polytopes.py +467 -0
  122. sage/combinat/crystals/pbw_crystal.py +511 -0
  123. sage/combinat/crystals/pbw_datum.cpython-314-x86_64-linux-musl.so +0 -0
  124. sage/combinat/crystals/pbw_datum.pxd +4 -0
  125. sage/combinat/crystals/pbw_datum.pyx +487 -0
  126. sage/combinat/crystals/polyhedral_realization.py +372 -0
  127. sage/combinat/crystals/spins.cpython-314-x86_64-linux-musl.so +0 -0
  128. sage/combinat/crystals/spins.pxd +21 -0
  129. sage/combinat/crystals/spins.pyx +756 -0
  130. sage/combinat/crystals/star_crystal.py +290 -0
  131. sage/combinat/crystals/subcrystal.py +464 -0
  132. sage/combinat/crystals/tensor_product.py +1177 -0
  133. sage/combinat/crystals/tensor_product_element.cpython-314-x86_64-linux-musl.so +0 -0
  134. sage/combinat/crystals/tensor_product_element.pxd +35 -0
  135. sage/combinat/crystals/tensor_product_element.pyx +1870 -0
  136. sage/combinat/crystals/virtual_crystal.py +420 -0
  137. sage/combinat/cyclic_sieving_phenomenon.py +204 -0
  138. sage/combinat/debruijn_sequence.cpython-314-x86_64-linux-musl.so +0 -0
  139. sage/combinat/debruijn_sequence.pyx +355 -0
  140. sage/combinat/decorated_permutation.py +270 -0
  141. sage/combinat/degree_sequences.cpython-314-x86_64-linux-musl.so +0 -0
  142. sage/combinat/degree_sequences.pyx +588 -0
  143. sage/combinat/derangements.py +527 -0
  144. sage/combinat/descent_algebra.py +1008 -0
  145. sage/combinat/diagram.py +1551 -0
  146. sage/combinat/diagram_algebras.py +5886 -0
  147. sage/combinat/dyck_word.py +4349 -0
  148. sage/combinat/e_one_star.py +1623 -0
  149. sage/combinat/enumerated_sets.py +123 -0
  150. sage/combinat/expnums.cpython-314-x86_64-linux-musl.so +0 -0
  151. sage/combinat/expnums.pyx +148 -0
  152. sage/combinat/fast_vector_partitions.cpython-314-x86_64-linux-musl.so +0 -0
  153. sage/combinat/fast_vector_partitions.pyx +346 -0
  154. sage/combinat/fqsym.py +1977 -0
  155. sage/combinat/free_dendriform_algebra.py +954 -0
  156. sage/combinat/free_prelie_algebra.py +1141 -0
  157. sage/combinat/fully_commutative_elements.py +1077 -0
  158. sage/combinat/fully_packed_loop.py +1523 -0
  159. sage/combinat/gelfand_tsetlin_patterns.py +1409 -0
  160. sage/combinat/gray_codes.py +311 -0
  161. sage/combinat/grossman_larson_algebras.py +667 -0
  162. sage/combinat/growth.py +4352 -0
  163. sage/combinat/hall_polynomial.py +188 -0
  164. sage/combinat/hillman_grassl.py +866 -0
  165. sage/combinat/integer_matrices.py +329 -0
  166. sage/combinat/integer_vectors_mod_permgroup.py +1238 -0
  167. sage/combinat/k_tableau.py +4564 -0
  168. sage/combinat/kazhdan_lusztig.py +215 -0
  169. sage/combinat/key_polynomial.py +885 -0
  170. sage/combinat/knutson_tao_puzzles.py +2286 -0
  171. sage/combinat/lr_tableau.py +311 -0
  172. sage/combinat/matrices/all.py +24 -0
  173. sage/combinat/matrices/hadamard_matrix.py +3790 -0
  174. sage/combinat/matrices/latin.py +2912 -0
  175. sage/combinat/misc.py +401 -0
  176. sage/combinat/multiset_partition_into_sets_ordered.py +3541 -0
  177. sage/combinat/ncsf_qsym/all.py +21 -0
  178. sage/combinat/ncsf_qsym/combinatorics.py +317 -0
  179. sage/combinat/ncsf_qsym/generic_basis_code.py +1427 -0
  180. sage/combinat/ncsf_qsym/ncsf.py +5637 -0
  181. sage/combinat/ncsf_qsym/qsym.py +4053 -0
  182. sage/combinat/ncsf_qsym/tutorial.py +447 -0
  183. sage/combinat/ncsym/all.py +21 -0
  184. sage/combinat/ncsym/bases.py +855 -0
  185. sage/combinat/ncsym/dual.py +593 -0
  186. sage/combinat/ncsym/ncsym.py +2076 -0
  187. sage/combinat/necklace.py +551 -0
  188. sage/combinat/non_decreasing_parking_function.py +634 -0
  189. sage/combinat/nu_dyck_word.py +1474 -0
  190. sage/combinat/output.py +861 -0
  191. sage/combinat/parallelogram_polyomino.py +4326 -0
  192. sage/combinat/parking_functions.py +1602 -0
  193. sage/combinat/partition_algebra.py +1998 -0
  194. sage/combinat/partition_kleshchev.py +1982 -0
  195. sage/combinat/partition_shifting_algebras.py +584 -0
  196. sage/combinat/partition_tuple.py +3114 -0
  197. sage/combinat/path_tableaux/all.py +13 -0
  198. sage/combinat/path_tableaux/catalog.py +29 -0
  199. sage/combinat/path_tableaux/dyck_path.py +380 -0
  200. sage/combinat/path_tableaux/frieze.py +476 -0
  201. sage/combinat/path_tableaux/path_tableau.py +728 -0
  202. sage/combinat/path_tableaux/semistandard.py +510 -0
  203. sage/combinat/perfect_matching.py +779 -0
  204. sage/combinat/plane_partition.py +3300 -0
  205. sage/combinat/q_bernoulli.cpython-314-x86_64-linux-musl.so +0 -0
  206. sage/combinat/q_bernoulli.pyx +128 -0
  207. sage/combinat/quickref.py +81 -0
  208. sage/combinat/recognizable_series.py +2051 -0
  209. sage/combinat/regular_sequence.py +4316 -0
  210. sage/combinat/regular_sequence_bounded.py +543 -0
  211. sage/combinat/restricted_growth.py +81 -0
  212. sage/combinat/ribbon.py +20 -0
  213. sage/combinat/ribbon_shaped_tableau.py +489 -0
  214. sage/combinat/ribbon_tableau.py +1180 -0
  215. sage/combinat/rigged_configurations/all.py +46 -0
  216. sage/combinat/rigged_configurations/bij_abstract_class.py +548 -0
  217. sage/combinat/rigged_configurations/bij_infinity.py +370 -0
  218. sage/combinat/rigged_configurations/bij_type_A.py +163 -0
  219. sage/combinat/rigged_configurations/bij_type_A2_dual.py +338 -0
  220. sage/combinat/rigged_configurations/bij_type_A2_even.py +218 -0
  221. sage/combinat/rigged_configurations/bij_type_A2_odd.py +199 -0
  222. sage/combinat/rigged_configurations/bij_type_B.py +900 -0
  223. sage/combinat/rigged_configurations/bij_type_C.py +267 -0
  224. sage/combinat/rigged_configurations/bij_type_D.py +771 -0
  225. sage/combinat/rigged_configurations/bij_type_D_tri.py +392 -0
  226. sage/combinat/rigged_configurations/bij_type_D_twisted.py +576 -0
  227. sage/combinat/rigged_configurations/bij_type_E67.py +402 -0
  228. sage/combinat/rigged_configurations/bijection.py +143 -0
  229. sage/combinat/rigged_configurations/kleber_tree.py +1475 -0
  230. sage/combinat/rigged_configurations/kr_tableaux.py +1898 -0
  231. sage/combinat/rigged_configurations/rc_crystal.py +461 -0
  232. sage/combinat/rigged_configurations/rc_infinity.py +540 -0
  233. sage/combinat/rigged_configurations/rigged_configuration_element.py +2403 -0
  234. sage/combinat/rigged_configurations/rigged_configurations.py +1918 -0
  235. sage/combinat/rigged_configurations/rigged_partition.cpython-314-x86_64-linux-musl.so +0 -0
  236. sage/combinat/rigged_configurations/rigged_partition.pxd +15 -0
  237. sage/combinat/rigged_configurations/rigged_partition.pyx +680 -0
  238. sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +499 -0
  239. sage/combinat/rigged_configurations/tensor_product_kr_tableaux_element.py +428 -0
  240. sage/combinat/rsk.py +3438 -0
  241. sage/combinat/schubert_polynomial.py +508 -0
  242. sage/combinat/set_partition.py +3318 -0
  243. sage/combinat/set_partition_iterator.cpython-314-x86_64-linux-musl.so +0 -0
  244. sage/combinat/set_partition_iterator.pyx +136 -0
  245. sage/combinat/set_partition_ordered.py +1590 -0
  246. sage/combinat/sf/abreu_nigro.py +346 -0
  247. sage/combinat/sf/all.py +52 -0
  248. sage/combinat/sf/character.py +576 -0
  249. sage/combinat/sf/classical.py +319 -0
  250. sage/combinat/sf/dual.py +996 -0
  251. sage/combinat/sf/elementary.py +549 -0
  252. sage/combinat/sf/hall_littlewood.py +1028 -0
  253. sage/combinat/sf/hecke.py +336 -0
  254. sage/combinat/sf/homogeneous.py +464 -0
  255. sage/combinat/sf/jack.py +1428 -0
  256. sage/combinat/sf/k_dual.py +1458 -0
  257. sage/combinat/sf/kfpoly.py +447 -0
  258. sage/combinat/sf/llt.py +789 -0
  259. sage/combinat/sf/macdonald.py +2019 -0
  260. sage/combinat/sf/monomial.py +525 -0
  261. sage/combinat/sf/multiplicative.py +113 -0
  262. sage/combinat/sf/new_kschur.py +1786 -0
  263. sage/combinat/sf/ns_macdonald.py +964 -0
  264. sage/combinat/sf/orthogonal.py +246 -0
  265. sage/combinat/sf/orthotriang.py +355 -0
  266. sage/combinat/sf/powersum.py +963 -0
  267. sage/combinat/sf/schur.py +880 -0
  268. sage/combinat/sf/sf.py +1653 -0
  269. sage/combinat/sf/sfa.py +7053 -0
  270. sage/combinat/sf/symplectic.py +253 -0
  271. sage/combinat/sf/witt.py +721 -0
  272. sage/combinat/shifted_primed_tableau.py +2735 -0
  273. sage/combinat/shuffle.py +830 -0
  274. sage/combinat/sidon_sets.py +146 -0
  275. sage/combinat/similarity_class_type.py +1721 -0
  276. sage/combinat/sine_gordon.py +618 -0
  277. sage/combinat/six_vertex_model.py +784 -0
  278. sage/combinat/skew_partition.py +2053 -0
  279. sage/combinat/skew_tableau.py +2989 -0
  280. sage/combinat/sloane_functions.py +8935 -0
  281. sage/combinat/specht_module.py +1403 -0
  282. sage/combinat/species/all.py +48 -0
  283. sage/combinat/species/characteristic_species.py +321 -0
  284. sage/combinat/species/composition_species.py +273 -0
  285. sage/combinat/species/cycle_species.py +284 -0
  286. sage/combinat/species/empty_species.py +155 -0
  287. sage/combinat/species/functorial_composition_species.py +148 -0
  288. sage/combinat/species/generating_series.py +673 -0
  289. sage/combinat/species/library.py +148 -0
  290. sage/combinat/species/linear_order_species.py +169 -0
  291. sage/combinat/species/misc.py +83 -0
  292. sage/combinat/species/partition_species.py +290 -0
  293. sage/combinat/species/permutation_species.py +268 -0
  294. sage/combinat/species/product_species.py +423 -0
  295. sage/combinat/species/recursive_species.py +476 -0
  296. sage/combinat/species/set_species.py +192 -0
  297. sage/combinat/species/species.py +820 -0
  298. sage/combinat/species/structure.py +539 -0
  299. sage/combinat/species/subset_species.py +243 -0
  300. sage/combinat/species/sum_species.py +225 -0
  301. sage/combinat/subword.py +564 -0
  302. sage/combinat/subword_complex.py +2122 -0
  303. sage/combinat/subword_complex_c.cpython-314-x86_64-linux-musl.so +0 -0
  304. sage/combinat/subword_complex_c.pyx +119 -0
  305. sage/combinat/super_tableau.py +821 -0
  306. sage/combinat/superpartition.py +1154 -0
  307. sage/combinat/symmetric_group_algebra.py +3774 -0
  308. sage/combinat/symmetric_group_representations.py +1830 -0
  309. sage/combinat/t_sequences.py +877 -0
  310. sage/combinat/tableau.py +9506 -0
  311. sage/combinat/tableau_residues.py +860 -0
  312. sage/combinat/tableau_tuple.py +5353 -0
  313. sage/combinat/tiling.py +2432 -0
  314. sage/combinat/triangles_FHM.py +777 -0
  315. sage/combinat/tutorial.py +1857 -0
  316. sage/combinat/vector_partition.py +337 -0
  317. sage/combinat/words/abstract_word.py +1722 -0
  318. sage/combinat/words/all.py +59 -0
  319. sage/combinat/words/alphabet.py +268 -0
  320. sage/combinat/words/finite_word.py +7201 -0
  321. sage/combinat/words/infinite_word.py +113 -0
  322. sage/combinat/words/lyndon_word.py +652 -0
  323. sage/combinat/words/morphic.py +351 -0
  324. sage/combinat/words/morphism.py +3878 -0
  325. sage/combinat/words/paths.py +2932 -0
  326. sage/combinat/words/shuffle_product.py +278 -0
  327. sage/combinat/words/suffix_trees.py +1873 -0
  328. sage/combinat/words/word.py +769 -0
  329. sage/combinat/words/word_char.cpython-314-x86_64-linux-musl.so +0 -0
  330. sage/combinat/words/word_char.pyx +847 -0
  331. sage/combinat/words/word_datatypes.cpython-314-x86_64-linux-musl.so +0 -0
  332. sage/combinat/words/word_datatypes.pxd +4 -0
  333. sage/combinat/words/word_datatypes.pyx +1067 -0
  334. sage/combinat/words/word_generators.py +2026 -0
  335. sage/combinat/words/word_infinite_datatypes.py +1218 -0
  336. sage/combinat/words/word_options.py +99 -0
  337. sage/combinat/words/words.py +2396 -0
  338. sage/data_structures/all__sagemath_combinat.py +1 -0
  339. sage/databases/all__sagemath_combinat.py +13 -0
  340. sage/databases/findstat.py +4897 -0
  341. sage/databases/oeis.py +2058 -0
  342. sage/databases/sloane.py +393 -0
  343. sage/dynamics/all__sagemath_combinat.py +14 -0
  344. sage/dynamics/cellular_automata/all.py +7 -0
  345. sage/dynamics/cellular_automata/catalog.py +34 -0
  346. sage/dynamics/cellular_automata/elementary.py +612 -0
  347. sage/dynamics/cellular_automata/glca.py +477 -0
  348. sage/dynamics/cellular_automata/solitons.py +1463 -0
  349. sage/dynamics/finite_dynamical_system.py +1249 -0
  350. sage/dynamics/finite_dynamical_system_catalog.py +382 -0
  351. sage/games/all.py +7 -0
  352. sage/games/hexad.py +704 -0
  353. sage/games/quantumino.py +591 -0
  354. sage/games/sudoku.py +889 -0
  355. sage/games/sudoku_backtrack.cpython-314-x86_64-linux-musl.so +0 -0
  356. sage/games/sudoku_backtrack.pyx +189 -0
  357. sage/groups/all__sagemath_combinat.py +1 -0
  358. sage/groups/indexed_free_group.py +489 -0
  359. sage/libs/all__sagemath_combinat.py +6 -0
  360. sage/libs/lrcalc/__init__.py +1 -0
  361. sage/libs/lrcalc/lrcalc.py +525 -0
  362. sage/libs/symmetrica/__init__.py +7 -0
  363. sage/libs/symmetrica/all.py +101 -0
  364. sage/libs/symmetrica/kostka.pxi +168 -0
  365. sage/libs/symmetrica/part.pxi +193 -0
  366. sage/libs/symmetrica/plet.pxi +42 -0
  367. sage/libs/symmetrica/sab.pxi +196 -0
  368. sage/libs/symmetrica/sb.pxi +332 -0
  369. sage/libs/symmetrica/sc.pxi +192 -0
  370. sage/libs/symmetrica/schur.pxi +956 -0
  371. sage/libs/symmetrica/symmetrica.cpython-314-x86_64-linux-musl.so +0 -0
  372. sage/libs/symmetrica/symmetrica.pxi +1172 -0
  373. sage/libs/symmetrica/symmetrica.pyx +39 -0
  374. sage/monoids/all.py +13 -0
  375. sage/monoids/automatic_semigroup.py +1054 -0
  376. sage/monoids/free_abelian_monoid.py +315 -0
  377. sage/monoids/free_abelian_monoid_element.cpython-314-x86_64-linux-musl.so +0 -0
  378. sage/monoids/free_abelian_monoid_element.pxd +16 -0
  379. sage/monoids/free_abelian_monoid_element.pyx +397 -0
  380. sage/monoids/free_monoid.py +335 -0
  381. sage/monoids/free_monoid_element.py +431 -0
  382. sage/monoids/hecke_monoid.py +65 -0
  383. sage/monoids/string_monoid.py +817 -0
  384. sage/monoids/string_monoid_element.py +547 -0
  385. sage/monoids/string_ops.py +143 -0
  386. sage/monoids/trace_monoid.py +972 -0
  387. sage/rings/all__sagemath_combinat.py +2 -0
  388. sage/sat/all.py +4 -0
  389. sage/sat/boolean_polynomials.py +405 -0
  390. sage/sat/converters/__init__.py +6 -0
  391. sage/sat/converters/anf2cnf.py +14 -0
  392. sage/sat/converters/polybori.py +611 -0
  393. sage/sat/solvers/__init__.py +5 -0
  394. sage/sat/solvers/cryptominisat.py +287 -0
  395. sage/sat/solvers/dimacs.py +783 -0
  396. sage/sat/solvers/picosat.py +228 -0
  397. sage/sat/solvers/sat_lp.py +156 -0
  398. sage/sat/solvers/satsolver.cpython-314-x86_64-linux-musl.so +0 -0
  399. sage/sat/solvers/satsolver.pxd +3 -0
  400. sage/sat/solvers/satsolver.pyx +405 -0
@@ -0,0 +1,2396 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ r"""
3
+ Set of words
4
+
5
+ To define a new class of words, please refer to the documentation file:
6
+ sage/combinat/words/notes/word_inheritance_howto.rst
7
+
8
+ AUTHORS:
9
+
10
+ - Franco Saliola (2008-12-17): merged into sage
11
+ - Sebastien Labbe (2008-12-17): merged into sage
12
+ - Arnaud Bergeron (2008-12-17): merged into sage
13
+ - Sebastien Labbe (2009-07-21): Improved morphism iterator (:issue:`6571`).
14
+ - Vincent Delecroix (2015): classes simplifications (:issue:`19619`)
15
+
16
+ EXAMPLES::
17
+
18
+ sage: Words()
19
+ Finite and infinite words over Set of Python objects of class 'object'
20
+ sage: Words(4)
21
+ Finite and infinite words over {1, 2, 3, 4}
22
+ sage: Words(4,5)
23
+ Words of length 5 over {1, 2, 3, 4}
24
+
25
+ sage: FiniteWords('ab')
26
+ Finite words over {'a', 'b'}
27
+ sage: InfiniteWords('natural numbers')
28
+ Infinite words over Non negative integers
29
+ """
30
+ # ****************************************************************************
31
+ # Copyright (C) 2008 Arnaud Bergeron <abergeron@gmail.com>,
32
+ # Sébastien Labbé <slabqc@gmail.com>,
33
+ # Franco Saliola <saliola@gmail.com>
34
+ # 2015 Vincent Delecroix <20100.delecroix@gmail.com>
35
+ #
36
+ # This program is free software: you can redistribute it and/or modify
37
+ # it under the terms of the GNU General Public License as published by
38
+ # the Free Software Foundation, either version 2 of the License, or
39
+ # (at your option) any later version.
40
+ # https://www.gnu.org/licenses/
41
+ # ****************************************************************************
42
+
43
+ import itertools
44
+ from collections.abc import Iterable
45
+
46
+ from sage.misc.cachefunc import cached_method
47
+ from sage.misc.lazy_attribute import lazy_attribute
48
+ from sage.misc.persist import register_unpickle_override
49
+
50
+ from sage.structure.parent import Parent
51
+
52
+ from sage.categories.sets_cat import Sets
53
+
54
+ from sage.combinat.combinat import CombinatorialObject
55
+ from sage.structure.list_clone import ClonableElement
56
+ from sage.combinat.words.alphabet import build_alphabet
57
+
58
+ from sage.rings.infinity import Infinity
59
+ from sage.rings.integer import Integer
60
+ from sage.rings.integer_ring import ZZ
61
+
62
+
63
+ def Words(alphabet=None, length=None, finite=True, infinite=True):
64
+ """
65
+ Return the combinatorial class of words of length k over an alphabet.
66
+
67
+ EXAMPLES::
68
+
69
+ sage: Words()
70
+ Finite and infinite words over Set of Python objects of class 'object'
71
+ sage: Words(length=7)
72
+ Words of length 7 over Set of Python objects of class 'object'
73
+ sage: Words(5)
74
+ Finite and infinite words over {1, 2, 3, 4, 5}
75
+ sage: Words(5, 3)
76
+ Words of length 3 over {1, 2, 3, 4, 5}
77
+ sage: Words(5, infinite=False)
78
+ Finite words over {1, 2, 3, 4, 5}
79
+ sage: Words(5, finite=False)
80
+ Infinite words over {1, 2, 3, 4, 5}
81
+ sage: Words('ab')
82
+ Finite and infinite words over {'a', 'b'}
83
+ sage: Words('ab', 2)
84
+ Words of length 2 over {'a', 'b'}
85
+ sage: Words('ab', infinite=False)
86
+ Finite words over {'a', 'b'}
87
+ sage: Words('ab', finite=False)
88
+ Infinite words over {'a', 'b'}
89
+ sage: Words('positive integers', finite=False)
90
+ Infinite words over Positive integers
91
+ sage: Words('natural numbers')
92
+ Finite and infinite words over Non negative integers
93
+ """
94
+ if isinstance(alphabet, (FiniteWords,
95
+ InfiniteWords,
96
+ FiniteOrInfiniteWords,
97
+ Words_n)):
98
+ return alphabet
99
+
100
+ if length is None:
101
+ if finite and infinite:
102
+ return FiniteOrInfiniteWords(alphabet)
103
+ elif finite:
104
+ return FiniteWords(alphabet)
105
+ elif infinite:
106
+ return InfiniteWords(alphabet)
107
+ else:
108
+ raise ValueError("either finite or infinite must be True")
109
+
110
+ elif isinstance(length, (int, Integer)):
111
+ return Words_n(FiniteWords(alphabet), length)
112
+
113
+ raise ValueError("do not know how to make a combinatorial class of words from your input")
114
+
115
+
116
+ class AbstractLanguage(Parent):
117
+ r"""
118
+ Abstract base class.
119
+
120
+ This is *not* to be used by any means. This class gather previous features
121
+ of set of words (prior to :issue:`19619`). In the future that class might
122
+ simply disappear or become a common base class for all languages. In the
123
+ latter case, its name would possibly change to ``Language``.
124
+ """
125
+ def __init__(self, alphabet=None, category=None):
126
+ r"""
127
+ INPUT:
128
+
129
+ - ``alphabet`` -- the underlying alphabet
130
+
131
+ TESTS::
132
+
133
+ sage: loads(dumps(FiniteWords('ab'))) == FiniteWords('ab')
134
+ True
135
+ sage: loads(dumps(InfiniteWords('ab'))) == InfiniteWords('ab')
136
+ True
137
+
138
+ sage: Words('abc').sortkey_letters
139
+ <bound method AbstractLanguage._sortkey_trivial of ...>
140
+ sage: Words('bac').sortkey_letters
141
+ <bound method AbstractLanguage._sortkey_letters of ...>
142
+ """
143
+ if isinstance(alphabet, (int, Integer)):
144
+ from sage.sets.integer_range import IntegerRange
145
+ alphabet = IntegerRange(1, alphabet + 1)
146
+ elif (alphabet == "integers" or
147
+ alphabet == "positive integers" or
148
+ alphabet == "natural numbers"):
149
+ alphabet = build_alphabet(name=alphabet)
150
+ else:
151
+ alphabet = build_alphabet(alphabet)
152
+
153
+ self._alphabet = alphabet
154
+
155
+ # Default sorting key: use rank()
156
+ self.sortkey_letters = self._sortkey_letters
157
+
158
+ # Check if we should use the trivial sorting key
159
+ N = alphabet.cardinality()
160
+ if N == Infinity:
161
+ self.sortkey_letters = self._sortkey_trivial
162
+ elif N < 36:
163
+ try:
164
+ if all(alphabet.unrank(i) > alphabet.unrank(j)
165
+ for i in range(N) for j in range(i)):
166
+ self.sortkey_letters = self._sortkey_trivial
167
+ except TypeError:
168
+ pass
169
+
170
+ if category is None:
171
+ category = Sets()
172
+
173
+ Parent.__init__(self, category=category)
174
+
175
+ def alphabet(self):
176
+ r"""
177
+ EXAMPLES::
178
+
179
+ sage: Words(NN).alphabet()
180
+ Non negative integer semiring
181
+
182
+ sage: InfiniteWords([1,2,3]).alphabet()
183
+ {1, 2, 3}
184
+ sage: InfiniteWords('ab').alphabet()
185
+ {'a', 'b'}
186
+
187
+ sage: FiniteWords([1,2,3]).alphabet()
188
+ {1, 2, 3}
189
+ sage: FiniteWords().alphabet()
190
+ Set of Python objects of class 'object'
191
+ """
192
+ return self._alphabet
193
+
194
+ def identity_morphism(self):
195
+ r"""
196
+ Return the identity morphism from ``self`` to itself.
197
+
198
+ EXAMPLES::
199
+
200
+ sage: W = Words('ab')
201
+ sage: W.identity_morphism()
202
+ WordMorphism: a->a, b->b
203
+
204
+ ::
205
+
206
+ sage: W = Words(range(3))
207
+ sage: W.identity_morphism()
208
+ WordMorphism: 0->0, 1->1, 2->2
209
+
210
+ There is no support yet for infinite alphabet::
211
+
212
+ sage: W = Words(alphabet=Alphabet(name='NN'))
213
+ sage: W
214
+ Finite and infinite words over Non negative integers
215
+ sage: W.identity_morphism()
216
+ Traceback (most recent call last):
217
+ ...
218
+ NotImplementedError: size of alphabet must be finite
219
+ """
220
+ if self.alphabet().cardinality() not in ZZ:
221
+ raise NotImplementedError('size of alphabet must be finite')
222
+ from sage.combinat.words.morphism import WordMorphism
223
+ return WordMorphism({a: a for a in self.alphabet()})
224
+
225
+ def _check(self, w, length=40):
226
+ r"""
227
+ Check that the first length elements are actually in the alphabet.
228
+
229
+ INPUT:
230
+
231
+ - ``w`` -- word
232
+
233
+ - ``length`` -- integer (default: `40`)
234
+
235
+ EXAMPLES::
236
+
237
+ sage: W = FiniteWords(['a','b','c'])
238
+ sage: W._check('abcabc') is None
239
+ True
240
+ sage: W._check('abcabcd')
241
+ Traceback (most recent call last):
242
+ ...
243
+ ValueError: d not in alphabet
244
+ sage: W._check('abcabc'*10+'z') is None
245
+ True
246
+ sage: W._check('abcabc'*10+'z', length=80)
247
+ Traceback (most recent call last):
248
+ ...
249
+ ValueError: z not in alphabet
250
+ """
251
+ stop = None if length is None else int(length)
252
+ for a in itertools.islice(w, stop):
253
+ if a not in self.alphabet():
254
+ raise ValueError("%s not in alphabet" % a)
255
+
256
+ def _sortkey_trivial(self, letter1):
257
+ """
258
+ Trivial function, used to sort the letters by their names.
259
+
260
+ INPUT:
261
+
262
+ - ``letter1`` -- a letter in the alphabet
263
+
264
+ EXAMPLES::
265
+
266
+ sage: W = FiniteWords('ade')
267
+ sage: W.sortkey_letters('d') # indirect doctest
268
+ 'd'
269
+ """
270
+ return letter1
271
+
272
+ def _sortkey_letters(self, letter1):
273
+ r"""
274
+ Return the default value used to sort the letters.
275
+
276
+ INPUT:
277
+
278
+ - ``letter1`` -- a letter in the alphabet
279
+
280
+ EXAMPLES::
281
+
282
+ sage: W = FiniteWords('woa')
283
+ sage: W.sortkey_letters('w') # indirect doctest
284
+ 0
285
+ sage: W.sortkey_letters('o') # indirect doctest
286
+ 1
287
+ sage: W.sortkey_letters('a') # indirect doctest
288
+ 2
289
+
290
+ TESTS::
291
+
292
+ sage: assert W.sortkey_letters == W._sortkey_letters
293
+ """
294
+ rk = self.alphabet().rank
295
+ return rk(letter1)
296
+
297
+ def __eq__(self, other) -> bool:
298
+ r"""
299
+ TESTS::
300
+
301
+ sage: FiniteWords() == FiniteWords()
302
+ True
303
+ sage: FiniteWords() == InfiniteWords()
304
+ False
305
+ sage: InfiniteWords() == Words()
306
+ False
307
+ sage: FiniteWords([0,1]) == FiniteWords([0,1,2,3])
308
+ False
309
+ """
310
+ return self is other or (type(self) is type(other) and
311
+ self.alphabet() == other.alphabet())
312
+
313
+ def __ne__(self, other) -> bool:
314
+ r"""
315
+ TESTS::
316
+
317
+ sage: InfiniteWords() != InfiniteWords()
318
+ False
319
+ sage: FiniteWords() != Words()
320
+ True
321
+ sage: Words('ab') != Words('ab')
322
+ False
323
+ """
324
+ return not (self == other)
325
+
326
+
327
+ class FiniteWords(AbstractLanguage):
328
+ r"""
329
+ The set of finite words over a fixed alphabet.
330
+
331
+ EXAMPLES::
332
+
333
+ sage: W = FiniteWords('ab')
334
+ sage: W
335
+ Finite words over {'a', 'b'}
336
+
337
+ TESTS::
338
+
339
+ sage: TestSuite(FiniteWords('ab')).run()
340
+ sage: TestSuite(FiniteWords([])).run()
341
+ sage: TestSuite(FiniteWords(['a'])).run()
342
+ """
343
+
344
+ def __init__(self, alphabet=None, category=None):
345
+ """
346
+ INPUT:
347
+
348
+ - ``alphabet`` -- the underlying alphabet
349
+ - ``category`` -- the suggested category of the set
350
+ (normally should be automatically determined)
351
+
352
+ TESTS::
353
+
354
+ sage: FiniteWords('ab').is_finite()
355
+ False
356
+ sage: FiniteWords('ab').category()
357
+ Category of infinite sets
358
+ sage: FiniteWords([]).is_finite()
359
+ True
360
+ sage: FiniteWords([]).category()
361
+ Category of finite sets
362
+ sage: FiniteWords([], Sets()).category()
363
+ Category of finite sets
364
+ """
365
+ if category is None:
366
+ category = Sets()
367
+ if alphabet:
368
+ category = category.Infinite()
369
+ else:
370
+ category = category.Finite()
371
+ super().__init__(alphabet, category)
372
+
373
+ def is_empty(self):
374
+ """
375
+ Return ``False``, because the empty word is in the set.
376
+
377
+ TESTS::
378
+
379
+ sage: FiniteWords('ab').is_empty()
380
+ False
381
+ sage: FiniteWords([]).is_empty()
382
+ False
383
+ """
384
+ return False
385
+
386
+ def cardinality(self):
387
+ r"""
388
+ Return the cardinality of this set.
389
+
390
+ EXAMPLES::
391
+
392
+ sage: FiniteWords('').cardinality()
393
+ 1
394
+ sage: FiniteWords('a').cardinality()
395
+ +Infinity
396
+ """
397
+ if not self.alphabet():
398
+ return ZZ.one()
399
+ return Infinity
400
+
401
+ def __hash__(self):
402
+ r"""
403
+ TESTS::
404
+
405
+ sage: hash(FiniteWords('ab')) # random
406
+ 12
407
+ """
408
+ return hash(self.alphabet()) ^ hash('finite words')
409
+
410
+ @cached_method
411
+ def shift(self):
412
+ r"""
413
+ Return the set of infinite words on the same alphabet.
414
+
415
+ EXAMPLES::
416
+
417
+ sage: FiniteWords('ab').shift()
418
+ Infinite words over {'a', 'b'}
419
+ """
420
+ return InfiniteWords(self.alphabet())
421
+
422
+ def factors(self):
423
+ r"""
424
+ Return itself.
425
+
426
+ EXAMPLES::
427
+
428
+ sage: FiniteWords('ab').factors()
429
+ Finite words over {'a', 'b'}
430
+ """
431
+ return self
432
+
433
+ @lazy_attribute
434
+ def _element_classes(self):
435
+ r"""
436
+ Return a dictionary that gives the class of the element of ``self``.
437
+
438
+ The word may be finite, infinite or of unknown length.
439
+ Its data may be string, list, tuple, a callable or an iterable.
440
+ For callable and iterable, the data may be cached.
441
+
442
+ EXAMPLES:
443
+
444
+ Once you get the class, it can be used to create a new word::
445
+
446
+ sage: W = FiniteWords([0,1,2])
447
+ sage: L = [0,1,0] * 100
448
+ sage: cls = W._element_classes['list']
449
+ sage: w = cls(W, L)
450
+ sage: type(w)
451
+ <class 'sage.combinat.words.word.FiniteWord_list'>
452
+ sage: w
453
+ word: 0100100100100100100100100100100100100100...
454
+ sage: w.parent()
455
+ Finite words over {0, 1, 2}
456
+
457
+ TESTS::
458
+
459
+ sage: d = FiniteWords()._element_classes
460
+ sage: type(d)
461
+ <class 'dict'>
462
+ sage: len(d)
463
+ 7
464
+ sage: e = FiniteWords('abcdefg')._element_classes
465
+ sage: d == e
466
+ True
467
+ """
468
+ import sage.combinat.words.word as word
469
+ classes = {
470
+ 'list': word.FiniteWord_list,
471
+ 'str': word.FiniteWord_str,
472
+ 'tuple': word.FiniteWord_tuple,
473
+ 'callable_with_caching': word.FiniteWord_callable_with_caching,
474
+ 'callable': word.FiniteWord_callable,
475
+ 'iter_with_caching': word.FiniteWord_iter_with_caching,
476
+ 'iter': word.FiniteWord_iter}
477
+
478
+ # test whether or not we can use the class Finiteword_char
479
+ if (self.alphabet().cardinality() <= 256 and
480
+ all(isinstance(i, (int, Integer)) and
481
+ 0 <= i < 256 for i in self.alphabet())):
482
+ L = self.alphabet().list()
483
+ key = self.sortkey_letters
484
+ if (all(L[i] < L[i + 1] for i in range(len(L) - 1)) and
485
+ all(key(L[i]) < key(L[i + 1]) for i in range(len(L) - 1))):
486
+ classes['char'] = word.FiniteWord_char
487
+
488
+ return classes
489
+
490
+ def _word_from_word(self, data):
491
+ r"""
492
+ Return a word from a word.
493
+
494
+ The data is assumed to be ok, no check is performed.
495
+
496
+ INPUT:
497
+
498
+ - ``data`` -- word
499
+
500
+ EXAMPLES::
501
+
502
+ sage: W = FiniteWords([0,1,2])
503
+ sage: w = W([0,1,2,0,1,2])
504
+ sage: z = W._word_from_word(w)
505
+ sage: z
506
+ word: 012012
507
+ sage: w is z
508
+ True
509
+ """
510
+ ####################
511
+ # If `data` is already a word and if its parent is self, then
512
+ # return `data`.
513
+ ###########################
514
+ if data.parent() is self or data.parent() == self:
515
+ return data
516
+
517
+ ###########################
518
+ # Otherwise, if self is not the parent of `data`, then we try to
519
+ # recover the data, the length and the datatype of the input `data`
520
+ # To minimize the impact of the import, we do it only at the time there
521
+ # are needed
522
+ ###########################
523
+ from sage.combinat.words.word_char import WordDatatype_char
524
+ if isinstance(data, WordDatatype_char):
525
+ data = list(data)
526
+ if 'char' in self._element_classes:
527
+ return self._element_classes['char'](self, data)
528
+ else:
529
+ return self._element_classes['list'](self, data)
530
+
531
+ from sage.combinat.words.word_datatypes import (WordDatatype_str,
532
+ WordDatatype_list,
533
+ WordDatatype_tuple)
534
+ if isinstance(data, WordDatatype_str):
535
+ return self._element_classes['str'](self, data._data)
536
+ if isinstance(data, WordDatatype_tuple):
537
+ return self._element_classes['tuple'](self, data._data)
538
+ if isinstance(data, WordDatatype_list):
539
+ return self._element_classes['list'](self, data._data)
540
+
541
+ from sage.combinat.words.word_infinite_datatypes import \
542
+ (WordDatatype_callable, WordDatatype_iter)
543
+ if isinstance(data, WordDatatype_callable):
544
+ length = data.length()
545
+ data = data._func
546
+ return self._word_from_callable(data, length, caching=False)
547
+ if isinstance(data, WordDatatype_iter):
548
+ length = data.length()
549
+ data = iter(data)
550
+ return self._word_from_iter(data, length, caching=False)
551
+
552
+ raise TypeError("any instance of Word_class must be an instance of WordDatatype")
553
+
554
+ def _word_from_callable(self, data, length, caching=True):
555
+ r"""
556
+ Return a word represented by a callable.
557
+
558
+ The data is assumed to be ok, no check is performed.
559
+
560
+ INPUT:
561
+
562
+ - ``data`` -- callable
563
+ - ``length`` -- integer or ``None`` or ``'infinite'`` or ``Infinity``
564
+ - ``caching`` -- boolean (default: ``True``); whether to keep a cache
565
+ of the letters computed by the callable
566
+
567
+ EXAMPLES::
568
+
569
+ sage: W = FiniteWords([0,1,2])
570
+ sage: f = lambda n : n % 3
571
+ sage: W._word_from_callable(f, 100)
572
+ word: 0120120120120120120120120120120120120120...
573
+ """
574
+ wc = '_with_caching' if caching else ""
575
+ if length not in ZZ or length < 0:
576
+ raise ValueError("not a correct value for length (%s)" % length)
577
+ return self._element_classes['callable' + wc](self, data, length)
578
+
579
+ def _word_from_iter(self, data, length=None, caching=True):
580
+ r"""
581
+ Return a word represented by an iterator.
582
+
583
+ The data is assumed to be ok, no check is performed.
584
+
585
+ INPUT:
586
+
587
+ - ``data`` -- iterable
588
+
589
+ - ``length`` -- (optional) integer
590
+
591
+ - ``caching`` -- boolean (default: ``True``); whether to keep a cache
592
+ of the letters computed by the iterator
593
+
594
+ EXAMPLES::
595
+
596
+ sage: W = FiniteWords([0,1,2])
597
+ sage: W._word_from_iter(iter([1]*10))
598
+ word: 1111111111
599
+ sage: W._word_from_iter(iter([1]*10), 5)
600
+ word: 11111
601
+ """
602
+ wc = '_with_caching' if caching else ""
603
+ if length is None or length == "finite":
604
+ length = "finite"
605
+ elif length not in ZZ or length < 0:
606
+ raise ValueError("not a correct value for length (%s)" % length)
607
+ return self._element_classes['iter' + wc](self, data, length)
608
+
609
+ def __call__(self, data=None, length=None, datatype=None, caching=True, check=True):
610
+ r"""
611
+ Construct a new word object with parent ``self``.
612
+
613
+ INPUT:
614
+
615
+ - ``data`` -- (default: ``None``) list, string, tuple, iterator, ``None``
616
+ (shorthand for []), or a callable defined on [0,1,...,length]
617
+
618
+ - ``length`` -- integer (default: ``None``); only used if the data is
619
+ an iterator or a callable. It determines the length of the word
620
+
621
+ - ``datatype`` -- (default: ``None``) ``None``, "char", "list", "str",
622
+ "tuple", "iter", "callable" or "pickled_function"; if ``None``, then
623
+ the function tries to guess this from the data
624
+
625
+ - ``caching`` -- boolean (default: ``True``); whether to keep a cache
626
+ of the letters computed by an iterator or callable
627
+
628
+ - ``check`` -- boolean (default: ``True``); whether to check if
629
+ the 40 first letters are in the parent alphabet. This is a
630
+ check done to test for small programming errors. Since we also
631
+ support infinite words, we cannot really implement a more
632
+ accurate check.
633
+
634
+ .. NOTE::
635
+
636
+ The check makes this method about 10 times slower (20µs instead
637
+ of 2µs), so make sure to set it to False if you know the
638
+ alphabet is OK. Fast creation (about 1µs) of a word can be
639
+ done using the class directly (see :meth:`_element_classes`).
640
+
641
+ .. WARNING::
642
+
643
+ Be careful when defining words using callables and iterators. It
644
+ appears that islice does not pickle correctly causing various errors
645
+ when reloading. Also, most iterators do not support copying and
646
+ should not support pickling by extension.
647
+
648
+ EXAMPLES::
649
+
650
+ sage: W = FiniteWords()
651
+
652
+ Empty word::
653
+
654
+ sage: W()
655
+ word:
656
+
657
+ Word with string::
658
+
659
+ sage: W("abbabaab")
660
+ word: abbabaab
661
+
662
+ Word with string constructed from other types::
663
+
664
+ sage: W([0,1,1,0,1,0,0,1], datatype='str')
665
+ word: 01101001
666
+ sage: W((0,1,1,0,1,0,0,1), datatype='str')
667
+ word: 01101001
668
+
669
+ Word with list::
670
+
671
+ sage: W([0,1,1,0,1,0,0,1])
672
+ word: 01101001
673
+
674
+ Word with list constructed from other types::
675
+
676
+ sage: W("01101001", datatype='list')
677
+ word: 01101001
678
+ sage: W((0,1,1,0,1,0,0,1), datatype='list')
679
+ word: 01101001
680
+
681
+ Word with tuple::
682
+
683
+ sage: W((0,1,1,0,1,0,0,1))
684
+ word: 01101001
685
+
686
+ Word with tuple constructed from other types::
687
+
688
+ sage: W([0,1,1,0,1,0,0,1], datatype='tuple')
689
+ word: 01101001
690
+ sage: W("01101001", datatype='str')
691
+ word: 01101001
692
+
693
+ Word with iterator::
694
+
695
+ sage: from itertools import count
696
+ sage: W(count(), length=10)
697
+ word: 0123456789
698
+ sage: W(iter("abbabaab"))
699
+ word: abbabaab
700
+
701
+ Word with function (a 'callable')::
702
+
703
+ sage: f = lambda n : add(Integer(n).digits(2)) % 2
704
+ sage: W(f, length=12)
705
+ word: 011010011001
706
+ sage: FiniteWords([0,1,2])(f, length=12)
707
+ word: 011010011001
708
+
709
+ Word over a string with a parent::
710
+
711
+ sage: w = FiniteWords('abc')("abbabaab"); w
712
+ word: abbabaab
713
+ sage: w.parent()
714
+ Finite words over {'a', 'b', 'c'}
715
+
716
+ The fourty first letters of the word are checked if they are in the
717
+ parent alphabet::
718
+
719
+ sage: FiniteWords("ab")("abca")
720
+ Traceback (most recent call last):
721
+ ...
722
+ ValueError: c not in alphabet
723
+ sage: FiniteWords("ab")("abca", check=False)
724
+ word: abca
725
+
726
+ The default parent is the combinatorial class of all words::
727
+
728
+ sage: w = Word("abbabaab"); w
729
+ word: abbabaab
730
+ sage: w.parent()
731
+ Finite words over Set of Python objects of class 'object'
732
+
733
+ Creation of a word from a word::
734
+
735
+ sage: FiniteWords([0,1,2,3])(FiniteWords([2,3])([2,2,2,3,3,2]))
736
+ word: 222332
737
+ sage: _.parent()
738
+ Finite words over {0, 1, 2, 3}
739
+
740
+ ::
741
+
742
+ sage: FiniteWords([3,2,1])(FiniteWords([2,3])([2,2,2,3,3,2]))
743
+ word: 222332
744
+ sage: _.parent()
745
+ Finite words over {3, 2, 1}
746
+
747
+ Construction of a word from a word when the parents are the same::
748
+
749
+ sage: W = FiniteWords()
750
+ sage: w = W(range(8))
751
+ sage: z = W(w)
752
+ sage: w is z
753
+ True
754
+
755
+ Construction of a word path from a finite word::
756
+
757
+ sage: W = FiniteWords('abcd')
758
+ sage: P = WordPaths('abcd') # needs sage.modules
759
+ sage: w = W('aaab')
760
+ sage: P(w) # needs sage.modules
761
+ Path: aaab
762
+
763
+ Construction of a word path from a Christoffel word::
764
+
765
+ sage: w = words.ChristoffelWord(5,8)
766
+ sage: w
767
+ word: 0010010100101
768
+ sage: P = WordPaths([0,1,2,3]) # needs sage.modules
769
+ sage: P(w) # needs sage.modules
770
+ Path: 0010010100101
771
+
772
+ Construction of a word represented by a list from a word
773
+ represented by a str ::
774
+
775
+ sage: w = W('ababbbabab')
776
+ sage: type(w)
777
+ <class 'sage.combinat.words.word.FiniteWord_str'>
778
+ sage: z = Word(w, datatype='list')
779
+ sage: type(z)
780
+ <class 'sage.combinat.words.word.FiniteWord_list'>
781
+ sage: y = Word(w, alphabet='abc', datatype='list')
782
+ sage: type(y)
783
+ <class 'sage.combinat.words.word.FiniteWord_list'>
784
+
785
+ Creation of a word from a concatenation of words::
786
+
787
+ sage: W = FiniteWords()
788
+ sage: w = W() * W('a')
789
+ sage: Z = Words('ab')
790
+ sage: Z(w)
791
+ word: a
792
+
793
+ Creation of a word path from a FiniteWord_iter::
794
+
795
+ sage: w = words.FibonacciWord()
796
+ sage: f = w[:100]
797
+ sage: P = WordPaths([0,1,2,3]) # needs sage.modules
798
+ sage: p = P(f); p # needs sage.modules
799
+ Path: 0100101001001010010100100101001001010010...
800
+ sage: p.length() # needs sage.modules
801
+ 100
802
+
803
+ Creation of a word path from a FiniteWord_callable::
804
+
805
+ sage: g = W(lambda n:n%2, length = 100)
806
+ sage: P = WordPaths([0,1,2,3]) # needs sage.modules
807
+ sage: p = P(g); p # needs sage.modules
808
+ Path: 0101010101010101010101010101010101010101...
809
+ sage: p.length() # needs sage.modules
810
+ 100
811
+
812
+ Creation of a word from a pickled function::
813
+
814
+ sage: f = lambda n : n % 10
815
+ sage: from sage.misc.fpickle import pickle_function
816
+ sage: s = pickle_function(f)
817
+ sage: W(s, length=10, datatype='pickled_function')
818
+ word: 0123456789
819
+
820
+ If the alphabet is a subset of [0, 255], then it uses char as datatype::
821
+
822
+ sage: type(Word([0,1,1,2,0], alphabet=list(range(256))))
823
+ <class 'sage.combinat.words.word.FiniteWord_char'>
824
+
825
+ If the alphabet is a subset of [0, 255], then the letters must
826
+ convert to an unsigned char. Otherwise an error is raised before
827
+ the check is done::
828
+
829
+ sage: type(Word([0,1,1,2,0,257], alphabet=list(range(256))))
830
+ Traceback (most recent call last):
831
+ ...
832
+ OverflowError: value too large to convert to unsigned char
833
+ sage: type(Word([0,1,1,2,0,258], alphabet=list(range(257))))
834
+ Traceback (most recent call last):
835
+ ...
836
+ ValueError: 258 not in alphabet
837
+ sage: type(Word([0,1,1,2,0,103], alphabet=list(range(100))))
838
+ Traceback (most recent call last):
839
+ ...
840
+ ValueError: 103 not in alphabet
841
+ """
842
+ if datatype is not None:
843
+ if datatype == 'list':
844
+ w = self._element_classes['list'](self, data)
845
+ elif datatype == 'char':
846
+ w = self._element_classes['char'](self, data)
847
+ elif datatype == 'tuple':
848
+ w = self._element_classes['tuple'](self, data)
849
+ elif datatype == 'str':
850
+ w = self._element_classes['str'](self, data)
851
+ elif datatype == 'callable':
852
+ w = self._word_from_callable(data, length, caching)
853
+ elif datatype == 'iter':
854
+ w = self._word_from_iter(data, length, caching)
855
+ elif datatype == 'pickled_function':
856
+ from sage.misc.fpickle import unpickle_function
857
+ data = unpickle_function(data)
858
+ w = self._word_from_callable(data, length, caching)
859
+ else:
860
+ raise ValueError("unknown datatype (={})".format(datatype))
861
+
862
+ elif 'char' in self._element_classes:
863
+ if data is None:
864
+ data = []
865
+ elif callable(data):
866
+ data = [data(i) for i in range(length)]
867
+ elif not isinstance(data, (tuple, list)):
868
+ data = list(data)
869
+ w = self._element_classes['char'](self, data)
870
+
871
+ elif isinstance(data, list):
872
+ w = self._element_classes['list'](self, data)
873
+
874
+ elif data is None:
875
+ w = self._element_classes['list'](self, [])
876
+
877
+ elif isinstance(data, str):
878
+ w = self._element_classes['str'](self, data)
879
+
880
+ elif isinstance(data, tuple):
881
+ w = self._element_classes['tuple'](self, data)
882
+
883
+ elif isinstance(data, (CombinatorialObject, ClonableElement)):
884
+ w = self._element_classes['list'](self, list(data))
885
+
886
+ elif callable(data):
887
+ w = self._word_from_callable(data, length, caching)
888
+
889
+ elif isinstance(data, Iterable):
890
+ from sage.combinat.words.abstract_word import Word_class
891
+ if isinstance(data, Word_class):
892
+ w = self._word_from_word(data)
893
+ else:
894
+ w = self._word_from_iter(data, length, caching)
895
+
896
+ else:
897
+ raise ValueError("cannot guess a datatype from data (=%s); please specify one" % data)
898
+
899
+ if check:
900
+ self._check(w)
901
+ return w
902
+
903
+ def _repr_(self) -> str:
904
+ """
905
+ EXAMPLES::
906
+
907
+ sage: FiniteWords() # indirect doctest
908
+ Finite words over Set of Python objects of class 'object'
909
+ """
910
+ return 'Finite words over {!r}'.format(self.alphabet())
911
+
912
+ def _an_element_(self):
913
+ r"""
914
+ Return an element of ``self``.
915
+
916
+ EXAMPLES::
917
+
918
+ sage: FiniteWords(4).an_element() # indirect doctest
919
+ word: 212
920
+ sage: FiniteWords([5, 1, 9]).an_element() # indirect doctest
921
+ word: 151
922
+ sage: FiniteWords([1]).an_element() # indirect doctest
923
+ word: 111
924
+ sage: FiniteWords(NN).an_element() # indirect doctest
925
+ word: 101
926
+ """
927
+ try:
928
+ some_letters = list(self.alphabet().some_elements())
929
+ except (TypeError, ValueError, AttributeError, NotImplementedError):
930
+ return self([])
931
+
932
+ if len(some_letters) == 0:
933
+ return self([])
934
+ if len(some_letters) == 1:
935
+ return self([some_letters[0]] * 3)
936
+
937
+ a, b = some_letters[:2]
938
+ return self([b, a, b])
939
+
940
+ def iterate_by_length(self, l=1):
941
+ r"""
942
+ Return an iterator over all the words of ``self`` of length `l`.
943
+
944
+ INPUT:
945
+
946
+ - ``l`` -- integer (default: 1); the length of the desired words
947
+
948
+ EXAMPLES::
949
+
950
+ sage: W = FiniteWords('ab')
951
+ sage: list(W.iterate_by_length(1))
952
+ [word: a, word: b]
953
+ sage: list(W.iterate_by_length(2))
954
+ [word: aa, word: ab, word: ba, word: bb]
955
+ sage: list(W.iterate_by_length(3))
956
+ [word: aaa,
957
+ word: aab,
958
+ word: aba,
959
+ word: abb,
960
+ word: baa,
961
+ word: bab,
962
+ word: bba,
963
+ word: bbb]
964
+ sage: list(W.iterate_by_length('a'))
965
+ Traceback (most recent call last):
966
+ ...
967
+ TypeError: the parameter l (='a') must be an integer
968
+
969
+ TESTS::
970
+
971
+ sage: W = FiniteWords(NN)
972
+ sage: list(W.iterate_by_length(1))
973
+ Traceback (most recent call last):
974
+ ...
975
+ NotImplementedError: cannot iterate over words for infinite alphabets
976
+ """
977
+ if not isinstance(l, (int, Integer)):
978
+ raise TypeError("the parameter l (=%r) must be an integer" % l)
979
+ cls = self._element_classes['tuple']
980
+ if not self.alphabet().is_finite():
981
+ raise NotImplementedError("cannot iterate over words for infinite alphabets")
982
+ for w in itertools.product(self.alphabet(), repeat=l):
983
+ yield cls(self, w)
984
+
985
+ def __iter__(self):
986
+ r"""
987
+ Return an iterator over all the words of ``self``.
988
+
989
+ The iterator outputs the words in shortlex order (see
990
+ :wikipedia:`Shortlex_order`), i.e. first by increasing length and then
991
+ lexicographically.
992
+
993
+ EXAMPLES::
994
+
995
+ sage: W = Words([4,5], infinite=False)
996
+ sage: for w in W:
997
+ ....: if len(w)>3:
998
+ ....: break
999
+ ....: else:
1000
+ ....: w
1001
+ word:
1002
+ word: 4
1003
+ word: 5
1004
+ word: 44
1005
+ word: 45
1006
+ ...
1007
+ word: 554
1008
+ word: 555
1009
+ sage: W = Words([5,4], infinite=False)
1010
+ sage: for w in W:
1011
+ ....: if len(w)>3:
1012
+ ....: break
1013
+ ....: else:
1014
+ ....: w
1015
+ word:
1016
+ word: 5
1017
+ word: 4
1018
+ word: 55
1019
+ word: 54
1020
+ ...
1021
+ word: 445
1022
+ word: 444
1023
+ """
1024
+ for l in itertools.count():
1025
+ yield from self.iterate_by_length(l)
1026
+
1027
+ def __contains__(self, x) -> bool:
1028
+ """
1029
+ Test whether ``self`` contains ``x``.
1030
+
1031
+ OUTPUT:
1032
+
1033
+ This method returns ``True`` if ``x`` is a word of the appropriate
1034
+ length and the alphabets of the parents match. It returns ``False``
1035
+ otherwise.
1036
+
1037
+ EXAMPLES::
1038
+
1039
+ sage: W = FiniteWords('ab')
1040
+ sage: W('ab') in W
1041
+ True
1042
+ sage: W('aa') in FiniteWords('aa')
1043
+ False
1044
+ sage: FiniteWords('a')('aa') in FiniteWords('ab')
1045
+ False
1046
+ sage: 2 in FiniteWords([1,2,3])
1047
+ False
1048
+ sage: [2] in FiniteWords([1,2,3])
1049
+ False
1050
+ sage: [1, 'a'] in FiniteWords([1,2,3])
1051
+ False
1052
+ """
1053
+ from sage.combinat.words.finite_word import FiniteWord_class
1054
+ return isinstance(x, FiniteWord_class) and x.parent().alphabet() == self.alphabet()
1055
+
1056
+ def random_element(self, length=None, *args, **kwds):
1057
+ r"""
1058
+ Return a random finite word on the given alphabet.
1059
+
1060
+ INPUT:
1061
+
1062
+ - ``length`` -- (optional) the length of the word; if not set, will use
1063
+ a uniformly random number between 0 and 10
1064
+
1065
+ - all other argument are transmitted to the random generator of the
1066
+ alphabet
1067
+
1068
+ EXAMPLES::
1069
+
1070
+ sage: W = FiniteWords(5)
1071
+ sage: W.random_element() # random
1072
+ word: 5114325445423521544531411434451152142155...
1073
+
1074
+ sage: W = FiniteWords(ZZ)
1075
+ sage: W.random_element() # random
1076
+ word: 5,-1,-1,-1,0,0,0,0,-3,-11
1077
+ sage: W.random_element(length=4, x=0, y=4) # random
1078
+ word: 1003
1079
+
1080
+ TESTS::
1081
+
1082
+ sage: _ = FiniteWords(GF(5)).random_element() # needs sage.rings.finite_rings
1083
+ """
1084
+ if length is None:
1085
+ length = ZZ.random_element(0, 10)
1086
+ return self([self.alphabet().random_element(*args, **kwds)
1087
+ for x in range(length)])
1088
+
1089
+ def iter_morphisms(self, arg=None, codomain=None, min_length=1):
1090
+ r"""
1091
+ Iterate over all morphisms with domain ``self`` and the given
1092
+ codomain.
1093
+
1094
+ INPUT:
1095
+
1096
+ - ``arg`` -- (default: ``None``) it can be one of the following:
1097
+
1098
+ - ``None`` -- then the method iterates through all morphisms
1099
+
1100
+ - tuple `(a, b)` of two integers -- it specifies the range
1101
+ ``range(a, b)`` of values to consider for the sum of the length
1102
+ of the image of each letter in the alphabet
1103
+
1104
+ - list of nonnegative integers -- the length of the list must be
1105
+ equal to the size of the alphabet, and the `i`-th integer of
1106
+ ``arg`` determines the length of the word mapped to by the `i`-th
1107
+ letter of the (ordered) alphabet
1108
+
1109
+ - ``codomain`` -- (default: ``None``) a combinatorial class of words;
1110
+ by default, ``codomain`` is ``self``
1111
+
1112
+ - ``min_length`` -- nonnegative integer (default: 1); if ``arg`` is
1113
+ not specified, then iterate through all the morphisms where the
1114
+ length of the images of each letter in the alphabet is at least
1115
+ ``min_length``. This is ignored if ``arg`` is a list.
1116
+
1117
+ OUTPUT: iterator
1118
+
1119
+ EXAMPLES:
1120
+
1121
+ Iterator over all non-erasing morphisms::
1122
+
1123
+ sage: W = FiniteWords('ab')
1124
+ sage: it = W.iter_morphisms()
1125
+ sage: for _ in range(7): next(it)
1126
+ WordMorphism: a->a, b->a
1127
+ WordMorphism: a->a, b->b
1128
+ WordMorphism: a->b, b->a
1129
+ WordMorphism: a->b, b->b
1130
+ WordMorphism: a->aa, b->a
1131
+ WordMorphism: a->aa, b->b
1132
+ WordMorphism: a->ab, b->a
1133
+
1134
+ Iterator over all morphisms including erasing morphisms::
1135
+
1136
+ sage: W = FiniteWords('ab')
1137
+ sage: it = W.iter_morphisms(min_length=0)
1138
+ sage: for _ in range(7): next(it)
1139
+ WordMorphism: a->, b->
1140
+ WordMorphism: a->a, b->
1141
+ WordMorphism: a->b, b->
1142
+ WordMorphism: a->, b->a
1143
+ WordMorphism: a->, b->b
1144
+ WordMorphism: a->aa, b->
1145
+ WordMorphism: a->ab, b->
1146
+
1147
+ Iterator over morphisms where the sum of the lengths of the images
1148
+ of the letters is in a specific range::
1149
+
1150
+ sage: for m in W.iter_morphisms((0, 3), min_length=0): m
1151
+ WordMorphism: a->aa, b->
1152
+ WordMorphism: a->ab, b->
1153
+ WordMorphism: a->ba, b->
1154
+ WordMorphism: a->bb, b->
1155
+ WordMorphism: a->a, b->a
1156
+ WordMorphism: a->a, b->b
1157
+ WordMorphism: a->b, b->a
1158
+ WordMorphism: a->b, b->b
1159
+ WordMorphism: a->a, b->
1160
+ WordMorphism: a->b, b->
1161
+ WordMorphism: a->, b->aa
1162
+ WordMorphism: a->, b->ab
1163
+ WordMorphism: a->, b->ba
1164
+ WordMorphism: a->, b->bb
1165
+ WordMorphism: a->, b->a
1166
+ WordMorphism: a->, b->b
1167
+ WordMorphism: a->, b->
1168
+
1169
+ ::
1170
+
1171
+ sage: for m in W.iter_morphisms( (2, 4) ): m
1172
+ WordMorphism: a->aa, b->a
1173
+ WordMorphism: a->aa, b->b
1174
+ WordMorphism: a->ab, b->a
1175
+ WordMorphism: a->ab, b->b
1176
+ WordMorphism: a->ba, b->a
1177
+ WordMorphism: a->ba, b->b
1178
+ WordMorphism: a->bb, b->a
1179
+ WordMorphism: a->bb, b->b
1180
+ WordMorphism: a->a, b->aa
1181
+ WordMorphism: a->a, b->ab
1182
+ WordMorphism: a->a, b->ba
1183
+ WordMorphism: a->a, b->bb
1184
+ WordMorphism: a->b, b->aa
1185
+ WordMorphism: a->b, b->ab
1186
+ WordMorphism: a->b, b->ba
1187
+ WordMorphism: a->b, b->bb
1188
+ WordMorphism: a->a, b->a
1189
+ WordMorphism: a->a, b->b
1190
+ WordMorphism: a->b, b->a
1191
+ WordMorphism: a->b, b->b
1192
+
1193
+ Iterator over morphisms with specific image lengths::
1194
+
1195
+ sage: for m in W.iter_morphisms([0, 0]): m
1196
+ WordMorphism: a->, b->
1197
+ sage: for m in W.iter_morphisms([0, 1]): m
1198
+ WordMorphism: a->, b->a
1199
+ WordMorphism: a->, b->b
1200
+ sage: for m in W.iter_morphisms([2, 1]): m
1201
+ WordMorphism: a->aa, b->a
1202
+ WordMorphism: a->aa, b->b
1203
+ WordMorphism: a->ab, b->a
1204
+ WordMorphism: a->ab, b->b
1205
+ WordMorphism: a->ba, b->a
1206
+ WordMorphism: a->ba, b->b
1207
+ WordMorphism: a->bb, b->a
1208
+ WordMorphism: a->bb, b->b
1209
+ sage: for m in W.iter_morphisms([2, 2]): m
1210
+ WordMorphism: a->aa, b->aa
1211
+ WordMorphism: a->aa, b->ab
1212
+ WordMorphism: a->aa, b->ba
1213
+ WordMorphism: a->aa, b->bb
1214
+ WordMorphism: a->ab, b->aa
1215
+ WordMorphism: a->ab, b->ab
1216
+ WordMorphism: a->ab, b->ba
1217
+ WordMorphism: a->ab, b->bb
1218
+ WordMorphism: a->ba, b->aa
1219
+ WordMorphism: a->ba, b->ab
1220
+ WordMorphism: a->ba, b->ba
1221
+ WordMorphism: a->ba, b->bb
1222
+ WordMorphism: a->bb, b->aa
1223
+ WordMorphism: a->bb, b->ab
1224
+ WordMorphism: a->bb, b->ba
1225
+ WordMorphism: a->bb, b->bb
1226
+
1227
+ The codomain may be specified as well::
1228
+
1229
+ sage: Y = FiniteWords('xyz')
1230
+ sage: for m in W.iter_morphisms([0, 2], codomain=Y): m
1231
+ WordMorphism: a->, b->xx
1232
+ WordMorphism: a->, b->xy
1233
+ WordMorphism: a->, b->xz
1234
+ WordMorphism: a->, b->yx
1235
+ WordMorphism: a->, b->yy
1236
+ WordMorphism: a->, b->yz
1237
+ WordMorphism: a->, b->zx
1238
+ WordMorphism: a->, b->zy
1239
+ WordMorphism: a->, b->zz
1240
+ sage: for m in Y.iter_morphisms([0,2,1], codomain=W): m
1241
+ WordMorphism: x->, y->aa, z->a
1242
+ WordMorphism: x->, y->aa, z->b
1243
+ WordMorphism: x->, y->ab, z->a
1244
+ WordMorphism: x->, y->ab, z->b
1245
+ WordMorphism: x->, y->ba, z->a
1246
+ WordMorphism: x->, y->ba, z->b
1247
+ WordMorphism: x->, y->bb, z->a
1248
+ WordMorphism: x->, y->bb, z->b
1249
+ sage: it = W.iter_morphisms(codomain=Y)
1250
+ sage: for _ in range(10): next(it)
1251
+ WordMorphism: a->x, b->x
1252
+ WordMorphism: a->x, b->y
1253
+ WordMorphism: a->x, b->z
1254
+ WordMorphism: a->y, b->x
1255
+ WordMorphism: a->y, b->y
1256
+ WordMorphism: a->y, b->z
1257
+ WordMorphism: a->z, b->x
1258
+ WordMorphism: a->z, b->y
1259
+ WordMorphism: a->z, b->z
1260
+ WordMorphism: a->xx, b->x
1261
+
1262
+ TESTS::
1263
+
1264
+ sage: list(W.iter_morphisms([1,0]))
1265
+ [WordMorphism: a->a, b->, WordMorphism: a->b, b->]
1266
+ sage: list(W.iter_morphisms([0,0], codomain=Y))
1267
+ [WordMorphism: a->, b->]
1268
+ sage: list(W.iter_morphisms([0, 1, 2]))
1269
+ Traceback (most recent call last):
1270
+ ...
1271
+ TypeError: arg (=[0, 1, 2]) must be an iterable of 2 integers
1272
+ sage: list(W.iter_morphisms([0, 'a']))
1273
+ Traceback (most recent call last):
1274
+ ...
1275
+ TypeError: arg (=[0, 'a']) must be an iterable of 2 integers
1276
+ sage: list(W.iter_morphisms([0, 1], codomain='a'))
1277
+ Traceback (most recent call last):
1278
+ ...
1279
+ TypeError: codomain (=a) must be an instance of FiniteWords
1280
+ """
1281
+ n = self.alphabet().cardinality()
1282
+ min_length = max(min_length, 0)
1283
+ # create an iterable of compositions (all "compositions" if arg is
1284
+ # None, or [arg] otherwise)
1285
+ if arg is None:
1286
+ from sage.combinat.integer_lists.nn import IntegerListsNN
1287
+ compositions = IntegerListsNN(length=n, min_part=min_length)
1288
+ elif isinstance(arg, tuple):
1289
+ from sage.combinat.integer_lists import IntegerListsLex
1290
+ a, b = arg
1291
+ compositions = IntegerListsLex(min_sum=a, max_sum=b - 1,
1292
+ length=n, min_part=min_length)
1293
+ else:
1294
+ arg = list(arg)
1295
+ if (not len(arg) == n or not
1296
+ all(isinstance(a, (int, Integer)) for a in arg)):
1297
+ raise TypeError(
1298
+ "arg (=%s) must be an iterable of %s integers" % (arg, n))
1299
+ compositions = [arg]
1300
+
1301
+ # set the codomain
1302
+ if codomain is None:
1303
+ codomain = self
1304
+ elif isinstance(codomain, FiniteOrInfiniteWords):
1305
+ codomain = codomain.finite_words()
1306
+ elif not isinstance(codomain, FiniteWords):
1307
+ raise TypeError("codomain (=%s) must be an instance of FiniteWords" % codomain)
1308
+
1309
+ # iterate through the morphisms
1310
+ from sage.combinat.words.morphism import WordMorphism
1311
+ for composition in compositions:
1312
+ cuts = [0] + list(composition)
1313
+ for i in range(1, len(cuts)):
1314
+ cuts[i] += cuts[i - 1]
1315
+ s = cuts[-1] # same but better than s = sum(composition)
1316
+ for big_word in codomain.iterate_by_length(s):
1317
+ d = {}
1318
+ i = 0
1319
+ for a in self.alphabet():
1320
+ d[a] = big_word[cuts[i]:cuts[i + 1]]
1321
+ i += 1
1322
+ yield WordMorphism(d, codomain=codomain)
1323
+
1324
+
1325
+ class InfiniteWords(AbstractLanguage):
1326
+ def cardinality(self):
1327
+ r"""
1328
+ Return the cardinality of this set.
1329
+
1330
+ EXAMPLES::
1331
+
1332
+ sage: InfiniteWords('ab').cardinality()
1333
+ +Infinity
1334
+ sage: InfiniteWords('a').cardinality()
1335
+ 1
1336
+ sage: InfiniteWords('').cardinality()
1337
+ 0
1338
+ """
1339
+ if not self.alphabet().cardinality():
1340
+ return ZZ.zero()
1341
+ elif self.alphabet().cardinality().is_one():
1342
+ return ZZ.one()
1343
+ else:
1344
+ return Infinity
1345
+
1346
+ def __hash__(self):
1347
+ r"""
1348
+ TESTS::
1349
+
1350
+ sage: hash(InfiniteWords('ab')) # random
1351
+ 12
1352
+ """
1353
+ return hash(self.alphabet()) ^ hash('infinite words')
1354
+
1355
+ @cached_method
1356
+ def factors(self):
1357
+ r"""
1358
+ Return the set of finite words on the same alphabet.
1359
+
1360
+ EXAMPLES::
1361
+
1362
+ sage: InfiniteWords('ab').factors()
1363
+ Finite words over {'a', 'b'}
1364
+ """
1365
+ return FiniteWords(self.alphabet())
1366
+
1367
+ def shift(self):
1368
+ r"""
1369
+ Return itself.
1370
+
1371
+ EXAMPLES::
1372
+
1373
+ sage: InfiniteWords('ab').shift()
1374
+ Infinite words over {'a', 'b'}
1375
+ """
1376
+ return self
1377
+
1378
+ @lazy_attribute
1379
+ def _element_classes(self):
1380
+ r"""
1381
+ Return a dictionary that gives the class of the element of ``self``.
1382
+
1383
+ The word may be finite, infinite or of unknown length.
1384
+ Its data may be string, list, tuple, a callable or an iterable.
1385
+ For callable and iterable, the data may be cached.
1386
+
1387
+ EXAMPLES:
1388
+
1389
+ Once you get the class, it can be used to create a new word::
1390
+
1391
+ sage: W = InfiniteWords([0,1,2])
1392
+ sage: cls = W._element_classes['iter_with_caching']
1393
+ sage: from itertools import count
1394
+ sage: w = cls(W, (i%3 for i in count()))
1395
+ sage: type(w)
1396
+ <class 'sage.combinat.words.word.InfiniteWord_iter_with_caching'>
1397
+ sage: w
1398
+ word: 0120120120120120120120120120120120120120...
1399
+ sage: w.parent()
1400
+ Infinite words over {0, 1, 2}
1401
+
1402
+ TESTS::
1403
+
1404
+ sage: d = InfiniteWords()._element_classes
1405
+ sage: type(d)
1406
+ <class 'dict'>
1407
+ sage: len(d)
1408
+ 4
1409
+ sage: e = InfiniteWords('abcdefg')._element_classes
1410
+ sage: d == e
1411
+ True
1412
+ """
1413
+ import sage.combinat.words.word as word
1414
+ return {
1415
+ 'callable_with_caching': word.InfiniteWord_callable_with_caching,
1416
+ 'callable': word.InfiniteWord_callable,
1417
+ 'iter_with_caching': word.InfiniteWord_iter_with_caching,
1418
+ 'iter': word.InfiniteWord_iter}
1419
+
1420
+ def random_element(self, *args, **kwds):
1421
+ r"""
1422
+ Return a random infinite word.
1423
+
1424
+ EXAMPLES::
1425
+
1426
+ sage: W = InfiniteWords('ab')
1427
+ sage: W.random_element() # random
1428
+ word: abbbabbaabbbabbabbaabaabbabbbbbbbbaabbbb...
1429
+
1430
+ sage: W = InfiniteWords(ZZ)
1431
+ sage: W.random_element(x=2,y=4) # random
1432
+ word: 3333223322232233333223323223222233233233...
1433
+ """
1434
+ rd = self.alphabet().random_element
1435
+ from itertools import count
1436
+ return self._word_from_iter(rd(*args, **kwds) for i in count())
1437
+
1438
+ def _word_from_word(self, data):
1439
+ r"""
1440
+ Return a word from a word.
1441
+
1442
+ The data is assumed to be ok, no check is performed.
1443
+
1444
+ INPUT:
1445
+
1446
+ - ``data`` -- word
1447
+
1448
+ EXAMPLES::
1449
+
1450
+ sage: W = InfiniteWords([0,1,2])
1451
+ sage: w = W(words.FibonacciWord())
1452
+ sage: w
1453
+ word: 0100101001001010010100100101001001010010...
1454
+ sage: w.parent() is W
1455
+ True
1456
+ sage: z = W._word_from_word(w)
1457
+ sage: w is z
1458
+ True
1459
+ """
1460
+ ####################
1461
+ # If `data` is already a word and if its parent is self, then
1462
+ # return `data` (no matter what the parameter length, datatype)
1463
+ ###########################
1464
+ if data.parent() is self or data.parent() == self:
1465
+ return data
1466
+ elif data.length() != Infinity:
1467
+ raise ValueError("cannot build an infinite word from a finite one")
1468
+
1469
+ ###########################
1470
+ # Otherwise, if self is not the parent of `data`, then we try to
1471
+ # recover the data, the length and the datatype of the input `data`
1472
+ ###########################
1473
+ from sage.combinat.words.word_infinite_datatypes import (WordDatatype_callable,
1474
+ WordDatatype_iter)
1475
+ if isinstance(data, WordDatatype_callable):
1476
+ data = data._func
1477
+ return self._word_from_callable(data, caching=False)
1478
+ elif isinstance(data, WordDatatype_iter):
1479
+ data = iter(data)
1480
+ return self._word_from_iter(data, caching=False)
1481
+ else:
1482
+ raise TypeError("any instance of Word_class must be an instance of WordDatatype")
1483
+
1484
+ def _word_from_callable(self, data, caching=True):
1485
+ r"""
1486
+ Return a word represented by a callable.
1487
+
1488
+ The data is assumed to be ok, no check is performed.
1489
+
1490
+ INPUT:
1491
+
1492
+ - ``data`` -- callable
1493
+
1494
+ - ``caching`` -- boolean (default: ``True``); whether to keep a cache
1495
+ of the letters computed by the callable
1496
+
1497
+ EXAMPLES::
1498
+
1499
+ sage: W = InfiniteWords([0,1,2])
1500
+ sage: f = lambda n : n % 3
1501
+ sage: W._word_from_callable(f)
1502
+ word: 0120120120120120120120120120120120120120...
1503
+ """
1504
+ wc = '_with_caching' if caching else ""
1505
+ return self._element_classes['callable' + wc](self, data, Infinity)
1506
+
1507
+ def _word_from_iter(self, data, caching=True):
1508
+ r"""
1509
+ Return a word represented by an iterator.
1510
+
1511
+ The data is assumed to be ok, no check is performed.
1512
+
1513
+ INPUT:
1514
+
1515
+ - ``data`` -- iterable
1516
+
1517
+ - ``caching`` -- boolean (default: ``True``); whether to keep a cache
1518
+ of the letters computed by the iterator
1519
+
1520
+ EXAMPLES::
1521
+
1522
+ sage: W = InfiniteWords([0,1,2])
1523
+ sage: from itertools import count
1524
+ sage: W._word_from_iter((i % 3 for i in count()))
1525
+ word: 0120120120120120120120120120120120120120...
1526
+ """
1527
+ wc = '_with_caching' if caching else ""
1528
+ return self._element_classes['iter' + wc](self, data, Infinity)
1529
+
1530
+ def __call__(self, data=None, datatype=None, caching=True, check=True):
1531
+ r"""
1532
+ Construct a new word object with parent ``self``.
1533
+
1534
+ INPUT:
1535
+
1536
+ - ``data`` -- iterator or a callable
1537
+
1538
+ - ``datatype`` -- (default: ``None``) ``None``, "iter", "callable" or
1539
+ "pickled_function"; if ``None``, then the function tries to guess
1540
+ this from the data
1541
+
1542
+ - ``caching`` -- boolean (default: ``True``); whether to keep a
1543
+ cache of the letters computed by an iterator or callable
1544
+
1545
+ - ``check`` -- boolean (default: ``True``); whether to check if
1546
+ the 40 first letters are in the parent alphabet. This is a
1547
+ check done to test for small programming errors. Since we also
1548
+ support infinite words, we cannot really implement a more
1549
+ accurate check.
1550
+
1551
+ .. NOTE::
1552
+
1553
+ The check makes this method about 10 times slower (20µs instead
1554
+ of 2µs), so make sure to set it to False if you know the
1555
+ alphabet is OK. Fast creation (about 1µs) of a word can be
1556
+ done using the class directly (see :meth:`_element_classes`).
1557
+
1558
+ .. WARNING::
1559
+
1560
+ Be careful when defining words using callables and iterators. It
1561
+ appears that islice does not pickle correctly causing various errors
1562
+ when reloading. Also, most iterators do not support copying and
1563
+ should not support pickling by extension.
1564
+
1565
+ EXAMPLES:
1566
+
1567
+ Word with iterator::
1568
+
1569
+ sage: from itertools import count
1570
+ sage: InfiniteWords()(count())
1571
+ 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,...
1572
+
1573
+ Word with function (a 'callable')::
1574
+
1575
+ sage: f = lambda n : add(Integer(n).digits(2)) % 2
1576
+ sage: InfiniteWords()(f)
1577
+ word: 0110100110010110100101100110100110010110...
1578
+
1579
+ The fourty first letters of the word are checked if they are in the
1580
+ parent alphabet::
1581
+
1582
+ sage: from itertools import count
1583
+ sage: InfiniteWords("ab")(("c" if i == 0 else "a" for i in count()))
1584
+ Traceback (most recent call last):
1585
+ ...
1586
+ ValueError: c not in alphabet
1587
+
1588
+ Creation of a word from a word::
1589
+
1590
+ sage: w = InfiniteWords([0,1,2,3])(words.FibonacciWord())
1591
+ sage: w
1592
+ word: 0100101001001010010100100101001001010010...
1593
+ sage: w.parent()
1594
+ Infinite words over {0, 1, 2, 3}
1595
+ sage: InfiniteWords([0,1,2,3])(w) is w
1596
+ True
1597
+
1598
+ Creation of a word from a pickled function::
1599
+
1600
+ sage: f = lambda n : n % 10
1601
+ sage: from sage.misc.fpickle import pickle_function
1602
+ sage: s = pickle_function(f)
1603
+ sage: Word(s, datatype='pickled_function')
1604
+ word: 0123456789012345678901234567890123456789...
1605
+ """
1606
+ if datatype is not None:
1607
+ if datatype == 'callable':
1608
+ w = self._word_from_callable(data, caching)
1609
+ elif datatype == 'iter':
1610
+ w = self._word_from_iter(data, caching)
1611
+ elif datatype == 'pickled_function':
1612
+ from sage.misc.fpickle import unpickle_function
1613
+ data = unpickle_function(data)
1614
+ w = self._word_from_callable(data, caching)
1615
+ else:
1616
+ raise ValueError("unknown datatype (={})".format(datatype))
1617
+
1618
+ elif callable(data):
1619
+ w = self._word_from_callable(data, caching)
1620
+
1621
+ elif isinstance(data, Iterable):
1622
+ from sage.combinat.words.abstract_word import Word_class
1623
+ if isinstance(data, Word_class):
1624
+ w = self._word_from_word(data)
1625
+ else:
1626
+ w = self._word_from_iter(data, caching)
1627
+
1628
+ else:
1629
+ raise ValueError("cannot guess a datatype from data (=%s); please specify one" % data)
1630
+
1631
+ if check:
1632
+ self._check(w)
1633
+ return w
1634
+
1635
+ def _repr_(self):
1636
+ r"""
1637
+ Return a string representation of ``self``.
1638
+
1639
+ EXAMPLES::
1640
+
1641
+ sage: Words('ab', finite=False) # indirect doctest
1642
+ Infinite words over {'a', 'b'}
1643
+ """
1644
+ return "Infinite words over {!r}".format(self.alphabet())
1645
+
1646
+ def _an_element_(self):
1647
+ r"""
1648
+ Return an element of ``self``.
1649
+
1650
+ EXAMPLES::
1651
+
1652
+ sage: W = Words('ac', finite=False); W
1653
+ Infinite words over {'a', 'c'}
1654
+ sage: W.an_element()
1655
+ word: accacaaccaacaccacaacaccaaccacaaccaacacca...
1656
+
1657
+ sage: W = Words(NN, finite=False); W
1658
+ Infinite words over Non negative integer semiring
1659
+ sage: W.an_element()
1660
+ word: 0110100110010110100101100110100110010110...
1661
+
1662
+ sage: W = Words('z', finite=False); W
1663
+ Infinite words over {'z'}
1664
+ sage: W.an_element()
1665
+ word: zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz...
1666
+ """
1667
+ some_letters = list(self.alphabet().some_elements())
1668
+ if len(some_letters) > 1:
1669
+ from sage.combinat.words.word_generators import words
1670
+ letters = some_letters[:2]
1671
+ return self(words.ThueMorseWord(alphabet=letters))
1672
+ else:
1673
+ letter = some_letters[0]
1674
+ return self(lambda n: letter)
1675
+
1676
+
1677
+ class FiniteOrInfiniteWords(AbstractLanguage):
1678
+ def __init__(self, alphabet):
1679
+ r"""
1680
+ INPUT:
1681
+
1682
+ - ``alphabet`` -- the underlying alphabet
1683
+
1684
+ TESTS::
1685
+
1686
+ sage: loads(dumps(Words())) == Words()
1687
+ True
1688
+ """
1689
+ AbstractLanguage.__init__(self, alphabet)
1690
+
1691
+ def __setstate__(self, state):
1692
+ r"""
1693
+ TESTS::
1694
+
1695
+ sage: import os, tempfile
1696
+ sage: W = Words('ab')
1697
+ sage: with tempfile.TemporaryDirectory() as d:
1698
+ ....: filename = os.path.join(d, 'test.sobj')
1699
+ ....: W.save(filename)
1700
+ ....: load(filename)
1701
+ Finite and infinite words over {'a', 'b'}
1702
+ """
1703
+ # add a default to support old pickles from #19619
1704
+ self._alphabet = state.get('_alphabet', build_alphabet())
1705
+
1706
+ def cardinality(self):
1707
+ r"""
1708
+ Return the cardinality of this set of words.
1709
+
1710
+ EXAMPLES::
1711
+
1712
+ sage: Words('abcd').cardinality()
1713
+ +Infinity
1714
+ sage: Words('a').cardinality()
1715
+ +Infinity
1716
+ sage: Words('').cardinality()
1717
+ 1
1718
+ """
1719
+ return self.finite_words().cardinality()
1720
+
1721
+ @lazy_attribute
1722
+ def _element_classes(self):
1723
+ r"""
1724
+ Return the element classes corresponding to words of unknown length.
1725
+
1726
+ EXAMPLES::
1727
+
1728
+ sage: Words('ab')._element_classes
1729
+ {'iter': <class 'sage.combinat.words.word.Word_iter'>,
1730
+ 'iter_with_caching': <class 'sage.combinat.words.word.Word_iter_with_caching'>}
1731
+ """
1732
+ import sage.combinat.words.word as word
1733
+ return {'iter_with_caching': word.Word_iter_with_caching,
1734
+ 'iter': word.Word_iter}
1735
+
1736
+ def __hash__(self):
1737
+ r"""
1738
+ TESTS::
1739
+
1740
+ sage: hash(Words('ab')) # random
1741
+ 12
1742
+ """
1743
+ return hash(self.alphabet()) ^ hash('words')
1744
+
1745
+ @cached_method
1746
+ def finite_words(self):
1747
+ r"""
1748
+ Return the set of finite words.
1749
+
1750
+ EXAMPLES::
1751
+
1752
+ sage: Words('ab').finite_words()
1753
+ Finite words over {'a', 'b'}
1754
+ """
1755
+ return FiniteWords(self.alphabet())
1756
+
1757
+ factors = finite_words
1758
+
1759
+ @cached_method
1760
+ def infinite_words(self):
1761
+ r"""
1762
+ Return the set of infinite words.
1763
+
1764
+ EXAMPLES::
1765
+
1766
+ sage: Words('ab').infinite_words()
1767
+ Infinite words over {'a', 'b'}
1768
+ """
1769
+ return InfiniteWords(self.alphabet())
1770
+
1771
+ shift = infinite_words
1772
+
1773
+ def iterate_by_length(self, length):
1774
+ r"""
1775
+ Return an iterator over the words of given length.
1776
+
1777
+ EXAMPLES::
1778
+
1779
+ sage: [w.string_rep() for w in Words('ab').iterate_by_length(3)]
1780
+ ['aaa', 'aab', 'aba', 'abb', 'baa', 'bab', 'bba', 'bbb']
1781
+ """
1782
+ return self.finite_words().iterate_by_length(length)
1783
+
1784
+ def _word_from_word(self, data):
1785
+ r"""
1786
+ TESTS::
1787
+
1788
+ sage: W = Words('ab')
1789
+ sage: w = FiniteWords('abc')('abba')
1790
+ sage: W._word_from_word(w)
1791
+ word: abba
1792
+ sage: _.parent()
1793
+ Finite words over {'a', 'b'}
1794
+
1795
+ sage: w = InfiniteWords('abc')(lambda i: 'a')
1796
+ sage: W._word_from_word(w)
1797
+ word: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...
1798
+ sage: _.parent()
1799
+ Infinite words over {'a', 'b'}
1800
+ """
1801
+ P = data.parent()
1802
+ if P is self or P is self.finite_words() or P is self.infinite_words() or \
1803
+ P == self or P == self.finite_words() or P == self.infinite_words():
1804
+ return data
1805
+ elif data.is_finite():
1806
+ return self.finite_words()._word_from_word(data)
1807
+ else:
1808
+ return self.infinite_words()._word_from_word(data)
1809
+
1810
+ def _word_from_iter(self, data, caching=True):
1811
+ r"""
1812
+ TESTS::
1813
+
1814
+ sage: W = Words([0,1,2])
1815
+ sage: u = Word(iter("abcabc"*100))
1816
+ sage: type(u)
1817
+ <class 'sage.combinat.words.word.Word_iter_with_caching'>
1818
+ sage: u.length() is None
1819
+ True
1820
+
1821
+ sage: u = Word(iter("abcabc"))
1822
+ sage: type(u)
1823
+ <class 'sage.combinat.words.word.FiniteWord_iter_with_caching'>
1824
+ sage: u.length()
1825
+ 6
1826
+ """
1827
+ wc = '_with_caching' if caching else ''
1828
+ cls = self._element_classes['iter' + wc]
1829
+ return cls(self, data, None)
1830
+
1831
+ def __call__(self, data=None, length=None, datatype=None, caching=True, check=True):
1832
+ r"""
1833
+ Construct a new word object with parent ``self``.
1834
+
1835
+ INPUT:
1836
+
1837
+ - ``data`` -- (default: ``None``) list, string, tuple, iterator, ``None``
1838
+ (shorthand for []), or a callable defined on [0,1,...,length]
1839
+
1840
+ - ``length`` -- (default: ``None``) this is dependent on the type of data.
1841
+ It is ignored for words defined by lists, strings, tuples,
1842
+ etc., because they have a naturally defined length.
1843
+ For callables, this defines the domain of definition,
1844
+ which is assumed to be [0, 1, 2, ..., length-1].
1845
+ For iterators: Infinity if you know the iterator will not
1846
+ terminate (default); ``'unknown'`` if you do not know whether the
1847
+ iterator terminates; ``'finite'`` if you know that the iterator
1848
+ terminates, but do not know the length.
1849
+
1850
+ - ``datatype`` -- (default: ``None``) ``None``, "char", "list", "str",
1851
+ "tuple", "iter", "callable" or "pickled_function"; if ``None``, then
1852
+ the function tries to guess this from the data.
1853
+
1854
+ - ``caching`` -- boolean (default: ``True``); whether to keep a cache
1855
+ of the letters computed by an iterator or callable
1856
+
1857
+ - ``check`` -- boolean (default: ``True``); whether to check if
1858
+ the 40 first letters are in the parent alphabet. This is a
1859
+ check done to test for small programming errors. Since we also
1860
+ support infinite words, we cannot really implement a more
1861
+ accurate check.
1862
+
1863
+ .. NOTE::
1864
+
1865
+ The check makes this method about 10 times slower (20µs instead
1866
+ of 2µs), so make sure to set it to False if you know the
1867
+ alphabet is OK. Fast creation (about 1µs) of a word can be
1868
+ done using the class directly (see :meth:`_element_classes`).
1869
+
1870
+ .. WARNING::
1871
+
1872
+ Be careful when defining words using callables and iterators. It
1873
+ appears that islice does not pickle correctly causing various errors
1874
+ when reloading. Also, most iterators do not support copying and
1875
+ should not support pickling by extension.
1876
+
1877
+ EXAMPLES:
1878
+
1879
+ Empty word::
1880
+
1881
+ sage: Words()()
1882
+ word:
1883
+
1884
+ Word with string::
1885
+
1886
+ sage: Words()("abbabaab")
1887
+ word: abbabaab
1888
+
1889
+ Word with string constructed from other types::
1890
+
1891
+ sage: Words()([0,1,1,0,1,0,0,1], datatype='str')
1892
+ word: 01101001
1893
+ sage: Words()((0,1,1,0,1,0,0,1), datatype='str')
1894
+ word: 01101001
1895
+
1896
+ Word with list::
1897
+
1898
+ sage: Words()([0,1,1,0,1,0,0,1])
1899
+ word: 01101001
1900
+
1901
+ Word with list constructed from other types::
1902
+
1903
+ sage: Words()("01101001", datatype='list')
1904
+ word: 01101001
1905
+ sage: Words()((0,1,1,0,1,0,0,1), datatype='list')
1906
+ word: 01101001
1907
+
1908
+ Word with tuple::
1909
+
1910
+ sage: Words()((0,1,1,0,1,0,0,1))
1911
+ word: 01101001
1912
+
1913
+ Word with tuple constructed from other types::
1914
+
1915
+ sage: Words()([0,1,1,0,1,0,0,1], datatype='tuple')
1916
+ word: 01101001
1917
+ sage: Words()("01101001", datatype='str')
1918
+ word: 01101001
1919
+
1920
+ Word with iterator::
1921
+
1922
+ sage: from itertools import count
1923
+ sage: Words()(count())
1924
+ 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,...
1925
+ sage: Words()(iter("abbabaab")) # iterators default to infinite words
1926
+ word: abbabaab
1927
+ sage: Words()(iter("abbabaab"), length='unknown')
1928
+ word: abbabaab
1929
+ sage: Words()(iter("abbabaab"), length='finite')
1930
+ word: abbabaab
1931
+
1932
+ Word with function (a 'callable')::
1933
+
1934
+ sage: f = lambda n : add(Integer(n).digits(2)) % 2
1935
+ sage: Words()(f)
1936
+ word: 0110100110010110100101100110100110010110...
1937
+ sage: Words()(f, length=8)
1938
+ word: 01101001
1939
+
1940
+ Word over a string with a parent::
1941
+
1942
+ sage: w = Words('abc')("abbabaab"); w
1943
+ word: abbabaab
1944
+ sage: w.parent()
1945
+ Finite words over {'a', 'b', 'c'}
1946
+
1947
+ The fourty first letters of the word are checked if they are in the
1948
+ parent alphabet::
1949
+
1950
+ sage: Words("ab")("abca")
1951
+ Traceback (most recent call last):
1952
+ ...
1953
+ ValueError: c not in alphabet
1954
+ sage: Words("ab")("abca", check=False)
1955
+ word: abca
1956
+
1957
+ The default parent is the combinatorial class of all words::
1958
+
1959
+ sage: w = Words()("abbabaab"); w
1960
+ word: abbabaab
1961
+ sage: w.parent()
1962
+ Finite words over Set of Python objects of class 'object'
1963
+
1964
+ Creation of a word from a word::
1965
+
1966
+ sage: Words([0,1,2,3])(Words([2,3])([2,2,2,3,3,2]))
1967
+ word: 222332
1968
+ sage: _.parent()
1969
+ Finite words over {0, 1, 2, 3}
1970
+
1971
+ ::
1972
+
1973
+ sage: Words([3,2,1])(Words([2,3])([2,2,2,3,3,2]))
1974
+ word: 222332
1975
+ sage: _.parent()
1976
+ Finite words over {3, 2, 1}
1977
+
1978
+ Construction of a word from a word when the parents are the same::
1979
+
1980
+ sage: W = Words()
1981
+ sage: w = W(range(8))
1982
+ sage: z = W(w)
1983
+ sage: w is z
1984
+ True
1985
+
1986
+ Construction of a word path from a finite word::
1987
+
1988
+ sage: W = Words('abcd')
1989
+ sage: P = WordPaths('abcd') # needs sage.modules
1990
+ sage: w = W('aaab')
1991
+ sage: P(w) # needs sage.modules
1992
+ Path: aaab
1993
+
1994
+ Construction of a word path from a Christoffel word::
1995
+
1996
+ sage: w = words.ChristoffelWord(5,8)
1997
+ sage: w
1998
+ word: 0010010100101
1999
+ sage: P = WordPaths([0,1,2,3]) # needs sage.modules
2000
+ sage: P(w) # needs sage.modules
2001
+ Path: 0010010100101
2002
+
2003
+ Construction of a word represented by a list from a word
2004
+ represented by a str ::
2005
+
2006
+ sage: w = Word('ababbbabab')
2007
+ sage: type(w)
2008
+ <class 'sage.combinat.words.word.FiniteWord_str'>
2009
+ sage: z = Word(w, datatype='list')
2010
+ sage: type(z)
2011
+ <class 'sage.combinat.words.word.FiniteWord_list'>
2012
+ sage: y = Word(w, alphabet='abc', datatype='list')
2013
+ sage: type(y)
2014
+ <class 'sage.combinat.words.word.FiniteWord_list'>
2015
+
2016
+ Creation of a word from a concatenation of words::
2017
+
2018
+ sage: W = Words()
2019
+ sage: w = W() * W('a')
2020
+ sage: Z = Words('ab')
2021
+ sage: Z(w)
2022
+ word: a
2023
+
2024
+ Creation of a word path from a FiniteWord_iter::
2025
+
2026
+ sage: w = words.FibonacciWord()
2027
+ sage: f = w[:100]
2028
+ sage: P = WordPaths([0,1,2,3]) # needs sage.modules
2029
+ sage: p = P(f); p # needs sage.modules
2030
+ Path: 0100101001001010010100100101001001010010...
2031
+ sage: p.length() # needs sage.modules
2032
+ 100
2033
+
2034
+ Creation of a word path from a :class:`FiniteWord_callable`::
2035
+
2036
+ sage: g = Word(lambda n: n%2, length=100)
2037
+ sage: P = WordPaths([0,1,2,3]) # needs sage.modules
2038
+ sage: p = P(g); p # needs sage.modules
2039
+ Path: 0101010101010101010101010101010101010101...
2040
+ sage: p.length() # needs sage.modules
2041
+ 100
2042
+
2043
+ Creation of a word from a pickled function::
2044
+
2045
+ sage: f = lambda n: n % 10
2046
+ sage: from sage.misc.fpickle import pickle_function
2047
+ sage: s = pickle_function(f)
2048
+ sage: Word(s, datatype='pickled_function')
2049
+ word: 0123456789012345678901234567890123456789...
2050
+
2051
+ If the alphabet is a subset of [0, 255], then it uses char as datatype::
2052
+
2053
+ sage: type(Word([0,1,1,2,0], alphabet=list(range(256))))
2054
+ <class 'sage.combinat.words.word.FiniteWord_char'>
2055
+
2056
+ If the alphabet is a subset of [0, 255], then the letters must
2057
+ convert to an unsigned char. Otherwise an error is raised before
2058
+ the check is done::
2059
+
2060
+ sage: type(Word([0,1,1,2,0,257], alphabet=list(range(256))))
2061
+ Traceback (most recent call last):
2062
+ ...
2063
+ OverflowError: value too large to convert to unsigned char
2064
+ sage: type(Word([0,1,1,2,0,258], alphabet=list(range(257))))
2065
+ Traceback (most recent call last):
2066
+ ...
2067
+ ValueError: 258 not in alphabet
2068
+ sage: type(Word([0,1,1,2,0,103], alphabet=list(range(100))))
2069
+ Traceback (most recent call last):
2070
+ ...
2071
+ ValueError: 103 not in alphabet
2072
+
2073
+ Check that the type is rightly guessed for parking functions which are
2074
+ callable::
2075
+
2076
+ sage: p = ParkingFunction([2,2,1])
2077
+ sage: Word(p).parent()
2078
+ Finite words over Set of Python objects of class 'object'
2079
+ """
2080
+ # try to guess `length` from the `datatype` or `data` if not given
2081
+ if length is None or length == 'unknown':
2082
+ if data is None:
2083
+ length = 'finite'
2084
+ elif datatype in ('callable', 'pickled_function'):
2085
+ length = 'infinite'
2086
+ elif datatype in ('list', 'char', 'str', 'tuple'):
2087
+ length = 'finite'
2088
+ elif datatype is None:
2089
+ try:
2090
+ length = len(data)
2091
+ except TypeError:
2092
+ if callable(data):
2093
+ length = 'infinite'
2094
+
2095
+ # now build finite/infinite or unknown length words
2096
+ if length == 'finite' or length in ZZ:
2097
+ return self.finite_words()(data, datatype=datatype, length=length, caching=caching, check=check)
2098
+
2099
+ elif length == 'infinite' or length == Infinity:
2100
+ return self.infinite_words()(data, datatype=datatype, check=check, caching=caching)
2101
+
2102
+ elif length == 'unknown' or length is None:
2103
+ from sage.combinat.words.abstract_word import Word_class
2104
+ if isinstance(data, Word_class):
2105
+ w = self._word_from_word(data)
2106
+ elif isinstance(data, Iterable):
2107
+ w = self._word_from_iter(data, caching)
2108
+ else:
2109
+ raise ValueError("cannot guess a datatype from data (={!r}); please specify one".format(data))
2110
+
2111
+ if check:
2112
+ w.parent()._check(w)
2113
+ return w
2114
+
2115
+ else:
2116
+ raise ValueError("invalid argument length (={!r})".format(length))
2117
+
2118
+ def _repr_(self):
2119
+ r"""
2120
+ Return a string representation of ``self``.
2121
+
2122
+ EXAMPLES::
2123
+
2124
+ sage: Words('ab', finite=False)._repr_()
2125
+ "Infinite words over {'a', 'b'}"
2126
+ """
2127
+ return "Finite and infinite words over {!r}".format(self.alphabet())
2128
+
2129
+
2130
+ class Words_n(Parent):
2131
+ r"""
2132
+ The set of words of fixed length on a given alphabet.
2133
+ """
2134
+ def __init__(self, words, n):
2135
+ r"""
2136
+ INPUT:
2137
+
2138
+ - ``words`` -- set of finite words
2139
+
2140
+ - ``n`` -- nonnegative integer
2141
+
2142
+ TESTS::
2143
+
2144
+ sage: Words([0,1], length=-42)
2145
+ Traceback (most recent call last):
2146
+ ...
2147
+ ValueError: n = -42 must be nonnegative
2148
+ """
2149
+ n = ZZ(n)
2150
+ if n < 0:
2151
+ raise ValueError("n = {} must be nonnegative".format(n))
2152
+ self._words = words
2153
+ self._n = n
2154
+
2155
+ Parent.__init__(self, category=Sets(), facade=(words,))
2156
+
2157
+ def __setstate__(self, state):
2158
+ r"""
2159
+ TESTS::
2160
+
2161
+ sage: import os, tempfile
2162
+ sage: W = Words('ab', 10)
2163
+ sage: with tempfile.TemporaryDirectory() as d:
2164
+ ....: filename = os.path.join(d, 'test.sobj')
2165
+ ....: W.save(filename)
2166
+ ....: load(filename)
2167
+ Words of length 10 over {'a', 'b'}
2168
+ """
2169
+ # add a default to support old pickles from #19619
2170
+ self._n = state.get('_n')
2171
+ self._words = state.get('_words', FiniteWords())
2172
+
2173
+ def alphabet(self):
2174
+ r"""
2175
+ Return the underlying alphabet.
2176
+
2177
+ EXAMPLES::
2178
+
2179
+ sage: Words([0,1], 4).alphabet()
2180
+ {0, 1}
2181
+ """
2182
+ return self._words.alphabet()
2183
+
2184
+ def __call__(self, data, *args, **kwds):
2185
+ r"""
2186
+ INPUT:
2187
+
2188
+ - all arguments are sent directly to the underlying set of finite words.
2189
+ See the documentation there for the actual input.
2190
+
2191
+ TESTS::
2192
+
2193
+ sage: Words(5,3)([1,2,3])
2194
+ word: 123
2195
+ sage: Words(5,3)([1,2,3,1])
2196
+ Traceback (most recent call last):
2197
+ ...
2198
+ ValueError: wrong length
2199
+ """
2200
+ if 'length' in kwds:
2201
+ if kwds['length'] != self._n:
2202
+ raise ValueError("wrong length")
2203
+ else:
2204
+ kwds['length'] = self._n
2205
+ w = self._words(data, *args, **kwds)
2206
+
2207
+ if kwds.get('check', True):
2208
+ if w.length() != self._n:
2209
+ raise ValueError("wrong length")
2210
+ return w
2211
+
2212
+ def list(self):
2213
+ r"""
2214
+ Return a list of all the words contained in ``self``.
2215
+
2216
+ EXAMPLES::
2217
+
2218
+ sage: Words(0,0).list()
2219
+ [word: ]
2220
+ sage: Words(5,0).list()
2221
+ [word: ]
2222
+ sage: Words(['a','b','c'],0).list()
2223
+ [word: ]
2224
+ sage: Words(5,1).list()
2225
+ [word: 1, word: 2, word: 3, word: 4, word: 5]
2226
+ sage: Words(['a','b','c'],2).list()
2227
+ [word: aa, word: ab, word: ac, word: ba, word: bb, word: bc, word: ca, word: cb, word: cc]
2228
+ """
2229
+ return list(self)
2230
+
2231
+ def _an_element_(self):
2232
+ r"""
2233
+ Return an element of ``self``.
2234
+
2235
+ EXAMPLES::
2236
+
2237
+ sage: W = Words(2, 3); W
2238
+ Words of length 3 over {1, 2}
2239
+ sage: W.an_element()
2240
+ word: 121
2241
+
2242
+ sage: W = Words("bac", 7); W
2243
+ Words of length 7 over {'b', 'a', 'c'}
2244
+ sage: W.an_element()
2245
+ word: bacbacb
2246
+
2247
+ sage: W = Words("baczxy", 5); W
2248
+ Words of length 5 over {'b', 'a', 'c', 'z', 'x', 'y'}
2249
+ sage: W.an_element()
2250
+ word: baczx
2251
+ """
2252
+ letters = list(self.alphabet().some_elements())
2253
+ r = self._n % len(letters)
2254
+ q = (self._n - r) / len(letters)
2255
+ return self(letters * int(q) + letters[:r])
2256
+
2257
+ def random_element(self, *args, **kwds):
2258
+ r"""
2259
+ Return a random word in this set.
2260
+
2261
+ EXAMPLES::
2262
+
2263
+ sage: W = Words('ab', 4)
2264
+ sage: W.random_element() # random
2265
+ word: bbab
2266
+ sage: W.random_element() in W
2267
+ True
2268
+
2269
+ sage: W = Words(ZZ, 5)
2270
+ sage: W.random_element() # random
2271
+ word: 1,2,2,-1,12
2272
+ sage: W.random_element() in W
2273
+ True
2274
+
2275
+ TESTS::
2276
+
2277
+ sage: _ = Words(GF(5),4).random_element() # needs sage.rings.finite_rings
2278
+
2279
+ Check that :issue:`18283` is fixed::
2280
+
2281
+ sage: w = Words('abc', 5).random_element()
2282
+ sage: w.length()
2283
+ 5
2284
+ """
2285
+ return self._words.random_element(length=self._n, *args, **kwds)
2286
+
2287
+ def _repr_(self):
2288
+ """
2289
+ EXAMPLES::
2290
+
2291
+ sage: Words(3,5) # indirect doctest
2292
+ Words of length 5 over {1, 2, 3}
2293
+ """
2294
+ from sage.combinat.words.word_options import word_options
2295
+ if word_options['old_repr']:
2296
+ return "Words over {} of length {}".format(self.alphabet(), self._n)
2297
+ return "Words of length {} over {}".format(self._n, self.alphabet())
2298
+
2299
+ def __contains__(self, x):
2300
+ """
2301
+ EXAMPLES::
2302
+
2303
+ sage: W = Words(3,5)
2304
+ sage: W.an_element() in W
2305
+ True
2306
+
2307
+ sage: 2 in Words(length=3)
2308
+ False
2309
+ sage: [1,'a',3] in Words(length=3)
2310
+ False
2311
+ sage: [1,2] in Words(length=3)
2312
+ False
2313
+ sage: "abc" in Words(length=3)
2314
+ False
2315
+ sage: Words("abc")("ababc") in Words(length=3)
2316
+ False
2317
+ sage: Words([0,1])([1,0,1]) in Words([0,1], length=3)
2318
+ True
2319
+ """
2320
+ return x in self._words and x.length() == self._n
2321
+
2322
+ def cardinality(self):
2323
+ r"""
2324
+ Return the number of words of length `n` from alphabet.
2325
+
2326
+ EXAMPLES::
2327
+
2328
+ sage: Words(['a','b','c'], 4).cardinality()
2329
+ 81
2330
+ sage: Words(3, 4).cardinality()
2331
+ 81
2332
+ sage: Words(0,0).cardinality()
2333
+ 1
2334
+ sage: Words(5,0).cardinality()
2335
+ 1
2336
+ sage: Words(['a','b','c'],0).cardinality()
2337
+ 1
2338
+ sage: Words(0,1).cardinality()
2339
+ 0
2340
+ sage: Words(5,1).cardinality()
2341
+ 5
2342
+ sage: Words(['a','b','c'],1).cardinality()
2343
+ 3
2344
+ sage: Words(7,13).cardinality()
2345
+ 96889010407
2346
+ sage: Words(['a','b','c','d','e','f','g'],13).cardinality()
2347
+ 96889010407
2348
+ """
2349
+ return self.alphabet().cardinality() ** self._n
2350
+
2351
+ __len__ = cardinality
2352
+
2353
+ def __iter__(self):
2354
+ r"""
2355
+ TESTS::
2356
+
2357
+ sage: [w for w in Words(['a', 'b'], 2)]
2358
+ [word: aa, word: ab, word: ba, word: bb]
2359
+ sage: [w for w in Words(['b', 'a'], 2)]
2360
+ [word: bb, word: ba, word: ab, word: aa]
2361
+ sage: [w for w in Words(['a', 'b'], 0)]
2362
+ [word: ]
2363
+ sage: [w for w in Words([], 3)]
2364
+ []
2365
+ """
2366
+ return self._words.iterate_by_length(self._n)
2367
+
2368
+ def iterate_by_length(self, length):
2369
+ r"""
2370
+ All words in this class are of the same length, so use iterator
2371
+ instead.
2372
+
2373
+ TESTS::
2374
+
2375
+ sage: W = Words(['a', 'b'], 2)
2376
+ sage: list(W.iterate_by_length(2))
2377
+ [word: aa, word: ab, word: ba, word: bb]
2378
+ sage: list(W.iterate_by_length(1))
2379
+ []
2380
+ """
2381
+ if length == self._n:
2382
+ return iter(self)
2383
+ else:
2384
+ return iter([])
2385
+
2386
+
2387
+ ###############
2388
+ # old pickles #
2389
+ ###############
2390
+
2391
+
2392
+ register_unpickle_override("sage.combinat.words.words", "Words_over_OrderedAlphabet", FiniteOrInfiniteWords)
2393
+ register_unpickle_override("sage.combinat.words.words", "Words_over_Alphabet", FiniteOrInfiniteWords)
2394
+ register_unpickle_override("sage.combinat.words.words", "FiniteWords_length_k_over_OrderedAlphabet", Words_n)
2395
+ register_unpickle_override("sage.combinat.words.words", "FiniteWords_over_OrderedAlphabet", FiniteWords)
2396
+ register_unpickle_override("sage.combinat.words.words", "InfiniteWords_over_OrderedAlphabet", InfiniteWords)