passagemath-graphs 10.6.1rc1__cp310-cp310-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 (260) hide show
  1. passagemath_graphs-10.6.1rc1.dist-info/METADATA +292 -0
  2. passagemath_graphs-10.6.1rc1.dist-info/RECORD +260 -0
  3. passagemath_graphs-10.6.1rc1.dist-info/WHEEL +5 -0
  4. passagemath_graphs-10.6.1rc1.dist-info/top_level.txt +2 -0
  5. passagemath_graphs.libs/libgcc_s-69c45f16.so.1 +0 -0
  6. passagemath_graphs.libs/libgmp-8e78bd9b.so.10.5.0 +0 -0
  7. passagemath_graphs.libs/libstdc++-1f1a71be.so.6.0.33 +0 -0
  8. sage/all__sagemath_graphs.py +39 -0
  9. sage/combinat/abstract_tree.py +2723 -0
  10. sage/combinat/all__sagemath_graphs.py +34 -0
  11. sage/combinat/binary_tree.py +5306 -0
  12. sage/combinat/cluster_algebra_quiver/all.py +22 -0
  13. sage/combinat/cluster_algebra_quiver/cluster_seed.py +5208 -0
  14. sage/combinat/cluster_algebra_quiver/interact.py +124 -0
  15. sage/combinat/cluster_algebra_quiver/mutation_class.py +625 -0
  16. sage/combinat/cluster_algebra_quiver/mutation_type.py +1555 -0
  17. sage/combinat/cluster_algebra_quiver/quiver.py +2290 -0
  18. sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py +2468 -0
  19. sage/combinat/designs/MOLS_handbook_data.py +570 -0
  20. sage/combinat/designs/all.py +58 -0
  21. sage/combinat/designs/bibd.py +1655 -0
  22. sage/combinat/designs/block_design.py +1071 -0
  23. sage/combinat/designs/covering_array.py +269 -0
  24. sage/combinat/designs/covering_design.py +530 -0
  25. sage/combinat/designs/database.py +5615 -0
  26. sage/combinat/designs/design_catalog.py +122 -0
  27. sage/combinat/designs/designs_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
  28. sage/combinat/designs/designs_pyx.pxd +21 -0
  29. sage/combinat/designs/designs_pyx.pyx +993 -0
  30. sage/combinat/designs/difference_family.py +3951 -0
  31. sage/combinat/designs/difference_matrices.py +279 -0
  32. sage/combinat/designs/evenly_distributed_sets.cpython-310-aarch64-linux-gnu.so +0 -0
  33. sage/combinat/designs/evenly_distributed_sets.pyx +661 -0
  34. sage/combinat/designs/ext_rep.py +1064 -0
  35. sage/combinat/designs/gen_quadrangles_with_spread.cpython-310-aarch64-linux-gnu.so +0 -0
  36. sage/combinat/designs/gen_quadrangles_with_spread.pyx +339 -0
  37. sage/combinat/designs/group_divisible_designs.py +361 -0
  38. sage/combinat/designs/incidence_structures.py +2357 -0
  39. sage/combinat/designs/latin_squares.py +581 -0
  40. sage/combinat/designs/orthogonal_arrays.py +2244 -0
  41. sage/combinat/designs/orthogonal_arrays_build_recursive.py +1780 -0
  42. sage/combinat/designs/orthogonal_arrays_find_recursive.cpython-310-aarch64-linux-gnu.so +0 -0
  43. sage/combinat/designs/orthogonal_arrays_find_recursive.pyx +967 -0
  44. sage/combinat/designs/resolvable_bibd.py +815 -0
  45. sage/combinat/designs/steiner_quadruple_systems.py +1306 -0
  46. sage/combinat/designs/subhypergraph_search.cpython-310-aarch64-linux-gnu.so +0 -0
  47. sage/combinat/designs/subhypergraph_search.pyx +530 -0
  48. sage/combinat/designs/twographs.py +306 -0
  49. sage/combinat/finite_state_machine.py +14874 -0
  50. sage/combinat/finite_state_machine_generators.py +2006 -0
  51. sage/combinat/graph_path.py +448 -0
  52. sage/combinat/interval_posets.py +3908 -0
  53. sage/combinat/nu_tamari_lattice.py +269 -0
  54. sage/combinat/ordered_tree.py +1446 -0
  55. sage/combinat/posets/all.py +46 -0
  56. sage/combinat/posets/bubble_shuffle.py +247 -0
  57. sage/combinat/posets/cartesian_product.py +493 -0
  58. sage/combinat/posets/d_complete.py +182 -0
  59. sage/combinat/posets/elements.py +273 -0
  60. sage/combinat/posets/forest.py +30 -0
  61. sage/combinat/posets/hasse_cython.cpython-310-aarch64-linux-gnu.so +0 -0
  62. sage/combinat/posets/hasse_cython.pyx +174 -0
  63. sage/combinat/posets/hasse_diagram.py +3672 -0
  64. sage/combinat/posets/hochschild_lattice.py +158 -0
  65. sage/combinat/posets/incidence_algebras.py +794 -0
  66. sage/combinat/posets/lattices.py +5117 -0
  67. sage/combinat/posets/linear_extension_iterator.cpython-310-aarch64-linux-gnu.so +0 -0
  68. sage/combinat/posets/linear_extension_iterator.pyx +292 -0
  69. sage/combinat/posets/linear_extensions.py +1037 -0
  70. sage/combinat/posets/mobile.py +275 -0
  71. sage/combinat/posets/moebius_algebra.py +776 -0
  72. sage/combinat/posets/poset_examples.py +2178 -0
  73. sage/combinat/posets/posets.py +9360 -0
  74. sage/combinat/rooted_tree.py +1070 -0
  75. sage/combinat/shard_order.py +239 -0
  76. sage/combinat/tamari_lattices.py +384 -0
  77. sage/combinat/yang_baxter_graph.py +923 -0
  78. sage/databases/all__sagemath_graphs.py +1 -0
  79. sage/databases/knotinfo_db.py +1231 -0
  80. sage/ext_data/all__sagemath_graphs.py +1 -0
  81. sage/ext_data/graphs/graph_plot_js.html +330 -0
  82. sage/ext_data/kenzo/CP2.txt +45 -0
  83. sage/ext_data/kenzo/CP3.txt +349 -0
  84. sage/ext_data/kenzo/CP4.txt +4774 -0
  85. sage/ext_data/kenzo/README.txt +49 -0
  86. sage/ext_data/kenzo/S4.txt +20 -0
  87. sage/graphs/all.py +42 -0
  88. sage/graphs/asteroidal_triples.cpython-310-aarch64-linux-gnu.so +0 -0
  89. sage/graphs/asteroidal_triples.pyx +320 -0
  90. sage/graphs/base/all.py +1 -0
  91. sage/graphs/base/boost_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  92. sage/graphs/base/boost_graph.pxd +106 -0
  93. sage/graphs/base/boost_graph.pyx +3045 -0
  94. sage/graphs/base/c_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  95. sage/graphs/base/c_graph.pxd +106 -0
  96. sage/graphs/base/c_graph.pyx +5096 -0
  97. sage/graphs/base/dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  98. sage/graphs/base/dense_graph.pxd +28 -0
  99. sage/graphs/base/dense_graph.pyx +801 -0
  100. sage/graphs/base/graph_backends.cpython-310-aarch64-linux-gnu.so +0 -0
  101. sage/graphs/base/graph_backends.pxd +5 -0
  102. sage/graphs/base/graph_backends.pyx +797 -0
  103. sage/graphs/base/overview.py +85 -0
  104. sage/graphs/base/sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  105. sage/graphs/base/sparse_graph.pxd +90 -0
  106. sage/graphs/base/sparse_graph.pyx +1653 -0
  107. sage/graphs/base/static_dense_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  108. sage/graphs/base/static_dense_graph.pxd +5 -0
  109. sage/graphs/base/static_dense_graph.pyx +1032 -0
  110. sage/graphs/base/static_sparse_backend.cpython-310-aarch64-linux-gnu.so +0 -0
  111. sage/graphs/base/static_sparse_backend.pxd +27 -0
  112. sage/graphs/base/static_sparse_backend.pyx +1583 -0
  113. sage/graphs/base/static_sparse_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  114. sage/graphs/base/static_sparse_graph.pxd +37 -0
  115. sage/graphs/base/static_sparse_graph.pyx +1375 -0
  116. sage/graphs/bipartite_graph.py +2732 -0
  117. sage/graphs/centrality.cpython-310-aarch64-linux-gnu.so +0 -0
  118. sage/graphs/centrality.pyx +1038 -0
  119. sage/graphs/cographs.py +519 -0
  120. sage/graphs/comparability.cpython-310-aarch64-linux-gnu.so +0 -0
  121. sage/graphs/comparability.pyx +851 -0
  122. sage/graphs/connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
  123. sage/graphs/connectivity.pxd +157 -0
  124. sage/graphs/connectivity.pyx +4813 -0
  125. sage/graphs/convexity_properties.cpython-310-aarch64-linux-gnu.so +0 -0
  126. sage/graphs/convexity_properties.pxd +16 -0
  127. sage/graphs/convexity_properties.pyx +870 -0
  128. sage/graphs/digraph.py +4754 -0
  129. sage/graphs/digraph_generators.py +1993 -0
  130. sage/graphs/distances_all_pairs.cpython-310-aarch64-linux-gnu.so +0 -0
  131. sage/graphs/distances_all_pairs.pxd +12 -0
  132. sage/graphs/distances_all_pairs.pyx +2938 -0
  133. sage/graphs/domination.py +1363 -0
  134. sage/graphs/dot2tex_utils.py +100 -0
  135. sage/graphs/edge_connectivity.cpython-310-aarch64-linux-gnu.so +0 -0
  136. sage/graphs/edge_connectivity.pyx +1215 -0
  137. sage/graphs/generators/all.py +1 -0
  138. sage/graphs/generators/basic.py +1769 -0
  139. sage/graphs/generators/chessboard.py +538 -0
  140. sage/graphs/generators/classical_geometries.py +1611 -0
  141. sage/graphs/generators/degree_sequence.py +235 -0
  142. sage/graphs/generators/distance_regular.cpython-310-aarch64-linux-gnu.so +0 -0
  143. sage/graphs/generators/distance_regular.pyx +2846 -0
  144. sage/graphs/generators/families.py +4759 -0
  145. sage/graphs/generators/intersection.py +565 -0
  146. sage/graphs/generators/platonic_solids.py +262 -0
  147. sage/graphs/generators/random.py +2623 -0
  148. sage/graphs/generators/smallgraphs.py +5741 -0
  149. sage/graphs/generators/world_map.py +724 -0
  150. sage/graphs/generic_graph.py +26867 -0
  151. sage/graphs/generic_graph_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
  152. sage/graphs/generic_graph_pyx.pxd +34 -0
  153. sage/graphs/generic_graph_pyx.pyx +1673 -0
  154. sage/graphs/genus.cpython-310-aarch64-linux-gnu.so +0 -0
  155. sage/graphs/genus.pyx +622 -0
  156. sage/graphs/graph.py +9645 -0
  157. sage/graphs/graph_coloring.cpython-310-aarch64-linux-gnu.so +0 -0
  158. sage/graphs/graph_coloring.pyx +2284 -0
  159. sage/graphs/graph_database.py +1177 -0
  160. sage/graphs/graph_decompositions/all.py +1 -0
  161. sage/graphs/graph_decompositions/bandwidth.cpython-310-aarch64-linux-gnu.so +0 -0
  162. sage/graphs/graph_decompositions/bandwidth.pyx +428 -0
  163. sage/graphs/graph_decompositions/clique_separators.cpython-310-aarch64-linux-gnu.so +0 -0
  164. sage/graphs/graph_decompositions/clique_separators.pyx +616 -0
  165. sage/graphs/graph_decompositions/cutwidth.cpython-310-aarch64-linux-gnu.so +0 -0
  166. sage/graphs/graph_decompositions/cutwidth.pyx +753 -0
  167. sage/graphs/graph_decompositions/fast_digraph.cpython-310-aarch64-linux-gnu.so +0 -0
  168. sage/graphs/graph_decompositions/fast_digraph.pxd +13 -0
  169. sage/graphs/graph_decompositions/fast_digraph.pyx +212 -0
  170. sage/graphs/graph_decompositions/graph_products.cpython-310-aarch64-linux-gnu.so +0 -0
  171. sage/graphs/graph_decompositions/graph_products.pyx +508 -0
  172. sage/graphs/graph_decompositions/modular_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
  173. sage/graphs/graph_decompositions/modular_decomposition.pxd +27 -0
  174. sage/graphs/graph_decompositions/modular_decomposition.pyx +1536 -0
  175. sage/graphs/graph_decompositions/slice_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
  176. sage/graphs/graph_decompositions/slice_decomposition.pxd +18 -0
  177. sage/graphs/graph_decompositions/slice_decomposition.pyx +1106 -0
  178. sage/graphs/graph_decompositions/tree_decomposition.cpython-310-aarch64-linux-gnu.so +0 -0
  179. sage/graphs/graph_decompositions/tree_decomposition.pxd +17 -0
  180. sage/graphs/graph_decompositions/tree_decomposition.pyx +1996 -0
  181. sage/graphs/graph_decompositions/vertex_separation.cpython-310-aarch64-linux-gnu.so +0 -0
  182. sage/graphs/graph_decompositions/vertex_separation.pxd +5 -0
  183. sage/graphs/graph_decompositions/vertex_separation.pyx +1963 -0
  184. sage/graphs/graph_editor.py +82 -0
  185. sage/graphs/graph_generators.py +3314 -0
  186. sage/graphs/graph_generators_pyx.cpython-310-aarch64-linux-gnu.so +0 -0
  187. sage/graphs/graph_generators_pyx.pyx +95 -0
  188. sage/graphs/graph_input.py +812 -0
  189. sage/graphs/graph_latex.py +2064 -0
  190. sage/graphs/graph_list.py +410 -0
  191. sage/graphs/graph_plot.py +1756 -0
  192. sage/graphs/graph_plot_js.py +338 -0
  193. sage/graphs/hyperbolicity.cpython-310-aarch64-linux-gnu.so +0 -0
  194. sage/graphs/hyperbolicity.pyx +1704 -0
  195. sage/graphs/hypergraph_generators.py +364 -0
  196. sage/graphs/independent_sets.cpython-310-aarch64-linux-gnu.so +0 -0
  197. sage/graphs/independent_sets.pxd +13 -0
  198. sage/graphs/independent_sets.pyx +402 -0
  199. sage/graphs/isgci.py +1033 -0
  200. sage/graphs/isoperimetric_inequalities.cpython-310-aarch64-linux-gnu.so +0 -0
  201. sage/graphs/isoperimetric_inequalities.pyx +489 -0
  202. sage/graphs/line_graph.cpython-310-aarch64-linux-gnu.so +0 -0
  203. sage/graphs/line_graph.pyx +743 -0
  204. sage/graphs/lovasz_theta.py +77 -0
  205. sage/graphs/matching.py +1633 -0
  206. sage/graphs/matching_covered_graph.py +3590 -0
  207. sage/graphs/orientations.py +1489 -0
  208. sage/graphs/partial_cube.py +459 -0
  209. sage/graphs/path_enumeration.cpython-310-aarch64-linux-gnu.so +0 -0
  210. sage/graphs/path_enumeration.pyx +2040 -0
  211. sage/graphs/pq_trees.py +1129 -0
  212. sage/graphs/print_graphs.py +201 -0
  213. sage/graphs/schnyder.py +865 -0
  214. sage/graphs/spanning_tree.cpython-310-aarch64-linux-gnu.so +0 -0
  215. sage/graphs/spanning_tree.pyx +1457 -0
  216. sage/graphs/strongly_regular_db.cpython-310-aarch64-linux-gnu.so +0 -0
  217. sage/graphs/strongly_regular_db.pyx +3340 -0
  218. sage/graphs/traversals.cpython-310-aarch64-linux-gnu.so +0 -0
  219. sage/graphs/traversals.pxd +9 -0
  220. sage/graphs/traversals.pyx +1872 -0
  221. sage/graphs/trees.cpython-310-aarch64-linux-gnu.so +0 -0
  222. sage/graphs/trees.pxd +15 -0
  223. sage/graphs/trees.pyx +310 -0
  224. sage/graphs/tutte_polynomial.py +713 -0
  225. sage/graphs/views.cpython-310-aarch64-linux-gnu.so +0 -0
  226. sage/graphs/views.pyx +794 -0
  227. sage/graphs/weakly_chordal.cpython-310-aarch64-linux-gnu.so +0 -0
  228. sage/graphs/weakly_chordal.pyx +604 -0
  229. sage/groups/all__sagemath_graphs.py +1 -0
  230. sage/groups/perm_gps/all__sagemath_graphs.py +1 -0
  231. sage/groups/perm_gps/partn_ref/all__sagemath_graphs.py +1 -0
  232. sage/groups/perm_gps/partn_ref/refinement_graphs.cpython-310-aarch64-linux-gnu.so +0 -0
  233. sage/groups/perm_gps/partn_ref/refinement_graphs.pxd +38 -0
  234. sage/groups/perm_gps/partn_ref/refinement_graphs.pyx +1666 -0
  235. sage/knots/all.py +6 -0
  236. sage/knots/free_knotinfo_monoid.py +507 -0
  237. sage/knots/gauss_code.py +291 -0
  238. sage/knots/knot.py +682 -0
  239. sage/knots/knot_table.py +284 -0
  240. sage/knots/knotinfo.py +2900 -0
  241. sage/knots/link.py +4715 -0
  242. sage/sandpiles/all.py +13 -0
  243. sage/sandpiles/examples.py +225 -0
  244. sage/sandpiles/sandpile.py +6365 -0
  245. sage/topology/all.py +22 -0
  246. sage/topology/cell_complex.py +1214 -0
  247. sage/topology/cubical_complex.py +1976 -0
  248. sage/topology/delta_complex.py +1806 -0
  249. sage/topology/filtered_simplicial_complex.py +744 -0
  250. sage/topology/moment_angle_complex.py +823 -0
  251. sage/topology/simplicial_complex.py +5160 -0
  252. sage/topology/simplicial_complex_catalog.py +92 -0
  253. sage/topology/simplicial_complex_examples.py +1680 -0
  254. sage/topology/simplicial_complex_homset.py +205 -0
  255. sage/topology/simplicial_complex_morphism.py +836 -0
  256. sage/topology/simplicial_set.py +4102 -0
  257. sage/topology/simplicial_set_catalog.py +55 -0
  258. sage/topology/simplicial_set_constructions.py +2954 -0
  259. sage/topology/simplicial_set_examples.py +865 -0
  260. sage/topology/simplicial_set_morphism.py +1464 -0
@@ -0,0 +1,1037 @@
1
+ # sage_setup: distribution = sagemath-graphs
2
+ r"""
3
+ Linear extensions of posets
4
+ """
5
+ # ****************************************************************************
6
+ # Copyright (C) 2012 Anne Schilling <anne at math.ucdavis.edu>
7
+ #
8
+ # Distributed under the terms of the GNU General Public License (GPL)
9
+ #
10
+ # This code is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # General Public License for more details.
14
+ #
15
+ # The full text of the GPL is available at:
16
+ #
17
+ # https://www.gnu.org/licenses/
18
+ # ***************************************************************************
19
+
20
+ from sage.misc.lazy_import import lazy_import
21
+ from sage.rings.rational_field import QQ
22
+ from sage.structure.unique_representation import UniqueRepresentation
23
+ from sage.structure.parent import Parent
24
+ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
25
+ from sage.graphs.digraph import DiGraph
26
+ from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass
27
+ from sage.graphs.dot2tex_utils import have_dot2tex
28
+ from sage.structure.list_clone import ClonableArray
29
+ from sage.arith.misc import factorial
30
+
31
+ lazy_import('sage.matrix.constructor', 'matrix')
32
+
33
+
34
+ class LinearExtensionOfPoset(ClonableArray,
35
+ metaclass=InheritComparisonClasscallMetaclass):
36
+ r"""
37
+ A linear extension of a finite poset `P` of size `n` is a total
38
+ ordering `\pi := \pi_0 \pi_1 \ldots \pi_{n-1}` of its elements
39
+ such that `i<j` whenever `\pi_i < \pi_j` in the poset `P`.
40
+
41
+ When the elements of `P` are indexed by `\{1,2,\ldots,n\}`, `\pi`
42
+ denotes a permutation of the elements of `P` in one-line notation.
43
+
44
+ INPUT:
45
+
46
+ - ``linear_extension`` -- list of the elements of `P`
47
+ - ``poset`` -- the underlying poset `P`
48
+
49
+ .. SEEALSO:: :class:`~sage.combinat.posets.posets.Poset`, :class:`LinearExtensionsOfPoset`
50
+
51
+ EXAMPLES::
52
+
53
+ sage: P = Poset(([1,2,3,4], [[1,3],[1,4],[2,3]]),
54
+ ....: linear_extension=True, facade=False)
55
+ sage: p = P.linear_extension([1,4,2,3]); p
56
+ [1, 4, 2, 3]
57
+ sage: p.parent()
58
+ The set of all linear extensions of
59
+ Finite poset containing 4 elements with distinguished linear extension
60
+ sage: p[0], p[1], p[2], p[3]
61
+ (1, 4, 2, 3)
62
+
63
+ Following Schützenberger and later Haiman and
64
+ Malvenuto-Reutenauer, Stanley [Stan2009]_ defined a promotion
65
+ and evacuation operator on any finite poset `P` using operators
66
+ `\tau_i` on the linear extensions of `P`::
67
+
68
+ sage: p.promotion()
69
+ [1, 2, 3, 4]
70
+ sage: Q = p.promotion().to_poset()
71
+ sage: Q.cover_relations()
72
+ [[1, 3], [1, 4], [2, 3]]
73
+ sage: Q == P
74
+ True
75
+
76
+ sage: p.promotion(3)
77
+ [1, 4, 2, 3]
78
+ sage: Q = p.promotion(3).to_poset()
79
+ sage: Q == P
80
+ False
81
+ sage: Q.cover_relations()
82
+ [[1, 2], [1, 4], [3, 4]]
83
+ """
84
+ @staticmethod
85
+ def __classcall_private__(cls, linear_extension, poset):
86
+ r"""
87
+ Implement the shortcut ``LinearExtensionOfPoset(linear_extension, poset)``
88
+ to ``LinearExtensionsOfPoset(poset)(linear_extension)``.
89
+
90
+ INPUT:
91
+
92
+ - ``linear_extension`` -- list of elements of ``poset``
93
+ - ``poset`` -- a finite poset
94
+
95
+ .. TODO:: check whether this method is still useful
96
+
97
+ TESTS::
98
+
99
+ sage: from sage.combinat.posets.linear_extensions import LinearExtensionOfPoset
100
+ sage: P = Poset(([1,2,3,4], [[1,3],[1,4],[2,3]]))
101
+ sage: p = LinearExtensionOfPoset([1,4,2,3], P)
102
+ sage: p.parent()
103
+ The set of all linear extensions of Finite poset containing 4 elements
104
+ sage: type(p)
105
+ <class 'sage.combinat.posets.linear_extensions.LinearExtensionsOfPoset_with_category.element_class'>
106
+ sage: p.poset()
107
+ Finite poset containing 4 elements
108
+ sage: TestSuite(p).run()
109
+
110
+ TESTS::
111
+
112
+ sage: LinearExtensionOfPoset([4,3,2,1], P)
113
+ Traceback (most recent call last):
114
+ ...
115
+ ValueError: [4, 3, 2, 1] is not a linear extension of Finite poset containing 4 elements
116
+
117
+ sage: p is LinearExtensionOfPoset(p, P)
118
+ True
119
+ """
120
+ if isinstance(linear_extension, cls):
121
+ return linear_extension
122
+ return LinearExtensionsOfPoset(poset)(linear_extension)
123
+
124
+ def check(self) -> None:
125
+ r"""
126
+ Check whether ``self`` is indeed a linear extension of the underlying poset.
127
+
128
+ TESTS::
129
+
130
+ sage: P = Poset(([1,2,3,4], [[1,3],[1,4],[2,3]]))
131
+ sage: P.linear_extension([1,4,2,3])
132
+ [1, 4, 2, 3]
133
+ sage: P.linear_extension([4,3,2,1])
134
+ Traceback (most recent call last):
135
+ ...
136
+ ValueError: [4, 3, 2, 1] is not a linear extension of Finite poset containing 4 elements
137
+ """
138
+ P = self.parent().poset()
139
+ if not P.is_linear_extension(self):
140
+ raise ValueError(f"{self} is not a linear extension of {P}")
141
+
142
+ def poset(self):
143
+ r"""
144
+ Return the underlying original poset.
145
+
146
+ EXAMPLES::
147
+
148
+ sage: P = Poset(([1,2,3,4], [[1,2],[2,3],[1,4]]))
149
+ sage: p = P.linear_extension([1,2,4,3])
150
+ sage: p.poset()
151
+ Finite poset containing 4 elements
152
+ """
153
+ return self.parent().poset()
154
+
155
+ def _latex_(self) -> str:
156
+ r"""
157
+ Return the latex string for ``self``.
158
+
159
+ EXAMPLES::
160
+
161
+ sage: P = Poset(([1,2,3,4], [[1,3],[1,4],[2,3]]))
162
+ sage: p = P.linear_extension([1,2,3,4])
163
+ sage: p._latex_()
164
+ '\\mathtt{(1, 2, 3, 4)}'
165
+ """
166
+ return "\\mathtt{" + str(tuple(self)) + "}"
167
+
168
+ def to_poset(self):
169
+ r"""
170
+ Return the poset associated to the linear extension ``self``.
171
+
172
+ This method returns the poset obtained from the original poset
173
+ `P` by relabelling the `i`-th element of ``self`` to the
174
+ `i`-th element of the original poset, while keeping the linear
175
+ extension of the original poset.
176
+
177
+ For a poset with default linear extension `1,\dots,n`,
178
+ ``self`` can be interpreted as a permutation, and the
179
+ relabelling is done according to the inverse of this
180
+ permutation.
181
+
182
+ EXAMPLES::
183
+
184
+ sage: P = Poset(([1,2,3,4], [[1,2],[1,3],[3,4]]), linear_extension=True, facade=False)
185
+ sage: p = P.linear_extension([1,3,4,2])
186
+ sage: Q = p.to_poset(); Q
187
+ Finite poset containing 4 elements with distinguished linear extension
188
+ sage: P == Q
189
+ False
190
+
191
+ The default linear extension remains the same::
192
+
193
+ sage: list(P)
194
+ [1, 2, 3, 4]
195
+ sage: list(Q)
196
+ [1, 2, 3, 4]
197
+
198
+ But the relabelling can be seen on cover relations::
199
+
200
+ sage: P.cover_relations()
201
+ [[1, 2], [1, 3], [3, 4]]
202
+ sage: Q.cover_relations()
203
+ [[1, 2], [1, 4], [2, 3]]
204
+
205
+ sage: p = P.linear_extension([1,2,3,4])
206
+ sage: Q = p.to_poset()
207
+ sage: P == Q
208
+ True
209
+ """
210
+ P = self.parent().poset()
211
+ old = (P.unwrap(x) for x in self)
212
+ new = [P.unwrap(x) for x in P]
213
+ relabelling = dict(zip(old, new))
214
+ return P.relabel(relabelling).with_linear_extension(new)
215
+
216
+ def is_greedy(self) -> bool:
217
+ r"""
218
+ Return ``True`` if the linear extension is greedy.
219
+
220
+ A linear extension `[e_1, e_2, \ldots, e_n]` is *greedy* if for
221
+ every `i` either `e_{i+1}` covers `e_i` or all upper covers
222
+ of `e_i` have at least one lower cover that is not in
223
+ `[e_1, e_2, \ldots, e_i]`.
224
+
225
+ Informally said a linear extension is greedy if it "always
226
+ goes up when possible" and so has no unnecessary jumps.
227
+
228
+ EXAMPLES::
229
+
230
+ sage: P = posets.PentagonPoset() # needs sage.modules
231
+ sage: for l in P.linear_extensions(): # needs sage.modules
232
+ ....: if not l.is_greedy():
233
+ ....: print(l)
234
+ [0, 2, 1, 3, 4]
235
+
236
+ TESTS::
237
+
238
+ sage: E = Poset()
239
+ sage: E.linear_extensions()[0].is_greedy()
240
+ True
241
+ """
242
+ P = self.poset()
243
+ for i in range(len(self) - 1):
244
+ if not P.covers(self[i], self[i + 1]):
245
+ for u in P.upper_covers(self[i]):
246
+ if all(l in self[:i + 1] for l in P.lower_covers(u)):
247
+ return False
248
+ return True
249
+
250
+ def is_supergreedy(self) -> bool:
251
+ r"""
252
+ Return ``True`` if the linear extension is supergreedy.
253
+
254
+ A linear extension of a poset `P` with elements `\{x_1,x_2,...,x_t\}`
255
+ is *super greedy*, if it can be obtained using the following
256
+ algorithm: choose `x_1` to be a minimal element of `P`;
257
+ suppose `X = \{x_1,...,x_i\}` have been chosen; let `M` be
258
+ the set of minimal elements of `P\setminus X`. If there is an element
259
+ of `M` which covers an element `x_j` in `X`, then let `x_{i+1}`
260
+ be one of these such that `j` is maximal; otherwise, choose `x_{i+1}`
261
+ to be any element of `M`.
262
+
263
+ Informally, a linear extension is supergreedy if it "always
264
+ goes up and receedes the least"; in other words, supergreedy
265
+ linear extensions are depth-first linear extensions.
266
+ For more details see [KTZ1987]_.
267
+
268
+ EXAMPLES::
269
+
270
+ sage: X = [0,1,2,3,4,5,6]
271
+ sage: Y = [[0,5],[1,4],[1,5],[3,6],[4,3],[5,6],[6,2]]
272
+ sage: P = Poset((X,Y), cover_relations=True, facade=False)
273
+ sage: for l in P.linear_extensions(): # needs sage.modules
274
+ ....: if l.is_supergreedy():
275
+ ....: print(l)
276
+ [1, 4, 3, 0, 5, 6, 2]
277
+ [0, 1, 4, 3, 5, 6, 2]
278
+ [0, 1, 5, 4, 3, 6, 2]
279
+
280
+ sage: Q = posets.PentagonPoset() # needs sage.modules
281
+ sage: for l in Q.linear_extensions(): # needs sage.modules sage.rings.finite_rings
282
+ ....: if not l.is_supergreedy():
283
+ ....: print(l)
284
+ [0, 2, 1, 3, 4]
285
+
286
+ TESTS::
287
+
288
+ sage: T = Poset()
289
+ sage: T.linear_extensions()[0].is_supergreedy()
290
+ True
291
+ """
292
+ H = self.poset().hasse_diagram()
293
+ L = sources = H.sources()
294
+ linext = []
295
+ for e in self:
296
+ if e not in L:
297
+ return False
298
+ linext.append(e)
299
+ for y in reversed(linext):
300
+ L = [x for x in H.neighbor_out_iterator(y)
301
+ if x not in linext
302
+ and all(low in linext for low in H.neighbor_in_iterator(x))]
303
+ if L:
304
+ break
305
+ else:
306
+ L = sources = [x for x in sources if x not in linext]
307
+ return True
308
+
309
+ def tau(self, i):
310
+ r"""
311
+ Return the operator `\tau_i` on linear extensions ``self`` of a poset.
312
+
313
+ INPUT:
314
+
315
+ - ``i`` -- integer between `1` and `n-1`, where `n` is the
316
+ cardinality of the poset
317
+
318
+ The operator `\tau_i` on a linear extension `\pi` of a poset
319
+ `P` interchanges positions `i` and `i+1` if the result is
320
+ again a linear extension of `P`, and otherwise acts
321
+ trivially. For more details, see [Stan2009]_.
322
+
323
+ EXAMPLES::
324
+
325
+ sage: P = Poset(([1,2,3,4], [[1,3],[1,4],[2,3]]), linear_extension=True)
326
+ sage: L = P.linear_extensions()
327
+ sage: l = L.an_element(); l
328
+ [1, 2, 3, 4]
329
+ sage: l.tau(1)
330
+ [2, 1, 3, 4]
331
+ sage: for p in L: # needs sage.modules
332
+ ....: for i in range(1,4):
333
+ ....: print("{} {} {}".format(i, p, p.tau(i)))
334
+ 1 [1, 2, 3, 4] [2, 1, 3, 4]
335
+ 2 [1, 2, 3, 4] [1, 2, 3, 4]
336
+ 3 [1, 2, 3, 4] [1, 2, 4, 3]
337
+ 1 [2, 1, 3, 4] [1, 2, 3, 4]
338
+ 2 [2, 1, 3, 4] [2, 1, 3, 4]
339
+ 3 [2, 1, 3, 4] [2, 1, 4, 3]
340
+ 1 [2, 1, 4, 3] [1, 2, 4, 3]
341
+ 2 [2, 1, 4, 3] [2, 1, 4, 3]
342
+ 3 [2, 1, 4, 3] [2, 1, 3, 4]
343
+ 1 [1, 4, 2, 3] [1, 4, 2, 3]
344
+ 2 [1, 4, 2, 3] [1, 2, 4, 3]
345
+ 3 [1, 4, 2, 3] [1, 4, 2, 3]
346
+ 1 [1, 2, 4, 3] [2, 1, 4, 3]
347
+ 2 [1, 2, 4, 3] [1, 4, 2, 3]
348
+ 3 [1, 2, 4, 3] [1, 2, 3, 4]
349
+
350
+ TESTS::
351
+
352
+ sage: type(l.tau(1))
353
+ <class 'sage.combinat.posets.linear_extensions.LinearExtensionsOfPoset_with_category.element_class'>
354
+ sage: l.tau(2) == l
355
+ True
356
+ """
357
+ P = self.poset()
358
+ a = self[i - 1]
359
+ b = self[i]
360
+ if P.lt(a, b) or P.lt(b, a):
361
+ return self
362
+ with self.clone() as q:
363
+ q[i - 1] = b
364
+ q[i] = a
365
+ return q
366
+
367
+ def promotion(self, i=1):
368
+ r"""
369
+ Compute the (generalized) promotion on the linear extension of a poset.
370
+
371
+ INPUT:
372
+
373
+ - ``i`` -- (default: `1`) an integer between `1` and `n-1`,
374
+ where `n` is the cardinality of the poset
375
+
376
+ The `i`-th generalized promotion operator `\partial_i` on a linear
377
+ extension `\pi` is defined as `\pi \tau_i \tau_{i+1} \cdots \tau_{n-1}`,
378
+ where `n` is the size of the linear extension (or size of the
379
+ underlying poset).
380
+
381
+ For more details see [Stan2009]_.
382
+
383
+ .. SEEALSO:: :meth:`tau`, :meth:`evacuation`
384
+
385
+ EXAMPLES::
386
+
387
+ sage: P = Poset(([1,2,3,4,5,6,7], [[1,2],[1,4],[2,3],[2,5],[3,6],[4,7],[5,6]]))
388
+ sage: p = P.linear_extension([1,2,3,4,5,6,7])
389
+ sage: q = p.promotion(4); q
390
+ [1, 2, 3, 5, 6, 4, 7]
391
+ sage: p.to_poset() == q.to_poset()
392
+ False
393
+ sage: p.to_poset().is_isomorphic(q.to_poset())
394
+ True
395
+ """
396
+ for j in range(i, len(self)):
397
+ self = self.tau(j)
398
+ return self
399
+
400
+ def evacuation(self):
401
+ r"""
402
+ Compute evacuation on the linear extension of a poset.
403
+
404
+ Evacuation on a linear extension `\pi` of length `n` is defined as
405
+ `\pi (\tau_1 \cdots \tau_{n-1}) (\tau_1 \cdots \tau_{n-2}) \cdots (\tau_1)`.
406
+ For more details see [Stan2009]_.
407
+
408
+ .. SEEALSO:: :meth:`tau`, :meth:`promotion`
409
+
410
+ EXAMPLES::
411
+
412
+ sage: P = Poset(([1,2,3,4,5,6,7], [[1,2],[1,4],[2,3],[2,5],[3,6],[4,7],[5,6]]))
413
+ sage: p = P.linear_extension([1,2,3,4,5,6,7])
414
+ sage: p.evacuation()
415
+ [1, 4, 2, 3, 7, 5, 6]
416
+ sage: p.evacuation().evacuation() == p
417
+ True
418
+ """
419
+ for i in reversed(range(1, len(self) + 1)):
420
+ for j in range(1, i):
421
+ self = self.tau(j)
422
+ return self
423
+
424
+ def jump_count(self) -> int:
425
+ r"""
426
+ Return the number of jumps in the linear extension.
427
+
428
+ A *jump* in a linear extension `[e_1, e_2, \ldots, e_n]`
429
+ is a pair `(e_i, e_{i+1})` such that `e_{i+1}` does not
430
+ cover `e_i`.
431
+
432
+ .. SEEALSO::
433
+
434
+ - :meth:`sage.combinat.posets.posets.FinitePoset.jump_number()`
435
+
436
+ EXAMPLES::
437
+
438
+ sage: B3 = posets.BooleanLattice(3)
439
+ sage: l1 = B3.linear_extension((0, 1, 2, 3, 4, 5, 6, 7))
440
+ sage: l1.jump_count()
441
+ 3
442
+ sage: l2 = B3.linear_extension((0, 1, 2, 4, 3, 5, 6, 7))
443
+ sage: l2.jump_count()
444
+ 5
445
+
446
+ TESTS::
447
+
448
+ sage: E = Poset()
449
+ sage: E.linear_extensions()[0].jump_count()
450
+ 0
451
+ sage: C4 = posets.ChainPoset(4)
452
+ sage: C4.linear_extensions()[0].jump_count()
453
+ 0
454
+ sage: A4 = posets.AntichainPoset(4)
455
+ sage: A4.linear_extensions()[0].jump_count()
456
+ 3
457
+ """
458
+ P = self.poset()
459
+ n = 0
460
+ for i in range(len(self) - 1):
461
+ if not P.covers(self[i], self[i + 1]):
462
+ n += 1
463
+ return n
464
+
465
+
466
+ class LinearExtensionsOfPoset(UniqueRepresentation, Parent):
467
+ """
468
+ The set of all linear extensions of a finite poset.
469
+
470
+ INPUT:
471
+
472
+ - ``poset`` -- a poset `P` of size `n`
473
+ - ``facade`` -- boolean (default: ``False``)
474
+
475
+ .. SEEALSO::
476
+
477
+ - :meth:`sage.combinat.posets.posets.FinitePoset.linear_extensions`
478
+
479
+ EXAMPLES::
480
+
481
+ sage: elms = [1,2,3,4]
482
+ sage: rels = [[1,3],[1,4],[2,3]]
483
+ sage: P = Poset((elms, rels), linear_extension=True)
484
+ sage: L = P.linear_extensions(); L
485
+ The set of all linear extensions of
486
+ Finite poset containing 4 elements with distinguished linear extension
487
+ sage: L.cardinality()
488
+ 5
489
+ sage: L.list() # needs sage.modules
490
+ [[1, 2, 3, 4], [2, 1, 3, 4], [2, 1, 4, 3], [1, 4, 2, 3], [1, 2, 4, 3]]
491
+ sage: L.an_element()
492
+ [1, 2, 3, 4]
493
+ sage: L.poset()
494
+ Finite poset containing 4 elements with distinguished linear extension
495
+ """
496
+
497
+ @staticmethod
498
+ def __classcall_private__(cls, poset, facade=False):
499
+ r"""
500
+ Straighten arguments before unique representation.
501
+
502
+ TESTS::
503
+
504
+ sage: from sage.combinat.posets.linear_extensions import LinearExtensionsOfPoset
505
+ sage: P = Poset(([1,2],[[1,2]]))
506
+ sage: L = LinearExtensionsOfPoset(P)
507
+ sage: type(L)
508
+ <class 'sage.combinat.posets.linear_extensions.LinearExtensionsOfPoset_with_category'>
509
+ sage: L is LinearExtensionsOfPoset(P,facade=False)
510
+ True
511
+ """
512
+ return super().__classcall__(cls, poset, facade=facade)
513
+
514
+ def __init__(self, poset, facade) -> None:
515
+ """
516
+ TESTS::
517
+
518
+ sage: from sage.combinat.posets.linear_extensions import LinearExtensionsOfPoset
519
+ sage: P = Poset(([1,2,3],[[1,2],[1,3]]))
520
+ sage: L = P.linear_extensions()
521
+ sage: L is LinearExtensionsOfPoset(P)
522
+ True
523
+ sage: L._poset is P
524
+ True
525
+ sage: TestSuite(L).run() # needs sage.modules
526
+
527
+ sage: P = Poset((divisors(15), attrcall("divides")))
528
+ sage: L = P.linear_extensions()
529
+ sage: TestSuite(L).run() # needs sage.modules
530
+
531
+ sage: P = Poset((divisors(15), attrcall("divides")), facade=True)
532
+ sage: L = P.linear_extensions()
533
+ sage: TestSuite(L).run() # needs sage.modules
534
+
535
+ sage: L = P.linear_extensions(facade=True)
536
+ sage: TestSuite(L).run(skip='_test_an_element') # needs sage.modules
537
+ """
538
+ self._poset = poset
539
+ self._is_facade = facade
540
+ if facade:
541
+ facade = (list,)
542
+ Parent.__init__(self, category=FiniteEnumeratedSets(), facade=facade)
543
+
544
+ def _repr_(self) -> str:
545
+ """
546
+ TESTS::
547
+
548
+ sage: P = Poset(([1,2,3],[[1,2],[1,3]]))
549
+ sage: P.linear_extensions()
550
+ The set of all linear extensions of Finite poset containing 3 elements
551
+ """
552
+ return "The set of all linear extensions of %s" % (self._poset)
553
+
554
+ def poset(self):
555
+ r"""
556
+ Return the underlying original poset.
557
+
558
+ EXAMPLES::
559
+
560
+ sage: P = Poset(([1,2,3,4], [[1,2],[2,3],[1,4]]))
561
+ sage: L = P.linear_extensions()
562
+ sage: L.poset()
563
+ Finite poset containing 4 elements
564
+ """
565
+ return self._poset
566
+
567
+ def cardinality(self):
568
+ """
569
+ Return the number of linear extensions.
570
+
571
+ EXAMPLES::
572
+
573
+ sage: N = Poset({0: [2, 3], 1: [3]})
574
+ sage: N.linear_extensions().cardinality()
575
+ 5
576
+
577
+ TESTS::
578
+
579
+ sage: Poset().linear_extensions().cardinality()
580
+ 1
581
+ sage: posets.ChainPoset(1).linear_extensions().cardinality()
582
+ 1
583
+ sage: posets.BooleanLattice(4).linear_extensions().cardinality()
584
+ 1680384
585
+ """
586
+ from sage.rings.integer import Integer
587
+
588
+ n = len(self._poset)
589
+ if not n:
590
+ return Integer(1)
591
+
592
+ up = self._poset._hasse_diagram.to_dictionary()
593
+ # Convert to the Hasse diagram so our poset can be realized on
594
+ # the set {0,...,n-1} with a nice dictionary of edges
595
+
596
+ for i in range(n):
597
+ up[n - 1 - i] = sorted(set(up[n - 1 - i] +
598
+ [item for x in up[n - 1 - i]
599
+ for item in up[x]]))
600
+ # Compute the principal order filter for each element.
601
+
602
+ Jup = {1: []}
603
+ # Jup will be a dictionary giving up edges in J(P)
604
+
605
+ # We will perform a loop where after k loops, we will have a
606
+ # list of up edges for the lattice of order ideals for P
607
+ # restricted to entries 0,...,k.
608
+ loc = [1] * n
609
+
610
+ # This list will be indexed by entries in P. After k loops,
611
+ # the entry loc[i] will correspond to the element of J(P) that
612
+ # is the principal order ideal of i, restricted to the
613
+ # elements 0,...,k .
614
+
615
+ m = 1
616
+ # m keeps track of how many elements we currently have in J(P).
617
+ # We start with just the empty order ideal, and no relations.
618
+ for x in range(n):
619
+ # Use the existing Jup table to compute all covering
620
+ # relations in J(P) for things that are above loc(x).
621
+ K0 = [[loc[x]]]
622
+ j = 0
623
+ while K0[j]:
624
+ K0.append([b for a in K0[j] for b in Jup[a]])
625
+ j += 1
626
+ K = sorted({item for sublist in K0 for item in sublist})
627
+ for j in range(len(K)):
628
+ i = m + j + 1
629
+ Jup[i] = [m + K.index(a) + 1 for a in Jup[K[j]]]
630
+ # These are copies of the covering relations with
631
+ # elements from K, but now with the underlying
632
+ # elements containing x.
633
+ Jup[K[j]] = Jup[K[j]] + [i]
634
+ # There are the new covering relations we get between
635
+ # ideals that don't contain x and those that do.
636
+ for y in up[x]:
637
+ loc[y] = K.index(loc[y]) + m + 1
638
+ # Updates loc[y] if y is above x.
639
+ m += len(K)
640
+ # Now we have a dictionary of covering relations for J(P). The
641
+ # following shortcut works to count maximal chains, since we
642
+ # made J(P) naturally labelled, and J(P) has a unique maximal
643
+ # element and minimum element.
644
+
645
+ Jup[m] = Integer(1)
646
+ while m > 1:
647
+ m -= 1
648
+ ct = Integer(0)
649
+ for j in Jup[m]:
650
+ ct += Jup[j]
651
+ Jup[m] = ct
652
+ return ct
653
+
654
+ def __iter__(self):
655
+ r"""
656
+ Iterate through the linear extensions of the underlying poset.
657
+
658
+ EXAMPLES::
659
+
660
+ sage: elms = [1,2,3,4]
661
+ sage: rels = [[1,3],[1,4],[2,3]]
662
+ sage: P = Poset((elms, rels), linear_extension=True)
663
+ sage: L = P.linear_extensions()
664
+ sage: list(L) # needs sage.modules
665
+ [[1, 2, 3, 4], [2, 1, 3, 4], [2, 1, 4, 3], [1, 4, 2, 3], [1, 2, 4, 3]]
666
+ """
667
+ from sage.combinat.posets.linear_extension_iterator import linear_extension_iterator
668
+ vertex_to_element = self._poset._vertex_to_element
669
+ for lin_ext in linear_extension_iterator(self._poset._hasse_diagram):
670
+ yield self._element_constructor_([vertex_to_element(_) for _ in lin_ext])
671
+
672
+ def __contains__(self, obj) -> bool:
673
+ """
674
+ Membership testing
675
+
676
+ EXAMPLES::
677
+
678
+ sage: P = Poset((divisors(12), attrcall("divides")), facade=True, linear_extension=True)
679
+ sage: P.list()
680
+ [1, 2, 3, 4, 6, 12]
681
+ sage: L = P.linear_extensions()
682
+ sage: L([1, 2, 4, 3, 6, 12]) in L
683
+ True
684
+ sage: [1, 2, 4, 3, 6, 12] in L
685
+ False
686
+
687
+ sage: L = P.linear_extensions(facade=True)
688
+ sage: [1, 2, 4, 3, 6, 12] in L
689
+ True
690
+ sage: [1, 3, 2, 6, 4, 12] in L
691
+ True
692
+ sage: [1, 3, 6, 2, 4, 12] in L
693
+ False
694
+
695
+ sage: [p for p in Permutations(list(P)) if list(p) in L]
696
+ [[1, 2, 3, 4, 6, 12], [1, 2, 3, 6, 4, 12], [1, 2, 4, 3, 6, 12], [1, 3, 2, 4, 6, 12], [1, 3, 2, 6, 4, 12]]
697
+ """
698
+ if not self._is_facade:
699
+ return super().__contains__(obj)
700
+ return (isinstance(obj, (list, tuple)) and
701
+ self.poset().is_linear_extension(obj))
702
+
703
+ def markov_chain_digraph(self, action='promotion', labeling='identity') -> DiGraph:
704
+ r"""
705
+ Return the digraph of the action of generalized promotion or tau on ``self``.
706
+
707
+ INPUT:
708
+
709
+ - ``action`` -- 'promotion' or 'tau' (default: ``'promotion'``)
710
+ - ``labeling`` -- 'identity' or 'source' (default: ``'identity'``)
711
+
712
+ .. TODO::
713
+
714
+ - generalize this feature by accepting a family of operators as input
715
+ - move up in some appropriate category
716
+
717
+ This method creates a graph with vertices being the linear extensions of a given finite
718
+ poset and an edge from `\pi` to `\pi'` if `\pi' = \pi \partial_i` where `\partial_i` is
719
+ the promotion operator (see :meth:`promotion`) if ``action`` is set to ``promotion``
720
+ and `\tau_i` (see :meth:`tau`) if ``action`` is set to ``tau``. The label of the edge
721
+ is `i` (resp. `\pi_i`) if ``labeling`` is set to ``identity`` (resp. ``source``).
722
+
723
+ EXAMPLES::
724
+
725
+ sage: # needs sage.modules
726
+ sage: P = Poset(([1,2,3,4], [[1,3],[1,4],[2,3]]), linear_extension=True)
727
+ sage: L = P.linear_extensions()
728
+ sage: G = L.markov_chain_digraph(); G
729
+ Looped multi-digraph on 5 vertices
730
+ sage: G.vertices(sort=True, key=repr)
731
+ [[1, 2, 3, 4], [1, 2, 4, 3], [1, 4, 2, 3], [2, 1, 3, 4], [2, 1, 4, 3]]
732
+ sage: G.edges(sort=True, key=repr)
733
+ [([1, 2, 3, 4], [1, 2, 3, 4], 4), ([1, 2, 3, 4], [1, 2, 4, 3], 2), ([1, 2, 3, 4], [1, 2, 4, 3], 3),
734
+ ([1, 2, 3, 4], [2, 1, 4, 3], 1), ([1, 2, 4, 3], [1, 2, 3, 4], 3), ([1, 2, 4, 3], [1, 2, 4, 3], 4),
735
+ ([1, 2, 4, 3], [1, 4, 2, 3], 2), ([1, 2, 4, 3], [2, 1, 3, 4], 1), ([1, 4, 2, 3], [1, 2, 3, 4], 1),
736
+ ([1, 4, 2, 3], [1, 2, 3, 4], 2), ([1, 4, 2, 3], [1, 4, 2, 3], 3), ([1, 4, 2, 3], [1, 4, 2, 3], 4),
737
+ ([2, 1, 3, 4], [1, 2, 4, 3], 1), ([2, 1, 3, 4], [2, 1, 3, 4], 4), ([2, 1, 3, 4], [2, 1, 4, 3], 2),
738
+ ([2, 1, 3, 4], [2, 1, 4, 3], 3), ([2, 1, 4, 3], [1, 4, 2, 3], 1), ([2, 1, 4, 3], [2, 1, 3, 4], 2),
739
+ ([2, 1, 4, 3], [2, 1, 3, 4], 3), ([2, 1, 4, 3], [2, 1, 4, 3], 4)]
740
+ sage: G = L.markov_chain_digraph(labeling='source')
741
+ sage: G.vertices(sort=True, key=repr)
742
+ [[1, 2, 3, 4], [1, 2, 4, 3], [1, 4, 2, 3], [2, 1, 3, 4], [2, 1, 4, 3]]
743
+ sage: G.edges(sort=True, key=repr)
744
+ [([1, 2, 3, 4], [1, 2, 3, 4], 4), ([1, 2, 3, 4], [1, 2, 4, 3], 2), ([1, 2, 3, 4], [1, 2, 4, 3], 3),
745
+ ([1, 2, 3, 4], [2, 1, 4, 3], 1), ([1, 2, 4, 3], [1, 2, 3, 4], 4), ([1, 2, 4, 3], [1, 2, 4, 3], 3),
746
+ ([1, 2, 4, 3], [1, 4, 2, 3], 2), ([1, 2, 4, 3], [2, 1, 3, 4], 1), ([1, 4, 2, 3], [1, 2, 3, 4], 1),
747
+ ([1, 4, 2, 3], [1, 2, 3, 4], 4), ([1, 4, 2, 3], [1, 4, 2, 3], 2), ([1, 4, 2, 3], [1, 4, 2, 3], 3),
748
+ ([2, 1, 3, 4], [1, 2, 4, 3], 2), ([2, 1, 3, 4], [2, 1, 3, 4], 4), ([2, 1, 3, 4], [2, 1, 4, 3], 1),
749
+ ([2, 1, 3, 4], [2, 1, 4, 3], 3), ([2, 1, 4, 3], [1, 4, 2, 3], 2), ([2, 1, 4, 3], [2, 1, 3, 4], 1),
750
+ ([2, 1, 4, 3], [2, 1, 3, 4], 4), ([2, 1, 4, 3], [2, 1, 4, 3], 3)]
751
+
752
+ The edges of the graph are by default colored using blue for
753
+ edge 1, red for edge 2, green for edge 3, and yellow for edge 4::
754
+
755
+ sage: view(G) # optional - dot2tex graphviz, not tested (opens external window)
756
+
757
+ Alternatively, one may get the graph of the action of the ``tau`` operator::
758
+
759
+ sage: G = L.markov_chain_digraph(action='tau'); G
760
+ Looped multi-digraph on 5 vertices
761
+ sage: G.vertices(sort=True, key=repr)
762
+ [[1, 2, 3, 4], [1, 2, 4, 3], [1, 4, 2, 3], [2, 1, 3, 4], [2, 1, 4, 3]]
763
+ sage: G.edges(sort=True, key=repr)
764
+ [([1, 2, 3, 4], [1, 2, 3, 4], 2), ([1, 2, 3, 4], [1, 2, 4, 3], 3), ([1, 2, 3, 4], [2, 1, 3, 4], 1),
765
+ ([1, 2, 4, 3], [1, 2, 3, 4], 3), ([1, 2, 4, 3], [1, 4, 2, 3], 2), ([1, 2, 4, 3], [2, 1, 4, 3], 1),
766
+ ([1, 4, 2, 3], [1, 2, 4, 3], 2), ([1, 4, 2, 3], [1, 4, 2, 3], 1), ([1, 4, 2, 3], [1, 4, 2, 3], 3),
767
+ ([2, 1, 3, 4], [1, 2, 3, 4], 1), ([2, 1, 3, 4], [2, 1, 3, 4], 2), ([2, 1, 3, 4], [2, 1, 4, 3], 3),
768
+ ([2, 1, 4, 3], [1, 2, 4, 3], 1), ([2, 1, 4, 3], [2, 1, 3, 4], 3), ([2, 1, 4, 3], [2, 1, 4, 3], 2)]
769
+ sage: view(G) # optional - dot2tex graphviz, not tested (opens external window)
770
+
771
+ .. SEEALSO:: :meth:`markov_chain_transition_matrix`, :meth:`promotion`, :meth:`tau`
772
+
773
+ TESTS::
774
+
775
+ sage: P = Poset(([1,2,3,4], [[1,3],[1,4],[2,3]]), linear_extension=True, facade=True)
776
+ sage: L = P.linear_extensions()
777
+ sage: G = L.markov_chain_digraph(labeling='source'); G
778
+ Looped multi-digraph on 5 vertices
779
+ """
780
+ L = sorted(self)
781
+ d = {x: {y: [] for y in L} for x in L}
782
+ if action == 'promotion':
783
+ R = list(range(self.poset().cardinality()))
784
+ else:
785
+ R = list(range(self.poset().cardinality() - 1))
786
+ if labeling == 'source':
787
+ for x in L:
788
+ for i in R:
789
+ child = getattr(x, action)(i + 1)
790
+ d[x][child] += [self.poset().unwrap(x[i])]
791
+ else:
792
+ for x in L:
793
+ for i in R:
794
+ child = getattr(x, action)(i + 1)
795
+ d[x][child] += [i + 1]
796
+ G = DiGraph(d, format='dict_of_dicts')
797
+ if have_dot2tex():
798
+ G.set_latex_options(format='dot2tex', edge_labels=True,
799
+ color_by_label={1: "blue", 2: "red",
800
+ 3: "green", 4: "yellow"})
801
+ return G
802
+
803
+ def markov_chain_transition_matrix(self, action='promotion', labeling='identity'):
804
+ r"""
805
+ Return the transition matrix of the Markov chain for the action of
806
+ generalized promotion or tau on ``self``.
807
+
808
+ INPUT:
809
+
810
+ - ``action`` -- ``'promotion'`` or ``'tau'`` (default: ``'promotion'``)
811
+ - ``labeling`` -- ``'identity'`` or ``'source'`` (default: ``'identity'``)
812
+
813
+ This method yields the transition matrix of the Markov chain defined by
814
+ the action of the generalized promotion operator `\partial_i` (resp.
815
+ `\tau_i`) on the set of linear extensions of a finite poset. Here the
816
+ transition from the linear extension `\pi` to `\pi'`, where
817
+ `\pi' = \pi \partial_i` (resp. `\pi'= \pi \tau_i`) is counted with
818
+ weight `x_i` (resp. `x_{\pi_i}` if ``labeling`` is set to ``source``).
819
+
820
+ EXAMPLES::
821
+
822
+ sage: P = Poset(([1,2,3,4], [[1,3],[1,4],[2,3]]), linear_extension=True)
823
+ sage: L = P.linear_extensions()
824
+ sage: L.markov_chain_transition_matrix() # needs sage.modules
825
+ [-x0 - x1 - x2 x2 x0 + x1 0 0]
826
+ [ x1 + x2 -x0 - x1 - x2 0 x0 0]
827
+ [ 0 x1 -x0 - x1 0 x0]
828
+ [ 0 x0 0 -x0 - x1 - x2 x1 + x2]
829
+ [ x0 0 0 x1 + x2 -x0 - x1 - x2]
830
+
831
+ sage: L.markov_chain_transition_matrix(labeling='source') # needs sage.modules
832
+ [-x0 - x1 - x2 x3 x0 + x3 0 0]
833
+ [ x1 + x2 -x0 - x1 - x3 0 x1 0]
834
+ [ 0 x1 -x0 - x3 0 x1]
835
+ [ 0 x0 0 -x0 - x1 - x2 x0 + x3]
836
+ [ x0 0 0 x0 + x2 -x0 - x1 - x3]
837
+
838
+ sage: L.markov_chain_transition_matrix(action='tau') # needs sage.modules
839
+ [ -x0 - x2 x2 0 x0 0]
840
+ [ x2 -x0 - x1 - x2 x1 0 x0]
841
+ [ 0 x1 -x1 0 0]
842
+ [ x0 0 0 -x0 - x2 x2]
843
+ [ 0 x0 0 x2 -x0 - x2]
844
+
845
+ sage: L.markov_chain_transition_matrix(action='tau', labeling='source') # needs sage.modules
846
+ [ -x0 - x2 x3 0 x1 0]
847
+ [ x2 -x0 - x1 - x3 x3 0 x1]
848
+ [ 0 x1 -x3 0 0]
849
+ [ x0 0 0 -x1 - x2 x3]
850
+ [ 0 x0 0 x2 -x1 - x3]
851
+
852
+ .. SEEALSO:: :meth:`markov_chain_digraph`, :meth:`promotion`, :meth:`tau`
853
+ """
854
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
855
+ from sage.matrix.constructor import matrix
856
+ L = sorted(self.list())
857
+ n = self.poset().cardinality()
858
+ R = PolynomialRing(QQ, 'x', n)
859
+ x = [R.gen(i) for i in range(n)]
860
+ l = self.cardinality()
861
+ M = {(i, j): 0 for i in range(l) for j in range(l)}
862
+ if labeling == 'source':
863
+ for i in range(l):
864
+ perm = [self.poset().unwrap(k) for k in L[i]]
865
+ for j in range(n - 1):
866
+ p = getattr(L[i], action)(j + 1)
867
+ M[(L.index(p), i)] += x[perm[j] - 1]
868
+ else:
869
+ for i in range(l):
870
+ for j in range(n - 1):
871
+ p = getattr(L[i], action)(j + 1)
872
+ M[(L.index(p), i)] += x[j]
873
+ for i in range(l):
874
+ M[(i, i)] += -sum(M[(j, i)] for j in range(l))
875
+ return matrix(l, l, lambda x, y: M[(x, y)])
876
+
877
+ def _element_constructor_(self, lst, check=True):
878
+ r"""
879
+ Constructor for elements of this class.
880
+
881
+ TESTS::
882
+
883
+ sage: P = Poset(([1,2,3,4], [[1,2],[1,4],[2,3]]))
884
+ sage: L = P.linear_extensions()
885
+ sage: x = L._element_constructor_([1,2,4,3]); x
886
+ [1, 2, 4, 3]
887
+ sage: x.parent() is L
888
+ True
889
+
890
+ sage: L._element_constructor_([4,3,2,1])
891
+ Traceback (most recent call last):
892
+ ...
893
+ ValueError: [4, 3, 2, 1] is not a linear extension of Finite poset containing 4 elements
894
+ sage: L._element_constructor_([4,3,2,1],check=False)
895
+ [4, 3, 2, 1]
896
+ """
897
+ if isinstance(lst, LinearExtensionOfPoset):
898
+ lst = list(lst)
899
+ if not isinstance(lst, (list, tuple)):
900
+ raise TypeError("input should be a list or tuple")
901
+ lst = [self._poset(e) for e in lst]
902
+ if self._is_facade:
903
+ return lst
904
+ return self.element_class(self, lst, check)
905
+
906
+ Element = LinearExtensionOfPoset
907
+
908
+
909
+ class LinearExtensionsOfPosetWithHooks(LinearExtensionsOfPoset):
910
+ r"""
911
+ Linear extensions such that the poset has well-defined
912
+ hook lengths (i.e., d-complete).
913
+ """
914
+
915
+ def cardinality(self):
916
+ r"""
917
+ Count the number of linear extensions using a hook-length formula.
918
+
919
+ EXAMPLES::
920
+
921
+ sage: from sage.combinat.posets.poset_examples import Posets
922
+ sage: P = Posets.YoungDiagramPoset(Partition([3,2]), dual=True) # needs sage.combinat sage.modules
923
+ sage: P.linear_extensions().cardinality() # needs sage.combinat sage.modules
924
+ 5
925
+ """
926
+ num_elmts = self._poset.cardinality()
927
+
928
+ if num_elmts == 0:
929
+ return 1
930
+
931
+ hook_product = self._poset.hook_product()
932
+ return factorial(num_elmts) // hook_product
933
+
934
+
935
+ class LinearExtensionsOfForest(LinearExtensionsOfPoset):
936
+ r"""
937
+ Linear extensions such that the poset is a forest.
938
+ """
939
+
940
+ def cardinality(self):
941
+ r"""
942
+ Use Atkinson's algorithm to compute the number of linear extensions.
943
+
944
+ EXAMPLES::
945
+
946
+ sage: from sage.combinat.posets.forest import ForestPoset
947
+ sage: from sage.combinat.posets.poset_examples import Posets
948
+ sage: P = Poset({0: [2], 1: [2], 2: [3, 4], 3: [], 4: []})
949
+ sage: P.linear_extensions().cardinality() # needs sage.modules
950
+ 4
951
+
952
+ sage: Q = Poset({0: [1], 1: [2, 3], 2: [], 3: [], 4: [5, 6], 5: [], 6: []})
953
+ sage: Q.linear_extensions().cardinality() # needs sage.modules
954
+ 140
955
+ """
956
+ return sum(self.atkinson(self._elements[0]))
957
+
958
+
959
+ class LinearExtensionsOfMobile(LinearExtensionsOfPoset):
960
+ r"""
961
+ Linear extensions for a mobile poset.
962
+ """
963
+
964
+ def cardinality(self):
965
+ r"""
966
+ Return the number of linear extensions by using the determinant
967
+ formula for counting linear extensions of mobiles.
968
+
969
+ EXAMPLES::
970
+
971
+ sage: from sage.combinat.posets.mobile import MobilePoset
972
+ sage: M = MobilePoset(DiGraph([[0,1,2,3,4,5,6,7,8], [(1,0),(3,0),(2,1),(2,3),(4,
973
+ ....: 3), (5,4),(5,6),(7,4),(7,8)]]))
974
+ sage: M.linear_extensions().cardinality() # needs sage.modules
975
+ 1098
976
+
977
+ sage: M1 = posets.RibbonPoset(6, [1,3])
978
+ sage: M1.linear_extensions().cardinality() # needs sage.modules
979
+ 61
980
+
981
+ sage: P = posets.MobilePoset(posets.RibbonPoset(7, [1,3]), # needs sage.combinat sage.modules
982
+ ....: {1: [posets.YoungDiagramPoset([3, 2], dual=True)],
983
+ ....: 3: [posets.DoubleTailedDiamond(6)]},
984
+ ....: anchor=(4, 2, posets.ChainPoset(6)))
985
+ sage: P.linear_extensions().cardinality() # needs sage.combinat sage.modules
986
+ 361628701868606400
987
+ """
988
+ import sage.combinat.posets.d_complete as dc
989
+ # Find folds
990
+ if self._poset._anchor:
991
+ anchor_index = self._poset._ribbon.index(self._poset._anchor[0])
992
+ else:
993
+ anchor_index = len(self._poset._ribbon)
994
+
995
+ folds_up = []
996
+ folds_down = []
997
+
998
+ for ind, r in enumerate(self._poset._ribbon[:-1]):
999
+ if ind < anchor_index and self._poset.is_greater_than(r, self._poset._ribbon[ind + 1]):
1000
+ folds_up.append((self._poset._ribbon[ind + 1], r))
1001
+ elif ind >= anchor_index and self._poset.is_less_than(r, self._poset._ribbon[ind + 1]):
1002
+ folds_down.append((r, self._poset._ribbon[ind + 1]))
1003
+
1004
+ if not folds_up and not folds_down:
1005
+ return dc.DCompletePoset(self._poset).linear_extensions().cardinality()
1006
+
1007
+ # Get ordered connected components
1008
+ cr = self._poset.cover_relations()
1009
+ foldless_cr = [tuple(c) for c in cr if tuple(c) not in folds_up and tuple(c) not in folds_down]
1010
+
1011
+ elmts = list(self._poset._elements)
1012
+ poset_components = DiGraph([elmts, foldless_cr])
1013
+ ordered_poset_components = [poset_components.connected_component_containing_vertex(f[1], sort=False)
1014
+ for f in folds_up]
1015
+ ordered_poset_components.extend(poset_components.connected_component_containing_vertex(f[0], sort=False)
1016
+ for f in folds_down)
1017
+ ordered_poset_components.append(poset_components.connected_component_containing_vertex(
1018
+ folds_down[-1][1] if folds_down else folds_up[-1][0], sort=False))
1019
+
1020
+ # Return determinant
1021
+
1022
+ # Consoludate the folds lists
1023
+ folds = folds_up
1024
+ folds.extend(folds_down)
1025
+
1026
+ mat = []
1027
+ for i in range(len(folds) + 1):
1028
+ mat_poset = dc.DCompletePoset(self._poset.subposet(ordered_poset_components[i]))
1029
+ row = [0] * (i - 1 if i - 1 > 0 else 0) + [1] * (1 if i >= 1 else 0)
1030
+ row.append(1 / mat_poset.hook_product())
1031
+ for j, f in enumerate(folds[i:]):
1032
+ next_poset = self._poset.subposet(ordered_poset_components[j + i + 1])
1033
+ mat_poset = dc.DCompletePoset(next_poset.slant_sum(mat_poset, f[0], f[1]))
1034
+ row.append(1 / mat_poset.hook_product())
1035
+
1036
+ mat.append(row)
1037
+ return matrix(QQ, mat).determinant() * factorial(self._poset.cardinality())