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,1070 @@
1
+ # sage_setup: distribution = sagemath-graphs
2
+ r"""
3
+ Rooted (unordered) trees
4
+
5
+ AUTHORS:
6
+
7
+ - Florent Hivert (2011): initial version
8
+ """
9
+
10
+ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
11
+ from sage.categories.sets_cat import Sets
12
+ from sage.combinat.abstract_tree import (AbstractClonableTree,
13
+ AbstractLabelledClonableTree)
14
+ from sage.misc.cachefunc import cached_function, cached_method
15
+ from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass
16
+ from sage.misc.lazy_attribute import lazy_attribute, lazy_class_attribute
17
+ from sage.rings.integer import Integer
18
+ from sage.rings.integer_ring import ZZ
19
+ from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets
20
+ from sage.sets.family import Family
21
+ from sage.sets.non_negative_integers import NonNegativeIntegers
22
+ from sage.structure.list_clone import NormalizedClonableList
23
+ from sage.structure.parent import Parent
24
+ from sage.structure.unique_representation import UniqueRepresentation
25
+
26
+
27
+ @cached_function
28
+ def number_of_rooted_trees(n):
29
+ r"""
30
+ Return the number of rooted trees with `n` nodes.
31
+
32
+ Compute the number `a(n)` of rooted trees with `n` nodes using the
33
+ recursive formula ([SL000081]_):
34
+
35
+ .. MATH::
36
+
37
+ a(n+1) = \frac{1}{n} \sum_{k=1}^{n} \left( \sum_{d|k} d a(d) \right) a(n-k+1)
38
+
39
+ EXAMPLES::
40
+
41
+ sage: from sage.combinat.rooted_tree import number_of_rooted_trees
42
+ sage: [number_of_rooted_trees(i) for i in range(10)]
43
+ [0, 1, 1, 2, 4, 9, 20, 48, 115, 286]
44
+
45
+ REFERENCES:
46
+
47
+ .. [SL000081] Sloane's :oeis:`A000081`
48
+ """
49
+ if n == 0:
50
+ return Integer(0)
51
+ if n == 1:
52
+ return Integer(1)
53
+ n = Integer(n)
54
+ return sum(sum(d * number_of_rooted_trees(d) for d in k.divisors()) *
55
+ number_of_rooted_trees(n - k)
56
+ for k in ZZ.range(1, n)) // (n - 1)
57
+
58
+
59
+ class RootedTree(AbstractClonableTree, NormalizedClonableList,
60
+ metaclass=InheritComparisonClasscallMetaclass):
61
+ r"""
62
+ The class for unordered rooted trees.
63
+
64
+ The *unordered rooted trees* are an inductive datatype defined
65
+ as follows: An unordered rooted tree is a multiset of
66
+ unordered rooted trees. The trees that belong to this
67
+ multiset are said to be the *children* of the tree. The tree
68
+ that has no children is called a *leaf*.
69
+
70
+ The *labelled rooted trees* (:class:`LabelledRootedTree`)
71
+ form a subclass of this class; they carry additional data.
72
+
73
+ One can create a tree from any list (or more generally iterable)
74
+ of trees or objects convertible to a tree.
75
+
76
+ EXAMPLES::
77
+
78
+ sage: RootedTree([])
79
+ []
80
+ sage: RootedTree([[], [[]]])
81
+ [[], [[]]]
82
+ sage: RootedTree([[[]], []])
83
+ [[], [[]]]
84
+ sage: O = OrderedTree([[[]], []]); O
85
+ [[[]], []]
86
+ sage: RootedTree(O) # this is O with the ordering forgotten
87
+ [[], [[]]]
88
+
89
+ One can also enter any small rooted tree ("small" meaning that
90
+ no vertex has more than `15` children) by using a simple
91
+ numerical encoding of rooted trees, namely, the
92
+ :func:`~sage.combinat.abstract_tree.from_hexacode` function.
93
+ (This function actually parametrizes ordered trees, and here
94
+ we make it parametrize unordered trees by forgetting the
95
+ ordering.) ::
96
+
97
+ sage: from sage.combinat.abstract_tree import from_hexacode
98
+ sage: RT = RootedTrees()
99
+ sage: from_hexacode('32001010', RT)
100
+ [[[]], [[]], [[], []]]
101
+
102
+ .. NOTE::
103
+
104
+ Unlike an ordered tree, an (unordered) rooted tree is a
105
+ multiset (rather than a list) of children. That is, two
106
+ ordered trees which differ from each other by switching
107
+ the order of children are equal to each other as (unordered)
108
+ rooted trees. Internally, rooted trees are encoded as
109
+ :class:`sage.structure.list_clone.NormalizedClonableList`
110
+ instances, and instead of storing their children as an
111
+ actual multiset, they store their children as a list which
112
+ is sorted according to their :meth:`sort_key` value. This
113
+ is as good as storing them as multisets, since the
114
+ :meth:`sort_key` values are sortable and distinguish
115
+ different (unordered) trees. However, if you wish to define
116
+ a subclass of :class:`RootedTree` which implements rooted
117
+ trees with extra structure (say, a class of edge-colored
118
+ rooted trees, or a class of rooted trees with a cyclic
119
+ order on the list of children), then the inherited
120
+ :meth:`sort_key` method will no longer distinguish different
121
+ trees (and, as a consequence, equal trees will be regarded
122
+ as distinct). Thus, you will have to override the method by
123
+ one that does distinguish different trees.
124
+ """
125
+ # Standard auto-parent trick
126
+ @staticmethod
127
+ def __classcall_private__(cls, *args, **opts):
128
+ """
129
+ Ensure that rooted trees created by the enumerated sets and directly
130
+ are the same and that they are instances of :class:`RootedTree`.
131
+
132
+ TESTS::
133
+
134
+ sage: from sage.combinat.rooted_tree import (RootedTrees_all,
135
+ ....: RootedTrees_size)
136
+ sage: issubclass(RootedTrees_all().element_class, RootedTree)
137
+ True
138
+ sage: issubclass(RootedTrees_size(3).element_class, RootedTree)
139
+ True
140
+ sage: t0 = RootedTree([[],[[]]])
141
+ sage: t0.parent()
142
+ Rooted trees
143
+ sage: type(t0)
144
+ <class 'sage.combinat.rooted_tree.RootedTrees_all_with_category.element_class'>
145
+
146
+ sage: t1 = RootedTrees()([[],[[]]])
147
+ sage: t1.parent() is t0.parent()
148
+ True
149
+ sage: type(t1) is type(t0)
150
+ True
151
+
152
+ sage: t1 = RootedTrees(4)([[],[[]]])
153
+ sage: t1.parent() is t0.parent()
154
+ True
155
+ sage: type(t1) is type(t0)
156
+ True
157
+ """
158
+ return cls._auto_parent.element_class(cls._auto_parent, *args, **opts)
159
+
160
+ @lazy_class_attribute
161
+ def _auto_parent(cls):
162
+ """
163
+ The automatic parent of the elements of this class.
164
+
165
+ When calling the constructor of an element of this class, one needs a
166
+ parent. This class attribute specifies which parent is used.
167
+
168
+ EXAMPLES::
169
+
170
+ sage: RootedTree._auto_parent
171
+ Rooted trees
172
+ sage: RootedTree([]).parent()
173
+ Rooted trees
174
+ """
175
+ return RootedTrees_all()
176
+
177
+ def __init__(self, parent=None, children=[], check=True):
178
+ """
179
+ TESTS::
180
+
181
+ sage: RT4 = RootedTrees(4)
182
+ sage: t1 = RT4([[],[[]]])
183
+ sage: TestSuite(t1).run()
184
+
185
+ Some bad inputs are refused::
186
+
187
+ sage: RT4(69)
188
+ Traceback (most recent call last):
189
+ ...
190
+ TypeError: input (69) is not a valid tree
191
+ """
192
+ try:
193
+ children = list(children)
194
+ except TypeError:
195
+ raise TypeError(f"input ({children}) is not a valid tree")
196
+ # if not (children.__class__ is self.__class__
197
+ # and children.parent() == parent):
198
+ children = [self.__class__(parent, x) for x in children]
199
+ NormalizedClonableList.__init__(self, parent, children, check=check)
200
+
201
+ def sort_key(self):
202
+ """
203
+ Return a tuple of nonnegative integers encoding the rooted
204
+ tree ``self``.
205
+
206
+ The first entry of the tuple is the number of children of the
207
+ root. Then the rest of the tuple is obtained as follows: List
208
+ the tuples corresponding to all children (we are regarding the
209
+ children themselves as trees). Order this list (not the
210
+ tuples!) in lexicographically increasing order, and flatten
211
+ it into a single tuple.
212
+
213
+ This tuple characterizes the rooted tree uniquely, and can be
214
+ used to sort the rooted trees.
215
+
216
+ .. NOTE::
217
+
218
+ The tree ``self`` must be normalized before calling this
219
+ method (see :meth:`normalize`). This does not matter
220
+ unless you are inside the :meth:`clone` context manager,
221
+ because outside of it every rooted tree is already
222
+ normalized.
223
+
224
+ .. NOTE::
225
+
226
+ By default, this method does not encode any extra
227
+ structure that ``self`` might have. If you have a subclass
228
+ inheriting from :class:`RootedTree` which allows for some
229
+ extra structure, you need to override :meth:`sort_key` in
230
+ order to preserve this structure (for example, the
231
+ :class:`LabelledRootedTree` class does this in
232
+ :meth:`LabelledRootedTree.sort_key`). See the note in the
233
+ docstring of
234
+ :meth:`sage.combinat.ordered_tree.OrderedTree.sort_key`
235
+ for a pitfall.
236
+
237
+ EXAMPLES::
238
+
239
+ sage: RT = RootedTree
240
+ sage: RT([[],[[]]]).sort_key()
241
+ (2, 0, 1, 0)
242
+ sage: RT([[[]],[]]).sort_key()
243
+ (2, 0, 1, 0)
244
+ """
245
+ l = len(self)
246
+ if l == 0:
247
+ return (0,)
248
+ resu = [l] + [u for t in self for u in t.sort_key()]
249
+ return tuple(resu)
250
+
251
+ def __hash__(self):
252
+ """
253
+ Return a hash for ``self``.
254
+
255
+ This is based on :meth:`sort_key`.
256
+
257
+ EXAMPLES::
258
+
259
+ sage: RT = RootedTree
260
+ sage: hash(RT([[],[[]]])) == hash((2, 0, 1, 0)) # indirect doctest
261
+ True
262
+ """
263
+ return hash(self.sort_key())
264
+
265
+ def normalize(self):
266
+ r"""
267
+ Normalize ``self``.
268
+
269
+ This function is at the core of the implementation of rooted
270
+ (unordered) trees. The underlying structure is provided by
271
+ ordered rooted trees. Every rooted tree is represented by a
272
+ normalized element in the set of its planar embeddings.
273
+
274
+ There should be no need to call ``normalize`` directly as it
275
+ is called automatically upon creation and cloning or
276
+ modification (by ``NormalizedClonableList``).
277
+
278
+ The normalization has a recursive definition. It means first
279
+ that every sub-tree is itself normalized, and also that
280
+ sub-trees are sorted. Here the sort is performed according to
281
+ the values of the :meth:`sort_key` method.
282
+
283
+ EXAMPLES::
284
+
285
+ sage: RT = RootedTree
286
+ sage: RT([[],[[]]]) == RT([[[]],[]]) # indirect doctest
287
+ True
288
+ sage: rt1 = RT([[],[[]]])
289
+ sage: rt2 = RT([[[]],[]])
290
+ sage: rt1 is rt2
291
+ False
292
+ sage: rt1 == rt2
293
+ True
294
+ sage: rt1._get_list() == rt2._get_list()
295
+ True
296
+ """
297
+ self._require_mutable()
298
+ for st in self:
299
+ assert st.is_immutable(), "Subtree {} is not normalized".format(st)
300
+ self._get_list().sort(key=lambda t: t.sort_key())
301
+ # ensure unique representation
302
+ self.set_immutable()
303
+
304
+ def is_empty(self):
305
+ r"""
306
+ Return if ``self`` is the empty tree.
307
+
308
+ For rooted trees, this always returns ``False``.
309
+
310
+ .. NOTE::
311
+
312
+ This is not the same as ``bool(t)``, which returns whether
313
+ ``t`` has some child or not.
314
+
315
+ EXAMPLES::
316
+
317
+ sage: t = RootedTrees(4)([[],[[]]])
318
+ sage: t.is_empty()
319
+ False
320
+ sage: bool(t)
321
+ True
322
+ sage: t = RootedTrees(1)([])
323
+ sage: t.is_empty()
324
+ False
325
+ sage: bool(t)
326
+ False
327
+ """
328
+ return False
329
+
330
+ def graft_list(self, other):
331
+ """
332
+ Return the list of trees obtained by grafting ``other`` on ``self``.
333
+
334
+ Here grafting means that one takes the disjoint union of
335
+ ``self`` and ``other``, chooses a node of ``self``,
336
+ and adds the root of ``other`` to the list of children of
337
+ this node. The root of the resulting tree is the root of
338
+ ``self``. (This can be done for each node of ``self``;
339
+ this method returns the list of all results.)
340
+
341
+ This is useful for free pre-Lie algebras.
342
+
343
+ EXAMPLES::
344
+
345
+ sage: RT = RootedTree
346
+ sage: x = RT([])
347
+ sage: y = RT([x, x])
348
+ sage: x.graft_list(x)
349
+ [[[]]]
350
+ sage: l = y.graft_list(x); l
351
+ [[[], [], []], [[], [[]]], [[], [[]]]]
352
+ sage: [parent(i) for i in l]
353
+ [Rooted trees, Rooted trees, Rooted trees]
354
+
355
+ TESTS::
356
+
357
+ sage: x = RootedTrees(1)([])
358
+ sage: y = RootedTrees(3)([x, x])
359
+ sage: l = y.graft_list(x); l
360
+ [[[], [], []], [[], [[]]], [[], [[]]]]
361
+ sage: [parent(i) for i in l]
362
+ [Rooted trees, Rooted trees, Rooted trees]
363
+
364
+ sage: x = RootedTree([[[], []], []])
365
+ sage: y = RootedTree([[], []])
366
+ sage: len(set(x.graft_list(y)))
367
+ 4
368
+ """
369
+ resu = []
370
+ # Grafting ``other`` on the root:
371
+ with self.clone() as t:
372
+ t.append(other)
373
+ resu += [t]
374
+ for i, sub in enumerate(self):
375
+ # Grafting ``other`` on a descendant of the
376
+ # ``i``-th child:
377
+ for new_sub in sub.graft_list(other):
378
+ with self.clone() as t:
379
+ t[i] = new_sub
380
+ resu += [t]
381
+ return resu
382
+
383
+ def graft_on_root(self, other):
384
+ """
385
+ Return the tree obtained by grafting ``other`` on the root of ``self``.
386
+
387
+ Here grafting means that one takes the disjoint union of
388
+ ``self`` and ``other``, and adds the root of ``other`` to
389
+ the list of children of ``self``. The root of the resulting
390
+ tree is the root of ``self``.
391
+
392
+ This is useful for free Nap algebras.
393
+
394
+ EXAMPLES::
395
+
396
+ sage: RT = RootedTree
397
+ sage: x = RT([])
398
+ sage: y = RT([x, x])
399
+ sage: x.graft_on_root(x)
400
+ [[]]
401
+ sage: y.graft_on_root(x)
402
+ [[], [], []]
403
+ sage: x.graft_on_root(y)
404
+ [[[], []]]
405
+ """
406
+ with self.clone() as t:
407
+ t.append(other)
408
+ return t
409
+
410
+ def single_graft(self, x, grafting_function, path_prefix=()):
411
+ r"""
412
+ Graft subtrees of `x` on ``self`` using the given function.
413
+
414
+ Let `x_1, x_2, \ldots, x_p` be the children of the root of
415
+ `x`. For each `i`, the subtree of `x` comprising all
416
+ descendants of `x_i` is joined by a new edge to
417
+ the vertex of ``self`` specified by the `i`-th path in the
418
+ grafting function (i.e., by the path
419
+ ``grafting_function[i]``).
420
+
421
+ The number of vertices of the result is the sum of the numbers
422
+ of vertices of ``self`` and `x` minus one, because the root of
423
+ `x` is not used.
424
+
425
+ This is used to define the product of the Grossman-Larson algebras.
426
+
427
+ INPUT:
428
+
429
+ - ``x`` -- a rooted tree
430
+
431
+ - ``grafting_function`` -- list of paths in ``self``
432
+
433
+ - ``path_prefix`` -- tuple (default: ``()``)
434
+
435
+ The ``path_prefix`` argument is only used for internal recursion.
436
+
437
+ EXAMPLES::
438
+
439
+ sage: LT = LabelledRootedTrees()
440
+ sage: y = LT([LT([],label='b')], label='a')
441
+ sage: x = LT([LT([],label='d')], label='c')
442
+ sage: y.single_graft(x,[(0,)])
443
+ a[b[d[]]]
444
+ sage: t = LT([LT([],label='b'),LT([],label='c')], label='a')
445
+ sage: s = LT([LT([],label='d'),LT([],label='e')], label='f')
446
+ sage: t.single_graft(s,[(0,),(1,)])
447
+ a[b[d[]], c[e[]]]
448
+ """
449
+ P = self.parent()
450
+ child_grafts = [suby.single_graft(x, grafting_function,
451
+ path_prefix + (i,))
452
+ for i, suby in enumerate(self)]
453
+ try:
454
+ y1 = P(child_grafts, label=self.label())
455
+ except AttributeError:
456
+ y1 = P(child_grafts)
457
+
458
+ with y1.clone() as y2:
459
+ for k in range(len(x)):
460
+ if grafting_function[k] == path_prefix:
461
+ y2.append(x[k])
462
+ return y2
463
+
464
+
465
+ class RootedTrees(UniqueRepresentation, Parent):
466
+ """
467
+ Factory class for rooted trees.
468
+
469
+ INPUT:
470
+
471
+ - ``size`` -- integer (optional)
472
+
473
+ OUTPUT:
474
+
475
+ the set of all rooted trees (of the given size ``size`` if
476
+ specified)
477
+
478
+ EXAMPLES::
479
+
480
+ sage: RootedTrees()
481
+ Rooted trees
482
+
483
+ sage: RootedTrees(2)
484
+ Rooted trees with 2 nodes
485
+ """
486
+ @staticmethod
487
+ def __classcall_private__(cls, n=None):
488
+ """
489
+ TESTS::
490
+
491
+ sage: from sage.combinat.rooted_tree import (RootedTrees_all,
492
+ ....: RootedTrees_size)
493
+ sage: RootedTrees(2) is RootedTrees_size(2)
494
+ True
495
+ sage: RootedTrees(5).cardinality()
496
+ 9
497
+ sage: RootedTrees() is RootedTrees_all()
498
+ True
499
+
500
+ TESTS::
501
+
502
+ sage: RootedTrees(0)
503
+ Traceback (most recent call last):
504
+ ...
505
+ ValueError: n must be a positive integer
506
+ """
507
+ if n is None:
508
+ return RootedTrees_all()
509
+
510
+ if n not in ZZ or n < 1:
511
+ raise ValueError("n must be a positive integer")
512
+ return RootedTrees_size(Integer(n))
513
+
514
+
515
+ class RootedTrees_all(DisjointUnionEnumeratedSets, RootedTrees):
516
+ r"""
517
+ Class of all (unordered, unlabelled) rooted trees.
518
+
519
+ See :class:`RootedTree` for a definition.
520
+ """
521
+
522
+ def __init__(self):
523
+ """
524
+ TESTS::
525
+
526
+ sage: sum(x**len(t) # needs sage.symbolic
527
+ ....: for t in set(RootedTree(t) for t in OrderedTrees(6)))
528
+ x^5 + x^4 + 3*x^3 + 6*x^2 + 9*x
529
+ sage: sum(x**len(t) for t in RootedTrees(6)) # needs sage.symbolic
530
+ x^5 + x^4 + 3*x^3 + 6*x^2 + 9*x
531
+
532
+ sage: TestSuite(RootedTrees()).run() # long time
533
+ """
534
+ DisjointUnionEnumeratedSets.__init__(
535
+ self, Family(NonNegativeIntegers(), RootedTrees_size),
536
+ facade=True, keepkey=False)
537
+
538
+ def _repr_(self):
539
+ r"""
540
+ TESTS::
541
+
542
+ sage: RootedTrees()
543
+ Rooted trees
544
+ """
545
+ return "Rooted trees"
546
+
547
+ def __contains__(self, x):
548
+ """
549
+ TESTS::
550
+
551
+ sage: S = RootedTrees()
552
+ sage: 1 in S
553
+ False
554
+ sage: S([]) in S
555
+ True
556
+ """
557
+ return isinstance(x, self.element_class)
558
+
559
+ def unlabelled_trees(self):
560
+ """
561
+ Return the set of unlabelled trees associated to ``self``.
562
+
563
+ EXAMPLES::
564
+
565
+ sage: RootedTrees().unlabelled_trees()
566
+ Rooted trees
567
+ """
568
+ return self
569
+
570
+ def labelled_trees(self):
571
+ """
572
+ Return the set of labelled trees associated to ``self``.
573
+
574
+ EXAMPLES::
575
+
576
+ sage: RootedTrees().labelled_trees()
577
+ Labelled rooted trees
578
+
579
+ As a consequence::
580
+
581
+ sage: lb = RootedTrees()([[],[[], []]]).canonical_labelling()
582
+ sage: lb
583
+ 1[2[], 3[4[], 5[]]]
584
+ sage: lb.__class__
585
+ <class 'sage.combinat.rooted_tree.LabelledRootedTrees_all_with_category.element_class'>
586
+ sage: lb.parent()
587
+ Labelled rooted trees
588
+ """
589
+ return LabelledRootedTrees()
590
+
591
+ def _element_constructor_(self, *args, **keywords):
592
+ """
593
+ EXAMPLES::
594
+
595
+ sage: B = RootedTrees()
596
+ sage: B._element_constructor_([])
597
+ []
598
+ sage: B([[],[]]) # indirect doctest
599
+ [[], []]
600
+ """
601
+ return self.element_class(self, *args, **keywords)
602
+
603
+ @cached_method
604
+ def leaf(self):
605
+ """
606
+ Return a leaf tree with ``self`` as parent.
607
+
608
+ EXAMPLES::
609
+
610
+ sage: RootedTrees().leaf()
611
+ []
612
+ """
613
+ return self([])
614
+
615
+ Element = RootedTree
616
+
617
+
618
+ class RootedTrees_size(RootedTrees):
619
+ """
620
+ The enumerated set of rooted trees with a given number of nodes.
621
+
622
+ The number of nodes of a rooted tree is defined recursively:
623
+ The number of nodes of a rooted tree with `a` children is `a`
624
+ plus the sum of the number of nodes of each of these children.
625
+
626
+ TESTS::
627
+
628
+ sage: from sage.combinat.rooted_tree import RootedTrees_size
629
+ sage: for i in range(1, 6): TestSuite(RootedTrees_size(i)).run() # needs sage.combinat
630
+ """
631
+
632
+ def __init__(self, n):
633
+ """
634
+ TESTS::
635
+
636
+ sage: for i in range(1, 6): # needs sage.combinat
637
+ ....: TestSuite(RootedTrees(i)).run()
638
+ """
639
+ super().__init__(category=FiniteEnumeratedSets())
640
+ self._n = n
641
+
642
+ def _repr_(self):
643
+ r"""
644
+ TESTS::
645
+
646
+ sage: RootedTrees(4) # indirect doctest
647
+ Rooted trees with 4 nodes
648
+ """
649
+ return "Rooted trees with {} nodes".format(self._n)
650
+
651
+ def __contains__(self, x):
652
+ """
653
+ TESTS::
654
+
655
+ sage: S = RootedTrees(3)
656
+ sage: 1 in S
657
+ False
658
+ sage: S([[],[]]) in S
659
+ True
660
+ """
661
+ return isinstance(x, self.element_class) and x.node_number() == self._n
662
+
663
+ def _an_element_(self):
664
+ """
665
+ TESTS::
666
+
667
+ sage: RootedTrees(4).an_element() # indirect doctest # needs sage.combinat
668
+ [[[[]]]]
669
+ """
670
+ return self.first()
671
+
672
+ def __iter__(self):
673
+ """
674
+ An iterator for ``self``.
675
+
676
+ This generates the rooted trees of given size. The algorithm
677
+ first picks a partition for the sizes of subtrees, then picks
678
+ appropriate tuples of smaller trees.
679
+
680
+ EXAMPLES::
681
+
682
+ sage: from sage.combinat.rooted_tree import *
683
+ sage: RootedTrees(1).list()
684
+ [[]]
685
+ sage: RootedTrees(2).list() # needs sage.combinat
686
+ [[[]]]
687
+ sage: RootedTrees(3).list() # needs sage.combinat
688
+ [[[[]]], [[], []]]
689
+ sage: RootedTrees(4).list() # needs sage.combinat
690
+ [[[[[]]]], [[[], []]], [[], [[]]], [[], [], []]]
691
+ """
692
+ if self._n == 1:
693
+ yield self._element_constructor_([])
694
+ return
695
+
696
+ from sage.combinat.partition import Partitions
697
+ from itertools import combinations_with_replacement, product
698
+ for part in Partitions(self._n - 1):
699
+ mults = part.to_exp_dict()
700
+ choices = []
701
+ for p, mp in mults.items():
702
+ lp = self.__class__(p).list()
703
+ new_choice = [list(z) for z in combinations_with_replacement(lp, mp)]
704
+ choices.append(new_choice)
705
+ for c in product(*choices):
706
+ yield self.element_class(self._parent_for, sum(c, []))
707
+
708
+ def check_element(self, el, check=True):
709
+ r"""
710
+ Check that a given tree actually belongs to ``self``.
711
+
712
+ This just checks the number of vertices.
713
+
714
+ EXAMPLES::
715
+
716
+ sage: RT3 = RootedTrees(3)
717
+ sage: RT3([[],[]]) # indirect doctest
718
+ [[], []]
719
+ sage: RT3([[],[],[]]) # indirect doctest
720
+ Traceback (most recent call last):
721
+ ...
722
+ ValueError: wrong number of nodes
723
+ """
724
+ if el.node_number() != self._n:
725
+ raise ValueError("wrong number of nodes")
726
+
727
+ def cardinality(self):
728
+ r"""
729
+ Return the cardinality of ``self``.
730
+
731
+ EXAMPLES::
732
+
733
+ sage: RootedTrees(1).cardinality()
734
+ 1
735
+ sage: RootedTrees(3).cardinality()
736
+ 2
737
+ """
738
+ return number_of_rooted_trees(self._n)
739
+
740
+ @lazy_attribute
741
+ def _parent_for(self):
742
+ """
743
+ The parent of the elements generated by ``self``.
744
+
745
+ TESTS::
746
+
747
+ sage: S = RootedTrees(3)
748
+ sage: S._parent_for
749
+ Rooted trees
750
+ """
751
+ return RootedTrees_all()
752
+
753
+ @lazy_attribute
754
+ def element_class(self):
755
+ """
756
+ TESTS::
757
+
758
+ sage: S = RootedTrees(3)
759
+ sage: S.element_class
760
+ <class 'sage.combinat.rooted_tree.RootedTrees_all_with_category.element_class'>
761
+ sage: S.first().__class__ == RootedTrees().first().__class__ # needs sage.combinat
762
+ True
763
+ """
764
+ return self._parent_for.element_class
765
+
766
+ def _element_constructor_(self, *args, **keywords):
767
+ """
768
+ EXAMPLES::
769
+
770
+ sage: S = RootedTrees(2)
771
+ sage: S([]) # indirect doctest
772
+ Traceback (most recent call last):
773
+ ...
774
+ ValueError: wrong number of nodes
775
+ sage: S([[]]) # indirect doctest
776
+ [[]]
777
+
778
+ sage: S = RootedTrees(1) # indirect doctest
779
+ sage: S([])
780
+ []
781
+ """
782
+ res = self.element_class(self._parent_for, *args, **keywords)
783
+ if res.node_number() != self._n:
784
+ raise ValueError("wrong number of nodes")
785
+ return res
786
+
787
+
788
+ class LabelledRootedTree(AbstractLabelledClonableTree, RootedTree):
789
+ """
790
+ Labelled rooted trees.
791
+
792
+ A labelled rooted tree is a rooted tree with a label
793
+ attached at each node.
794
+
795
+ More formally:
796
+ The *labelled rooted trees* are an inductive datatype defined
797
+ as follows: A labelled rooted tree is a multiset of labelled
798
+ rooted trees, endowed with a label (which can be any object,
799
+ including ``None``). The trees that belong to this multiset
800
+ are said to be the *children* of the tree. (Notice that the
801
+ labels of these children may and may not be of the same type
802
+ as the label of the tree). A labelled rooted tree which has
803
+ no children (so the only information it carries is its label)
804
+ is said to be a *leaf*.
805
+
806
+ Every labelled rooted tree gives rise to an unlabelled rooted
807
+ tree (:class:`RootedTree`) by forgetting the labels. (This is
808
+ implemented as a conversion.)
809
+
810
+ INPUT:
811
+
812
+ - ``children`` -- list or tuple or more generally any iterable
813
+ of trees or objects convertible to trees
814
+
815
+ - ``label`` -- any hashable Sage object (default: ``None``)
816
+
817
+ .. NOTE::
818
+
819
+ It is required that all labels are comparable.
820
+
821
+ EXAMPLES::
822
+
823
+ sage: x = LabelledRootedTree([], label = 3); x
824
+ 3[]
825
+ sage: LabelledRootedTree([x, x, x], label = 2)
826
+ 2[3[], 3[], 3[]]
827
+ sage: LabelledRootedTree((x, x, x), label = 2)
828
+ 2[3[], 3[], 3[]]
829
+ sage: LabelledRootedTree([[],[[], []]], label = 3)
830
+ 3[None[], None[None[], None[]]]
831
+
832
+ Children are reordered using the value of the :meth:`sort_key` method::
833
+
834
+ sage: y = LabelledRootedTree([], label = 5); y
835
+ 5[]
836
+ sage: xyy2 = LabelledRootedTree((x, y, y), label = 2); xyy2
837
+ 2[3[], 5[], 5[]]
838
+ sage: yxy2 = LabelledRootedTree((y, x, y), label = 2); yxy2
839
+ 2[3[], 5[], 5[]]
840
+ sage: xyy2 == yxy2
841
+ True
842
+
843
+ Converting labelled into unlabelled rooted trees by
844
+ forgetting the labels, and back (the labels are
845
+ initialized as ``None``)::
846
+
847
+ sage: yxy2crude = RootedTree(yxy2); yxy2crude
848
+ [[], [], []]
849
+ sage: LabelledRootedTree(yxy2crude)
850
+ None[None[], None[], None[]]
851
+
852
+ TESTS::
853
+
854
+ sage: xyy2._get_list() == yxy2._get_list()
855
+ True
856
+ """
857
+ @staticmethod
858
+ def __classcall_private__(cls, *args, **opts):
859
+ """
860
+ Ensure that trees created by the sets and directly are the same and
861
+ that they are instances of :class:`LabelledRootedTree`.
862
+
863
+ TESTS::
864
+
865
+ sage: issubclass(LabelledRootedTrees().element_class, LabelledRootedTree)
866
+ True
867
+ sage: t0 = LabelledRootedTree([[],[[], []]], label = 3)
868
+ sage: t0.parent()
869
+ Labelled rooted trees
870
+ sage: type(t0)
871
+ <class 'sage.combinat.rooted_tree.LabelledRootedTrees_all_with_category.element_class'>
872
+ """
873
+ return cls._auto_parent.element_class(cls._auto_parent, *args, **opts)
874
+
875
+ @lazy_class_attribute
876
+ def _auto_parent(cls):
877
+ """
878
+ The automatic parent of the element of this class.
879
+
880
+ When calling the constructor of an element of this class, one needs a
881
+ parent. This class attribute specifies which parent is used.
882
+
883
+ EXAMPLES::
884
+
885
+ sage: LabelledRootedTree._auto_parent
886
+ Labelled rooted trees
887
+ sage: LabelledRootedTree([], label = 3).parent()
888
+ Labelled rooted trees
889
+ """
890
+ return LabelledRootedTrees()
891
+
892
+ def sort_key(self):
893
+ """
894
+ Return a tuple of nonnegative integers encoding the labelled
895
+ rooted tree ``self``.
896
+
897
+ The first entry of the tuple is a pair consisting of the
898
+ number of children of the root and the label of the root. Then
899
+ the rest of the tuple is obtained as follows: List
900
+ the tuples corresponding to all children (we are regarding the
901
+ children themselves as trees). Order this list (not the
902
+ tuples!) in lexicographically increasing order, and flatten
903
+ it into a single tuple.
904
+
905
+ This tuple characterizes the labelled rooted tree uniquely, and
906
+ can be used to sort the labelled rooted trees provided that the
907
+ labels belong to a type which is totally ordered.
908
+
909
+ .. NOTE::
910
+
911
+ The tree ``self`` must be normalized before calling this
912
+ method (see :meth:`normalize`). This does not matter
913
+ unless you are inside the :meth:`clone` context manager,
914
+ because outside of it every rooted tree is already
915
+ normalized.
916
+
917
+ .. NOTE::
918
+
919
+ This method overrides :meth:`RootedTree.sort_key`
920
+ and returns a result different from what the latter
921
+ would return, as it wants to encode the whole labelled
922
+ tree including its labelling rather than just the
923
+ unlabelled tree. Therefore, be careful with using this
924
+ method on subclasses of :class:`RootedOrderedTree`;
925
+ under some circumstances they could inherit it from
926
+ another superclass instead of from :class:`RootedTree`,
927
+ which would cause the method to forget the labelling.
928
+ See the docstrings of :meth:`RootedTree.sort_key` and
929
+ :meth:`sage.combinat.ordered_tree.OrderedTree.sort_key`.
930
+
931
+ EXAMPLES::
932
+
933
+ sage: LRT = LabelledRootedTrees(); LRT
934
+ Labelled rooted trees
935
+ sage: x = LRT([], label = 3); x
936
+ 3[]
937
+ sage: x.sort_key()
938
+ ((0, 3),)
939
+ sage: y = LRT([x, x, x], label = 2); y
940
+ 2[3[], 3[], 3[]]
941
+ sage: y.sort_key()
942
+ ((3, 2), (0, 3), (0, 3), (0, 3))
943
+ sage: LRT.an_element().sort_key()
944
+ ((3, 'alpha'), (0, 3), (1, 5), (0, None), (2, 42), (0, 3), (0, 3))
945
+ sage: lb = RootedTrees()([[],[[], []]]).canonical_labelling()
946
+ sage: lb.sort_key()
947
+ ((2, 1), (0, 2), (2, 3), (0, 4), (0, 5))
948
+ """
949
+ l = len(self)
950
+ if l == 0:
951
+ return ((0, self.label()),)
952
+ resu = [(l, self.label())] + [u for t in self for u in t.sort_key()]
953
+ return tuple(resu)
954
+
955
+ def __hash__(self):
956
+ """
957
+ Return a hash for ``self``.
958
+
959
+ EXAMPLES::
960
+
961
+ sage: lb = RootedTrees()([[],[[], []]]).canonical_labelling()
962
+ sage: hash(lb) == hash(((2, 1), (0, 2), (2, 3), (0, 4), (0, 5))) # indirect doctest
963
+ True
964
+ """
965
+ return hash(self.sort_key())
966
+
967
+ _UnLabelled = RootedTree
968
+
969
+
970
+ class LabelledRootedTrees(UniqueRepresentation, Parent):
971
+ """
972
+ This is a parent stub to serve as a factory class for labelled
973
+ rooted trees.
974
+
975
+ EXAMPLES::
976
+
977
+ sage: LRT = LabelledRootedTrees(); LRT
978
+ Labelled rooted trees
979
+ sage: x = LRT([], label = 3); x
980
+ 3[]
981
+ sage: x.parent() is LRT
982
+ True
983
+ sage: y = LRT([x, x, x], label = 2); y
984
+ 2[3[], 3[], 3[]]
985
+ sage: y.parent() is LRT
986
+ True
987
+
988
+ .. TODO::
989
+
990
+ Add the possibility to restrict the labels to a fixed set.
991
+ """
992
+ @staticmethod
993
+ def __classcall_private__(cls, n=None):
994
+ """
995
+ TESTS::
996
+
997
+ sage: from sage.combinat.rooted_tree import LabelledRootedTrees_all
998
+ sage: LabelledRootedTrees_all() == LabelledRootedTrees()
999
+ True
1000
+ """
1001
+ return LabelledRootedTrees_all()
1002
+
1003
+
1004
+ class LabelledRootedTrees_all(LabelledRootedTrees):
1005
+ r"""
1006
+ Class of all (unordered) labelled rooted trees.
1007
+
1008
+ See :class:`LabelledRootedTree` for a definition.
1009
+ """
1010
+
1011
+ def __init__(self, category=None):
1012
+ """
1013
+ TESTS::
1014
+
1015
+ sage: TestSuite(LabelledRootedTrees()).run()
1016
+ """
1017
+ if category is None:
1018
+ category = Sets()
1019
+ category = category.Infinite()
1020
+ Parent.__init__(self, category=category)
1021
+
1022
+ def _repr_(self):
1023
+ """
1024
+ Return the string representation of ``self``.
1025
+
1026
+ TESTS::
1027
+
1028
+ sage: LabelledRootedTrees()
1029
+ Labelled rooted trees
1030
+ """
1031
+ return "Labelled rooted trees"
1032
+
1033
+ def _an_element_(self):
1034
+ """
1035
+ Return a labelled tree.
1036
+
1037
+ EXAMPLES::
1038
+
1039
+ sage: LabelledRootedTrees().an_element() # indirect doctest
1040
+ alpha[3[], 5[None[]], 42[3[], 3[]]]
1041
+ """
1042
+ LT = self._element_constructor_
1043
+ t = LT([], label=3)
1044
+ t1 = LT([t, t], label=42)
1045
+ t2 = LT([[]], label=5)
1046
+ return LT([t, t1, t2], label='alpha')
1047
+
1048
+ def unlabelled_trees(self):
1049
+ """
1050
+ Return the set of unlabelled trees associated to ``self``.
1051
+
1052
+ EXAMPLES::
1053
+
1054
+ sage: LabelledRootedTrees().unlabelled_trees()
1055
+ Rooted trees
1056
+ """
1057
+ return RootedTrees_all()
1058
+
1059
+ def labelled_trees(self):
1060
+ """
1061
+ Return the set of labelled trees associated to ``self``.
1062
+
1063
+ EXAMPLES::
1064
+
1065
+ sage: LabelledRootedTrees().labelled_trees()
1066
+ Labelled rooted trees
1067
+ """
1068
+ return self
1069
+
1070
+ Element = LabelledRootedTree