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,3312 @@
1
+ # sage_setup: distribution = sagemath-categories
2
+ r"""
3
+ Mutable Poset
4
+
5
+ This module provides a class representing a finite partially ordered
6
+ set (poset) for the purpose of being used as a data structure. Thus
7
+ the posets introduced in this module are mutable, i.e., elements can
8
+ be added and removed from a poset at any time.
9
+
10
+ To get in touch with Sage's "usual" posets, start with the page
11
+ :mod:`Posets <sage.combinat.posets.__init__>` in the reference manual.
12
+
13
+
14
+ .. _mutable_poset_examples:
15
+
16
+ Examples
17
+ ========
18
+
19
+ First Steps
20
+ -----------
21
+
22
+ We start by creating an empty poset. This is simply done by
23
+
24
+ ::
25
+
26
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
27
+ sage: P = MP()
28
+ sage: P
29
+ poset()
30
+
31
+ A poset should contain elements, thus let us add them with
32
+
33
+ ::
34
+
35
+ sage: P.add(42)
36
+ sage: P.add(7)
37
+ sage: P.add(13)
38
+ sage: P.add(3)
39
+
40
+ Let us look at the poset again::
41
+
42
+ sage: P
43
+ poset(3, 7, 13, 42)
44
+
45
+ We see that they elements are sorted using `\leq` which exists on the
46
+ integers `\ZZ`. Since this is even a total order, we could have used a
47
+ more efficient data structure. Alternatively, we can write
48
+ ::
49
+
50
+ sage: MP([42, 7, 13, 3])
51
+ poset(3, 7, 13, 42)
52
+
53
+ to add several elements at once on construction.
54
+
55
+
56
+ A less boring Example
57
+ ---------------------
58
+
59
+ Let us continue with a less boring example. We define the class
60
+
61
+ ::
62
+
63
+ sage: class T(tuple):
64
+ ....: def __le__(left, right):
65
+ ....: return all(l <= r for l, r in zip(left, right))
66
+
67
+ It is equipped with a `\leq`-operation such that `a \leq b` if all
68
+ entries of `a` are at most the corresponding entry of `b`. For
69
+ example, we have
70
+
71
+ ::
72
+
73
+ sage: a = T((1,1))
74
+ sage: b = T((2,1))
75
+ sage: c = T((1,2))
76
+ sage: a <= b, a <= c, b <= c
77
+ (True, True, False)
78
+
79
+ The last comparison gives ``False``, since the comparison of the
80
+ first component checks whether `2 \leq 1`.
81
+
82
+ Now, let us add such elements to a poset::
83
+
84
+ sage: Q = MP([T((1, 1)), T((3, 3)), T((4, 1)),
85
+ ....: T((3, 2)), T((2, 3)), T((2, 2))]); Q
86
+ poset((1, 1), (2, 2), (2, 3), (3, 2), (3, 3), (4, 1))
87
+
88
+ In the representation above, the elements are sorted topologically,
89
+ smallest first. This does not (directly) show more structural
90
+ information. We can overcome this and display a "wiring layout" by
91
+ typing::
92
+
93
+ sage: print(Q.repr_full(reverse=True))
94
+ poset((3, 3), (2, 3), (3, 2), (2, 2), (4, 1), (1, 1))
95
+ +-- oo
96
+ | +-- no successors
97
+ | +-- predecessors: (3, 3), (4, 1)
98
+ +-- (3, 3)
99
+ | +-- successors: oo
100
+ | +-- predecessors: (2, 3), (3, 2)
101
+ +-- (2, 3)
102
+ | +-- successors: (3, 3)
103
+ | +-- predecessors: (2, 2)
104
+ +-- (3, 2)
105
+ | +-- successors: (3, 3)
106
+ | +-- predecessors: (2, 2)
107
+ +-- (2, 2)
108
+ | +-- successors: (2, 3), (3, 2)
109
+ | +-- predecessors: (1, 1)
110
+ +-- (4, 1)
111
+ | +-- successors: oo
112
+ | +-- predecessors: (1, 1)
113
+ +-- (1, 1)
114
+ | +-- successors: (2, 2), (4, 1)
115
+ | +-- predecessors: null
116
+ +-- null
117
+ | +-- successors: (1, 1)
118
+ | +-- no predecessors
119
+
120
+ Note that we use ``reverse=True`` to let the elements appear from
121
+ largest (on the top) to smallest (on the bottom).
122
+
123
+ If you look at the output above, you'll see two additional elements,
124
+ namely ``oo`` (`\infty`) and ``null`` (`\emptyset`). So what are these
125
+ strange animals? The answer is simple and maybe you can guess it
126
+ already. The `\infty`-element is larger than every other element,
127
+ therefore a successor of the maximal elements in the poset. Similarly,
128
+ the `\emptyset`-element is smaller than any other element, therefore a
129
+ predecessor of the poset's minimal elements. Both do not have to scare
130
+ us; they are just there and sometimes useful.
131
+
132
+
133
+ AUTHORS:
134
+
135
+ - Daniel Krenn (2015)
136
+
137
+ ACKNOWLEDGEMENT:
138
+
139
+ - Daniel Krenn is supported by the Austrian Science Fund (FWF): P 24644-N26.
140
+
141
+ Classes and their Methods
142
+ =========================
143
+ """
144
+ # ****************************************************************************
145
+ # Copyright (C) 2015 Daniel Krenn <dev@danielkrenn.at>
146
+ #
147
+ # Distributed under the terms of the GNU General Public License (GPL)
148
+ # as published by the Free Software Foundation; either version 2 of
149
+ # the License, or (at your option) any later version.
150
+ # https://www.gnu.org/licenses/
151
+ # ****************************************************************************
152
+
153
+ from sage.structure.sage_object import SageObject
154
+
155
+
156
+ class MutablePosetShell(SageObject):
157
+ r"""
158
+ A shell for an element of a :class:`mutable poset <MutablePoset>`.
159
+
160
+ INPUT:
161
+
162
+ - ``poset`` -- the poset to which this shell belongs
163
+
164
+ - ``element`` -- the element which should be
165
+ contained/encapsulated in this shell
166
+
167
+ OUTPUT: a shell for the given element
168
+
169
+ .. NOTE::
170
+
171
+ If the :meth:`element` of a shell is ``None``, then this
172
+ element is considered as "special" (see :meth:`is_special`).
173
+ There are two special elements, namely
174
+
175
+ - a ``'null'`` (an element smaller than each other element;
176
+ it has no predecessors) and
177
+ - an ``'oo'`` (an element larger than each other element;
178
+ it has no successors).
179
+
180
+ EXAMPLES::
181
+
182
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
183
+ sage: P = MP()
184
+ sage: P.add(66)
185
+ sage: P
186
+ poset(66)
187
+ sage: s = P.shell(66)
188
+ sage: type(s)
189
+ <class 'sage.data_structures.mutable_poset.MutablePosetShell'>
190
+
191
+ .. SEEALSO::
192
+
193
+ :class:`MutablePoset`
194
+ """
195
+ def __init__(self, poset, element):
196
+ r"""
197
+ See :class:`MutablePosetShell` for details.
198
+
199
+ TESTS::
200
+
201
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
202
+ sage: P = MP()
203
+ sage: from sage.data_structures.mutable_poset import MutablePosetShell
204
+ sage: MutablePosetShell(P, (1, 2))
205
+ (1, 2)
206
+ """
207
+ self._poset_ = poset
208
+ self._element_ = element
209
+ self._key_ = self.poset.get_key(element)
210
+ self._predecessors_ = set()
211
+ self._successors_ = set()
212
+ super().__init__()
213
+
214
+ @property
215
+ def poset(self):
216
+ r"""
217
+ The poset to which this shell belongs.
218
+
219
+ .. SEEALSO::
220
+
221
+ :class:`MutablePoset`
222
+
223
+ TESTS::
224
+
225
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
226
+ sage: P = MP()
227
+ sage: from sage.data_structures.mutable_poset import MutablePosetShell
228
+ sage: e = MutablePosetShell(P, (1, 2))
229
+ sage: e.poset is P
230
+ True
231
+ """
232
+ return self._poset_
233
+
234
+ @property
235
+ def element(self):
236
+ r"""
237
+ The element contained in this shell.
238
+
239
+ .. SEEALSO::
240
+
241
+ :meth:`key`,
242
+ :class:`MutablePoset`.
243
+
244
+ TESTS::
245
+
246
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
247
+ sage: P = MP()
248
+ sage: from sage.data_structures.mutable_poset import MutablePosetShell
249
+ sage: e = MutablePosetShell(P, (1, 2))
250
+ sage: e.element
251
+ (1, 2)
252
+ """
253
+ return self._element_
254
+
255
+ @property
256
+ def key(self):
257
+ r"""
258
+ The key of the element contained in this shell.
259
+
260
+ The key of an element is determined by the mutable poset (the
261
+ parent) via the ``key``-function (see construction of a
262
+ :class:`MutablePoset`).
263
+
264
+ .. SEEALSO::
265
+
266
+ :meth:`element`,
267
+ :class:`MutablePoset`.
268
+
269
+ TESTS::
270
+
271
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
272
+ sage: from sage.data_structures.mutable_poset import MutablePosetShell
273
+ sage: P = MP()
274
+ sage: e = MutablePosetShell(P, (1, 2))
275
+ sage: e.key
276
+ (1, 2)
277
+ sage: Q = MP(key=lambda k: k[0])
278
+ sage: f = MutablePosetShell(Q, (1, 2))
279
+ sage: f.key
280
+ 1
281
+
282
+ Test the caching of the key::
283
+
284
+ sage: def k(k):
285
+ ....: print('key %s' % (k,))
286
+ ....: return k
287
+ sage: R = MP(key=k)
288
+ sage: h = MutablePosetShell(R, (1, 2))
289
+ key (1, 2)
290
+ sage: h.key; h.key
291
+ (1, 2)
292
+ (1, 2)
293
+ """
294
+ return self._key_
295
+
296
+ def predecessors(self, reverse=False):
297
+ r"""
298
+ Return the predecessors of this shell.
299
+
300
+ INPUT:
301
+
302
+ - ``reverse`` -- boolean (default: ``False``); if set, then return
303
+ successors instead
304
+
305
+ OUTPUT: set
306
+
307
+ .. SEEALSO::
308
+
309
+ :meth:`successors`,
310
+ :class:`MutablePoset`.
311
+
312
+ TESTS::
313
+
314
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
315
+ sage: P = MP()
316
+ sage: from sage.data_structures.mutable_poset import MutablePosetShell
317
+ sage: e = MutablePosetShell(P, (1, 2))
318
+ sage: e.predecessors()
319
+ set()
320
+ """
321
+ if reverse:
322
+ return self._successors_
323
+ return self._predecessors_
324
+
325
+ def successors(self, reverse=False):
326
+ r"""
327
+ Return the successors of this shell.
328
+
329
+ INPUT:
330
+
331
+ - ``reverse`` -- boolean (default: ``False``); if set, then return
332
+ predecessors instead
333
+
334
+ OUTPUT: set
335
+
336
+ .. SEEALSO::
337
+
338
+ :meth:`predecessors`,
339
+ :class:`MutablePoset`.
340
+
341
+ TESTS::
342
+
343
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
344
+ sage: P = MP()
345
+ sage: from sage.data_structures.mutable_poset import MutablePosetShell
346
+ sage: e = MutablePosetShell(P, (1, 2))
347
+ sage: e.successors()
348
+ set()
349
+ """
350
+ if reverse:
351
+ return self._predecessors_
352
+ return self._successors_
353
+
354
+ def is_special(self):
355
+ r"""
356
+ Return whether this shell contains either the null-element, i.e., the
357
+ element smaller than any possible other element or the
358
+ infinity-element, i.e., the element larger than any possible
359
+ other element.
360
+
361
+ OUTPUT: boolean
362
+
363
+ .. SEEALSO::
364
+
365
+ :meth:`is_null`,
366
+ :meth:`is_oo`,
367
+ :class:`MutablePoset`.
368
+
369
+ TESTS::
370
+
371
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
372
+ sage: P = MP()
373
+ sage: P.null.is_special()
374
+ True
375
+ sage: P.oo.is_special()
376
+ True
377
+ """
378
+ return self.element is None
379
+
380
+ def is_null(self):
381
+ r"""
382
+ Return whether this shell contains the null-element, i.e., the element
383
+ smaller than any possible other element.
384
+
385
+ OUTPUT: boolean
386
+
387
+ .. SEEALSO::
388
+
389
+ :meth:`is_special`,
390
+ :meth:`is_oo`,
391
+ :meth:`MutablePoset.null`,
392
+ :class:`MutablePoset`.
393
+
394
+ TESTS::
395
+
396
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
397
+ sage: P = MP()
398
+ sage: P.null.is_null()
399
+ True
400
+ sage: P.oo.is_null()
401
+ False
402
+ """
403
+ return self.element is None and not self.predecessors()
404
+
405
+ def is_oo(self):
406
+ r"""
407
+ Return whether this shell contains the infinity-element, i.e., the element
408
+ larger than any possible other element.
409
+
410
+ OUTPUT: boolean
411
+
412
+ .. SEEALSO::
413
+
414
+ :meth:`is_null`,
415
+ :meth:`is_special`,
416
+ :meth:`MutablePoset.oo`,
417
+ :class:`MutablePoset`.
418
+
419
+ TESTS::
420
+
421
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
422
+ sage: P = MP()
423
+ sage: P.null.is_oo()
424
+ False
425
+ sage: P.oo.is_oo()
426
+ True
427
+ """
428
+ return self.element is None and not self.successors()
429
+
430
+ def _repr_(self):
431
+ r"""
432
+ Return the representation of this shell.
433
+
434
+ OUTPUT: string
435
+
436
+ .. NOTE::
437
+
438
+ If the :meth:`element` of this shell is not ``None``,
439
+ this method returns the respective representation string.
440
+ Otherwise, ``'null'`` or ``'oo'`` are returned,
441
+ depending on the non-existence of predecessors or
442
+ successors, respectively.
443
+
444
+ TESTS::
445
+
446
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
447
+ sage: P = MP()
448
+ sage: from sage.data_structures.mutable_poset import MutablePosetShell
449
+ sage: repr(MutablePosetShell(P, (1, 2))) # indirect doctest
450
+ '(1, 2)'
451
+ sage: repr(P.null) # indirect doctest
452
+ 'null'
453
+ sage: repr(P.oo) # indirect doctest
454
+ 'oo'
455
+ """
456
+ if self.is_null():
457
+ return 'null'
458
+ elif self.is_oo():
459
+ return 'oo'
460
+ else:
461
+ return repr(self.element)
462
+
463
+ def __hash__(self):
464
+ r"""
465
+ Return the hash of this shell.
466
+
467
+ OUTPUT: a hash value
468
+
469
+ This returns the hash value of the key of the element
470
+ contained in this shell.
471
+
472
+ TESTS::
473
+
474
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
475
+ sage: P = MP()
476
+ sage: from sage.data_structures.mutable_poset import MutablePosetShell
477
+ sage: hash(MutablePosetShell(P, (1, 2))) == hash((1, 2))
478
+ True
479
+ """
480
+ return hash(self.key)
481
+
482
+ def le(self, other, reverse=False):
483
+ r"""
484
+ Return whether this shell is less than or equal to ``other``.
485
+
486
+ INPUT:
487
+
488
+ - ``other`` -- a shell
489
+
490
+ - ``reverse`` -- boolean (default: ``False``); if set, then return
491
+ whether this shell is greater than or equal to ``other``
492
+
493
+ OUTPUT: boolean
494
+
495
+ .. NOTE::
496
+
497
+ The comparison of the shells is based on the comparison
498
+ of the keys of the elements contained in the shells,
499
+ except for special shells (see :class:`MutablePosetShell`).
500
+
501
+ .. SEEALSO::
502
+
503
+ :meth:`eq`,
504
+ :class:`MutablePoset`.
505
+
506
+ TESTS::
507
+
508
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
509
+ sage: P = MP()
510
+ sage: from sage.data_structures.mutable_poset import MutablePosetShell
511
+ sage: e = MutablePosetShell(P, (1, 2))
512
+ sage: z = P.null
513
+ sage: oo = P.oo
514
+ sage: z <= e # indirect doctest
515
+ True
516
+ sage: e <= oo # indirect doctest
517
+ True
518
+ sage: z <= oo # indirect doctest
519
+ True
520
+ sage: oo <= z # indirect doctest
521
+ False
522
+ sage: oo <= e # indirect doctest
523
+ False
524
+ sage: e <= z # indirect doctest
525
+ False
526
+ sage: z <= z # indirect doctest
527
+ True
528
+ sage: oo <= oo # indirect doctest
529
+ True
530
+ sage: e <= e # indirect doctest
531
+ True
532
+
533
+ ::
534
+
535
+ sage: z.le(e, reverse=True)
536
+ False
537
+ sage: e.le(oo, reverse=True)
538
+ False
539
+ sage: z.le(oo, reverse=True)
540
+ False
541
+ sage: oo.le(z, reverse=True)
542
+ True
543
+ sage: oo.le(e, reverse=True)
544
+ True
545
+ sage: e.le(z, reverse=True)
546
+ True
547
+ sage: z.le(z, reverse=True)
548
+ True
549
+ sage: oo.le(oo, reverse=True)
550
+ True
551
+ sage: e.le(e, reverse=True)
552
+ True
553
+ """
554
+ if reverse:
555
+ return other.le(self, reverse=False)
556
+
557
+ if self.element is None:
558
+ if not self._predecessors_:
559
+ # null on the left
560
+ return True
561
+ else:
562
+ # oo on the left
563
+ if other.element is None:
564
+ # null or oo on the right
565
+ return not other._successors_
566
+ else:
567
+ # not null, not oo on the right
568
+ return False
569
+ elif other.element is None:
570
+ # null/oo on the right
571
+ return not other._successors_
572
+
573
+ return self.key <= other.key
574
+
575
+ __le__ = le
576
+
577
+ def eq(self, other):
578
+ r"""
579
+ Return whether this shell is equal to ``other``.
580
+
581
+ INPUT:
582
+
583
+ - ``other`` -- a shell
584
+
585
+ OUTPUT: boolean
586
+
587
+ .. NOTE::
588
+
589
+ This method compares the keys of the elements contained
590
+ in the (non-special) shells. In particular,
591
+ elements/shells with the same key are considered as equal.
592
+
593
+ .. SEEALSO::
594
+
595
+ :meth:`le`,
596
+ :class:`MutablePoset`.
597
+
598
+ TESTS::
599
+
600
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
601
+ sage: P = MP()
602
+ sage: from sage.data_structures.mutable_poset import MutablePosetShell
603
+ sage: e = MutablePosetShell(P, (1, 2))
604
+ sage: f = MutablePosetShell(P, (2, 1))
605
+ sage: z = P.null
606
+ sage: oo = P.oo
607
+ sage: z == z
608
+ True
609
+ sage: oo == oo
610
+ True
611
+ sage: e == e
612
+ True
613
+ sage: e == f
614
+ False
615
+ sage: z == e
616
+ False
617
+ sage: e == oo
618
+ False
619
+ sage: oo == z
620
+ False
621
+
622
+ Comparing elements in different mutable posets is possible; their
623
+ shells are equal if their elements are::
624
+
625
+ sage: S = MP([42]); s = S.shell(42)
626
+ sage: T = MP([42]); t = T.shell(42)
627
+ sage: s == t
628
+ True
629
+ sage: S.oo == T.oo
630
+ True
631
+ """
632
+ if self.element is None and other.element is None:
633
+ return self.is_null() == other.is_null()
634
+ return self.key == other.key
635
+
636
+ __eq__ = eq
637
+
638
+ def _copy_all_linked_(self, memo, poset, mapping):
639
+ r"""
640
+ Return a copy of this shell. All shells linked to this shell
641
+ are copied as well.
642
+
643
+ This is a helper function for :meth:`MutablePoset.copy`.
644
+
645
+ INPUT:
646
+
647
+ - ``memo`` -- dictionary which assigns to the id of the
648
+ calling shell to a copy of it
649
+
650
+ - ``poset`` -- the poset to which the newly created shells
651
+ belongs. Note that the elements are not inserted into
652
+ ``poset``; this is done in the calling method
653
+ :meth:`MutablePoset._copy_shells_`.
654
+
655
+ - ``mapping`` -- a function which is applied on each of the elements
656
+
657
+ OUTPUT: a new shell
658
+
659
+ .. SEEALSO::
660
+
661
+ :meth:`MutablePoset.copy`,
662
+ :class:`MutablePoset`.
663
+
664
+ TESTS::
665
+
666
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
667
+ sage: P = MP()
668
+ sage: Q = MP()
669
+ sage: memo = {}
670
+ sage: z = P.null._copy_all_linked_(memo, Q, lambda e: e)
671
+ sage: z.poset is Q
672
+ True
673
+ sage: oo = z.successors().pop()
674
+ sage: oo.is_oo()
675
+ True
676
+
677
+ Note that :meth:`_copy_all_linked_` does not change the mutable
678
+ poset ``Q`` (this is done in the calling method
679
+ :meth:`MutablePoset._copy_shells_`). Thus we have
680
+ ::
681
+
682
+ sage: oo is Q.oo
683
+ False
684
+ """
685
+ try:
686
+ return memo[id(self)]
687
+ except KeyError:
688
+ pass
689
+
690
+ new = self.__class__(poset, mapping(self.element)
691
+ if self.element is not None else None)
692
+ memo[id(self)] = new
693
+
694
+ for reverse in (False, True):
695
+ for e in self.successors(reverse):
696
+ new.successors(reverse).add(e._copy_all_linked_(memo, poset, mapping))
697
+
698
+ return new
699
+
700
+ def lower_covers(self, shell, reverse=False):
701
+ r"""
702
+ Return the lower covers of the specified ``shell``;
703
+ the search is started at this (``self``) shell.
704
+
705
+ A lower cover of `x` is an element `y` of the poset
706
+ such that `y < x` and there is no element `z` of the poset
707
+ so that `y < z < x`.
708
+
709
+ INPUT:
710
+
711
+ - ``shell`` -- the shell for which to find the covering shells
712
+ There is no restriction of ``shell`` being contained in the poset
713
+ If ``shell`` is contained in the poset, then use the more efficient
714
+ methods :meth:`predecessors` and :meth:`successors`.
715
+
716
+ - ``reverse`` -- boolean (default: ``False``); if set, then find
717
+ the upper covers (see also :meth:`upper_covers`)
718
+ instead of the lower covers
719
+
720
+ OUTPUT: a set of :class:`shells <MutablePosetShell>`
721
+
722
+ .. NOTE::
723
+
724
+ Suppose ``reverse`` is ``False``. This method starts at
725
+ the calling shell (``self``) and searches towards ``'oo'``.
726
+ Thus, only shells which are (not necessarily
727
+ direct) successors of this shell are considered.
728
+
729
+ If ``reverse`` is ``True``, then the reverse direction is
730
+ taken.
731
+
732
+ EXAMPLES::
733
+
734
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
735
+ sage: class T(tuple):
736
+ ....: def __le__(left, right):
737
+ ....: return all(l <= r for l, r in zip(left, right))
738
+ sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
739
+ ....: T((4, 4)), T((1, 2)), T((2, 2))])
740
+ sage: e = P.shell(T((2, 2))); e
741
+ (2, 2)
742
+ sage: sorted(P.null.lower_covers(e),
743
+ ....: key=lambda c: repr(c.element))
744
+ [(1, 2), (2, 1)]
745
+ sage: set(_) == e.predecessors()
746
+ True
747
+ sage: sorted(P.oo.upper_covers(e),
748
+ ....: key=lambda c: repr(c.element))
749
+ [(4, 4)]
750
+ sage: set(_) == e.successors()
751
+ True
752
+
753
+ ::
754
+
755
+ sage: Q = MP([T((3, 2))])
756
+ sage: f = next(Q.shells())
757
+ sage: sorted(P.null.lower_covers(f),
758
+ ....: key=lambda c: repr(c.element))
759
+ [(2, 2)]
760
+ sage: sorted(P.oo.upper_covers(f),
761
+ ....: key=lambda c: repr(c.element))
762
+ [(4, 4)]
763
+
764
+ .. SEEALSO::
765
+
766
+ :meth:`upper_covers`,
767
+ :meth:`predecessors`,
768
+ :meth:`successors`,
769
+ :class:`MutablePoset`.
770
+ """
771
+ if self == shell:
772
+ return set()
773
+ covers = set().union(*(e.lower_covers(shell, reverse)
774
+ for e in self.successors(reverse)
775
+ if e.le(shell, reverse)))
776
+ return covers or set([self])
777
+
778
+ def upper_covers(self, shell, reverse=False):
779
+ r"""
780
+ Return the upper covers of the specified ``shell``;
781
+ the search is started at this (``self``) shell.
782
+
783
+ An upper cover of `x` is an element `y` of the poset
784
+ such that `x < y` and there is no element `z` of the poset
785
+ so that `x < z < y`.
786
+
787
+ INPUT:
788
+
789
+ - ``shell`` -- the shell for which to find the covering shells
790
+ There is no restriction of ``shell`` being contained in the poset
791
+ If ``shell`` is contained in the poset, then use the more efficient
792
+ methods :meth:`predecessors` and :meth:`successors`.
793
+
794
+ - ``reverse`` -- boolean (default: ``False``); if set, then find
795
+ the lower covers (see also :meth:`lower_covers`)
796
+ instead of the upper covers.
797
+
798
+ OUTPUT: a set of :class:`shells <MutablePosetShell>`
799
+
800
+ .. NOTE::
801
+
802
+ Suppose ``reverse`` is ``False``. This method starts at
803
+ the calling shell (``self``) and searches towards ``'null'``.
804
+ Thus, only shells which are (not necessarily
805
+ direct) predecessors of this shell are considered.
806
+
807
+ If ``reverse`` is ``True``, then the reverse direction is
808
+ taken.
809
+
810
+ EXAMPLES::
811
+
812
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
813
+ sage: class T(tuple):
814
+ ....: def __le__(left, right):
815
+ ....: return all(l <= r for l, r in zip(left, right))
816
+ sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
817
+ ....: T((4, 4)), T((1, 2)), T((2, 2))])
818
+ sage: e = P.shell(T((2, 2))); e
819
+ (2, 2)
820
+ sage: sorted(P.null.lower_covers(e),
821
+ ....: key=lambda c: repr(c.element))
822
+ [(1, 2), (2, 1)]
823
+ sage: set(_) == e.predecessors()
824
+ True
825
+ sage: sorted(P.oo.upper_covers(e),
826
+ ....: key=lambda c: repr(c.element))
827
+ [(4, 4)]
828
+ sage: set(_) == e.successors()
829
+ True
830
+
831
+ ::
832
+
833
+ sage: Q = MP([T((3, 2))])
834
+ sage: f = next(Q.shells())
835
+ sage: sorted(P.null.lower_covers(f),
836
+ ....: key=lambda c: repr(c.element))
837
+ [(2, 2)]
838
+ sage: sorted(P.oo.upper_covers(f),
839
+ ....: key=lambda c: repr(c.element))
840
+ [(4, 4)]
841
+
842
+ .. SEEALSO::
843
+
844
+ :meth:`predecessors`,
845
+ :meth:`successors`,
846
+ :class:`MutablePoset`.
847
+ """
848
+ return self.lower_covers(shell, not reverse)
849
+
850
+ def _iter_depth_first_visit_(self, marked,
851
+ reverse=False, key=None,
852
+ condition=None):
853
+ r"""
854
+ Return an iterator over all shells in depth first order.
855
+
856
+ This is a helper function for :meth:`iter_depth_first`.
857
+
858
+ INPUT:
859
+
860
+ - ``marked`` -- set in which marked shells are stored
861
+
862
+ - ``reverse`` -- boolean (default: ``False``); if set, reverses the
863
+ order, i.e., ``False`` searches towards ``'oo'`` and
864
+ ``True`` searches towards ``'null'``
865
+
866
+ - ``key`` -- (default: ``None``) a function used for sorting
867
+ the direct successors of a shell (used in case of a
868
+ tie). If this is ``None``, no sorting occurs.
869
+
870
+ - ``condition`` -- (default: ``None``) a function mapping a
871
+ shell to ``True`` (include in iteration) or ``False`` (do
872
+ not include). ``None`` is equivalent to a function returning
873
+ always ``True``. Note that the iteration does not go beyond a
874
+ not included shell.
875
+
876
+ .. NOTE::
877
+
878
+ The depth first search starts at this (``self``) shell. Thus
879
+ only this shell and shells greater than (in case of
880
+ ``reverse=False``) this shell are visited.
881
+
882
+ .. SEEALSO::
883
+
884
+ :meth:`iter_depth_first`,
885
+ :meth:`iter_topological`,
886
+ :class:`MutablePoset`.
887
+
888
+ TESTS::
889
+
890
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
891
+ sage: P = MP()
892
+ sage: P.add(42)
893
+ sage: P.add(5)
894
+ sage: marked = set()
895
+ sage: list(P.oo._iter_depth_first_visit_(marked, reverse=True))
896
+ [oo, 42, 5, null]
897
+ """
898
+ if (condition is not None and
899
+ not self.is_special() and not condition(self)):
900
+ return
901
+ if self in marked:
902
+ return
903
+ marked.add(self)
904
+ yield self
905
+ S = self.successors(reverse)
906
+ if key is not None:
907
+ S = sorted(S, key=key)
908
+ for shell in S:
909
+ yield from shell._iter_depth_first_visit_(marked, reverse,
910
+ key, condition)
911
+
912
+ def iter_depth_first(self, reverse=False, key=None, condition=None):
913
+ r"""
914
+ Iterate over all shells in depth first order.
915
+
916
+ INPUT:
917
+
918
+ - ``reverse`` -- boolean (default: ``False``); if set, reverses the
919
+ order, i.e., ``False`` searches towards ``'oo'`` and
920
+ ``True`` searches towards ``'null'``
921
+
922
+ - ``key`` -- (default: ``None``) a function used for sorting
923
+ the direct successors of a shell (used in case of a
924
+ tie). If this is ``None``, no sorting occurs.
925
+
926
+ - ``condition`` -- (default: ``None``) a function mapping a
927
+ shell to ``True`` (include in iteration) or ``False`` (do
928
+ not include). ``None`` is equivalent to a function returning
929
+ always ``True``. Note that the iteration does not go beyond a
930
+ not included shell.
931
+
932
+ .. NOTE::
933
+
934
+ The depth first search starts at this (``self``) shell. Thus
935
+ only this shell and shells greater than (in case of
936
+ ``reverse=False``) this shell are visited.
937
+
938
+ ALGORITHM:
939
+
940
+ See :wikipedia:`Depth-first_search`.
941
+
942
+ EXAMPLES::
943
+
944
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
945
+ sage: class T(tuple):
946
+ ....: def __le__(left, right):
947
+ ....: return all(l <= r for l, r in zip(left, right))
948
+ sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
949
+ ....: T((4, 4)), T((1, 2)), T((2, 2))])
950
+ sage: list(P.null.iter_depth_first(reverse=False, key=repr))
951
+ [null, (1, 1), (1, 2), (1, 3), (4, 4), oo, (2, 2), (2, 1)]
952
+ sage: list(P.oo.iter_depth_first(reverse=True, key=repr))
953
+ [oo, (4, 4), (1, 3), (1, 2), (1, 1), null, (2, 2), (2, 1)]
954
+ sage: list(P.null.iter_depth_first(
955
+ ....: condition=lambda s: s.element[0] == 1))
956
+ [null, (1, 1), (1, 2), (1, 3)]
957
+
958
+ .. SEEALSO::
959
+
960
+ :meth:`iter_topological`,
961
+ :class:`MutablePoset`.
962
+ """
963
+ marked = set()
964
+ return self._iter_depth_first_visit_(marked, reverse, key, condition)
965
+
966
+ def _iter_topological_visit_(self, marked,
967
+ reverse=False, key=None,
968
+ condition=None):
969
+ r"""
970
+ Return an iterator over all shells in topological order.
971
+
972
+ This is a helper function for :meth:`iter_topological`.
973
+
974
+ INPUT:
975
+
976
+ - ``marked`` -- set in which marked shells are stored
977
+
978
+ - ``reverse`` -- boolean (default: ``False``); if set, reverses the
979
+ order, i.e., ``False`` searches towards ``'oo'`` and
980
+ ``True`` searches towards ``'null'``
981
+
982
+ - ``key`` -- (default: ``None``) a function used for sorting
983
+ the direct predecessors of a shell (used in case of a
984
+ tie). If this is ``None``, no sorting occurs.
985
+
986
+ - ``condition`` -- (default: ``None``) a function mapping a
987
+ shell to ``True`` (include in iteration) or ``False`` (do
988
+ not include). ``None`` is equivalent to a function returning
989
+ always ``True``. Note that the iteration does not go beyond a
990
+ not included shell.
991
+
992
+ OUTPUT: an iterator
993
+
994
+ .. NOTE::
995
+
996
+ The topological search will only find shells smaller than
997
+ (in case of ``reverse=False``)
998
+ or equal to this (``self``) shell. This is in contrast to
999
+ :meth:`iter_depth_first`.
1000
+
1001
+ .. SEEALSO::
1002
+
1003
+ :meth:`iter_depth_first`,
1004
+ :meth:`iter_topological`,
1005
+ :class:`MutablePoset`.
1006
+
1007
+ TESTS::
1008
+
1009
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1010
+ sage: P = MP()
1011
+ sage: P.add(42)
1012
+ sage: P.add(5)
1013
+ sage: marked = set()
1014
+ sage: list(P.null._iter_topological_visit_(marked, reverse=True, key=repr))
1015
+ [oo, 42, 5, null]
1016
+ """
1017
+ if (condition is not None and
1018
+ not self.is_special() and not condition(self)):
1019
+ return
1020
+ if self in marked:
1021
+ return
1022
+ marked.add(self)
1023
+ S = self.predecessors(reverse)
1024
+ if key is not None and len(S) > 1:
1025
+ S = sorted(S, key=key)
1026
+ for shell in S:
1027
+ yield from shell._iter_topological_visit_(marked, reverse,
1028
+ key, condition)
1029
+ yield self
1030
+
1031
+ def iter_topological(self, reverse=False, key=None, condition=None):
1032
+ r"""
1033
+ Iterate over all shells in topological order.
1034
+
1035
+ INPUT:
1036
+
1037
+ - ``reverse`` -- boolean (default: ``False``); if set, reverses the
1038
+ order, i.e., ``False`` searches towards ``'oo'`` and
1039
+ ``True`` searches towards ``'null'``
1040
+
1041
+ - ``key`` -- (default: ``None``) a function used for sorting
1042
+ the direct predecessors of a shell (used in case of a
1043
+ tie). If this is ``None``, no sorting occurs.
1044
+
1045
+ - ``condition`` -- (default: ``None``) a function mapping a
1046
+ shell to ``True`` (include in iteration) or ``False`` (do
1047
+ not include). ``None`` is equivalent to a function returning
1048
+ always ``True``. Note that the iteration does not go beyond a
1049
+ not included shell.
1050
+
1051
+ OUTPUT: an iterator
1052
+
1053
+ .. NOTE::
1054
+
1055
+ The topological search will only find shells smaller than
1056
+ (in case of ``reverse=False``)
1057
+ or equal to this (``self``) shell. This is in contrast to
1058
+ :meth:`iter_depth_first`.
1059
+
1060
+ ALGORITHM:
1061
+
1062
+ Here a simplified version of the algorithm found in [Tar1976]_
1063
+ and [CLRS2001]_ is used. See also
1064
+ :wikipedia:`Topological_sorting`.
1065
+
1066
+ EXAMPLES::
1067
+
1068
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1069
+ sage: class T(tuple):
1070
+ ....: def __le__(left, right):
1071
+ ....: return all(l <= r for l, r in zip(left, right))
1072
+ sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
1073
+ ....: T((4, 4)), T((1, 2)), T((2, 2))])
1074
+
1075
+ ::
1076
+
1077
+ sage: for e in P.shells_topological(include_special=True,
1078
+ ....: reverse=True, key=repr):
1079
+ ....: print(e)
1080
+ ....: print(list(e.iter_topological(reverse=True, key=repr)))
1081
+ oo
1082
+ [oo]
1083
+ (4, 4)
1084
+ [oo, (4, 4)]
1085
+ (1, 3)
1086
+ [oo, (4, 4), (1, 3)]
1087
+ (2, 2)
1088
+ [oo, (4, 4), (2, 2)]
1089
+ (1, 2)
1090
+ [oo, (4, 4), (1, 3), (2, 2), (1, 2)]
1091
+ (2, 1)
1092
+ [oo, (4, 4), (2, 2), (2, 1)]
1093
+ (1, 1)
1094
+ [oo, (4, 4), (1, 3), (2, 2), (1, 2), (2, 1), (1, 1)]
1095
+ null
1096
+ [oo, (4, 4), (1, 3), (2, 2), (1, 2), (2, 1), (1, 1), null]
1097
+
1098
+ ::
1099
+
1100
+ sage: for e in P.shells_topological(include_special=True,
1101
+ ....: reverse=True, key=repr):
1102
+ ....: print(e)
1103
+ ....: print(list(e.iter_topological(reverse=False, key=repr)))
1104
+ oo
1105
+ [null, (1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (4, 4), oo]
1106
+ (4, 4)
1107
+ [null, (1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (4, 4)]
1108
+ (1, 3)
1109
+ [null, (1, 1), (1, 2), (1, 3)]
1110
+ (2, 2)
1111
+ [null, (1, 1), (1, 2), (2, 1), (2, 2)]
1112
+ (1, 2)
1113
+ [null, (1, 1), (1, 2)]
1114
+ (2, 1)
1115
+ [null, (1, 1), (2, 1)]
1116
+ (1, 1)
1117
+ [null, (1, 1)]
1118
+ null
1119
+ [null]
1120
+
1121
+ ::
1122
+
1123
+ sage: list(P.null.iter_topological(
1124
+ ....: reverse=True, condition=lambda s: s.element[0] == 1,
1125
+ ....: key=repr))
1126
+ [(1, 3), (1, 2), (1, 1), null]
1127
+
1128
+ .. SEEALSO::
1129
+
1130
+ :meth:`iter_depth_first`,
1131
+ :meth:`MutablePoset.shells_topological`,
1132
+ :meth:`MutablePoset.elements_topological`,
1133
+ :meth:`MutablePoset.keys_topological`,
1134
+ :class:`MutablePoset`.
1135
+ """
1136
+ marked = set()
1137
+ return self._iter_topological_visit_(marked, reverse, key, condition)
1138
+
1139
+ def merge(self, element, check=True, delete=True):
1140
+ r"""
1141
+ Merge the given element with the element contained in this
1142
+ shell.
1143
+
1144
+ INPUT:
1145
+
1146
+ - ``element`` -- an element (of the poset)
1147
+
1148
+ - ``check`` -- boolean (default: ``True``); if set, then the
1149
+ ``can_merge``-function of :class:`MutablePoset` determines
1150
+ whether the merge is possible. ``can_merge`` is ``None`` means
1151
+ that this check is always passed.
1152
+
1153
+ - ``delete`` -- boolean (default: ``True``); if set, then ``element``
1154
+ is removed from the poset after the merge
1155
+
1156
+ OUTPUT: nothing
1157
+
1158
+ .. NOTE::
1159
+
1160
+ This operation depends on the parameters ``merge`` and
1161
+ ``can_merge`` of the :class:`MutablePoset` this shell is
1162
+ contained in. These parameters are defined when the poset
1163
+ is constructed.
1164
+
1165
+ .. NOTE::
1166
+
1167
+ If the ``merge`` function returns ``None``, then this shell
1168
+ is removed from the poset.
1169
+
1170
+ EXAMPLES::
1171
+
1172
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1173
+ sage: def add(left, right):
1174
+ ....: return (left[0], ''.join(sorted(left[1] + right[1])))
1175
+ sage: def can_add(left, right):
1176
+ ....: return left[0] <= right[0]
1177
+ sage: P = MP([(1, 'a'), (3, 'b'), (2, 'c'), (4, 'd')],
1178
+ ....: key=lambda c: c[0], merge=add, can_merge=can_add)
1179
+ sage: P
1180
+ poset((1, 'a'), (2, 'c'), (3, 'b'), (4, 'd'))
1181
+ sage: P.shell(2).merge((3, 'b'))
1182
+ sage: P
1183
+ poset((1, 'a'), (2, 'bc'), (4, 'd'))
1184
+
1185
+ .. SEEALSO::
1186
+
1187
+ :meth:`MutablePoset.merge`,
1188
+ :class:`MutablePoset`.
1189
+
1190
+ TESTS::
1191
+
1192
+ sage: MP([2], merge=operator.add,
1193
+ ....: can_merge=lambda _, __: False).shell(2).merge(1)
1194
+ Traceback (most recent call last):
1195
+ ...
1196
+ RuntimeError: Cannot merge 2 with 1.
1197
+ """
1198
+ poset = self.poset
1199
+ if poset._merge_ is None:
1200
+ # poset._merge_ is None means no merge (poset._merge_ simply
1201
+ # returns its first input argument).
1202
+ return
1203
+ self_element = self.element
1204
+ if check:
1205
+ if not poset._can_merge_(self_element, element):
1206
+ raise RuntimeError('Cannot merge %s with %s.' %
1207
+ (self_element, element))
1208
+ new = poset._merge_(self_element, element)
1209
+ if new is None:
1210
+ poset.discard(poset.get_key(self.element))
1211
+ else:
1212
+ self._element_ = new
1213
+ if delete:
1214
+ poset.remove(poset.get_key(element))
1215
+
1216
+
1217
+ # *****************************************************************************
1218
+
1219
+
1220
+ def is_MutablePoset(P):
1221
+ r"""
1222
+ Test whether ``P`` inherits from :class:`MutablePoset`.
1223
+
1224
+ .. SEEALSO::
1225
+
1226
+ :class:`MutablePoset`
1227
+
1228
+ TESTS::
1229
+
1230
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1231
+ sage: from sage.data_structures.mutable_poset import is_MutablePoset
1232
+ sage: P = MP()
1233
+ sage: is_MutablePoset(P)
1234
+ doctest:warning...
1235
+ DeprecationWarning: The function is_MutablePoset is deprecated; use 'isinstance(..., MutablePoset)' instead.
1236
+ See https://github.com/sagemath/sage/issues/38125 for details.
1237
+ True
1238
+ """
1239
+ from sage.misc.superseded import deprecation
1240
+ deprecation(38125,
1241
+ "The function is_MutablePoset is deprecated; "
1242
+ "use 'isinstance(..., MutablePoset)' instead.")
1243
+ return isinstance(P, MutablePoset)
1244
+
1245
+
1246
+ class MutablePoset(SageObject):
1247
+ r"""
1248
+ A data structure that models a mutable poset (partially ordered
1249
+ set).
1250
+
1251
+ INPUT:
1252
+
1253
+ - ``data`` -- data from which to construct the poset. It can be
1254
+ any of the following:
1255
+
1256
+ #. ``None`` (default), in which case an empty poset is created,
1257
+
1258
+ #. a :class:`MutablePoset`, which will be copied during creation,
1259
+
1260
+ #. an iterable, whose elements will be in the poset.
1261
+
1262
+ - ``key`` -- a function which maps elements to keys. If ``None``
1263
+ (default), this is the identity, i.e., keys are equal to their
1264
+ elements.
1265
+
1266
+ Two elements with the same keys are considered as equal; so only
1267
+ one of these two elements can be in the poset.
1268
+
1269
+ This ``key`` is not used for sorting (in contrast to
1270
+ sorting-functions, e.g. ``sorted``).
1271
+
1272
+ - ``merge`` -- a function which merges its second argument (an
1273
+ element) to its first (again an element) and returns the result
1274
+ (as an element). If the return value is ``None``, the element is
1275
+ removed from the poset.
1276
+
1277
+ This hook is called by :meth:`merge`. Moreover it is used during
1278
+ :meth:`add` when an element (more precisely its key) is already
1279
+ in this poset.
1280
+
1281
+ ``merge`` is ``None`` (default) is equivalent to ``merge``
1282
+ returning its first argument. Note that it is not allowed that the
1283
+ key of the returning element differs from the key of the first
1284
+ input parameter. This means ``merge`` must not change the
1285
+ position of the element in the poset.
1286
+
1287
+ - ``can_merge`` -- a function which checks whether its second argument
1288
+ can be merged to its first
1289
+
1290
+ This hook is called by :meth:`merge`. Moreover it is used during
1291
+ :meth:`add` when an element (more precisely its key) is already
1292
+ in this poset.
1293
+
1294
+ ``can_merge`` is ``None`` (default) is equivalent to ``can_merge``
1295
+ returning ``True`` in all cases.
1296
+
1297
+ OUTPUT: a mutable poset
1298
+
1299
+ You can find a short introduction and examples
1300
+ :mod:`here <sage.data_structures.mutable_poset>`.
1301
+
1302
+ EXAMPLES::
1303
+
1304
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1305
+
1306
+ We illustrate the different input formats
1307
+
1308
+ #. No input::
1309
+
1310
+ sage: A = MP(); A
1311
+ poset()
1312
+
1313
+ #. A :class:`MutablePoset`::
1314
+
1315
+ sage: B = MP(A); B
1316
+ poset()
1317
+ sage: B.add(42)
1318
+ sage: C = MP(B); C
1319
+ poset(42)
1320
+
1321
+ #. An iterable::
1322
+
1323
+ sage: C = MP([5, 3, 11]); C
1324
+ poset(3, 5, 11)
1325
+
1326
+ .. SEEALSO::
1327
+
1328
+ :class:`MutablePosetShell`.
1329
+ """
1330
+ def __init__(self, data=None, key=None, merge=None, can_merge=None):
1331
+ r"""
1332
+ See :class:`MutablePoset` for details.
1333
+
1334
+ TESTS::
1335
+
1336
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1337
+ sage: MP()
1338
+ poset()
1339
+
1340
+ ::
1341
+
1342
+ sage: P = MP()
1343
+ sage: P.add(42)
1344
+ sage: MP(P)
1345
+ poset(42)
1346
+
1347
+ ::
1348
+
1349
+ sage: MP([3, 5, 7])
1350
+ poset(3, 5, 7)
1351
+
1352
+ ::
1353
+
1354
+ sage: MP(33)
1355
+ Traceback (most recent call last):
1356
+ ...
1357
+ TypeError: 33 is not iterable; do not know what to do with it.
1358
+ """
1359
+ if isinstance(data, MutablePoset):
1360
+ if key is not None:
1361
+ raise TypeError('Cannot use key when data is a poset.')
1362
+ self._copy_shells_(data, lambda e: e)
1363
+
1364
+ else:
1365
+ self.clear()
1366
+
1367
+ if key is None:
1368
+ self._key_ = lambda k: k
1369
+ else:
1370
+ self._key_ = key
1371
+
1372
+ self._merge_ = merge
1373
+ if can_merge is None:
1374
+ self._can_merge_ = lambda _, __: True
1375
+ else:
1376
+ self._can_merge_ = can_merge
1377
+
1378
+ if data is not None:
1379
+ try:
1380
+ it = iter(data)
1381
+ except TypeError:
1382
+ raise TypeError('%s is not iterable; do not know what to '
1383
+ 'do with it.' % (data,))
1384
+ self.union_update(it)
1385
+ super().__init__()
1386
+
1387
+ def clear(self):
1388
+ r"""
1389
+ Remove all elements from this poset.
1390
+
1391
+ OUTPUT: nothing
1392
+
1393
+ .. SEEALSO::
1394
+
1395
+ :meth:`discard`,
1396
+ :meth:`pop`,
1397
+ :meth:`remove`.
1398
+
1399
+ TESTS::
1400
+
1401
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1402
+ sage: P = MP()
1403
+ sage: P.add(42); P
1404
+ poset(42)
1405
+ sage: P.clear()
1406
+ sage: print(P.repr_full())
1407
+ poset()
1408
+ +-- null
1409
+ | +-- no predecessors
1410
+ | +-- successors: oo
1411
+ +-- oo
1412
+ | +-- predecessors: null
1413
+ | +-- no successors
1414
+ """
1415
+ self._null_ = MutablePosetShell(self, None)
1416
+ self._oo_ = MutablePosetShell(self, None)
1417
+ self._null_.successors().add(self._oo_)
1418
+ self._oo_.predecessors().add(self._null_)
1419
+ self._shells_ = {}
1420
+
1421
+ def __len__(self):
1422
+ r"""
1423
+ Return the number of elements contained in this poset.
1424
+
1425
+ OUTPUT: integer
1426
+
1427
+ .. NOTE::
1428
+
1429
+ The special elements ``'null'`` and ``'oo'`` are not counted.
1430
+
1431
+ TESTS::
1432
+
1433
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1434
+ sage: P = MP()
1435
+ sage: len(P) # indirect doctest
1436
+ 0
1437
+ sage: bool(P)
1438
+ False
1439
+ sage: P.add(42)
1440
+ sage: len(P)
1441
+ 1
1442
+ sage: bool(P)
1443
+ True
1444
+ """
1445
+ return len(self._shells_)
1446
+
1447
+ @property
1448
+ def null(self):
1449
+ r"""
1450
+ The shell `\emptyset` whose element is smaller than any
1451
+ other element.
1452
+
1453
+ EXAMPLES::
1454
+
1455
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1456
+ sage: P = MP()
1457
+ sage: z = P.null; z
1458
+ null
1459
+ sage: z.is_null()
1460
+ True
1461
+
1462
+ .. SEEALSO::
1463
+
1464
+ :meth:`oo`,
1465
+ :meth:`MutablePosetShell.is_null`,
1466
+ :meth:`MutablePosetShell.is_special`.
1467
+ """
1468
+ return self._null_
1469
+
1470
+ @property
1471
+ def oo(self):
1472
+ r"""
1473
+ The shell `\infty` whose element is larger than any other
1474
+ element.
1475
+
1476
+ EXAMPLES::
1477
+
1478
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1479
+ sage: P = MP()
1480
+ sage: oo = P.oo; oo
1481
+ oo
1482
+ sage: oo.is_oo()
1483
+ True
1484
+
1485
+ .. SEEALSO::
1486
+
1487
+ :meth:`null`,
1488
+ :meth:`MutablePosetShell.is_oo`,
1489
+ :meth:`MutablePosetShell.is_special`.
1490
+ """
1491
+ return self._oo_
1492
+
1493
+ def shell(self, key):
1494
+ r"""
1495
+ Return the shell of the element corresponding to ``key``.
1496
+
1497
+ INPUT:
1498
+
1499
+ - ``key`` -- the key of an object
1500
+
1501
+ OUTPUT: an instance of :class:`MutablePosetShell`
1502
+
1503
+ .. NOTE::
1504
+
1505
+ Each element is contained/encapsulated in a shell inside
1506
+ the poset.
1507
+
1508
+ EXAMPLES::
1509
+
1510
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1511
+ sage: P = MP()
1512
+ sage: P.add(42)
1513
+ sage: e = P.shell(42); e
1514
+ 42
1515
+ sage: type(e)
1516
+ <class 'sage.data_structures.mutable_poset.MutablePosetShell'>
1517
+
1518
+ .. SEEALSO::
1519
+
1520
+ :meth:`element`,
1521
+ :meth:`get_key`.
1522
+ """
1523
+ return self._shells_[key]
1524
+
1525
+ def element(self, key):
1526
+ r"""
1527
+ Return the element corresponding to ``key``.
1528
+
1529
+ INPUT:
1530
+
1531
+ - ``key`` -- the key of an object
1532
+
1533
+ OUTPUT: an object
1534
+
1535
+ EXAMPLES::
1536
+
1537
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1538
+ sage: P = MP()
1539
+ sage: P.add(42)
1540
+ sage: e = P.element(42); e
1541
+ 42
1542
+ sage: type(e)
1543
+ <class 'sage.rings.integer.Integer'>
1544
+
1545
+ .. SEEALSO::
1546
+
1547
+ :meth:`shell`,
1548
+ :meth:`get_key`.
1549
+ """
1550
+ return self.shell(key).element
1551
+
1552
+ def get_key(self, element):
1553
+ r"""
1554
+ Return the key corresponding to the given element.
1555
+
1556
+ INPUT:
1557
+
1558
+ - ``element`` -- an object
1559
+
1560
+ OUTPUT: an object (the key of ``element``)
1561
+
1562
+ .. SEEALSO::
1563
+
1564
+ :meth:`element`,
1565
+ :meth:`shell`.
1566
+
1567
+ TESTS::
1568
+
1569
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1570
+ sage: P = MP()
1571
+ sage: P.get_key(None) is None
1572
+ True
1573
+ sage: P.get_key((1, 2))
1574
+ (1, 2)
1575
+ sage: Q = MP(key=lambda k: k[0])
1576
+ sage: Q.get_key((1, 2))
1577
+ 1
1578
+ """
1579
+ if element is None:
1580
+ return None
1581
+ return self._key_(element)
1582
+
1583
+ def _copy_shells_(self, other, mapping):
1584
+ r"""
1585
+ Copy shells from another poset.
1586
+
1587
+ INPUT:
1588
+
1589
+ - ``other`` -- the mutable poset from which the shells
1590
+ should be copied to this poset
1591
+
1592
+ - ``mapping`` -- a function that is applied to each element
1593
+
1594
+ OUTPUT: nothing
1595
+
1596
+ .. SEEALSO::
1597
+
1598
+ :meth:`copy`
1599
+
1600
+ TESTS::
1601
+
1602
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1603
+ sage: class T(tuple):
1604
+ ....: def __le__(left, right):
1605
+ ....: return all(l <= r for l, r in zip(left, right))
1606
+ sage: P = MP()
1607
+ sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
1608
+ ....: T((4, 4)), T((1, 2))])
1609
+ sage: Q = MP()
1610
+ sage: Q._copy_shells_(P, lambda e: e)
1611
+ sage: P.repr_full() == Q.repr_full()
1612
+ True
1613
+ """
1614
+ from copy import copy
1615
+ self._key_ = copy(other._key_)
1616
+ self._merge_ = copy(other._merge_)
1617
+ self._can_merge_ = copy(other._can_merge_)
1618
+ memo = {}
1619
+ self._null_ = other._null_._copy_all_linked_(memo, self, mapping)
1620
+ self._oo_ = memo[id(other._oo_)]
1621
+ self._shells_ = {f.key: f for f in iter(memo[id(e)] for e in
1622
+ other._shells_.values())}
1623
+
1624
+ def copy(self, mapping=None):
1625
+ r"""
1626
+ Create a shallow copy.
1627
+
1628
+ INPUT:
1629
+
1630
+ - ``mapping`` -- a function which is applied on each of the elements
1631
+
1632
+ OUTPUT: a poset with the same content as ``self``
1633
+
1634
+ .. SEEALSO::
1635
+
1636
+ :meth:`map`,
1637
+ :meth:`mapped`.
1638
+
1639
+ TESTS::
1640
+
1641
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1642
+ sage: class T(tuple):
1643
+ ....: def __le__(left, right):
1644
+ ....: return all(l <= r for l, r in zip(left, right))
1645
+ sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
1646
+ ....: T((4, 4)), T((1, 2))])
1647
+ sage: Q = copy(P) # indirect doctest
1648
+ sage: P.repr_full() == Q.repr_full()
1649
+ True
1650
+ """
1651
+ if mapping is None:
1652
+
1653
+ def mapping(element):
1654
+ return element
1655
+ new = self.__class__()
1656
+ new._copy_shells_(self, mapping)
1657
+ return new
1658
+
1659
+ __copy__ = copy
1660
+
1661
+ def shells(self, include_special=False):
1662
+ r"""
1663
+ Return an iterator over all shells.
1664
+
1665
+ INPUT:
1666
+
1667
+ - ``include_special`` -- boolean (default: ``False``); if set, then
1668
+ including shells containing a smallest element (`\emptyset`)
1669
+ and a largest element (`\infty`)
1670
+
1671
+ OUTPUT: an iterator
1672
+
1673
+ .. NOTE::
1674
+
1675
+ Each element is contained/encapsulated in a shell inside
1676
+ the poset.
1677
+
1678
+ EXAMPLES::
1679
+
1680
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1681
+ sage: P = MP()
1682
+ sage: tuple(P.shells())
1683
+ ()
1684
+ sage: tuple(P.shells(include_special=True))
1685
+ (null, oo)
1686
+
1687
+ .. SEEALSO::
1688
+
1689
+ :meth:`shells_topological`,
1690
+ :meth:`elements`,
1691
+ :meth:`elements_topological`,
1692
+ :meth:`keys`,
1693
+ :meth:`keys_topological`,
1694
+ :meth:`MutablePosetShell.iter_depth_first`,
1695
+ :meth:`MutablePosetShell.iter_topological`.
1696
+ """
1697
+ if include_special:
1698
+ yield self.null
1699
+ yield from self._shells_.values()
1700
+ if include_special:
1701
+ yield self.oo
1702
+
1703
+ def shells_topological(self, include_special=False,
1704
+ reverse=False, key=None):
1705
+ r"""
1706
+ Return an iterator over all shells in topological order.
1707
+
1708
+ INPUT:
1709
+
1710
+ - ``include_special`` -- boolean (default: ``False``); if set, then
1711
+ including shells containing a smallest element (`\emptyset`)
1712
+ and a largest element (`\infty`).
1713
+
1714
+ - ``reverse`` -- boolean (default: ``False``); if set, reverses the
1715
+ order, i.e., ``False`` gives smallest elements first,
1716
+ ``True`` gives largest first.
1717
+
1718
+ - ``key`` -- (default: ``None``) a function used for sorting
1719
+ the direct successors of a shell (used in case of a tie).
1720
+ If this is ``None``, no sorting occurs.
1721
+
1722
+ OUTPUT: an iterator
1723
+
1724
+ .. NOTE::
1725
+
1726
+ Each element is contained/encapsulated in a shell inside
1727
+ the poset.
1728
+
1729
+ EXAMPLES::
1730
+
1731
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1732
+ sage: class T(tuple):
1733
+ ....: def __le__(left, right):
1734
+ ....: return all(l <= r for l, r in zip(left, right))
1735
+ sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
1736
+ ....: T((4, 4)), T((1, 2)), T((2, 2))])
1737
+ sage: list(P.shells_topological(key=repr))
1738
+ [(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (4, 4)]
1739
+ sage: list(P.shells_topological(reverse=True, key=repr))
1740
+ [(4, 4), (1, 3), (2, 2), (1, 2), (2, 1), (1, 1)]
1741
+ sage: list(P.shells_topological(include_special=True, key=repr))
1742
+ [null, (1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (4, 4), oo]
1743
+ sage: list(P.shells_topological(
1744
+ ....: include_special=True, reverse=True, key=repr))
1745
+ [oo, (4, 4), (1, 3), (2, 2), (1, 2), (2, 1), (1, 1), null]
1746
+
1747
+ .. SEEALSO::
1748
+
1749
+ :meth:`shells`,
1750
+ :meth:`elements`,
1751
+ :meth:`elements_topological`,
1752
+ :meth:`keys`,
1753
+ :meth:`keys_topological`,
1754
+ :meth:`MutablePosetShell.iter_depth_first`,
1755
+ :meth:`MutablePosetShell.iter_topological`.
1756
+ """
1757
+ shell = self.oo if not reverse else self.null
1758
+ return iter(e for e in shell.iter_topological(reverse, key)
1759
+ if include_special or not e.is_special())
1760
+
1761
+ def elements(self, **kwargs):
1762
+ r"""
1763
+ Return an iterator over all elements.
1764
+
1765
+ INPUT:
1766
+
1767
+ - ``kwargs`` -- arguments are passed to :meth:`shells`
1768
+
1769
+ EXAMPLES::
1770
+
1771
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1772
+ sage: P = MP([3, 42, 7])
1773
+ sage: [(v, type(v)) for v in sorted(P.elements())]
1774
+ [(3, <class 'sage.rings.integer.Integer'>),
1775
+ (7, <class 'sage.rings.integer.Integer'>),
1776
+ (42, <class 'sage.rings.integer.Integer'>)]
1777
+
1778
+ Note that
1779
+
1780
+ ::
1781
+
1782
+ sage: it = iter(P)
1783
+ sage: sorted(it)
1784
+ [3, 7, 42]
1785
+
1786
+ returns all elements as well.
1787
+
1788
+ .. SEEALSO::
1789
+
1790
+ :meth:`shells`,
1791
+ :meth:`shells_topological`,
1792
+ :meth:`elements_topological`,
1793
+ :meth:`keys`,
1794
+ :meth:`keys_topological`,
1795
+ :meth:`MutablePosetShell.iter_depth_first`,
1796
+ :meth:`MutablePosetShell.iter_topological`.
1797
+ """
1798
+ for shell in self.shells(**kwargs):
1799
+ yield shell.element
1800
+
1801
+ __iter__ = elements
1802
+
1803
+ def elements_topological(self, **kwargs):
1804
+ r"""
1805
+ Return an iterator over all elements in topological order.
1806
+
1807
+ INPUT:
1808
+
1809
+ - ``kwargs`` -- arguments are passed to :meth:`shells_topological`
1810
+
1811
+ EXAMPLES::
1812
+
1813
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1814
+ sage: class T(tuple):
1815
+ ....: def __le__(left, right):
1816
+ ....: return all(l <= r for l, r in zip(left, right))
1817
+ sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
1818
+ ....: T((4, 4)), T((1, 2)), T((2, 2))])
1819
+ sage: [(v, type(v)) for v in P.elements_topological(key=repr)]
1820
+ [((1, 1), <class '__main__.T'>),
1821
+ ((1, 2), <class '__main__.T'>),
1822
+ ((1, 3), <class '__main__.T'>),
1823
+ ((2, 1), <class '__main__.T'>),
1824
+ ((2, 2), <class '__main__.T'>),
1825
+ ((4, 4), <class '__main__.T'>)]
1826
+
1827
+ .. SEEALSO::
1828
+
1829
+ :meth:`shells`,
1830
+ :meth:`shells_topological`,
1831
+ :meth:`elements`,
1832
+ :meth:`keys`,
1833
+ :meth:`keys_topological`,
1834
+ :meth:`MutablePosetShell.iter_depth_first`,
1835
+ :meth:`MutablePosetShell.iter_topological`.
1836
+ """
1837
+ for shell in self.shells_topological(**kwargs):
1838
+ yield shell.element
1839
+
1840
+ def keys(self, **kwargs):
1841
+ r"""
1842
+ Return an iterator over all keys of the elements.
1843
+
1844
+ INPUT:
1845
+
1846
+ - ``kwargs`` -- arguments are passed to :meth:`shells`
1847
+
1848
+ EXAMPLES::
1849
+
1850
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1851
+ sage: P = MP([3, 42, 7], key=lambda c: -c)
1852
+ sage: [(v, type(v)) for v in sorted(P.keys())]
1853
+ [(-42, <class 'sage.rings.integer.Integer'>),
1854
+ (-7, <class 'sage.rings.integer.Integer'>),
1855
+ (-3, <class 'sage.rings.integer.Integer'>)]
1856
+
1857
+ sage: [(v, type(v)) for v in sorted(P.elements())]
1858
+ [(3, <class 'sage.rings.integer.Integer'>),
1859
+ (7, <class 'sage.rings.integer.Integer'>),
1860
+ (42, <class 'sage.rings.integer.Integer'>)]
1861
+
1862
+ sage: [(v, type(v)) for v in sorted(P.shells(),
1863
+ ....: key=lambda c: c.element)]
1864
+ [(3, <class 'sage.data_structures.mutable_poset.MutablePosetShell'>),
1865
+ (7, <class 'sage.data_structures.mutable_poset.MutablePosetShell'>),
1866
+ (42, <class 'sage.data_structures.mutable_poset.MutablePosetShell'>)]
1867
+
1868
+ .. SEEALSO::
1869
+
1870
+ :meth:`shells`,
1871
+ :meth:`shells_topological`,
1872
+ :meth:`elements`,
1873
+ :meth:`elements_topological`,
1874
+ :meth:`keys_topological`,
1875
+ :meth:`MutablePosetShell.iter_depth_first`,
1876
+ :meth:`MutablePosetShell.iter_topological`.
1877
+ """
1878
+ for shell in self.shells(**kwargs):
1879
+ yield shell.key
1880
+
1881
+ def keys_topological(self, **kwargs):
1882
+ r"""
1883
+ Return an iterator over all keys of the elements in
1884
+ topological order.
1885
+
1886
+ INPUT:
1887
+
1888
+ - ``kwargs`` -- arguments are passed to :meth:`shells_topological`
1889
+
1890
+ EXAMPLES::
1891
+
1892
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1893
+ sage: P = MP([(1, 1), (2, 1), (4, 4)],
1894
+ ....: key=lambda c: c[0])
1895
+ sage: [(v, type(v)) for v in P.keys_topological(key=repr)]
1896
+ [(1, <class 'sage.rings.integer.Integer'>),
1897
+ (2, <class 'sage.rings.integer.Integer'>),
1898
+ (4, <class 'sage.rings.integer.Integer'>)]
1899
+ sage: [(v, type(v)) for v in P.elements_topological(key=repr)]
1900
+ [((1, 1), <... 'tuple'>),
1901
+ ((2, 1), <... 'tuple'>),
1902
+ ((4, 4), <... 'tuple'>)]
1903
+ sage: [(v, type(v)) for v in P.shells_topological(key=repr)]
1904
+ [((1, 1), <class 'sage.data_structures.mutable_poset.MutablePosetShell'>),
1905
+ ((2, 1), <class 'sage.data_structures.mutable_poset.MutablePosetShell'>),
1906
+ ((4, 4), <class 'sage.data_structures.mutable_poset.MutablePosetShell'>)]
1907
+
1908
+ .. SEEALSO::
1909
+
1910
+ :meth:`shells`,
1911
+ :meth:`shells_topological`,
1912
+ :meth:`elements`,
1913
+ :meth:`elements_topological`,
1914
+ :meth:`keys`,
1915
+ :meth:`MutablePosetShell.iter_depth_first`,
1916
+ :meth:`MutablePosetShell.iter_topological`.
1917
+ """
1918
+ for shell in self.shells_topological(**kwargs):
1919
+ yield shell.key
1920
+
1921
+ def repr(self, include_special=False, reverse=False):
1922
+ r"""
1923
+ Return a representation of the poset.
1924
+
1925
+ INPUT:
1926
+
1927
+ - ``include_special`` -- boolean (default: ``False``); whether to
1928
+ include the special elements ``'null'`` and ``'oo'`` or not
1929
+
1930
+ - ``reverse`` -- boolean (default: ``False``); if set, then
1931
+ largest elements are displayed first
1932
+
1933
+ OUTPUT: string
1934
+
1935
+ .. SEEALSO::
1936
+
1937
+ :meth:`repr_full`
1938
+
1939
+ TESTS::
1940
+
1941
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1942
+ sage: print(MP().repr())
1943
+ poset()
1944
+ """
1945
+ s = 'poset('
1946
+ s += ', '.join(repr(shell) for shell in
1947
+ self.shells_topological(include_special, reverse,
1948
+ key=repr))
1949
+ s += ')'
1950
+ return s
1951
+
1952
+ def repr_full(self, reverse=False):
1953
+ r"""
1954
+ Return a representation with ordering details of the poset.
1955
+
1956
+ INPUT:
1957
+
1958
+ - ``reverse`` -- boolean (default: ``False``); if set, then
1959
+ largest elements are displayed first
1960
+
1961
+ OUTPUT: string
1962
+
1963
+ .. SEEALSO::
1964
+
1965
+ :meth:`repr`
1966
+
1967
+ TESTS::
1968
+
1969
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
1970
+ sage: print(MP().repr_full(reverse=True))
1971
+ poset()
1972
+ +-- oo
1973
+ | +-- no successors
1974
+ | +-- predecessors: null
1975
+ +-- null
1976
+ | +-- successors: oo
1977
+ | +-- no predecessors
1978
+ """
1979
+ sortedshells = tuple(
1980
+ self.shells_topological(include_special=True,
1981
+ reverse=reverse,
1982
+ key=repr))
1983
+ strings = [self.repr(include_special=False, reverse=reverse)]
1984
+ for shell in sortedshells:
1985
+ strings.append('+-- ' + repr(shell))
1986
+ for rev in (not reverse, reverse):
1987
+ what = 'successors' if not rev else 'predecessors'
1988
+ if shell.successors(rev):
1989
+ s = '| +-- ' + what + ': '
1990
+ s += ', '.join(repr(e) for e in
1991
+ sortedshells if e in shell.successors(rev))
1992
+ else:
1993
+ s = '| +-- no ' + what
1994
+ strings.append(s)
1995
+ return '\n'.join(strings)
1996
+
1997
+ _repr_ = repr
1998
+
1999
+ def contains(self, key):
2000
+ r"""
2001
+ Test whether ``key`` is encapsulated by one of the poset's elements.
2002
+
2003
+ INPUT:
2004
+
2005
+ - ``key`` -- an object
2006
+
2007
+ OUTPUT: boolean
2008
+
2009
+ .. SEEALSO::
2010
+
2011
+ :meth:`shells`,
2012
+ :meth:`elements`,
2013
+ :meth:`keys`.
2014
+
2015
+ TESTS::
2016
+
2017
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
2018
+ sage: class T(tuple):
2019
+ ....: def __le__(left, right):
2020
+ ....: return all(l <= r for l, r in zip(left, right))
2021
+ sage: P = MP()
2022
+ sage: P.add(T((1, 1)))
2023
+ sage: T((1, 1)) in P # indirect doctest
2024
+ True
2025
+ sage: T((1, 2)) in P # indirect doctest
2026
+ False
2027
+ """
2028
+ return key in self._shells_
2029
+
2030
+ __contains__ = contains
2031
+
2032
+ def add(self, element):
2033
+ r"""
2034
+ Add the given object as element to the poset.
2035
+
2036
+ INPUT:
2037
+
2038
+ - ``element`` -- an object (hashable and supporting comparison
2039
+ with the operator ``<=``)
2040
+
2041
+ OUTPUT: nothing
2042
+
2043
+ EXAMPLES::
2044
+
2045
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
2046
+ sage: class T(tuple):
2047
+ ....: def __le__(left, right):
2048
+ ....: return all(l <= r for l, r in zip(left, right))
2049
+ sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
2050
+ ....: T((4, 4)), T((1, 2))])
2051
+ sage: print(P.repr_full(reverse=True))
2052
+ poset((4, 4), (1, 3), (1, 2), (2, 1), (1, 1))
2053
+ +-- oo
2054
+ | +-- no successors
2055
+ | +-- predecessors: (4, 4)
2056
+ +-- (4, 4)
2057
+ | +-- successors: oo
2058
+ | +-- predecessors: (1, 3), (2, 1)
2059
+ +-- (1, 3)
2060
+ | +-- successors: (4, 4)
2061
+ | +-- predecessors: (1, 2)
2062
+ +-- (1, 2)
2063
+ | +-- successors: (1, 3)
2064
+ | +-- predecessors: (1, 1)
2065
+ +-- (2, 1)
2066
+ | +-- successors: (4, 4)
2067
+ | +-- predecessors: (1, 1)
2068
+ +-- (1, 1)
2069
+ | +-- successors: (1, 2), (2, 1)
2070
+ | +-- predecessors: null
2071
+ +-- null
2072
+ | +-- successors: (1, 1)
2073
+ | +-- no predecessors
2074
+ sage: P.add(T((2, 2)))
2075
+ sage: reprP = P.repr_full(reverse=True); print(reprP)
2076
+ poset((4, 4), (1, 3), (2, 2), (1, 2), (2, 1), (1, 1))
2077
+ +-- oo
2078
+ | +-- no successors
2079
+ | +-- predecessors: (4, 4)
2080
+ +-- (4, 4)
2081
+ | +-- successors: oo
2082
+ | +-- predecessors: (1, 3), (2, 2)
2083
+ +-- (1, 3)
2084
+ | +-- successors: (4, 4)
2085
+ | +-- predecessors: (1, 2)
2086
+ +-- (2, 2)
2087
+ | +-- successors: (4, 4)
2088
+ | +-- predecessors: (1, 2), (2, 1)
2089
+ +-- (1, 2)
2090
+ | +-- successors: (1, 3), (2, 2)
2091
+ | +-- predecessors: (1, 1)
2092
+ +-- (2, 1)
2093
+ | +-- successors: (2, 2)
2094
+ | +-- predecessors: (1, 1)
2095
+ +-- (1, 1)
2096
+ | +-- successors: (1, 2), (2, 1)
2097
+ | +-- predecessors: null
2098
+ +-- null
2099
+ | +-- successors: (1, 1)
2100
+ | +-- no predecessors
2101
+
2102
+ When adding an element which is already in the poset, nothing happens::
2103
+
2104
+ sage: e = T((2, 2))
2105
+ sage: P.add(e)
2106
+ sage: P.repr_full(reverse=True) == reprP
2107
+ True
2108
+
2109
+ We can influence the behavior when an element with existing key
2110
+ is to be inserted in the poset. For example, we can perform an
2111
+ addition on some argument of the elements::
2112
+
2113
+ sage: def add(left, right):
2114
+ ....: return (left[0], ''.join(sorted(left[1] + right[1])))
2115
+ sage: A = MP(key=lambda k: k[0], merge=add)
2116
+ sage: A.add((3, 'a'))
2117
+ sage: A
2118
+ poset((3, 'a'))
2119
+ sage: A.add((3, 'b'))
2120
+ sage: A
2121
+ poset((3, 'ab'))
2122
+
2123
+ We can also deal with cancellations. If the return value of
2124
+ our hook-function is ``None``, then the element is removed out of
2125
+ the poset::
2126
+
2127
+ sage: def add_None(left, right):
2128
+ ....: s = left[1] + right[1]
2129
+ ....: if s == 0:
2130
+ ....: return None
2131
+ ....: return (left[0], s)
2132
+ sage: B = MP(key=lambda k: k[0],
2133
+ ....: merge=add_None)
2134
+ sage: B.add((7, 42))
2135
+ sage: B.add((7, -42))
2136
+ sage: B
2137
+ poset()
2138
+
2139
+ .. SEEALSO::
2140
+
2141
+ :meth:`discard`,
2142
+ :meth:`pop`,
2143
+ :meth:`remove`.
2144
+
2145
+ TESTS::
2146
+
2147
+ sage: R = MP([(1, 1, 42), (1, 3, 42), (2, 1, 7),
2148
+ ....: (4, 4, 42), (1, 2, 7), (2, 2, 7)],
2149
+ ....: key=lambda k: T(k[2:3]))
2150
+ sage: print(R.repr_full(reverse=True))
2151
+ poset((1, 1, 42), (2, 1, 7))
2152
+ +-- oo
2153
+ | +-- no successors
2154
+ | +-- predecessors: (1, 1, 42)
2155
+ +-- (1, 1, 42)
2156
+ | +-- successors: oo
2157
+ | +-- predecessors: (2, 1, 7)
2158
+ +-- (2, 1, 7)
2159
+ | +-- successors: (1, 1, 42)
2160
+ | +-- predecessors: null
2161
+ +-- null
2162
+ | +-- successors: (2, 1, 7)
2163
+ | +-- no predecessors
2164
+
2165
+ ::
2166
+
2167
+ sage: P = MP()
2168
+ sage: P.add(None)
2169
+ Traceback (most recent call last):
2170
+ ...
2171
+ ValueError: None is not an allowed element.
2172
+ """
2173
+ if element is None:
2174
+ raise ValueError('None is not an allowed element.')
2175
+ key = self.get_key(element)
2176
+
2177
+ if key in self._shells_:
2178
+ if self._merge_ is not None:
2179
+ self.shell(key).merge(element, delete=False)
2180
+ return
2181
+
2182
+ new = MutablePosetShell(self, element)
2183
+ new._predecessors_ = self.null.lower_covers(new)
2184
+ new._successors_ = self.oo.upper_covers(new)
2185
+
2186
+ for s in new.predecessors():
2187
+ for l in s.successors().intersection(new.successors()):
2188
+ l.predecessors().remove(s)
2189
+ s.successors().remove(l)
2190
+ s.successors().add(new)
2191
+ for l in new.successors():
2192
+ l.predecessors().add(new)
2193
+
2194
+ self._shells_[key] = new
2195
+
2196
+ def remove(self, key, raise_key_error=True):
2197
+ r"""
2198
+ Remove the given object from the poset.
2199
+
2200
+ INPUT:
2201
+
2202
+ - ``key`` -- the key of an object
2203
+
2204
+ - ``raise_key_error`` -- boolean (default: ``True``); switch raising
2205
+ :exc:`KeyError` on and off
2206
+
2207
+ OUTPUT: nothing
2208
+
2209
+ If the element is not a member and ``raise_key_error`` is set
2210
+ (default), raise a :exc:`KeyError`.
2211
+
2212
+ .. NOTE::
2213
+
2214
+ As with Python's ``set``, the methods :meth:`remove`
2215
+ and :meth:`discard` only differ in their behavior when an
2216
+ element is not contained in the poset: :meth:`remove`
2217
+ raises a :exc:`KeyError` whereas :meth:`discard` does not
2218
+ raise any exception.
2219
+
2220
+ This default behavior can be overridden with the
2221
+ ``raise_key_error`` parameter.
2222
+
2223
+ EXAMPLES::
2224
+
2225
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
2226
+ sage: class T(tuple):
2227
+ ....: def __le__(left, right):
2228
+ ....: return all(l <= r for l, r in zip(left, right))
2229
+ sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
2230
+ ....: T((4, 4)), T((1, 2)), T((2, 2))])
2231
+ sage: print(P.repr_full(reverse=True))
2232
+ poset((4, 4), (1, 3), (2, 2), (1, 2), (2, 1), (1, 1))
2233
+ +-- oo
2234
+ | +-- no successors
2235
+ | +-- predecessors: (4, 4)
2236
+ +-- (4, 4)
2237
+ | +-- successors: oo
2238
+ | +-- predecessors: (1, 3), (2, 2)
2239
+ +-- (1, 3)
2240
+ | +-- successors: (4, 4)
2241
+ | +-- predecessors: (1, 2)
2242
+ +-- (2, 2)
2243
+ | +-- successors: (4, 4)
2244
+ | +-- predecessors: (1, 2), (2, 1)
2245
+ +-- (1, 2)
2246
+ | +-- successors: (1, 3), (2, 2)
2247
+ | +-- predecessors: (1, 1)
2248
+ +-- (2, 1)
2249
+ | +-- successors: (2, 2)
2250
+ | +-- predecessors: (1, 1)
2251
+ +-- (1, 1)
2252
+ | +-- successors: (1, 2), (2, 1)
2253
+ | +-- predecessors: null
2254
+ +-- null
2255
+ | +-- successors: (1, 1)
2256
+ | +-- no predecessors
2257
+ sage: P.remove(T((1, 2)))
2258
+ sage: print(P.repr_full(reverse=True))
2259
+ poset((4, 4), (1, 3), (2, 2), (2, 1), (1, 1))
2260
+ +-- oo
2261
+ | +-- no successors
2262
+ | +-- predecessors: (4, 4)
2263
+ +-- (4, 4)
2264
+ | +-- successors: oo
2265
+ | +-- predecessors: (1, 3), (2, 2)
2266
+ +-- (1, 3)
2267
+ | +-- successors: (4, 4)
2268
+ | +-- predecessors: (1, 1)
2269
+ +-- (2, 2)
2270
+ | +-- successors: (4, 4)
2271
+ | +-- predecessors: (2, 1)
2272
+ +-- (2, 1)
2273
+ | +-- successors: (2, 2)
2274
+ | +-- predecessors: (1, 1)
2275
+ +-- (1, 1)
2276
+ | +-- successors: (1, 3), (2, 1)
2277
+ | +-- predecessors: null
2278
+ +-- null
2279
+ | +-- successors: (1, 1)
2280
+ | +-- no predecessors
2281
+
2282
+ .. SEEALSO::
2283
+
2284
+ :meth:`add`,
2285
+ :meth:`clear`,
2286
+ :meth:`discard`,
2287
+ :meth:`pop`.
2288
+
2289
+ TESTS::
2290
+
2291
+ sage: Q = MP([(1, 1, 42), (1, 3, 42), (2, 1, 7),
2292
+ ....: (4, 4, 42), (1, 2, 7), (2, 2, 7)],
2293
+ ....: key=lambda k: T(k[0:2]))
2294
+ sage: print(Q.repr_full(reverse=True))
2295
+ poset((4, 4, 42), (1, 3, 42), (2, 2, 7),
2296
+ (1, 2, 7), (2, 1, 7), (1, 1, 42))
2297
+ +-- oo
2298
+ | +-- no successors
2299
+ | +-- predecessors: (4, 4, 42)
2300
+ +-- (4, 4, 42)
2301
+ | +-- successors: oo
2302
+ | +-- predecessors: (1, 3, 42), (2, 2, 7)
2303
+ +-- (1, 3, 42)
2304
+ | +-- successors: (4, 4, 42)
2305
+ | +-- predecessors: (1, 2, 7)
2306
+ +-- (2, 2, 7)
2307
+ | +-- successors: (4, 4, 42)
2308
+ | +-- predecessors: (1, 2, 7), (2, 1, 7)
2309
+ +-- (1, 2, 7)
2310
+ | +-- successors: (1, 3, 42), (2, 2, 7)
2311
+ | +-- predecessors: (1, 1, 42)
2312
+ +-- (2, 1, 7)
2313
+ | +-- successors: (2, 2, 7)
2314
+ | +-- predecessors: (1, 1, 42)
2315
+ +-- (1, 1, 42)
2316
+ | +-- successors: (1, 2, 7), (2, 1, 7)
2317
+ | +-- predecessors: null
2318
+ +-- null
2319
+ | +-- successors: (1, 1, 42)
2320
+ | +-- no predecessors
2321
+ sage: Q.remove((1,1))
2322
+ sage: print(Q.repr_full(reverse=True))
2323
+ poset((4, 4, 42), (1, 3, 42), (2, 2, 7), (1, 2, 7), (2, 1, 7))
2324
+ +-- oo
2325
+ | +-- no successors
2326
+ | +-- predecessors: (4, 4, 42)
2327
+ +-- (4, 4, 42)
2328
+ | +-- successors: oo
2329
+ | +-- predecessors: (1, 3, 42), (2, 2, 7)
2330
+ +-- (1, 3, 42)
2331
+ | +-- successors: (4, 4, 42)
2332
+ | +-- predecessors: (1, 2, 7)
2333
+ +-- (2, 2, 7)
2334
+ | +-- successors: (4, 4, 42)
2335
+ | +-- predecessors: (1, 2, 7), (2, 1, 7)
2336
+ +-- (1, 2, 7)
2337
+ | +-- successors: (1, 3, 42), (2, 2, 7)
2338
+ | +-- predecessors: null
2339
+ +-- (2, 1, 7)
2340
+ | +-- successors: (2, 2, 7)
2341
+ | +-- predecessors: null
2342
+ +-- null
2343
+ | +-- successors: (1, 2, 7), (2, 1, 7)
2344
+ | +-- no predecessors
2345
+
2346
+ ::
2347
+
2348
+ sage: P = MP()
2349
+ sage: P.remove(None)
2350
+ Traceback (most recent call last):
2351
+ ...
2352
+ ValueError: None is not an allowed key.
2353
+ """
2354
+ if key is None:
2355
+ raise ValueError('None is not an allowed key.')
2356
+
2357
+ try:
2358
+ shell = self._shells_[key]
2359
+ except KeyError:
2360
+ if not raise_key_error:
2361
+ return
2362
+ raise KeyError('Key %s is not contained in this poset.' % (key,))
2363
+
2364
+ for reverse in (False, True):
2365
+ for p in shell.predecessors(reverse):
2366
+ S = p.successors(reverse)
2367
+ S.remove(shell)
2368
+ D = set(s for s in p.iter_depth_first(reverse)
2369
+ if s in shell.successors(reverse))
2370
+ S.update(shell.successors(reverse))
2371
+ S.difference_update(D)
2372
+ del self._shells_[key]
2373
+
2374
+ def discard(self, key, raise_key_error=False):
2375
+ r"""
2376
+ Remove the given object from the poset.
2377
+
2378
+ INPUT:
2379
+
2380
+ - ``key`` -- the key of an object
2381
+
2382
+ - ``raise_key_error`` -- boolean (default: ``False``); switch raising
2383
+ :exc:`KeyError` on and off
2384
+
2385
+ OUTPUT: nothing
2386
+
2387
+ If the element is not a member and ``raise_key_error`` is set
2388
+ (not default), raise a :exc:`KeyError`.
2389
+
2390
+ .. NOTE::
2391
+
2392
+ As with Python's ``set``, the methods :meth:`remove`
2393
+ and :meth:`discard` only differ in their behavior when an
2394
+ element is not contained in the poset: :meth:`remove`
2395
+ raises a :exc:`KeyError` whereas :meth:`discard` does not
2396
+ raise any exception.
2397
+
2398
+ This default behavior can be overridden with the
2399
+ ``raise_key_error`` parameter.
2400
+
2401
+ EXAMPLES::
2402
+
2403
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
2404
+ sage: class T(tuple):
2405
+ ....: def __le__(left, right):
2406
+ ....: return all(l <= r for l, r in zip(left, right))
2407
+ sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
2408
+ ....: T((4, 4)), T((1, 2)), T((2, 2))])
2409
+ sage: P.discard(T((1, 2)))
2410
+ sage: P.remove(T((1, 2)))
2411
+ Traceback (most recent call last):
2412
+ ...
2413
+ KeyError: 'Key (1, 2) is not contained in this poset.'
2414
+ sage: P.discard(T((1, 2)))
2415
+
2416
+ .. SEEALSO::
2417
+
2418
+ :meth:`add`,
2419
+ :meth:`clear`,
2420
+ :meth:`remove`,
2421
+ :meth:`pop`.
2422
+ """
2423
+ return self.remove(key, raise_key_error)
2424
+
2425
+ def pop(self, **kwargs):
2426
+ r"""
2427
+ Remove and return an arbitrary poset element.
2428
+
2429
+ INPUT:
2430
+
2431
+ - ``kwargs`` -- arguments are passed to :meth:`shells_topological`
2432
+
2433
+ OUTPUT: an object
2434
+
2435
+ .. NOTE::
2436
+
2437
+ The special elements ``'null'`` and ``'oo'`` cannot be popped.
2438
+
2439
+ EXAMPLES::
2440
+
2441
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
2442
+ sage: P = MP()
2443
+ sage: P.add(3)
2444
+ sage: P
2445
+ poset(3)
2446
+ sage: P.pop()
2447
+ 3
2448
+ sage: P
2449
+ poset()
2450
+ sage: P.pop()
2451
+ Traceback (most recent call last):
2452
+ ...
2453
+ KeyError: 'pop from an empty poset'
2454
+
2455
+ .. SEEALSO::
2456
+
2457
+ :meth:`add`,
2458
+ :meth:`clear`,
2459
+ :meth:`discard`,
2460
+ :meth:`remove`.
2461
+ """
2462
+ kwargs['include_special'] = False
2463
+
2464
+ try:
2465
+ shell = next(self.shells_topological(**kwargs))
2466
+ except StopIteration:
2467
+ raise KeyError('pop from an empty poset')
2468
+ self.remove(shell.key)
2469
+ return shell.element
2470
+
2471
+ def union(self, *other):
2472
+ r"""
2473
+ Return the union of the given posets as a new poset.
2474
+
2475
+ INPUT:
2476
+
2477
+ - ``other`` -- a poset or an iterable. In the latter case the
2478
+ iterated objects are seen as elements of a poset.
2479
+ It is possible to specify more than one ``other`` as
2480
+ variadic arguments (arbitrary argument lists).
2481
+
2482
+ .. NOTE::
2483
+
2484
+ The key of an element is used for comparison. Thus elements with
2485
+ the same key are considered as equal.
2486
+
2487
+ Due to keys and a ``merge`` function (see :class:`MutablePoset`)
2488
+ this operation might not be commutative.
2489
+
2490
+ .. TODO::
2491
+
2492
+ Use the already existing information in the other poset to speed
2493
+ up this function. (At the moment each element of the other poset
2494
+ is inserted one by one and without using this information.)
2495
+
2496
+ EXAMPLES::
2497
+
2498
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
2499
+ sage: P = MP([3, 42, 7]); P
2500
+ poset(3, 7, 42)
2501
+ sage: Q = MP([4, 8, 42]); Q
2502
+ poset(4, 8, 42)
2503
+ sage: P.union(Q)
2504
+ poset(3, 4, 7, 8, 42)
2505
+
2506
+ .. SEEALSO::
2507
+
2508
+ :meth:`union_update`,
2509
+ :meth:`difference`, :meth:`difference_update`,
2510
+ :meth:`intersection`, :meth:`intersection_update`,
2511
+ :meth:`symmetric_difference`, :meth:`symmetric_difference_update`,
2512
+ :meth:`is_disjoint`,
2513
+ :meth:`is_subset`,
2514
+ :meth:`is_superset`.
2515
+
2516
+ TESTS::
2517
+
2518
+ sage: P.union(P, Q, Q, P)
2519
+ poset(3, 4, 7, 8, 42)
2520
+ """
2521
+ new = self.copy()
2522
+ new.update(*other)
2523
+ return new
2524
+
2525
+ def union_update(self, *other):
2526
+ r"""
2527
+ Update this poset with the union of itself and another poset.
2528
+
2529
+ INPUT:
2530
+
2531
+ - ``other`` -- a poset or an iterable. In the latter case the
2532
+ iterated objects are seen as elements of a poset.
2533
+ It is possible to specify more than one ``other`` as
2534
+ variadic arguments (arbitrary argument lists).
2535
+
2536
+ OUTPUT: nothing
2537
+
2538
+ .. NOTE::
2539
+
2540
+ The key of an element is used for comparison. Thus elements with
2541
+ the same key are considered as equal;
2542
+ ``A.union_update(B)`` and ``B.union_update(A)`` might
2543
+ result in different posets.
2544
+
2545
+ .. TODO::
2546
+
2547
+ Use the already existing information in the other poset to speed
2548
+ up this function. (At the moment each element of the other poset
2549
+ is inserted one by one and without using this information.)
2550
+
2551
+ EXAMPLES::
2552
+
2553
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
2554
+ sage: P = MP([3, 42, 7]); P
2555
+ poset(3, 7, 42)
2556
+ sage: Q = MP([4, 8, 42]); Q
2557
+ poset(4, 8, 42)
2558
+ sage: P.union_update(Q)
2559
+ sage: P
2560
+ poset(3, 4, 7, 8, 42)
2561
+
2562
+ .. SEEALSO::
2563
+
2564
+ :meth:`union`,
2565
+ :meth:`difference`, :meth:`difference_update`,
2566
+ :meth:`intersection`, :meth:`intersection_update`,
2567
+ :meth:`symmetric_difference`, :meth:`symmetric_difference_update`,
2568
+ :meth:`is_disjoint`,
2569
+ :meth:`is_subset`,
2570
+ :meth:`is_superset`.
2571
+
2572
+ TESTS::
2573
+
2574
+ sage: Q.update(P)
2575
+ sage: Q
2576
+ poset(3, 4, 7, 8, 42)
2577
+ """
2578
+ for o in other:
2579
+ try:
2580
+ it = o.elements()
2581
+ except AttributeError:
2582
+ it = iter(o)
2583
+ for element in it:
2584
+ self.add(element)
2585
+
2586
+ update = union_update # as in a Python set
2587
+ r"""
2588
+ Alias of :meth:`union_update`.
2589
+ """
2590
+
2591
+ def difference(self, *other):
2592
+ r"""
2593
+ Return a new poset where all elements of this poset, which are
2594
+ contained in one of the other given posets, are removed.
2595
+
2596
+ INPUT:
2597
+
2598
+ - ``other`` -- a poset or an iterable. In the latter case the
2599
+ iterated objects are seen as elements of a poset.
2600
+ It is possible to specify more than one ``other`` as
2601
+ variadic arguments (arbitrary argument lists).
2602
+
2603
+ .. NOTE::
2604
+
2605
+ The key of an element is used for comparison. Thus elements with
2606
+ the same key are considered as equal.
2607
+
2608
+ EXAMPLES::
2609
+
2610
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
2611
+ sage: P = MP([3, 42, 7]); P
2612
+ poset(3, 7, 42)
2613
+ sage: Q = MP([4, 8, 42]); Q
2614
+ poset(4, 8, 42)
2615
+ sage: P.difference(Q)
2616
+ poset(3, 7)
2617
+
2618
+ .. SEEALSO::
2619
+
2620
+ :meth:`union`, :meth:`union_update`,
2621
+ :meth:`difference_update`,
2622
+ :meth:`intersection`, :meth:`intersection_update`,
2623
+ :meth:`symmetric_difference`, :meth:`symmetric_difference_update`,
2624
+ :meth:`is_disjoint`,
2625
+ :meth:`is_subset`,
2626
+ :meth:`is_superset`.
2627
+
2628
+ TESTS::
2629
+
2630
+ sage: P.difference(Q, Q)
2631
+ poset(3, 7)
2632
+ sage: P.difference(P)
2633
+ poset()
2634
+ sage: P.difference(Q, P)
2635
+ poset()
2636
+ """
2637
+ new = self.copy()
2638
+ new.difference_update(*other)
2639
+ return new
2640
+
2641
+ def difference_update(self, *other):
2642
+ r"""
2643
+ Remove all elements of another poset from this poset.
2644
+
2645
+ INPUT:
2646
+
2647
+ - ``other`` -- a poset or an iterable. In the latter case the
2648
+ iterated objects are seen as elements of a poset.
2649
+ It is possible to specify more than one ``other`` as
2650
+ variadic arguments (arbitrary argument lists).
2651
+
2652
+ OUTPUT: nothing
2653
+
2654
+ .. NOTE::
2655
+
2656
+ The key of an element is used for comparison. Thus elements with
2657
+ the same key are considered as equal.
2658
+
2659
+ EXAMPLES::
2660
+
2661
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
2662
+ sage: P = MP([3, 42, 7]); P
2663
+ poset(3, 7, 42)
2664
+ sage: Q = MP([4, 8, 42]); Q
2665
+ poset(4, 8, 42)
2666
+ sage: P.difference_update(Q)
2667
+ sage: P
2668
+ poset(3, 7)
2669
+
2670
+ .. SEEALSO::
2671
+
2672
+ :meth:`union`, :meth:`union_update`,
2673
+ :meth:`difference`,
2674
+ :meth:`intersection`, :meth:`intersection_update`,
2675
+ :meth:`symmetric_difference`, :meth:`symmetric_difference_update`,
2676
+ :meth:`is_disjoint`,
2677
+ :meth:`is_subset`,
2678
+ :meth:`is_superset`.
2679
+ """
2680
+ for o in other:
2681
+ try:
2682
+ it = o.keys()
2683
+ except AttributeError:
2684
+ it = iter(o)
2685
+ for key in it:
2686
+ self.discard(key)
2687
+
2688
+ def intersection(self, *other):
2689
+ r"""
2690
+ Return the intersection of the given posets as a new poset.
2691
+
2692
+ INPUT:
2693
+
2694
+ - ``other`` -- a poset or an iterable. In the latter case the
2695
+ iterated objects are seen as elements of a poset.
2696
+ It is possible to specify more than one ``other`` as
2697
+ variadic arguments (arbitrary argument lists).
2698
+
2699
+ .. NOTE::
2700
+
2701
+ The key of an element is used for comparison. Thus elements with
2702
+ the same key are considered as equal.
2703
+
2704
+ EXAMPLES::
2705
+
2706
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
2707
+ sage: P = MP([3, 42, 7]); P
2708
+ poset(3, 7, 42)
2709
+ sage: Q = MP([4, 8, 42]); Q
2710
+ poset(4, 8, 42)
2711
+ sage: P.intersection(Q)
2712
+ poset(42)
2713
+
2714
+ .. SEEALSO::
2715
+
2716
+ :meth:`union`, :meth:`union_update`,
2717
+ :meth:`difference`, :meth:`difference_update`,
2718
+ :meth:`intersection_update`,
2719
+ :meth:`symmetric_difference`, :meth:`symmetric_difference_update`,
2720
+ :meth:`is_disjoint`,
2721
+ :meth:`is_subset`,
2722
+ :meth:`is_superset`.
2723
+
2724
+ TESTS::
2725
+
2726
+ sage: P.intersection(P, Q, Q, P)
2727
+ poset(42)
2728
+ """
2729
+ new = self.copy()
2730
+ new.intersection_update(*other)
2731
+ return new
2732
+
2733
+ def intersection_update(self, *other):
2734
+ r"""
2735
+ Update this poset with the intersection of itself and another poset.
2736
+
2737
+ INPUT:
2738
+
2739
+ - ``other`` -- a poset or an iterable. In the latter case the
2740
+ iterated objects are seen as elements of a poset.
2741
+ It is possible to specify more than one ``other`` as
2742
+ variadic arguments (arbitrary argument lists).
2743
+
2744
+ OUTPUT: nothing
2745
+
2746
+ .. NOTE::
2747
+
2748
+ The key of an element is used for comparison. Thus elements with
2749
+ the same key are considered as equal;
2750
+ ``A.intersection_update(B)`` and ``B.intersection_update(A)`` might
2751
+ result in different posets.
2752
+
2753
+ EXAMPLES::
2754
+
2755
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
2756
+ sage: P = MP([3, 42, 7]); P
2757
+ poset(3, 7, 42)
2758
+ sage: Q = MP([4, 8, 42]); Q
2759
+ poset(4, 8, 42)
2760
+ sage: P.intersection_update(Q)
2761
+ sage: P
2762
+ poset(42)
2763
+
2764
+ .. SEEALSO::
2765
+
2766
+ :meth:`union`, :meth:`union_update`,
2767
+ :meth:`difference`, :meth:`difference_update`,
2768
+ :meth:`intersection`,
2769
+ :meth:`symmetric_difference`, :meth:`symmetric_difference_update`,
2770
+ :meth:`is_disjoint`,
2771
+ :meth:`is_subset`,
2772
+ :meth:`is_superset`.
2773
+ """
2774
+ keys = tuple(self.keys())
2775
+ for key in keys:
2776
+ if any(key not in o for o in other):
2777
+ self.discard(key)
2778
+
2779
+ def symmetric_difference(self, other):
2780
+ r"""
2781
+ Return the symmetric difference of two posets as a new poset.
2782
+
2783
+ INPUT:
2784
+
2785
+ - ``other`` -- a poset
2786
+
2787
+ .. NOTE::
2788
+
2789
+ The key of an element is used for comparison. Thus elements with
2790
+ the same key are considered as equal.
2791
+
2792
+ EXAMPLES::
2793
+
2794
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
2795
+ sage: P = MP([3, 42, 7]); P
2796
+ poset(3, 7, 42)
2797
+ sage: Q = MP([4, 8, 42]); Q
2798
+ poset(4, 8, 42)
2799
+ sage: P.symmetric_difference(Q)
2800
+ poset(3, 4, 7, 8)
2801
+
2802
+ .. SEEALSO::
2803
+
2804
+ :meth:`union`, :meth:`union_update`,
2805
+ :meth:`difference`, :meth:`difference_update`,
2806
+ :meth:`intersection`, :meth:`intersection_update`,
2807
+ :meth:`symmetric_difference_update`,
2808
+ :meth:`is_disjoint`,
2809
+ :meth:`is_subset`,
2810
+ :meth:`is_superset`.
2811
+ """
2812
+ new = self.copy()
2813
+ new.symmetric_difference_update(other)
2814
+ return new
2815
+
2816
+ def symmetric_difference_update(self, other):
2817
+ r"""
2818
+ Update this poset with the symmetric difference of itself and
2819
+ another poset.
2820
+
2821
+ INPUT:
2822
+
2823
+ - ``other`` -- a poset
2824
+
2825
+ OUTPUT: nothing
2826
+
2827
+ .. NOTE::
2828
+
2829
+ The key of an element is used for comparison. Thus elements with
2830
+ the same key are considered as equal;
2831
+ ``A.symmetric_difference_update(B)`` and
2832
+ ``B.symmetric_difference_update(A)`` might
2833
+ result in different posets.
2834
+
2835
+ EXAMPLES::
2836
+
2837
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
2838
+ sage: P = MP([3, 42, 7]); P
2839
+ poset(3, 7, 42)
2840
+ sage: Q = MP([4, 8, 42]); Q
2841
+ poset(4, 8, 42)
2842
+ sage: P.symmetric_difference_update(Q)
2843
+ sage: P
2844
+ poset(3, 4, 7, 8)
2845
+
2846
+ .. SEEALSO::
2847
+
2848
+ :meth:`union`, :meth:`union_update`,
2849
+ :meth:`difference`, :meth:`difference_update`,
2850
+ :meth:`intersection`, :meth:`intersection_update`,
2851
+ :meth:`symmetric_difference`,
2852
+ :meth:`is_disjoint`,
2853
+ :meth:`is_subset`,
2854
+ :meth:`is_superset`.
2855
+ """
2856
+ T = other.difference(self)
2857
+ self.difference_update(other)
2858
+ self.union_update(T)
2859
+
2860
+ def is_disjoint(self, other):
2861
+ r"""
2862
+ Return whether another poset is disjoint to this poset.
2863
+
2864
+ INPUT:
2865
+
2866
+ - ``other`` -- a poset or an iterable; in the latter case the
2867
+ iterated objects are seen as elements of a poset
2868
+
2869
+ OUTPUT: nothing
2870
+
2871
+ .. NOTE::
2872
+
2873
+ If this poset uses a ``key``-function, then all
2874
+ comparisons are performed on the keys of the elements (and
2875
+ not on the elements themselves).
2876
+
2877
+ EXAMPLES::
2878
+
2879
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
2880
+ sage: P = MP([3, 42, 7]); P
2881
+ poset(3, 7, 42)
2882
+ sage: Q = MP([4, 8, 42]); Q
2883
+ poset(4, 8, 42)
2884
+ sage: P.is_disjoint(Q)
2885
+ False
2886
+ sage: P.is_disjoint(Q.difference(P))
2887
+ True
2888
+
2889
+ .. SEEALSO::
2890
+
2891
+ :meth:`is_subset`,
2892
+ :meth:`is_superset`,
2893
+ :meth:`union`, :meth:`union_update`,
2894
+ :meth:`difference`, :meth:`difference_update`,
2895
+ :meth:`intersection`, :meth:`intersection_update`,
2896
+ :meth:`symmetric_difference`, :meth:`symmetric_difference_update`.
2897
+ """
2898
+ return all(key not in other for key in self.keys())
2899
+
2900
+ isdisjoint = is_disjoint # as in a Python set
2901
+ r"""
2902
+ Alias of :meth:`is_disjoint`.
2903
+ """
2904
+
2905
+ def is_subset(self, other):
2906
+ r"""
2907
+ Return whether another poset contains this poset, i.e., whether this poset
2908
+ is a subset of the other poset.
2909
+
2910
+ INPUT:
2911
+
2912
+ - ``other`` -- a poset or an iterable; in the latter case the
2913
+ iterated objects are seen as elements of a poset
2914
+
2915
+ OUTPUT: nothing
2916
+
2917
+ .. NOTE::
2918
+
2919
+ If this poset uses a ``key``-function, then all
2920
+ comparisons are performed on the keys of the elements (and
2921
+ not on the elements themselves).
2922
+
2923
+ EXAMPLES::
2924
+
2925
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
2926
+ sage: P = MP([3, 42, 7]); P
2927
+ poset(3, 7, 42)
2928
+ sage: Q = MP([4, 8, 42]); Q
2929
+ poset(4, 8, 42)
2930
+ sage: P.is_subset(Q)
2931
+ False
2932
+ sage: Q.is_subset(P)
2933
+ False
2934
+ sage: P.is_subset(P)
2935
+ True
2936
+ sage: P.is_subset(P.union(Q))
2937
+ True
2938
+
2939
+ .. SEEALSO::
2940
+
2941
+ :meth:`is_disjoint`,
2942
+ :meth:`is_superset`,
2943
+ :meth:`union`, :meth:`union_update`,
2944
+ :meth:`difference`, :meth:`difference_update`,
2945
+ :meth:`intersection`, :meth:`intersection_update`,
2946
+ :meth:`symmetric_difference`, :meth:`symmetric_difference_update`.
2947
+ """
2948
+ return all(key in other for key in self.keys())
2949
+
2950
+ issubset = is_subset # as in a Python set
2951
+ r"""
2952
+ Alias of :meth:`is_subset`.
2953
+ """
2954
+
2955
+ def is_superset(self, other):
2956
+ r"""
2957
+ Return whether this poset contains another poset, i.e., whether this poset
2958
+ is a superset of the other poset.
2959
+
2960
+ INPUT:
2961
+
2962
+ - ``other`` -- a poset or an iterable; in the latter case the
2963
+ iterated objects are seen as elements of a poset
2964
+
2965
+ OUTPUT: nothing
2966
+
2967
+ .. NOTE::
2968
+
2969
+ If this poset uses a ``key``-function, then all
2970
+ comparisons are performed on the keys of the elements (and
2971
+ not on the elements themselves).
2972
+
2973
+ EXAMPLES::
2974
+
2975
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
2976
+ sage: P = MP([3, 42, 7]); P
2977
+ poset(3, 7, 42)
2978
+ sage: Q = MP([4, 8, 42]); Q
2979
+ poset(4, 8, 42)
2980
+ sage: P.is_superset(Q)
2981
+ False
2982
+ sage: Q.is_superset(P)
2983
+ False
2984
+ sage: P.is_superset(P)
2985
+ True
2986
+ sage: P.union(Q).is_superset(P)
2987
+ True
2988
+
2989
+ .. SEEALSO::
2990
+
2991
+ :meth:`is_disjoint`,
2992
+ :meth:`is_subset`,
2993
+ :meth:`union`, :meth:`union_update`,
2994
+ :meth:`difference`, :meth:`difference_update`,
2995
+ :meth:`intersection`, :meth:`intersection_update`,
2996
+ :meth:`symmetric_difference`, :meth:`symmetric_difference_update`.
2997
+ """
2998
+ try:
2999
+ it = other.keys()
3000
+ except AttributeError:
3001
+ it = iter(other)
3002
+ return all(key in self for key in it)
3003
+
3004
+ issuperset = is_superset # as in a Python set
3005
+ r"""
3006
+ Alias of :meth:`is_superset`.
3007
+ """
3008
+
3009
+ def merge(self, key=None, reverse=False):
3010
+ r"""
3011
+ Merge the given element with its successors/predecessors.
3012
+
3013
+ INPUT:
3014
+
3015
+ - ``key`` -- the key specifying an element or ``None``
3016
+ (default), in which case this method is called on each
3017
+ element in this poset
3018
+
3019
+ - ``reverse`` -- boolean (default: ``False``); specifies which
3020
+ direction to go first:
3021
+ ``False`` searches towards ``'oo'`` and
3022
+ ``True`` searches towards ``'null'``.
3023
+ When ``key=None``, then this also
3024
+ specifies which elements are merged first.
3025
+
3026
+ OUTPUT: nothing
3027
+
3028
+ This method tests all (not necessarily direct) successors and
3029
+ predecessors of the given element whether they can be merged with
3030
+ the element itself. This is done by the ``can_merge``-function
3031
+ of :class:`MutablePoset`. If this merge is possible, then it
3032
+ is performed by calling :class:`MutablePoset`'s
3033
+ ``merge``-function and the corresponding successor/predecessor
3034
+ is removed from the poset.
3035
+
3036
+ .. NOTE::
3037
+
3038
+ ``can_merge`` is applied in the sense of the condition of
3039
+ depth first iteration, i.e., once ``can_merge`` fails,
3040
+ the successors/predecessors are no longer tested.
3041
+
3042
+ .. NOTE::
3043
+
3044
+ The motivation for such a merge behavior comes from
3045
+ asymptotic expansions: `O(n^3)` merges with, for
3046
+ example, `3n^2` or `O(n)` to `O(n^3)` (as `n` tends to
3047
+ `\infty`; see :wikipedia:`Big_O_notation`).
3048
+
3049
+ EXAMPLES::
3050
+
3051
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
3052
+ sage: class T(tuple):
3053
+ ....: def __le__(left, right):
3054
+ ....: return all(l <= r for l, r in zip(left, right))
3055
+ sage: key = lambda t: T(t[0:2])
3056
+ sage: def add(left, right):
3057
+ ....: return (left[0], left[1],
3058
+ ....: ''.join(sorted(left[2] + right[2])))
3059
+ sage: def can_add(left, right):
3060
+ ....: return key(left) >= key(right)
3061
+ sage: P = MP([(1, 1, 'a'), (1, 3, 'b'), (2, 1, 'c'),
3062
+ ....: (4, 4, 'd'), (1, 2, 'e'), (2, 2, 'f')],
3063
+ ....: key=key, merge=add, can_merge=can_add)
3064
+ sage: Q = copy(P)
3065
+ sage: Q.merge(T((1, 3)))
3066
+ sage: print(Q.repr_full(reverse=True))
3067
+ poset((4, 4, 'd'), (1, 3, 'abe'), (2, 2, 'f'), (2, 1, 'c'))
3068
+ +-- oo
3069
+ | +-- no successors
3070
+ | +-- predecessors: (4, 4, 'd')
3071
+ +-- (4, 4, 'd')
3072
+ | +-- successors: oo
3073
+ | +-- predecessors: (1, 3, 'abe'), (2, 2, 'f')
3074
+ +-- (1, 3, 'abe')
3075
+ | +-- successors: (4, 4, 'd')
3076
+ | +-- predecessors: null
3077
+ +-- (2, 2, 'f')
3078
+ | +-- successors: (4, 4, 'd')
3079
+ | +-- predecessors: (2, 1, 'c')
3080
+ +-- (2, 1, 'c')
3081
+ | +-- successors: (2, 2, 'f')
3082
+ | +-- predecessors: null
3083
+ +-- null
3084
+ | +-- successors: (1, 3, 'abe'), (2, 1, 'c')
3085
+ | +-- no predecessors
3086
+ sage: for k in sorted(P.keys()):
3087
+ ....: Q = copy(P)
3088
+ ....: Q.merge(k)
3089
+ ....: print('merging %s: %s' % (k, Q))
3090
+ merging (1, 1): poset((1, 1, 'a'), (1, 2, 'e'), (1, 3, 'b'),
3091
+ (2, 1, 'c'), (2, 2, 'f'), (4, 4, 'd'))
3092
+ merging (1, 2): poset((1, 2, 'ae'), (1, 3, 'b'), (2, 1, 'c'),
3093
+ (2, 2, 'f'), (4, 4, 'd'))
3094
+ merging (1, 3): poset((1, 3, 'abe'), (2, 1, 'c'), (2, 2, 'f'),
3095
+ (4, 4, 'd'))
3096
+ merging (2, 1): poset((1, 2, 'e'), (1, 3, 'b'), (2, 1, 'ac'),
3097
+ (2, 2, 'f'), (4, 4, 'd'))
3098
+ merging (2, 2): poset((1, 3, 'b'), (2, 2, 'acef'), (4, 4, 'd'))
3099
+ merging (4, 4): poset((4, 4, 'abcdef'))
3100
+
3101
+ sage: Q = copy(P)
3102
+ sage: Q.merge(); Q
3103
+ poset((4, 4, 'abcdef'))
3104
+
3105
+ .. SEEALSO::
3106
+
3107
+ :meth:`MutablePosetShell.merge`
3108
+
3109
+ TESTS::
3110
+
3111
+ sage: copy(P).merge(reverse=False) == copy(P).merge(reverse=True)
3112
+ True
3113
+
3114
+ ::
3115
+
3116
+ sage: P = MP(srange(4),
3117
+ ....: merge=lambda l, r: l, can_merge=lambda l, r: l >= r); P
3118
+ poset(0, 1, 2, 3)
3119
+ sage: Q = P.copy()
3120
+ sage: Q.merge(reverse=True); Q
3121
+ poset(3)
3122
+ sage: R = P.mapped(lambda x: x+1)
3123
+ sage: R.merge(reverse=True); R
3124
+ poset(4)
3125
+
3126
+ ::
3127
+
3128
+ sage: P = MP(srange(4),
3129
+ ....: merge=lambda l, r: r, can_merge=lambda l, r: l < r)
3130
+ sage: P.merge()
3131
+ Traceback (most recent call last):
3132
+ ...
3133
+ RuntimeError: Stopping merge before started;
3134
+ the can_merge-function is not reflexive.
3135
+ """
3136
+ if key is None:
3137
+ for shell in tuple(self.shells_topological(reverse=reverse)):
3138
+ if shell.key in self._shells_:
3139
+ self.merge(key=shell.key)
3140
+ return
3141
+
3142
+ shell = self.shell(key)
3143
+
3144
+ def can_merge(other):
3145
+ return self._can_merge_(shell.element, other.element)
3146
+ for rev in (reverse, not reverse):
3147
+ to_merge = shell.iter_depth_first(
3148
+ reverse=rev, condition=can_merge)
3149
+ try:
3150
+ next(to_merge)
3151
+ except StopIteration:
3152
+ raise RuntimeError('Stopping merge before started; the '
3153
+ 'can_merge-function is not reflexive.')
3154
+ for m in tuple(to_merge):
3155
+ if m.is_special():
3156
+ continue
3157
+ shell.merge(m.element, check=False, delete=True)
3158
+
3159
+ def maximal_elements(self):
3160
+ r"""
3161
+ Return an iterator over the maximal elements of this poset.
3162
+
3163
+ OUTPUT: an iterator
3164
+
3165
+ EXAMPLES::
3166
+
3167
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
3168
+ sage: class T(tuple):
3169
+ ....: def __le__(left, right):
3170
+ ....: return all(l <= r for l, r in zip(left, right))
3171
+ sage: P = MP([T((1, 1)), T((1, 3)), T((2, 1)),
3172
+ ....: T((1, 2)), T((2, 2))])
3173
+ sage: sorted(P.maximal_elements())
3174
+ [(1, 3), (2, 2)]
3175
+
3176
+ .. SEEALSO::
3177
+
3178
+ :meth:`minimal_elements`
3179
+ """
3180
+ return iter(shell.element
3181
+ for shell in self.oo.predecessors()
3182
+ if not shell.is_special())
3183
+
3184
+ def minimal_elements(self):
3185
+ r"""
3186
+ Return an iterator over the minimal elements of this poset.
3187
+
3188
+ OUTPUT: an iterator
3189
+
3190
+ EXAMPLES::
3191
+
3192
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
3193
+ sage: class T(tuple):
3194
+ ....: def __le__(left, right):
3195
+ ....: return all(l <= r for l, r in zip(left, right))
3196
+ sage: P = MP([T((1, 3)), T((2, 1)),
3197
+ ....: T((4, 4)), T((1, 2)), T((2, 2))])
3198
+ sage: sorted(P.minimal_elements())
3199
+ [(1, 2), (2, 1)]
3200
+
3201
+ .. SEEALSO::
3202
+
3203
+ :meth:`maximal_elements`
3204
+ """
3205
+ return iter(shell.element
3206
+ for shell in self.null.successors()
3207
+ if not shell.is_special())
3208
+
3209
+ def map(self, function, topological=False, reverse=False):
3210
+ r"""
3211
+ Apply the given ``function`` to each element of this poset.
3212
+
3213
+ INPUT:
3214
+
3215
+ - ``function`` -- a function mapping an existing element to
3216
+ a new element
3217
+
3218
+ - ``topological`` -- boolean (default: ``False``); if set, then the
3219
+ mapping is done in topological order, otherwise unordered
3220
+
3221
+ - ``reverse`` -- is passed on to topological ordering
3222
+
3223
+ OUTPUT: nothing
3224
+
3225
+ .. NOTE::
3226
+
3227
+ Since this method works inplace, it is not allowed that
3228
+ ``function`` alters the key of an element.
3229
+
3230
+ .. NOTE::
3231
+
3232
+ If ``function`` returns ``None``, then the element is
3233
+ removed.
3234
+
3235
+ EXAMPLES::
3236
+
3237
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
3238
+ sage: class T(tuple):
3239
+ ....: def __le__(left, right):
3240
+ ....: return all(l <= r for l, r in zip(left, right))
3241
+ sage: P = MP([T((1, 3)), T((2, 1)),
3242
+ ....: T((4, 4)), T((1, 2)), T((2, 2))],
3243
+ ....: key=lambda e: e[:2])
3244
+ sage: P.map(lambda e: e + (sum(e),))
3245
+ sage: P
3246
+ poset((1, 2, 3), (1, 3, 4), (2, 1, 3), (2, 2, 4), (4, 4, 8))
3247
+
3248
+ TESTS::
3249
+
3250
+ sage: P.map(lambda e: e if e[2] != 4 else None); P
3251
+ poset((1, 2, 3), (2, 1, 3), (4, 4, 8))
3252
+
3253
+ .. SEEALSO::
3254
+
3255
+ :meth:`copy`,
3256
+ :meth:`mapped`.
3257
+ """
3258
+ shells = self.shells_topological(reverse=reverse) \
3259
+ if topological else self.shells()
3260
+ remove = []
3261
+ for shell in shells:
3262
+ image = function(shell._element_)
3263
+ if image is None:
3264
+ remove.append(shell.key)
3265
+ else:
3266
+ shell._element_ = image
3267
+ for key in remove:
3268
+ self.remove(key)
3269
+
3270
+ def mapped(self, function):
3271
+ r"""
3272
+ Return a poset where on each element the given ``function``
3273
+ was applied.
3274
+
3275
+ INPUT:
3276
+
3277
+ - ``function`` -- a function mapping an existing element to
3278
+ a new element
3279
+
3280
+ - ``topological`` -- boolean (default: ``False``); if set, then the
3281
+ mapping is done in topological order, otherwise unordered
3282
+
3283
+ - ``reverse`` -- is passed on to topological ordering
3284
+
3285
+ OUTPUT: a :class:`MutablePoset`
3286
+
3287
+ .. NOTE::
3288
+
3289
+ ``function`` is not allowed to change the order of the keys,
3290
+ but changing the keys themselves is allowed (in contrast
3291
+ to :meth:`map`).
3292
+
3293
+ EXAMPLES::
3294
+
3295
+ sage: from sage.data_structures.mutable_poset import MutablePoset as MP
3296
+ sage: class T(tuple):
3297
+ ....: def __le__(left, right):
3298
+ ....: return all(l <= r for l, r in zip(left, right))
3299
+ sage: P = MP([T((1, 3)), T((2, 1)),
3300
+ ....: T((4, 4)), T((1, 2)), T((2, 2))])
3301
+ sage: P.mapped(lambda e: str(e))
3302
+ poset('(1, 2)', '(1, 3)', '(2, 1)', '(2, 2)', '(4, 4)')
3303
+
3304
+ .. SEEALSO::
3305
+
3306
+ :meth:`copy`,
3307
+ :meth:`map`.
3308
+ """
3309
+ return self.copy(mapping=function)
3310
+
3311
+
3312
+ # *****************************************************************************