passagemath-categories 10.6.44__cp310-cp310-win_arm64.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 (719) hide show
  1. passagemath_categories/__init__.py +3 -0
  2. passagemath_categories-10.6.44.dist-info/DELVEWHEEL +2 -0
  3. passagemath_categories-10.6.44.dist-info/METADATA +157 -0
  4. passagemath_categories-10.6.44.dist-info/RECORD +719 -0
  5. passagemath_categories-10.6.44.dist-info/WHEEL +5 -0
  6. passagemath_categories-10.6.44.dist-info/top_level.txt +3 -0
  7. passagemath_categories.libs/libgmp-10-98b8b97e0a62cfb2d4dd4b0f18b70bdd.dll +0 -0
  8. passagemath_categories.libs/msvcp140-9cb625fcbc2fbbd6fca1aee8b24b0ebe.dll +0 -0
  9. sage/all__sagemath_categories.py +37 -0
  10. sage/arith/all.py +38 -0
  11. sage/arith/constants.pxd +27 -0
  12. sage/arith/functions.cp310-win_arm64.pyd +0 -0
  13. sage/arith/functions.pxd +4 -0
  14. sage/arith/functions.pyx +221 -0
  15. sage/arith/misc.py +6552 -0
  16. sage/arith/multi_modular.cp310-win_arm64.pyd +0 -0
  17. sage/arith/multi_modular.pxd +39 -0
  18. sage/arith/multi_modular.pyx +994 -0
  19. sage/arith/rational_reconstruction.cp310-win_arm64.pyd +0 -0
  20. sage/arith/rational_reconstruction.pxd +4 -0
  21. sage/arith/rational_reconstruction.pyx +115 -0
  22. sage/arith/srange.cp310-win_arm64.pyd +0 -0
  23. sage/arith/srange.pyx +571 -0
  24. sage/calculus/all__sagemath_categories.py +2 -0
  25. sage/calculus/functional.py +481 -0
  26. sage/calculus/functions.py +151 -0
  27. sage/categories/additive_groups.py +73 -0
  28. sage/categories/additive_magmas.py +1044 -0
  29. sage/categories/additive_monoids.py +114 -0
  30. sage/categories/additive_semigroups.py +184 -0
  31. sage/categories/affine_weyl_groups.py +238 -0
  32. sage/categories/algebra_ideals.py +95 -0
  33. sage/categories/algebra_modules.py +96 -0
  34. sage/categories/algebras.py +349 -0
  35. sage/categories/algebras_with_basis.py +377 -0
  36. sage/categories/all.py +160 -0
  37. sage/categories/aperiodic_semigroups.py +29 -0
  38. sage/categories/associative_algebras.py +47 -0
  39. sage/categories/bialgebras.py +101 -0
  40. sage/categories/bialgebras_with_basis.py +414 -0
  41. sage/categories/bimodules.py +206 -0
  42. sage/categories/chain_complexes.py +268 -0
  43. sage/categories/classical_crystals.py +480 -0
  44. sage/categories/coalgebras.py +405 -0
  45. sage/categories/coalgebras_with_basis.py +232 -0
  46. sage/categories/coercion_methods.cp310-win_arm64.pyd +0 -0
  47. sage/categories/coercion_methods.pyx +52 -0
  48. sage/categories/commutative_additive_groups.py +104 -0
  49. sage/categories/commutative_additive_monoids.py +45 -0
  50. sage/categories/commutative_additive_semigroups.py +48 -0
  51. sage/categories/commutative_algebra_ideals.py +87 -0
  52. sage/categories/commutative_algebras.py +94 -0
  53. sage/categories/commutative_ring_ideals.py +58 -0
  54. sage/categories/commutative_rings.py +736 -0
  55. sage/categories/complete_discrete_valuation.py +293 -0
  56. sage/categories/complex_reflection_groups.py +145 -0
  57. sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
  58. sage/categories/coxeter_group_algebras.py +186 -0
  59. sage/categories/coxeter_groups.py +3402 -0
  60. sage/categories/crystals.py +2628 -0
  61. sage/categories/cw_complexes.py +216 -0
  62. sage/categories/dedekind_domains.py +137 -0
  63. sage/categories/discrete_valuation.py +325 -0
  64. sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
  65. sage/categories/division_rings.py +114 -0
  66. sage/categories/domains.py +95 -0
  67. sage/categories/drinfeld_modules.py +789 -0
  68. sage/categories/dual.py +42 -0
  69. sage/categories/enumerated_sets.py +1146 -0
  70. sage/categories/euclidean_domains.py +271 -0
  71. sage/categories/examples/algebras_with_basis.py +102 -0
  72. sage/categories/examples/all.py +1 -0
  73. sage/categories/examples/commutative_additive_monoids.py +130 -0
  74. sage/categories/examples/commutative_additive_semigroups.py +199 -0
  75. sage/categories/examples/coxeter_groups.py +8 -0
  76. sage/categories/examples/crystals.py +236 -0
  77. sage/categories/examples/cw_complexes.py +163 -0
  78. sage/categories/examples/facade_sets.py +187 -0
  79. sage/categories/examples/filtered_algebras_with_basis.py +204 -0
  80. sage/categories/examples/filtered_modules_with_basis.py +154 -0
  81. sage/categories/examples/finite_coxeter_groups.py +252 -0
  82. sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
  83. sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
  84. sage/categories/examples/finite_enumerated_sets.py +208 -0
  85. sage/categories/examples/finite_monoids.py +150 -0
  86. sage/categories/examples/finite_semigroups.py +190 -0
  87. sage/categories/examples/finite_weyl_groups.py +191 -0
  88. sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
  89. sage/categories/examples/graded_modules_with_basis.py +168 -0
  90. sage/categories/examples/graphs.py +122 -0
  91. sage/categories/examples/hopf_algebras_with_basis.py +145 -0
  92. sage/categories/examples/infinite_enumerated_sets.py +190 -0
  93. sage/categories/examples/lie_algebras.py +352 -0
  94. sage/categories/examples/lie_algebras_with_basis.py +196 -0
  95. sage/categories/examples/magmas.py +162 -0
  96. sage/categories/examples/manifolds.py +94 -0
  97. sage/categories/examples/monoids.py +144 -0
  98. sage/categories/examples/posets.py +178 -0
  99. sage/categories/examples/semigroups.py +580 -0
  100. sage/categories/examples/semigroups_cython.cp310-win_arm64.pyd +0 -0
  101. sage/categories/examples/semigroups_cython.pyx +221 -0
  102. sage/categories/examples/semirings.py +249 -0
  103. sage/categories/examples/sets_cat.py +706 -0
  104. sage/categories/examples/sets_with_grading.py +101 -0
  105. sage/categories/examples/with_realizations.py +542 -0
  106. sage/categories/fields.py +991 -0
  107. sage/categories/filtered_algebras.py +63 -0
  108. sage/categories/filtered_algebras_with_basis.py +548 -0
  109. sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
  110. sage/categories/filtered_modules.py +210 -0
  111. sage/categories/filtered_modules_with_basis.py +1209 -0
  112. sage/categories/finite_complex_reflection_groups.py +1506 -0
  113. sage/categories/finite_coxeter_groups.py +1138 -0
  114. sage/categories/finite_crystals.py +103 -0
  115. sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
  116. sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
  117. sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
  118. sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
  119. sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
  120. sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
  121. sage/categories/finite_dimensional_modules_with_basis.py +1566 -0
  122. sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
  123. sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
  124. sage/categories/finite_enumerated_sets.py +769 -0
  125. sage/categories/finite_fields.py +252 -0
  126. sage/categories/finite_groups.py +256 -0
  127. sage/categories/finite_lattice_posets.py +242 -0
  128. sage/categories/finite_monoids.py +316 -0
  129. sage/categories/finite_permutation_groups.py +339 -0
  130. sage/categories/finite_posets.py +1994 -0
  131. sage/categories/finite_semigroups.py +136 -0
  132. sage/categories/finite_sets.py +93 -0
  133. sage/categories/finite_weyl_groups.py +39 -0
  134. sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
  135. sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
  136. sage/categories/finitely_generated_magmas.py +57 -0
  137. sage/categories/finitely_generated_semigroups.py +214 -0
  138. sage/categories/function_fields.py +76 -0
  139. sage/categories/g_sets.py +77 -0
  140. sage/categories/gcd_domains.py +65 -0
  141. sage/categories/generalized_coxeter_groups.py +94 -0
  142. sage/categories/graded_algebras.py +85 -0
  143. sage/categories/graded_algebras_with_basis.py +258 -0
  144. sage/categories/graded_bialgebras.py +32 -0
  145. sage/categories/graded_bialgebras_with_basis.py +32 -0
  146. sage/categories/graded_coalgebras.py +65 -0
  147. sage/categories/graded_coalgebras_with_basis.py +51 -0
  148. sage/categories/graded_hopf_algebras.py +41 -0
  149. sage/categories/graded_hopf_algebras_with_basis.py +169 -0
  150. sage/categories/graded_lie_algebras.py +91 -0
  151. sage/categories/graded_lie_algebras_with_basis.py +44 -0
  152. sage/categories/graded_lie_conformal_algebras.py +74 -0
  153. sage/categories/graded_modules.py +133 -0
  154. sage/categories/graded_modules_with_basis.py +329 -0
  155. sage/categories/graphs.py +138 -0
  156. sage/categories/group_algebras.py +430 -0
  157. sage/categories/groupoid.py +94 -0
  158. sage/categories/groups.py +667 -0
  159. sage/categories/h_trivial_semigroups.py +64 -0
  160. sage/categories/hecke_modules.py +185 -0
  161. sage/categories/highest_weight_crystals.py +980 -0
  162. sage/categories/hopf_algebras.py +219 -0
  163. sage/categories/hopf_algebras_with_basis.py +309 -0
  164. sage/categories/infinite_enumerated_sets.py +115 -0
  165. sage/categories/integral_domains.py +203 -0
  166. sage/categories/j_trivial_semigroups.py +29 -0
  167. sage/categories/kac_moody_algebras.py +82 -0
  168. sage/categories/kahler_algebras.py +203 -0
  169. sage/categories/l_trivial_semigroups.py +63 -0
  170. sage/categories/lambda_bracket_algebras.py +280 -0
  171. sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
  172. sage/categories/lattice_posets.py +89 -0
  173. sage/categories/left_modules.py +49 -0
  174. sage/categories/lie_algebras.py +1070 -0
  175. sage/categories/lie_algebras_with_basis.py +261 -0
  176. sage/categories/lie_conformal_algebras.py +350 -0
  177. sage/categories/lie_conformal_algebras_with_basis.py +147 -0
  178. sage/categories/lie_groups.py +73 -0
  179. sage/categories/loop_crystals.py +1290 -0
  180. sage/categories/magmas.py +1189 -0
  181. sage/categories/magmas_and_additive_magmas.py +149 -0
  182. sage/categories/magmatic_algebras.py +365 -0
  183. sage/categories/manifolds.py +352 -0
  184. sage/categories/matrix_algebras.py +40 -0
  185. sage/categories/metric_spaces.py +387 -0
  186. sage/categories/modular_abelian_varieties.py +78 -0
  187. sage/categories/modules.py +989 -0
  188. sage/categories/modules_with_basis.py +2985 -0
  189. sage/categories/monoid_algebras.py +38 -0
  190. sage/categories/monoids.py +739 -0
  191. sage/categories/noetherian_rings.py +87 -0
  192. sage/categories/number_fields.py +242 -0
  193. sage/categories/ore_modules.py +189 -0
  194. sage/categories/partially_ordered_monoids.py +49 -0
  195. sage/categories/permutation_groups.py +63 -0
  196. sage/categories/pointed_sets.py +42 -0
  197. sage/categories/polyhedra.py +74 -0
  198. sage/categories/poor_man_map.py +270 -0
  199. sage/categories/posets.py +722 -0
  200. sage/categories/principal_ideal_domains.py +270 -0
  201. sage/categories/quantum_group_representations.py +543 -0
  202. sage/categories/quotient_fields.py +728 -0
  203. sage/categories/r_trivial_semigroups.py +45 -0
  204. sage/categories/regular_crystals.py +898 -0
  205. sage/categories/regular_supercrystals.py +170 -0
  206. sage/categories/right_modules.py +49 -0
  207. sage/categories/ring_ideals.py +74 -0
  208. sage/categories/rings.py +1904 -0
  209. sage/categories/rngs.py +175 -0
  210. sage/categories/schemes.py +393 -0
  211. sage/categories/semigroups.py +1060 -0
  212. sage/categories/semirings.py +71 -0
  213. sage/categories/semisimple_algebras.py +114 -0
  214. sage/categories/sets_with_grading.py +235 -0
  215. sage/categories/shephard_groups.py +43 -0
  216. sage/categories/signed_tensor.py +120 -0
  217. sage/categories/simplicial_complexes.py +134 -0
  218. sage/categories/simplicial_sets.py +1206 -0
  219. sage/categories/super_algebras.py +149 -0
  220. sage/categories/super_algebras_with_basis.py +144 -0
  221. sage/categories/super_hopf_algebras_with_basis.py +126 -0
  222. sage/categories/super_lie_conformal_algebras.py +193 -0
  223. sage/categories/super_modules.py +229 -0
  224. sage/categories/super_modules_with_basis.py +193 -0
  225. sage/categories/supercommutative_algebras.py +99 -0
  226. sage/categories/supercrystals.py +406 -0
  227. sage/categories/tensor.py +110 -0
  228. sage/categories/topological_spaces.py +170 -0
  229. sage/categories/triangular_kac_moody_algebras.py +439 -0
  230. sage/categories/tutorial.py +58 -0
  231. sage/categories/unique_factorization_domains.py +318 -0
  232. sage/categories/unital_algebras.py +426 -0
  233. sage/categories/vector_bundles.py +159 -0
  234. sage/categories/vector_spaces.py +357 -0
  235. sage/categories/weyl_groups.py +853 -0
  236. sage/combinat/all__sagemath_categories.py +34 -0
  237. sage/combinat/backtrack.py +180 -0
  238. sage/combinat/combinat.py +2269 -0
  239. sage/combinat/combinat_cython.cp310-win_arm64.pyd +0 -0
  240. sage/combinat/combinat_cython.pxd +6 -0
  241. sage/combinat/combinat_cython.pyx +390 -0
  242. sage/combinat/combination.py +796 -0
  243. sage/combinat/combinatorial_map.py +416 -0
  244. sage/combinat/composition.py +2192 -0
  245. sage/combinat/dlx.py +510 -0
  246. sage/combinat/integer_lists/__init__.py +7 -0
  247. sage/combinat/integer_lists/base.cp310-win_arm64.pyd +0 -0
  248. sage/combinat/integer_lists/base.pxd +16 -0
  249. sage/combinat/integer_lists/base.pyx +713 -0
  250. sage/combinat/integer_lists/invlex.cp310-win_arm64.pyd +0 -0
  251. sage/combinat/integer_lists/invlex.pxd +4 -0
  252. sage/combinat/integer_lists/invlex.pyx +1650 -0
  253. sage/combinat/integer_lists/lists.py +328 -0
  254. sage/combinat/integer_lists/nn.py +48 -0
  255. sage/combinat/integer_vector.py +1818 -0
  256. sage/combinat/integer_vector_weighted.py +413 -0
  257. sage/combinat/matrices/all__sagemath_categories.py +5 -0
  258. sage/combinat/matrices/dancing_links.cp310-win_arm64.pyd +0 -0
  259. sage/combinat/matrices/dancing_links.pyx +1159 -0
  260. sage/combinat/matrices/dancing_links_c.h +380 -0
  261. sage/combinat/matrices/dlxcpp.py +136 -0
  262. sage/combinat/partition.py +10070 -0
  263. sage/combinat/partitions.cp310-win_arm64.pyd +0 -0
  264. sage/combinat/partitions.pyx +743 -0
  265. sage/combinat/permutation.py +10168 -0
  266. sage/combinat/permutation_cython.cp310-win_arm64.pyd +0 -0
  267. sage/combinat/permutation_cython.pxd +11 -0
  268. sage/combinat/permutation_cython.pyx +407 -0
  269. sage/combinat/q_analogues.py +1090 -0
  270. sage/combinat/ranker.py +268 -0
  271. sage/combinat/subset.py +1561 -0
  272. sage/combinat/subsets_hereditary.py +202 -0
  273. sage/combinat/subsets_pairwise.py +184 -0
  274. sage/combinat/tools.py +63 -0
  275. sage/combinat/tuple.py +348 -0
  276. sage/data_structures/all.py +2 -0
  277. sage/data_structures/all__sagemath_categories.py +2 -0
  278. sage/data_structures/binary_matrix.pxd +138 -0
  279. sage/data_structures/binary_search.cp310-win_arm64.pyd +0 -0
  280. sage/data_structures/binary_search.pxd +3 -0
  281. sage/data_structures/binary_search.pyx +66 -0
  282. sage/data_structures/bitset.cp310-win_arm64.pyd +0 -0
  283. sage/data_structures/bitset.pxd +40 -0
  284. sage/data_structures/bitset.pyx +2385 -0
  285. sage/data_structures/bitset_base.cp310-win_arm64.pyd +0 -0
  286. sage/data_structures/bitset_base.pxd +926 -0
  287. sage/data_structures/bitset_base.pyx +117 -0
  288. sage/data_structures/bitset_intrinsics.h +487 -0
  289. sage/data_structures/blas_dict.cp310-win_arm64.pyd +0 -0
  290. sage/data_structures/blas_dict.pxd +12 -0
  291. sage/data_structures/blas_dict.pyx +469 -0
  292. sage/data_structures/list_of_pairs.cp310-win_arm64.pyd +0 -0
  293. sage/data_structures/list_of_pairs.pxd +16 -0
  294. sage/data_structures/list_of_pairs.pyx +122 -0
  295. sage/data_structures/mutable_poset.py +3312 -0
  296. sage/data_structures/pairing_heap.cp310-win_arm64.pyd +0 -0
  297. sage/data_structures/pairing_heap.h +346 -0
  298. sage/data_structures/pairing_heap.pxd +88 -0
  299. sage/data_structures/pairing_heap.pyx +1464 -0
  300. sage/data_structures/sparse_bitset.pxd +62 -0
  301. sage/data_structures/stream.py +5070 -0
  302. sage/databases/all__sagemath_categories.py +7 -0
  303. sage/databases/sql_db.py +2236 -0
  304. sage/ext/all__sagemath_categories.py +3 -0
  305. sage/ext/fast_callable.cp310-win_arm64.pyd +0 -0
  306. sage/ext/fast_callable.pxd +4 -0
  307. sage/ext/fast_callable.pyx +2746 -0
  308. sage/ext/fast_eval.cp310-win_arm64.pyd +0 -0
  309. sage/ext/fast_eval.pxd +1 -0
  310. sage/ext/fast_eval.pyx +102 -0
  311. sage/ext/interpreters/all__sagemath_categories.py +2 -0
  312. sage/ext/interpreters/wrapper_el.cp310-win_arm64.pyd +0 -0
  313. sage/ext/interpreters/wrapper_el.pxd +18 -0
  314. sage/ext/interpreters/wrapper_el.pyx +148 -0
  315. sage/ext/interpreters/wrapper_py.cp310-win_arm64.pyd +0 -0
  316. sage/ext/interpreters/wrapper_py.pxd +17 -0
  317. sage/ext/interpreters/wrapper_py.pyx +133 -0
  318. sage/functions/airy.py +937 -0
  319. sage/functions/all.py +97 -0
  320. sage/functions/bessel.py +2102 -0
  321. sage/functions/error.py +784 -0
  322. sage/functions/exp_integral.py +1529 -0
  323. sage/functions/gamma.py +1087 -0
  324. sage/functions/generalized.py +672 -0
  325. sage/functions/hyperbolic.py +747 -0
  326. sage/functions/hypergeometric.py +1156 -0
  327. sage/functions/jacobi.py +1705 -0
  328. sage/functions/log.py +1402 -0
  329. sage/functions/min_max.py +338 -0
  330. sage/functions/orthogonal_polys.py +3106 -0
  331. sage/functions/other.py +2303 -0
  332. sage/functions/piecewise.py +1505 -0
  333. sage/functions/prime_pi.cp310-win_arm64.pyd +0 -0
  334. sage/functions/prime_pi.pyx +262 -0
  335. sage/functions/special.py +1212 -0
  336. sage/functions/spike_function.py +278 -0
  337. sage/functions/transcendental.py +690 -0
  338. sage/functions/trig.py +1062 -0
  339. sage/functions/wigner.py +726 -0
  340. sage/geometry/abc.cp310-win_arm64.pyd +0 -0
  341. sage/geometry/abc.pyx +82 -0
  342. sage/geometry/all__sagemath_categories.py +1 -0
  343. sage/groups/all__sagemath_categories.py +11 -0
  344. sage/groups/generic.py +1733 -0
  345. sage/groups/groups_catalog.py +113 -0
  346. sage/groups/perm_gps/all__sagemath_categories.py +1 -0
  347. sage/groups/perm_gps/partn_ref/all.py +1 -0
  348. sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
  349. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cp310-win_arm64.pyd +0 -0
  350. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
  351. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
  352. sage/groups/perm_gps/partn_ref/canonical_augmentation.cp310-win_arm64.pyd +0 -0
  353. sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
  354. sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
  355. sage/groups/perm_gps/partn_ref/data_structures.cp310-win_arm64.pyd +0 -0
  356. sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
  357. sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
  358. sage/groups/perm_gps/partn_ref/double_coset.cp310-win_arm64.pyd +0 -0
  359. sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
  360. sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
  361. sage/groups/perm_gps/partn_ref/refinement_lists.cp310-win_arm64.pyd +0 -0
  362. sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
  363. sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
  364. sage/groups/perm_gps/partn_ref/refinement_python.cp310-win_arm64.pyd +0 -0
  365. sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
  366. sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
  367. sage/groups/perm_gps/partn_ref/refinement_sets.cp310-win_arm64.pyd +0 -0
  368. sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
  369. sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
  370. sage/interfaces/abc.py +140 -0
  371. sage/interfaces/all.py +58 -0
  372. sage/interfaces/all__sagemath_categories.py +1 -0
  373. sage/interfaces/expect.py +1643 -0
  374. sage/interfaces/interface.py +1682 -0
  375. sage/interfaces/process.cp310-win_arm64.pyd +0 -0
  376. sage/interfaces/process.pxd +5 -0
  377. sage/interfaces/process.pyx +320 -0
  378. sage/interfaces/quit.py +167 -0
  379. sage/interfaces/sage0.py +604 -0
  380. sage/interfaces/sagespawn.cp310-win_arm64.pyd +0 -0
  381. sage/interfaces/sagespawn.pyx +308 -0
  382. sage/interfaces/tab_completion.py +101 -0
  383. sage/misc/all__sagemath_categories.py +78 -0
  384. sage/misc/allocator.cp310-win_arm64.pyd +0 -0
  385. sage/misc/allocator.pxd +6 -0
  386. sage/misc/allocator.pyx +47 -0
  387. sage/misc/binary_tree.cp310-win_arm64.pyd +0 -0
  388. sage/misc/binary_tree.pxd +29 -0
  389. sage/misc/binary_tree.pyx +537 -0
  390. sage/misc/callable_dict.cp310-win_arm64.pyd +0 -0
  391. sage/misc/callable_dict.pyx +89 -0
  392. sage/misc/citation.cp310-win_arm64.pyd +0 -0
  393. sage/misc/citation.pyx +159 -0
  394. sage/misc/converting_dict.py +293 -0
  395. sage/misc/defaults.py +129 -0
  396. sage/misc/derivative.cp310-win_arm64.pyd +0 -0
  397. sage/misc/derivative.pyx +223 -0
  398. sage/misc/functional.py +2005 -0
  399. sage/misc/html.py +589 -0
  400. sage/misc/latex.py +2673 -0
  401. sage/misc/latex_macros.py +236 -0
  402. sage/misc/latex_standalone.py +1833 -0
  403. sage/misc/map_threaded.py +38 -0
  404. sage/misc/mathml.py +76 -0
  405. sage/misc/method_decorator.py +88 -0
  406. sage/misc/mrange.py +755 -0
  407. sage/misc/multireplace.py +41 -0
  408. sage/misc/object_multiplexer.py +92 -0
  409. sage/misc/parser.cp310-win_arm64.pyd +0 -0
  410. sage/misc/parser.pyx +1107 -0
  411. sage/misc/random_testing.py +264 -0
  412. sage/misc/rest_index_of_methods.py +377 -0
  413. sage/misc/search.cp310-win_arm64.pyd +0 -0
  414. sage/misc/search.pxd +2 -0
  415. sage/misc/search.pyx +68 -0
  416. sage/misc/stopgap.cp310-win_arm64.pyd +0 -0
  417. sage/misc/stopgap.pyx +95 -0
  418. sage/misc/table.py +853 -0
  419. sage/monoids/all__sagemath_categories.py +1 -0
  420. sage/monoids/indexed_free_monoid.py +1071 -0
  421. sage/monoids/monoid.py +82 -0
  422. sage/numerical/all__sagemath_categories.py +1 -0
  423. sage/numerical/backends/all__sagemath_categories.py +1 -0
  424. sage/numerical/backends/generic_backend.cp310-win_arm64.pyd +0 -0
  425. sage/numerical/backends/generic_backend.pxd +61 -0
  426. sage/numerical/backends/generic_backend.pyx +1893 -0
  427. sage/numerical/backends/generic_sdp_backend.cp310-win_arm64.pyd +0 -0
  428. sage/numerical/backends/generic_sdp_backend.pxd +38 -0
  429. sage/numerical/backends/generic_sdp_backend.pyx +755 -0
  430. sage/parallel/all.py +6 -0
  431. sage/parallel/decorate.py +575 -0
  432. sage/parallel/map_reduce.py +1997 -0
  433. sage/parallel/multiprocessing_sage.py +77 -0
  434. sage/parallel/ncpus.py +35 -0
  435. sage/parallel/parallelism.py +364 -0
  436. sage/parallel/reference.py +47 -0
  437. sage/parallel/use_fork.py +333 -0
  438. sage/rings/abc.cp310-win_arm64.pyd +0 -0
  439. sage/rings/abc.pxd +31 -0
  440. sage/rings/abc.pyx +526 -0
  441. sage/rings/algebraic_closure_finite_field.py +1154 -0
  442. sage/rings/all__sagemath_categories.py +91 -0
  443. sage/rings/big_oh.py +227 -0
  444. sage/rings/continued_fraction.py +2754 -0
  445. sage/rings/continued_fraction_gosper.py +220 -0
  446. sage/rings/factorint.cp310-win_arm64.pyd +0 -0
  447. sage/rings/factorint.pyx +295 -0
  448. sage/rings/fast_arith.cp310-win_arm64.pyd +0 -0
  449. sage/rings/fast_arith.pxd +21 -0
  450. sage/rings/fast_arith.pyx +535 -0
  451. sage/rings/finite_rings/all__sagemath_categories.py +9 -0
  452. sage/rings/finite_rings/conway_polynomials.py +542 -0
  453. sage/rings/finite_rings/element_base.cp310-win_arm64.pyd +0 -0
  454. sage/rings/finite_rings/element_base.pxd +12 -0
  455. sage/rings/finite_rings/element_base.pyx +1176 -0
  456. sage/rings/finite_rings/finite_field_base.cp310-win_arm64.pyd +0 -0
  457. sage/rings/finite_rings/finite_field_base.pxd +7 -0
  458. sage/rings/finite_rings/finite_field_base.pyx +2171 -0
  459. sage/rings/finite_rings/finite_field_constructor.py +827 -0
  460. sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
  461. sage/rings/finite_rings/galois_group.py +154 -0
  462. sage/rings/finite_rings/hom_finite_field.cp310-win_arm64.pyd +0 -0
  463. sage/rings/finite_rings/hom_finite_field.pxd +23 -0
  464. sage/rings/finite_rings/hom_finite_field.pyx +856 -0
  465. sage/rings/finite_rings/hom_prime_finite_field.cp310-win_arm64.pyd +0 -0
  466. sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
  467. sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
  468. sage/rings/finite_rings/homset.py +357 -0
  469. sage/rings/finite_rings/integer_mod.cp310-win_arm64.pyd +0 -0
  470. sage/rings/finite_rings/integer_mod.pxd +56 -0
  471. sage/rings/finite_rings/integer_mod.pyx +4586 -0
  472. sage/rings/finite_rings/integer_mod_limits.h +11 -0
  473. sage/rings/finite_rings/integer_mod_ring.py +2044 -0
  474. sage/rings/finite_rings/residue_field.cp310-win_arm64.pyd +0 -0
  475. sage/rings/finite_rings/residue_field.pxd +30 -0
  476. sage/rings/finite_rings/residue_field.pyx +1811 -0
  477. sage/rings/finite_rings/stdint.pxd +19 -0
  478. sage/rings/fraction_field.py +1452 -0
  479. sage/rings/fraction_field_element.cp310-win_arm64.pyd +0 -0
  480. sage/rings/fraction_field_element.pyx +1357 -0
  481. sage/rings/function_field/all.py +7 -0
  482. sage/rings/function_field/all__sagemath_categories.py +2 -0
  483. sage/rings/function_field/constructor.py +218 -0
  484. sage/rings/function_field/element.cp310-win_arm64.pyd +0 -0
  485. sage/rings/function_field/element.pxd +11 -0
  486. sage/rings/function_field/element.pyx +1008 -0
  487. sage/rings/function_field/element_rational.cp310-win_arm64.pyd +0 -0
  488. sage/rings/function_field/element_rational.pyx +513 -0
  489. sage/rings/function_field/extensions.py +230 -0
  490. sage/rings/function_field/function_field.py +1468 -0
  491. sage/rings/function_field/function_field_rational.py +1005 -0
  492. sage/rings/function_field/ideal.py +1155 -0
  493. sage/rings/function_field/ideal_rational.py +629 -0
  494. sage/rings/function_field/jacobian_base.py +826 -0
  495. sage/rings/function_field/jacobian_hess.py +1053 -0
  496. sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
  497. sage/rings/function_field/maps.py +1039 -0
  498. sage/rings/function_field/order.py +281 -0
  499. sage/rings/function_field/order_basis.py +586 -0
  500. sage/rings/function_field/order_rational.py +576 -0
  501. sage/rings/function_field/place.py +426 -0
  502. sage/rings/function_field/place_rational.py +181 -0
  503. sage/rings/generic.py +320 -0
  504. sage/rings/homset.py +332 -0
  505. sage/rings/ideal.py +1885 -0
  506. sage/rings/ideal_monoid.py +215 -0
  507. sage/rings/infinity.py +1890 -0
  508. sage/rings/integer.cp310-win_arm64.pyd +0 -0
  509. sage/rings/integer.pxd +45 -0
  510. sage/rings/integer.pyx +7874 -0
  511. sage/rings/integer_ring.cp310-win_arm64.pyd +0 -0
  512. sage/rings/integer_ring.pxd +8 -0
  513. sage/rings/integer_ring.pyx +1693 -0
  514. sage/rings/laurent_series_ring.py +931 -0
  515. sage/rings/laurent_series_ring_element.cp310-win_arm64.pyd +0 -0
  516. sage/rings/laurent_series_ring_element.pxd +11 -0
  517. sage/rings/laurent_series_ring_element.pyx +1927 -0
  518. sage/rings/lazy_series.py +7815 -0
  519. sage/rings/lazy_series_ring.py +4356 -0
  520. sage/rings/localization.py +1043 -0
  521. sage/rings/morphism.cp310-win_arm64.pyd +0 -0
  522. sage/rings/morphism.pxd +39 -0
  523. sage/rings/morphism.pyx +3299 -0
  524. sage/rings/multi_power_series_ring.py +1145 -0
  525. sage/rings/multi_power_series_ring_element.py +2184 -0
  526. sage/rings/noncommutative_ideals.cp310-win_arm64.pyd +0 -0
  527. sage/rings/noncommutative_ideals.pyx +423 -0
  528. sage/rings/number_field/all__sagemath_categories.py +1 -0
  529. sage/rings/number_field/number_field_base.cp310-win_arm64.pyd +0 -0
  530. sage/rings/number_field/number_field_base.pxd +8 -0
  531. sage/rings/number_field/number_field_base.pyx +507 -0
  532. sage/rings/number_field/number_field_element_base.cp310-win_arm64.pyd +0 -0
  533. sage/rings/number_field/number_field_element_base.pxd +6 -0
  534. sage/rings/number_field/number_field_element_base.pyx +36 -0
  535. sage/rings/number_field/number_field_ideal.py +3550 -0
  536. sage/rings/padics/all__sagemath_categories.py +4 -0
  537. sage/rings/padics/local_generic.py +1670 -0
  538. sage/rings/padics/local_generic_element.cp310-win_arm64.pyd +0 -0
  539. sage/rings/padics/local_generic_element.pxd +5 -0
  540. sage/rings/padics/local_generic_element.pyx +1017 -0
  541. sage/rings/padics/misc.py +256 -0
  542. sage/rings/padics/padic_generic.py +1911 -0
  543. sage/rings/padics/pow_computer.cp310-win_arm64.pyd +0 -0
  544. sage/rings/padics/pow_computer.pxd +38 -0
  545. sage/rings/padics/pow_computer.pyx +671 -0
  546. sage/rings/padics/precision_error.py +24 -0
  547. sage/rings/polynomial/all__sagemath_categories.py +25 -0
  548. sage/rings/polynomial/commutative_polynomial.cp310-win_arm64.pyd +0 -0
  549. sage/rings/polynomial/commutative_polynomial.pxd +6 -0
  550. sage/rings/polynomial/commutative_polynomial.pyx +24 -0
  551. sage/rings/polynomial/cyclotomic.cp310-win_arm64.pyd +0 -0
  552. sage/rings/polynomial/cyclotomic.pyx +404 -0
  553. sage/rings/polynomial/flatten.py +711 -0
  554. sage/rings/polynomial/ideal.py +102 -0
  555. sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
  556. sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
  557. sage/rings/polynomial/laurent_polynomial.cp310-win_arm64.pyd +0 -0
  558. sage/rings/polynomial/laurent_polynomial.pxd +18 -0
  559. sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
  560. sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
  561. sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
  562. sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
  563. sage/rings/polynomial/multi_polynomial.cp310-win_arm64.pyd +0 -0
  564. sage/rings/polynomial/multi_polynomial.pxd +15 -0
  565. sage/rings/polynomial/multi_polynomial.pyx +3082 -0
  566. sage/rings/polynomial/multi_polynomial_element.py +2570 -0
  567. sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
  568. sage/rings/polynomial/multi_polynomial_ring.py +947 -0
  569. sage/rings/polynomial/multi_polynomial_ring_base.cp310-win_arm64.pyd +0 -0
  570. sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
  571. sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
  572. sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
  573. sage/rings/polynomial/polydict.cp310-win_arm64.pyd +0 -0
  574. sage/rings/polynomial/polydict.pxd +45 -0
  575. sage/rings/polynomial/polydict.pyx +2701 -0
  576. sage/rings/polynomial/polynomial_compiled.cp310-win_arm64.pyd +0 -0
  577. sage/rings/polynomial/polynomial_compiled.pxd +59 -0
  578. sage/rings/polynomial/polynomial_compiled.pyx +509 -0
  579. sage/rings/polynomial/polynomial_element.cp310-win_arm64.pyd +0 -0
  580. sage/rings/polynomial/polynomial_element.pxd +67 -0
  581. sage/rings/polynomial/polynomial_element.pyx +13255 -0
  582. sage/rings/polynomial/polynomial_element_generic.py +1637 -0
  583. sage/rings/polynomial/polynomial_fateman.py +97 -0
  584. sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
  585. sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
  586. sage/rings/polynomial/polynomial_ring.py +3784 -0
  587. sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
  588. sage/rings/polynomial/polynomial_ring_homomorphism.cp310-win_arm64.pyd +0 -0
  589. sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
  590. sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
  591. sage/rings/polynomial/polynomial_singular_interface.py +549 -0
  592. sage/rings/polynomial/symmetric_ideal.py +989 -0
  593. sage/rings/polynomial/symmetric_reduction.cp310-win_arm64.pyd +0 -0
  594. sage/rings/polynomial/symmetric_reduction.pxd +8 -0
  595. sage/rings/polynomial/symmetric_reduction.pyx +669 -0
  596. sage/rings/polynomial/term_order.py +2279 -0
  597. sage/rings/polynomial/toy_buchberger.py +449 -0
  598. sage/rings/polynomial/toy_d_basis.py +387 -0
  599. sage/rings/polynomial/toy_variety.py +362 -0
  600. sage/rings/power_series_mpoly.cp310-win_arm64.pyd +0 -0
  601. sage/rings/power_series_mpoly.pxd +9 -0
  602. sage/rings/power_series_mpoly.pyx +161 -0
  603. sage/rings/power_series_poly.cp310-win_arm64.pyd +0 -0
  604. sage/rings/power_series_poly.pxd +10 -0
  605. sage/rings/power_series_poly.pyx +1317 -0
  606. sage/rings/power_series_ring.py +1441 -0
  607. sage/rings/power_series_ring_element.cp310-win_arm64.pyd +0 -0
  608. sage/rings/power_series_ring_element.pxd +12 -0
  609. sage/rings/power_series_ring_element.pyx +3028 -0
  610. sage/rings/puiseux_series_ring.py +487 -0
  611. sage/rings/puiseux_series_ring_element.cp310-win_arm64.pyd +0 -0
  612. sage/rings/puiseux_series_ring_element.pxd +7 -0
  613. sage/rings/puiseux_series_ring_element.pyx +1055 -0
  614. sage/rings/qqbar_decorators.py +167 -0
  615. sage/rings/quotient_ring.py +1598 -0
  616. sage/rings/quotient_ring_element.py +979 -0
  617. sage/rings/rational.cp310-win_arm64.pyd +0 -0
  618. sage/rings/rational.pxd +20 -0
  619. sage/rings/rational.pyx +4284 -0
  620. sage/rings/rational_field.py +1730 -0
  621. sage/rings/real_double.cp310-win_arm64.pyd +0 -0
  622. sage/rings/real_double.pxd +16 -0
  623. sage/rings/real_double.pyx +2218 -0
  624. sage/rings/real_lazy.cp310-win_arm64.pyd +0 -0
  625. sage/rings/real_lazy.pxd +30 -0
  626. sage/rings/real_lazy.pyx +1773 -0
  627. sage/rings/ring.cp310-win_arm64.pyd +0 -0
  628. sage/rings/ring.pxd +30 -0
  629. sage/rings/ring.pyx +850 -0
  630. sage/rings/semirings/all.py +3 -0
  631. sage/rings/semirings/non_negative_integer_semiring.py +107 -0
  632. sage/rings/semirings/tropical_mpolynomial.py +972 -0
  633. sage/rings/semirings/tropical_polynomial.py +997 -0
  634. sage/rings/semirings/tropical_semiring.cp310-win_arm64.pyd +0 -0
  635. sage/rings/semirings/tropical_semiring.pyx +676 -0
  636. sage/rings/semirings/tropical_variety.py +1701 -0
  637. sage/rings/sum_of_squares.cp310-win_arm64.pyd +0 -0
  638. sage/rings/sum_of_squares.pxd +3 -0
  639. sage/rings/sum_of_squares.pyx +336 -0
  640. sage/rings/tests.py +504 -0
  641. sage/schemes/affine/affine_homset.py +508 -0
  642. sage/schemes/affine/affine_morphism.py +1574 -0
  643. sage/schemes/affine/affine_point.py +460 -0
  644. sage/schemes/affine/affine_rational_point.py +308 -0
  645. sage/schemes/affine/affine_space.py +1264 -0
  646. sage/schemes/affine/affine_subscheme.py +592 -0
  647. sage/schemes/affine/all.py +25 -0
  648. sage/schemes/all__sagemath_categories.py +5 -0
  649. sage/schemes/generic/algebraic_scheme.py +2092 -0
  650. sage/schemes/generic/all.py +5 -0
  651. sage/schemes/generic/ambient_space.py +400 -0
  652. sage/schemes/generic/divisor.py +465 -0
  653. sage/schemes/generic/divisor_group.py +313 -0
  654. sage/schemes/generic/glue.py +84 -0
  655. sage/schemes/generic/homset.py +820 -0
  656. sage/schemes/generic/hypersurface.py +234 -0
  657. sage/schemes/generic/morphism.py +2107 -0
  658. sage/schemes/generic/point.py +237 -0
  659. sage/schemes/generic/scheme.py +1190 -0
  660. sage/schemes/generic/spec.py +199 -0
  661. sage/schemes/product_projective/all.py +6 -0
  662. sage/schemes/product_projective/homset.py +236 -0
  663. sage/schemes/product_projective/morphism.py +517 -0
  664. sage/schemes/product_projective/point.py +568 -0
  665. sage/schemes/product_projective/rational_point.py +550 -0
  666. sage/schemes/product_projective/space.py +1301 -0
  667. sage/schemes/product_projective/subscheme.py +466 -0
  668. sage/schemes/projective/all.py +24 -0
  669. sage/schemes/projective/proj_bdd_height.py +453 -0
  670. sage/schemes/projective/projective_homset.py +718 -0
  671. sage/schemes/projective/projective_morphism.py +2792 -0
  672. sage/schemes/projective/projective_point.py +1484 -0
  673. sage/schemes/projective/projective_rational_point.py +569 -0
  674. sage/schemes/projective/projective_space.py +2571 -0
  675. sage/schemes/projective/projective_subscheme.py +1574 -0
  676. sage/sets/all.py +17 -0
  677. sage/sets/cartesian_product.py +376 -0
  678. sage/sets/condition_set.py +525 -0
  679. sage/sets/disjoint_set.cp310-win_arm64.pyd +0 -0
  680. sage/sets/disjoint_set.pxd +36 -0
  681. sage/sets/disjoint_set.pyx +998 -0
  682. sage/sets/disjoint_union_enumerated_sets.py +625 -0
  683. sage/sets/family.cp310-win_arm64.pyd +0 -0
  684. sage/sets/family.pxd +12 -0
  685. sage/sets/family.pyx +1556 -0
  686. sage/sets/finite_enumerated_set.py +406 -0
  687. sage/sets/finite_set_map_cy.cp310-win_arm64.pyd +0 -0
  688. sage/sets/finite_set_map_cy.pxd +34 -0
  689. sage/sets/finite_set_map_cy.pyx +708 -0
  690. sage/sets/finite_set_maps.py +591 -0
  691. sage/sets/image_set.py +448 -0
  692. sage/sets/integer_range.py +829 -0
  693. sage/sets/non_negative_integers.py +241 -0
  694. sage/sets/positive_integers.py +93 -0
  695. sage/sets/primes.py +188 -0
  696. sage/sets/real_set.py +2760 -0
  697. sage/sets/recursively_enumerated_set.cp310-win_arm64.pyd +0 -0
  698. sage/sets/recursively_enumerated_set.pxd +31 -0
  699. sage/sets/recursively_enumerated_set.pyx +2088 -0
  700. sage/sets/set.py +2083 -0
  701. sage/sets/set_from_iterator.py +1021 -0
  702. sage/sets/totally_ordered_finite_set.py +329 -0
  703. sage/symbolic/all__sagemath_categories.py +1 -0
  704. sage/symbolic/function.cp310-win_arm64.pyd +0 -0
  705. sage/symbolic/function.pxd +29 -0
  706. sage/symbolic/function.pyx +1488 -0
  707. sage/symbolic/symbols.py +56 -0
  708. sage/tests/all__sagemath_categories.py +1 -0
  709. sage/tests/cython.cp310-win_arm64.pyd +0 -0
  710. sage/tests/cython.pyx +37 -0
  711. sage/tests/stl_vector.cp310-win_arm64.pyd +0 -0
  712. sage/tests/stl_vector.pyx +171 -0
  713. sage/typeset/all.py +6 -0
  714. sage/typeset/ascii_art.py +295 -0
  715. sage/typeset/character_art.py +789 -0
  716. sage/typeset/character_art_factory.py +572 -0
  717. sage/typeset/symbols.py +334 -0
  718. sage/typeset/unicode_art.py +183 -0
  719. sage/typeset/unicode_characters.py +101 -0
@@ -0,0 +1,2088 @@
1
+ # sage_setup: distribution = sagemath-categories
2
+ r"""
3
+ Recursively Enumerated Sets
4
+
5
+ A set `S` is called recursively enumerable if there is an algorithm that
6
+ enumerates the members of `S`. We consider here the recursively enumerated
7
+ sets that are described by some ``seeds`` and a successor function
8
+ ``successors``. The successor function may have some structure (symmetric,
9
+ graded, forest) or not. The elements of a set having a symmetric, graded or
10
+ forest structure can be enumerated uniquely without keeping all of them in
11
+ memory. Many kinds of iterators are provided in this module: depth first
12
+ search, breadth first search and elements of given depth.
13
+
14
+ See :wikipedia:`Recursively_enumerable_set`.
15
+
16
+ See the documentation of :func:`RecursivelyEnumeratedSet` below for the
17
+ description of the inputs.
18
+
19
+ AUTHORS:
20
+
21
+ - Sébastien Labbé, April 2014, at Sage Days 57, Cernay-la-ville
22
+
23
+ EXAMPLES:
24
+
25
+ .. RUBRIC:: No hypothesis on the structure
26
+
27
+ What we mean by "no hypothesis" is that the set is not known
28
+ to be a forest, symmetric, or graded. However, it may have other
29
+ structure, such as not containing an oriented cycle, that does not
30
+ help with the enumeration.
31
+
32
+ In this example, the seed is 0 and the successor function is either ``+2``
33
+ or ``+3``. This is the set of nonnegative linear combinations of 2 and 3::
34
+
35
+ sage: succ = lambda a:[a+2,a+3]
36
+ sage: C = RecursivelyEnumeratedSet([0], succ)
37
+ sage: C
38
+ A recursively enumerated set (breadth first search)
39
+
40
+ Breadth first search::
41
+
42
+ sage: it = C.breadth_first_search_iterator()
43
+ sage: [next(it) for _ in range(10)]
44
+ [0, 2, 3, 4, 5, 6, 7, 8, 9, 10]
45
+
46
+ Depth first search::
47
+
48
+ sage: it = C.depth_first_search_iterator()
49
+ sage: [next(it) for _ in range(10)]
50
+ [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
51
+
52
+ .. RUBRIC:: Symmetric structure
53
+
54
+ The origin ``(0, 0)`` as seed and the upper, lower, left and right lattice
55
+ point as successor function. This function is symmetric since `p` is a
56
+ successor of `q` if and only if `q` is a successor or `p`::
57
+
58
+ sage: succ = lambda a: [(a[0]-1,a[1]), (a[0],a[1]-1), (a[0]+1,a[1]), (a[0],a[1]+1)]
59
+ sage: seeds = [(0,0)]
60
+ sage: C = RecursivelyEnumeratedSet(seeds, succ, structure='symmetric', enumeration='depth')
61
+ sage: C
62
+ A recursively enumerated set with a symmetric structure (depth first search)
63
+
64
+ In this case, depth first search is the default enumeration for iteration::
65
+
66
+ sage: it_depth = iter(C)
67
+ sage: [next(it_depth) for _ in range(10)]
68
+ [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 9)]
69
+
70
+ Breadth first search::
71
+
72
+ sage: it_breadth = C.breadth_first_search_iterator()
73
+ sage: [next(it_breadth) for _ in range(13)]
74
+ [(0, 0),
75
+ (-1, 0), (0, -1), (1, 0), (0, 1),
76
+ (-2, 0), (-1, -1), (-1, 1), (0, -2), (1, -1), (2, 0), (1, 1), (0, 2)]
77
+
78
+ Levels (elements of given depth)::
79
+
80
+ sage: sorted(C.graded_component(0))
81
+ [(0, 0)]
82
+ sage: sorted(C.graded_component(1))
83
+ [(-1, 0), (0, -1), (0, 1), (1, 0)]
84
+ sage: sorted(C.graded_component(2))
85
+ [(-2, 0), (-1, -1), (-1, 1), (0, -2), (0, 2), (1, -1), (1, 1), (2, 0)]
86
+
87
+ .. RUBRIC:: Graded structure
88
+
89
+ Identity permutation as seed and ``permutohedron_succ`` as successor
90
+ function::
91
+
92
+ sage: succ = attrcall("permutohedron_succ")
93
+ sage: seed = [Permutation([1..5])]
94
+ sage: R = RecursivelyEnumeratedSet(seed, succ, structure='graded')
95
+ sage: R
96
+ A recursively enumerated set with a graded structure (breadth first search)
97
+
98
+ Depth first search iterator::
99
+
100
+ sage: it_depth = R.depth_first_search_iterator()
101
+ sage: [next(it_depth) for _ in range(5)]
102
+ [[1, 2, 3, 4, 5],
103
+ [1, 2, 3, 5, 4],
104
+ [1, 2, 5, 3, 4],
105
+ [1, 2, 5, 4, 3],
106
+ [1, 5, 2, 4, 3]]
107
+
108
+ Breadth first search iterator::
109
+
110
+ sage: it_breadth = R.breadth_first_search_iterator()
111
+ sage: [next(it_breadth) for _ in range(5)]
112
+ [[1, 2, 3, 4, 5],
113
+ [2, 1, 3, 4, 5],
114
+ [1, 3, 2, 4, 5],
115
+ [1, 2, 4, 3, 5],
116
+ [1, 2, 3, 5, 4]]
117
+
118
+ Elements of given depth iterator::
119
+
120
+ sage: sorted(R.elements_of_depth_iterator(9))
121
+ [[4, 5, 3, 2, 1], [5, 3, 4, 2, 1], [5, 4, 2, 3, 1], [5, 4, 3, 1, 2]]
122
+ sage: list(R.elements_of_depth_iterator(10))
123
+ [[5, 4, 3, 2, 1]]
124
+
125
+ Graded components (set of elements of the same depth)::
126
+
127
+ sage: # needs sage.combinat
128
+ sage: sorted(R.graded_component(0))
129
+ [[1, 2, 3, 4, 5]]
130
+ sage: sorted(R.graded_component(1))
131
+ [[1, 2, 3, 5, 4], [1, 2, 4, 3, 5], [1, 3, 2, 4, 5], [2, 1, 3, 4, 5]]
132
+ sage: sorted(R.graded_component(9))
133
+ [[4, 5, 3, 2, 1], [5, 3, 4, 2, 1], [5, 4, 2, 3, 1], [5, 4, 3, 1, 2]]
134
+ sage: sorted(R.graded_component(10))
135
+ [[5, 4, 3, 2, 1]]
136
+
137
+ .. RUBRIC:: Forest structure (Example 1)
138
+
139
+ The set of words over the alphabet `\{a,b\}` can be generated from the
140
+ empty word by appending the letter `a` or `b` as a successor function. This set
141
+ has a forest structure::
142
+
143
+ sage: seeds = ['']
144
+ sage: succ = lambda w: [w+'a', w+'b']
145
+ sage: C = RecursivelyEnumeratedSet(seeds, succ, structure='forest')
146
+ sage: C
147
+ An enumerated set with a forest structure
148
+
149
+ Depth first search iterator::
150
+
151
+ sage: it = C.depth_first_search_iterator()
152
+ sage: [next(it) for _ in range(6)]
153
+ ['', 'a', 'aa', 'aaa', 'aaaa', 'aaaaa']
154
+
155
+ Breadth first search iterator::
156
+
157
+ sage: it = C.breadth_first_search_iterator()
158
+ sage: [next(it) for _ in range(6)]
159
+ ['', 'a', 'b', 'aa', 'ab', 'ba']
160
+
161
+ This example was provided by Florent Hivert.
162
+
163
+ How to define a set using those classes?
164
+
165
+ Only two things are necessary to define a set using a
166
+ :class:`RecursivelyEnumeratedSet` object (the other
167
+ classes being very similar):
168
+
169
+ .. MATH::
170
+
171
+ \begin{array}{ccc}
172
+ & \emptyset \\
173
+ \hfil\swarrow & \downarrow & \searrow\hfil\\
174
+ a & b & c \\
175
+ \begin{array}{ccc}
176
+ \swarrow & \downarrow & \searrow \\
177
+ aa & ab & ac \\
178
+ \end{array} &
179
+ \begin{array}{ccc}
180
+ \swarrow & \downarrow & \searrow \\
181
+ ba & bb & bc \\
182
+ \end{array} &
183
+ \begin{array}{ccc}
184
+ \swarrow & \downarrow & \searrow \\
185
+ ca & cb & cc \\
186
+ \end{array}
187
+ \end{array}
188
+
189
+ For the previous example, the two necessary pieces of information are:
190
+
191
+ - the initial element ``""``;
192
+
193
+ - the function::
194
+
195
+ lambda x: [x + letter for letter in ['a', 'b', 'c']
196
+
197
+ This would actually describe an **infinite** set, as such rules describe
198
+ "all words" on 3 letters. Hence, it is a good idea to replace the function by::
199
+
200
+ lambda x: [x + letter for letter in ['a', 'b', 'c']] if len(x) < 2 else []
201
+
202
+ or even::
203
+
204
+ sage: def children(x):
205
+ ....: if len(x) < 2:
206
+ ....: for letter in ['a', 'b', 'c']:
207
+ ....: yield x+letter
208
+
209
+ We can then create the :class:`RecursivelyEnumeratedSet` object with either::
210
+
211
+ sage: S = RecursivelyEnumeratedSet([''],
212
+ ....: lambda x: [x + letter for letter in ['a', 'b', 'c']]
213
+ ....: if len(x) < 2 else [],
214
+ ....: structure='forest', enumeration='depth',
215
+ ....: category=FiniteEnumeratedSets())
216
+ sage: S.list()
217
+ ['', 'a', 'aa', 'ab', 'ac', 'b', 'ba', 'bb', 'bc', 'c', 'ca', 'cb', 'cc']
218
+
219
+ or::
220
+
221
+ sage: S = RecursivelyEnumeratedSet([''], children,
222
+ ....: structure='forest', enumeration='depth',
223
+ ....: category=FiniteEnumeratedSets())
224
+ sage: S.list()
225
+ ['', 'a', 'aa', 'ab', 'ac', 'b', 'ba', 'bb', 'bc', 'c', 'ca', 'cb', 'cc']
226
+
227
+ .. RUBRIC:: Forest structure (Example 2)
228
+
229
+ This example was provided by Florent Hivert.
230
+
231
+ Here is a little more involved example. We want to iterate through all
232
+ permutations of a given set `S`. One solution is to take elements of `S` one
233
+ by one and insert them at every position. So a node of the generating tree
234
+ contains two pieces of information:
235
+
236
+ - the list ``lst`` of already inserted element;
237
+ - the set ``st`` of the yet to be inserted element.
238
+
239
+ We want to generate a permutation only if ``st`` is empty (leaves on the
240
+ tree). Also suppose for the sake of the example, that instead of list we want
241
+ to generate tuples. This selection of some nodes and final mapping of a
242
+ function to the element is done by the ``post_process = f`` argument. The
243
+ convention is that the generated elements are the ``s := f(n)``, except when
244
+ ``s`` not ``None`` when no element is generated at all. Here is the code::
245
+
246
+ sage: def children(node):
247
+ ....: (lst, st) = node
248
+ ....: st = set(st) # make a copy
249
+ ....: if st:
250
+ ....: el = st.pop()
251
+ ....: for i in range(len(lst) + 1):
252
+ ....: yield (lst[0:i] + [el] + lst[i:], st)
253
+ sage: list(children(([1,2], {3,7,9})))
254
+ [([9, 1, 2], {3, 7}), ([1, 9, 2], {3, 7}), ([1, 2, 9], {3, 7})]
255
+ sage: def post_process(node):
256
+ ....: (l, s) = node
257
+ ....: return tuple(l) if not s else None
258
+ sage: S = RecursivelyEnumeratedSet( [([], {1,3,6,8})],
259
+ ....: children, post_process=post_process,
260
+ ....: structure='forest', enumeration='depth',
261
+ ....: category=FiniteEnumeratedSets())
262
+ sage: S.list()
263
+ [(6, 3, 1, 8), (3, 6, 1, 8), (3, 1, 6, 8), (3, 1, 8, 6), (6, 1, 3, 8),
264
+ (1, 6, 3, 8), (1, 3, 6, 8), (1, 3, 8, 6), (6, 1, 8, 3), (1, 6, 8, 3),
265
+ (1, 8, 6, 3), (1, 8, 3, 6), (6, 3, 8, 1), (3, 6, 8, 1), (3, 8, 6, 1),
266
+ (3, 8, 1, 6), (6, 8, 3, 1), (8, 6, 3, 1), (8, 3, 6, 1), (8, 3, 1, 6),
267
+ (6, 8, 1, 3), (8, 6, 1, 3), (8, 1, 6, 3), (8, 1, 3, 6)]
268
+ sage: S.cardinality()
269
+ 24
270
+ """
271
+
272
+ # ****************************************************************************
273
+ # Copyright (C) 2014 Sebastien Labbe <slabqc at gmail.com>
274
+ #
275
+ # This program is free software: you can redistribute it and/or modify
276
+ # it under the terms of the GNU General Public License as published by
277
+ # the Free Software Foundation, either version 2 of the License, or
278
+ # (at your option) any later version.
279
+ # https://www.gnu.org/licenses/
280
+ # ****************************************************************************
281
+
282
+ from sage.structure.parent cimport Parent
283
+ from sage.categories.enumerated_sets import EnumeratedSets
284
+ from sage.misc.abstract_method import abstract_method
285
+ from sage.misc.prandom import randint
286
+ from collections import deque
287
+
288
+
289
+ def RecursivelyEnumeratedSet(seeds, successors, structure=None,
290
+ enumeration=None, max_depth=float("inf"),
291
+ post_process=None,
292
+ facade=None, category=None):
293
+ r"""
294
+ Return a recursively enumerated set.
295
+
296
+ A set `S` is called recursively enumerable if there is an algorithm that
297
+ enumerates the members of `S`. We consider here the recursively
298
+ enumerated sets that are described by some ``seeds`` and a successor
299
+ function ``successors``.
300
+
301
+ Let `U` be a set and ``successors`` `:U \to 2^U` be a successor function
302
+ associating to each element of `U` a subset of `U`. Let ``seeds`` be a
303
+ subset of `U`. Let `S\subseteq U` be the set of elements of `U` that
304
+ can be reached from a seed by applying recursively the ``successors``
305
+ function. This class provides different kinds of iterators (breadth first,
306
+ depth first, elements of given depth, etc.) for the elements of `S`.
307
+
308
+ See :wikipedia:`Recursively_enumerable_set`.
309
+
310
+ INPUT:
311
+
312
+ - ``seeds`` -- list (or iterable) of hashable objects
313
+ - ``successors`` -- function (or callable) returning a list (or iterable) of
314
+ hashable objects
315
+ - ``structure`` -- string (default: ``None``); structure of the
316
+ set, possible values are:
317
+
318
+ - ``None`` -- nothing is known about the structure of the set
319
+ - ``'forest'`` -- if the ``successors`` function generates a *forest*, that
320
+ is, each element can be reached uniquely from a seed
321
+ - ``'graded'`` -- if the ``successors`` function is *graded*, that is, all
322
+ paths from a seed to a given element have equal length
323
+ - ``'symmetric'`` -- if the relation is *symmetric*, that is,
324
+ ``y in successors(x)`` if and only if ``x in successors(y)``
325
+
326
+ - ``enumeration`` -- ``'depth'``, ``'breadth'``, ``'naive'`` or ``None``
327
+ (default: ``None``); the default enumeration for the
328
+ ``__iter__`` function
329
+ - ``max_depth`` -- integer (default: ``float("inf")``); limit
330
+ the search to a certain depth, currently works only for breadth first
331
+ search
332
+ - ``post_process`` -- (default: ``None``) for forest only
333
+ - ``facade`` -- (default: ``None``)
334
+ - ``category`` -- (default: ``None``)
335
+
336
+ EXAMPLES:
337
+
338
+ A recursive set with no other information::
339
+
340
+ sage: f = lambda a: [a+3, a+5]
341
+ sage: C = RecursivelyEnumeratedSet([0], f)
342
+ sage: C
343
+ A recursively enumerated set (breadth first search)
344
+ sage: it = iter(C)
345
+ sage: [next(it) for _ in range(10)]
346
+ [0, 3, 5, 6, 8, 10, 9, 11, 13, 15]
347
+
348
+ A recursive set with a forest structure::
349
+
350
+ sage: f = lambda a: [2*a,2*a+1]
351
+ sage: C = RecursivelyEnumeratedSet([1], f, structure='forest'); C
352
+ An enumerated set with a forest structure
353
+ sage: it = C.depth_first_search_iterator()
354
+ sage: [next(it) for _ in range(7)]
355
+ [1, 2, 4, 8, 16, 32, 64]
356
+ sage: it = C.breadth_first_search_iterator()
357
+ sage: [next(it) for _ in range(7)]
358
+ [1, 2, 3, 4, 5, 6, 7]
359
+
360
+ A recursive set given by a symmetric relation::
361
+
362
+ sage: f = lambda a: [a-1,a+1]
363
+ sage: C = RecursivelyEnumeratedSet([10, 15], f, structure='symmetric')
364
+ sage: C
365
+ A recursively enumerated set with a symmetric structure (breadth first search)
366
+ sage: it = iter(C)
367
+ sage: [next(it) for _ in range(7)]
368
+ [10, 15, 9, 11, 14, 16, 8]
369
+
370
+ A recursive set given by a graded relation::
371
+
372
+ sage: # needs sage.symbolic
373
+ sage: def f(a):
374
+ ....: return [a + 1, a + I]
375
+ sage: C = RecursivelyEnumeratedSet([0], f, structure='graded'); C
376
+ A recursively enumerated set with a graded structure (breadth first search)
377
+ sage: it = iter(C)
378
+ sage: [next(it) for _ in range(7)]
379
+ [0, 1, I, 2, I + 1, 2*I, 3]
380
+
381
+ .. WARNING::
382
+
383
+ If you do not set a good structure, you might obtain bad results,
384
+ like elements generated twice::
385
+
386
+ sage: f = lambda a: [a-1,a+1]
387
+ sage: C = RecursivelyEnumeratedSet([0], f, structure='graded')
388
+ sage: it = iter(C)
389
+ sage: [next(it) for _ in range(7)]
390
+ [0, -1, 1, -2, 0, 2, -3]
391
+
392
+ TESTS:
393
+
394
+ The successors method is an attribute::
395
+
396
+ sage: R = RecursivelyEnumeratedSet([1], lambda x: [x+1, x-1])
397
+ sage: R.successors(4)
398
+ [5, 3]
399
+
400
+ ::
401
+
402
+ sage: C = RecursivelyEnumeratedSet((1, 2, 3), factor)
403
+ sage: C.successors
404
+ <function factor at ...>
405
+ sage: C._seeds
406
+ (1, 2, 3)
407
+ """
408
+ if structure is None:
409
+ if enumeration is None:
410
+ enumeration = 'breadth'
411
+ return RecursivelyEnumeratedSet_generic(seeds, successors,
412
+ enumeration, max_depth, facade=facade, category=category)
413
+ if structure == 'symmetric':
414
+ if enumeration is None:
415
+ enumeration = 'breadth'
416
+ return RecursivelyEnumeratedSet_symmetric(seeds, successors,
417
+ enumeration, max_depth, facade=facade, category=category)
418
+ if structure == 'forest':
419
+ if enumeration is None:
420
+ enumeration = 'depth'
421
+ return RecursivelyEnumeratedSet_forest(roots=seeds, children=successors,
422
+ algorithm=enumeration, post_process=post_process,
423
+ facade=facade, category=category)
424
+ if structure == 'graded':
425
+ if enumeration is None:
426
+ enumeration = 'breadth'
427
+ return RecursivelyEnumeratedSet_graded(seeds, successors, enumeration,
428
+ max_depth, facade=facade, category=category)
429
+
430
+ raise ValueError("Unknown value for structure (={})".format(structure))
431
+
432
+
433
+ cdef class RecursivelyEnumeratedSet_generic(Parent):
434
+ r"""
435
+ A generic recursively enumerated set.
436
+
437
+ For more information, see :func:`RecursivelyEnumeratedSet`.
438
+
439
+ EXAMPLES::
440
+
441
+ sage: f = lambda a:[a+1]
442
+
443
+ Different structure for the sets::
444
+
445
+ sage: RecursivelyEnumeratedSet([0], f, structure=None)
446
+ A recursively enumerated set (breadth first search)
447
+ sage: RecursivelyEnumeratedSet([0], f, structure='graded')
448
+ A recursively enumerated set with a graded structure (breadth first search)
449
+ sage: RecursivelyEnumeratedSet([0], f, structure='symmetric')
450
+ A recursively enumerated set with a symmetric structure (breadth first search)
451
+ sage: RecursivelyEnumeratedSet([0], f, structure='forest')
452
+ An enumerated set with a forest structure
453
+
454
+ Different default enumeration algorithms::
455
+
456
+ sage: RecursivelyEnumeratedSet([0], f, enumeration='breadth')
457
+ A recursively enumerated set (breadth first search)
458
+ sage: RecursivelyEnumeratedSet([0], f, enumeration='naive')
459
+ A recursively enumerated set (naive search)
460
+ sage: RecursivelyEnumeratedSet([0], f, enumeration='depth')
461
+ A recursively enumerated set (depth first search)
462
+ """
463
+ def __init__(self, seeds, successors,
464
+ enumeration='depth', max_depth=float("inf"),
465
+ post_process=None, facade=None, category=None):
466
+ r"""
467
+ TESTS::
468
+
469
+ sage: f = lambda a: [a+3, a+5]
470
+ sage: C = RecursivelyEnumeratedSet([0], f)
471
+ sage: C
472
+ A recursively enumerated set (breadth first search)
473
+ """
474
+ assert enumeration in ['naive', 'depth', 'breadth'], \
475
+ "unknown enumeration(={})".format(enumeration)
476
+
477
+ self._seeds = seeds
478
+ self.successors = successors
479
+ self._enumeration = enumeration
480
+ self._max_depth = max_depth
481
+
482
+ if post_process is not None:
483
+ self.post_process = post_process
484
+ self._graded_component = None
485
+ Parent.__init__(self, facade=facade,
486
+ category=EnumeratedSets().or_subcategory(category))
487
+
488
+ def __reduce__(self):
489
+ r"""
490
+ Return a tuple of three elements:
491
+
492
+ - The function :func:`RecursivelyEnumeratedSet`
493
+ - Arguments for the function :func:`RecursivelyEnumeratedSet`
494
+ - The actual state of ``self``.
495
+
496
+ EXAMPLES::
497
+
498
+ sage: C = RecursivelyEnumeratedSet((1, 2, 3), factor)
499
+ sage: loads(dumps(C))
500
+ A recursively enumerated set (breadth first search)
501
+ """
502
+ try:
503
+ pp = self.post_process
504
+ except AttributeError:
505
+ pp = None
506
+
507
+ classname = self.__class__.__name__
508
+ if classname.startswith('RecursivelyEnumeratedSet_graded'):
509
+ struct = 'graded'
510
+ elif classname.startswith('RecursivelyEnumeratedSet_symmetric'):
511
+ struct = 'symmetric'
512
+ elif classname.startswith('RecursivelyEnumeratedSet_forest'):
513
+ struct = 'forest'
514
+ elif classname.startswith('RecursivelyEnumeratedSet_generic'):
515
+ struct = None
516
+
517
+ args = (self._seeds, self.successors, struct,
518
+ self._enumeration, self._max_depth, pp)
519
+ return (RecursivelyEnumeratedSet, args, self.__getstate__())
520
+
521
+ def __getstate__(self):
522
+ r"""
523
+ Get the current state of ``self``. Used in pickling.
524
+
525
+ EXAMPLES::
526
+
527
+ sage: C = RecursivelyEnumeratedSet((1, 2, 3), factor)
528
+ sage: C.__getstate__()
529
+ (None,)
530
+ """
531
+ return (self._graded_component, )
532
+
533
+ def __setstate__(self, l):
534
+ r"""
535
+ Set the state of ``self``. Used in pickling.
536
+
537
+ INPUT:
538
+
539
+ - ``l`` -- the state in the pickle
540
+
541
+ EXAMPLES::
542
+
543
+ sage: C = RecursivelyEnumeratedSet((1, 2, 3), factor)
544
+ sage: C.__setstate__(C.__getstate__())
545
+ """
546
+ self._graded_component = l[0]
547
+ # Since github issue #21312, the graded component iterator is not used
548
+ # anymore but maybe some previously pickled object still have it
549
+ # self._graded_component_it = l[1]
550
+
551
+ def __len__(self):
552
+ """
553
+ Disable ``__len__()`` from :class:`Parent` :issue:`12955`.
554
+
555
+ Because Python assumes ``__len__()`` is fast and we cannot
556
+ have a fast default implementation.
557
+
558
+ EXAMPLES::
559
+
560
+ sage: f = lambda a: [a+3, a+5]
561
+ sage: C = RecursivelyEnumeratedSet([0], f)
562
+ sage: len(C)
563
+ Traceback (most recent call last):
564
+ ...
565
+ TypeError: cannot compute length of A recursively enumerated set (breadth first search)
566
+ """
567
+ raise TypeError(f"cannot compute length of {self}")
568
+
569
+ def __iter__(self):
570
+ r"""
571
+ Iterate on the elements of ``self``.
572
+
573
+ The enumeration is done depth first or breadth first depending on
574
+ the value of ``self._enumeration``.
575
+
576
+ EXAMPLES::
577
+
578
+ sage: f = lambda a: [a+3, a+5]
579
+ sage: it_naive = iter(RecursivelyEnumeratedSet([0], f, enumeration='naive'))
580
+ sage: it_depth = iter(RecursivelyEnumeratedSet([0], f, enumeration='depth'))
581
+ sage: it_breadth = iter(RecursivelyEnumeratedSet([0], f, enumeration='breadth'))
582
+ sage: sorted([next(it_naive) for _ in range(10)])
583
+ [0, 3, 5, 6, 8, 9, 10, 11, 12, 13]
584
+ sage: [next(it_depth) for _ in range(10)]
585
+ [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
586
+ sage: [next(it_breadth) for _ in range(10)]
587
+ [0, 3, 5, 6, 8, 10, 9, 11, 13, 15]
588
+ """
589
+ if self._enumeration == 'naive':
590
+ return self.naive_search_iterator()
591
+ elif self._enumeration == 'breadth':
592
+ return self.breadth_first_search_iterator(max_depth=self._max_depth)
593
+ elif self._enumeration == 'depth':
594
+ return self.depth_first_search_iterator()
595
+
596
+ raise ValueError("unknown value for enumeration(={})".format(self._enumeration))
597
+
598
+ def __contains__(self, elt):
599
+ r"""
600
+ Return ``True`` if ``elt`` is in ``self``.
601
+
602
+ .. WARNING::
603
+
604
+ This is achieved by iterating through the elements using the
605
+ default enumeration until ``elt`` is found. In particular, this
606
+ method will never stop when ``elt`` is not in ``self`` and
607
+ ``self`` is infinite or when ``elt`` is in ``self`` but the
608
+ enumeration is not appropriate.
609
+
610
+ EXAMPLES::
611
+
612
+ sage: f = lambda a:[a+3,a+5]
613
+ sage: R = RecursivelyEnumeratedSet([0], f)
614
+ sage: R
615
+ A recursively enumerated set (breadth first search)
616
+ sage: 8 in R
617
+ True
618
+
619
+ ::
620
+
621
+ sage: R = RecursivelyEnumeratedSet([0], f, enumeration='depth')
622
+ sage: R
623
+ A recursively enumerated set (depth first search)
624
+ sage: it = iter(R)
625
+ sage: [next(it) for _ in range(6)]
626
+ [0, 5, 10, 15, 20, 25]
627
+ sage: 8 in R # (should return True) not tested: does not terminate
628
+ sage: 7 in R # (should return False) not tested: does not terminate
629
+ """
630
+ return any(node == elt for node in self)
631
+
632
+ def _repr_(self):
633
+ r"""
634
+ TESTS::
635
+
636
+ sage: f = lambda x: [x-1, x+1]
637
+ sage: RecursivelyEnumeratedSet([1], f, structure=None)
638
+ A recursively enumerated set (breadth first search)
639
+
640
+ ::
641
+
642
+ sage: RecursivelyEnumeratedSet([1], f, structure='graded')
643
+ A recursively enumerated set with a graded structure (breadth first search)
644
+
645
+ ::
646
+
647
+ sage: RecursivelyEnumeratedSet([1], f, structure='symmetric')
648
+ A recursively enumerated set with a symmetric structure (breadth first search)
649
+
650
+ When ``max_depth`` is set::
651
+
652
+ sage: RecursivelyEnumeratedSet([1], f, structure='symmetric', max_depth=4)
653
+ A recursively enumerated set with a symmetric structure (breadth
654
+ first search) with max_depth=4
655
+ """
656
+ L = ["A recursively enumerated set"]
657
+ classname = self.__class__.__name__
658
+ if classname.startswith('RecursivelyEnumeratedSet_graded'):
659
+ L.append("with a graded structure")
660
+ elif classname.startswith('RecursivelyEnumeratedSet_symmetric'):
661
+ L.append("with a symmetric structure")
662
+ elif classname.startswith('RecursivelyEnumeratedSet_forest'):
663
+ L.append("with a forest structure")
664
+
665
+ if self._enumeration in ['depth', 'breadth']:
666
+ L.append("({} first search)".format(self._enumeration))
667
+ else:
668
+ L.append("({} search)".format(self._enumeration))
669
+
670
+ if not self._max_depth == float('inf'):
671
+ L.append("with max_depth={}".format(self._max_depth))
672
+ return " ".join(L)
673
+
674
+ cpdef seeds(self):
675
+ r"""
676
+ Return an iterable over the seeds of ``self``.
677
+
678
+ EXAMPLES::
679
+
680
+ sage: R = RecursivelyEnumeratedSet([1], lambda x: [x + 1, x - 1])
681
+ sage: R.seeds()
682
+ [1]
683
+ """
684
+ return self._seeds
685
+
686
+ # using this in a .pyx file makes sage crash at startup
687
+ # @abstract_method
688
+ # def successors(self, x):
689
+ # r"""
690
+ # Return the successors of the element ``x``
691
+ #
692
+ # OUTPUT:
693
+ #
694
+ # an iterable
695
+ #
696
+ # EXAMPLES::
697
+ #
698
+ # sage: R = RecursivelyEnumeratedSet([1], lambda x: [x+1, x-1])
699
+ # sage: R.successors(4)
700
+ # [5, 3]
701
+ # """
702
+
703
+ def graded_component_iterator(self):
704
+ r"""
705
+ Iterate over the graded components of ``self``.
706
+
707
+ A graded component is a set of elements of the same depth.
708
+
709
+ It is currently implemented only for graded or symmetric structure.
710
+
711
+ OUTPUT: an iterator of sets
712
+
713
+ EXAMPLES::
714
+
715
+ sage: f = lambda a: [a+3, a+5]
716
+ sage: C = RecursivelyEnumeratedSet([0], f)
717
+ sage: it = C.graded_component_iterator() # todo: not implemented
718
+ """
719
+ raise NotImplementedError("graded_component_iterator method currently"
720
+ " implemented only for graded or symmetric structure")
721
+
722
+ cpdef graded_component(self, depth):
723
+ r"""
724
+ Return the graded component of given depth.
725
+
726
+ This method caches each lower graded component.
727
+
728
+ A graded component is a set of elements of the same depth where the
729
+ depth of an element is its minimal distance to a root.
730
+
731
+ It is currently implemented only for graded or symmetric structure.
732
+
733
+ INPUT:
734
+
735
+ - ``depth`` -- integer
736
+
737
+ OUTPUT: set
738
+
739
+ EXAMPLES::
740
+
741
+ sage: f = lambda a: [a+3, a+5]
742
+ sage: C = RecursivelyEnumeratedSet([0], f)
743
+ sage: C.graded_component(0)
744
+ Traceback (most recent call last):
745
+ ...
746
+ NotImplementedError: graded_component_iterator method currently implemented only for graded or symmetric structure
747
+ """
748
+ raise NotImplementedError("graded_component_iterator method currently"
749
+ " implemented only for graded or symmetric structure")
750
+
751
+ def elements_of_depth_iterator(self, depth):
752
+ r"""
753
+ Iterate over the elements of ``self`` of given depth.
754
+
755
+ An element of depth `n` can be obtained by applying the
756
+ successor function `n` times to a seed.
757
+
758
+ INPUT:
759
+
760
+ - ``depth`` -- integer
761
+
762
+ OUTPUT: an iterator
763
+
764
+ EXAMPLES::
765
+
766
+ sage: f = lambda a: [a-1, a+1]
767
+ sage: S = RecursivelyEnumeratedSet([5, 10], f, structure='symmetric')
768
+ sage: it = S.elements_of_depth_iterator(2)
769
+ sage: sorted(it)
770
+ [3, 7, 8, 12]
771
+ """
772
+ return iter(self.graded_component(depth))
773
+
774
+ def breadth_first_search_iterator(self, max_depth=None):
775
+ r"""
776
+ Iterate on the elements of ``self`` (breadth first).
777
+
778
+ This code remembers every element generated.
779
+
780
+ The elements are guaranteed to be enumerated in the order in which they
781
+ are first visited (left-to-right traversal).
782
+
783
+ INPUT:
784
+
785
+ - ``max_depth`` -- (default: ``self._max_depth``) specifies the
786
+ maximal depth to which elements are computed
787
+
788
+ EXAMPLES::
789
+
790
+ sage: f = lambda a: [a+3, a+5]
791
+ sage: C = RecursivelyEnumeratedSet([0], f)
792
+ sage: it = C.breadth_first_search_iterator()
793
+ sage: [next(it) for _ in range(10)]
794
+ [0, 3, 5, 6, 8, 10, 9, 11, 13, 15]
795
+ """
796
+ if max_depth is None:
797
+ max_depth = self._max_depth
798
+ current_level = self._seeds
799
+ known = set(current_level)
800
+ if max_depth >= 0:
801
+ yield from current_level
802
+ depth = 0
803
+ while current_level and depth < max_depth:
804
+ next_level = []
805
+ for x in current_level:
806
+ for y in self.successors(x):
807
+ if y is None or y in known:
808
+ continue
809
+ yield y
810
+ next_level.append(y)
811
+ known.add(y)
812
+ current_level = next_level
813
+ depth += 1
814
+
815
+ def _breadth_first_search_iterator_using_queue(self):
816
+ r"""
817
+ Iterate on the elements of ``self`` (breadth first).
818
+
819
+ This code remembers every element generated and uses python
820
+ queues. It is 3 times slower than the other one.
821
+
822
+ See :wikipedia:`Breadth-first_search`.
823
+
824
+ EXAMPLES::
825
+
826
+ sage: f = lambda a: [a+3, a+5]
827
+ sage: C = RecursivelyEnumeratedSet([0], f)
828
+ sage: it = C._breadth_first_search_iterator_using_queue()
829
+ sage: [next(it) for _ in range(10)]
830
+ [0, 3, 5, 6, 8, 10, 9, 11, 13, 15]
831
+ """
832
+ cdef set known
833
+ known = set(self._seeds)
834
+ q = deque(self._seeds)
835
+ while q:
836
+ x = q.popleft()
837
+ yield x
838
+ for y in self.successors(x):
839
+ if y is None or y in known:
840
+ continue
841
+ q.append(y)
842
+ known.add(y)
843
+
844
+ def naive_search_iterator(self):
845
+ r"""
846
+ Iterate on the elements of ``self`` (in no particular order).
847
+
848
+ This code remembers every element generated.
849
+
850
+ TESTS:
851
+
852
+ We compute all the permutations of 3::
853
+
854
+ sage: # needs sage.combinat
855
+ sage: seeds = [Permutation([1,2,3])]
856
+ sage: succ = attrcall("permutohedron_succ")
857
+ sage: R = RecursivelyEnumeratedSet(seeds, succ)
858
+ sage: sorted(R.naive_search_iterator())
859
+ [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
860
+ """
861
+ cdef set known, todo
862
+ known = set(self._seeds)
863
+ todo = known.copy()
864
+ while todo:
865
+ x = todo.pop()
866
+ yield x
867
+ for y in self.successors(x):
868
+ if y is None or y in known:
869
+ continue
870
+ todo.add(y)
871
+ known.add(y)
872
+
873
+ def depth_first_search_iterator(self):
874
+ r"""
875
+ Iterate on the elements of ``self`` (depth first).
876
+
877
+ This code remembers every element generated.
878
+
879
+ The elements are traversed right-to-left, so the last element returned
880
+ by the successor function is visited first.
881
+
882
+ See :wikipedia:`Depth-first_search`.
883
+
884
+ EXAMPLES::
885
+
886
+ sage: f = lambda a: [a+3, a+5]
887
+ sage: C = RecursivelyEnumeratedSet([0], f)
888
+ sage: it = C.depth_first_search_iterator()
889
+ sage: [next(it) for _ in range(10)]
890
+ [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
891
+ """
892
+ cdef list stack
893
+ cdef set known
894
+ stack = list(self._seeds)
895
+ known = set()
896
+ while stack:
897
+ x = stack.pop()
898
+ if x is None or x in known:
899
+ continue
900
+ yield x
901
+ known.add(x)
902
+ for y in self.successors(x):
903
+ stack.append(y)
904
+
905
+ def to_digraph(self, max_depth=None, loops=True, multiedges=True):
906
+ r"""
907
+ Return the directed graph of the recursively enumerated set.
908
+
909
+ INPUT:
910
+
911
+ - ``max_depth`` -- (default: ``self._max_depth``) specifies the
912
+ maximal depth for which outgoing edges of elements are computed
913
+ - ``loops`` -- boolean (default: ``True``); option for the digraph
914
+ - ``multiedges`` -- boolean (default: ``True``); option of the digraph
915
+
916
+ OUTPUT: a directed graph
917
+
918
+ .. WARNING::
919
+
920
+ If the set is infinite, this will loop forever unless ``max_depth``
921
+ is finite.
922
+
923
+ EXAMPLES::
924
+
925
+ sage: child = lambda i: [(i+3) % 10, (i+8) % 10]
926
+ sage: R = RecursivelyEnumeratedSet([0], child)
927
+ sage: R.to_digraph() # needs sage.graphs
928
+ Looped multi-digraph on 10 vertices
929
+
930
+ Digraph of a recursively enumerated set with a symmetric structure of
931
+ infinite cardinality using ``max_depth`` argument::
932
+
933
+ sage: succ = lambda a: [(a[0]-1,a[1]), (a[0],a[1]-1), (a[0]+1,a[1]), (a[0],a[1]+1)]
934
+ sage: seeds = [(0,0)]
935
+ sage: C = RecursivelyEnumeratedSet(seeds, succ, structure='symmetric')
936
+ sage: C.to_digraph(max_depth=3) # needs sage.graphs
937
+ Looped multi-digraph on 41 vertices
938
+
939
+ The ``max_depth`` argument can be given at the creation of the set::
940
+
941
+ sage: C = RecursivelyEnumeratedSet(seeds, succ, structure='symmetric',
942
+ ....: max_depth=2)
943
+ sage: C.to_digraph() # needs sage.graphs
944
+ Looped multi-digraph on 25 vertices
945
+
946
+ Digraph of a recursively enumerated set with a graded structure::
947
+
948
+ sage: f = lambda a: [a+1, a+I]
949
+ sage: C = RecursivelyEnumeratedSet([0], f, structure='graded')
950
+ sage: C.to_digraph(max_depth=4) # needs sage.graphs sage.symbolic
951
+ Looped multi-digraph on 21 vertices
952
+ """
953
+ successors = self.successors
954
+ it = self.breadth_first_search_iterator(max_depth=max_depth)
955
+ E = [(u, v) for u in it for v in successors(u)]
956
+ from sage.graphs.digraph import DiGraph
957
+ return DiGraph(E, format='list_of_edges', loops=loops,
958
+ multiedges=multiedges)
959
+
960
+
961
+ cdef class RecursivelyEnumeratedSet_symmetric(RecursivelyEnumeratedSet_generic):
962
+ r"""
963
+ Generic tool for constructing ideals of a symmetric relation.
964
+
965
+ INPUT:
966
+
967
+ - ``seeds`` -- list (or iterable) of hashable objects
968
+ - ``successors`` -- function (or callable) returning a list (or iterable)
969
+ - ``enumeration`` -- ``'depth'``, ``'breadth'`` or ``None`` (default: ``None``)
970
+ - ``max_depth`` -- integer (default: ``float("inf")``)
971
+
972
+ EXAMPLES::
973
+
974
+ sage: f = lambda a: [a-1,a+1]
975
+ sage: C = RecursivelyEnumeratedSet([0], f, structure='symmetric')
976
+ sage: C
977
+ A recursively enumerated set with a symmetric structure (breadth first search)
978
+ sage: it = iter(C)
979
+ sage: [next(it) for _ in range(7)]
980
+ [0, -1, 1, -2, 2, -3, 3]
981
+
982
+ TESTS:
983
+
984
+ Do not use lambda functions for saving purposes::
985
+
986
+ sage: f = lambda a: [a-1,a+1]
987
+ sage: C = RecursivelyEnumeratedSet([0], f, structure='symmetric')
988
+ sage: try:
989
+ ....: loads(dumps(C))
990
+ ....: except Exception as e:
991
+ ....: if 'PicklingError' in str(type(e).__name__):
992
+ ....: print('PicklingError Caught')
993
+ PicklingError Caught
994
+
995
+ This works in the command line but apparently not as a doctest::
996
+
997
+ sage: def f(a): return [a-1,a+1]
998
+ sage: C = RecursivelyEnumeratedSet([0], f, structure='symmetric')
999
+ sage: try:
1000
+ ....: loads(dumps(C))
1001
+ ....: except Exception as e:
1002
+ ....: if 'PicklingError' in str(type(e).__name__):
1003
+ ....: print('PicklingError Caught')
1004
+ PicklingError Caught
1005
+ """
1006
+
1007
+ def breadth_first_search_iterator(self, max_depth=None):
1008
+ r"""
1009
+ Iterate on the elements of ``self`` (breadth first).
1010
+
1011
+ This iterator makes use of the graded structure by remembering only
1012
+ the last two graded components since the structure is symmetric.
1013
+
1014
+ The elements are guaranteed to be enumerated in the order in which they
1015
+ are first visited (left-to-right traversal).
1016
+
1017
+ INPUT:
1018
+
1019
+ - ``max_depth`` -- (default: ``self._max_depth``) specifies the
1020
+ maximal depth to which elements are computed
1021
+
1022
+ EXAMPLES::
1023
+
1024
+ sage: f = lambda a: [(a[0]-1,a[1]), (a[0],a[1]-1), (a[0]+1,a[1]), (a[0],a[1]+1)]
1025
+ sage: C = RecursivelyEnumeratedSet([(0,0)], f, structure='symmetric')
1026
+ sage: s = list(C.breadth_first_search_iterator(max_depth=2)); s
1027
+ [(0, 0),
1028
+ (-1, 0), (0, -1), (1, 0), (0, 1),
1029
+ (-2, 0), (-1, -1), (-1, 1), (0, -2), (1, -1), (2, 0), (1, 1), (0, 2)]
1030
+
1031
+ This iterator is used by default for symmetric structure::
1032
+
1033
+ sage: it = iter(C)
1034
+ sage: s == [next(it) for _ in range(13)]
1035
+ True
1036
+
1037
+ TESTS:
1038
+
1039
+ Check that :issue:`28674` is fixed::
1040
+
1041
+ sage: D = RecursivelyEnumeratedSet([(0,0)], f)
1042
+ sage: s == list(D.breadth_first_search_iterator(max_depth=2))
1043
+ True
1044
+ """
1045
+ cdef list C
1046
+ cdef set set_A, set_B
1047
+ cdef int depth
1048
+ if max_depth is None:
1049
+ max_depth = self._max_depth
1050
+
1051
+ set_A = set()
1052
+ B = self._seeds
1053
+ set_B = set(B)
1054
+ if max_depth >= 0:
1055
+ yield from B
1056
+ depth = 0
1057
+ while B and depth < max_depth:
1058
+ C = list()
1059
+ set_C = set()
1060
+ for x in B:
1061
+ for y in self.successors(x):
1062
+ if y is None or y in set_C or y in set_A or y in set_B:
1063
+ continue
1064
+ yield y
1065
+ C.append(y)
1066
+ set_C.add(y)
1067
+ set_A = set_B
1068
+ set_B = set_C
1069
+ B = C
1070
+ depth += 1
1071
+
1072
+ def graded_component_iterator(self):
1073
+ r"""
1074
+ Iterate over the graded components of ``self``.
1075
+
1076
+ A graded component is a set of elements of the same depth.
1077
+
1078
+ The enumeration remembers only the last two graded components
1079
+ generated since the structure is symmetric.
1080
+
1081
+ OUTPUT: an iterator of sets
1082
+
1083
+ EXAMPLES::
1084
+
1085
+ sage: f = lambda a: [a-1, a+1]
1086
+ sage: S = RecursivelyEnumeratedSet([10], f, structure='symmetric')
1087
+ sage: it = S.graded_component_iterator()
1088
+ sage: [sorted(next(it)) for _ in range(5)]
1089
+ [[10], [9, 11], [8, 12], [7, 13], [6, 14]]
1090
+
1091
+ Starting with two generators::
1092
+
1093
+ sage: f = lambda a: [a-1, a+1]
1094
+ sage: S = RecursivelyEnumeratedSet([5, 10], f, structure='symmetric')
1095
+ sage: it = S.graded_component_iterator()
1096
+ sage: [sorted(next(it)) for _ in range(5)]
1097
+ [[5, 10], [4, 6, 9, 11], [3, 7, 8, 12], [2, 13], [1, 14]]
1098
+
1099
+ Gaussian integers::
1100
+
1101
+ sage: # needs sage.symbolic
1102
+ sage: def f(a):
1103
+ ....: return [a + 1, a + I]
1104
+ sage: S = RecursivelyEnumeratedSet([0], f, structure='symmetric')
1105
+ sage: it = S.graded_component_iterator()
1106
+ sage: [sorted(next(it)) for _ in range(7)]
1107
+ [[0],
1108
+ [I, 1],
1109
+ [2*I, I + 1, 2],
1110
+ [3*I, 2*I + 1, I + 2, 3],
1111
+ [4*I, 3*I + 1, 2*I + 2, I + 3, 4],
1112
+ [5*I, 4*I + 1, 3*I + 2, 2*I + 3, I + 4, 5],
1113
+ [6*I, 5*I + 1, 4*I + 2, 3*I + 3, 2*I + 4, I + 5, 6]]
1114
+
1115
+ TESTS:
1116
+
1117
+ Note that interrupting the computation (``KeyboardInterrupt`` for
1118
+ instance) breaks the iterator::
1119
+
1120
+ sage: # needs sage.symbolic
1121
+ sage: def f(a):
1122
+ ....: sleep(0.05r)
1123
+ ....: return [a - 1, a + 1]
1124
+ sage: C = RecursivelyEnumeratedSet([0], f, structure='symmetric')
1125
+ sage: it = C.graded_component_iterator()
1126
+ sage: next(it)
1127
+ {0}
1128
+ sage: next(it)
1129
+ {-1, 1}
1130
+ sage: from sage.doctest.util import ensure_interruptible_after
1131
+ sage: with ensure_interruptible_after(0.02): next(it)
1132
+ sage: next(it)
1133
+ Traceback (most recent call last):
1134
+ ...
1135
+ StopIteration
1136
+ """
1137
+ cdef set A, B
1138
+ A = set()
1139
+ B = set(self._seeds)
1140
+ while B:
1141
+ yield B
1142
+ A, B = B, self._get_next_graded_component(A, B)
1143
+
1144
+ cpdef graded_component(self, depth):
1145
+ r"""
1146
+ Return the graded component of given depth.
1147
+
1148
+ This method caches each lower graded component. See
1149
+ :meth:`graded_component_iterator` to generate each graded component
1150
+ without caching the previous ones.
1151
+
1152
+ A graded component is a set of elements of the same depth where the
1153
+ depth of an element is its minimal distance to a root.
1154
+
1155
+ INPUT:
1156
+
1157
+ - ``depth`` -- integer
1158
+
1159
+ OUTPUT: set
1160
+
1161
+ EXAMPLES::
1162
+
1163
+ sage: f = lambda a: [a-1,a+1]
1164
+ sage: C = RecursivelyEnumeratedSet([10, 15], f, structure='symmetric')
1165
+ sage: for i in range(5): sorted(C.graded_component(i))
1166
+ [10, 15]
1167
+ [9, 11, 14, 16]
1168
+ [8, 12, 13, 17]
1169
+ [7, 18]
1170
+ [6, 19]
1171
+
1172
+ TESTS:
1173
+
1174
+ We make sure that :issue:`21312` is fixed::
1175
+
1176
+ sage: def f(a):
1177
+ ....: sleep(0.1r)
1178
+ ....: return [a - 1, a + 1]
1179
+ sage: C = RecursivelyEnumeratedSet([0], f, structure='symmetric')
1180
+ sage: from sage.doctest.util import ensure_interruptible_after
1181
+ sage: with ensure_interruptible_after(0.45): C.graded_component(10)
1182
+ sage: C.graded_component(1)
1183
+ {-1, 1}
1184
+ sage: C.graded_component(2)
1185
+ {-2, 2}
1186
+ sage: C.graded_component(3)
1187
+ {-3, 3}
1188
+ sage: C.graded_component(4)
1189
+ {-4, 4}
1190
+ sage: C.graded_component(5)
1191
+ {-5, 5}
1192
+ """
1193
+ cdef set A, B, C
1194
+ if self._graded_component is None:
1195
+ A = set()
1196
+ B = set(self._seeds)
1197
+ C = self._get_next_graded_component(A, B)
1198
+ self._graded_component = [B, C]
1199
+ while len(self._graded_component) <= depth:
1200
+ A = self._graded_component[-2]
1201
+ B = self._graded_component[-1]
1202
+ C = self._get_next_graded_component(A, B)
1203
+ self._graded_component.append(C)
1204
+ return self._graded_component[depth]
1205
+
1206
+ cdef set _get_next_graded_component(self, set A, set B):
1207
+ r"""
1208
+ Return the set of elements of depth `n+1`.
1209
+
1210
+ INPUT:
1211
+
1212
+ - ``A`` -- set, the set of elements of depth n-1
1213
+ - ``B`` -- set, the set of elements of depth n
1214
+
1215
+ OUTPUT: ``C``; the set of elements of depth n+1
1216
+
1217
+ .. TODO::
1218
+
1219
+ Can :class:`collections.OrderedDict` help maintain the
1220
+ breadth first search enumeration for each graded component?
1221
+
1222
+ EXAMPLES::
1223
+
1224
+ sage: f = lambda a: [a-1, a+1]
1225
+ sage: S = RecursivelyEnumeratedSet([5, 10], f, structure='symmetric')
1226
+ sage: it = S.graded_component_iterator()
1227
+ sage: [sorted(next(it)) for _ in range(3)] # indirect doctest
1228
+ [[5, 10], [4, 6, 9, 11], [3, 7, 8, 12]]
1229
+ """
1230
+ cdef set C
1231
+ C = set()
1232
+ for x in B:
1233
+ for y in self.successors(x):
1234
+ if (y is None or y in A or y in B):
1235
+ continue
1236
+ C.add(y)
1237
+ return C
1238
+
1239
+
1240
+ cdef class RecursivelyEnumeratedSet_graded(RecursivelyEnumeratedSet_generic):
1241
+ r"""
1242
+ Generic tool for constructing ideals of a graded relation.
1243
+
1244
+ INPUT:
1245
+
1246
+ - ``seeds`` -- list (or iterable) of hashable objects
1247
+ - ``successors`` -- function (or callable) returning a list (or iterable)
1248
+ - ``enumeration`` -- ``'depth'``, ``'breadth'`` or ``None`` (default: ``None``)
1249
+ - ``max_depth`` -- integer (default: ``float("inf")``)
1250
+
1251
+ EXAMPLES::
1252
+
1253
+ sage: f = lambda a: [(a[0]+1,a[1]), (a[0],a[1]+1)]
1254
+ sage: C = RecursivelyEnumeratedSet([(0,0)], f, structure='graded', max_depth=3)
1255
+ sage: C
1256
+ A recursively enumerated set with a graded structure (breadth first
1257
+ search) with max_depth=3
1258
+ sage: list(C)
1259
+ [(0, 0),
1260
+ (1, 0), (0, 1),
1261
+ (2, 0), (1, 1), (0, 2),
1262
+ (3, 0), (2, 1), (1, 2), (0, 3)]
1263
+ """
1264
+ def breadth_first_search_iterator(self, max_depth=None):
1265
+ r"""
1266
+ Iterate on the elements of ``self`` (breadth first).
1267
+
1268
+ This iterator makes use of the graded structure by remembering only
1269
+ the elements of the current depth.
1270
+
1271
+ The elements are guaranteed to be enumerated in the order in which they
1272
+ are first visited (left-to-right traversal).
1273
+
1274
+ INPUT:
1275
+
1276
+ - ``max_depth`` -- (default: ``self._max_depth``) specifies the
1277
+ maximal depth to which elements are computed
1278
+
1279
+ EXAMPLES::
1280
+
1281
+ sage: f = lambda a: [(a[0]+1,a[1]), (a[0],a[1]+1)]
1282
+ sage: C = RecursivelyEnumeratedSet([(0,0)], f, structure='graded')
1283
+ sage: list(C.breadth_first_search_iterator(max_depth=3))
1284
+ [(0, 0),
1285
+ (1, 0), (0, 1),
1286
+ (2, 0), (1, 1), (0, 2),
1287
+ (3, 0), (2, 1), (1, 2), (0, 3)]
1288
+ """
1289
+ cdef list next_level
1290
+ cdef set set_next_level
1291
+ cdef int depth
1292
+ if max_depth is None:
1293
+ max_depth = self._max_depth
1294
+ current_level = self._seeds
1295
+ if max_depth >= 0:
1296
+ yield from current_level
1297
+ depth = 0
1298
+ while current_level and depth < max_depth:
1299
+ next_level = list()
1300
+ set_next_level = set()
1301
+
1302
+ for x in current_level:
1303
+ for y in self.successors(x):
1304
+ if y is None or y in set_next_level:
1305
+ continue
1306
+ yield y
1307
+ next_level.append(y)
1308
+ set_next_level.add(y)
1309
+ current_level = next_level
1310
+ depth += 1
1311
+
1312
+ def graded_component_iterator(self):
1313
+ r"""
1314
+ Iterate over the graded components of ``self``.
1315
+
1316
+ A graded component is a set of elements of the same depth.
1317
+
1318
+ The algorithm remembers only the current graded component generated
1319
+ since the structure is graded.
1320
+
1321
+ OUTPUT: an iterator of sets
1322
+
1323
+ EXAMPLES::
1324
+
1325
+ sage: f = lambda a: [(a[0]+1,a[1]), (a[0],a[1]+1)]
1326
+ sage: C = RecursivelyEnumeratedSet([(0,0)], f, structure='graded', max_depth=3)
1327
+ sage: it = C.graded_component_iterator()
1328
+ sage: for _ in range(4): sorted(next(it))
1329
+ [(0, 0)]
1330
+ [(0, 1), (1, 0)]
1331
+ [(0, 2), (1, 1), (2, 0)]
1332
+ [(0, 3), (1, 2), (2, 1), (3, 0)]
1333
+
1334
+ TESTS:
1335
+
1336
+ Make sure that :issue:`20225` is fixed::
1337
+
1338
+ sage: child = lambda k:[2*k,2*k+1] if k<8 else []
1339
+ sage: root = [0]
1340
+ sage: R = RecursivelyEnumeratedSet(root, child, structure='graded')
1341
+ sage: it = R.graded_component_iterator()
1342
+ sage: for _ in range(7): next(it)
1343
+ {0}
1344
+ {1}
1345
+ {2, 3}
1346
+ {4, 5, 6, 7}
1347
+ {8, 9, 10, 11, 12, 13, 14, 15}
1348
+ set()
1349
+ set()
1350
+ """
1351
+ cdef set B
1352
+ B = set(self._seeds)
1353
+ while True:
1354
+ yield B
1355
+ B = self._get_next_graded_component(B)
1356
+
1357
+ cpdef graded_component(self, depth):
1358
+ r"""
1359
+ Return the graded component of given depth.
1360
+
1361
+ This method caches each lower graded component. See
1362
+ :meth:`graded_component_iterator` to generate each graded component
1363
+ without caching the previous ones.
1364
+
1365
+ A graded component is a set of elements of the same depth where the
1366
+ depth of an element is its minimal distance to a root.
1367
+
1368
+ INPUT:
1369
+
1370
+ - ``depth`` -- integer
1371
+
1372
+ OUTPUT: set
1373
+
1374
+ EXAMPLES::
1375
+
1376
+ sage: # needs sage.symbolic
1377
+ sage: def f(a):
1378
+ ....: return [a + 1, a + I]
1379
+ sage: C = RecursivelyEnumeratedSet([0], f, structure='graded')
1380
+ sage: for i in range(5): sorted(C.graded_component(i))
1381
+ [0]
1382
+ [I, 1]
1383
+ [2*I, I + 1, 2]
1384
+ [3*I, 2*I + 1, I + 2, 3]
1385
+ [4*I, 3*I + 1, 2*I + 2, I + 3, 4]
1386
+
1387
+ TESTS:
1388
+
1389
+ We make sure that :issue:`21312` is fixed::
1390
+
1391
+ sage: # needs sage.symbolic
1392
+ sage: def f(a):
1393
+ ....: sleep(0.1r)
1394
+ ....: return [a + 1, a + I]
1395
+ sage: C = RecursivelyEnumeratedSet([0], f, structure='graded')
1396
+ sage: from sage.doctest.util import ensure_interruptible_after
1397
+ sage: with ensure_interruptible_after(0.45): C.graded_component(10)
1398
+ sage: C.graded_component(2)
1399
+ {2*I, I + 1, 2}
1400
+ sage: C.graded_component(3)
1401
+ {3*I, 2*I + 1, I + 2, 3}
1402
+ sage: C.graded_component(4)
1403
+ {4*I, 3*I + 1, 2*I + 2, I + 3, 4}
1404
+ """
1405
+ cdef set B, C
1406
+ if self._graded_component is None:
1407
+ B = set(self._seeds)
1408
+ self._graded_component = [B]
1409
+ while len(self._graded_component) <= depth:
1410
+ B = self._graded_component[-1]
1411
+ C = self._get_next_graded_component(B)
1412
+ self._graded_component.append(C)
1413
+ return self._graded_component[depth]
1414
+
1415
+ cdef set _get_next_graded_component(self, set B):
1416
+ r"""
1417
+ Return the set of elements of depth `n+1`.
1418
+
1419
+ INPUT:
1420
+
1421
+ - ``B`` -- set, the set of elements of depth `n`
1422
+
1423
+ OUTPUT: ``C``; the set of elements of depth `n+1`
1424
+
1425
+ .. TODO::
1426
+
1427
+ Can :class:`collections.OrderedDict` help maintain the
1428
+ breadth first search enumeration for each graded component?
1429
+
1430
+ EXAMPLES::
1431
+
1432
+ sage: f = lambda a: [(a[0]+1,a[1]), (a[0],a[1]+1)]
1433
+ sage: C = RecursivelyEnumeratedSet([(0,0)], f, structure='graded')
1434
+ sage: it = C.graded_component_iterator()
1435
+ sage: [sorted(next(it)) for _ in range(2)] # indirect doctest
1436
+ [[(0, 0)], [(0, 1), (1, 0)]]
1437
+ """
1438
+ cdef set C
1439
+ C = set()
1440
+ for x in B:
1441
+ for y in self.successors(x):
1442
+ if (y is None or y in B):
1443
+ continue
1444
+ C.add(y)
1445
+ return C
1446
+
1447
+
1448
+ def _imap_and_filter_none(function, iterable):
1449
+ r"""
1450
+ Return an iterator over the elements ``function(x)``, where ``x``
1451
+ iterates through ``iterable``, such that ``function(x)`` is not
1452
+ ``None``.
1453
+
1454
+ EXAMPLES::
1455
+
1456
+ sage: from sage.sets.recursively_enumerated_set import _imap_and_filter_none
1457
+ sage: p = _imap_and_filter_none(lambda x: x if is_prime(x) else None, range(15))
1458
+ sage: [next(p), next(p), next(p), next(p), next(p), next(p)]
1459
+ [2, 3, 5, 7, 11, 13]
1460
+ sage: p = _imap_and_filter_none(lambda x: x + x, ['a','b','c','d','e'])
1461
+ sage: [next(p), next(p), next(p), next(p), next(p)]
1462
+ ['aa', 'bb', 'cc', 'dd', 'ee']
1463
+ """
1464
+ for x in iterable:
1465
+ x = function(x)
1466
+ if x is not None:
1467
+ yield x
1468
+
1469
+
1470
+ def search_forest_iterator(roots, children, algorithm='depth'):
1471
+ r"""
1472
+ Return an iterator on the nodes of the forest having the given
1473
+ roots, and where ``children(x)`` returns the children of the node ``x``
1474
+ of the forest. Note that every node of the tree is returned,
1475
+ not simply the leaves.
1476
+
1477
+ INPUT:
1478
+
1479
+ - ``roots`` -- list (or iterable)
1480
+ - ``children`` -- a function returning a list (or iterable)
1481
+ - ``algorithm`` -- ``'depth'`` or ``'breadth'`` (default: ``'depth'``)
1482
+
1483
+ EXAMPLES:
1484
+
1485
+ We construct the prefix tree of binary sequences of length at most
1486
+ three, and enumerate its nodes::
1487
+
1488
+ sage: from sage.sets.recursively_enumerated_set import search_forest_iterator
1489
+ sage: list(search_forest_iterator([[]], lambda l: [l + [0], l + [1]]
1490
+ ....: if len(l) < 3 else []))
1491
+ [[], [0], [0, 0], [0, 0, 0], [0, 0, 1], [0, 1], [0, 1, 0],
1492
+ [0, 1, 1], [1], [1, 0], [1, 0, 0], [1, 0, 1], [1, 1], [1, 1, 0], [1, 1, 1]]
1493
+
1494
+ By default, the nodes are iterated through by depth first search.
1495
+ We can instead use a breadth first search (increasing depth)::
1496
+
1497
+ sage: list(search_forest_iterator([[]], lambda l: [l + [0], l + [1]]
1498
+ ....: if len(l) < 3 else [],
1499
+ ....: algorithm='breadth'))
1500
+ [[],
1501
+ [0], [1],
1502
+ [0, 0], [0, 1], [1, 0], [1, 1],
1503
+ [0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1],
1504
+ [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]]
1505
+
1506
+ This allows for iterating through trees of infinite depth::
1507
+
1508
+ sage: it = search_forest_iterator([[]], lambda l: [l + [0], l + [1]],
1509
+ ....: algorithm='breadth')
1510
+ sage: [ next(it) for i in range(16) ]
1511
+ [[],
1512
+ [0], [1], [0, 0], [0, 1], [1, 0], [1, 1],
1513
+ [0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1],
1514
+ [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1],
1515
+ [0, 0, 0, 0]]
1516
+
1517
+ Here is an iterator through the prefix tree of sequences of
1518
+ letters in `0,1,2` without repetitions, sorted by length; the
1519
+ leaves are therefore permutations::
1520
+
1521
+ sage: list(search_forest_iterator([[]], lambda l: [l + [i] for i in range(3) if i not in l],
1522
+ ....: algorithm='breadth'))
1523
+ [[],
1524
+ [0], [1], [2],
1525
+ [0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1],
1526
+ [0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
1527
+ """
1528
+ # Little trick: the same implementation handles both depth and
1529
+ # breadth first search. Setting position to -1 results in a depth search
1530
+ # (you ask the children for the last node you met). Setting
1531
+ # position on 0 results in a breadth search (enumerate all the
1532
+ # descendants of a node before going on to the next father)
1533
+ position = -1 if algorithm == 'depth' else 0
1534
+
1535
+ # Invariant:
1536
+ # - for breadth first search: stack[i] contains an iterator over the nodes
1537
+ # of depth ``i`` in the tree
1538
+ # - for depth first search: stack[i] contains an iterator over the children
1539
+ # of the node at depth ``i-1`` in the current branch (assuming a virtual
1540
+ # father of all roots at depth ``-1``)
1541
+ stack = [iter(roots)]
1542
+ while stack:
1543
+ try:
1544
+ node = next(stack[position])
1545
+ except StopIteration:
1546
+ # If there are no more, go back up the tree
1547
+ # We also need to check if we've exhausted all
1548
+ # possibilities
1549
+ stack.pop(position)
1550
+ continue
1551
+
1552
+ yield node
1553
+ stack.append(iter(children(node)))
1554
+
1555
+
1556
+ class RecursivelyEnumeratedSet_forest(Parent):
1557
+ r"""
1558
+ The enumerated set of the nodes of the forest having the given
1559
+ ``roots``, and where ``children(x)`` returns the children of the
1560
+ node ``x`` of the forest.
1561
+
1562
+ See also :class:`sage.combinat.backtrack.GenericBacktracker`,
1563
+ :class:`RecursivelyEnumeratedSet_graded`, and
1564
+ :class:`RecursivelyEnumeratedSet_symmetric`.
1565
+
1566
+ INPUT:
1567
+
1568
+ - ``roots`` -- list (or iterable)
1569
+ - ``children`` -- a function returning a list (or iterable, or iterator)
1570
+ - ``post_process`` -- a function defined over the nodes of the
1571
+ forest (default: no post processing)
1572
+ - ``algorithm`` -- ``'depth'`` or ``'breadth'`` (default: ``'depth'``)
1573
+ - ``category`` -- a category (default: :class:`EnumeratedSets`)
1574
+
1575
+ The option ``post_process`` allows for customizing the nodes that
1576
+ are actually produced. Furthermore, if ``f(x)`` returns ``None``,
1577
+ then ``x`` won't be output at all.
1578
+
1579
+ EXAMPLES:
1580
+
1581
+ We construct the set of all binary sequences of length at most
1582
+ three, and list them::
1583
+
1584
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1585
+ sage: S = RecursivelyEnumeratedSet_forest( [[]],
1586
+ ....: lambda l: [l + [0], l + [1]] if len(l) < 3 else [],
1587
+ ....: category=FiniteEnumeratedSets())
1588
+ sage: S.list()
1589
+ [[],
1590
+ [0], [0, 0], [0, 0, 0], [0, 0, 1], [0, 1], [0, 1, 0], [0, 1, 1],
1591
+ [1], [1, 0], [1, 0, 0], [1, 0, 1], [1, 1], [1, 1, 0], [1, 1, 1]]
1592
+
1593
+ ``RecursivelyEnumeratedSet_forest`` needs to be explicitly told that the set is
1594
+ finite for the following to work::
1595
+
1596
+ sage: S.category()
1597
+ Category of finite enumerated sets
1598
+ sage: S.cardinality()
1599
+ 15
1600
+
1601
+ We proceed with the set of all lists of letters in ``0,1,2``
1602
+ without repetitions, ordered by increasing length (i.e. using a
1603
+ breadth first search through the tree)::
1604
+
1605
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1606
+ sage: tb = RecursivelyEnumeratedSet_forest( [[]],
1607
+ ....: lambda l: [l + [i] for i in range(3) if i not in l],
1608
+ ....: algorithm = 'breadth',
1609
+ ....: category=FiniteEnumeratedSets())
1610
+ sage: tb[0]
1611
+ []
1612
+ sage: tb.cardinality()
1613
+ 16
1614
+ sage: list(tb)
1615
+ [[],
1616
+ [0], [1], [2],
1617
+ [0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1],
1618
+ [0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
1619
+
1620
+ For infinite sets, this option should be set carefully to ensure
1621
+ that all elements are actually generated. The following example
1622
+ builds the set of all ordered pairs `(i,j)` of nonnegative
1623
+ integers such that `j\leq 1`::
1624
+
1625
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1626
+ sage: I = RecursivelyEnumeratedSet_forest([(0,0)],
1627
+ ....: lambda l: [(l[0]+1, l[1]), (l[0], 1)]
1628
+ ....: if l[1] == 0 else [(l[0], l[1]+1)])
1629
+
1630
+ With a depth first search, only the elements of the form `(i,0)`
1631
+ are generated::
1632
+
1633
+ sage: depth_search = I.depth_first_search_iterator()
1634
+ sage: [next(depth_search) for i in range(7)]
1635
+ [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0)]
1636
+
1637
+ Using instead breadth first search gives the usual anti-diagonal
1638
+ iterator::
1639
+
1640
+ sage: breadth_search = I.breadth_first_search_iterator()
1641
+ sage: [next(breadth_search) for i in range(15)]
1642
+ [(0, 0),
1643
+ (1, 0), (0, 1),
1644
+ (2, 0), (1, 1), (0, 2),
1645
+ (3, 0), (2, 1), (1, 2), (0, 3),
1646
+ (4, 0), (3, 1), (2, 2), (1, 3), (0, 4)]
1647
+
1648
+ .. rubric:: Deriving subclasses
1649
+
1650
+ The class of a parent `A` may derive from :class:`RecursivelyEnumeratedSet_forest` so
1651
+ that `A` can benefit from enumeration tools. As a running example,
1652
+ we consider the problem of enumerating integers whose binary
1653
+ expansion have at most three nonzero digits. For example, `3 =
1654
+ 2^1 + 2^0` has two nonzero digits. `15 = 2^3 + 2^2 + 2^1 + 2^0`
1655
+ has four nonzero digits. In fact, `15` is the smallest integer
1656
+ which is not in the enumerated set.
1657
+
1658
+ To achieve this, we use ``RecursivelyEnumeratedSet_forest`` to enumerate binary tuples
1659
+ with at most three nonzero digits, apply a post processing to
1660
+ recover the corresponding integers, and discard tuples finishing
1661
+ by zero.
1662
+
1663
+ A first approach is to pass the ``roots`` and ``children``
1664
+ functions as arguments to :meth:`RecursivelyEnumeratedSet_forest.__init__`::
1665
+
1666
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1667
+ sage: class A(UniqueRepresentation, RecursivelyEnumeratedSet_forest):
1668
+ ....: def __init__(self):
1669
+ ....: RecursivelyEnumeratedSet_forest.__init__(self, [()],
1670
+ ....: lambda x: [x + (0,), x + (1,)] if sum(x) < 3 else [],
1671
+ ....: lambda x: sum(x[i]*2^i for i in range(len(x)))
1672
+ ....: if sum(x) != 0 and x[-1] != 0 else None,
1673
+ ....: algorithm='breadth',
1674
+ ....: category=InfiniteEnumeratedSets())
1675
+ sage: MyForest = A(); MyForest
1676
+ An enumerated set with a forest structure
1677
+ sage: MyForest.category()
1678
+ Category of infinite enumerated sets
1679
+ sage: p = iter(MyForest)
1680
+ sage: [next(p) for i in range(30)]
1681
+ [1, 2, 3, 4, 6, 5, 7, 8, 12, 10, 14, 9, 13, 11, 16, 24,
1682
+ 20, 28, 18, 26, 22, 17, 25, 21, 19, 32, 48, 40, 56, 36]
1683
+
1684
+ An alternative approach is to implement ``roots`` and ``children``
1685
+ as methods of the subclass (in fact they could also be attributes
1686
+ of `A`). Namely, ``A.roots()`` must return an iterable containing
1687
+ the enumeration generators, and ``A.children(x)`` must return an
1688
+ iterable over the children of `x`. Optionally, `A` can have a
1689
+ method or attribute such that ``A.post_process(x)`` returns the
1690
+ desired output for the node ``x`` of the tree::
1691
+
1692
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1693
+ sage: class A(UniqueRepresentation, RecursivelyEnumeratedSet_forest):
1694
+ ....: def __init__(self):
1695
+ ....: RecursivelyEnumeratedSet_forest.__init__(self, algorithm='breadth',
1696
+ ....: category=InfiniteEnumeratedSets())
1697
+ ....: def roots(self):
1698
+ ....: return [()]
1699
+ ....: def children(self, x):
1700
+ ....: if sum(x) < 3:
1701
+ ....: return [x + (0,), x + (1,)]
1702
+ ....: else:
1703
+ ....: return []
1704
+ ....: def post_process(self, x):
1705
+ ....: if sum(x) == 0 or x[-1] == 0:
1706
+ ....: return None
1707
+ ....: else:
1708
+ ....: return sum(x[i]*2^i for i in range(len(x)))
1709
+ sage: MyForest = A(); MyForest
1710
+ An enumerated set with a forest structure
1711
+ sage: MyForest.category()
1712
+ Category of infinite enumerated sets
1713
+ sage: p = iter(MyForest)
1714
+ sage: [next(p) for i in range(30)]
1715
+ [1, 2, 3, 4, 6, 5, 7, 8, 12, 10, 14, 9, 13, 11, 16, 24,
1716
+ 20, 28, 18, 26, 22, 17, 25, 21, 19, 32, 48, 40, 56, 36]
1717
+
1718
+ .. warning::
1719
+
1720
+ A :class:`RecursivelyEnumeratedSet_forest` instance is picklable if and only if
1721
+ the input functions are themselves picklable. This excludes
1722
+ anonymous or interactively defined functions::
1723
+
1724
+ sage: def children(x):
1725
+ ....: return [x + 1]
1726
+ sage: S = RecursivelyEnumeratedSet_forest([1], children, category=InfiniteEnumeratedSets())
1727
+ sage: try:
1728
+ ....: dumps(S)
1729
+ ....: except Exception as e:
1730
+ ....: if 'PicklingError' in str(type(e).__name__):
1731
+ ....: print('PicklingError Caught')
1732
+ PicklingError Caught
1733
+
1734
+ Let us now fake ``children`` being defined in a Python module::
1735
+
1736
+ sage: import __main__
1737
+ sage: __main__.children = children
1738
+ sage: S = RecursivelyEnumeratedSet_forest([1], children, category=InfiniteEnumeratedSets())
1739
+ sage: loads(dumps(S))
1740
+ An enumerated set with a forest structure
1741
+ """
1742
+ def __init__(self, roots=None, children=None, post_process=None,
1743
+ algorithm='depth', facade=None, category=None):
1744
+ r"""
1745
+ TESTS::
1746
+
1747
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1748
+ sage: S = RecursivelyEnumeratedSet_forest(NN, lambda x: [], lambda x: x^2 if x.is_prime() else None)
1749
+ sage: S.category()
1750
+ Category of enumerated sets
1751
+ """
1752
+ if roots is not None:
1753
+ self._roots = roots
1754
+ if children is not None:
1755
+ self.children = children
1756
+ if post_process is not None:
1757
+ self.post_process = post_process
1758
+ self._algorithm = algorithm
1759
+ Parent.__init__(self, facade=facade,
1760
+ category=EnumeratedSets().or_subcategory(category))
1761
+
1762
+ __len__ = None
1763
+
1764
+ def _repr_(self):
1765
+ r"""
1766
+ TESTS::
1767
+
1768
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1769
+ sage: RecursivelyEnumeratedSet_forest( [1], lambda x: [x+1])
1770
+ An enumerated set with a forest structure
1771
+ """
1772
+ return "An enumerated set with a forest structure"
1773
+
1774
+ def roots(self):
1775
+ r"""
1776
+ Return an iterable over the roots of ``self``.
1777
+
1778
+ EXAMPLES::
1779
+
1780
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1781
+ sage: I = RecursivelyEnumeratedSet_forest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)])
1782
+ sage: [i for i in I.roots()]
1783
+ [(0, 0)]
1784
+ sage: I = RecursivelyEnumeratedSet_forest([(0,0),(1,1)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)])
1785
+ sage: [i for i in I.roots()]
1786
+ [(0, 0), (1, 1)]
1787
+ """
1788
+ return self._roots
1789
+
1790
+ @abstract_method
1791
+ def children(self, x):
1792
+ r"""
1793
+ Return the children of the element ``x``.
1794
+
1795
+ The result can be a list, an iterable, an iterator, or even a
1796
+ generator.
1797
+
1798
+ EXAMPLES::
1799
+
1800
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1801
+ sage: I = RecursivelyEnumeratedSet_forest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)])
1802
+ sage: [i for i in I.children((0,0))]
1803
+ [(1, 0), (0, 1)]
1804
+ sage: [i for i in I.children((1,0))]
1805
+ [(2, 0), (1, 1)]
1806
+ sage: [i for i in I.children((1,1))]
1807
+ [(1, 2)]
1808
+ sage: [i for i in I.children((4,1))]
1809
+ [(4, 2)]
1810
+ sage: [i for i in I.children((4,0))]
1811
+ [(5, 0), (4, 1)]
1812
+ """
1813
+
1814
+ def __iter__(self):
1815
+ r"""
1816
+ Return an iterator over the elements of ``self``.
1817
+
1818
+ EXAMPLES::
1819
+
1820
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1821
+ sage: def children(l):
1822
+ ....: return [l + [0], l + [1]]
1823
+ sage: C = RecursivelyEnumeratedSet_forest(([],), children)
1824
+ sage: f = C.__iter__()
1825
+ sage: next(f)
1826
+ []
1827
+ sage: next(f)
1828
+ [0]
1829
+ sage: next(f)
1830
+ [0, 0]
1831
+ """
1832
+ iter = search_forest_iterator(self.roots(),
1833
+ self.children,
1834
+ algorithm=self._algorithm)
1835
+ if hasattr(self, "post_process"):
1836
+ iter = _imap_and_filter_none(self.post_process, iter)
1837
+ return iter
1838
+
1839
+ def depth_first_search_iterator(self):
1840
+ r"""
1841
+ Return a depth first search iterator over the elements of ``self``.
1842
+
1843
+ EXAMPLES::
1844
+
1845
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1846
+ sage: f = RecursivelyEnumeratedSet_forest([[]],
1847
+ ....: lambda l: [l + [0], l + [1]] if len(l) < 3 else [])
1848
+ sage: list(f.depth_first_search_iterator())
1849
+ [[], [0], [0, 0], [0, 0, 0], [0, 0, 1], [0, 1], [0, 1, 0], [0, 1, 1],
1850
+ [1], [1, 0], [1, 0, 0], [1, 0, 1], [1, 1], [1, 1, 0], [1, 1, 1]]
1851
+ """
1852
+ return iter(self)
1853
+
1854
+ def breadth_first_search_iterator(self):
1855
+ r"""
1856
+ Return a breadth first search iterator over the elements of ``self``.
1857
+
1858
+ EXAMPLES::
1859
+
1860
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1861
+ sage: f = RecursivelyEnumeratedSet_forest([[]],
1862
+ ....: lambda l: [l+[0], l+[1]] if len(l) < 3 else [])
1863
+ sage: list(f.breadth_first_search_iterator())
1864
+ [[], [0], [1], [0, 0], [0, 1], [1, 0], [1, 1], [0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]]
1865
+ sage: S = RecursivelyEnumeratedSet_forest([(0,0)],
1866
+ ....: lambda x : [(x[0], x[1]+1)] if x[1] != 0 else [(x[0]+1,0), (x[0],1)],
1867
+ ....: post_process = lambda x: x if ((is_prime(x[0]) and is_prime(x[1])) and ((x[0] - x[1]) == 2)) else None)
1868
+ sage: p = S.breadth_first_search_iterator()
1869
+ sage: [next(p), next(p), next(p), next(p), next(p), next(p), next(p)]
1870
+ [(5, 3), (7, 5), (13, 11), (19, 17), (31, 29), (43, 41), (61, 59)]
1871
+ """
1872
+ iter = search_forest_iterator(self.roots(), self.children, algorithm='breadth')
1873
+ if hasattr(self, "post_process"):
1874
+ iter = _imap_and_filter_none(self.post_process, iter)
1875
+ return iter
1876
+
1877
+ def _elements_of_depth_iterator_rec(self, depth=0):
1878
+ r"""
1879
+ Return an iterator over the elements of ``self`` of given depth.
1880
+ An element of depth `n` can be obtained by applying the
1881
+ children function `n` times from a root. This function is not affected
1882
+ by post processing.
1883
+
1884
+ EXAMPLES::
1885
+
1886
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1887
+ sage: I = RecursivelyEnumeratedSet_forest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)])
1888
+ sage: list(I._elements_of_depth_iterator_rec(8))
1889
+ [(8, 0), (7, 1), (6, 2), (5, 3), (4, 4), (3, 5), (2, 6), (1, 7), (0, 8)]
1890
+ sage: I = RecursivelyEnumeratedSet_forest([[]], lambda l: [l+[0], l+[1]] if len(l) < 3 else [])
1891
+ sage: list(I._elements_of_depth_iterator_rec(0))
1892
+ [[]]
1893
+ sage: list(I._elements_of_depth_iterator_rec(1))
1894
+ [[0], [1]]
1895
+ sage: list(I._elements_of_depth_iterator_rec(2))
1896
+ [[0, 0], [0, 1], [1, 0], [1, 1]]
1897
+ sage: list(I._elements_of_depth_iterator_rec(3))
1898
+ [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]]
1899
+ sage: list(I._elements_of_depth_iterator_rec(4))
1900
+ []
1901
+ """
1902
+ if depth == 0:
1903
+ yield from self.roots()
1904
+ else:
1905
+ for father in self._elements_of_depth_iterator_rec(depth - 1):
1906
+ yield from self.children(father)
1907
+
1908
+ def elements_of_depth_iterator(self, depth=0):
1909
+ r"""
1910
+ Return an iterator over the elements of ``self`` of given depth.
1911
+ An element of depth `n` can be obtained by applying the
1912
+ children function `n` times from a root.
1913
+
1914
+ EXAMPLES::
1915
+
1916
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1917
+ sage: S = RecursivelyEnumeratedSet_forest([(0,0)] ,
1918
+ ....: lambda x : [(x[0], x[1]+1)] if x[1] != 0 else [(x[0]+1,0), (x[0],1)],
1919
+ ....: post_process = lambda x: x if ((is_prime(x[0]) and is_prime(x[1]))
1920
+ ....: and ((x[0] - x[1]) == 2)) else None)
1921
+ sage: p = S.elements_of_depth_iterator(8)
1922
+ sage: next(p)
1923
+ (5, 3)
1924
+ sage: S = RecursivelyEnumeratedSet_forest(NN, lambda x : [],
1925
+ ....: lambda x: x^2 if x.is_prime() else None)
1926
+ sage: p = S.elements_of_depth_iterator(0)
1927
+ sage: [next(p), next(p), next(p), next(p), next(p)]
1928
+ [4, 9, 25, 49, 121]
1929
+ """
1930
+ iter = self._elements_of_depth_iterator_rec(depth)
1931
+ if hasattr(self, "post_process"):
1932
+ iter = _imap_and_filter_none(self.post_process, iter)
1933
+ return iter
1934
+
1935
+ def __contains__(self, elt):
1936
+ r"""
1937
+ Return ``True`` if ``elt`` is in ``self``.
1938
+
1939
+ .. warning::
1940
+
1941
+ This is achieved by iterating through the elements until
1942
+ ``elt`` is found. In particular, this method will never
1943
+ stop when ``elt`` is not in ``self`` and ``self`` is
1944
+ infinite.
1945
+
1946
+ EXAMPLES::
1947
+
1948
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1949
+ sage: S = RecursivelyEnumeratedSet_forest([[]], lambda l: [l + [0], l + [1]] if len(l) < 3 else [],
1950
+ ....: category=FiniteEnumeratedSets())
1951
+ sage: [4] in S
1952
+ False
1953
+ sage: [1] in S
1954
+ True
1955
+ sage: [1,1,1,1] in S
1956
+ False
1957
+ sage: all(S.__contains__(i) for i in iter(S))
1958
+ True
1959
+ sage: S = RecursivelyEnumeratedSet_forest([1], lambda x: [x + 1], category=InfiniteEnumeratedSets())
1960
+ sage: 1 in S
1961
+ True
1962
+ sage: 732 in S
1963
+ True
1964
+ sage: -1 in S # not tested : Will never stop
1965
+
1966
+ The algorithm uses a random enumeration of the nodes of the
1967
+ forest. This choice was motivated by examples in which both
1968
+ depth first search and breadth first search failed. The
1969
+ following example enumerates all ordered pairs of nonnegative
1970
+ integers, starting from an infinite set of roots, where each
1971
+ root has an infinite number of children::
1972
+
1973
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1974
+ sage: S = RecursivelyEnumeratedSet_forest(
1975
+ ....: Family(NN, lambda x: (x, 0)),
1976
+ ....: lambda x: Family(PositiveIntegers(), lambda y: (x[0], y)) if x[1] == 0 else [])
1977
+ sage: p = S.depth_first_search_iterator()
1978
+ sage: [next(p), next(p), next(p), next(p), next(p), next(p), next(p)]
1979
+ [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6)]
1980
+ sage: p = S.breadth_first_search_iterator()
1981
+ sage: [next(p), next(p), next(p), next(p), next(p), next(p), next(p)]
1982
+ [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0)]
1983
+ sage: (0,0) in S
1984
+ True
1985
+ sage: (1,1) in S
1986
+ True
1987
+ sage: (10,10) in S
1988
+ True
1989
+ sage: (42,18) in S
1990
+ True
1991
+
1992
+ We now consider the same set of all ordered pairs of
1993
+ nonnegative integers but constructed in a different way. There
1994
+ still are infinitely many roots, but each node has a single
1995
+ child. From each root starts an infinite branch of breadth
1996
+ `1`::
1997
+
1998
+ sage: S = RecursivelyEnumeratedSet_forest(Family(NN, lambda x: (x, 0)),
1999
+ ....: lambda x: [(x[0], x[1] + 1)])
2000
+ sage: p = S.depth_first_search_iterator()
2001
+ sage: [next(p), next(p), next(p), next(p), next(p), next(p), next(p)]
2002
+ [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6)]
2003
+ sage: p = S.breadth_first_search_iterator()
2004
+ sage: [next(p), next(p), next(p), next(p), next(p), next(p), next(p)]
2005
+ [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0)]
2006
+ sage: (0,0) in S
2007
+ True
2008
+ sage: (1,1) in S
2009
+ True
2010
+ sage: (10,10) in S
2011
+ True
2012
+ sage: (37,11) in S
2013
+ True
2014
+ """
2015
+ stack = [iter(self.roots())]
2016
+ while stack:
2017
+ position = randint(0, len(stack) - 1)
2018
+ try:
2019
+ node = next(stack[position])
2020
+ except StopIteration:
2021
+ stack.pop(position)
2022
+ continue
2023
+
2024
+ if node == elt:
2025
+ return True
2026
+ stack.append(iter(self.children(node)))
2027
+ return False
2028
+
2029
+ def map_reduce(self, map_function=None,
2030
+ reduce_function=None,
2031
+ reduce_init=None):
2032
+ r"""
2033
+ Apply a Map/Reduce algorithm on ``self``.
2034
+
2035
+ INPUT:
2036
+
2037
+ - ``map_function`` -- a function from the element of ``self`` to some
2038
+ set with a reduce operation (e.g.: a monoid). The default value is
2039
+ the constant function ``1``.
2040
+
2041
+ - ``reduce_function`` -- the reduce function (e.g.: the addition of a
2042
+ monoid); the default value is ``+``
2043
+
2044
+ - ``reduce_init`` -- the initialisation of the reduction (e.g.: the
2045
+ neutral element of the monoid); the default value is ``0``
2046
+
2047
+ .. NOTE::
2048
+
2049
+ the effect of the default values is to compute the cardinality
2050
+ of ``self``.
2051
+
2052
+ EXAMPLES::
2053
+
2054
+ sage: seeds = [([i], i, i) for i in range(1, 10)]
2055
+ sage: def succ(t):
2056
+ ....: list, sum, last = t
2057
+ ....: return [(list + [i], sum + i, i) for i in range(1, last)]
2058
+ sage: F = RecursivelyEnumeratedSet(seeds, succ,
2059
+ ....: structure='forest', enumeration='depth')
2060
+
2061
+ sage: # needs sage.symbolic
2062
+ sage: y = var('y')
2063
+ sage: def map_function(t):
2064
+ ....: li, sum, _ = t
2065
+ ....: return y ^ sum
2066
+ sage: def reduce_function(x, y):
2067
+ ....: return x + y
2068
+ sage: F.map_reduce(map_function, reduce_function, 0)
2069
+ y^45 + y^44 + y^43 + 2*y^42 + 2*y^41 + 3*y^40 + 4*y^39 + 5*y^38 + 6*y^37
2070
+ + 8*y^36 + 9*y^35 + 10*y^34 + 12*y^33 + 13*y^32 + 15*y^31 + 17*y^30
2071
+ + 18*y^29 + 19*y^28 + 21*y^27 + 21*y^26 + 22*y^25 + 23*y^24 + 23*y^23
2072
+ + 23*y^22 + 23*y^21 + 22*y^20 + 21*y^19 + 21*y^18 + 19*y^17 + 18*y^16
2073
+ + 17*y^15 + 15*y^14 + 13*y^13 + 12*y^12 + 10*y^11 + 9*y^10 + 8*y^9 + 6*y^8
2074
+ + 5*y^7 + 4*y^6 + 3*y^5 + 2*y^4 + 2*y^3 + y^2 + y
2075
+
2076
+ Here is an example with the default values::
2077
+
2078
+ sage: F.map_reduce()
2079
+ 511
2080
+
2081
+ .. SEEALSO:: :mod:`sage.parallel.map_reduce`
2082
+ """
2083
+ import sage.parallel.map_reduce
2084
+ return sage.parallel.map_reduce.RESetMapReduce(
2085
+ forest=self,
2086
+ map_function=map_function,
2087
+ reduce_function=reduce_function,
2088
+ reduce_init=reduce_init).run()