passagemath-categories 10.6.32__cp314-cp314t-musllinux_1_2_aarch64.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-10.6.32.dist-info/METADATA +156 -0
  2. passagemath_categories-10.6.32.dist-info/RECORD +719 -0
  3. passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
  4. passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
  5. passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
  6. passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
  7. passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
  8. sage/all__sagemath_categories.py +28 -0
  9. sage/arith/all.py +38 -0
  10. sage/arith/constants.pxd +27 -0
  11. sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
  12. sage/arith/functions.pxd +4 -0
  13. sage/arith/functions.pyx +221 -0
  14. sage/arith/misc.py +6552 -0
  15. sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
  16. sage/arith/multi_modular.pxd +39 -0
  17. sage/arith/multi_modular.pyx +994 -0
  18. sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
  19. sage/arith/rational_reconstruction.pxd +4 -0
  20. sage/arith/rational_reconstruction.pyx +115 -0
  21. sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
  22. sage/arith/srange.pyx +571 -0
  23. sage/calculus/all__sagemath_categories.py +2 -0
  24. sage/calculus/functional.py +481 -0
  25. sage/calculus/functions.py +151 -0
  26. sage/categories/additive_groups.py +73 -0
  27. sage/categories/additive_magmas.py +1044 -0
  28. sage/categories/additive_monoids.py +114 -0
  29. sage/categories/additive_semigroups.py +184 -0
  30. sage/categories/affine_weyl_groups.py +238 -0
  31. sage/categories/algebra_ideals.py +95 -0
  32. sage/categories/algebra_modules.py +96 -0
  33. sage/categories/algebras.py +349 -0
  34. sage/categories/algebras_with_basis.py +377 -0
  35. sage/categories/all.py +160 -0
  36. sage/categories/aperiodic_semigroups.py +29 -0
  37. sage/categories/associative_algebras.py +47 -0
  38. sage/categories/bialgebras.py +101 -0
  39. sage/categories/bialgebras_with_basis.py +414 -0
  40. sage/categories/bimodules.py +206 -0
  41. sage/categories/chain_complexes.py +268 -0
  42. sage/categories/classical_crystals.py +480 -0
  43. sage/categories/coalgebras.py +405 -0
  44. sage/categories/coalgebras_with_basis.py +232 -0
  45. sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
  46. sage/categories/coercion_methods.pyx +52 -0
  47. sage/categories/commutative_additive_groups.py +104 -0
  48. sage/categories/commutative_additive_monoids.py +45 -0
  49. sage/categories/commutative_additive_semigroups.py +48 -0
  50. sage/categories/commutative_algebra_ideals.py +87 -0
  51. sage/categories/commutative_algebras.py +94 -0
  52. sage/categories/commutative_ring_ideals.py +58 -0
  53. sage/categories/commutative_rings.py +736 -0
  54. sage/categories/complete_discrete_valuation.py +293 -0
  55. sage/categories/complex_reflection_groups.py +145 -0
  56. sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
  57. sage/categories/coxeter_group_algebras.py +186 -0
  58. sage/categories/coxeter_groups.py +3402 -0
  59. sage/categories/crystals.py +2628 -0
  60. sage/categories/cw_complexes.py +216 -0
  61. sage/categories/dedekind_domains.py +137 -0
  62. sage/categories/discrete_valuation.py +325 -0
  63. sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
  64. sage/categories/division_rings.py +114 -0
  65. sage/categories/domains.py +95 -0
  66. sage/categories/drinfeld_modules.py +789 -0
  67. sage/categories/dual.py +42 -0
  68. sage/categories/enumerated_sets.py +1146 -0
  69. sage/categories/euclidean_domains.py +271 -0
  70. sage/categories/examples/algebras_with_basis.py +102 -0
  71. sage/categories/examples/all.py +1 -0
  72. sage/categories/examples/commutative_additive_monoids.py +130 -0
  73. sage/categories/examples/commutative_additive_semigroups.py +199 -0
  74. sage/categories/examples/coxeter_groups.py +8 -0
  75. sage/categories/examples/crystals.py +236 -0
  76. sage/categories/examples/cw_complexes.py +163 -0
  77. sage/categories/examples/facade_sets.py +187 -0
  78. sage/categories/examples/filtered_algebras_with_basis.py +204 -0
  79. sage/categories/examples/filtered_modules_with_basis.py +154 -0
  80. sage/categories/examples/finite_coxeter_groups.py +252 -0
  81. sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
  82. sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
  83. sage/categories/examples/finite_enumerated_sets.py +208 -0
  84. sage/categories/examples/finite_monoids.py +150 -0
  85. sage/categories/examples/finite_semigroups.py +190 -0
  86. sage/categories/examples/finite_weyl_groups.py +191 -0
  87. sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
  88. sage/categories/examples/graded_modules_with_basis.py +168 -0
  89. sage/categories/examples/graphs.py +122 -0
  90. sage/categories/examples/hopf_algebras_with_basis.py +145 -0
  91. sage/categories/examples/infinite_enumerated_sets.py +190 -0
  92. sage/categories/examples/lie_algebras.py +352 -0
  93. sage/categories/examples/lie_algebras_with_basis.py +196 -0
  94. sage/categories/examples/magmas.py +162 -0
  95. sage/categories/examples/manifolds.py +94 -0
  96. sage/categories/examples/monoids.py +144 -0
  97. sage/categories/examples/posets.py +178 -0
  98. sage/categories/examples/semigroups.py +580 -0
  99. sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  100. sage/categories/examples/semigroups_cython.pyx +221 -0
  101. sage/categories/examples/semirings.py +249 -0
  102. sage/categories/examples/sets_cat.py +706 -0
  103. sage/categories/examples/sets_with_grading.py +101 -0
  104. sage/categories/examples/with_realizations.py +542 -0
  105. sage/categories/fields.py +991 -0
  106. sage/categories/filtered_algebras.py +63 -0
  107. sage/categories/filtered_algebras_with_basis.py +548 -0
  108. sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
  109. sage/categories/filtered_modules.py +210 -0
  110. sage/categories/filtered_modules_with_basis.py +1209 -0
  111. sage/categories/finite_complex_reflection_groups.py +1506 -0
  112. sage/categories/finite_coxeter_groups.py +1138 -0
  113. sage/categories/finite_crystals.py +103 -0
  114. sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
  115. sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
  116. sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
  117. sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
  118. sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
  119. sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
  120. sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
  121. sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
  122. sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
  123. sage/categories/finite_enumerated_sets.py +769 -0
  124. sage/categories/finite_fields.py +252 -0
  125. sage/categories/finite_groups.py +256 -0
  126. sage/categories/finite_lattice_posets.py +242 -0
  127. sage/categories/finite_monoids.py +316 -0
  128. sage/categories/finite_permutation_groups.py +339 -0
  129. sage/categories/finite_posets.py +1994 -0
  130. sage/categories/finite_semigroups.py +136 -0
  131. sage/categories/finite_sets.py +93 -0
  132. sage/categories/finite_weyl_groups.py +39 -0
  133. sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
  134. sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
  135. sage/categories/finitely_generated_magmas.py +57 -0
  136. sage/categories/finitely_generated_semigroups.py +214 -0
  137. sage/categories/function_fields.py +76 -0
  138. sage/categories/g_sets.py +77 -0
  139. sage/categories/gcd_domains.py +65 -0
  140. sage/categories/generalized_coxeter_groups.py +94 -0
  141. sage/categories/graded_algebras.py +85 -0
  142. sage/categories/graded_algebras_with_basis.py +258 -0
  143. sage/categories/graded_bialgebras.py +32 -0
  144. sage/categories/graded_bialgebras_with_basis.py +32 -0
  145. sage/categories/graded_coalgebras.py +65 -0
  146. sage/categories/graded_coalgebras_with_basis.py +51 -0
  147. sage/categories/graded_hopf_algebras.py +41 -0
  148. sage/categories/graded_hopf_algebras_with_basis.py +169 -0
  149. sage/categories/graded_lie_algebras.py +91 -0
  150. sage/categories/graded_lie_algebras_with_basis.py +44 -0
  151. sage/categories/graded_lie_conformal_algebras.py +74 -0
  152. sage/categories/graded_modules.py +133 -0
  153. sage/categories/graded_modules_with_basis.py +329 -0
  154. sage/categories/graphs.py +138 -0
  155. sage/categories/group_algebras.py +430 -0
  156. sage/categories/groupoid.py +94 -0
  157. sage/categories/groups.py +667 -0
  158. sage/categories/h_trivial_semigroups.py +64 -0
  159. sage/categories/hecke_modules.py +185 -0
  160. sage/categories/highest_weight_crystals.py +980 -0
  161. sage/categories/hopf_algebras.py +219 -0
  162. sage/categories/hopf_algebras_with_basis.py +309 -0
  163. sage/categories/infinite_enumerated_sets.py +115 -0
  164. sage/categories/integral_domains.py +203 -0
  165. sage/categories/j_trivial_semigroups.py +29 -0
  166. sage/categories/kac_moody_algebras.py +82 -0
  167. sage/categories/kahler_algebras.py +203 -0
  168. sage/categories/l_trivial_semigroups.py +63 -0
  169. sage/categories/lambda_bracket_algebras.py +280 -0
  170. sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
  171. sage/categories/lattice_posets.py +89 -0
  172. sage/categories/left_modules.py +49 -0
  173. sage/categories/lie_algebras.py +1070 -0
  174. sage/categories/lie_algebras_with_basis.py +261 -0
  175. sage/categories/lie_conformal_algebras.py +350 -0
  176. sage/categories/lie_conformal_algebras_with_basis.py +147 -0
  177. sage/categories/lie_groups.py +73 -0
  178. sage/categories/loop_crystals.py +1290 -0
  179. sage/categories/magmas.py +1189 -0
  180. sage/categories/magmas_and_additive_magmas.py +149 -0
  181. sage/categories/magmatic_algebras.py +365 -0
  182. sage/categories/manifolds.py +352 -0
  183. sage/categories/matrix_algebras.py +40 -0
  184. sage/categories/metric_spaces.py +387 -0
  185. sage/categories/modular_abelian_varieties.py +78 -0
  186. sage/categories/modules.py +989 -0
  187. sage/categories/modules_with_basis.py +2794 -0
  188. sage/categories/monoid_algebras.py +38 -0
  189. sage/categories/monoids.py +739 -0
  190. sage/categories/noetherian_rings.py +87 -0
  191. sage/categories/number_fields.py +242 -0
  192. sage/categories/ore_modules.py +189 -0
  193. sage/categories/partially_ordered_monoids.py +49 -0
  194. sage/categories/permutation_groups.py +63 -0
  195. sage/categories/pointed_sets.py +42 -0
  196. sage/categories/polyhedra.py +74 -0
  197. sage/categories/poor_man_map.py +270 -0
  198. sage/categories/posets.py +722 -0
  199. sage/categories/principal_ideal_domains.py +270 -0
  200. sage/categories/quantum_group_representations.py +543 -0
  201. sage/categories/quotient_fields.py +728 -0
  202. sage/categories/r_trivial_semigroups.py +45 -0
  203. sage/categories/regular_crystals.py +898 -0
  204. sage/categories/regular_supercrystals.py +170 -0
  205. sage/categories/right_modules.py +49 -0
  206. sage/categories/ring_ideals.py +74 -0
  207. sage/categories/rings.py +1904 -0
  208. sage/categories/rngs.py +175 -0
  209. sage/categories/schemes.py +393 -0
  210. sage/categories/semigroups.py +1060 -0
  211. sage/categories/semirings.py +71 -0
  212. sage/categories/semisimple_algebras.py +114 -0
  213. sage/categories/sets_with_grading.py +235 -0
  214. sage/categories/shephard_groups.py +43 -0
  215. sage/categories/signed_tensor.py +120 -0
  216. sage/categories/simplicial_complexes.py +134 -0
  217. sage/categories/simplicial_sets.py +1206 -0
  218. sage/categories/super_algebras.py +149 -0
  219. sage/categories/super_algebras_with_basis.py +144 -0
  220. sage/categories/super_hopf_algebras_with_basis.py +126 -0
  221. sage/categories/super_lie_conformal_algebras.py +193 -0
  222. sage/categories/super_modules.py +229 -0
  223. sage/categories/super_modules_with_basis.py +193 -0
  224. sage/categories/supercommutative_algebras.py +99 -0
  225. sage/categories/supercrystals.py +406 -0
  226. sage/categories/tensor.py +110 -0
  227. sage/categories/topological_spaces.py +170 -0
  228. sage/categories/triangular_kac_moody_algebras.py +439 -0
  229. sage/categories/tutorial.py +58 -0
  230. sage/categories/unique_factorization_domains.py +318 -0
  231. sage/categories/unital_algebras.py +426 -0
  232. sage/categories/vector_bundles.py +159 -0
  233. sage/categories/vector_spaces.py +357 -0
  234. sage/categories/weyl_groups.py +853 -0
  235. sage/combinat/all__sagemath_categories.py +34 -0
  236. sage/combinat/backtrack.py +180 -0
  237. sage/combinat/combinat.py +2269 -0
  238. sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  239. sage/combinat/combinat_cython.pxd +6 -0
  240. sage/combinat/combinat_cython.pyx +390 -0
  241. sage/combinat/combination.py +796 -0
  242. sage/combinat/combinatorial_map.py +416 -0
  243. sage/combinat/composition.py +2192 -0
  244. sage/combinat/dlx.py +510 -0
  245. sage/combinat/integer_lists/__init__.py +7 -0
  246. sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
  247. sage/combinat/integer_lists/base.pxd +16 -0
  248. sage/combinat/integer_lists/base.pyx +713 -0
  249. sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
  250. sage/combinat/integer_lists/invlex.pxd +4 -0
  251. sage/combinat/integer_lists/invlex.pyx +1650 -0
  252. sage/combinat/integer_lists/lists.py +328 -0
  253. sage/combinat/integer_lists/nn.py +48 -0
  254. sage/combinat/integer_vector.py +1818 -0
  255. sage/combinat/integer_vector_weighted.py +413 -0
  256. sage/combinat/matrices/all__sagemath_categories.py +5 -0
  257. sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
  258. sage/combinat/matrices/dancing_links.pyx +1159 -0
  259. sage/combinat/matrices/dancing_links_c.h +380 -0
  260. sage/combinat/matrices/dlxcpp.py +136 -0
  261. sage/combinat/partition.py +10070 -0
  262. sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
  263. sage/combinat/partitions.pyx +743 -0
  264. sage/combinat/permutation.py +10168 -0
  265. sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  266. sage/combinat/permutation_cython.pxd +11 -0
  267. sage/combinat/permutation_cython.pyx +407 -0
  268. sage/combinat/q_analogues.py +1090 -0
  269. sage/combinat/ranker.py +268 -0
  270. sage/combinat/subset.py +1561 -0
  271. sage/combinat/subsets_hereditary.py +202 -0
  272. sage/combinat/subsets_pairwise.py +184 -0
  273. sage/combinat/tools.py +63 -0
  274. sage/combinat/tuple.py +348 -0
  275. sage/data_structures/all.py +2 -0
  276. sage/data_structures/all__sagemath_categories.py +2 -0
  277. sage/data_structures/binary_matrix.pxd +138 -0
  278. sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
  279. sage/data_structures/binary_search.pxd +3 -0
  280. sage/data_structures/binary_search.pyx +66 -0
  281. sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
  282. sage/data_structures/bitset.pxd +40 -0
  283. sage/data_structures/bitset.pyx +2385 -0
  284. sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
  285. sage/data_structures/bitset_base.pxd +926 -0
  286. sage/data_structures/bitset_base.pyx +117 -0
  287. sage/data_structures/bitset_intrinsics.h +487 -0
  288. sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  289. sage/data_structures/blas_dict.pxd +12 -0
  290. sage/data_structures/blas_dict.pyx +469 -0
  291. sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
  292. sage/data_structures/list_of_pairs.pxd +16 -0
  293. sage/data_structures/list_of_pairs.pyx +122 -0
  294. sage/data_structures/mutable_poset.py +3312 -0
  295. sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
  296. sage/data_structures/pairing_heap.h +346 -0
  297. sage/data_structures/pairing_heap.pxd +88 -0
  298. sage/data_structures/pairing_heap.pyx +1464 -0
  299. sage/data_structures/sparse_bitset.pxd +62 -0
  300. sage/data_structures/stream.py +5070 -0
  301. sage/databases/all__sagemath_categories.py +7 -0
  302. sage/databases/sql_db.py +2236 -0
  303. sage/ext/all__sagemath_categories.py +3 -0
  304. sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
  305. sage/ext/fast_callable.pxd +4 -0
  306. sage/ext/fast_callable.pyx +2746 -0
  307. sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
  308. sage/ext/fast_eval.pxd +1 -0
  309. sage/ext/fast_eval.pyx +102 -0
  310. sage/ext/interpreters/__init__.py +1 -0
  311. sage/ext/interpreters/all__sagemath_categories.py +2 -0
  312. sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +0 -0
  376. sage/interfaces/process.pxd +5 -0
  377. sage/interfaces/process.pyx +288 -0
  378. sage/interfaces/quit.py +167 -0
  379. sage/interfaces/sage0.py +604 -0
  380. sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +0 -0
  385. sage/misc/allocator.pxd +6 -0
  386. sage/misc/allocator.pyx +47 -0
  387. sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
  388. sage/misc/binary_tree.pxd +29 -0
  389. sage/misc/binary_tree.pyx +537 -0
  390. sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  391. sage/misc/callable_dict.pyx +89 -0
  392. sage/misc/citation.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +0 -0
  414. sage/misc/search.pxd +2 -0
  415. sage/misc/search.pyx +68 -0
  416. sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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 +76 -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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +0 -0
  447. sage/rings/factorint.pyx +295 -0
  448. sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +0 -0
  509. sage/rings/integer.pxd +45 -0
  510. sage/rings/integer.pyx +7874 -0
  511. sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +0 -0
  564. sage/rings/polynomial/multi_polynomial.pxd +12 -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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +0 -0
  574. sage/rings/polynomial/polydict.pxd +45 -0
  575. sage/rings/polynomial/polydict.pyx +2701 -0
  576. sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +0 -0
  580. sage/rings/polynomial/polynomial_element.pxd +64 -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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +0 -0
  622. sage/rings/real_double.pxd +16 -0
  623. sage/rings/real_double.pyx +2218 -0
  624. sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
  625. sage/rings/real_lazy.pxd +30 -0
  626. sage/rings/real_lazy.pyx +1773 -0
  627. sage/rings/ring.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +0 -0
  698. sage/sets/recursively_enumerated_set.pxd +31 -0
  699. sage/sets/recursively_enumerated_set.pyx +2082 -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.cpython-314t-aarch64-linux-musl.so +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.cpython-314t-aarch64-linux-musl.so +0 -0
  710. sage/tests/cython.pyx +37 -0
  711. sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +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,2082 @@
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: loads(dumps(C))
989
+ Traceback (most recent call last):
990
+ ...
991
+ PicklingError: ...
992
+
993
+ This works in the command line but apparently not as a doctest::
994
+
995
+ sage: def f(a): return [a-1,a+1]
996
+ sage: C = RecursivelyEnumeratedSet([0], f, structure='symmetric')
997
+ sage: loads(dumps(C))
998
+ Traceback (most recent call last):
999
+ ...
1000
+ PicklingError: ...
1001
+ """
1002
+
1003
+ def breadth_first_search_iterator(self, max_depth=None):
1004
+ r"""
1005
+ Iterate on the elements of ``self`` (breadth first).
1006
+
1007
+ This iterator makes use of the graded structure by remembering only
1008
+ the last two graded components since the structure is symmetric.
1009
+
1010
+ The elements are guaranteed to be enumerated in the order in which they
1011
+ are first visited (left-to-right traversal).
1012
+
1013
+ INPUT:
1014
+
1015
+ - ``max_depth`` -- (default: ``self._max_depth``) specifies the
1016
+ maximal depth to which elements are computed
1017
+
1018
+ EXAMPLES::
1019
+
1020
+ sage: f = lambda a: [(a[0]-1,a[1]), (a[0],a[1]-1), (a[0]+1,a[1]), (a[0],a[1]+1)]
1021
+ sage: C = RecursivelyEnumeratedSet([(0,0)], f, structure='symmetric')
1022
+ sage: s = list(C.breadth_first_search_iterator(max_depth=2)); s
1023
+ [(0, 0),
1024
+ (-1, 0), (0, -1), (1, 0), (0, 1),
1025
+ (-2, 0), (-1, -1), (-1, 1), (0, -2), (1, -1), (2, 0), (1, 1), (0, 2)]
1026
+
1027
+ This iterator is used by default for symmetric structure::
1028
+
1029
+ sage: it = iter(C)
1030
+ sage: s == [next(it) for _ in range(13)]
1031
+ True
1032
+
1033
+ TESTS:
1034
+
1035
+ Check that :issue:`28674` is fixed::
1036
+
1037
+ sage: D = RecursivelyEnumeratedSet([(0,0)], f)
1038
+ sage: s == list(D.breadth_first_search_iterator(max_depth=2))
1039
+ True
1040
+ """
1041
+ cdef list C
1042
+ cdef set set_A, set_B
1043
+ cdef int depth
1044
+ if max_depth is None:
1045
+ max_depth = self._max_depth
1046
+
1047
+ set_A = set()
1048
+ B = self._seeds
1049
+ set_B = set(B)
1050
+ if max_depth >= 0:
1051
+ yield from B
1052
+ depth = 0
1053
+ while B and depth < max_depth:
1054
+ C = list()
1055
+ set_C = set()
1056
+ for x in B:
1057
+ for y in self.successors(x):
1058
+ if y is None or y in set_C or y in set_A or y in set_B:
1059
+ continue
1060
+ yield y
1061
+ C.append(y)
1062
+ set_C.add(y)
1063
+ set_A = set_B
1064
+ set_B = set_C
1065
+ B = C
1066
+ depth += 1
1067
+
1068
+ def graded_component_iterator(self):
1069
+ r"""
1070
+ Iterate over the graded components of ``self``.
1071
+
1072
+ A graded component is a set of elements of the same depth.
1073
+
1074
+ The enumeration remembers only the last two graded components
1075
+ generated since the structure is symmetric.
1076
+
1077
+ OUTPUT: an iterator of sets
1078
+
1079
+ EXAMPLES::
1080
+
1081
+ sage: f = lambda a: [a-1, a+1]
1082
+ sage: S = RecursivelyEnumeratedSet([10], f, structure='symmetric')
1083
+ sage: it = S.graded_component_iterator()
1084
+ sage: [sorted(next(it)) for _ in range(5)]
1085
+ [[10], [9, 11], [8, 12], [7, 13], [6, 14]]
1086
+
1087
+ Starting with two generators::
1088
+
1089
+ sage: f = lambda a: [a-1, a+1]
1090
+ sage: S = RecursivelyEnumeratedSet([5, 10], f, structure='symmetric')
1091
+ sage: it = S.graded_component_iterator()
1092
+ sage: [sorted(next(it)) for _ in range(5)]
1093
+ [[5, 10], [4, 6, 9, 11], [3, 7, 8, 12], [2, 13], [1, 14]]
1094
+
1095
+ Gaussian integers::
1096
+
1097
+ sage: # needs sage.symbolic
1098
+ sage: def f(a):
1099
+ ....: return [a + 1, a + I]
1100
+ sage: S = RecursivelyEnumeratedSet([0], f, structure='symmetric')
1101
+ sage: it = S.graded_component_iterator()
1102
+ sage: [sorted(next(it)) for _ in range(7)]
1103
+ [[0],
1104
+ [I, 1],
1105
+ [2*I, I + 1, 2],
1106
+ [3*I, 2*I + 1, I + 2, 3],
1107
+ [4*I, 3*I + 1, 2*I + 2, I + 3, 4],
1108
+ [5*I, 4*I + 1, 3*I + 2, 2*I + 3, I + 4, 5],
1109
+ [6*I, 5*I + 1, 4*I + 2, 3*I + 3, 2*I + 4, I + 5, 6]]
1110
+
1111
+ TESTS:
1112
+
1113
+ Note that interrupting the computation (``KeyboardInterrupt`` for
1114
+ instance) breaks the iterator::
1115
+
1116
+ sage: # needs sage.symbolic
1117
+ sage: def f(a):
1118
+ ....: sleep(0.05r)
1119
+ ....: return [a - 1, a + 1]
1120
+ sage: C = RecursivelyEnumeratedSet([0], f, structure='symmetric')
1121
+ sage: it = C.graded_component_iterator()
1122
+ sage: next(it)
1123
+ {0}
1124
+ sage: next(it)
1125
+ {-1, 1}
1126
+ sage: from sage.doctest.util import ensure_interruptible_after
1127
+ sage: with ensure_interruptible_after(0.02): next(it)
1128
+ sage: next(it)
1129
+ Traceback (most recent call last):
1130
+ ...
1131
+ StopIteration
1132
+ """
1133
+ cdef set A, B
1134
+ A = set()
1135
+ B = set(self._seeds)
1136
+ while B:
1137
+ yield B
1138
+ A, B = B, self._get_next_graded_component(A, B)
1139
+
1140
+ cpdef graded_component(self, depth):
1141
+ r"""
1142
+ Return the graded component of given depth.
1143
+
1144
+ This method caches each lower graded component. See
1145
+ :meth:`graded_component_iterator` to generate each graded component
1146
+ without caching the previous ones.
1147
+
1148
+ A graded component is a set of elements of the same depth where the
1149
+ depth of an element is its minimal distance to a root.
1150
+
1151
+ INPUT:
1152
+
1153
+ - ``depth`` -- integer
1154
+
1155
+ OUTPUT: set
1156
+
1157
+ EXAMPLES::
1158
+
1159
+ sage: f = lambda a: [a-1,a+1]
1160
+ sage: C = RecursivelyEnumeratedSet([10, 15], f, structure='symmetric')
1161
+ sage: for i in range(5): sorted(C.graded_component(i))
1162
+ [10, 15]
1163
+ [9, 11, 14, 16]
1164
+ [8, 12, 13, 17]
1165
+ [7, 18]
1166
+ [6, 19]
1167
+
1168
+ TESTS:
1169
+
1170
+ We make sure that :issue:`21312` is fixed::
1171
+
1172
+ sage: def f(a):
1173
+ ....: sleep(0.1r)
1174
+ ....: return [a - 1, a + 1]
1175
+ sage: C = RecursivelyEnumeratedSet([0], f, structure='symmetric')
1176
+ sage: from sage.doctest.util import ensure_interruptible_after
1177
+ sage: with ensure_interruptible_after(0.45): C.graded_component(10)
1178
+ sage: C.graded_component(1)
1179
+ {-1, 1}
1180
+ sage: C.graded_component(2)
1181
+ {-2, 2}
1182
+ sage: C.graded_component(3)
1183
+ {-3, 3}
1184
+ sage: C.graded_component(4)
1185
+ {-4, 4}
1186
+ sage: C.graded_component(5)
1187
+ {-5, 5}
1188
+ """
1189
+ cdef set A, B, C
1190
+ if self._graded_component is None:
1191
+ A = set()
1192
+ B = set(self._seeds)
1193
+ C = self._get_next_graded_component(A, B)
1194
+ self._graded_component = [B, C]
1195
+ while len(self._graded_component) <= depth:
1196
+ A = self._graded_component[-2]
1197
+ B = self._graded_component[-1]
1198
+ C = self._get_next_graded_component(A, B)
1199
+ self._graded_component.append(C)
1200
+ return self._graded_component[depth]
1201
+
1202
+ cdef set _get_next_graded_component(self, set A, set B):
1203
+ r"""
1204
+ Return the set of elements of depth `n+1`.
1205
+
1206
+ INPUT:
1207
+
1208
+ - ``A`` -- set, the set of elements of depth n-1
1209
+ - ``B`` -- set, the set of elements of depth n
1210
+
1211
+ OUTPUT: ``C``; the set of elements of depth n+1
1212
+
1213
+ .. TODO::
1214
+
1215
+ Can :class:`collections.OrderedDict` help maintain the
1216
+ breadth first search enumeration for each graded component?
1217
+
1218
+ EXAMPLES::
1219
+
1220
+ sage: f = lambda a: [a-1, a+1]
1221
+ sage: S = RecursivelyEnumeratedSet([5, 10], f, structure='symmetric')
1222
+ sage: it = S.graded_component_iterator()
1223
+ sage: [sorted(next(it)) for _ in range(3)] # indirect doctest
1224
+ [[5, 10], [4, 6, 9, 11], [3, 7, 8, 12]]
1225
+ """
1226
+ cdef set C
1227
+ C = set()
1228
+ for x in B:
1229
+ for y in self.successors(x):
1230
+ if (y is None or y in A or y in B):
1231
+ continue
1232
+ C.add(y)
1233
+ return C
1234
+
1235
+
1236
+ cdef class RecursivelyEnumeratedSet_graded(RecursivelyEnumeratedSet_generic):
1237
+ r"""
1238
+ Generic tool for constructing ideals of a graded relation.
1239
+
1240
+ INPUT:
1241
+
1242
+ - ``seeds`` -- list (or iterable) of hashable objects
1243
+ - ``successors`` -- function (or callable) returning a list (or iterable)
1244
+ - ``enumeration`` -- ``'depth'``, ``'breadth'`` or ``None`` (default: ``None``)
1245
+ - ``max_depth`` -- integer (default: ``float("inf")``)
1246
+
1247
+ EXAMPLES::
1248
+
1249
+ sage: f = lambda a: [(a[0]+1,a[1]), (a[0],a[1]+1)]
1250
+ sage: C = RecursivelyEnumeratedSet([(0,0)], f, structure='graded', max_depth=3)
1251
+ sage: C
1252
+ A recursively enumerated set with a graded structure (breadth first
1253
+ search) with max_depth=3
1254
+ sage: list(C)
1255
+ [(0, 0),
1256
+ (1, 0), (0, 1),
1257
+ (2, 0), (1, 1), (0, 2),
1258
+ (3, 0), (2, 1), (1, 2), (0, 3)]
1259
+ """
1260
+ def breadth_first_search_iterator(self, max_depth=None):
1261
+ r"""
1262
+ Iterate on the elements of ``self`` (breadth first).
1263
+
1264
+ This iterator makes use of the graded structure by remembering only
1265
+ the elements of the current depth.
1266
+
1267
+ The elements are guaranteed to be enumerated in the order in which they
1268
+ are first visited (left-to-right traversal).
1269
+
1270
+ INPUT:
1271
+
1272
+ - ``max_depth`` -- (default: ``self._max_depth``) specifies the
1273
+ maximal depth to which elements are computed
1274
+
1275
+ EXAMPLES::
1276
+
1277
+ sage: f = lambda a: [(a[0]+1,a[1]), (a[0],a[1]+1)]
1278
+ sage: C = RecursivelyEnumeratedSet([(0,0)], f, structure='graded')
1279
+ sage: list(C.breadth_first_search_iterator(max_depth=3))
1280
+ [(0, 0),
1281
+ (1, 0), (0, 1),
1282
+ (2, 0), (1, 1), (0, 2),
1283
+ (3, 0), (2, 1), (1, 2), (0, 3)]
1284
+ """
1285
+ cdef list next_level
1286
+ cdef set set_next_level
1287
+ cdef int depth
1288
+ if max_depth is None:
1289
+ max_depth = self._max_depth
1290
+ current_level = self._seeds
1291
+ if max_depth >= 0:
1292
+ yield from current_level
1293
+ depth = 0
1294
+ while current_level and depth < max_depth:
1295
+ next_level = list()
1296
+ set_next_level = set()
1297
+
1298
+ for x in current_level:
1299
+ for y in self.successors(x):
1300
+ if y is None or y in set_next_level:
1301
+ continue
1302
+ yield y
1303
+ next_level.append(y)
1304
+ set_next_level.add(y)
1305
+ current_level = next_level
1306
+ depth += 1
1307
+
1308
+ def graded_component_iterator(self):
1309
+ r"""
1310
+ Iterate over the graded components of ``self``.
1311
+
1312
+ A graded component is a set of elements of the same depth.
1313
+
1314
+ The algorithm remembers only the current graded component generated
1315
+ since the structure is graded.
1316
+
1317
+ OUTPUT: an iterator of sets
1318
+
1319
+ EXAMPLES::
1320
+
1321
+ sage: f = lambda a: [(a[0]+1,a[1]), (a[0],a[1]+1)]
1322
+ sage: C = RecursivelyEnumeratedSet([(0,0)], f, structure='graded', max_depth=3)
1323
+ sage: it = C.graded_component_iterator()
1324
+ sage: for _ in range(4): sorted(next(it))
1325
+ [(0, 0)]
1326
+ [(0, 1), (1, 0)]
1327
+ [(0, 2), (1, 1), (2, 0)]
1328
+ [(0, 3), (1, 2), (2, 1), (3, 0)]
1329
+
1330
+ TESTS:
1331
+
1332
+ Make sure that :issue:`20225` is fixed::
1333
+
1334
+ sage: child = lambda k:[2*k,2*k+1] if k<8 else []
1335
+ sage: root = [0]
1336
+ sage: R = RecursivelyEnumeratedSet(root, child, structure='graded')
1337
+ sage: it = R.graded_component_iterator()
1338
+ sage: for _ in range(7): next(it)
1339
+ {0}
1340
+ {1}
1341
+ {2, 3}
1342
+ {4, 5, 6, 7}
1343
+ {8, 9, 10, 11, 12, 13, 14, 15}
1344
+ set()
1345
+ set()
1346
+ """
1347
+ cdef set B
1348
+ B = set(self._seeds)
1349
+ while True:
1350
+ yield B
1351
+ B = self._get_next_graded_component(B)
1352
+
1353
+ cpdef graded_component(self, depth):
1354
+ r"""
1355
+ Return the graded component of given depth.
1356
+
1357
+ This method caches each lower graded component. See
1358
+ :meth:`graded_component_iterator` to generate each graded component
1359
+ without caching the previous ones.
1360
+
1361
+ A graded component is a set of elements of the same depth where the
1362
+ depth of an element is its minimal distance to a root.
1363
+
1364
+ INPUT:
1365
+
1366
+ - ``depth`` -- integer
1367
+
1368
+ OUTPUT: set
1369
+
1370
+ EXAMPLES::
1371
+
1372
+ sage: # needs sage.symbolic
1373
+ sage: def f(a):
1374
+ ....: return [a + 1, a + I]
1375
+ sage: C = RecursivelyEnumeratedSet([0], f, structure='graded')
1376
+ sage: for i in range(5): sorted(C.graded_component(i))
1377
+ [0]
1378
+ [I, 1]
1379
+ [2*I, I + 1, 2]
1380
+ [3*I, 2*I + 1, I + 2, 3]
1381
+ [4*I, 3*I + 1, 2*I + 2, I + 3, 4]
1382
+
1383
+ TESTS:
1384
+
1385
+ We make sure that :issue:`21312` is fixed::
1386
+
1387
+ sage: # needs sage.symbolic
1388
+ sage: def f(a):
1389
+ ....: sleep(0.1r)
1390
+ ....: return [a + 1, a + I]
1391
+ sage: C = RecursivelyEnumeratedSet([0], f, structure='graded')
1392
+ sage: from sage.doctest.util import ensure_interruptible_after
1393
+ sage: with ensure_interruptible_after(0.45): C.graded_component(10)
1394
+ sage: C.graded_component(2)
1395
+ {2*I, I + 1, 2}
1396
+ sage: C.graded_component(3)
1397
+ {3*I, 2*I + 1, I + 2, 3}
1398
+ sage: C.graded_component(4)
1399
+ {4*I, 3*I + 1, 2*I + 2, I + 3, 4}
1400
+ """
1401
+ cdef set B, C
1402
+ if self._graded_component is None:
1403
+ B = set(self._seeds)
1404
+ self._graded_component = [B]
1405
+ while len(self._graded_component) <= depth:
1406
+ B = self._graded_component[-1]
1407
+ C = self._get_next_graded_component(B)
1408
+ self._graded_component.append(C)
1409
+ return self._graded_component[depth]
1410
+
1411
+ cdef set _get_next_graded_component(self, set B):
1412
+ r"""
1413
+ Return the set of elements of depth `n+1`.
1414
+
1415
+ INPUT:
1416
+
1417
+ - ``B`` -- set, the set of elements of depth `n`
1418
+
1419
+ OUTPUT: ``C``; the set of elements of depth `n+1`
1420
+
1421
+ .. TODO::
1422
+
1423
+ Can :class:`collections.OrderedDict` help maintain the
1424
+ breadth first search enumeration for each graded component?
1425
+
1426
+ EXAMPLES::
1427
+
1428
+ sage: f = lambda a: [(a[0]+1,a[1]), (a[0],a[1]+1)]
1429
+ sage: C = RecursivelyEnumeratedSet([(0,0)], f, structure='graded')
1430
+ sage: it = C.graded_component_iterator()
1431
+ sage: [sorted(next(it)) for _ in range(2)] # indirect doctest
1432
+ [[(0, 0)], [(0, 1), (1, 0)]]
1433
+ """
1434
+ cdef set C
1435
+ C = set()
1436
+ for x in B:
1437
+ for y in self.successors(x):
1438
+ if (y is None or y in B):
1439
+ continue
1440
+ C.add(y)
1441
+ return C
1442
+
1443
+
1444
+ def _imap_and_filter_none(function, iterable):
1445
+ r"""
1446
+ Return an iterator over the elements ``function(x)``, where ``x``
1447
+ iterates through ``iterable``, such that ``function(x)`` is not
1448
+ ``None``.
1449
+
1450
+ EXAMPLES::
1451
+
1452
+ sage: from sage.sets.recursively_enumerated_set import _imap_and_filter_none
1453
+ sage: p = _imap_and_filter_none(lambda x: x if is_prime(x) else None, range(15))
1454
+ sage: [next(p), next(p), next(p), next(p), next(p), next(p)]
1455
+ [2, 3, 5, 7, 11, 13]
1456
+ sage: p = _imap_and_filter_none(lambda x: x + x, ['a','b','c','d','e'])
1457
+ sage: [next(p), next(p), next(p), next(p), next(p)]
1458
+ ['aa', 'bb', 'cc', 'dd', 'ee']
1459
+ """
1460
+ for x in iterable:
1461
+ x = function(x)
1462
+ if x is not None:
1463
+ yield x
1464
+
1465
+
1466
+ def search_forest_iterator(roots, children, algorithm='depth'):
1467
+ r"""
1468
+ Return an iterator on the nodes of the forest having the given
1469
+ roots, and where ``children(x)`` returns the children of the node ``x``
1470
+ of the forest. Note that every node of the tree is returned,
1471
+ not simply the leaves.
1472
+
1473
+ INPUT:
1474
+
1475
+ - ``roots`` -- list (or iterable)
1476
+ - ``children`` -- a function returning a list (or iterable)
1477
+ - ``algorithm`` -- ``'depth'`` or ``'breadth'`` (default: ``'depth'``)
1478
+
1479
+ EXAMPLES:
1480
+
1481
+ We construct the prefix tree of binary sequences of length at most
1482
+ three, and enumerate its nodes::
1483
+
1484
+ sage: from sage.sets.recursively_enumerated_set import search_forest_iterator
1485
+ sage: list(search_forest_iterator([[]], lambda l: [l + [0], l + [1]]
1486
+ ....: if len(l) < 3 else []))
1487
+ [[], [0], [0, 0], [0, 0, 0], [0, 0, 1], [0, 1], [0, 1, 0],
1488
+ [0, 1, 1], [1], [1, 0], [1, 0, 0], [1, 0, 1], [1, 1], [1, 1, 0], [1, 1, 1]]
1489
+
1490
+ By default, the nodes are iterated through by depth first search.
1491
+ We can instead use a breadth first search (increasing depth)::
1492
+
1493
+ sage: list(search_forest_iterator([[]], lambda l: [l + [0], l + [1]]
1494
+ ....: if len(l) < 3 else [],
1495
+ ....: algorithm='breadth'))
1496
+ [[],
1497
+ [0], [1],
1498
+ [0, 0], [0, 1], [1, 0], [1, 1],
1499
+ [0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1],
1500
+ [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]]
1501
+
1502
+ This allows for iterating through trees of infinite depth::
1503
+
1504
+ sage: it = search_forest_iterator([[]], lambda l: [l + [0], l + [1]],
1505
+ ....: algorithm='breadth')
1506
+ sage: [ next(it) for i in range(16) ]
1507
+ [[],
1508
+ [0], [1], [0, 0], [0, 1], [1, 0], [1, 1],
1509
+ [0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1],
1510
+ [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1],
1511
+ [0, 0, 0, 0]]
1512
+
1513
+ Here is an iterator through the prefix tree of sequences of
1514
+ letters in `0,1,2` without repetitions, sorted by length; the
1515
+ leaves are therefore permutations::
1516
+
1517
+ sage: list(search_forest_iterator([[]], lambda l: [l + [i] for i in range(3) if i not in l],
1518
+ ....: algorithm='breadth'))
1519
+ [[],
1520
+ [0], [1], [2],
1521
+ [0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1],
1522
+ [0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
1523
+ """
1524
+ # Little trick: the same implementation handles both depth and
1525
+ # breadth first search. Setting position to -1 results in a depth search
1526
+ # (you ask the children for the last node you met). Setting
1527
+ # position on 0 results in a breadth search (enumerate all the
1528
+ # descendants of a node before going on to the next father)
1529
+ position = -1 if algorithm == 'depth' else 0
1530
+
1531
+ # Invariant:
1532
+ # - for breadth first search: stack[i] contains an iterator over the nodes
1533
+ # of depth ``i`` in the tree
1534
+ # - for depth first search: stack[i] contains an iterator over the children
1535
+ # of the node at depth ``i-1`` in the current branch (assuming a virtual
1536
+ # father of all roots at depth ``-1``)
1537
+ stack = [iter(roots)]
1538
+ while stack:
1539
+ try:
1540
+ node = next(stack[position])
1541
+ except StopIteration:
1542
+ # If there are no more, go back up the tree
1543
+ # We also need to check if we've exhausted all
1544
+ # possibilities
1545
+ stack.pop(position)
1546
+ continue
1547
+
1548
+ yield node
1549
+ stack.append(iter(children(node)))
1550
+
1551
+
1552
+ class RecursivelyEnumeratedSet_forest(Parent):
1553
+ r"""
1554
+ The enumerated set of the nodes of the forest having the given
1555
+ ``roots``, and where ``children(x)`` returns the children of the
1556
+ node ``x`` of the forest.
1557
+
1558
+ See also :class:`sage.combinat.backtrack.GenericBacktracker`,
1559
+ :class:`RecursivelyEnumeratedSet_graded`, and
1560
+ :class:`RecursivelyEnumeratedSet_symmetric`.
1561
+
1562
+ INPUT:
1563
+
1564
+ - ``roots`` -- list (or iterable)
1565
+ - ``children`` -- a function returning a list (or iterable, or iterator)
1566
+ - ``post_process`` -- a function defined over the nodes of the
1567
+ forest (default: no post processing)
1568
+ - ``algorithm`` -- ``'depth'`` or ``'breadth'`` (default: ``'depth'``)
1569
+ - ``category`` -- a category (default: :class:`EnumeratedSets`)
1570
+
1571
+ The option ``post_process`` allows for customizing the nodes that
1572
+ are actually produced. Furthermore, if ``f(x)`` returns ``None``,
1573
+ then ``x`` won't be output at all.
1574
+
1575
+ EXAMPLES:
1576
+
1577
+ We construct the set of all binary sequences of length at most
1578
+ three, and list them::
1579
+
1580
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1581
+ sage: S = RecursivelyEnumeratedSet_forest( [[]],
1582
+ ....: lambda l: [l + [0], l + [1]] if len(l) < 3 else [],
1583
+ ....: category=FiniteEnumeratedSets())
1584
+ sage: S.list()
1585
+ [[],
1586
+ [0], [0, 0], [0, 0, 0], [0, 0, 1], [0, 1], [0, 1, 0], [0, 1, 1],
1587
+ [1], [1, 0], [1, 0, 0], [1, 0, 1], [1, 1], [1, 1, 0], [1, 1, 1]]
1588
+
1589
+ ``RecursivelyEnumeratedSet_forest`` needs to be explicitly told that the set is
1590
+ finite for the following to work::
1591
+
1592
+ sage: S.category()
1593
+ Category of finite enumerated sets
1594
+ sage: S.cardinality()
1595
+ 15
1596
+
1597
+ We proceed with the set of all lists of letters in ``0,1,2``
1598
+ without repetitions, ordered by increasing length (i.e. using a
1599
+ breadth first search through the tree)::
1600
+
1601
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1602
+ sage: tb = RecursivelyEnumeratedSet_forest( [[]],
1603
+ ....: lambda l: [l + [i] for i in range(3) if i not in l],
1604
+ ....: algorithm = 'breadth',
1605
+ ....: category=FiniteEnumeratedSets())
1606
+ sage: tb[0]
1607
+ []
1608
+ sage: tb.cardinality()
1609
+ 16
1610
+ sage: list(tb)
1611
+ [[],
1612
+ [0], [1], [2],
1613
+ [0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1],
1614
+ [0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
1615
+
1616
+ For infinite sets, this option should be set carefully to ensure
1617
+ that all elements are actually generated. The following example
1618
+ builds the set of all ordered pairs `(i,j)` of nonnegative
1619
+ integers such that `j\leq 1`::
1620
+
1621
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1622
+ sage: I = RecursivelyEnumeratedSet_forest([(0,0)],
1623
+ ....: lambda l: [(l[0]+1, l[1]), (l[0], 1)]
1624
+ ....: if l[1] == 0 else [(l[0], l[1]+1)])
1625
+
1626
+ With a depth first search, only the elements of the form `(i,0)`
1627
+ are generated::
1628
+
1629
+ sage: depth_search = I.depth_first_search_iterator()
1630
+ sage: [next(depth_search) for i in range(7)]
1631
+ [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0)]
1632
+
1633
+ Using instead breadth first search gives the usual anti-diagonal
1634
+ iterator::
1635
+
1636
+ sage: breadth_search = I.breadth_first_search_iterator()
1637
+ sage: [next(breadth_search) for i in range(15)]
1638
+ [(0, 0),
1639
+ (1, 0), (0, 1),
1640
+ (2, 0), (1, 1), (0, 2),
1641
+ (3, 0), (2, 1), (1, 2), (0, 3),
1642
+ (4, 0), (3, 1), (2, 2), (1, 3), (0, 4)]
1643
+
1644
+ .. rubric:: Deriving subclasses
1645
+
1646
+ The class of a parent `A` may derive from :class:`RecursivelyEnumeratedSet_forest` so
1647
+ that `A` can benefit from enumeration tools. As a running example,
1648
+ we consider the problem of enumerating integers whose binary
1649
+ expansion have at most three nonzero digits. For example, `3 =
1650
+ 2^1 + 2^0` has two nonzero digits. `15 = 2^3 + 2^2 + 2^1 + 2^0`
1651
+ has four nonzero digits. In fact, `15` is the smallest integer
1652
+ which is not in the enumerated set.
1653
+
1654
+ To achieve this, we use ``RecursivelyEnumeratedSet_forest`` to enumerate binary tuples
1655
+ with at most three nonzero digits, apply a post processing to
1656
+ recover the corresponding integers, and discard tuples finishing
1657
+ by zero.
1658
+
1659
+ A first approach is to pass the ``roots`` and ``children``
1660
+ functions as arguments to :meth:`RecursivelyEnumeratedSet_forest.__init__`::
1661
+
1662
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1663
+ sage: class A(UniqueRepresentation, RecursivelyEnumeratedSet_forest):
1664
+ ....: def __init__(self):
1665
+ ....: RecursivelyEnumeratedSet_forest.__init__(self, [()],
1666
+ ....: lambda x: [x + (0,), x + (1,)] if sum(x) < 3 else [],
1667
+ ....: lambda x: sum(x[i]*2^i for i in range(len(x)))
1668
+ ....: if sum(x) != 0 and x[-1] != 0 else None,
1669
+ ....: algorithm='breadth',
1670
+ ....: category=InfiniteEnumeratedSets())
1671
+ sage: MyForest = A(); MyForest
1672
+ An enumerated set with a forest structure
1673
+ sage: MyForest.category()
1674
+ Category of infinite enumerated sets
1675
+ sage: p = iter(MyForest)
1676
+ sage: [next(p) for i in range(30)]
1677
+ [1, 2, 3, 4, 6, 5, 7, 8, 12, 10, 14, 9, 13, 11, 16, 24,
1678
+ 20, 28, 18, 26, 22, 17, 25, 21, 19, 32, 48, 40, 56, 36]
1679
+
1680
+ An alternative approach is to implement ``roots`` and ``children``
1681
+ as methods of the subclass (in fact they could also be attributes
1682
+ of `A`). Namely, ``A.roots()`` must return an iterable containing
1683
+ the enumeration generators, and ``A.children(x)`` must return an
1684
+ iterable over the children of `x`. Optionally, `A` can have a
1685
+ method or attribute such that ``A.post_process(x)`` returns the
1686
+ desired output for the node ``x`` of the tree::
1687
+
1688
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1689
+ sage: class A(UniqueRepresentation, RecursivelyEnumeratedSet_forest):
1690
+ ....: def __init__(self):
1691
+ ....: RecursivelyEnumeratedSet_forest.__init__(self, algorithm='breadth',
1692
+ ....: category=InfiniteEnumeratedSets())
1693
+ ....: def roots(self):
1694
+ ....: return [()]
1695
+ ....: def children(self, x):
1696
+ ....: if sum(x) < 3:
1697
+ ....: return [x + (0,), x + (1,)]
1698
+ ....: else:
1699
+ ....: return []
1700
+ ....: def post_process(self, x):
1701
+ ....: if sum(x) == 0 or x[-1] == 0:
1702
+ ....: return None
1703
+ ....: else:
1704
+ ....: return sum(x[i]*2^i for i in range(len(x)))
1705
+ sage: MyForest = A(); MyForest
1706
+ An enumerated set with a forest structure
1707
+ sage: MyForest.category()
1708
+ Category of infinite enumerated sets
1709
+ sage: p = iter(MyForest)
1710
+ sage: [next(p) for i in range(30)]
1711
+ [1, 2, 3, 4, 6, 5, 7, 8, 12, 10, 14, 9, 13, 11, 16, 24,
1712
+ 20, 28, 18, 26, 22, 17, 25, 21, 19, 32, 48, 40, 56, 36]
1713
+
1714
+ .. warning::
1715
+
1716
+ A :class:`RecursivelyEnumeratedSet_forest` instance is picklable if and only if
1717
+ the input functions are themselves picklable. This excludes
1718
+ anonymous or interactively defined functions::
1719
+
1720
+ sage: def children(x):
1721
+ ....: return [x + 1]
1722
+ sage: S = RecursivelyEnumeratedSet_forest([1], children, category=InfiniteEnumeratedSets())
1723
+ sage: dumps(S)
1724
+ Traceback (most recent call last):
1725
+ ...
1726
+ PicklingError: Can't pickle <...function...>: attribute lookup ... failed
1727
+
1728
+ Let us now fake ``children`` being defined in a Python module::
1729
+
1730
+ sage: import __main__
1731
+ sage: __main__.children = children
1732
+ sage: S = RecursivelyEnumeratedSet_forest([1], children, category=InfiniteEnumeratedSets())
1733
+ sage: loads(dumps(S))
1734
+ An enumerated set with a forest structure
1735
+ """
1736
+ def __init__(self, roots=None, children=None, post_process=None,
1737
+ algorithm='depth', facade=None, category=None):
1738
+ r"""
1739
+ TESTS::
1740
+
1741
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1742
+ sage: S = RecursivelyEnumeratedSet_forest(NN, lambda x: [], lambda x: x^2 if x.is_prime() else None)
1743
+ sage: S.category()
1744
+ Category of enumerated sets
1745
+ """
1746
+ if roots is not None:
1747
+ self._roots = roots
1748
+ if children is not None:
1749
+ self.children = children
1750
+ if post_process is not None:
1751
+ self.post_process = post_process
1752
+ self._algorithm = algorithm
1753
+ Parent.__init__(self, facade=facade,
1754
+ category=EnumeratedSets().or_subcategory(category))
1755
+
1756
+ __len__ = None
1757
+
1758
+ def _repr_(self):
1759
+ r"""
1760
+ TESTS::
1761
+
1762
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1763
+ sage: RecursivelyEnumeratedSet_forest( [1], lambda x: [x+1])
1764
+ An enumerated set with a forest structure
1765
+ """
1766
+ return "An enumerated set with a forest structure"
1767
+
1768
+ def roots(self):
1769
+ r"""
1770
+ Return an iterable over the roots of ``self``.
1771
+
1772
+ EXAMPLES::
1773
+
1774
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1775
+ 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)])
1776
+ sage: [i for i in I.roots()]
1777
+ [(0, 0)]
1778
+ 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)])
1779
+ sage: [i for i in I.roots()]
1780
+ [(0, 0), (1, 1)]
1781
+ """
1782
+ return self._roots
1783
+
1784
+ @abstract_method
1785
+ def children(self, x):
1786
+ r"""
1787
+ Return the children of the element ``x``.
1788
+
1789
+ The result can be a list, an iterable, an iterator, or even a
1790
+ generator.
1791
+
1792
+ EXAMPLES::
1793
+
1794
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1795
+ 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)])
1796
+ sage: [i for i in I.children((0,0))]
1797
+ [(1, 0), (0, 1)]
1798
+ sage: [i for i in I.children((1,0))]
1799
+ [(2, 0), (1, 1)]
1800
+ sage: [i for i in I.children((1,1))]
1801
+ [(1, 2)]
1802
+ sage: [i for i in I.children((4,1))]
1803
+ [(4, 2)]
1804
+ sage: [i for i in I.children((4,0))]
1805
+ [(5, 0), (4, 1)]
1806
+ """
1807
+
1808
+ def __iter__(self):
1809
+ r"""
1810
+ Return an iterator over the elements of ``self``.
1811
+
1812
+ EXAMPLES::
1813
+
1814
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1815
+ sage: def children(l):
1816
+ ....: return [l + [0], l + [1]]
1817
+ sage: C = RecursivelyEnumeratedSet_forest(([],), children)
1818
+ sage: f = C.__iter__()
1819
+ sage: next(f)
1820
+ []
1821
+ sage: next(f)
1822
+ [0]
1823
+ sage: next(f)
1824
+ [0, 0]
1825
+ """
1826
+ iter = search_forest_iterator(self.roots(),
1827
+ self.children,
1828
+ algorithm=self._algorithm)
1829
+ if hasattr(self, "post_process"):
1830
+ iter = _imap_and_filter_none(self.post_process, iter)
1831
+ return iter
1832
+
1833
+ def depth_first_search_iterator(self):
1834
+ r"""
1835
+ Return a depth first search iterator over the elements of ``self``.
1836
+
1837
+ EXAMPLES::
1838
+
1839
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1840
+ sage: f = RecursivelyEnumeratedSet_forest([[]],
1841
+ ....: lambda l: [l + [0], l + [1]] if len(l) < 3 else [])
1842
+ sage: list(f.depth_first_search_iterator())
1843
+ [[], [0], [0, 0], [0, 0, 0], [0, 0, 1], [0, 1], [0, 1, 0], [0, 1, 1],
1844
+ [1], [1, 0], [1, 0, 0], [1, 0, 1], [1, 1], [1, 1, 0], [1, 1, 1]]
1845
+ """
1846
+ return iter(self)
1847
+
1848
+ def breadth_first_search_iterator(self):
1849
+ r"""
1850
+ Return a breadth first search iterator over the elements of ``self``.
1851
+
1852
+ EXAMPLES::
1853
+
1854
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1855
+ sage: f = RecursivelyEnumeratedSet_forest([[]],
1856
+ ....: lambda l: [l+[0], l+[1]] if len(l) < 3 else [])
1857
+ sage: list(f.breadth_first_search_iterator())
1858
+ [[], [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]]
1859
+ sage: S = RecursivelyEnumeratedSet_forest([(0,0)],
1860
+ ....: lambda x : [(x[0], x[1]+1)] if x[1] != 0 else [(x[0]+1,0), (x[0],1)],
1861
+ ....: post_process = lambda x: x if ((is_prime(x[0]) and is_prime(x[1])) and ((x[0] - x[1]) == 2)) else None)
1862
+ sage: p = S.breadth_first_search_iterator()
1863
+ sage: [next(p), next(p), next(p), next(p), next(p), next(p), next(p)]
1864
+ [(5, 3), (7, 5), (13, 11), (19, 17), (31, 29), (43, 41), (61, 59)]
1865
+ """
1866
+ iter = search_forest_iterator(self.roots(), self.children, algorithm='breadth')
1867
+ if hasattr(self, "post_process"):
1868
+ iter = _imap_and_filter_none(self.post_process, iter)
1869
+ return iter
1870
+
1871
+ def _elements_of_depth_iterator_rec(self, depth=0):
1872
+ r"""
1873
+ Return an iterator over the elements of ``self`` of given depth.
1874
+ An element of depth `n` can be obtained by applying the
1875
+ children function `n` times from a root. This function is not affected
1876
+ by post processing.
1877
+
1878
+ EXAMPLES::
1879
+
1880
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1881
+ 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)])
1882
+ sage: list(I._elements_of_depth_iterator_rec(8))
1883
+ [(8, 0), (7, 1), (6, 2), (5, 3), (4, 4), (3, 5), (2, 6), (1, 7), (0, 8)]
1884
+ sage: I = RecursivelyEnumeratedSet_forest([[]], lambda l: [l+[0], l+[1]] if len(l) < 3 else [])
1885
+ sage: list(I._elements_of_depth_iterator_rec(0))
1886
+ [[]]
1887
+ sage: list(I._elements_of_depth_iterator_rec(1))
1888
+ [[0], [1]]
1889
+ sage: list(I._elements_of_depth_iterator_rec(2))
1890
+ [[0, 0], [0, 1], [1, 0], [1, 1]]
1891
+ sage: list(I._elements_of_depth_iterator_rec(3))
1892
+ [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]]
1893
+ sage: list(I._elements_of_depth_iterator_rec(4))
1894
+ []
1895
+ """
1896
+ if depth == 0:
1897
+ yield from self.roots()
1898
+ else:
1899
+ for father in self._elements_of_depth_iterator_rec(depth - 1):
1900
+ yield from self.children(father)
1901
+
1902
+ def elements_of_depth_iterator(self, depth=0):
1903
+ r"""
1904
+ Return an iterator over the elements of ``self`` of given depth.
1905
+ An element of depth `n` can be obtained by applying the
1906
+ children function `n` times from a root.
1907
+
1908
+ EXAMPLES::
1909
+
1910
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1911
+ sage: S = RecursivelyEnumeratedSet_forest([(0,0)] ,
1912
+ ....: lambda x : [(x[0], x[1]+1)] if x[1] != 0 else [(x[0]+1,0), (x[0],1)],
1913
+ ....: post_process = lambda x: x if ((is_prime(x[0]) and is_prime(x[1]))
1914
+ ....: and ((x[0] - x[1]) == 2)) else None)
1915
+ sage: p = S.elements_of_depth_iterator(8)
1916
+ sage: next(p)
1917
+ (5, 3)
1918
+ sage: S = RecursivelyEnumeratedSet_forest(NN, lambda x : [],
1919
+ ....: lambda x: x^2 if x.is_prime() else None)
1920
+ sage: p = S.elements_of_depth_iterator(0)
1921
+ sage: [next(p), next(p), next(p), next(p), next(p)]
1922
+ [4, 9, 25, 49, 121]
1923
+ """
1924
+ iter = self._elements_of_depth_iterator_rec(depth)
1925
+ if hasattr(self, "post_process"):
1926
+ iter = _imap_and_filter_none(self.post_process, iter)
1927
+ return iter
1928
+
1929
+ def __contains__(self, elt):
1930
+ r"""
1931
+ Return ``True`` if ``elt`` is in ``self``.
1932
+
1933
+ .. warning::
1934
+
1935
+ This is achieved by iterating through the elements until
1936
+ ``elt`` is found. In particular, this method will never
1937
+ stop when ``elt`` is not in ``self`` and ``self`` is
1938
+ infinite.
1939
+
1940
+ EXAMPLES::
1941
+
1942
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1943
+ sage: S = RecursivelyEnumeratedSet_forest([[]], lambda l: [l + [0], l + [1]] if len(l) < 3 else [],
1944
+ ....: category=FiniteEnumeratedSets())
1945
+ sage: [4] in S
1946
+ False
1947
+ sage: [1] in S
1948
+ True
1949
+ sage: [1,1,1,1] in S
1950
+ False
1951
+ sage: all(S.__contains__(i) for i in iter(S))
1952
+ True
1953
+ sage: S = RecursivelyEnumeratedSet_forest([1], lambda x: [x + 1], category=InfiniteEnumeratedSets())
1954
+ sage: 1 in S
1955
+ True
1956
+ sage: 732 in S
1957
+ True
1958
+ sage: -1 in S # not tested : Will never stop
1959
+
1960
+ The algorithm uses a random enumeration of the nodes of the
1961
+ forest. This choice was motivated by examples in which both
1962
+ depth first search and breadth first search failed. The
1963
+ following example enumerates all ordered pairs of nonnegative
1964
+ integers, starting from an infinite set of roots, where each
1965
+ root has an infinite number of children::
1966
+
1967
+ sage: from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet_forest
1968
+ sage: S = RecursivelyEnumeratedSet_forest(
1969
+ ....: Family(NN, lambda x: (x, 0)),
1970
+ ....: lambda x: Family(PositiveIntegers(), lambda y: (x[0], y)) if x[1] == 0 else [])
1971
+ sage: p = S.depth_first_search_iterator()
1972
+ sage: [next(p), next(p), next(p), next(p), next(p), next(p), next(p)]
1973
+ [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6)]
1974
+ sage: p = S.breadth_first_search_iterator()
1975
+ sage: [next(p), next(p), next(p), next(p), next(p), next(p), next(p)]
1976
+ [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0)]
1977
+ sage: (0,0) in S
1978
+ True
1979
+ sage: (1,1) in S
1980
+ True
1981
+ sage: (10,10) in S
1982
+ True
1983
+ sage: (42,18) in S
1984
+ True
1985
+
1986
+ We now consider the same set of all ordered pairs of
1987
+ nonnegative integers but constructed in a different way. There
1988
+ still are infinitely many roots, but each node has a single
1989
+ child. From each root starts an infinite branch of breadth
1990
+ `1`::
1991
+
1992
+ sage: S = RecursivelyEnumeratedSet_forest(Family(NN, lambda x: (x, 0)),
1993
+ ....: lambda x: [(x[0], x[1] + 1)])
1994
+ sage: p = S.depth_first_search_iterator()
1995
+ sage: [next(p), next(p), next(p), next(p), next(p), next(p), next(p)]
1996
+ [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6)]
1997
+ sage: p = S.breadth_first_search_iterator()
1998
+ sage: [next(p), next(p), next(p), next(p), next(p), next(p), next(p)]
1999
+ [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0)]
2000
+ sage: (0,0) in S
2001
+ True
2002
+ sage: (1,1) in S
2003
+ True
2004
+ sage: (10,10) in S
2005
+ True
2006
+ sage: (37,11) in S
2007
+ True
2008
+ """
2009
+ stack = [iter(self.roots())]
2010
+ while stack:
2011
+ position = randint(0, len(stack) - 1)
2012
+ try:
2013
+ node = next(stack[position])
2014
+ except StopIteration:
2015
+ stack.pop(position)
2016
+ continue
2017
+
2018
+ if node == elt:
2019
+ return True
2020
+ stack.append(iter(self.children(node)))
2021
+ return False
2022
+
2023
+ def map_reduce(self, map_function=None,
2024
+ reduce_function=None,
2025
+ reduce_init=None):
2026
+ r"""
2027
+ Apply a Map/Reduce algorithm on ``self``.
2028
+
2029
+ INPUT:
2030
+
2031
+ - ``map_function`` -- a function from the element of ``self`` to some
2032
+ set with a reduce operation (e.g.: a monoid). The default value is
2033
+ the constant function ``1``.
2034
+
2035
+ - ``reduce_function`` -- the reduce function (e.g.: the addition of a
2036
+ monoid); the default value is ``+``
2037
+
2038
+ - ``reduce_init`` -- the initialisation of the reduction (e.g.: the
2039
+ neutral element of the monoid); the default value is ``0``
2040
+
2041
+ .. NOTE::
2042
+
2043
+ the effect of the default values is to compute the cardinality
2044
+ of ``self``.
2045
+
2046
+ EXAMPLES::
2047
+
2048
+ sage: seeds = [([i], i, i) for i in range(1, 10)]
2049
+ sage: def succ(t):
2050
+ ....: list, sum, last = t
2051
+ ....: return [(list + [i], sum + i, i) for i in range(1, last)]
2052
+ sage: F = RecursivelyEnumeratedSet(seeds, succ,
2053
+ ....: structure='forest', enumeration='depth')
2054
+
2055
+ sage: # needs sage.symbolic
2056
+ sage: y = var('y')
2057
+ sage: def map_function(t):
2058
+ ....: li, sum, _ = t
2059
+ ....: return y ^ sum
2060
+ sage: def reduce_function(x, y):
2061
+ ....: return x + y
2062
+ sage: F.map_reduce(map_function, reduce_function, 0)
2063
+ y^45 + y^44 + y^43 + 2*y^42 + 2*y^41 + 3*y^40 + 4*y^39 + 5*y^38 + 6*y^37
2064
+ + 8*y^36 + 9*y^35 + 10*y^34 + 12*y^33 + 13*y^32 + 15*y^31 + 17*y^30
2065
+ + 18*y^29 + 19*y^28 + 21*y^27 + 21*y^26 + 22*y^25 + 23*y^24 + 23*y^23
2066
+ + 23*y^22 + 23*y^21 + 22*y^20 + 21*y^19 + 21*y^18 + 19*y^17 + 18*y^16
2067
+ + 17*y^15 + 15*y^14 + 13*y^13 + 12*y^12 + 10*y^11 + 9*y^10 + 8*y^9 + 6*y^8
2068
+ + 5*y^7 + 4*y^6 + 3*y^5 + 2*y^4 + 2*y^3 + y^2 + y
2069
+
2070
+ Here is an example with the default values::
2071
+
2072
+ sage: F.map_reduce()
2073
+ 511
2074
+
2075
+ .. SEEALSO:: :mod:`sage.parallel.map_reduce`
2076
+ """
2077
+ import sage.parallel.map_reduce
2078
+ return sage.parallel.map_reduce.RESetMapReduce(
2079
+ forest=self,
2080
+ map_function=map_function,
2081
+ reduce_function=reduce_function,
2082
+ reduce_init=reduce_init).run()