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
sage/databases/oeis.py ADDED
@@ -0,0 +1,2058 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ r"""
3
+ The On-Line Encyclopedia of Integer Sequences (OEIS)
4
+
5
+ You can query the OEIS (Online Database of Integer Sequences) through Sage in
6
+ order to:
7
+
8
+ - identify a sequence from its first terms.
9
+ - obtain more terms, formulae, references, etc. for a given sequence.
10
+
11
+ EXAMPLES::
12
+
13
+ sage: oeis
14
+ The On-Line Encyclopedia of Integer Sequences (https://oeis.org/)
15
+
16
+ What about a sequence starting with `3, 7, 15, 1` ?
17
+
18
+ ::
19
+
20
+ sage: # optional - internet
21
+ sage: search = oeis([3, 7, 15, 1], max_results=4); search # random
22
+ 0: A001203: Simple continued fraction expansion of Pi.
23
+ 1: A240698: Partial sums of divisors of n, cf. A027750.
24
+ 2: A082495: a(n) = (2^n - 1) mod n.
25
+ 3: A165416: Irregular array read by rows: The n-th row contains those
26
+ distinct positive integers that each, when written in binary,
27
+ occurs as a substring in binary n.
28
+ sage: [u.id() for u in search] # random
29
+ ['A001203', 'A240698', 'A082495', 'A165416']
30
+ sage: c = search[0]; c
31
+ A001203: Simple continued fraction expansion of Pi.
32
+
33
+ ::
34
+
35
+ sage: # optional - internet
36
+ sage: c.first_terms(15)
37
+ (3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14, 2, 1)
38
+ sage: c.examples()
39
+ 0: Pi = 3.1415926535897932384...
40
+ 1: = 3 + 1/(7 + 1/(15 + 1/(1 + 1/(292 + ...))))
41
+ 2: = [a_0; a_1, a_2, a_3, ...] = [3; 7, 15, 1, 292, ...].
42
+ sage: c.comments()
43
+ 0: The first 5821569425 terms were computed by _Eric W. Weisstein_ on Sep 18 2011.
44
+ 1: The first 10672905501 terms were computed by _Eric W. Weisstein_ on Jul 17 2013.
45
+ 2: The first 15000000000 terms were computed by _Eric W. Weisstein_ on Jul 27 2013.
46
+ 3: The first 30113021586 terms were computed by _Syed Fahad_ on Apr 27 2021.
47
+
48
+ ::
49
+
50
+ sage: # optional - internet
51
+ sage: x = c.natural_object(); type(x)
52
+ <class 'sage.rings.continued_fraction.ContinuedFraction_periodic'>
53
+ sage: x.convergents()[:7]
54
+ [3, 22/7, 333/106, 355/113, 103993/33102, 104348/33215, 208341/66317]
55
+ sage: RR(x.value())
56
+ 3.14159265358979
57
+ sage: RR(x.value()) == RR(pi)
58
+ True
59
+
60
+ What about posets? Are they hard to count? To which other structures are they
61
+ related?
62
+
63
+ ::
64
+
65
+ sage: # optional - internet
66
+ sage: [Posets(i).cardinality() for i in range(10)]
67
+ [1, 1, 2, 5, 16, 63, 318, 2045, 16999, 183231]
68
+ sage: oeis(_)
69
+ 0: A000112: Number of partially ordered sets ("posets") with n unlabeled elements.
70
+ sage: p = _[0]
71
+ sage: 'hard' in p.keywords()
72
+ True
73
+ sage: len(p.formulas())
74
+ 0
75
+ sage: len(p.first_terms())
76
+ 17
77
+ sage: p.cross_references(fetch=True) # random
78
+ 0: A000798: Number of different quasi-orders (or topologies, or transitive digraphs)
79
+ with n labeled elements.
80
+ 1: A001035: Number of partially ordered sets ("posets") with n labeled elements
81
+ (or labeled acyclic transitive digraphs).
82
+ 2: A001930: Number of topologies, or transitive digraphs with n unlabeled nodes.
83
+ 3: A006057: Number of topologies on n labeled points satisfying axioms T_0-T_4.
84
+ 4: A079263: Number of constrained mixed models with n factors.
85
+ 5: A079265: Number of antisymmetric transitive binary relations on n unlabeled points.
86
+ 6: A263859: Triangle read by rows: T(n,k) (n>=1, k>=0) is the number of posets
87
+ with n elements and rank k (or depth k+1).
88
+ 7: A316978: Number of factorizations of n into factors > 1 with no equivalent primes.
89
+ 8: A319559: Number of non-isomorphic T_0 set systems of weight n.
90
+ 9: A326939: Number of T_0 sets of subsets of {1..n} that cover all n vertices.
91
+ 10: A326943: Number of T_0 sets of subsets of {1..n} that cover all n vertices and
92
+ are closed under intersection.
93
+ ...
94
+
95
+ What does the Taylor expansion of the `e^{e^x-1}` function have to do with
96
+ primes ?
97
+
98
+ ::
99
+
100
+ sage: # optional - internet, needs sage.symbolic
101
+ sage: x = var('x') ; f(x) = e^(e^x - 1)
102
+ sage: L = [a*factorial(b) for a,b in taylor(f(x), x, 0, 20).coefficients()]; L
103
+ [1, 1, 2, 5, 15, 52, 203, 877, 4140, 21147, 115975, 678570, 4213597,
104
+ 27644437, 190899322, 1382958545, 10480142147, 82864869804, 682076806159,
105
+ 5832742205057, 51724158235372]
106
+ sage: oeis(L)
107
+ 0: A000110: Bell or exponential numbers: number of ways to partition
108
+ a set of n labeled elements.
109
+ 1: A292935: E.g.f.: exp(exp(-x) - 1).
110
+ sage: b = _[0]
111
+ sage: b.formulas()[0]
112
+ 'E.g.f.: exp(exp(x) - 1).'
113
+ sage: [i for i in b.comments() if 'prime' in i][-1]
114
+ 'When n is prime, ...'
115
+ sage: [n for n in range(2, 20) if (b(n)-2) % n == 0]
116
+ [2, 3, 5, 7, 11, 13, 17, 19]
117
+
118
+ .. SEEALSO::
119
+
120
+ - If you plan to do a lot of automatic searches for subsequences, you
121
+ should consider installing :mod:`SloaneEncyclopedia
122
+ <sage.databases.sloane>`, a local partial copy of the OEIS.
123
+ - Some infinite OEIS sequences are implemented in Sage, via the
124
+ :mod:`sloane_functions <sage.combinat.sloane_functions>` module.
125
+
126
+ AUTHORS:
127
+
128
+ - Thierry Monteil (2012-02-10 -- 2013-06-21): initial version.
129
+ - Vincent Delecroix (2014): modifies continued fractions because of :issue:`14567`
130
+ - Moritz Firsching (2016): modifies handling of dead sequence, see :issue:`17330`
131
+ - Thierry Monteil (2019): refactorization (unique representation :issue:`28480`,
132
+ laziness :issue:`28627`)
133
+ """
134
+
135
+ import re
136
+ from collections import defaultdict
137
+ from ssl import create_default_context as default_context
138
+ from urllib.parse import urlencode
139
+ # ****************************************************************************
140
+ # Copyright (C) 2012 Thierry Monteil <sage!lma.metelu.net>
141
+ #
142
+ # Distributed under the terms of the GNU General Public License (GPL)
143
+ # as published by the Free Software Foundation; either version 2 of
144
+ # the License, or (at your option) any later version.
145
+ # https://www.gnu.org/licenses/
146
+ # ****************************************************************************
147
+ from urllib.request import urlopen, Request
148
+
149
+ from sage.version import version
150
+ from sage.cpython.string import bytes_to_str
151
+ from sage.misc.cachefunc import cached_method
152
+ from sage.misc.flatten import flatten
153
+ from sage.misc.html import HtmlFragment
154
+ from sage.misc.temporary_file import tmp_filename
155
+ from sage.misc.unknown import Unknown
156
+ from sage.misc.verbose import verbose
157
+ from sage.repl.preparse import preparse
158
+ from sage.rings.integer import Integer
159
+ from sage.structure.sage_object import SageObject
160
+ from sage.structure.unique_representation import UniqueRepresentation
161
+
162
+ oeis_url = 'https://oeis.org/'
163
+
164
+
165
+ def _fetch(url):
166
+ r"""
167
+ Fetch the given ``url``.
168
+
169
+ INPUT:
170
+
171
+ - ``url`` -- string corresponding to the URL to be fetched
172
+
173
+ OUTPUT: string representing the fetched web page
174
+
175
+ TESTS::
176
+
177
+ sage: from sage.databases.oeis import _fetch, oeis_url # optional -- internet
178
+ sage: _fetch(oeis_url + 'hints.html')[-8:-1] # optional -- internet
179
+ '</html>'
180
+ """
181
+ try:
182
+ verbose("Fetching URL %s ..." % url, caller_name='OEIS')
183
+ with urlopen(Request(url, headers={'User-Agent': f'SageMath/{version}'})) as f:
184
+ return bytes_to_str(f.read())
185
+ except OSError as msg:
186
+ raise OSError("%s\nerror fetching %s" % (msg, url))
187
+
188
+
189
+ def _urls(html_string):
190
+ r"""
191
+ Return the list of URLs contained in ``html_string``.
192
+
193
+ Only URLs provided by HTML hyperlinks (``href`` attribute of ``<a>`` tags)
194
+ in are returned, not text strings starting with ``http://``.
195
+
196
+ INPUT:
197
+
198
+ - ``html_string`` -- string representing some HTML code
199
+
200
+ OUTPUT: list of (string) URLs contained in ``html_string``
201
+
202
+ EXAMPLES::
203
+
204
+ sage: from sage.databases.oeis import _urls
205
+ sage: html = 'http://example.com is not a link, but <a href="http://sagemath.org/">sagemath</a> is'
206
+ sage: _urls(html)
207
+ ['http://sagemath.org/']
208
+ """
209
+ urls = []
210
+ from html.parser import HTMLParser
211
+
212
+ class MyHTMLParser(HTMLParser):
213
+ def handle_starttag(self, tag, attrs):
214
+ if tag == 'a':
215
+ for attr in attrs:
216
+ if attr[0] == 'href':
217
+ urls.append(attr[1])
218
+ MyHTMLParser().feed(html_string)
219
+ return urls
220
+
221
+
222
+ def to_tuple(string):
223
+ """
224
+ Convert a string to a tuple of integers.
225
+
226
+ EXAMPLES::
227
+
228
+ sage: from sage.databases.oeis import to_tuple
229
+ sage: to_tuple('12,55,273')
230
+ (12, 55, 273)
231
+ """
232
+ return tuple(Integer(x) for x in string.split(",") if x)
233
+
234
+
235
+ class OEIS:
236
+ r"""
237
+ The On-Line Encyclopedia of Integer Sequences.
238
+
239
+ ``OEIS`` is a class representing the On-Line Encyclopedia of Integer
240
+ Sequences. You can query it using its methods, but ``OEIS`` can also be
241
+ called directly with three arguments:
242
+
243
+ - ``query`` -- it can be:
244
+
245
+ - a string representing an OEIS ID (e.g. 'A000045').
246
+ - an integer representing an OEIS ID (e.g. 45).
247
+ - a list representing a sequence of integers.
248
+ - a string, representing a text search.
249
+
250
+ - ``max_results`` -- (integer, default: 30) the maximum number of
251
+ results to return, they are sorted according to their relevance. In
252
+ any cases, the OEIS website will never provide more than 100 results.
253
+
254
+ - ``first_result`` -- (integer, default: 0) allow to skip the
255
+ ``first_result`` first results in the search, to go further.
256
+ This is useful if you are looking for a sequence that may appear
257
+ after the 100 first found sequences.
258
+
259
+ OUTPUT:
260
+
261
+ - if ``query`` is an integer or an OEIS ID (e.g. 'A000045'), returns
262
+ the associated OEIS sequence.
263
+
264
+ - if ``query`` is a string, returns a tuple of OEIS sequences whose
265
+ description corresponds to the query. Those sequences can be used
266
+ without the need to fetch the database again.
267
+
268
+ - if ``query`` is a list or tuple of integers, returns a tuple of
269
+ OEIS sequences containing it as a subsequence. Those sequences
270
+ can be used without the need to fetch the database again.
271
+
272
+ EXAMPLES::
273
+
274
+ sage: oeis
275
+ The On-Line Encyclopedia of Integer Sequences (https://oeis.org/)
276
+
277
+ A particular sequence can be called by its A-number or number::
278
+
279
+ sage: oeis('A000040') # optional -- internet
280
+ A000040: The prime numbers.
281
+ sage: oeis(45) # optional -- internet
282
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
283
+
284
+ The database can be searched by subsequence::
285
+
286
+ sage: search = oeis([1,2,3,5,8,13]); search # optional -- internet
287
+ 0: A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
288
+ 1: A290689: Number of transitive rooted trees with n nodes.
289
+ 2: A027926: Triangular array T read by rows: T(n,0) = T(n,2n) = 1 for n >= 0;
290
+ T(n,1) = 1 for n >= 1; T(n,k) = T(n-1,k-2) + T(n-1,k-1)
291
+ for k = 2..2n-1, n >= 2.
292
+
293
+ sage: fibo = search[0] # optional -- internet
294
+
295
+ sage: fibo.name() # optional -- internet
296
+ 'Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.'
297
+
298
+ sage: print(fibo.first_terms()) # optional -- internet
299
+ (0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597,
300
+ 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418,
301
+ 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465,
302
+ 14930352, 24157817, 39088169, 63245986, 102334155)
303
+
304
+ sage: fibo.cross_references()[0] # optional -- internet
305
+ 'A001622'
306
+
307
+ sage: fibo == oeis(45) # optional -- internet
308
+ True
309
+
310
+ sage: sfibo = oeis('A039834') # optional -- internet
311
+ sage: sfibo.first_terms() # optional -- internet
312
+ (1, 1, 0, 1, -1, 2, -3, 5, -8, 13, -21, 34, -55, 89, -144, 233,
313
+ -377, 610, -987, 1597, -2584, 4181, -6765, 10946, -17711, 28657,
314
+ -46368, 75025, -121393, 196418, -317811, 514229, -832040, 1346269,
315
+ -2178309, 3524578, -5702887, 9227465, -14930352, 24157817)
316
+
317
+ sage: tuple(abs(i) for i in sfibo.first_terms())[2:20] == fibo.first_terms()[:18] # optional -- internet
318
+ True
319
+
320
+ sage: fibo.formulas()[4] # optional -- internet
321
+ 'F(n) = F(n-1) + F(n-2) = -(-1)^n F(-n).'
322
+
323
+ sage: fibo.comments()[6] # optional -- internet
324
+ "F(n+2) = number of binary sequences of length n that have no
325
+ consecutive 0's."
326
+
327
+ sage: fibo.links()[0] # optional -- internet
328
+ 'https://oeis.org/A000045/b000045.txt'
329
+
330
+ The database can be searched by description::
331
+
332
+ sage: oeis('prime gap factorization', max_results=4) # random # optional -- internet
333
+ 0: A073491: Numbers having no prime gaps in their factorization.
334
+ 1: A073485: Product of any number of consecutive primes; squarefree numbers
335
+ with no gaps in their prime factorization.
336
+ 2: A073490: Number of prime gaps in factorization of n.
337
+ 3: A073492: Numbers having at least one prime gap in their factorization.
338
+
339
+ .. NOTE::
340
+
341
+ The following will fetch the OEIS database only once::
342
+
343
+ sage: oeis([1,2,3,5,8,13]) # optional -- internet
344
+ 0: A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
345
+ 1: A290689: Number of transitive rooted trees with n nodes.
346
+ 2: A027926: Triangular array T read by rows: T(n,0) = T(n,2n) = 1 for n >= 0;
347
+ T(n,1) = 1 for n >= 1; T(n,k) = T(n-1,k-2) + T(n-1,k-1)
348
+ for k = 2..2n-1, n >= 2.
349
+
350
+ sage: oeis('A000045') # optional -- internet
351
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
352
+
353
+ Indeed, due to some caching mechanism, the sequence is not re-created
354
+ when called from its ID.
355
+
356
+ TESTS::
357
+
358
+ sage: oeis((1,2,5,16,61)) # optional -- internet
359
+ 0: A000111: ...
360
+ sage: oeis('A000040') # optional -- internet
361
+ A000040: The prime numbers.
362
+ sage: oeis('A000045') # optional -- internet
363
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
364
+ """
365
+
366
+ def __call__(self, query, max_results=3, first_result=0):
367
+ r"""
368
+ See the documentation of :class:`OEIS`.
369
+
370
+ TESTS::
371
+
372
+ sage: oeis()
373
+ Traceback (most recent call last):
374
+ ...
375
+ TypeError: ...__call__() ...
376
+ """
377
+ if isinstance(query, str):
378
+ if re.match('^A[0-9]{6}$', query):
379
+ return self.find_by_id(query)
380
+ else:
381
+ return self.find_by_description(query, max_results, first_result)
382
+ elif isinstance(query, (int, Integer)):
383
+ return self.find_by_id(query)
384
+ elif isinstance(query, (list, tuple)):
385
+ return self.find_by_subsequence(query, max_results, first_result)
386
+
387
+ def __repr__(self) -> str:
388
+ r"""
389
+ Return the representation of ``self``.
390
+
391
+ TESTS::
392
+
393
+ sage: oeis
394
+ The On-Line Encyclopedia of Integer Sequences (https://oeis.org/)
395
+ """
396
+ return "The On-Line Encyclopedia of Integer Sequences (%s)" % oeis_url
397
+
398
+ def find_by_id(self, ident, fetch=False):
399
+ r"""
400
+ INPUT:
401
+
402
+ - ``ident`` -- string representing the A-number of the sequence
403
+ or an integer representing its number
404
+
405
+ - ``fetch`` -- boolean (default: ``False``); whether to force fetching the
406
+ content of the sequence on the internet
407
+
408
+ OUTPUT: the OEIS sequence whose A-number or number corresponds to ``ident``
409
+
410
+ EXAMPLES::
411
+
412
+ sage: oeis.find_by_id('A000040') # optional -- internet
413
+ A000040: The prime numbers.
414
+
415
+ sage: oeis.find_by_id(40) # optional -- internet
416
+ A000040: The prime numbers.
417
+ """
418
+ sequence = OEISSequence(ident=ident)
419
+ if fetch:
420
+ sequence.online_update()
421
+ return sequence
422
+
423
+ def find_by_entry(self, entry):
424
+ r"""
425
+ INPUT:
426
+
427
+ - ``entry`` -- string corresponding to an entry in the internal format
428
+ of the OEIS
429
+
430
+ OUTPUT: the corresponding OEIS sequence
431
+
432
+ EXAMPLES::
433
+
434
+ sage: entry = '%I A262002\n%N A262002 L.g.f.: log( Sum_{n>=0} x^n/n! * Product_{k=1..n} (k^2 + 1) ).\n%K A262002 nonn'
435
+ sage: s = oeis.find_by_entry(entry)
436
+ sage: s
437
+ A262002: L.g.f.: log( Sum_{n>=0} x^n/n! * Product_{k=1..n} (k^2 + 1) ).
438
+ """
439
+ ident = entry[3:10]
440
+ sequence = OEISSequence(ident=ident)
441
+ sequence._raw = entry
442
+ return sequence
443
+
444
+ def find_by_description(self, description, max_results=3, first_result=0):
445
+ r"""
446
+ Search for OEIS sequences corresponding to the description.
447
+
448
+ INPUT:
449
+
450
+ - ``description`` -- string; the description the searched sequences
451
+
452
+ - ``max_results`` -- (integer, default: 3) the maximum number of results
453
+ we want. In any case, the on-line encyclopedia will not return more
454
+ than 100 results.
455
+
456
+ - ``first_result`` -- (integer, default: 0) allow to skip the
457
+ ``first_result`` first results in the search, to go further.
458
+ This is useful if you are looking for a sequence that may appear
459
+ after the 100 first found sequences.
460
+
461
+ OUTPUT:
462
+
463
+ - a tuple (with fancy formatting) of at most ``max_results`` OEIS
464
+ sequences. Those sequences can be used without the need to fetch the
465
+ database again.
466
+
467
+ EXAMPLES::
468
+
469
+ sage: oeis.find_by_description('prime gap factorization') # optional -- internet
470
+ 0: A...: ...
471
+ 1: A...: ...
472
+ 2: A...: ...
473
+
474
+ sage: prime_gaps = _[2] ; prime_gaps # optional -- internet
475
+ A...
476
+
477
+ sage: oeis('beaver') # optional -- internet
478
+ 0: A...: ...eaver...
479
+ 1: A...: ...eaver...
480
+ 2: A...: ...eaver...
481
+
482
+ sage: oeis('beaver', max_results=4, first_result=2) # optional -- internet
483
+ 0: A...: ...eaver...
484
+ 1: A...: ...eaver...
485
+ 2: A...: ...eaver...
486
+ 3: A...: ...eaver...
487
+ """
488
+ options = {'q': description,
489
+ 'n': str(max_results),
490
+ 'fmt': 'text',
491
+ 'start': str(first_result)}
492
+ url = oeis_url + "search?" + urlencode(options)
493
+ sequence_list = _fetch(url).split('\n\n')[2:-1]
494
+ T = [self.find_by_entry(entry=s) for s in sequence_list]
495
+ return FancyTuple([s for s in T if not s.is_dead()])
496
+
497
+ def find_by_subsequence(self, subsequence, max_results=3, first_result=0):
498
+ r"""
499
+ Search for OEIS sequences containing the given subsequence.
500
+
501
+ INPUT:
502
+
503
+ - ``subsequence`` -- list or tuple of integers
504
+
505
+ - ``max_results`` -- integer (default: 3); the maximum of results requested
506
+
507
+ - ``first_result`` -- integer (default: 0); allow to skip the
508
+ ``first_result`` first results in the search, to go further.
509
+ This is useful if you are looking for a sequence that may appear
510
+ after the 100 first found sequences.
511
+
512
+ OUTPUT:
513
+
514
+ A tuple (with fancy formatting) of at most ``max_results`` OEIS
515
+ sequences. Those sequences can be used without the need to fetch the
516
+ database again.
517
+
518
+ EXAMPLES::
519
+
520
+ sage: oeis.find_by_subsequence([2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]) # optional -- internet # random
521
+ 0: A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
522
+ 1: A212804: Expansion of (1 - x)/(1 - x - x^2).
523
+ 2: A020695: Pisot sequence E(2,3).
524
+
525
+ sage: fibo = _[0] ; fibo # optional -- internet
526
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
527
+ """
528
+ subsequence = str(subsequence)[1:-1]
529
+ return self.find_by_description(subsequence, max_results, first_result)
530
+
531
+ def browse(self):
532
+ r"""
533
+ Open the OEIS web page in a browser.
534
+
535
+ EXAMPLES::
536
+
537
+ sage: oeis.browse() # optional -- webbrowser
538
+ """
539
+ import webbrowser
540
+ webbrowser.open(oeis_url)
541
+
542
+ def _imaginary_entry(self, ident='A999999', keywords=''):
543
+ r"""
544
+ This is an imaginary entry of an OEIS sequence for offline tests.
545
+
546
+ INPUT:
547
+
548
+ - ``ident`` -- string representing the A-number of the sequence
549
+
550
+ - ``keywords`` -- string corresponding to the keyword field of the
551
+ sequence
552
+
553
+ OUTPUT: string representing the entry of the sequence
554
+
555
+ TESTS::
556
+
557
+ sage: oeis._imaginary_entry().split('\n')[0]
558
+ '%I A999999 M9999 N9999'
559
+
560
+ sage: keywords = 'simon,cussonet'
561
+ sage: s = oeis.find_by_entry(entry=oeis._imaginary_entry(ident='A999998', keywords=keywords))
562
+ sage: ','.join(s.keywords()) == keywords
563
+ True
564
+ """
565
+ return ('%I ' + ident + ' M9999 N9999\n'
566
+ '%S ' + ident + ' 1,1,1,1,2,1,1,1,\n'
567
+ '%T ' + ident + ' 1,1,1,1,1,1,1,1,1,\n'
568
+ '%U ' + ident + ' 1,1,1,1,1,1,1,1,1\n'
569
+ '%N ' + ident + ' The characteristic sequence of 42 plus one, starting from 38.\n'
570
+ '%D ' + ident + ' Lewis Carroll, Alice\'s Adventures in Wonderland.\n'
571
+ '%D ' + ident + ' Lewis Carroll, The Hunting of the Snark.\n'
572
+ '%D ' + ident + ' Deep Thought, The Answer to the Ultimate Question of Life, The Universe, and Everything.\n'
573
+ '%H ' + ident + ' Wikipedia, <a href="https://en.wikipedia.org/wiki/42_(number)">42 (number)</a>\n'
574
+ '%H ' + ident + ' See. also <a href="https://github.com/sagemath/sage/issues/42">github issue #42</a>\n'
575
+ '%H ' + ident + ' Do not confuse with the sequence <a href="/A000042">A000042</a> or the sequence <a href="/A000024">A000024</a>\n'
576
+ '%H ' + ident + ' The string http://42.com is not a link.\n'
577
+ '%F ' + ident + ' For n big enough, s(n+1) - s(n) = 0.\n'
578
+ '%Y ' + ident + ' Related sequences are A000042 and its friend A000024.\n'
579
+ '%A ' + ident + ' Anonymous.\n'
580
+ '%O ' + ident + ' 38,4\n'
581
+ '%E ' + ident + ' This sequence does not contain errors.\n'
582
+ '%e ' + ident + ' s(42) + s(43) = 0.\n'
583
+ '%p ' + ident + ' Do not even try, Maple is not able to produce such a sequence.\n'
584
+ '%t ' + ident + ' Mathematica neither.\n'
585
+ '%o ' + ident + ' (Python)\n'
586
+ '%o ' + ident + ' def ' + ident + '(n):\n'
587
+ '%o ' + ident + ' assert(isinstance(n, (int, Integer))), "n must be an integer."\n'
588
+ '%o ' + ident + ' if n < 38:\n'
589
+ '%o ' + ident + ' raise ValueError("the value %s is not accepted" % str(n))\n'
590
+ '%o ' + ident + ' elif n == 42:\n'
591
+ '%o ' + ident + ' return 2\n'
592
+ '%o ' + ident + ' else:\n'
593
+ '%o ' + ident + ' return 1\n'
594
+ '%K ' + ident + ' ' + keywords + '\n'
595
+ '%C ' + ident + ' 42 is the product of the first 4 prime numbers, except 5 and perhaps 1.\n'
596
+ '%C ' + ident + ' Apart from that, i have no comment.')
597
+
598
+ def _imaginary_sequence(self, ident='A999999', keywords='sign,easy'):
599
+ r"""
600
+ This is the OEIS sequence corresponding to the imaginary entry.
601
+ Its main purpose is to allow offline doctesting.
602
+
603
+ INPUT:
604
+
605
+ - ``ident`` -- string representing the A-number of the sequence
606
+
607
+ - ``keywords`` -- string (default: ``'sign,easy'``); a list of words
608
+ separated by commas
609
+
610
+ OUTPUT: OEIS sequence
611
+
612
+ TESTS::
613
+
614
+ sage: s = oeis._imaginary_sequence()
615
+ sage: s
616
+ A999999: The characteristic sequence of 42 plus one, starting from 38.
617
+ sage: s[4]
618
+ 2
619
+ sage: s(42)
620
+ 2
621
+ """
622
+ return self.find_by_entry(entry=self._imaginary_entry(ident=ident, keywords=keywords))
623
+
624
+
625
+ class OEISSequence(SageObject, UniqueRepresentation):
626
+ r"""
627
+ The class of OEIS sequences.
628
+
629
+ This class implements OEIS sequences. They are usually produced by calls to
630
+ the On-Line Encyclopedia of Integer Sequences, represented by the class
631
+ :class:`OEIS`.
632
+
633
+ .. NOTE::
634
+
635
+ Since some sequences do not start with index 0, there is a difference
636
+ between calling and getting item, see :meth:`__call__` for more details
637
+ ::
638
+
639
+ sage: # optional - internet
640
+ sage: sfibo = oeis('A039834')
641
+ sage: sfibo.first_terms()[:10]
642
+ (1, 1, 0, 1, -1, 2, -3, 5, -8, 13)
643
+ sage: sfibo(-2)
644
+ 1
645
+ sage: sfibo(3)
646
+ 2
647
+ sage: sfibo.offsets()
648
+ (-2, 6)
649
+ sage: sfibo[0]
650
+ 1
651
+ sage: sfibo[6]
652
+ -3
653
+
654
+ .. automethod:: __call__
655
+ """
656
+ @staticmethod
657
+ def __classcall__(cls, ident):
658
+ r"""
659
+ Canonicalize the ID of the sequence into a A-number.
660
+
661
+ TESTS::
662
+
663
+ sage: oeis(45) is oeis('A000045')
664
+ True
665
+ """
666
+ if not isinstance(ident, str):
667
+ ident = str(ident)
668
+ ident = 'A000000'[:-len(ident)] + ident
669
+ return super().__classcall__(cls, ident)
670
+
671
+ def __init__(self, ident):
672
+ r"""
673
+ Initialize an OEIS sequence.
674
+
675
+ There is no fetching of additional information about the sequence at
676
+ this point, only the A-number is required to construct a sequence.
677
+
678
+ INPUT:
679
+
680
+ - ``ident`` -- string representing the A-number of the sequence or an
681
+ integer representing its number
682
+
683
+ TESTS::
684
+
685
+ sage: sfibo = oeis('A039834')
686
+
687
+ sage: s = oeis._imaginary_sequence()
688
+ """
689
+ self._id = ident
690
+
691
+ def online_update(self):
692
+ r"""
693
+ Fetch the online OEIS to update the informations about this sequence.
694
+
695
+ TESTS::
696
+
697
+ sage: # optional -- internet
698
+ sage: s = oeis._imaginary_sequence(ident='A004238')
699
+ sage: s
700
+ A004238: The characteristic sequence of 42 plus one, starting from 38.
701
+ sage: s.online_update()
702
+ sage: s
703
+ A004238: a(n) = 100*log(n) rounded to nearest integer.
704
+ """
705
+ options = {'q': self._id, 'n': '1', 'fmt': 'text'}
706
+ url = oeis_url + "search?" + urlencode(options)
707
+ self._raw = _fetch(url).split('\n\n')[2]
708
+ try:
709
+ del self._fields
710
+ except AttributeError:
711
+ pass
712
+
713
+ def _field(self, key, warn=True):
714
+ r"""
715
+ Return the ``key`` field of the entry of ``self``.
716
+
717
+ This method allows to handle the ``_fields`` dictionary in a lazy way.
718
+
719
+ INPUT:
720
+
721
+ - ``warn`` -- ignored
722
+
723
+ TESTS::
724
+
725
+ sage: s = oeis._imaginary_sequence()
726
+ sage: s._field('C')[0]
727
+ '42 is the product of the first 4 prime numbers, except 5 and perhaps 1.'
728
+ """
729
+ try:
730
+ return self._fields[key]
731
+ except AttributeError:
732
+ fields = defaultdict(list)
733
+ for line in self.raw_entry().splitlines():
734
+ fields[line[1]].append(line[11:])
735
+ self._fields = fields
736
+ return self._fields[key]
737
+
738
+ def id(self, format='A'):
739
+ r"""
740
+ The ID of the sequence ``self`` is the A-number that identifies
741
+ ``self``.
742
+
743
+ INPUT:
744
+
745
+ - ``format`` -- string (default: ``'A'``)
746
+
747
+ OUTPUT:
748
+
749
+ - if ``format`` is set to 'A', returns a string of the form 'A000123'.
750
+ - if ``format`` is set to 'int' returns an integer of the form 123.
751
+
752
+ EXAMPLES::
753
+
754
+ sage: f = oeis(45) ; f # optional -- internet
755
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
756
+
757
+ sage: f.id() # optional -- internet
758
+ 'A000045'
759
+
760
+ sage: f.id(format='int') # optional -- internet
761
+ 45
762
+
763
+ TESTS::
764
+
765
+ sage: s = oeis._imaginary_sequence()
766
+ sage: s.id()
767
+ 'A999999'
768
+ sage: s.id(format='int')
769
+ 999999
770
+ """
771
+ if format == 'A':
772
+ return self._id
773
+ elif format == 'int':
774
+ return int(self._id[1:].lstrip("0"))
775
+
776
+ def __hash__(self):
777
+ r"""
778
+ Return the hash of ``self``, which is its numerical OEIS ID.
779
+
780
+ This method allows unique representation of OEIS sequences.
781
+
782
+ OUTPUT: Python integer
783
+
784
+ EXAMPLES::
785
+
786
+ sage: s = oeis([1,2,3,5,8,13])[0] # optional -- internet
787
+ sage: hash(s) # optional -- internet
788
+ 45
789
+
790
+ We have unique representation::
791
+
792
+ sage: t = oeis(45) # optional -- internet
793
+ sage: s is t # optional -- internet
794
+ True
795
+ sage: s == t # optional -- internet
796
+ True
797
+
798
+ TESTS::
799
+
800
+ sage: s = oeis._imaginary_sequence()
801
+ sage: s is oeis._imaginary_sequence()
802
+ True
803
+ sage: s == oeis._imaginary_sequence()
804
+ True
805
+ """
806
+ return self.id(format='int')
807
+
808
+ def raw_entry(self):
809
+ r"""
810
+ Return the raw entry of the sequence ``self``, in the OEIS format.
811
+
812
+ The raw entry is fetched online if needed.
813
+
814
+ OUTPUT: string
815
+
816
+ EXAMPLES::
817
+
818
+ sage: f = oeis(45) ; f # optional -- internet
819
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
820
+
821
+ sage: print(f.raw_entry()) # optional -- internet
822
+ %I A000045 M0692 N0256...
823
+ %S A000045 0,1,1,2,3,5,8,13,21,34,55,89,144,...
824
+ %T A000045 10946,17711,28657,46368,...
825
+ ...
826
+
827
+ TESTS::
828
+
829
+ sage: s = oeis._imaginary_sequence()
830
+ sage: s.raw_entry() == oeis._imaginary_entry(keywords='sign,easy')
831
+ True
832
+ """
833
+ try:
834
+ return self._raw
835
+ except AttributeError:
836
+ self.online_update()
837
+ return self._raw
838
+
839
+ def name(self) -> str:
840
+ r"""
841
+ Return the name of the sequence ``self``.
842
+
843
+ OUTPUT: string
844
+
845
+ EXAMPLES::
846
+
847
+ sage: f = oeis(45) ; f # optional -- internet
848
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
849
+
850
+ sage: f.name() # optional -- internet
851
+ 'Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.'
852
+
853
+ TESTS::
854
+
855
+ sage: s = oeis._imaginary_sequence()
856
+ sage: s.name()
857
+ 'The characteristic sequence of 42 plus one, starting from 38.'
858
+ """
859
+ return self._field('N')[0]
860
+
861
+ def old_IDs(self):
862
+ r"""
863
+ Return the IDs of the sequence ``self`` corresponding to ancestors of OEIS.
864
+
865
+ OUTPUT:
866
+
867
+ - a tuple of at most two strings. When the string starts with `M`, it
868
+ corresponds to the ID of "The Encyclopedia of Integer Sequences" of
869
+ 1995. When the string starts with `N`, it corresponds to the ID of
870
+ the "Handbook of Integer Sequences" of 1973.
871
+
872
+ EXAMPLES::
873
+
874
+ sage: f = oeis(45) ; f # optional -- internet
875
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
876
+
877
+ sage: f.old_IDs() # optional -- internet
878
+ ('M0692', 'N0256')
879
+
880
+ TESTS::
881
+
882
+ sage: s = oeis._imaginary_sequence()
883
+ sage: s.old_IDs()
884
+ ('M9999', 'N9999')
885
+ """
886
+ s = self._field('I')[0]
887
+ # We remove all parts after '#'
888
+ s = s.split('#')[0].strip()
889
+ if not s:
890
+ return ()
891
+ return tuple(s.split(' '))
892
+
893
+ def offsets(self):
894
+ r"""
895
+ Return the offsets of the sequence ``self``.
896
+
897
+ The first offset is the subscript of the first term in the sequence
898
+ ``self``. When, the sequence represents the decimal expansion of a real
899
+ number, it corresponds to the number of digits of its integer part.
900
+
901
+ The second offset is the first term in the sequence ``self`` (starting
902
+ from 1) whose absolute value is greater than 1. This is set to 1 if all
903
+ the terms are 0 or +-1.
904
+
905
+ OUTPUT: tuple of two elements
906
+
907
+ EXAMPLES::
908
+
909
+ sage: f = oeis(45) ; f # optional -- internet
910
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
911
+
912
+ sage: f.offsets() # optional -- internet
913
+ (0, 4)
914
+
915
+ sage: f.first_terms()[:4] # optional -- internet
916
+ (0, 1, 1, 2)
917
+
918
+ TESTS::
919
+
920
+ sage: s = oeis._imaginary_sequence()
921
+ sage: s.offsets()
922
+ (38, 4)
923
+ """
924
+ return to_tuple(self._field('O')[0])
925
+
926
+ def author(self):
927
+ r"""
928
+ Return the author of the sequence in the encyclopedia.
929
+
930
+ OUTPUT: string
931
+
932
+ EXAMPLES::
933
+
934
+ sage: f = oeis(45) ; f # optional -- internet
935
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
936
+
937
+ sage: f.author() # optional -- internet
938
+ '_N. J. A. Sloane_, 1964'
939
+
940
+ TESTS::
941
+
942
+ sage: s = oeis._imaginary_sequence()
943
+ sage: s.author()
944
+ 'Anonymous.'
945
+ """
946
+ return self._field('A')[0]
947
+
948
+ def keywords(self, warn=True):
949
+ r"""
950
+ Return the keywords associated to the sequence ``self``.
951
+
952
+ OUTPUT: tuple of strings
953
+
954
+ EXAMPLES::
955
+
956
+ sage: f = oeis(53) ; f # optional -- internet
957
+ A000053: Local stops on New York City...
958
+
959
+ sage: f.keywords() # optional -- internet
960
+ ('nonn', 'fini', ...)
961
+
962
+ TESTS::
963
+
964
+ sage: s = oeis._imaginary_sequence()
965
+ sage: s.keywords()
966
+ ('sign', 'easy')
967
+
968
+ sage: s = oeis._imaginary_sequence(ident='A999997', keywords='nonn,hard')
969
+ sage: s.keywords()
970
+ ('nonn', 'hard')
971
+ """
972
+ return tuple(self._field('K', warn=warn)[0].split(','))
973
+
974
+ def natural_object(self):
975
+ r"""
976
+ Return the natural object associated to the sequence ``self``.
977
+
978
+ OUTPUT:
979
+
980
+ - If the sequence ``self`` corresponds to the digits of a real
981
+ number, returns the associated real number (as an element of
982
+ RealLazyField()).
983
+
984
+ - If the sequence ``self`` corresponds to the convergents of a
985
+ continued fraction, returns the associated continued fraction.
986
+
987
+ .. WARNING::
988
+
989
+ This method forgets the fact that the returned sequence may not be
990
+ complete.
991
+
992
+ .. TODO::
993
+
994
+ - ask OEIS to add a keyword telling whether the sequence comes from
995
+ a power series, e.g. for :oeis:`A000182`
996
+ - discover other possible conversions.
997
+
998
+ EXAMPLES::
999
+
1000
+ sage: g = oeis("A002852"); g # optional -- internet
1001
+ A002852: Continued fraction for Euler's constant (or Euler-Mascheroni constant) gamma.
1002
+
1003
+ sage: x = g.natural_object(); type(x) # optional -- internet
1004
+ <class 'sage.rings.continued_fraction.ContinuedFraction_periodic'>
1005
+
1006
+ sage: RDF(x) == RDF(euler_gamma) # optional -- internet
1007
+ True
1008
+
1009
+ sage: cfg = continued_fraction(euler_gamma) # needs sage.symbolic
1010
+ sage: x[:90] == cfg[:90] # optional - internet # needs sage.symbolic
1011
+ True
1012
+
1013
+ ::
1014
+
1015
+ sage: ee = oeis('A001113'); ee # optional -- internet
1016
+ A001113: Decimal expansion of e.
1017
+
1018
+ sage: x = ee.natural_object(); x # optional -- internet
1019
+ 2.718281828459046?
1020
+
1021
+ sage: x.parent() # optional -- internet
1022
+ Real Lazy Field
1023
+
1024
+ sage: x == RR(e) # optional -- internet
1025
+ True
1026
+
1027
+ ::
1028
+
1029
+ sage: av = oeis('A322578'); av # optional -- internet
1030
+ A322578: Decimal expansion ... Avogadro...
1031
+
1032
+ sage: av.natural_object() # optional -- internet
1033
+ 6.022140760000000?e23
1034
+
1035
+ ::
1036
+
1037
+ sage: fib = oeis('A000045'); fib # optional -- internet
1038
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
1039
+
1040
+ sage: x = fib.natural_object(); x.universe() # optional -- internet
1041
+ Non negative integer semiring
1042
+
1043
+ ::
1044
+
1045
+ sage: sfib = oeis('A039834'); sfib # optional -- internet
1046
+ A039834: a(n+2) = -a(n+1) + a(n) (signed Fibonacci numbers) with
1047
+ a(-2) = a(-1) = 1; or Fibonacci numbers (A000045)
1048
+ extended to negative indices.
1049
+
1050
+ sage: x = sfib.natural_object(); x.universe() # optional -- internet
1051
+ Integer Ring
1052
+
1053
+ TESTS::
1054
+
1055
+ sage: s = oeis._imaginary_sequence(ident='A999996', keywords='nonn,cofr')
1056
+ sage: type(s.natural_object())
1057
+ <class 'sage.rings.continued_fraction.ContinuedFraction_periodic'>
1058
+
1059
+ sage: s = oeis._imaginary_sequence(ident='A999995', keywords='nonn')
1060
+ sage: s.natural_object().universe()
1061
+ Non negative integer semiring
1062
+
1063
+ sage: s = oeis._imaginary_sequence()
1064
+ sage: s.natural_object().universe()
1065
+ Integer Ring
1066
+ """
1067
+ if 'cofr' in self.keywords() and 'frac' not in self.keywords():
1068
+ from sage.rings.continued_fraction import continued_fraction
1069
+ return continued_fraction(self.first_terms())
1070
+ elif 'cons' in self.keywords():
1071
+ offset = self.offsets()[0]
1072
+ terms = self.first_terms() + tuple([0] * abs(offset))
1073
+ from sage.rings.real_lazy import RealLazyField
1074
+ return RealLazyField()('0' + ''.join(map(str, terms[:offset])) + '.' + ''.join(map(str, terms[offset:])))
1075
+ elif 'nonn' in self.keywords():
1076
+ from sage.rings.semirings.non_negative_integer_semiring import NN
1077
+ from sage.structure.sequence import Sequence
1078
+ return Sequence(self.first_terms(), NN)
1079
+ else:
1080
+ from sage.rings.integer_ring import ZZ
1081
+ from sage.structure.sequence import Sequence
1082
+ return Sequence(self.first_terms(), ZZ)
1083
+
1084
+ def is_dead(self, warn_only=False) -> bool:
1085
+ r"""
1086
+ Tell whether the sequence is dead.
1087
+
1088
+ INPUT:
1089
+
1090
+ - ``warn_only`` -- ignored
1091
+
1092
+ EXAMPLES:
1093
+
1094
+ sage: s = oeis(17) # optional -- internet
1095
+ sage: s # optional -- internet
1096
+ A000017: Erroneous version of A032522.
1097
+
1098
+ TESTS::
1099
+
1100
+ sage: s.is_dead() # optional -- internet
1101
+ True
1102
+
1103
+ sage: t = oeis._imaginary_sequence()
1104
+ sage: t.is_dead()
1105
+ False
1106
+
1107
+ sage: u = oeis._imaginary_sequence(ident='A999994', keywords='dead')
1108
+ sage: u
1109
+ A999994: The characteristic sequence of 42 plus one, starting from 38.
1110
+
1111
+ sage: u.is_dead()
1112
+ True
1113
+ """
1114
+ return 'dead' in self.keywords()
1115
+
1116
+ def is_finite(self):
1117
+ r"""
1118
+ Tell whether the sequence is finite.
1119
+
1120
+ Currently, OEIS only provides a keyword when the sequence is known to
1121
+ be finite. So, when this keyword is not there, we do not know whether
1122
+ it is infinite or not.
1123
+
1124
+ OUTPUT:
1125
+
1126
+ - ``True`` when the sequence is known to be finite.
1127
+ - ``Unknown`` otherwise.
1128
+
1129
+ .. TODO::
1130
+
1131
+ Ask OEIS for a keyword ensuring that a sequence is infinite.
1132
+
1133
+ EXAMPLES::
1134
+
1135
+ sage: s = oeis('A114288') ; s # optional -- internet
1136
+ A114288: Lexicographically earliest solution of any 9 X 9 sudoku, read by rows.
1137
+
1138
+ sage: s.is_finite() # optional -- internet
1139
+ True
1140
+
1141
+ ::
1142
+
1143
+ sage: f = oeis(45) ; f # optional -- internet
1144
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
1145
+
1146
+ sage: f.is_finite() # optional -- internet
1147
+ Unknown
1148
+
1149
+ TESTS::
1150
+
1151
+ sage: s = oeis._imaginary_sequence()
1152
+ sage: s.is_finite()
1153
+ Unknown
1154
+
1155
+ sage: s = oeis._imaginary_sequence(ident='A999993', keywords='nonn,finit')
1156
+ sage: s.is_finite()
1157
+ True
1158
+ """
1159
+ if 'finit' in self.keywords() or 'full' in self.keywords():
1160
+ return True
1161
+ else:
1162
+ return Unknown
1163
+
1164
+ def is_full(self):
1165
+ r"""
1166
+ Tell whether the sequence ``self`` is full, that is, if all its
1167
+ elements are listed in ``self.first_terms()``.
1168
+
1169
+ Currently, OEIS only provides a keyword when the sequence is known to
1170
+ be full. So, when this keyword is not there, we do not know whether
1171
+ some elements are missing or not.
1172
+
1173
+ OUTPUT:
1174
+
1175
+ - ``True`` when the sequence is known to be full.
1176
+ - ``Unknown`` otherwise.
1177
+
1178
+ EXAMPLES::
1179
+
1180
+ sage: s = oeis('A114288') ; s # optional -- internet
1181
+ A114288: Lexicographically earliest solution of any 9 X 9 sudoku, read by rows.
1182
+
1183
+ sage: s.is_full() # optional -- internet
1184
+ True
1185
+
1186
+ ::
1187
+
1188
+ sage: f = oeis(45) ; f # optional -- internet
1189
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
1190
+
1191
+ sage: f.is_full() # optional -- internet
1192
+ Unknown
1193
+
1194
+ TESTS::
1195
+
1196
+ sage: s = oeis._imaginary_sequence()
1197
+ sage: s.is_full()
1198
+ Unknown
1199
+
1200
+ sage: s = oeis._imaginary_sequence(ident='A999992', keywords='nonn,full,finit')
1201
+ sage: s.is_full()
1202
+ True
1203
+ """
1204
+ if 'full' in self.keywords():
1205
+ return True
1206
+ else:
1207
+ return Unknown
1208
+
1209
+ @cached_method
1210
+ def first_terms(self, number=None):
1211
+ r"""
1212
+
1213
+ INPUT:
1214
+
1215
+ - ``number`` -- integer or ``None`` (default); the number of
1216
+ terms returned (if less than the number of available terms). When set
1217
+ to ``None``, returns all the known terms.
1218
+
1219
+ OUTPUT: tuple of integers
1220
+
1221
+ EXAMPLES::
1222
+
1223
+ sage: f = oeis(45); f # optional -- internet
1224
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
1225
+
1226
+ sage: f.first_terms()[:10] # optional -- internet
1227
+ (0, 1, 1, 2, 3, 5, 8, 13, 21, 34)
1228
+
1229
+ Handle dead sequences, see :issue:`17330` ::
1230
+
1231
+ sage: oeis(5000).first_terms(12) # optional -- internet
1232
+ (1, 0, 0, 1, 1, 1, 11, 36, 92, 491, 2537)
1233
+
1234
+ TESTS::
1235
+
1236
+ sage: s = oeis._imaginary_sequence()
1237
+ sage: s.first_terms()
1238
+ (1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
1239
+ sage: s.first_terms(5)
1240
+ (1, 1, 1, 1, 2)
1241
+ """
1242
+ fields = ['S', 'T', 'U']
1243
+ return to_tuple(" ".join(flatten([self._field(a) for a in fields])))[:number]
1244
+
1245
+ def _repr_(self):
1246
+ r"""
1247
+ Print the sequence number and a short summary of this sequence.
1248
+
1249
+ OUTPUT: string
1250
+
1251
+ EXAMPLES::
1252
+
1253
+ sage: f = oeis(45) # optional -- internet
1254
+ sage: f # optional -- internet
1255
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
1256
+
1257
+ TESTS::
1258
+
1259
+ sage: s = oeis._imaginary_sequence()
1260
+ sage: s
1261
+ A999999: The characteristic sequence of 42 plus one, starting from 38.
1262
+ """
1263
+ return "%s: %s" % (self.id(), self.name())
1264
+
1265
+ def __call__(self, k):
1266
+ r"""
1267
+ Return the element of the sequence ``self`` with index ``k``.
1268
+
1269
+ INPUT:
1270
+
1271
+ - ``k`` -- integer
1272
+
1273
+ OUTPUT: integer
1274
+
1275
+ .. NOTE::
1276
+
1277
+ The first index of the sequence ``self`` is not necessarily zero,
1278
+ it depends on the first offset of ``self``. If the sequence
1279
+ represents the decimal expansion of a real number, the index 0
1280
+ corresponds to the digit right after the decimal point.
1281
+
1282
+ EXAMPLES::
1283
+
1284
+ sage: f = oeis(45) # optional -- internet
1285
+ sage: f.first_terms()[:10] # optional -- internet
1286
+ (0, 1, 1, 2, 3, 5, 8, 13, 21, 34)
1287
+
1288
+ sage: f(4) # optional -- internet
1289
+ 3
1290
+
1291
+ ::
1292
+
1293
+ sage: sfibo = oeis('A039834') # optional -- internet
1294
+ sage: sfibo.first_terms()[:10] # optional -- internet
1295
+ (1, 1, 0, 1, -1, 2, -3, 5, -8, 13)
1296
+
1297
+ sage: sfibo(-2) # optional -- internet
1298
+ 1
1299
+ sage: sfibo(4) # optional -- internet
1300
+ -3
1301
+ sage: sfibo.offsets() # optional -- internet
1302
+ (-2, 6)
1303
+
1304
+ TESTS::
1305
+
1306
+ sage: s = oeis._imaginary_sequence()
1307
+ sage: s(38)
1308
+ 1
1309
+ sage: s(42)
1310
+ 2
1311
+ sage: s(2)
1312
+ Traceback (most recent call last):
1313
+ ...
1314
+ ValueError: sequence A999999 is not defined (or known) for index 2
1315
+ """
1316
+ offset = self.offsets()[0]
1317
+ if 'cons' in self.keywords():
1318
+ offset = - offset
1319
+ n = k - offset
1320
+ if not 0 <= n < len(self.first_terms()):
1321
+ raise ValueError("sequence %s is not defined (or known) for index %s" % (self.id(), k))
1322
+ return self.first_terms()[n]
1323
+
1324
+ def __getitem__(self, i):
1325
+ r"""
1326
+ Return the `i`-th element of sequence ``self``, viewed as a tuple.
1327
+
1328
+ The first element appearing in the sequence ``self``corresponds to
1329
+ ``self[0]``. Do not confuse with calling ``self(k)``.
1330
+
1331
+ INPUT:
1332
+
1333
+ - ``i`` -- integer
1334
+
1335
+ OUTPUT: integer
1336
+
1337
+ EXAMPLES::
1338
+
1339
+ sage: sfibo = oeis('A039834') # optional -- internet
1340
+ sage: sfibo[8] # optional -- internet
1341
+ -8
1342
+ sage: sfibo(8) # optional -- internet
1343
+ -21
1344
+
1345
+ TESTS::
1346
+
1347
+ sage: s = oeis._imaginary_sequence()
1348
+ sage: s[2]
1349
+ 1
1350
+ sage: s[4]
1351
+ 2
1352
+ sage: s[38]
1353
+ Traceback (most recent call last):
1354
+ ...
1355
+ IndexError: tuple index out of range
1356
+ """
1357
+ return self.first_terms()[i]
1358
+
1359
+ def __iter__(self):
1360
+ r"""
1361
+ Iterate over the first terms of ``self``, and raise an error if
1362
+ those first terms are exhausted and the real associated sequence
1363
+ still have terms to produce.
1364
+
1365
+ OUTPUT: integer
1366
+
1367
+ EXAMPLES::
1368
+
1369
+ sage: p = oeis('A085823') ; p # optional -- internet
1370
+ A085823: Numbers in which all substrings are primes.
1371
+
1372
+ sage: for i in p: # optional -- internet
1373
+ ....: print(i)
1374
+ 2
1375
+ 3
1376
+ 5
1377
+ 7
1378
+ 23
1379
+ 37
1380
+ 53
1381
+ 73
1382
+ 373
1383
+
1384
+ ::
1385
+
1386
+ sage: w = oeis(7540) ; w # optional -- internet
1387
+ A007540: Wilson primes: primes p such that (p-1)! == -1 (mod p^2).
1388
+
1389
+ sage: # optional - internet
1390
+ sage: i = w.__iter__()
1391
+ sage: next(i)
1392
+ 5
1393
+ sage: next(i)
1394
+ 13
1395
+ sage: next(i)
1396
+ 563
1397
+ sage: next(i)
1398
+ Traceback (most recent call last):
1399
+ ...
1400
+ LookupError: future values not provided by OEIS
1401
+
1402
+ ::
1403
+
1404
+ sage: f = oeis(45) ; f # optional -- internet
1405
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
1406
+
1407
+ sage: for i in f: # optional -- internet
1408
+ ....: print(i)
1409
+ Traceback (most recent call last):
1410
+ ...
1411
+ LookupError: future values not provided by OEIS
1412
+
1413
+ TESTS::
1414
+
1415
+ sage: s = oeis._imaginary_sequence()
1416
+ sage: for i in s:
1417
+ ....: pass
1418
+ Traceback (most recent call last):
1419
+ ...
1420
+ LookupError: future values not provided by OEIS
1421
+
1422
+ sage: for i in s:
1423
+ ....: if i == 2:
1424
+ ....: print(i)
1425
+ ....: break
1426
+ 2
1427
+
1428
+ sage: s = oeis._imaginary_sequence(ident='A999991', keywords='sign,full')
1429
+ sage: for i in s: pass
1430
+ """
1431
+ yield from self.first_terms()
1432
+ if self.is_full() is not True:
1433
+ raise LookupError("future values not provided by OEIS")
1434
+
1435
+ def references(self):
1436
+ r"""
1437
+ Return a tuple of references associated to the sequence ``self``.
1438
+
1439
+ OUTPUT:
1440
+
1441
+ - tuple of strings (with fancy formatting).
1442
+
1443
+ EXAMPLES::
1444
+
1445
+ sage: w = oeis(7540) ; w # optional -- internet
1446
+ A007540: Wilson primes: primes p such that (p-1)! == -1 (mod p^2).
1447
+
1448
+ sage: w.references() # optional -- internet
1449
+ ...Albert H. Beiler, Recreations in the Theory of Numbers, Dover, NY, 1964, p. 52.
1450
+ ...
1451
+
1452
+ TESTS::
1453
+
1454
+ sage: s = oeis._imaginary_sequence()
1455
+ sage: s.references()[1]
1456
+ 'Lewis Carroll, The Hunting of the Snark.'
1457
+ """
1458
+ return FancyTuple(self._field('D'))
1459
+
1460
+ def links(self, browse=None, format='guess'):
1461
+ r"""
1462
+ Return, display or browse links associated to the sequence ``self``.
1463
+
1464
+ INPUT:
1465
+
1466
+ - ``browse`` -- integer; a list of integers, or the word 'all'
1467
+ (default: ``None``) which links to open in a web browser
1468
+
1469
+ - ``format`` -- string (default: ``'guess'``); how to display the links
1470
+
1471
+ OUTPUT: tuple of strings (with fancy formatting):
1472
+
1473
+ - if ``format`` is ``url``, returns a tuple of absolute links without description.
1474
+ - if ``format`` is ``html``, returns nothing but prints a tuple of clickable absolute links in their context.
1475
+ - if ``format`` is ``guess``, adapts the output to the context (command line or notebook).
1476
+ - if ``format`` is ``raw``, the links as they appear in the database, relative links are not made absolute.
1477
+
1478
+ EXAMPLES::
1479
+
1480
+ sage: f = oeis(45) ; f # optional -- internet
1481
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
1482
+
1483
+ sage: f.links(format='url') # optional -- internet
1484
+ 0: https://oeis.org/A000045/b000045.txt
1485
+ 1: ...
1486
+ 2: ...
1487
+
1488
+ sage: f.links(format='raw') # optional -- internet
1489
+ 0: N. J. A. Sloane, <a href="/A000045/b000045.txt">The first 2000 Fibonacci numbers: Table of n, F(n) for n = 0..2000</a>
1490
+ 1: ...
1491
+ 2: ...
1492
+
1493
+ TESTS::
1494
+
1495
+ sage: s = oeis._imaginary_sequence()
1496
+ sage: s.links(format='raw')[2]
1497
+ 'Do not confuse with the sequence <a href="/A000042">A000042</a> or the sequence <a href="/A000024">A000024</a>'
1498
+
1499
+ sage: s.links(format='url')[3]
1500
+ 'https://oeis.org/A000024'
1501
+
1502
+ sage: HTML = s.links(format='html'); HTML
1503
+ 0: Wikipedia, <a href="https://en.wikipedia.org/wiki/42_(number)">42 (number)</a>
1504
+ 1: See. also <a href="https://github.com/sagemath/sage/issues/42">github issue #42</a>
1505
+ ...
1506
+ sage: type(HTML)
1507
+ <class 'sage.misc.html.HtmlFragment'>
1508
+ """
1509
+ def url_absolute(s):
1510
+ return re.sub(r'\"\/', '\"' + oeis_url, s)
1511
+
1512
+ if browse is None:
1513
+ if format == 'guess':
1514
+ return self.links(format='url')
1515
+ elif format == 'raw':
1516
+ return FancyTuple(self._field('H'))
1517
+ elif format == 'html':
1518
+ return HtmlFragment(FancyTuple([url_absolute(f) for f in self._field('H')]))
1519
+ elif format == 'url':
1520
+ url_list = flatten([_urls(url_absolute(string)) for string in self._field('H')])
1521
+ return FancyTuple(url_list)
1522
+ else:
1523
+ import webbrowser
1524
+ url_list = flatten([_urls(url_absolute(string)) for string in self._field('H')])
1525
+ if isinstance(browse, (int, Integer)):
1526
+ webbrowser.open(url_list[browse])
1527
+ elif isinstance(browse, (list, tuple)):
1528
+ for url_number in browse:
1529
+ webbrowser.open(url_list[url_number])
1530
+ elif browse == 'all':
1531
+ for url in url_list:
1532
+ webbrowser.open(url)
1533
+
1534
+ def formulas(self):
1535
+ r"""
1536
+ Return a tuple of formulas associated to the sequence ``self``.
1537
+
1538
+ OUTPUT:
1539
+
1540
+ - tuple of strings (with fancy formatting).
1541
+
1542
+ EXAMPLES::
1543
+
1544
+ sage: f = oeis(45) ; f # optional -- internet
1545
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
1546
+
1547
+ sage: f.formulas()[2] # optional -- internet
1548
+ 'F(n) = ((1+sqrt(5))^n - (1-sqrt(5))^n)/(2^n*sqrt(5)).'
1549
+
1550
+ TESTS::
1551
+
1552
+ sage: s = oeis._imaginary_sequence()
1553
+ sage: s.formulas()
1554
+ 0: For n big enough, s(n+1) - s(n) = 0.
1555
+ """
1556
+ return FancyTuple(self._field('F'))
1557
+
1558
+ def cross_references(self, fetch=False):
1559
+ r"""
1560
+ Return a tuple of cross references associated to the sequence
1561
+ ``self``.
1562
+
1563
+ INPUT:
1564
+
1565
+ - ``fetch`` -- boolean (default: ``False``)
1566
+
1567
+ OUTPUT:
1568
+
1569
+ - if ``fetch`` is ``False``, return a list of OEIS IDs (strings).
1570
+ - if ``fetch`` is ``True``, return a tuple of OEIS sequences.
1571
+
1572
+ EXAMPLES::
1573
+
1574
+ sage: nbalanced = oeis("A005598") ; nbalanced # optional -- internet
1575
+ A005598: a(n) = 1 + Sum_{i=1..n} (n-i+1)*phi(i).
1576
+
1577
+ sage: nbalanced.cross_references() # optional -- internet
1578
+ ('A000010', 'A002088', 'A011755', 'A049695', 'A049703', 'A103116')
1579
+
1580
+ sage: nbalanced.cross_references(fetch=True) # optional -- internet
1581
+ 0: A000010: Euler totient function phi(n): count numbers <= n and prime to n.
1582
+ 1: A002088: Sum of totient function: a(n) = Sum_{k=1..n} phi(k), cf. A000010.
1583
+ 2: A011755: a(n) = Sum_{k=1..n} k*phi(k).
1584
+ 3: A049695: Array T read by diagonals; T(i,j) is the number of nonnegative
1585
+ slopes of lines determined by 2 lattice points in
1586
+ [ 0,i ] X [ 0,j ] if i > 0; T(0,j)=1 if j > 0; T(0,0)=0.
1587
+ 4: A049703: a(0) = 0; for n>0, a(n) = A005598(n)/2.
1588
+ 5: A103116: a(n) = Sum_{i=1..n} (n-i+1)*phi(i).
1589
+
1590
+ sage: phi = _[3] # optional -- internet
1591
+
1592
+ TESTS::
1593
+
1594
+ sage: s = oeis._imaginary_sequence()
1595
+ sage: s.cross_references()
1596
+ ('A000042', 'A000024')
1597
+ """
1598
+ ref_list = re.findall('A[0-9]{6}', " ".join(self._field('Y')))
1599
+ if fetch:
1600
+ T = [oeis.find_by_id(r) for r in ref_list]
1601
+ return FancyTuple([s for s in T if not s.is_dead()])
1602
+ return tuple(ref_list)
1603
+
1604
+ def extensions_or_errors(self):
1605
+ r"""
1606
+ Return a tuple of extensions or errors associated to the
1607
+ sequence ``self``.
1608
+
1609
+ OUTPUT:
1610
+
1611
+ - tuple of strings (with fancy formatting).
1612
+
1613
+ EXAMPLES::
1614
+
1615
+ sage: sfibo = oeis('A039834'); sfibo # optional -- internet
1616
+ A039834: a(n+2) = -a(n+1) + a(n) (signed Fibonacci numbers) with
1617
+ a(-2) = a(-1) = 1; or Fibonacci numbers (A000045) extended
1618
+ to negative indices.
1619
+
1620
+ sage: sfibo.extensions_or_errors()[0] # optional -- internet
1621
+ 'Signs corrected by _Len Smiley_ and _N. J. A. Sloane_'
1622
+
1623
+ TESTS::
1624
+
1625
+ sage: s = oeis._imaginary_sequence()
1626
+ sage: s.extensions_or_errors()
1627
+ 0: This sequence does not contain errors.
1628
+ """
1629
+ return FancyTuple(self._field('E'))
1630
+
1631
+ def examples(self):
1632
+ r"""
1633
+ Return a tuple of examples associated to the sequence ``self``.
1634
+
1635
+ OUTPUT:
1636
+
1637
+ - tuple of strings (with fancy formatting).
1638
+
1639
+ EXAMPLES::
1640
+
1641
+ sage: c = oeis(1203); c # optional -- internet
1642
+ A001203: Simple continued fraction expansion of Pi.
1643
+
1644
+ sage: c.examples() # optional -- internet
1645
+ 0: Pi = 3.1415926535897932384...
1646
+ 1: = 3 + 1/(7 + 1/(15 + 1/(1 + 1/(292 + ...))))
1647
+ 2: = [a_0; a_1, a_2, a_3, ...] = [3; 7, 15, 1, 292, ...].
1648
+
1649
+ TESTS::
1650
+
1651
+ sage: s = oeis._imaginary_sequence()
1652
+ sage: s.examples()
1653
+ 0: s(42) + s(43) = 0.
1654
+ """
1655
+ return FancyTuple(self._field('e'))
1656
+
1657
+ def comments(self):
1658
+ r"""
1659
+ Return a tuple of comments associated to the sequence ``self``.
1660
+
1661
+ OUTPUT:
1662
+
1663
+ - tuple of strings (with fancy formatting).
1664
+
1665
+ EXAMPLES::
1666
+
1667
+ sage: f = oeis(45); f # optional -- internet
1668
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
1669
+
1670
+ sage: f.comments()[:8] # optional -- internet
1671
+ 0: D. E. Knuth writes...
1672
+ 1: In keeping with historical accounts...
1673
+ 2: Susantha Goonatilake writes...
1674
+ 3: Also sometimes called Hemachandra numbers.
1675
+ 4: Also sometimes called Lamé's sequence.
1676
+ 5: ...
1677
+ 6: F(n+2) = number of binary sequences of length n that have no consecutive 0's.
1678
+ 7: F(n+2) = number of subsets of {1,2,...,n} that contain no consecutive integers.
1679
+
1680
+ TESTS::
1681
+
1682
+ sage: s = oeis._imaginary_sequence()
1683
+ sage: s.comments()
1684
+ 0: 42 is the product of the first 4 prime numbers, except 5 and perhaps 1.
1685
+ 1: Apart from that, i have no comment.
1686
+ """
1687
+ return FancyTuple(self._field('C'))
1688
+
1689
+ def url(self):
1690
+ r"""
1691
+ Return the URL of the page associated to the sequence ``self``.
1692
+
1693
+ OUTPUT: string
1694
+
1695
+ EXAMPLES::
1696
+
1697
+ sage: f = oeis(45); f # optional -- internet
1698
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
1699
+
1700
+ sage: f.url() # optional -- internet
1701
+ 'https://oeis.org/A000045'
1702
+
1703
+ TESTS::
1704
+
1705
+ sage: s = oeis._imaginary_sequence()
1706
+ sage: s.url()
1707
+ 'https://oeis.org/A999999'
1708
+ """
1709
+ return oeis_url + self.id()
1710
+
1711
+ def browse(self):
1712
+ r"""
1713
+ Open the OEIS web page associated to the sequence ``self`` in a browser.
1714
+
1715
+ EXAMPLES::
1716
+
1717
+ sage: f = oeis(45); f # optional -- internet webbrowser
1718
+ A000045: Fibonacci numbers: F(n) = F(n-1) + F(n-2) with F(0) = 0 and F(1) = 1.
1719
+
1720
+ sage: f.browse() # optional -- internet webbrowser
1721
+
1722
+ TESTS::
1723
+
1724
+ sage: s = oeis._imaginary_sequence() # optional -- webbrowser
1725
+ sage: s.browse() # optional -- webbrowser
1726
+ """
1727
+ import webbrowser
1728
+ webbrowser.open(self.url())
1729
+
1730
+ def show(self):
1731
+ r"""
1732
+ Display most available information about the sequence ``self``.
1733
+
1734
+ EXAMPLES::
1735
+
1736
+ sage: s = oeis(12345) # optional -- internet
1737
+ sage: s.show() # optional -- internet
1738
+ ID
1739
+ A012345
1740
+ <BLANKLINE>
1741
+ NAME
1742
+ Coefficients in the expansion sinh(arcsin(x)*arcsin(x)) = 2*x^2/2!+8*x^4/4!+248*x^6/6!+11328*x^8/8!+...
1743
+ <BLANKLINE>
1744
+ FIRST TERMS
1745
+ (2, 8, 248, 11328, 849312, 94857600, 14819214720, 3091936512000, 831657655349760, 280473756197529600, 115967597965430077440, 57712257892456911912960, 34039765801079493369569280)
1746
+ <BLANKLINE>
1747
+ LINKS
1748
+ 0: https://oeis.org/A012345/b012345.txt
1749
+ <BLANKLINE>
1750
+ FORMULAS
1751
+ ...
1752
+ OFFSETS
1753
+ (0, 1)
1754
+ <BLANKLINE>
1755
+ URL
1756
+ https://oeis.org/A012345
1757
+ <BLANKLINE>
1758
+ AUTHOR
1759
+ Patrick Demichel (patrick.demichel(AT)hp.com)
1760
+ <BLANKLINE>
1761
+
1762
+ TESTS::
1763
+
1764
+ sage: s = oeis._imaginary_sequence()
1765
+ sage: s.show()
1766
+ ID
1767
+ A999999
1768
+ <BLANKLINE>
1769
+ NAME
1770
+ The characteristic sequence of 42 plus ...
1771
+ FIRST TERMS
1772
+ (1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
1773
+ <BLANKLINE>
1774
+ COMMENTS
1775
+ 0: 42 is the product of the first 4 prime numbers, except ...
1776
+ 1: Apart from that, i have no comment.
1777
+ ...
1778
+ """
1779
+ for s in ['id', 'name', 'first_terms', 'comments', 'references',
1780
+ 'links', 'formulas', 'examples', 'cross_references',
1781
+ 'programs', 'keywords', 'offsets', 'url', 'old_IDs',
1782
+ 'author', 'extensions_or_errors']:
1783
+ result = getattr(self, s)()
1784
+ if result != '' and result != ('',) and result != ():
1785
+ print(re.sub('_', ' ', s).upper())
1786
+ print(str(result) + '\n')
1787
+
1788
+ def programs(self, language='all', preparsing=True, keep_comments=False):
1789
+ r"""
1790
+ Return programs for the sequence ``self`` in the given ``language``.
1791
+
1792
+ INPUT:
1793
+
1794
+ - ``language`` -- string (default: ``'all'``); the chosen language.
1795
+ Possible values are 'all' for the full list, or
1796
+ any language name, for example 'sage', 'maple', 'mathematica', etc.
1797
+
1798
+ Some further optional input is specific to sage code treatment:
1799
+
1800
+ - ``preparsing`` -- boolean (default: ``True``); whether to preparse
1801
+ sage code
1802
+ - ``keep_comments`` -- boolean (default: ``False``); whether to keep
1803
+ comments in sage code
1804
+
1805
+ OUTPUT:
1806
+
1807
+ If ``language`` is ``'all'``, this returns a sorted list of pairs
1808
+ (language, code), where every language can appear several times.
1809
+
1810
+ Otherwise, this returns a list of programs in the ``language``,
1811
+ each program being a tuple of strings (with fancy formatting).
1812
+
1813
+ EXAMPLES::
1814
+
1815
+ sage: ee = oeis.find_by_id('A00260') # optional -- internet
1816
+ sage: ee.programs('pari')[0] # optional -- internet
1817
+ 0: {a(n) = binomial(...)};...
1818
+
1819
+ sage: G = oeis.find_by_id('A27642') # optional -- internet
1820
+ sage: G.programs('all') # optional -- internet
1821
+ [('haskell', ...),
1822
+ ('magma', ...),
1823
+ ...
1824
+ ('python', ...),
1825
+ ('sage', ...)]
1826
+
1827
+ TESTS::
1828
+
1829
+ sage: s = oeis._imaginary_sequence()
1830
+ sage: s.programs()
1831
+ [('maple', ...),
1832
+ ('mathematica', ...),
1833
+ ('python',
1834
+ 0: def A999999(n):
1835
+ 1: assert(isinstance(n, (int, Integer))), "n must be an integer."
1836
+ 2: if n < 38:
1837
+ 3: raise ValueError("the value %s is not accepted" % str(n))
1838
+ 4: elif n == 42:
1839
+ 5: return 2
1840
+ 6: else:
1841
+ 7: return 1)]
1842
+
1843
+ sage: s.programs('maple')[0]
1844
+ 0: Do not even try, Maple is not able to produce such a sequence.
1845
+
1846
+ sage: s.programs('mathematica')[0]
1847
+ 0: Mathematica neither.
1848
+ """
1849
+ language = language.lower()
1850
+ if language == "maple":
1851
+ return [FancyTuple(self._field('p'))]
1852
+ elif language == "mathematica":
1853
+ return [FancyTuple(self._field('t'))]
1854
+ if language == 'sagemath':
1855
+ language = 'sage'
1856
+ if language == 'all':
1857
+ table = (('maple', FancyTuple(self._field('p'))),
1858
+ ('mathematica', FancyTuple(self._field('t'))))
1859
+ table = [(lang, code) for lang, code in table if code]
1860
+ else:
1861
+ table = []
1862
+
1863
+ known_langs = ['sage', 'python', 'scheme']
1864
+
1865
+ def is_starting_line(line):
1866
+ """
1867
+ Help to split the big OEIS code block into blocks by language.
1868
+
1869
+ This returns ``None`` if ``line`` is not a starting line.
1870
+ """
1871
+ if not line.startswith('('):
1872
+ return None
1873
+ if ')' not in line:
1874
+ return None
1875
+ end = line.index(')')
1876
+ language = line[1:end].lower() # normalise the language names
1877
+ if '(' in language:
1878
+ return None
1879
+ for special in known_langs:
1880
+ if special in language:
1881
+ language = special
1882
+ if ' ' in language: # get rid of language versions
1883
+ language = language.split(' ')[0]
1884
+ if language == 'c#' or language == 'c++':
1885
+ language = 'c'
1886
+ if language.isalnum():
1887
+ return (language, end)
1888
+ return None
1889
+
1890
+ def filter_sage(lines):
1891
+ """
1892
+ Remove comments and preparse if required, only for sage code.
1893
+
1894
+ This is an iterator.
1895
+ """
1896
+ for line in lines:
1897
+ if keep_comments or not line.strip().startswith('#'):
1898
+ if preparsing:
1899
+ yield preparse(line)
1900
+ else:
1901
+ yield line
1902
+
1903
+ def flush_to_table(language, code_lines):
1904
+ """
1905
+ Put a list of code lines into the appropriate box of the table.
1906
+
1907
+ With special treatment for sage code blocks.
1908
+ """
1909
+ if language == 'sage':
1910
+ table.append((language, FancyTuple(filter_sage(code_lines))))
1911
+ elif language is not None:
1912
+ table.append((language, FancyTuple(code_lines)))
1913
+
1914
+ programs = FancyTuple(self._field('o'))
1915
+ code_lines = []
1916
+ old_language = None
1917
+ for line in programs:
1918
+ new_language = is_starting_line(line)
1919
+ if new_language is not None:
1920
+ # flush the stock of code lines if any
1921
+ flush_to_table(old_language, code_lines)
1922
+ # start new stock of code lines
1923
+ old_language, end = new_language
1924
+ rest = line[end + 1:].strip()
1925
+ code_lines = [rest] if rest else []
1926
+ else:
1927
+ code_lines.append(line)
1928
+ flush_to_table(old_language, code_lines)
1929
+
1930
+ if language == 'all':
1931
+ return sorted(table)
1932
+ return sorted(prog for la, prog in table if la == language)
1933
+
1934
+ def test_compile_sage_code(self):
1935
+ """
1936
+ Try to compile the extracted sage code, if there is any.
1937
+
1938
+ If there are several sage code fields, they are all considered.
1939
+
1940
+ Dead sequences are considered to compile correctly by default.
1941
+
1942
+ This returns ``True`` if the code compiles, and raises an error
1943
+ otherwise.
1944
+
1945
+ EXAMPLES:
1946
+
1947
+ One correct sequence::
1948
+
1949
+ sage: s = oeis.find_by_id('A027642') # optional -- internet
1950
+ sage: s.test_compile_sage_code() # optional -- internet
1951
+ True
1952
+
1953
+ One dead sequence::
1954
+
1955
+ sage: s = oeis.find_by_id('A000154') # optional -- internet
1956
+ sage: s.test_compile_sage_code() # optional -- internet
1957
+ True
1958
+ """
1959
+ if self.is_dead():
1960
+ return True
1961
+ filt = self.programs(language='sage')
1962
+ if filt:
1963
+ for v in filt:
1964
+ tp = tmp_filename(ext='.sage')
1965
+ _ = compile('\n'.join(v), tp, 'exec')
1966
+ return True
1967
+
1968
+
1969
+ class FancyTuple(tuple):
1970
+ r"""
1971
+ This class inherits from ``tuple``, it allows to nicely print tuples whose
1972
+ elements have a one line representation.
1973
+
1974
+ EXAMPLES::
1975
+
1976
+ sage: from sage.databases.oeis import FancyTuple
1977
+ sage: t = FancyTuple(['zero', 'one', 'two', 'three', 4]); t
1978
+ 0: zero
1979
+ 1: one
1980
+ 2: two
1981
+ 3: three
1982
+ 4: 4
1983
+
1984
+ sage: t[2]
1985
+ 'two'
1986
+ """
1987
+ def __repr__(self):
1988
+ r"""
1989
+ Print the tuple with one value per line, where each line
1990
+ begins with the index of the value in ``self``.
1991
+
1992
+ EXAMPLES::
1993
+
1994
+ sage: from sage.databases.oeis import FancyTuple
1995
+ sage: t = FancyTuple(['zero', 'one', 'two', 'three', 4]); t
1996
+ 0: zero
1997
+ 1: one
1998
+ 2: two
1999
+ 3: three
2000
+ 4: 4
2001
+
2002
+ sage: t = FancyTuple(['Français', 'Español', '中文']); t
2003
+ 0: Français
2004
+ 1: Español
2005
+ 2: 中文
2006
+ """
2007
+ length = len(str(len(self) - 1))
2008
+ return '\n'.join('{0:>{1}}: {2}'.format(i, length, item) for i, item in enumerate(self))
2009
+
2010
+ def __getslice__(self, i, j):
2011
+ r"""
2012
+ The slice of a FancyTuple remains a FancyTuple.
2013
+
2014
+ EXAMPLES::
2015
+
2016
+ sage: from sage.databases.oeis import FancyTuple
2017
+ sage: t = FancyTuple(['zero', 'one', 'two', 'three', 4])
2018
+ sage: t[-2:]
2019
+ 0: three
2020
+ 1: 4
2021
+
2022
+ TESTS::
2023
+
2024
+ sage: t = ('é', 'è', 'à', 'ç')
2025
+ sage: FancyTuple(t)[2:4]
2026
+ 0: à
2027
+ 1: ç
2028
+ """
2029
+ return self.__getitem__(slice(i, j))
2030
+
2031
+ def __getitem__(self, x):
2032
+ r"""
2033
+ If ``x`` is a slice return the corresponding sub FancyTuple,
2034
+ else return the ``x``-th item of ``self``.
2035
+
2036
+ TESTS::
2037
+
2038
+ sage: from sage.databases.oeis import FancyTuple
2039
+ sage: t = ('é', 'è', 'à', 'ç')
2040
+ sage: ft = FancyTuple(t)
2041
+ sage: ft[0] == 'é'
2042
+ True
2043
+ sage: ft[-1] == 'ç'
2044
+ True
2045
+
2046
+ Check that :issue:`26997` is fixed::
2047
+
2048
+ sage: FancyTuple([[1,2,3],(4,5,6)])
2049
+ 0: [1, 2, 3]
2050
+ 1: (4, 5, 6)
2051
+ """
2052
+ res = tuple.__getitem__(self, x)
2053
+ if isinstance(x, slice):
2054
+ res = FancyTuple(res)
2055
+ return res
2056
+
2057
+
2058
+ oeis = OEIS()