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,1180 @@
1
+ # sage_setup: distribution = sagemath-combinat
2
+ # sage.doctest: needs sage.combinat sage.modules
3
+ """
4
+ Binary recurrence sequences
5
+
6
+ This class implements several methods relating to general linear binary
7
+ recurrence sequences, including a sieve to find perfect powers in integral
8
+ linear binary recurrence sequences.
9
+
10
+ EXAMPLES::
11
+
12
+ sage: R = BinaryRecurrenceSequence(1,1) #the Fibonacci sequence
13
+ sage: R(137) #the 137th term of the Fibonacci sequence
14
+ 19134702400093278081449423917
15
+ sage: R(137) == fibonacci(137) # needs sage.libs.pari
16
+ True
17
+ sage: [R(i) % 4 for i in range(12)]
18
+ [0, 1, 1, 2, 3, 1, 0, 1, 1, 2, 3, 1]
19
+ sage: R.period(4) #the period of the fibonacci sequence modulo 4
20
+ 6
21
+ sage: R.pthpowers(2, 10**10) # long time (7 seconds) -- in fact these are all squares, c.f. [BMS06]
22
+ [0, 1, 2, 12]
23
+
24
+ sage: S = BinaryRecurrenceSequence(8,1) #a Lucas sequence
25
+ sage: S.period(73)
26
+ 148
27
+ sage: S(5) % 73 == S(5 +148) %73
28
+ True
29
+ sage: S.pthpowers(3, 10**10) # long time (3 seconds) -- provably finds the indices of all 3rd powers less than 10^10
30
+ [0, 1, 2]
31
+
32
+ sage: T = BinaryRecurrenceSequence(2,0,1,2)
33
+ sage: [T(i) for i in range(10)]
34
+ [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
35
+ sage: T.is_degenerate()
36
+ True
37
+ sage: T.is_geometric()
38
+ True
39
+ sage: T.pthpowers(7, 10**30) # needs sage.symbolic
40
+ Traceback (most recent call last):
41
+ ...
42
+ ValueError: the degenerate binary recurrence sequence is geometric or quasigeometric
43
+ and has many pth powers
44
+
45
+
46
+ AUTHORS:
47
+
48
+ - Isabel Vogt (2013): initial version
49
+
50
+ See [SV2013]_, [BMS2006]_, and [SS1983]_.
51
+ """
52
+
53
+ # ****************************************************************************
54
+ # Copyright (C) 2013 Isabel Vogt <ivogt161@gmail.com>
55
+ #
56
+ # This program is free software: you can redistribute it and/or modify
57
+ # it under the terms of the GNU General Public License as published by
58
+ # the Free Software Foundation, either version 2 of the License, or
59
+ # (at your option) any later version.
60
+ # https://www.gnu.org/licenses/
61
+ # ****************************************************************************
62
+
63
+
64
+ from sage.structure.sage_object import SageObject
65
+ from sage.rings.finite_rings.integer_mod_ring import Integers
66
+ from sage.rings.finite_rings.finite_field_constructor import GF
67
+ from sage.rings.integer import Integer
68
+ from sage.arith.functions import lcm
69
+ from sage.arith.misc import is_prime, next_prime, next_prime_power, legendre_symbol
70
+ from sage.misc.lazy_import import lazy_import
71
+ from sage.misc.functional import sqrt
72
+
73
+ lazy_import("sage.functions.log", "log")
74
+ lazy_import("sage.rings.number_field.number_field", "QuadraticField")
75
+ lazy_import("sage.matrix.constructor", "matrix")
76
+ lazy_import("sage.modules.free_module_element", "vector")
77
+
78
+
79
+ class BinaryRecurrenceSequence(SageObject):
80
+ """
81
+ Create a linear binary recurrence sequence defined by initial conditions
82
+ `u_0` and `u_1` and recurrence relation `u_{n+2} = b*u_{n+1}+c*u_n`.
83
+
84
+ INPUT:
85
+
86
+ - ``b`` -- integer; (partially determining the recurrence relation)
87
+
88
+ - ``c`` -- integer; (partially determining the recurrence relation)
89
+
90
+ - ``u0`` -- integer; (the `0`-th term of the binary recurrence sequence)
91
+
92
+ - ``u1`` -- integer; (the `1`-st term of the binary recurrence sequence)
93
+
94
+ OUTPUT: an integral linear binary recurrence sequence defined by `u_0`,
95
+ `u_1`, and `u_{n+2} = b u_{n+1}+c u_n`
96
+
97
+ .. SEEALSO::
98
+
99
+ :func:`fibonacci`, :func:`lucas_number1`, :func:`lucas_number2`
100
+
101
+ EXAMPLES::
102
+
103
+ sage: R = BinaryRecurrenceSequence(3,3,2,1)
104
+ sage: R
105
+ Binary recurrence sequence defined by: u_n = 3 * u_{n-1} + 3 * u_{n-2};
106
+ With initial conditions: u_0 = 2, and u_1 = 1
107
+ """
108
+
109
+ def __init__(self, b, c, u0=0, u1=1):
110
+ """
111
+ See :class:`BinaryRecurrenceSequence` for full documentation.
112
+
113
+ EXAMPLES::
114
+
115
+ sage: R = BinaryRecurrenceSequence(3,3,2,1)
116
+ sage: R
117
+ Binary recurrence sequence defined by: u_n = 3 * u_{n-1} + 3 * u_{n-2};
118
+ With initial conditions: u_0 = 2, and u_1 = 1
119
+
120
+ sage: R = BinaryRecurrenceSequence(1,1)
121
+ sage: loads(R.dumps()) == R
122
+ True
123
+ """
124
+ self.b = b
125
+ self.c = c
126
+ self.u0 = u0
127
+ self.u1 = u1
128
+ self._period_dict = {} # dictionary to cache the period of a sequence for future lookup
129
+ self._PGoodness = {} # dictionary to cache primes that are "good" by some prime power
130
+ self._ell = 1 # variable that keeps track of the last prime power to be used as a goodness
131
+
132
+ def __repr__(self) -> str:
133
+ """
134
+ Give string representation of the class.
135
+
136
+ EXAMPLES::
137
+
138
+ sage: R = BinaryRecurrenceSequence(3,3,2,1)
139
+ sage: R
140
+ Binary recurrence sequence defined by: u_n = 3 * u_{n-1} + 3 * u_{n-2};
141
+ With initial conditions: u_0 = 2, and u_1 = 1
142
+ """
143
+ return 'Binary recurrence sequence defined by: u_n = ' + str(self.b) + ' * u_{n-1} + ' + str(self.c) + ' * u_{n-2};\nWith initial conditions: u_0 = ' + str(self.u0) + ', and u_1 = ' + str(self.u1)
144
+
145
+ def __eq__(self, other) -> bool:
146
+ """
147
+ Compare two binary recurrence sequences.
148
+
149
+ EXAMPLES::
150
+
151
+ sage: R = BinaryRecurrenceSequence(3,3,2,1)
152
+ sage: S = BinaryRecurrenceSequence(3,3,2,1)
153
+ sage: R == S
154
+ True
155
+
156
+ sage: T = BinaryRecurrenceSequence(3,3,2,2)
157
+ sage: R == T
158
+ False
159
+ """
160
+ return (self.u0 == other.u0) and (self.u1 == other.u1) and (self.b == other.b) and (self.c == other.c)
161
+
162
+ def __call__(self, n, modulus=0):
163
+ """
164
+ Give the `n`-th term of a binary recurrence sequence, possibly mod some modulus.
165
+
166
+ INPUT:
167
+
168
+ - ``n`` -- integer; the index of the term in the binary recurrence sequence
169
+
170
+ - ``modulus`` -- a natural number (optional -- default value is 0)
171
+
172
+ OUTPUT:
173
+
174
+ - An integer (the `n`-th term of the binary recurrence sequence modulo ``modulus``)
175
+
176
+ EXAMPLES::
177
+
178
+ sage: R = BinaryRecurrenceSequence(3,3,2,1)
179
+ sage: R(2)
180
+ 9
181
+ sage: R(101)
182
+ 16158686318788579168659644539538474790082623100896663971001
183
+ sage: R(101,12)
184
+ 9
185
+ sage: R(101)%12
186
+ 9
187
+ """
188
+ R = Integers(modulus)
189
+ F = matrix(R, [[0, 1], [self.c, self.b]])
190
+ # F*[u_{n}, u_{n+1}]^T = [u_{n+1}, u_{n+2}]^T (T indicates transpose).
191
+ v = vector(R, [self.u0, self.u1])
192
+ return list(F**n * v)[0]
193
+
194
+ def is_degenerate(self) -> bool:
195
+ """
196
+ Decide whether the binary recurrence sequence is degenerate.
197
+
198
+ Let `\\alpha` and `\\beta` denote the roots of the characteristic polynomial
199
+ `p(x) = x^2-bx -c`. Let `a = u_1-u_0\\beta/(\\beta - \\alpha)` and
200
+ `b = u_1-u_0\\alpha/(\\beta - \\alpha)`. The sequence is, thus, given by
201
+ `u_n = a \\alpha^n - b\\beta^n`. Then we say that the sequence is nondegenerate
202
+ if and only if `a*b*\\alpha*\\beta \\neq 0` and `\\alpha/\\beta` is not a
203
+ root of unity.
204
+
205
+ More concretely, there are 4 classes of degeneracy, that can all be formulated
206
+ in terms of the matrix `F = [[0,1], [c, b]]`.
207
+
208
+ - `F` is singular -- this corresponds to ``c`` = 0, and thus
209
+ `\\alpha*\\beta = 0`. This sequence is geometric after term ``u0``
210
+ and so we call it ``quasigeometric``
211
+
212
+ - `v = [[u_0], [u_1]]` is an eigenvector of `F` -- this corresponds to
213
+ a ``geometric`` sequence with `a*b = 0`
214
+
215
+ - `F` is nondiagonalizable -- this corresponds to `\\alpha = \\beta`.
216
+ This sequence will be the point-wise product of an arithmetic and
217
+ geometric sequence.
218
+
219
+ - `F^k` is scalar, for some `k>1` -- this corresponds to
220
+ `\\alpha/\\beta` a `k` th root of unity. This sequence is a union of
221
+ several geometric sequences, and so we again call it ``quasigeometric``.
222
+
223
+ EXAMPLES::
224
+
225
+ sage: S = BinaryRecurrenceSequence(0,1)
226
+ sage: S.is_degenerate()
227
+ True
228
+ sage: S.is_geometric()
229
+ False
230
+ sage: S.is_quasigeometric()
231
+ True
232
+
233
+ sage: R = BinaryRecurrenceSequence(3,-2)
234
+ sage: R.is_degenerate()
235
+ False
236
+
237
+ sage: T = BinaryRecurrenceSequence(2,-1)
238
+ sage: T.is_degenerate()
239
+ True
240
+ sage: T.is_arithmetic()
241
+ True
242
+ """
243
+ D = self.b**2 + 4 * self.c
244
+ if D != 0:
245
+ if D.is_square():
246
+ A = sqrt(D)
247
+ else:
248
+ A = QuadraticField(D, 'x').gen()
249
+
250
+ aa = (self.u1 - self.u0 * (self.b + A)/2)/(A) # called `a` in Docstring
251
+ bb = (self.u1 - self.u0 * (self.b - A)/2)/(A) # called `b` in Docstring
252
+
253
+ # (b+A)/2 is called alpha in Docstring, (b-A)/2 is called beta in Docstring
254
+
255
+ if self.b != A:
256
+ if ((self.b+A)/(self.b-A))**6 == 1:
257
+ return True
258
+ else:
259
+ return True
260
+
261
+ return aa*bb*(self.b + A)*(self.b - A) == 0
262
+
263
+ return True
264
+
265
+ def is_geometric(self) -> bool:
266
+ """
267
+ Decide whether the binary recurrence sequence is geometric - ie a geometric sequence.
268
+
269
+ This is a subcase of a degenerate binary recurrence sequence, for which `ab=0`, i.e.
270
+ `u_{n}/u_{n-1}=r` for some value of `r`.
271
+
272
+ See :meth:`is_degenerate` for a description of
273
+ degeneracy and definitions of `a` and `b`.
274
+
275
+ EXAMPLES::
276
+
277
+ sage: S = BinaryRecurrenceSequence(2,0,1,2)
278
+ sage: [S(i) for i in range(10)]
279
+ [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
280
+ sage: S.is_geometric()
281
+ True
282
+ """
283
+ # If [u_0, u_1]^T is an eigenvector for the incrementation matrix F = [[0,1],[c,b]], then the sequence
284
+ # is geometric, ie we can write u_n = a*r^n for some a and r.
285
+
286
+ # We decide if u0, u1, u2 = b*u1+c*u0 are in geometric progression by whether u1^2 = (b*u1+c*u0)*u0
287
+
288
+ return (self.u1)**2 == (self.b*self.u1 + self.c*self.u0)*self.u0
289
+
290
+ def is_quasigeometric(self) -> bool:
291
+ """
292
+ Decide whether the binary recurrence sequence is degenerate and similar to a geometric sequence,
293
+ i.e. the union of multiple geometric sequences, or geometric after term ``u0``.
294
+
295
+ If `\\alpha/\\beta` is a `k` th root of unity, where `k>1`, then necessarily `k = 2, 3, 4, 6`.
296
+ Then `F = [[0,1],[c,b]` is diagonalizable, and `F^k = [[\\alpha^k, 0], [0,\\beta^k]]` is a diagonal
297
+ matrix. Thus for all values of `j` mod `k`, the `j` mod `k` terms of `u_n` form a geometric
298
+ series.
299
+
300
+ If `\\alpha` or `\\beta` is zero, this implies that `c=0`. This is the case when `F` is
301
+ singular. In this case, `u_1, u_2, u_3, ...` is geometric.
302
+
303
+ EXAMPLES::
304
+
305
+ sage: S = BinaryRecurrenceSequence(0,1)
306
+ sage: [S(i) for i in range(10)]
307
+ [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
308
+ sage: S.is_quasigeometric()
309
+ True
310
+
311
+ sage: R = BinaryRecurrenceSequence(3,0)
312
+ sage: [R(i) for i in range(10)]
313
+ [0, 1, 3, 9, 27, 81, 243, 729, 2187, 6561]
314
+ sage: R.is_quasigeometric()
315
+ True
316
+ """
317
+ # First test if F is singular... i.e. beta = 0
318
+ if self.c == 0:
319
+ return True
320
+
321
+ # Otherwise test if alpha/beta is a root of unity that is not 1
322
+ D = self.b**2 + 4 * self.c
323
+ if D != 0: # thus alpha/beta != 1
324
+ if D.is_square():
325
+ A = sqrt(D)
326
+ else:
327
+ A = QuadraticField(D, 'x').gen()
328
+ if ((self.b+A)/(self.b-A))**6 == 1:
329
+ return True
330
+
331
+ return False
332
+
333
+ def is_arithmetic(self) -> bool:
334
+ """
335
+ Decide whether the sequence is degenerate and an arithmetic sequence.
336
+
337
+ The sequence is arithmetic if and only if `u_1 - u_0 = u_2 - u_1 = u_3 - u_2`.
338
+
339
+ This corresponds to the matrix `F = [[0,1],[c,b]]` being nondiagonalizable
340
+ and `\\alpha/\\beta = 1`.
341
+
342
+ EXAMPLES::
343
+
344
+ sage: S = BinaryRecurrenceSequence(2,-1)
345
+ sage: [S(i) for i in range(10)]
346
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
347
+ sage: S.is_arithmetic()
348
+ True
349
+ """
350
+ return self(1) - self(0) == self(2) - self(1) == self(3) - self(2)
351
+
352
+ def period(self, m, *, eventual=False):
353
+ """
354
+ Return the period of the binary recurrence sequence modulo
355
+ an integer ``m``.
356
+
357
+ If `n_1` is congruent to `n_2` modulo ``period(m)``, then `u_{n_1}` is
358
+ is congruent to `u_{n_2}` modulo ``m``.
359
+
360
+ INPUT:
361
+
362
+ - ``m`` -- integer; modulo which the period of the recurrence relation is calculated
363
+
364
+ - ``eventual`` -- boolean (default: ``False``); if ``True``, allow the
365
+ sequence to be eventually periodic, rather than requiring it to be
366
+ purely periodic. So `n_1` might not be congruent to `n_2` modulo
367
+ ``period(m)`` unless `n_1` and `n_2` are large.
368
+
369
+ OUTPUT: integer (the period of the sequence modulo m)
370
+
371
+ EXAMPLES:
372
+
373
+ If `p = \\pm 1 \\mod 5`, then the period of the Fibonacci sequence
374
+ mod `p` is `p-1` (c.f. Lemma 3.3 of [BMS2006]_).
375
+
376
+ ::
377
+
378
+ sage: R = BinaryRecurrenceSequence(1,1)
379
+ sage: R.period(31)
380
+ 30
381
+
382
+ sage: [R(i) % 4 for i in range(12)]
383
+ [0, 1, 1, 2, 3, 1, 0, 1, 1, 2, 3, 1]
384
+ sage: R.period(4)
385
+ 6
386
+
387
+ This function works for degenerate sequences as well.
388
+
389
+ ::
390
+
391
+ sage: S = BinaryRecurrenceSequence(2,0,1,2)
392
+ sage: S.is_degenerate()
393
+ True
394
+ sage: S.is_geometric()
395
+ True
396
+ sage: [S(i) % 17 for i in range(16)]
397
+ [1, 2, 4, 8, 16, 15, 13, 9, 1, 2, 4, 8, 16, 15, 13, 9]
398
+ sage: S.period(17)
399
+ 8
400
+
401
+ Letting ``eventual`` be ``True`` allows us to find the period of a
402
+ sequence that is not purely periodic. ::
403
+
404
+ sage: T = BinaryRecurrenceSequence(5,12,u0=0,u1=1)
405
+ sage: [T(n) % 10 for n in range(20)]
406
+ [0, 1, 5, 7, 5, 9, 5, 3, 5, 1, 5, 7, 5, 9, 5, 3, 5, 1, 5, 7]
407
+ sage: T.period(10)
408
+ Traceback (most recent call last):
409
+ ...
410
+ ValueError: Binary recurrence sequence modulo 10 is not a purely
411
+ periodic sequence.
412
+ sage: T.period(10,eventual=True)
413
+ 8
414
+
415
+ .. NOTE:: The answer is cached.
416
+
417
+ TESTS:
418
+
419
+ Verify that :issue:`38112` is fixed::
420
+
421
+ sage: T = BinaryRecurrenceSequence(3,2,u0=0,u1=1)
422
+ sage: [T(n) % 4 for n in range(5)]
423
+ [0, 1, 3, 3, 3]
424
+ sage: T.period(4)
425
+ Traceback (most recent call last):
426
+ ...
427
+ ValueError: Binary recurrence sequence modulo 4 is not a purely
428
+ periodic sequence.
429
+ sage: T.period(4,eventual=True)
430
+ 1
431
+ """
432
+
433
+ # If we have already computed the period mod m, then we return the stored value.
434
+
435
+ if m in self._period_dict:
436
+ return self._period_dict[m]
437
+
438
+ else:
439
+ R = Integers(m)
440
+ A = matrix(R, [[0, 1], [self.c, self.b]])
441
+ w = vector(R, [self.u0, self.u1])
442
+ Fac = list(m.factor())
443
+ Periods = {}
444
+
445
+ if eventual is True:
446
+ # There are only m^2 possible pairs modulo m. Since the numbering
447
+ # of the sequence starts at 0, this implies that the term numbered
448
+ # m^2 must be in periodic part of the sequence. Hence, the
449
+ # sequence starting with the terms numbered m^2 and m^2 + 1 must
450
+ # be purely periodic.
451
+ an = (A**(m**2)) * w
452
+ return BinaryRecurrenceSequence(self.b, self.c,
453
+ an[0], an[1]).period(m, eventual=False)
454
+
455
+ # To compute the period mod m, we compute the least integer n such that A^n*w == w. This necessarily
456
+ # divides the order of A as a matrix in GL_2(Z/mZ).
457
+
458
+ # We compute the period modulo all distinct prime powers dividing m, and combine via the lcm.
459
+ # To compute the period mod p^e, we first compute the order mod p. Then the period mod p^e
460
+ # must divide p^{4e-4}*period(p), as the subgroup of matrices mod p^e, which reduce to
461
+ # the identity mod p is of order (p^{e-1})^4. So we compute the period mod p^e by successively
462
+ # multiplying the period mod p by powers of p.
463
+
464
+ for p, e in Fac:
465
+ # first compute the period mod p
466
+ if p in self._period_dict:
467
+ perp = self._period_dict[p]
468
+ else:
469
+ F = A.change_ring(GF(p))
470
+ v = w.change_ring(GF(p))
471
+ FF = F**(p-1)
472
+ p1fac = list((p-1).factor())
473
+
474
+ # The order of any matrix in GL_2(F_p) either divides p(p-1) or (p-1)(p+1).
475
+ # The order divides p-1 if it is diagonalizable. In any case, det(F^(p-1))=1,
476
+ # so if tr(F^(p-1)) = 2, then it must be triangular of the form [[1,a],[0,1]].
477
+ # The order of the subgroup of matrices of this form is p, so the order must divide
478
+ # p(p-1) -- in fact it must be a multiple of p. If this is not the case, then the
479
+ # order divides (p-1)(p+1). As the period divides the order of the matrix in GL_2(F_p),
480
+ # these conditions hold for the period as well.
481
+
482
+ # check if the order divides (p-1)
483
+ if FF*v == v:
484
+ M = p-1
485
+ Mfac = p1fac
486
+
487
+ # check if the trace is 2, then the order is a multiple of p dividing p*(p-1)
488
+ elif FF.trace() == 2:
489
+ M = p-1
490
+ Mfac = p1fac
491
+ F = F**p # replace F by F^p as now we only need to determine the factor dividing (p-1)
492
+
493
+ # otherwise it will divide (p+1)(p-1)
494
+ else:
495
+ M = (p+1)*(p-1)
496
+ p2fac = list((p+1).factor()) # factor the (p+1) and (p-1) terms separately and then combine for speed
497
+ Mfac_dic = {}
498
+ for i0, i1 in list(p1fac + p2fac):
499
+ if i0 not in Mfac_dic:
500
+ Mfac_dic[i0] = i1
501
+ else:
502
+ Mfac_dic[i0] += i1
503
+ Mfac = list(Mfac_dic.items())
504
+
505
+ # Now use a fast order algorithm to compute the period. We know that the period divides
506
+ # M = i_1*i_2*...*i_l where the i_j denote not necessarily distinct prime factors. As
507
+ # F^M*v == v, for each i_j, if F^(M/i_j)*v == v, then the period divides (M/i_j). After
508
+ # all factors have been iterated over, the result is the period mod p.
509
+
510
+ Mfac = list(Mfac)
511
+
512
+ # expand the list of prime factors so every factor is with multiplicity 1
513
+ C = [i0 for i0, i1 in Mfac for _ in range(i1)]
514
+
515
+ Mfac = C
516
+ n = M
517
+ for ii in Mfac:
518
+ b = n // ii
519
+ if F**b * v == v:
520
+ n = b
521
+ perp = n
522
+
523
+ # Now compute the period mod p^e by stepping up by multiples of p
524
+ F = A.change_ring(Integers(p**e))
525
+ v = w.change_ring(Integers(p**e))
526
+ FF = F**perp
527
+ if FF*v == v:
528
+ perpe = perp
529
+ else:
530
+ tries = 0
531
+ while True:
532
+ tries += 1
533
+ FF = FF**p
534
+ if FF*v == v:
535
+ perpe = perp*p**tries
536
+ break
537
+ if tries > e:
538
+ raise ValueError("Binary recurrence sequence " +
539
+ f"modulo {m} is not a purely " +
540
+ "periodic sequence.")
541
+ Periods[p] = perpe
542
+
543
+ # take the lcm of the periods mod all distinct primes dividing m
544
+ period = lcm(Periods.values())
545
+
546
+ self._period_dict[m] = period # cache the period mod m
547
+ return period
548
+
549
+ def pthpowers(self, p, Bound):
550
+ """
551
+ Find the indices of proveably all `p`-th powers in the recurrence sequence
552
+ bounded by Bound.
553
+
554
+ Let `u_n` be a binary recurrence sequence. A ``p`` th power in `u_n`
555
+ is a solution to `u_n = y^p` for some integer `y`. There are only
556
+ finitely many ``p`` th powers in any recurrence sequence [SS1983]_.
557
+
558
+ INPUT:
559
+
560
+ - ``p`` -- a rational prime integer (the fixed p in `u_n = y^p`)
561
+
562
+ - ``Bound`` -- a natural number (the maximum index `n` in `u_n = y^p` that is checked)
563
+
564
+ OUTPUT:
565
+
566
+ A list of the indices of all ``p`` th powers less bounded by
567
+ ``Bound``. If the sequence is degenerate and there are many
568
+ ``p`` th powers, raises :exc:`ValueError`.
569
+
570
+ EXAMPLES::
571
+
572
+ sage: R = BinaryRecurrenceSequence(1,1) #the Fibonacci sequence
573
+ sage: R.pthpowers(2, 10**10) # long time (7 seconds) -- in fact these are all squares, c.f. [BMS2006]_
574
+ [0, 1, 2, 12]
575
+
576
+ sage: S = BinaryRecurrenceSequence(8,1) #a Lucas sequence
577
+ sage: S.pthpowers(3,10**10) # long time (3 seconds) -- provably finds the indices of all 3rd powers less than 10^10
578
+ [0, 1, 2]
579
+
580
+ sage: Q = BinaryRecurrenceSequence(3,3,2,1)
581
+ sage: Q.pthpowers(11,10**10) # long time (7.5 seconds)
582
+ [1]
583
+
584
+ If the sequence is degenerate, and there are no ``p`` th powers, returns `[]`. Otherwise, if
585
+ there are many ``p`` th powers, raises :exc:`ValueError`.
586
+
587
+ ::
588
+
589
+ sage: T = BinaryRecurrenceSequence(2,0,1,2)
590
+ sage: T.is_degenerate()
591
+ True
592
+ sage: T.is_geometric()
593
+ True
594
+ sage: T.pthpowers(7, 10**30) # needs sage.symbolic
595
+ Traceback (most recent call last):
596
+ ...
597
+ ValueError: the degenerate binary recurrence sequence is geometric or
598
+ quasigeometric and has many pth powers
599
+
600
+ sage: L = BinaryRecurrenceSequence(4,0,2,2)
601
+ sage: [L(i).factor() for i in range(10)]
602
+ [2, 2, 2^3, 2^5, 2^7, 2^9, 2^11, 2^13, 2^15, 2^17]
603
+ sage: L.is_quasigeometric()
604
+ True
605
+ sage: L.pthpowers(2, 10**30) # needs sage.symbolic
606
+ []
607
+
608
+ .. NOTE::
609
+
610
+ This function is primarily optimized in the range where
611
+ ``Bound`` is much larger than ``p``.
612
+ """
613
+ # Thanks to Jesse Silliman for helpful conversations!
614
+
615
+ # Reset the dictionary of good primes, as this depends on p
616
+ self._PGoodness = {}
617
+ # Starting lower bound on good primes
618
+ self._ell = 1
619
+
620
+ # If the sequence is geometric, then the `n`th term is `a*r^n`. Thus the
621
+ # property of being a ``p`` th power is periodic mod ``p``. So there are either
622
+ # no ``p`` th powers if there are none in the first ``p`` terms, or many if there
623
+ # is at least one in the first ``p`` terms.
624
+
625
+ if self.is_geometric() or self.is_quasigeometric():
626
+ no_powers = True
627
+ for i in range(1, 6*p+1):
628
+ if _is_p_power(self(i), p):
629
+ no_powers = False
630
+ break
631
+ if no_powers:
632
+ if _is_p_power(self.u0, p):
633
+ return [0]
634
+ return []
635
+ else:
636
+ raise ValueError("the degenerate binary recurrence sequence is geometric or quasigeometric and has many pth powers")
637
+
638
+ # If the sequence is degenerate without being geometric or quasigeometric, there
639
+ # may be many ``p`` th powers or no ``p`` th powers.
640
+
641
+ elif (self.b**2+4*self.c) == 0:
642
+
643
+ # This is the case if the matrix F is not diagonalizable, ie b^2 +4c = 0, and alpha/beta = 1.
644
+
645
+ alpha = self.b/2
646
+
647
+ # In this case, u_n = u_0*alpha^n + (u_1 - u_0*alpha)*n*alpha^(n-1) = alpha^(n-1)*(u_0 +n*(u_1 - u_0*alpha)),
648
+ # that is, it is a geometric term (alpha^(n-1)) times an arithmetic term (u_0 + n*(u_1-u_0*alpha)).
649
+
650
+ # Look at classes n = k mod p, for k = 1,...,p.
651
+
652
+ for k in range(1, p + 1):
653
+
654
+ # The linear equation alpha^(k-1)*u_0 + (k+pm)*(alpha^(k-1)*u1 - u0*alpha^k)
655
+ # must thus be a pth power. This is a linear equation in m, namely, A + B*m, where
656
+
657
+ A = (alpha**(k-1)*self.u0 + k*(alpha**(k-1)*self.u1 - self.u0*alpha**k))
658
+ B = p*(alpha**(k-1)*self.u1 - self.u0*alpha**k)
659
+
660
+ # This linear equation represents a pth power iff A is a pth power mod B.
661
+
662
+ if _is_p_power_mod(A, p, B):
663
+ raise ValueError("the degenerate binary recurrence sequence has many pth powers")
664
+ return []
665
+
666
+ # We find ``p`` th powers using an elementary sieve. Term `u_n` is a ``p`` th
667
+ # power if and only if it is a ``p`` th power modulo every prime `\\ell`. This condition
668
+ # gives nontrivial information if ``p`` divides the order of the multiplicative group of
669
+ # `\\Bold(F)_{\\ell}`, i.e. if `\\ell` is ` 1 \mod{p}`, as then only `1/p` terms are ``p`` th
670
+ # powers modulo `\\ell``.
671
+
672
+ # Thus, given such an `\\ell`, we get a set of necessary congruences for the index modulo the
673
+ # the period of the sequence mod `\\ell`. Then we intersect these congruences for many primes
674
+ # to get a tight list modulo a growing modulus. In order to keep this step manageable, we
675
+ # only use primes `\\ell` that have particularly smooth periods.
676
+
677
+ # Some congruences in the list will remain as the modulus grows. If a congruence remains through
678
+ # 7 rounds of increasing the modulus, then we check if this corresponds to a perfect power (if
679
+ # it does, we add it to our list of indices corresponding to ``p`` th powers). The rest of the congruences
680
+ # are transient and grow with the modulus. Once the smallest of these is greater than the bound,
681
+ # the list of known indices corresponding to ``p`` th powers is complete.
682
+
683
+ else:
684
+
685
+ if Bound < 3 * p:
686
+
687
+ powers = []
688
+ ell = p + 1
689
+
690
+ while not is_prime(ell):
691
+ ell += p
692
+
693
+ F = GF(ell)
694
+ a0 = F(self.u0)
695
+ a1 = F(self.u1) # a0 and a1 are variables for terms in sequence
696
+ bf, cf = F(self.b), F(self.c)
697
+
698
+ for n in range(Bound): # n is the index of the a0
699
+
700
+ # Check whether a0 is a perfect power mod ell
701
+ if _is_p_power_mod(a0, p, ell):
702
+ # if a0 is a perfect power mod ell, check if nth term is ppower
703
+ if _is_p_power(self(n), p):
704
+ powers.append(n)
705
+
706
+ a0, a1 = a1, bf*a1 + cf*a0 # step up the variables
707
+
708
+ else:
709
+
710
+ powers = [] # documents the indices of the sequence that provably correspond to pth powers
711
+ cong = [0] # list of necessary congruences on the index for it to correspond to pth powers
712
+ Possible_count = {} # keeps track of the number of rounds a congruence lasts in cong
713
+
714
+ # These parameters are involved in how we choose primes to increase the modulus
715
+ qqold = 1 # we believe that we know complete information coming from primes good by qqold
716
+ M1 = 1 # we have congruences modulo M1, this may not be the tightest list
717
+ M2 = p # we want to move to have congruences mod M2
718
+ qq = 1 # the largest prime power divisor of M1 is qq
719
+
720
+ # This loop ups the modulus.
721
+ while True:
722
+
723
+ # Try to get good data mod M2
724
+
725
+ # patience of how long we should search for a "good prime"
726
+ patience = 0.01 * _estimated_time(lcm(M2, p * next_prime_power(qq)),
727
+ M1, len(cong), p)
728
+ tries = 0
729
+
730
+ # This loop uses primes to get a small set of congruences mod M2.
731
+ while True:
732
+
733
+ # only proceed if took less than patience time to find the next good prime
734
+ ell = _next_good_prime(p, self, qq, patience, qqold)
735
+ if ell:
736
+
737
+ # gather congruence data for the sequence mod ell, which will be mod period(ell) = modu
738
+ cong1, modu = _find_cong1(p, self, ell)
739
+
740
+ # makes a new list from cong that is now mod M = lcm(M1, modu) instead of M1
741
+ M = lcm(M1, modu)
742
+ CongNew = [k * M1 + i for k in range(M // M1)
743
+ for i in cong]
744
+ cong = set(CongNew)
745
+
746
+ M1 = M
747
+
748
+ killed_something = False # keeps track of when cong1 can rule out a congruence in cong
749
+
750
+ # CRT by hand to gain speed
751
+ for i in list(cong):
752
+ if i % modu not in cong1: # congruence in cong is inconsistent with any in cong1
753
+ cong.remove(i) # remove that congruence
754
+ killed_something = True
755
+
756
+ if M1 == M2:
757
+ if not killed_something:
758
+ tries += 1
759
+ if tries == 2: # try twice to rule out congruences
760
+ cong = list(cong)
761
+ qqold = qq
762
+ qq = next_prime_power(qq)
763
+ M2 = lcm(M2, p * qq)
764
+ break
765
+
766
+ else:
767
+ qq = next_prime_power(qq)
768
+ M2 = lcm(M2, p * qq)
769
+ cong = list(cong)
770
+ break
771
+
772
+ # Document how long each element of cong has been there
773
+ for i in cong:
774
+ if i in Possible_count:
775
+ Possible_count[i] += 1
776
+ else:
777
+ Possible_count[i] = 1
778
+
779
+ # Check how long each element has persisted, if it is for at least 7 cycles,
780
+ # then we check to see if it is actually a perfect power
781
+ for i, pci in Possible_count.items():
782
+ if pci == 7:
783
+ n = Integer(i)
784
+ if n < Bound:
785
+ if _is_p_power(self(n), p):
786
+ powers.append(n)
787
+
788
+ # check for a contradiction
789
+ if len(cong) > len(powers):
790
+ if cong[len(powers)] > Bound:
791
+ break
792
+ elif M1 > Bound:
793
+ break
794
+
795
+ return powers
796
+
797
+
798
+ def _prime_powers(N):
799
+ r"""
800
+ Find the prime powers dividing `N`.
801
+
802
+ In other words, if `N = q_1^{e_1} q_2^{e_2} \cdots q_n^{e_n}`, it returns
803
+ `[q_1^{e_1}, q_2^{e_2}, \ldots, q_n^{e_n}]`.
804
+
805
+ INPUT:
806
+
807
+ - ``N`` -- integer
808
+
809
+ OUTPUT: list of the prime powers dividing N
810
+
811
+ EXAMPLES::
812
+
813
+ sage: sage.combinat.binary_recurrence_sequences._prime_powers(124656)
814
+ [3, 16, 49, 53]
815
+
816
+ sage: sage.combinat.binary_recurrence_sequences._prime_powers(65537)
817
+ [65537]
818
+ """
819
+ return sorted(i**j for i, j in N.factor())
820
+
821
+
822
+ def _largest_ppower_divisor(N):
823
+ """
824
+ Find the largest prime power divisor of `N`.
825
+
826
+ INPUT:
827
+
828
+ - ``N`` -- integer
829
+
830
+ OUTPUT: the largest prime power dividing `N`
831
+
832
+ EXAMPLES::
833
+
834
+ sage: sage.combinat.binary_recurrence_sequences._largest_ppower_divisor(124656)
835
+ 53
836
+ sage: sage.combinat.binary_recurrence_sequences._largest_ppower_divisor(65537)
837
+ 65537
838
+ """
839
+ return _prime_powers(N)[-1]
840
+
841
+
842
+ def _goodness(n, R, p):
843
+ """
844
+ Return the goodness of `n` for the sequence `R` and the prime `p` -- that is the largest
845
+ non-`p` prime power dividing ``period(n)``.
846
+
847
+ INPUT:
848
+
849
+ - ``n`` -- an integer
850
+
851
+ - ``R`` -- an object in the class ``BinaryRecurrenceSequence``
852
+
853
+ - ``p`` -- a rational prime
854
+
855
+ OUTPUT:
856
+
857
+ - An integer which is the "goodness" of ``n``, i.e. the largest non-``p`` prime power dividing ``period(n)``.
858
+
859
+ EXAMPLES::
860
+
861
+ sage: R = BinaryRecurrenceSequence(11,2)
862
+ sage: sage.combinat.binary_recurrence_sequences._goodness(89,R,7)
863
+ 11
864
+
865
+ sage: R = BinaryRecurrenceSequence(1,1)
866
+ sage: sage.combinat.binary_recurrence_sequences._goodness(13,R,7)
867
+ 4
868
+ sage: R.period(13) #the period of R mod 13 is divisible by 7
869
+ 28
870
+ """
871
+ # The period of R mod ell
872
+ K = R.period(n)
873
+ return _largest_ppower_divisor(K // K.gcd(p))
874
+
875
+
876
+ def _next_good_prime(p, R, qq, patience, qqold):
877
+ r"""
878
+ Find the next prime `\ell` which is good by ``qq`` but not by ``qqold``, 1 mod ``p``, and for which
879
+ ``b^2+4*c`` is a square mod `\ell`, for the sequence ``R`` if it is possible in runtime patience.
880
+
881
+ INPUT:
882
+
883
+ - ``p`` -- a prime
884
+
885
+ - ``R`` -- an object in the class ``BinaryRecurrenceSequence``
886
+
887
+ - ``qq`` -- a perfect power
888
+
889
+ - ``patience`` -- a real number
890
+
891
+ - ``qqold`` -- a perfect power less than or equal to ``qq``
892
+
893
+ OUTPUT: a prime `\ell` such that `\ell` is 1 mod `p`, `b^2+4 c` is a
894
+ square mod `\ell` and the period of `\ell` has ``goodness`` by ``qq`` but
895
+ not ``qqold``, if patience has not be surpased; otherwise ``False``
896
+
897
+ EXAMPLES::
898
+
899
+ sage: # needs sage.libs.pari
900
+ sage: R = BinaryRecurrenceSequence(1,1)
901
+ sage: sage.combinat.binary_recurrence_sequences._next_good_prime(7,R,1,100,1) #ran out of patience to search for good primes
902
+ False
903
+ sage: sage.combinat.binary_recurrence_sequences._next_good_prime(7,R,2,100,1)
904
+ 29
905
+ sage: sage.combinat.binary_recurrence_sequences._next_good_prime(7,R,2,100,2) #ran out of patience, as qqold == qq, so no primes work
906
+ False
907
+ """
908
+ # We are looking for pth powers in R.
909
+ # Our primes must be good by qq, but not qqold.
910
+ # We only allow patience number of iterations to find a good prime.
911
+
912
+ # The variable _ell for R keeps track of the last "good" prime returned
913
+ # that was not found from the dictionary _PGoodness
914
+
915
+ # First, we check to see if we have already computed the goodness of a prime that fits
916
+ # our requirement of being good by qq but not by qqold. This is stored in the _PGoodness
917
+ # dictionary.
918
+
919
+ # Then if we have, we return the smallest such prime and delete it from the list. If not, we
920
+ # search through patience number of primes R._ell to find one good by qq but not qqold. If it is
921
+ # not good by either qqold or qq, then we add this prime to R._PGoodness under its goodness.
922
+
923
+ # Possible_Primes keeps track of possible primes satisfying our goodness requirements we might return
924
+ # check to see if anything in R._PGoodness fits our goodness requirements
925
+ Possible_Primes = [item[0] for j, item in R._PGoodness.items()
926
+ if qqold < j <= qq and item]
927
+
928
+ # If we found good primes, we take the smallest
929
+ if Possible_Primes:
930
+ q = min(Possible_Primes)
931
+ n = _goodness(q, R, p)
932
+ del R._PGoodness[n][0] # if we are going to use it, then we delete it from R._PGoodness
933
+ return q
934
+
935
+ # If nothing is already stored in R._PGoodness, we start (from where we left off at R._ell) checking
936
+ # for good primes. We only tolerate patience number of tries before giving up.
937
+ else:
938
+ i = 0
939
+ while i < patience:
940
+ i += 1
941
+ R._ell = next_prime(R._ell)
942
+
943
+ # we require that R._ell is 1 mod p, so that p divides the order of the multiplicative
944
+ # group mod R._ell, so that not all elements of GF(R._ell) are pth powers.
945
+ if R._ell % p == 1:
946
+
947
+ # requiring that b^2 + 4c is a square in GF(R._ell) ensures that the period mod R._ell
948
+ # divides R._ell - 1
949
+ if legendre_symbol(R.b**2 + 4*R.c, R._ell) == 1:
950
+
951
+ N = _goodness(R._ell, R, p)
952
+
953
+ # proceed only if R._ell satisfies the goodness requirements
954
+ if qqold < N <= qq:
955
+ return R._ell
956
+
957
+ # if we do not use the prime, we store it in R._PGoodness
958
+ else:
959
+ if N in R._PGoodness:
960
+ R._PGoodness[N].append(R._ell)
961
+ else:
962
+ R._PGoodness[N] = [R._ell]
963
+
964
+ return False
965
+
966
+
967
+ def _is_p_power_mod(a, p, N):
968
+ """
969
+ Determine if ``a`` is a ``p`` th power modulo ``N``.
970
+
971
+ By the CRT, this is equivalent to the condition that ``a`` be a ``p`` th power mod all
972
+ distinct prime powers dividing ``N``. For each of these, we use the strong statement of
973
+ Hensel's lemma to lift ``p`` th powers mod `q` or `q^2` or `q^3` to ``p`` th powers mod `q^e`.
974
+
975
+ INPUT:
976
+
977
+ - ``a`` -- integer
978
+
979
+ - ``p`` -- a rational prime number
980
+
981
+ - ``N`` -- positive integer
982
+
983
+ OUTPUT: ``True`` if `a` is a `p`-th power modulo `N`; ``False`` otherwise
984
+
985
+ EXAMPLES::
986
+
987
+ sage: sage.combinat.binary_recurrence_sequences._is_p_power_mod(2**3,7,29)
988
+ False
989
+ sage: sage.combinat.binary_recurrence_sequences._is_p_power_mod(2**3,3,29)
990
+ True
991
+ """
992
+ # By the chinese remainder theorem, we can answer this question by examining whether
993
+ # a is a pth power mod q^e, for all distinct prime powers q^e dividing N.
994
+
995
+ for q, e in N.factor():
996
+
997
+ # If a = q^v*x, with
998
+
999
+ v = a.valuation(q)
1000
+
1001
+ # then if v>=e, a is congruent to 0 mod q^e and is thus a pth power trivially.
1002
+
1003
+ if v >= e:
1004
+ continue
1005
+
1006
+ # otherwise, it can only be a pth power if v is a multiple of p.
1007
+ if v % p:
1008
+ return False
1009
+
1010
+ # in this cse it is a pth power if x is a pth power mod q^(e-v), so let x = aa,
1011
+ # and (e-v) = ee:
1012
+
1013
+ aa = a / q**v
1014
+ ee = e - v
1015
+
1016
+ # The above steps are equivalent to the statement that we may assume a and qq are
1017
+ # relatively prime, if we replace a with aa and e with ee. Now we must determine when
1018
+ # aa is a pth power mod q^ee for (aa,q)=1.
1019
+
1020
+ # If q != p, then by Hensel's lemma, we may lift a pth power mod q, to a pth power
1021
+ # mod q^2, etc.
1022
+
1023
+ if q != p:
1024
+
1025
+ # aa is necessarily a pth power mod q if p does not divide the order of the multiplicative
1026
+ # group mod q, ie if q is not 1 mod p.
1027
+
1028
+ if q % p == 1:
1029
+
1030
+ # otherwise aa if a pth power mod q iff aa^(q-1)/p == 1
1031
+
1032
+ if GF(q)(aa)**((q - 1) / p) != 1:
1033
+ return False
1034
+
1035
+ # If q = p and ee = 1, then everything is a pth power p by Fermat's little theorem.
1036
+
1037
+ elif ee > 1:
1038
+
1039
+ # We use the strong statement of Hensel's lemma, which implies that if p is odd
1040
+ # and aa is a pth power mod p^2, then aa is a pth power mod any higher power of p
1041
+
1042
+ if p % 2:
1043
+
1044
+ # ZZ/(p^2)ZZ^\times is abstractly isomorphic to ZZ/(p)ZZ cross ZZ/(p-1)ZZ. then
1045
+ # aa is a pth power mod p^2 if (aa)^(p*(p-1)/p) == 1, ie if aa^(p-1) == 1.
1046
+
1047
+ if Integers(p**2)(aa)**(p - 1) != 1:
1048
+ return False
1049
+
1050
+ # Otherwise, p=2. By the strong statement of Hensel's lemma, if aa is a pth power
1051
+ # mod p^3, then it is a pth power mod higher powers of p. So we need only check if it
1052
+ # is a pth power mod p^2 and p^3.
1053
+
1054
+ elif ee == 2:
1055
+
1056
+ # all odd squares a 1 mod 4
1057
+
1058
+ if aa % 4 != 1:
1059
+ return False
1060
+
1061
+ # all odd squares are 1 mod 8
1062
+
1063
+ elif aa % 8 != 1:
1064
+ return False
1065
+
1066
+ return True
1067
+
1068
+
1069
+ def _estimated_time(M2, M1, length, p):
1070
+ """
1071
+ Find the estimated time to extend congruences mod M1 to consistent congruences mod M2.
1072
+
1073
+ INPUT:
1074
+
1075
+ - ``M2`` -- integer; (the new modulus)
1076
+
1077
+ - ``M1`` -- integer; (the old modulus)
1078
+
1079
+ - ``length`` -- list (the current length of the list of congruences mod ``M1``)
1080
+
1081
+ - ``p`` -- a prime
1082
+
1083
+ OUTPUT: the estimated run time of the "CRT" step to combine consistent congruences
1084
+
1085
+ EXAMPLES::
1086
+
1087
+ sage: from sage.combinat.binary_recurrence_sequences import _estimated_time
1088
+ sage: _estimated_time(2**4*3**2*5*7*11*13*17, 2**4*3**2*5*7*11*13, 20, 7) # needs sage.symbolic
1089
+ 106.211159309421
1090
+ """
1091
+ # The heuristic run time of the CRT step to go from modulus M1 to M2
1092
+
1093
+ # length is the current length of cong
1094
+
1095
+ Q = p * log(M2) # Size of our primes.
1096
+ NPrimes = log(M2 / M1) / log(Q) # The number of primes
1097
+
1098
+ return (length * (Q / p)**NPrimes).n()
1099
+
1100
+
1101
+ # Find the list of necessary congruences for the index n of binary recurrence
1102
+ # sequence R using the fact that the reduction mod ell must be a pth power
1103
+ def _find_cong1(p, R, ell):
1104
+ """
1105
+ Find the list of permissible indices `n` for which `u_n = y^p` mod ``ell``.
1106
+
1107
+ INPUT:
1108
+
1109
+ - ``p`` -- a prime number
1110
+
1111
+ - ``R`` -- an object in class :class:`BinaryRecurrenceSequence`
1112
+
1113
+ - ``ell`` -- a prime number
1114
+
1115
+ OUTPUT:
1116
+
1117
+ - A list of permissible values of `n` modulo ``period(ell)`` and the integer ``period(ell)``.
1118
+
1119
+ EXAMPLES::
1120
+
1121
+ sage: R = BinaryRecurrenceSequence(1,1)
1122
+ sage: sage.combinat.binary_recurrence_sequences._find_cong1(7, R, 29) # needs sage.rings.finite_rings
1123
+ ([0, 1, 2, 12, 13], 14)
1124
+ """
1125
+ F = GF(ell)
1126
+ u0 = F(R.u0)
1127
+ u1 = F(R.u1)
1128
+ bf, cf = F(R.b), F(R.c)
1129
+ a0 = u0
1130
+ a1 = u1 # a0 and a1 are variables for terms in sequence
1131
+
1132
+ # The set of pth powers mod ell
1133
+ PPowers = set(i**p for i in F)
1134
+
1135
+ # The period of R mod ell
1136
+ modu = R.period(ell)
1137
+
1138
+ # cong1 keeps track of congruences mod modu for the sequence mod ell
1139
+ cong1 = []
1140
+
1141
+ for n in range(modu): # n is the index of the a0
1142
+
1143
+ # Check whether a0 is a perfect power mod ell
1144
+ if a0 in PPowers:
1145
+ # if a0 is a perfect power mod ell, add the index
1146
+ # to the list of necessary congruences
1147
+ cong1.append(n)
1148
+
1149
+ a0, a1 = a1, bf * a1 + cf * a0 # step up the variables
1150
+
1151
+ cong1.sort()
1152
+
1153
+ return cong1, modu
1154
+
1155
+
1156
+ def _is_p_power(a, p) -> bool:
1157
+ """
1158
+ Determine whether `a` is a perfect `p`-th power.
1159
+
1160
+ INPUT:
1161
+
1162
+ - ``a`` -- integer
1163
+
1164
+ - ``p`` -- a prime number
1165
+
1166
+ OUTPUT: boolean
1167
+
1168
+ EXAMPLES::
1169
+
1170
+ sage: from sage.combinat.binary_recurrence_sequences import _is_p_power
1171
+ sage: _is_p_power(2**7, 7)
1172
+ True
1173
+ sage: _is_p_power(2**7*3**2, 7)
1174
+ False
1175
+ """
1176
+ try:
1177
+ Integer(a).nth_root(p)
1178
+ except ValueError:
1179
+ return False
1180
+ return True