Path: blob/master/src/sage/dev/test/data/trac_8703-trees-fh.patch
8817 views
#8703: Enumerated sets and data structure for ordered and binary trees1- The Class Abstract[Labelled]Tree allows for inheritance from different2Cython classes.3- Added shape on labelled trees.4- Add a new function as_digraph() that maps a tree to the associated directed5graph, with edges oriented away from from the root6- Added canopee to binary trees.7- Decreasing and increasing Binary tree of a permutations.8- Added Binary tree insertion.9- Added Binary search tree of a permutation10- removed sage.misc.sagex_ds.BinaryTree from the interface.1112diff --git a/doc/en/reference/combinat/index.rst b/doc/en/reference/combinat/index.rst13--- a/doc/en/reference/combinat/index.rst14+++ b/doc/en/reference/combinat/index.rst15@@ -45,6 +45,9 @@ Combinatorics16sage/combinat/sidon_sets17sage/combinat/set_partition_ordered18sage/combinat/set_partition19+ sage/combinat/abstract_tree20+ sage/combinat/ordered_tree21+ sage/combinat/binary_tree22sage/combinat/skew_partition23sage/combinat/subset24sage/combinat/subsets_pairwise25diff --git a/sage/combinat/abstract_tree.py b/sage/combinat/abstract_tree.py26new file mode 10064427--- /dev/null28+++ b/sage/combinat/abstract_tree.py29@@ -0,0 +1,979 @@30+"""31+Abstract Recursive Trees32+33+The purpose of this class is to help implement trees with a specific structure34+on the children of each node. For instance, one could want to define a tree in35+which each node sees its children as linearly (see the :mod:`Ordered Trees36+<sage.combinat.ordered_tree>` module) or cyclically ordered.37+38+**Tree structures**39+40+Conceptually, one can define a tree structure from any object that can contain41+others. Indeed, a list can contain lists which contain lists which contain42+lists, and thus define a tree ... The same can be done with sets, or any kind43+of iterable objects.44+45+While any iterable is sufficient to encode trees, it can prove useful to have46+other methods available like isomorphism tests (see next section), conversions47+to DiGraphs objects (see :meth:`~.AbstractLabelledTree.as_digraph`) or48+computation of the number of automorphisms constrained by the structure on49+children. Providing such methods is the whole purpose of the50+:class:`AbstractTree` class.51+52+As a result, the :class:`AbstractTree` class is not meant to be53+instantiated, but extended. It is expected that classes extending this one may54+also inherit from classes representing iterables, for instance55+:class:`ClonableArray` or :class:`~sage.structure.list_clone.ClonableList`56+57+**Constrained Trees**58+59+The tree built from a specific container will reflect the properties of the60+container. Indeed, if ``A`` is an iterable class whose elements are linearly61+ordered, a class ``B`` extending both of :class:`AbstractTree` and ``A`` will62+be such that the children of a node will be linearly ordered. If ``A`` behaves63+like a set (i.e. if there is no order on the elements it contains), then two64+trees will be considered as equal if one can be obtained from the other65+through permutations between the children of a same node (see next section).66+67+**Paths and ID**68+69+It is expected that each element of a set of children should be identified by70+its index in the container. This way, any node of the tree can be identified71+by a word describing a path from the root node.72+73+**Canonical labellings**74+75+Equality between instances of classes extending both of :class:`AbstractTree`76+and ``A`` is entirely defined by the equality defined on the elements of77+``A``. A canonical labelling of such a tree however, should be such that two78+trees ``a`` and ``b`` satisfying ``a == b`` should have the same canonical79+labellings. On the other hand, the canonical labellings of trees ``a`` and80+``b`` satisfying ``a != b`` are expected to be different.81+82+For this reason, the values returned by the :meth:`canonical_labelling83+<AbstractTree.canonical_labelling>` method heavily84+depend on the data structure used for a node's children and **should be**85+**overridden** by most of the classes extending :class:`AbstractTree` if it is86+incoherent with the data structure.87+88+**Authors**89+90+- Florent Hivert (2010-2011): initial revision91+- Frederic Chapoton (2011): contributed some methods92+"""93+94+from sage.structure.list_clone import ClonableArray95+from sage.rings.integer import Integer96+from sage.misc.misc_c import prod97+98+# Unfortunately Cython forbids multiple inheritance. Therefore, we do not99+# inherits from SageObject to be able to inherits from Element or a subclass100+# of it later.101+class AbstractTree(object):102+ """103+ Abstract Tree104+105+ There is no data structure defined here, as this class is meant to be106+ extended, not instantiated.107+108+ .. rubric:: How should this class be extended ?109+110+ A class extending :class:`AbstractTree111+ <sage.combinat.abstract_tree.AbstractTree>` should respect several112+ assumptions:113+114+ * For a tree ``T``, the call ``iter(T)`` should return an iterator on the115+ children of the root ``T``.116+117+ * The :meth:`canonical_labelling118+ <AbstractTree.canonical_labelling>` method119+ should return the same value for trees that are considered equal (see the120+ "canonical labellings" section in the documentation of the121+ :class:`AbstractTree <sage.combinat.abstract_tree.AbstractTree>` module).122+123+ * For a tree ``T`` the call ``T.parent().labelled_trees()`` should return124+ a parent for labelled trees of the same kind: for example,125+126+ - if ``T`` is a binary tree, ``T.parent()`` is ``BinaryTrees()`` and127+ ``T.parent().labelled_trees()`` is ``LabelledBinaryTrees()``128+129+ - if ``T`` is an ordered tree, ``T.parent()`` is ``OrderedTrees()`` and130+ ``T.parent().labelled_trees()`` is ``LabelledOrderedTrees()``131+132+ TESTS::133+134+ sage: TestSuite(OrderedTree()).run()135+ sage: TestSuite(BinaryTree()).run()136+ """137+138+ def subtrees(self):139+ """140+ Returns a generator for all subtrees of ``self``141+142+ The number of subtrees of a tree is its number of elements.143+144+ EXAMPLES::145+146+ sage: list(OrderedTree([]).subtrees())147+ [[]]148+ sage: list(OrderedTree([[],[[]]]).subtrees())149+ [[[], [[]]], [], [[]], []]150+151+ sage: list(BinaryTree([[],[[],[]]]).subtrees())152+ [[[., .], [[., .], [., .]]], [., .], [[., .], [., .]], [., .], [., .]]153+154+ TESTS::155+156+ sage: t = OrderedTree([[], [[], [[], []], [[], []]], [[], []]])157+ sage: t.node_number() == len(list(t.subtrees()))158+ True159+ sage: list(BinaryTree().subtrees())160+ []161+ sage: bt = BinaryTree([[],[[],[]]])162+ sage: bt.node_number() == len(list(bt.subtrees()))163+ True164+ """165+ if not self.is_empty():166+ yield self167+ for i in self:168+ for t in i.subtrees():169+ yield t170+171+ def paths(self):172+ """173+ Returns a generator for all paths to nodes of ``self``174+175+ OUTPUT:176+177+ This method returns a list of sequences of integers. Each of these178+ sequences represents a path from the root node to another one : `(1, 3,179+ 2, 5, 3)` represents the node obtained by chosing the 1st children of180+ the root node (in the ordering returned by ``iter``), then the 3rd of181+ its children, then the 2nd of this element, etc.182+183+ The root element is represented by the empty tuple ``()``.184+185+ EXAMPLES::186+187+ sage: list(OrderedTree([]).paths())188+ [()]189+ sage: list(OrderedTree([[],[[]]]).paths())190+ [(), (0,), (1,), (1, 0)]191+192+ sage: list(BinaryTree([[],[[],[]]]).paths())193+ [(), (0,), (1,), (1, 0), (1, 1)]194+195+ TESTS::196+197+ sage: t = OrderedTree([[], [[], [[], []], [[], []]], [[], []]])198+ sage: t.node_number() == len(list(t.paths()))199+ True200+ sage: list(BinaryTree().paths())201+ []202+ sage: bt = BinaryTree([[],[[],[]]])203+ sage: bt.node_number() == len(list(bt.paths()))204+ True205+ """206+ if not self.is_empty():207+ yield ()208+ for i, t in enumerate(self):209+ for p in t.paths():210+ yield (i,)+p211+212+ def node_number(self):213+ """214+ The number of nodes of ``self``215+216+ EXAMPLES::217+218+ sage: OrderedTree().node_number()219+ 1220+ sage: OrderedTree([]).node_number()221+ 1222+ sage: OrderedTree([[],[]]).node_number()223+ 3224+ sage: OrderedTree([[],[[]]]).node_number()225+ 4226+ sage: OrderedTree([[], [[], [[], []], [[], []]], [[], []]]).node_number()227+ 13228+229+ EXAMPLE::230+231+ sage: BinaryTree(None).node_number()232+ 0233+ sage: BinaryTree([]).node_number()234+ 1235+ sage: BinaryTree([[], None]).node_number()236+ 2237+ sage: BinaryTree([[None, [[], []]], None]).node_number()238+ 5239+ """240+ if self.is_empty():241+ return 0242+ else:243+ return sum((i.node_number() for i in self), Integer(1))244+245+ def depth(self):246+ """247+ The depth of ``self``248+249+ EXAMPLES::250+251+ sage: OrderedTree().depth()252+ 1253+ sage: OrderedTree([]).depth()254+ 1255+ sage: OrderedTree([[],[]]).depth()256+ 2257+ sage: OrderedTree([[],[[]]]).depth()258+ 3259+ sage: OrderedTree([[], [[], [[], []], [[], []]], [[], []]]).depth()260+ 4261+262+ sage: BinaryTree().depth()263+ 0264+ sage: BinaryTree([[],[[],[]]]).depth()265+ 3266+ """267+ if self:268+ return Integer(1 + max(i.depth() for i in self))269+ else:270+ return Integer(0 if self.is_empty() else 1)271+272+ def canonical_labelling(self,shift=1):273+ """274+ Returns a labelled version of ``self``275+276+ The actual canonical labelling is currently unspecified. However, it277+ is guaranteed to have labels in `1...n` where `n` is the number of278+ nodes of the tree. Moreover, two (unlabelled) trees compare as equal if279+ and only if they canonical labelled trees compare as equal.280+281+ EXAMPLES::282+283+ sage: t = OrderedTree([[], [[], [[], []], [[], []]], [[], []]])284+ sage: t.canonical_labelling()285+ 1[2[], 3[4[], 5[6[], 7[]], 8[9[], 10[]]], 11[12[], 13[]]]286+287+ sage: BinaryTree([]).canonical_labelling()288+ 1[., .]289+ sage: BinaryTree([[],[[],[]]]).canonical_labelling()290+ 2[1[., .], 4[3[., .], 5[., .]]]291+292+ TESTS::293+294+ sage: BinaryTree().canonical_labelling()295+ .296+ """297+ LTR = self.parent().labelled_trees()298+ liste=[]299+ deca=1300+ for subtree in self:301+ liste=liste+[subtree.canonical_labelling(shift+deca)]302+ deca=deca+subtree.node_number()303+ return LTR._element_constructor_(liste,label=shift)304+305+ def tree_factorial(self):306+ """307+ Returns the tree-factorial of ``self``308+309+ Definition:310+311+ The tree-factorial `T!` of a tree `T` is the product `\prod_{v\in312+ T}\#\mbox{children}(v)`.313+314+ EXAMPLES::315+316+ sage: LT=LabelledOrderedTrees()317+ sage: t=LT([LT([],label=6),LT([],label=1)],label=9)318+ sage: t.tree_factorial()319+ 3320+321+ sage: BinaryTree([[],[[],[]]]).tree_factorial()322+ 15323+324+ TESTS::325+326+ sage: BinaryTree().tree_factorial()327+ 1328+ """329+ nb = self.node_number()330+ if nb <= 1:331+ return 1332+ else:333+ return nb*prod(s.tree_factorial() for s in self)334+335+ latex_unit_length = "4mm"336+ latex_node_diameter = "0.5"337+ latex_root_diameter = "0.7"338+339+ def _latex_(self):340+ """341+ Returns a LaTeX version of ``self``342+343+ EXAMPLES::344+345+ sage: print(OrderedTree([[],[]])._latex_())346+ \vcenter{\hbox{{\setlength\unitlength{4mm}347+ \begin{picture}(4,3)348+ \put(1,1){\circle*{0.5}}349+ \put(2,2){\circle*{0.5}}350+ \put(3,1){\circle*{0.5}}351+ \put(2,2){\line(-1,-1){1}}352+ \put(2,2){\line(1,-1){1}}353+ \put(2,2){\circle*{0.7}}354+ \end{picture}}}}355+356+ TESTS::357+358+ sage: OrderedTree([])._latex_()359+ '\\vcenter{\\hbox{{\\setlength\\unitlength{4mm}\n\\begin{picture}(2,2)\n\\put(1,1){\\circle*{0.5}}\n\\put(1,1){\\circle*{0.7}}\n\\end{picture}}}}'360+ sage: OrderedTree([[]])._latex_()361+ '\\vcenter{\\hbox{{\\setlength\\unitlength{4mm}\n\\begin{picture}(2,3)\n\\put(1,1){\\circle*{0.5}}\n\\put(1,2){\\circle*{0.5}}\n\\put(1,2){\\line(0,-1){1}}\n\\put(1,2){\\circle*{0.7}}\n\\end{picture}}}}'362+ sage: OrderedTree([[], [[], [[], []], [[], []]], [[], []]])._latex_()363+ '\\vcenter{\\hbox{{\\setlength\\unitlength{4mm}\n\\begin{picture}(12,5)\n\\put(1,3){\\circle*{0.5}}\n\\put(2,2){\\circle*{0.5}}\n\\put(3,1){\\circle*{0.5}}\n\\put(4,2){\\circle*{0.5}}\n\\put(5,1){\\circle*{0.5}}\n\\put(4,2){\\line(-1,-1){1}}\n\\put(4,2){\\line(1,-1){1}}\n\\put(4,3){\\circle*{0.5}}\n\\put(6,1){\\circle*{0.5}}\n\\put(7,2){\\circle*{0.5}}\n\\put(8,1){\\circle*{0.5}}\n\\put(7,2){\\line(-1,-1){1}}\n\\put(7,2){\\line(1,-1){1}}\n\\put(4,3){\\line(-2,-1){2}}\n\\put(4,3){\\line(0,-1){1}}\n\\put(4,3){\\line(3,-1){3}}\n\\put(4,4){\\circle*{0.5}}\n\\put(9,2){\\circle*{0.5}}\n\\put(10,3){\\circle*{0.5}}\n\\put(11,2){\\circle*{0.5}}\n\\put(10,3){\\line(-1,-1){1}}\n\\put(10,3){\\line(1,-1){1}}\n\\put(4,4){\\line(-3,-1){3}}\n\\put(4,4){\\line(0,-1){1}}\n\\put(4,4){\\line(6,-1){6}}\n\\put(4,4){\\circle*{0.7}}\n\\end{picture}}}}'364+ """365+ from sage.misc.latex import latex366+ drawing = [""] # allows modification of in rec...367+ x = [1] # allows modification of x[0] in rec...368+ max_label_width = [0] # allows modification of x[0] in rec...369+ maxy = self.depth()370+371+ def rec(t, y):372+ """373+ Draw the subtree t on the drawing, below y (included) and to374+ the right of x[0] (included). Update x[0]. Returns the horizontal375+ position of the root376+ """377+ if t.node_number() == 0 : return -1378+ n = len(t)379+ posChild = [rec(t[i], y+1) for i in range(n // 2)]380+ i = n // 2381+ if n % 2 == 1:382+ xc = rec(t[i], y+1)383+ posChild.append(xc)384+ i += 1385+ else:386+ xc = x[0]387+ x[0] +=1388+ drawing[0] = drawing[0] + "\\put(%s,%s){\\circle*{%s}}\n"%(389+ xc, maxy-y, self.latex_node_diameter)390+ try:391+ lbl = t.label()392+ except AttributeError:393+ pass394+ else:395+ max_label_width[0] = 1 # TODO find a better heuristic396+ drawing[0] = drawing[0] + "\\put(%s,%s){$\scriptstyle %s$}"%(397+ xc+0.3, maxy-y-0.3, latex(lbl))398+ posChild += [rec(t[j], y+1) for j in range(i, n)]399+ for i in range(n):400+ if posChild[i] != -1:401+ drawing[0] = (drawing[0] +402+ "\\put(%s,%s){\\line(%s,-1){%s}}\n"%(403+ xc, maxy-y, posChild[i]-xc,404+ max(abs(posChild[i]-xc), 1)))405+ return xc406+407+ res = rec(self, 0)408+ drawing[0] = drawing[0] + "\\put(%s,%s){\\circle*{%s}}\n"%(409+ res, maxy, self.latex_root_diameter)410+ return "\\vcenter{\hbox{{\setlength\unitlength{%s}\n\\begin{picture}(%s,%s)\n%s\\end{picture}}}}"%(411+ self.latex_unit_length,412+ x[0] + max_label_width[0],413+ maxy + 1,414+ drawing[0])415+416+class AbstractClonableTree(AbstractTree):417+ """418+ Abstract Clonable Tree419+420+ An abstract class for trees with clone protocol (see421+ :mod:`~sage.structure.list_clone`). It is expected that classes extending422+ this one may also inherit from classes like :class:`ClonableArray` or423+ :class:`~sage.structure.list_clone.ClonableList` depending wether one424+ wants to build trees where adding a child is allowed.425+426+ .. note:: Due to the limitation of Cython inheritance, one cannot inherit427+ here from :class:`~sage.structure.list_clone.ClonableElement`, because428+ it would prevent us to inherit later from429+ :class:`~sage.structure.list_clone.ClonableArray` or430+ :class:`~sage.structure.list_clone.ClonableList`.431+432+ .. rubric:: How should this class be extended ?433+434+ A class extending :class:`AbstractTree435+ <sage.combinat.abstract_tree.AbstractTree>` should the following436+ assumptions:437+438+ * An instantiable class extending :class:`AbstractTree439+ <sage.combinat.abstract_tree.AbstractTree>` should also extend the440+ :class:`ClonableElement <sage.structure.list_clone.ClonableElement>`441+ class or one of its subclass generally at least :class:`ClonableArray442+ <sage.structure.list_clone.ClonableArray>`.443+444+445+ * To respect the Clone protocol, the :meth:`AbstractClonableTree.check`446+ method should be overridden by the new class.447+ """448+ def check(self):449+ """450+ Check that ``self`` is a correct tree451+452+ This method does nothing. It is implemented here because many453+ extensions of :class:`AbstractTree454+ <sage.combinat.abstract_tree.AbstractTree>` also extend455+ :class:`sage.structure.list_clone.ClonableElement`, which requires it.456+457+ It should be overriden in subclass is order to chech that the458+ invariant of the kind of tree holds (eg: two children for binary459+ trees).460+461+ EXAMPLES::462+463+ sage: OrderedTree([[],[[]]]).check()464+ sage: BinaryTree([[],[[],[]]]).check()465+ """466+ pass467+468+ def __setitem__(self, idx, value):469+ """470+ Substitute a subtree471+472+ .. NOTE::473+474+ The tree ``self`` must be in a mutable state. See475+ :mod:`sage.structure.list_clone` for more details about476+ mutability. The default implementation here assume that the477+ container of the node implement a method `_setitem` with signature478+ `self._setitem(idx, value)`. It is usually provided by inheriting479+ from :class:`~sage.structure.list_clone.ClonableArray`.480+481+ INPUT:482+483+ - ``idx`` -- a valid path in ``self`` identifying a node484+485+ - ``value`` -- the tree to be substituted486+487+ EXAMPLES:488+489+ Trying to modify a non mutable tree raise an error::490+491+ sage: x = OrderedTree([])492+ sage: x[0] = OrderedTree([[]])493+ Traceback (most recent call last):494+ ...495+ ValueError: object is immutable; please change a copy instead.496+497+ Here is the correct way to do it::498+499+ sage: x = OrderedTree([[],[[]]])500+ sage: with x.clone() as x:501+ ... x[0] = OrderedTree([[]])502+ sage: x503+ [[[]], [[]]]504+505+ One can also substitute at any depths::506+507+ sage: y = OrderedTree(x)508+ sage: with x.clone() as x:509+ ... x[0,0] = OrderedTree([[]])510+ sage: x511+ [[[[]]], [[]]]512+ sage: y513+ [[[]], [[]]]514+ sage: with y.clone() as y:515+ ... y[(0,)] = OrderedTree([])516+ sage: y517+ [[], [[]]]518+519+ This works for binary trees as well::520+521+ sage: bt = BinaryTree([[],[[],[]]]); bt522+ [[., .], [[., .], [., .]]]523+ sage: with bt.clone() as bt1:524+ ... bt1[0,0] = BinaryTree([[[], []], None])525+ sage: bt1526+ [[[[[., .], [., .]], .], .], [[., .], [., .]]]527+528+ TESTS::529+530+ sage: x = OrderedTree([])531+ sage: with x.clone() as x:532+ ... x[0] = OrderedTree([[]])533+ Traceback (most recent call last):534+ ...535+ IndexError: list assignment index out of range536+537+ sage: x = OrderedTree([]); x = OrderedTree([x,x]);x = OrderedTree([x,x]); x = OrderedTree([x,x])538+ sage: with x.clone() as x:539+ ... x[0,0] = OrderedTree()540+ sage: x541+ [[[], [[], []]], [[[], []], [[], []]]]542+ """543+ assert isinstance(value, self.__class__)544+545+ if isinstance(idx, tuple):546+ self.__setitem_rec__(idx, 0, value)547+ else:548+ self._setitem(idx, value)549+550+ def __setitem_rec__(self, idx, i, value):551+ """552+ TESTS::553+554+ sage: x = OrderedTree([[[], []],[[]]])555+ sage: with x.clone() as x:556+ ... x[0,1] = OrderedTree([[[]]]) # indirect doctest557+ sage: x558+ [[[], [[[]]]], [[]]]559+ """560+ if i == len(idx) - 1:561+ self._setitem(idx[-1], value)562+ else:563+ with self[idx[i]].clone() as child:564+ child.__setitem_rec__(idx, i+1, value)565+ self[idx[i]] = child566+567+ def __getitem__(self, idx):568+ """569+ INPUT:570+571+ - ``idx`` -- a valid path in ``self`` identifying a node572+573+ ..note::574+575+ The default implementation here assume that the container of the576+ node inherits from577+ :class:`~sage.structure.list_clone.ClonableArray`.578+579+ EXAMPLES::580+581+ sage: x = OrderedTree([[],[[]]])582+ sage: x[1,0]583+ []584+ sage: x = OrderedTree([[],[[]]])585+ sage: x[()]586+ [[], [[]]]587+ sage: x[(0,)]588+ []589+ sage: x[0,0]590+ Traceback (most recent call last):591+ ...592+ IndexError: list index out of range593+ """594+ if isinstance(idx, slice):595+ return ClonableArray.__getitem__(self, idx)596+ try:597+ i = int(idx)598+ except TypeError:599+ res = self600+ # idx is supposed to be an iterable of ints601+ for i in idx:602+ res = ClonableArray._getitem(res, i)603+ return res604+ else:605+ return ClonableArray._getitem(self, i)606+607+608+class AbstractLabelledTree(AbstractTree):609+ """610+ Abstract Labelled Tree611+612+ Typically a class for labelled tree is contructed by inheriting from a613+ class for unlabelled trees and :class:`AbstractLabelledTree`614+615+ .. rubric:: How should this class be extended ?616+617+ A class extending :class:`AbstractLabelledTree618+ <sage.combinat.abstract_tree.AbstractLabelledTree>` should respect the619+ following assumptions:620+621+ * For a labelled tree ``T`` the call ``T.parent().unlabelled_trees()``622+ should return a parent for labelled trees of the same kind: for example,623+624+ - if ``T`` is a binary labelled tree, ``T.parent()`` is625+ ``LabelledBinaryTrees()`` and ``T.parent().unlabelled_trees()`` is626+ ``BinaryTrees()``627+628+ - if ``T`` is an ordered labelled tree, ``T.parent()`` is629+ ``LabelledOrderedTrees()`` and ``T.parent().unlabelled_trees()`` is630+ ``OrderedTrees()``631+632+ * In the same vein, the class of ``T`` should contains an attribute633+ ``_Unlabelled`` which should be the class for the corresponding634+ unlabelled trees.635+636+ .. SEEALSO:: :class:`AbstractTree`637+ """638+ def __init__(self, parent, children, label = None, check = True):639+ """640+ TESTS::641+642+ sage: LabelledOrderedTree([])643+ None[]644+ sage: LabelledOrderedTree([], 3)645+ 3[]646+ sage: LT = LabelledOrderedTree647+ sage: t = LT([LT([LT([], label=42), LT([], 21)])], label=1)648+ sage: t649+ 1[None[42[], 21[]]]650+ sage: LabelledOrderedTree(OrderedTree([[],[[],[]],[]]))651+ None[None[], None[None[], None[]], None[]]652+ """653+ # We must initialize the label before the subtrees to allows rooted654+ # trees canonization. Indeed it needs that ``self``._hash_() is working655+ # at the end of the call super(..., self).__init__(...)656+ if isinstance(children, self.__class__):657+ if label is None:658+ self._label = children._label659+ else:660+ self._label = label661+ else:662+ self._label = label663+ super(AbstractLabelledTree, self).__init__(parent, children, check=check)664+665+ def _repr_(self):666+ """667+ Returns the string representation of ``self``668+669+ TESTS::670+671+ sage: LabelledOrderedTree([]) # indirect doctest672+ None[]673+ sage: LabelledOrderedTree([], label=3) # indirect doctest674+ 3[]675+ sage: LabelledOrderedTree([[],[[]]]) # indirect doctest676+ None[None[], None[None[]]]677+ sage: LabelledOrderedTree([[],LabelledOrderedTree([[]], label=2)], label=3)678+ 3[None[], 2[None[]]]679+ """680+ return "%s%s"%(self._label, self[:])681+682+ def label(self, path=None):683+ """684+ Returns the label of ``self``685+686+ INPUT:687+688+ - ``path`` -- None (default) or a path (list or tuple of children index689+ in the tree)690+691+ OUTPUT: the label of the subtree at indexed by ``path``692+693+ EXAMPLES::694+695+ sage: t=LabelledOrderedTree([[],[]], label = 3)696+ sage: t.label()697+ 3698+ sage: t[0].label()699+ sage: t=LabelledOrderedTree([LabelledOrderedTree([], 5),[]], label = 3)700+ sage: t.label()701+ 3702+ sage: t[0].label()703+ 5704+ sage: t[1].label()705+ sage: t.label([0])706+ 5707+ """708+ if path is None:709+ return self._label710+ else:711+ tr = self712+ for i in path:713+ tr = tr[i]714+ return tr._label715+716+ def labels(self):717+ """718+ Returns the list of labels of ``self``719+720+ EXAMPLES::721+722+ sage: LT = LabelledOrderedTree723+ sage: t = LT([LT([],label='b'),LT([],label='c')],label='a')724+ sage: t.labels()725+ ['a', 'b', 'c']726+727+ sage: LBT = LabelledBinaryTree728+ sage: LBT([LBT([],label=1),LBT([],label=4)],label=2).labels()729+ [2, 1, 4]730+ """731+ return [t.label() for t in self.subtrees()]732+733+ def leaf_labels(self):734+ """735+ Returns the list of labels of the leaves of ``self``736+737+ EXAMPLES::738+739+ sage: LT = LabelledOrderedTree740+ sage: t = LT([LT([],label='b'),LT([],label='c')],label='a')741+ sage: t.leaf_labels()742+ ['b', 'c']743+744+ sage: LBT = LabelledBinaryTree745+ sage: bt = LBT([LBT([],label='b'),LBT([],label='c')],label='a')746+ sage: bt.leaf_labels()747+ ['b', 'c']748+ sage: LBT([], label='1').leaf_labels()749+ ['1']750+ sage: LBT(None).leaf_labels()751+ []752+ """753+ return [t.label() for t in self.subtrees() if t.node_number()==1]754+755+ def __eq__(self, other):756+ """757+ Tests if ``self`` is equal to ``other``758+759+ TESTS::760+761+ sage LabelledOrderedTree() == LabelledOrderedTree()762+ True763+ sage LabelledOrderedTree([]) == LabelledOrderedTree()764+ False765+ sage: t1 = LabelledOrderedTree([[],[[]]])766+ sage: t2 = LabelledOrderedTree([[],[[]]])767+ sage: t1 == t2768+ True769+ sage: t2 = LabelledOrderedTree(t1)770+ sage: t1 == t2771+ True772+ sage: t1 = LabelledOrderedTree([[],[[]]])773+ sage: t2 = LabelledOrderedTree([[[]],[]])774+ sage: t1 == t2775+ False776+ """777+ return ( super(AbstractLabelledTree, self).__eq__(other) and778+ self._label == other._label )779+780+ def _hash_(self):781+ """782+ Returns the hash value for ``self``783+784+ TESTS::785+786+ sage: t1 = LabelledOrderedTree([[],[[]]], label = 1); t1hash = t1.__hash__()787+ sage: LabelledOrderedTree([[],[[]]], label = 1).__hash__() == t1hash788+ True789+ sage: LabelledOrderedTree([[[]],[]], label = 1).__hash__() == t1hash790+ False791+ sage: LabelledOrderedTree(t1, label = 1).__hash__() == t1hash792+ True793+ sage: LabelledOrderedTree([[],[[]]], label = 25).__hash__() == t1hash794+ False795+ sage: LabelledOrderedTree(t1, label = 25).__hash__() == t1hash796+ False797+798+ sage: LabelledBinaryTree([[],[[],[]]], label = 25).__hash__() #random799+ 8544617749928727644800+801+ We check that the hash value depend on the value of the labels of the802+ subtrees::803+804+ sage: LBT = LabelledBinaryTree805+ sage: t1 = LBT([], label = 1)806+ sage: t2 = LBT([], label = 2)807+ sage: t3 = LBT([], label = 3)808+ sage: t12 = LBT([t1, t2], label = "a")809+ sage: t13 = LBT([t1, t3], label = "a")810+ sage: t12.__hash__() != t13.__hash__()811+ True812+ """813+ return self._UnLabelled._hash_(self) ^ hash(self._label)814+815+ def shape(self):816+ """817+ Returns the unlabelled tree associated to ``self``818+819+ EXAMPLES::820+821+ sage: t = LabelledOrderedTree([[],[[]]], label = 25).shape(); t822+ [[], [[]]]823+824+ sage: LabelledBinaryTree([[],[[],[]]], label = 25).shape()825+ [[., .], [[., .], [., .]]]826+827+ TESTS::828+829+ sage: t.parent()830+ Ordered trees831+ sage: type(t)832+ <class 'sage.combinat.ordered_tree.OrderedTrees_all_with_category.element_class'>833+ """834+ TR = self.parent().unlabelled_trees()835+ if not self:836+ return TR.leaf()837+ else:838+ return TR._element_constructor_([i.shape() for i in self])839+840+ def as_digraph(self):841+ """842+ Returns a directed graph version of ``self``843+844+ EXAMPLES::845+846+ sage: LT=LabelledOrderedTrees()847+ sage: ko=LT([LT([],label=6),LT([],label=1)],label=9)848+ sage: ko.as_digraph()849+ Digraph on 3 vertices850+851+ sage: t = BinaryTree([[None, None],[[],None]]);852+ sage: lt = t.canonical_labelling()853+ sage: lt.as_digraph()854+ Digraph on 4 vertices855+ """856+ from sage.graphs.digraph import DiGraph857+ resu=dict([[self.label(),858+ [t.label() for t in self if not t.is_empty()]]])859+ resu=DiGraph(resu)860+ for t in self:861+ if not t.is_empty():862+ resu=resu.union(t.as_digraph())863+ return resu864+865+866+class AbstractLabelledClonableTree(AbstractLabelledTree,867+ AbstractClonableTree):868+ """869+ Abstract Labelled Clonable Tree870+871+ This class take care of modification for the label by the clone protocol.872+873+ .. note:: Due to the limitation of Cython inheritance, one cannot inherit874+ here from :class:`ClonableArray`, because it would prevent us to875+ inherit later from :class:`~sage.structure.list_clone.ClonableList`.876+ """877+ def set_root_label(self, label):878+ """879+ Sets the label of the root of ``self``880+881+ INPUT: ``label`` -- any Sage object882+883+ OUPUT: ``None``, ``self`` is modified in place884+885+ .. note::886+887+ ``self`` must be in a mutable state. See888+ :mod:`sage.structure.list_clone` for more details about889+ mutability.890+891+ EXAMPLES::892+893+ sage: t=LabelledOrderedTree([[],[[],[]]])894+ sage: t.set_root_label(3)895+ Traceback (most recent call last):896+ ...897+ ValueError: object is immutable; please change a copy instead.898+ sage: with t.clone() as t:899+ ... t.set_root_label(3)900+ sage: t.label()901+ 3902+ sage: t903+ 3[None[], None[None[], None[]]]904+905+ This also work for binary trees::906+907+ sage: bt=LabelledBinaryTree([[],[]])908+ sage: bt.set_root_label(3)909+ Traceback (most recent call last):910+ ...911+ ValueError: object is immutable; please change a copy instead.912+ sage: with bt.clone() as bt:913+ ... bt.set_root_label(3)914+ sage: bt.label()915+ 3916+ sage: bt917+ 3[None[., .], None[., .]]918+919+ TESTS::920+921+ sage: with t.clone() as t:922+ ... t[0] = LabelledOrderedTree(t[0], label = 4)923+ sage: t924+ 3[4[], None[None[], None[]]]925+ sage: with t.clone() as t:926+ ... t[1,0] = LabelledOrderedTree(t[1,0], label = 42)927+ sage: t928+ 3[4[], None[42[], None[]]]929+ """930+ self._require_mutable()931+ self._label = label932+933+ def set_label(self, path, label):934+ """935+ Changes the label of subtree indexed by ``path`` to ``label``936+937+ INPUT:938+939+ - ``path`` -- ``None`` (default) or a path (list or tuple of children940+ index in the tree)941+942+ - ``label`` -- any sage object943+944+ OUPUT: Nothing, ``self`` is modified in place945+946+ .. note::947+948+ ``self`` must be in a mutable state. See949+ :mod:`sage.structure.list_clone` for more details about950+ mutability.951+952+ EXAMPLES::953+954+ sage: t=LabelledOrderedTree([[],[[],[]]])955+ sage: t.set_label((0,), 4)956+ Traceback (most recent call last):957+ ...958+ ValueError: object is immutable; please change a copy instead.959+ sage: with t.clone() as t:960+ ... t.set_label((0,), 4)961+ sage: t962+ None[4[], None[None[], None[]]]963+ sage: with t.clone() as t:964+ ... t.set_label((1,0), label = 42)965+ sage: t966+ None[4[], None[42[], None[]]]967+968+ .. todo::969+970+ Do we want to implement the following syntactic sugar::971+972+ with t.clone() as tt:973+ tt.labels[1,2] = 3 ?974+ """975+ self._require_mutable()976+ path = tuple(path)977+ if path == ():978+ self._label = label979+ else:980+ with self[path[0]].clone() as child:981+ child.set_label(path[1:], label)982+ self[path[0]] = child983+984+ def map_labels(self, f):985+ """986+ Applies the function `f` to the labels of ``self``987+988+ This method returns a copy of ``self`` on which the function `f` has989+ been applied on all labels (a label `x` is replaced by `f(x)`).990+991+ EXAMPLES::992+993+ sage: LT = LabelledOrderedTree994+ sage: t = LT([LT([],label=1),LT([],label=7)],label=3); t995+ 3[1[], 7[]]996+ sage: t.map_labels(lambda z:z+1)997+ 4[2[], 8[]]998+999+ sage: LBT = LabelledBinaryTree1000+ sage: bt = LBT([LBT([],label=1),LBT([],label=4)],label=2); bt1001+ 2[1[., .], 4[., .]]1002+ sage: bt.map_labels(lambda z:z+1)1003+ 3[2[., .], 5[., .]]1004+ """1005+ if self.is_empty():1006+ return self1007+ return self.parent()([t.map_labels(f) for t in self],1008+ label=f(self.label()))1009diff --git a/sage/combinat/all.py b/sage/combinat/all.py1010--- a/sage/combinat/all.py1011+++ b/sage/combinat/all.py1012@@ -86,6 +86,10 @@ from alternating_sign_matrix import Alte1013# Non Decreasing Parking Functions1014from non_decreasing_parking_function import NonDecreasingParkingFunctions, NonDecreasingParkingFunction10151016+from ordered_tree import (OrderedTree, OrderedTrees,1017+ LabelledOrderedTree, LabelledOrderedTrees)1018+from binary_tree import (BinaryTree, BinaryTrees,1019+ LabelledBinaryTree, LabelledBinaryTrees)10201021from combination import Combinations1022from cartesian_product import CartesianProduct1023diff --git a/sage/combinat/binary_tree.py b/sage/combinat/binary_tree.py1024new file mode 1006441025--- /dev/null1026+++ b/sage/combinat/binary_tree.py1027@@ -0,0 +1,1039 @@1028+"""1029+Binary trees1030+1031+This module deals with binary trees as mathematical (in particular immmutable)1032+objects.1033+1034+.. note :: If you need the data-structure for example to represent sets or hash1035+ tables with AVL trees, you should have a look at1036+ :mod:`sage.misc.sagex_ds`.1037+1038+On the use of Factories to query a database of counting algorithms1039+------------------------------------------------------------------1040+1041+**The problem we try to solve**1042+1043+A common problem in combinatorics is to enumerate or count some standard1044+mathematical objects satisfying a set of constraints. For instance, one can be1045+interested in the :mod:`partitions <sage.combinat.partition>` of an integer `n`1046+of length `7` and parts of size at least `3` and at most `8`, [...]1047+1048+For partitions, the number of different parameters available is actually quite1049+large :1050+1051+- The length of the partition (i.e. partitions in `k` parts, or in "at least"1052+ `k_1` parts "at most" `k_2` parts).1053+1054+- The sum of the partition (i.e. the integer `n`).1055+1056+- The min/max size of a part, or even a set of integers such that the partition1057+ should only use integers from the given set.1058+1059+- The min/max slope of the partition.1060+1061+- An inner and outer profile.1062+1063+- A min/max value for the lexicographical ordering of the partition.1064+1065+One may in particular be interested in enumerating/counting the partitions1066+satisfying *some arbitrary combination* of constraints using the parameters1067+listed above.1068+1069+This all means that there is a real need of unifying a large family of1070+algorithms, so that users do not have to find their way through a library1071+of 50 different counting/enumeration algorithms *all* dealing with partitions1072+with different set of parameters.1073+1074+**How we solve it**1075+1076+We try to build a *database* of algorithms that the user can query easily in1077+order to use the best implementation for his needs.1078+1079+Namely, in the case of :mod:`partitions <sage.combinat.partition>`, we want to1080+define a class factory named ``Partitions`` and accepting any combination of1081+constraints as an input. The role of the ``Partitions`` class factory is in this1082+situation to identify the counting/enumeration algorithm corresponding to this1083+set of constraint, and to return a hand-made object with the best set of1084+methods.1085+1086+**The design**1087+1088+For each combination of constraints that has specific enumeration/counting1089+algorithms in Sage, we want to create a corresponding class. The result will be1090+-- if we stick with the example of partitions -- a brand new Zoo with weird things1091+inside :1092+1093+- ``PartitionsWithFixedSlopeAndOuterProfile(slope, outer_profile)`` --1094+ representing the partitions with slope ``slope`` and outer profile1095+ ``outer_profile``1096+1097+- ``PartitionsWithRestrictedPartsAndBoundedLength(part_set, length)`` --1098+ represeting the partitions with a set of allowed parts and given length.1099+1100+- ...1101+1102+Each of these classes should define methods like ``__iter__`` (so that we can1103+iterate on its elements) or ``cardinality``.1104+1105+The main class ``Partitions`` will then take as arguments *all of the*1106+*combinations of parameters the user may like*, and query the database for the1107+best secialized class implemented. The user then receives an instance of this1108+specialized class that he can use with the best algorithms implemented.1109+1110+Of course, it may happen that there is actually no algorithm able to enumerate1111+partitions with the set of constraints specified. In this case, the best way is1112+to build a class enumerating a larger set of partitions, and to check for each1113+of them whether is also satisfies the more restrictive set of constraints. This1114+is costly, but it is the best way available, and the library should also be able1115+to answer the question *"what is the best implementation available to list the1116+partitions asked by the user ?"*. We then need to make sure we enumerate as few1117+unnecessary elements as possible.1118+1119+**AUTHORS:**1120+1121+- Florent Hivert (2010-2011): initial implementation.1122+"""1123+#*****************************************************************************1124+# Copyright (C) 2010 Florent Hivert <[email protected]>,1125+#1126+# Distributed under the terms of the GNU General Public License (GPL)1127+# as published by the Free Software Foundation; either version 2 of1128+# the License, or (at your option) any later version.1129+# http://www.gnu.org/licenses/1130+#*****************************************************************************1131+from sage.structure.list_clone import ClonableArray, ClonableList1132+from sage.combinat.abstract_tree import (AbstractClonableTree,1133+ AbstractLabelledClonableTree)1134+from sage.combinat.ordered_tree import LabelledOrderedTrees1135+from sage.rings.integer import Integer1136+from sage.misc.classcall_metaclass import ClasscallMetaclass1137+from sage.misc.lazy_attribute import lazy_attribute, lazy_class_attribute1138+1139+class BinaryTree(AbstractClonableTree, ClonableArray):1140+ """1141+ The class of binary trees1142+1143+ INPUT:1144+1145+ - ``children`` -- ``None`` (default) or a list, tuple or iterable of1146+ length 2 of binary trees or convertible objects.1147+1148+ - ``check`` -- (default to ``True``) whether check for binary should be1149+ performed or not.1150+1151+ .. warning:: despite what the HTML documentation may say, ``BinaryTree``1152+ does not have any ``parent`` argument, as the examples below1153+ show.1154+1155+ EXAMPLES::1156+1157+ sage: BinaryTree()1158+ .1159+ sage: BinaryTree([None, None])1160+ [., .]1161+ sage: BinaryTree([None, []])1162+ [., [., .]]1163+ sage: BinaryTree([[], None])1164+ [[., .], .]1165+ sage: BinaryTree([[], None, []])1166+ Traceback (most recent call last):1167+ ...1168+ AssertionError: This is not a binary tree1169+1170+ TESTS::1171+1172+ sage: t1 = BinaryTree([[None, [[],[[], None]]],[[],[]]])1173+ sage: t2 = BinaryTree([[[],[]],[]])1174+ sage: with t1.clone() as t1c:1175+ ... t1c[1,1,1] = t21176+ sage: t1 == t1c1177+ False1178+ """1179+ __metaclass__ = ClasscallMetaclass1180+1181+ @staticmethod1182+ def __classcall_private__(cls, *args, **opts):1183+ """1184+ Ensure that binary trees created by the enumerated sets and directly1185+ are the same and that they are instances of :class:`BinaryTree`1186+1187+ TESTS::1188+1189+ sage: from sage.combinat.binary_tree import BinaryTrees_all1190+ sage: issubclass(BinaryTrees_all().element_class, BinaryTree)1191+ True1192+ sage: t0 = BinaryTree([[],[[], None]])1193+ sage: t0.parent()1194+ Binary trees1195+ sage: type(t0)1196+ <class 'sage.combinat.binary_tree.BinaryTrees_all_with_category.element_class'>1197+1198+ sage: t1 = BinaryTrees()([[],[[], None]])1199+ sage: t1.parent() is t0.parent()1200+ True1201+ sage: type(t1) is type(t0)1202+ True1203+1204+ sage: t1 = BinaryTrees(4)([[],[[], None]])1205+ sage: t1.parent() is t0.parent()1206+ True1207+ sage: type(t1) is type(t0)1208+ True1209+ """1210+ return cls._auto_parent.element_class(cls._auto_parent, *args, **opts)1211+1212+ @lazy_class_attribute1213+ def _auto_parent(cls):1214+ """1215+ The automatic parent of the element of this class1216+1217+ When calling the constructor of an element of this class, one needs a1218+ parent. This class attribute specifies which parent is used.1219+1220+ EXAMPLES::1221+1222+ sage: BinaryTree._auto_parent1223+ Binary trees1224+ sage: BinaryTree([None, None]).parent()1225+ Binary trees1226+ """1227+ return BinaryTrees_all()1228+1229+ def __init__(self, parent, children = None, check=True):1230+ """1231+ TESTS::1232+1233+ sage: BinaryTree([None, None]).parent()1234+ Binary trees1235+ """1236+ if children is None:1237+ children = []1238+ elif children == [] or isinstance(children, (Integer, int)):1239+ children = [None, None]1240+ if (children.__class__ is self.__class__ and1241+ children.parent() == parent):1242+ children = list(children)1243+ else:1244+ children = [self.__class__(parent, x) for x in children]1245+ ClonableArray.__init__(self, parent, children, check=check)1246+1247+ def check(self):1248+ """1249+ Checks that ``self`` is a binary tree1250+1251+ EXAMPLES::1252+1253+ sage: BinaryTree([[], []]) # indirect doctest1254+ [[., .], [., .]]1255+ sage: BinaryTree([[], [], []]) # indirect doctest1256+ Traceback (most recent call last):1257+ ...1258+ AssertionError: This is not a binary tree1259+ sage: BinaryTree([[]]) # indirect doctest1260+ Traceback (most recent call last):1261+ ...1262+ AssertionError: This is not a binary tree1263+ """1264+ assert (not self or len(self) == 2), "This is not a binary tree"1265+1266+ def _repr_(self):1267+ """1268+ TESTS::1269+1270+ sage: t1 = BinaryTree([[], None]); t1 # indirect doctest1271+ [[., .], .]1272+ sage: BinaryTree([[None, t1], None]) # indirect doctest1273+ [[., [[., .], .]], .]1274+ """1275+ if not self:1276+ return "."1277+ else:1278+ return super(BinaryTree, self)._repr_()1279+1280+ def is_empty(self):1281+ """1282+ Returns whether ``self`` is empty.1283+1284+ EXAMPLES::1285+1286+ sage: BinaryTree().is_empty()1287+ True1288+ sage: BinaryTree([]).is_empty()1289+ False1290+ sage: BinaryTree([[], None]).is_empty()1291+ False1292+ """1293+ return not self1294+1295+ def graph(self):1296+ """1297+ Convert ``self`` to a digraph1298+1299+ EXAMPLE::1300+1301+ sage: t1 = BinaryTree([[], None])1302+ sage: t1.graph()1303+ Digraph on 5 vertices1304+1305+ sage: t1 = BinaryTree([[], [[], None]])1306+ sage: t1.graph()1307+ Digraph on 9 vertices1308+ sage: t1.graph().edges()1309+ [(0, 1, None), (0, 4, None), (1, 2, None), (1, 3, None), (4, 5, None), (4, 8, None), (5, 6, None), (5, 7, None)]1310+ """1311+ from sage.graphs.graph import DiGraph1312+ res = DiGraph()1313+ def rec(tr, idx):1314+ if not tr:1315+ return1316+ else:1317+ nbl = 2*tr[0].node_number() + 11318+ res.add_edges([[idx,idx+1], [idx,idx+1+nbl]])1319+ rec(tr[0], idx + 1)1320+ rec(tr[1], idx + nbl + 1)1321+ rec(self, 0)1322+ return res1323+1324+ def canonical_labelling(self,shift=1):1325+ """1326+ Returns a labelled version of ``self``.1327+1328+ The actual canonical labelling is currently unspecified. However, it1329+ is guaranteed to have labels in `1...n` where `n` is the number of1330+ node of the tree. Moreover, two (unlabelled) trees compare as equal if1331+ and only if they canonical labelled trees compare as equal.1332+1333+ EXAMPLES::1334+1335+ sage: BinaryTree().canonical_labelling()1336+ .1337+ sage: BinaryTree([]).canonical_labelling()1338+ 1[., .]1339+ sage: BinaryTree([[[], [[], None]], [[], []]]).canonical_labelling()1340+ 5[2[1[., .], 4[3[., .], .]], 7[6[., .], 8[., .]]]1341+ """1342+ LTR = self.parent().labelled_trees()1343+ if self:1344+ sz0 = self[0].node_number()1345+ return LTR([self[0].canonical_labelling(shift),1346+ self[1].canonical_labelling(shift+1+sz0)],1347+ label=shift+sz0)1348+ else:1349+ return LTR(None)1350+1351+ def show(self):1352+ """1353+ TESTS::1354+1355+ sage: t1 = BinaryTree([[], [[], None]])1356+ sage: t1.show()1357+ """1358+ self.graph().show(layout='tree', tree_root=0, tree_orientation="down")1359+1360+ def make_node(self, child_list = [None, None]):1361+ """1362+ Modify ``self`` so that it becomes a node with children ``childlist``1363+1364+ INPUT:1365+1366+ - ``child_list`` -- a pair of binary trees (or objects convertible to)1367+1368+ .. note:: ``self`` must be in a mutable state.1369+1370+ .. seealso::1371+ :meth:`make_leaf <sage.combinat.binary_tree.BinaryTree.make_leaf>`1372+1373+ EXAMPLES::1374+1375+ sage: t = BinaryTree()1376+ sage: t.make_node([None, None])1377+ Traceback (most recent call last):1378+ ...1379+ ValueError: object is immutable; please change a copy instead.1380+ sage: with t.clone() as t1:1381+ ... t1.make_node([None, None])1382+ sage: t, t11383+ (., [., .])1384+ sage: with t.clone() as t:1385+ ... t.make_node([BinaryTree(), BinaryTree(), BinaryTree([])])1386+ Traceback (most recent call last):1387+ AssertionError: the list must have length 21388+ sage: with t1.clone() as t2:1389+ ... t2.make_node([t1, t1])1390+ sage: with t2.clone() as t3:1391+ ... t3.make_node([t1, t2])1392+ sage: t1, t2, t31393+ ([., .], [[., .], [., .]], [[., .], [[., .], [., .]]])1394+ """1395+ self._require_mutable()1396+ child_lst = [self.__class__(self.parent(), x) for x in child_list]1397+ assert(len(child_lst) == 2), "the list must have length 2"1398+ self.__init__(self.parent(), child_lst, check=False)1399+1400+ def make_leaf(self):1401+ """1402+ Modify ``self`` so that it became a leaf1403+1404+ .. note:: ``self`` must be in a mutable state.1405+1406+ .. seealso::1407+ :meth:`make_node <sage.combinat.binary_tree.BinaryTree.make_node>`1408+1409+ EXAMPLES::1410+1411+ sage: t = BinaryTree([None, None])1412+ sage: t.make_leaf()1413+ Traceback (most recent call last):1414+ ...1415+ ValueError: object is immutable; please change a copy instead.1416+ sage: with t.clone() as t1:1417+ ... t1.make_leaf()1418+ sage: t, t11419+ ([., .], .)1420+ """1421+ self._require_mutable()1422+ self.__init__(self.parent(), None)1423+1424+ def _to_dyck_word_rec(self):1425+ r"""1426+ EXAMPLES::1427+1428+ sage: BinaryTree()._to_dyck_word_rec()1429+ []1430+ sage: BinaryTree([])._to_dyck_word_rec()1431+ [1, 0]1432+ sage: BinaryTree([[[], [[], None]], [[], []]])._to_dyck_word_rec()1433+ [1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0]1434+ """1435+ if self:1436+ return ([1]+self[0]._to_dyck_word_rec()+1437+ [0]+self[1]._to_dyck_word_rec())1438+ else:1439+ return []1440+1441+ def to_dyck_word(self):1442+ r"""1443+ Return the Dyck word associated to ``self``1444+1445+ The bijection is defined recursively as follows:1446+1447+ - a leaf is associated to the empty Dyck Word1448+1449+ - a tree with chidren `l,r` is associated to the Dyck word1450+ `1 T(l) 0 T(r)` where `T(l)` and `T(r)` are the trees1451+ associated to `l` and `r`.1452+1453+ EXAMPLES::1454+1455+ sage: BinaryTree().to_dyck_word()1456+ []1457+ sage: BinaryTree([]).to_dyck_word()1458+ [1, 0]1459+ sage: BinaryTree([[[], [[], None]], [[], []]]).to_dyck_word()1460+ [1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0]1461+ """1462+ from sage.combinat.dyck_word import DyckWord1463+ return DyckWord(self._to_dyck_word_rec())1464+1465+ def canopee(self):1466+ """1467+ Returns the canopee of ``self``1468+1469+ The *canopee* of a non empty binary tree `T` with `n` internal nodes is1470+ the list `l` of `0` and `1` of length `n-1` obtained by going along the1471+ leaves of `T` from left to right except the two extremal ones, writing1472+ `0` if the leaf is a right leaf and `1` is a left leaf.1473+1474+ EXAMPLES::1475+1476+ sage: BinaryTree([]).canopee()1477+ []1478+ sage: BinaryTree([None, []]).canopee()1479+ [1]1480+ sage: BinaryTree([[], None]).canopee()1481+ [0]1482+ sage: BinaryTree([[], []]).canopee()1483+ [0, 1]1484+ sage: BinaryTree([[[], [[], None]], [[], []]]).canopee()1485+ [0, 1, 0, 0, 1, 0, 1]1486+1487+ The number of pairs `(t_1, t_2)` of binary trees of size `n` such that1488+ the canopee of `t_1` is the complementary of the canopee of `t_2` is1489+ also the number of Baxter permutations (see [DG]_, see also sequences1490+ A001181 in Sloane's database). We check this in small cases::1491+1492+ sage: [len([(u,v) for u in BinaryTrees(n) for v in BinaryTrees(n)1493+ ... if map(lambda x:1-x, u.canopee()) == v.canopee()])1494+ ... for n in range(1, 5)]1495+ [1, 2, 6, 22]1496+1497+ Here is a less trivial implementation of this::1498+1499+ sage: from sage.sets.finite_set_map_cy import fibers1500+ sage: from sage.misc.all import attrcall1501+ sage: def baxter(n):1502+ ... f = fibers(lambda t: tuple(t.canopee()),1503+ ... BinaryTrees(n))1504+ ... return sum(len(f[i])*len(f[tuple(1-x for x in i)])1505+ ... for i in f)1506+ sage: [baxter(n) for n in range(1, 7)]1507+ [1, 2, 6, 22, 92, 422]1508+1509+ TESTS::1510+1511+ sage: t = BinaryTree().canopee()1512+ Traceback (most recent call last):1513+ ...1514+ ValueError: canopee is only defined for non empty binary trees1515+1516+ REFERENCES:1517+1518+ .. [DG] S. Dulucq and O, Guibert. Mots de piles, tableaux1519+ standards et permutations de Baxter, proceedings of1520+ Formal Power Series and Algebraic Combinatorics, 1994.1521+ """1522+ if not self:1523+ raise ValueError, "canopee is only defined for non empty binary trees"1524+ res = []1525+ def add_leaf_rec(tr):1526+ for i in range(2):1527+ if tr[i]:1528+ add_leaf_rec(tr[i])1529+ else:1530+ res.append(1-i)1531+ add_leaf_rec(self)1532+ return res[1:-1]1533+1534+1535+from sage.structure.parent import Parent1536+from sage.structure.unique_representation import UniqueRepresentation1537+from sage.misc.classcall_metaclass import ClasscallMetaclass1538+1539+from sage.sets.non_negative_integers import NonNegativeIntegers1540+from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets1541+from sage.sets.family import Family1542+from sage.misc.cachefunc import cached_method1543+1544+1545+# Abstract class to serve as a Factory no instance are created.1546+class BinaryTrees(UniqueRepresentation, Parent):1547+ """1548+ Factory for binary trees.1549+1550+ INPUT:1551+1552+ - ``size`` -- (optional) an integer1553+1554+ OUPUT:1555+1556+ - the set of all binary trees (of the given ``size`` if specified)1557+1558+ EXAMPLES::1559+1560+ sage: BinaryTrees()1561+ Binary trees1562+1563+ sage: BinaryTrees(2)1564+ Binary trees of size 21565+1566+ .. note:: this in a factory class whose constructor returns instances of1567+ subclasses.1568+1569+ .. note:: the fact that OrderedTrees is a class instead a simple callable1570+ is an implementation detail. It could be changed in the future1571+ and one should not rely on it.1572+ """1573+ @staticmethod1574+ def __classcall_private__(cls, n=None):1575+ """1576+ TESTS::1577+1578+ sage: from sage.combinat.binary_tree import BinaryTrees_all, BinaryTrees_size1579+ sage: isinstance(BinaryTrees(2), BinaryTrees)1580+ True1581+ sage: isinstance(BinaryTrees(), BinaryTrees)1582+ True1583+ sage: BinaryTrees(2) is BinaryTrees_size(2)1584+ True1585+ sage: BinaryTrees(5).cardinality()1586+ 421587+ sage: BinaryTrees() is BinaryTrees_all()1588+ True1589+ """1590+ if n is None:1591+ return BinaryTrees_all()1592+ else:1593+ assert (isinstance(n, (Integer, int)) and n >= 0), "n must be a non negative integer"1594+ return BinaryTrees_size(Integer(n))1595+1596+ @cached_method1597+ def leaf(self):1598+ """1599+ Return a left tree with ``self`` as parent.1600+1601+ EXAMPLES::1602+1603+ sage: BinaryTrees().leaf()1604+ .1605+1606+ TEST::1607+1608+ sage: (BinaryTrees().leaf() is1609+ ... sage.combinat.binary_tree.BinaryTrees_all().leaf())1610+ True1611+ """1612+ return self(None)1613+1614+#################################################################1615+# Enumerated set of all binary trees1616+#################################################################1617+class BinaryTrees_all(DisjointUnionEnumeratedSets, BinaryTrees):1618+1619+ def __init__(self):1620+ """1621+ TESTS::1622+1623+ sage: from sage.combinat.binary_tree import BinaryTrees_all1624+ sage: B = BinaryTrees_all()1625+ sage: B.cardinality()1626+ +Infinity1627+1628+ sage: it = iter(B)1629+ sage: (it.next(), it.next(), it.next(), it.next(), it.next())1630+ (., [., .], [., [., .]], [[., .], .], [., [., [., .]]])1631+ sage: it.next().parent()1632+ Binary trees1633+ sage: B([])1634+ [., .]1635+1636+ sage: B is BinaryTrees_all()1637+ True1638+ sage: TestSuite(B).run()1639+ """1640+ DisjointUnionEnumeratedSets.__init__(1641+ self, Family(NonNegativeIntegers(), BinaryTrees_size),1642+ facade=True, keepkey = False)1643+1644+ def _repr_(self):1645+ """1646+ TEST::1647+1648+ sage: BinaryTrees() # indirect doctest1649+ Binary trees1650+ """1651+ return "Binary trees"1652+1653+ def __contains__(self, x):1654+ """1655+ TESTS::1656+1657+ sage: S = BinaryTrees()1658+ sage: 1 in S1659+ False1660+ sage: S([]) in S1661+ True1662+ """1663+ return isinstance(x, self.element_class)1664+1665+ def __call__(self, x=None, *args, **keywords):1666+ """1667+ Ensure that ``None`` instead of ``0`` is passed by default.1668+1669+ TESTS::1670+1671+ sage: B = BinaryTrees()1672+ sage: B()1673+ .1674+ """1675+ return super(BinaryTrees, self).__call__(x, *args, **keywords)1676+1677+ def unlabelled_trees(self):1678+ """1679+ Returns the set of unlabelled trees associated to ``self``1680+1681+ EXAMPLES::1682+1683+ sage: BinaryTrees().unlabelled_trees()1684+ Binary trees1685+ """1686+ return self1687+1688+ def labelled_trees(self):1689+ """1690+ Returns the set of labelled trees associated to ``self``1691+1692+ EXAMPLES::1693+1694+ sage: BinaryTrees().labelled_trees()1695+ Labelled binary trees1696+ """1697+ return LabelledBinaryTrees()1698+1699+ def _element_constructor_(self, *args, **keywords):1700+ """1701+ EXAMPLES::1702+1703+ sage: B = BinaryTrees()1704+ sage: B._element_constructor_([])1705+ [., .]1706+ sage: B([[],[]]) # indirect doctest1707+ [[., .], [., .]]1708+ sage: B(None) # indirect doctest1709+ .1710+ """1711+ return self.element_class(self, *args, **keywords)1712+1713+ Element = BinaryTree1714+1715+from sage.misc.lazy_attribute import lazy_attribute1716+from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets1717+from combinat import catalan_number1718+#################################################################1719+# Enumerated set of binary trees of a given size1720+#################################################################1721+class BinaryTrees_size(BinaryTrees):1722+ """1723+ The enumerated sets of binary trees of given size1724+1725+ TESTS::1726+1727+ sage: from sage.combinat.binary_tree import BinaryTrees_size1728+ sage: for i in range(6): TestSuite(BinaryTrees_size(i)).run()1729+ """1730+ def __init__(self, size):1731+ """1732+ TESTS::1733+1734+ sage: S = BinaryTrees(3)1735+ sage: S == loads(dumps(S))1736+ True1737+1738+ sage: S is BinaryTrees(3)1739+ True1740+ """1741+ super(BinaryTrees_size, self).__init__(category = FiniteEnumeratedSets())1742+ self._size = size1743+1744+ def _repr_(self):1745+ """1746+ TESTS::1747+1748+ sage: BinaryTrees(3) # indirect doctest1749+ Binary trees of size 31750+ """1751+ return "Binary trees of size %s"%(self._size)1752+1753+ def __contains__(self, x):1754+ """1755+ TESTS::1756+1757+ sage: S = BinaryTrees(3)1758+ sage: 1 in S1759+ False1760+ sage: S([[],[]]) in S1761+ True1762+ """1763+ return isinstance(x, self.element_class) and x.node_number() == self._size1764+1765+ def _an_element_(self):1766+ """1767+ TESTS::1768+1769+ sage: BinaryTrees(0).an_element() # indirect doctest1770+ .1771+ """1772+ return self.first()1773+1774+ def cardinality(self):1775+ """1776+ The cardinality of self1777+1778+ This is a Catalan number.1779+1780+ TESTS::1781+1782+ sage: BinaryTrees(0).cardinality()1783+ 11784+ sage: BinaryTrees(5).cardinality()1785+ 421786+ """1787+ return catalan_number(self._size)1788+1789+ def __iter__(self):1790+ """1791+ A basic generator.1792+1793+ .. todo:: could be optimized.1794+1795+ TESTS::1796+1797+ sage: BinaryTrees(0).list()1798+ [.]1799+ sage: BinaryTrees(1).list()1800+ [[., .]]1801+ sage: BinaryTrees(3).list()1802+ [[., [., [., .]]], [., [[., .], .]], [[., .], [., .]], [[., [., .]], .], [[[., .], .], .]]1803+ """1804+ if self._size == 0:1805+ yield self._element_constructor_()1806+ else:1807+ for i in range(0, self._size):1808+ for lft in self.__class__(i):1809+ for rgt in self.__class__(self._size-1-i):1810+ yield self._element_constructor_([lft, rgt])1811+1812+ @lazy_attribute1813+ def _parent_for(self):1814+ """1815+ The parent of the element generated by ``self``1816+1817+ TESTS::1818+1819+ sage: S = BinaryTrees(3)1820+ sage: S._parent_for1821+ Binary trees1822+ """1823+ return BinaryTrees_all()1824+1825+ @lazy_attribute1826+ def element_class(self):1827+ """1828+ TESTS::1829+1830+ sage: S = BinaryTrees(3)1831+ sage: S.element_class1832+ <class 'sage.combinat.binary_tree.BinaryTrees_all_with_category.element_class'>1833+ sage: S.first().__class__ == BinaryTrees().first().__class__1834+ True1835+ """1836+ return self._parent_for.element_class1837+1838+ def _element_constructor_(self, *args, **keywords):1839+ """1840+ EXAMPLES::1841+1842+ sage: S = BinaryTrees(0)1843+ sage: S([]) # indirect doctest1844+ Traceback (most recent call last):1845+ ...1846+ ValueError: Wrong number of nodes1847+ sage: S(None) # indirect doctest1848+ .1849+1850+ sage: S = BinaryTrees(1) # indirect doctest1851+ sage: S([])1852+ [., .]1853+ """1854+ res = self.element_class(self._parent_for, *args, **keywords)1855+ if res.node_number() != self._size:1856+ raise ValueError, "Wrong number of nodes"1857+ return res1858+1859+1860+1861+class LabelledBinaryTree(AbstractLabelledClonableTree, BinaryTree):1862+ """1863+ The class of labelled binary tree1864+1865+ EXAMPLE::1866+1867+ sage: LBT = LabelledBinaryTree1868+ sage: t1 = LBT([[LBT([], label=2), None], None], label=4); t11869+ 4[None[2[., .], .], .]1870+ """1871+ __metaclass__ = ClasscallMetaclass1872+1873+ @staticmethod1874+ def __classcall_private__(cls, *args, **opts):1875+ """1876+ Ensure that trees created by the sets and directly are the same and1877+ that they are instance of :class:`LabelledTree`1878+1879+ TESTS::1880+1881+ sage: issubclass(LabelledBinaryTrees().element_class, LabelledBinaryTree)1882+ True1883+ sage: t0 = LabelledBinaryTree([[],[[], None]], label = 3)1884+ sage: t0.parent()1885+ Labelled binary trees1886+ sage: type(t0)1887+ <class 'sage.combinat.binary_tree.LabelledBinaryTrees_with_category.element_class'>1888+ """1889+ return cls._auto_parent.element_class(cls._auto_parent, *args, **opts)1890+1891+ @lazy_class_attribute1892+ def _auto_parent(cls):1893+ """1894+ The automatic parent of the element of this class1895+1896+ When calling the constructor of an element of this class, one need a1897+ parent. This class attribute specifies which parent is used.1898+1899+ EXAMPLES::1900+1901+ sage: LabelledBinaryTree._auto_parent1902+ Labelled binary trees1903+ sage: LabelledBinaryTree([], label = 3).parent()1904+ Labelled binary trees1905+ """1906+ return LabelledBinaryTrees()1907+1908+ def _repr_(self):1909+ """1910+ TESTS::1911+1912+ sage: LBT = LabelledBinaryTree1913+ sage: t1 = LBT([[LBT([], label=2), None], None], label=4); t11914+ 4[None[2[., .], .], .]1915+ sage: LBT([[],[[], None]], label = 3) # indirect doctest1916+ 3[None[., .], None[None[., .], .]]1917+ """1918+ if not self:1919+ if self._label is not None:1920+ return repr(self._label)1921+ else:1922+ return "."1923+ else:1924+ return "%s%s"%(self._label, self[:])1925+1926+ def binary_search_insert(self, letter):1927+ """1928+ Insert a letter in a binary search tree1929+1930+ INPUT:1931+1932+ - ``letter`` -- any object comparable with the label of ``self``1933+1934+ .. note:: ``self`` is supposed to be a binary search tree. No check is1935+ performed.1936+1937+ EXAMPLES::1938+1939+ sage: LBT = LabelledBinaryTree1940+ sage: LBT(None).binary_search_insert(3)1941+ 3[., .]1942+ sage: LBT([], label = 1).binary_search_insert(3)1943+ 1[., 3[., .]]1944+ sage: LBT([], label = 3).binary_search_insert(1)1945+ 3[1[., .], .]1946+ sage: res = LBT(None)1947+ sage: for i in [3,1,5,2,4,6]:1948+ ... res = res.binary_search_insert(i)1949+ sage: res1950+ 3[1[., 2[., .]], 5[4[., .], 6[., .]]]1951+ """1952+ LT = self.parent()._element_constructor_1953+ if not self:1954+ return LT([], label = letter)1955+ else:1956+ if letter <= self.label():1957+ fils = self[0].binary_search_insert(letter)1958+ return LT([fils, self[1]], label=self.label())1959+ else:1960+ fils = self[1].binary_search_insert(letter)1961+ return LT([self[0], fils], label=self.label())1962+1963+ _UnLabelled = BinaryTree1964+1965+1966+class LabelledBinaryTrees(LabelledOrderedTrees):1967+ """1968+ This is a parent stub to serve as a factory class for trees with various1969+ labels constraints1970+ """1971+ def _repr_(self):1972+ """1973+ TESTS::1974+1975+ sage: LabelledBinaryTrees() # indirect doctest1976+ Labelled binary trees1977+ """1978+ return "Labelled binary trees"1979+1980+ def _an_element_(self):1981+ """1982+ Returns a labelled binary tree1983+1984+ EXAMPLE::1985+1986+ sage: LabelledBinaryTrees().an_element() # indirect doctest1987+ toto[42[3[., .], 3[., .]], 5[None[., .], None[., .]]]1988+ """1989+ LT = self._element_constructor_1990+ t = LT([], label = 3)1991+ t1 = LT([t,t], label = 42)1992+ t2 = LT([[], []], label = 5)1993+ return LT([t1,t2], label = "toto")1994+1995+ def unlabelled_trees(self):1996+ """1997+ Returns the set of unlabelled trees associated to ``self``1998+1999+ EXAMPLES::2000+2001+ sage: LabelledBinaryTrees().unlabelled_trees()2002+ Binary trees2003+2004+ This is used to compute the shape::2005+2006+ sage: t = LabelledBinaryTrees().an_element().shape(); t2007+ [[[., .], [., .]], [[., .], [., .]]]2008+ sage: t.parent()2009+ Binary trees2010+2011+ TESTS::2012+2013+ sage: t = LabelledBinaryTrees().an_element()2014+ sage: t.canonical_labelling()2015+ 4[2[1[., .], 3[., .]], 6[5[., .], 7[., .]]]2016+ """2017+ return BinaryTrees_all()2018+2019+ def labelled_trees(self):2020+ """2021+ Returns the set of labelled trees associated to ``self``2022+2023+ EXAMPLES::2024+2025+ sage: LabelledBinaryTrees().labelled_trees()2026+ Labelled binary trees2027+ """2028+ return self2029+2030+ Element = LabelledBinaryTree2031+2032+2033+2034+################################################################2035+# Interface attempt with species...2036+#2037+# Kept here for further reference when species will be improved2038+################################################################2039+# from sage.combinat.species.library import (2040+# CombinatorialSpecies, EmptySetSpecies, SingletonSpecies)2041+2042+# BT = CombinatorialSpecies()2043+# F = EmptySetSpecies()2044+# N = SingletonSpecies()2045+# BT.define(F+N*(BT*BT))2046+# # b3 = BT.isotypes(range(3))2047+# # tr = b3.list()[1]2048+2049+# def BTsp_to_bintrees(bt):2050+# """2051+# sage: from sage.combinat.binary_tree import BT, BTsp_to_bintrees2052+# sage: BTsp_to_bintrees(BT.isotypes(range(5))[0])2053+# [., [., [., [., [., .]]]]]2054+# sage: def spls(size):2055+# ... return map(BTsp_to_bintrees, BT.isotypes(range(size)).list())2056+# sage: spls(3)2057+# [[., [., [., .]]], [., [[., .], .]], [[., .], [., .]], [[., [., .]], .], [[[., .], .], .]]2058+# sage: all(spls(i) == BinaryTrees(i).list() for i in range(5))2059+# True2060+# """2061+# if len(bt) == 0:2062+# return BinaryTree()2063+# elif len(bt) == 2 and len(bt[1]) == 2:2064+# return BinaryTree(map(BTsp_to_bintrees, list(bt[1])))2065+# else:2066+# raise ValueError2067diff --git a/sage/combinat/ordered_tree.py b/sage/combinat/ordered_tree.py2068new file mode 1006442069--- /dev/null2070+++ b/sage/combinat/ordered_tree.py2071@@ -0,0 +1,748 @@2072+"""2073+Ordered Rooted Trees2074+2075+AUTHORS:2076+2077+- Florent Hivert (2010-2011): initial revision2078+- Frederic Chapoton (2010): contributed some methods2079+"""2080+#*****************************************************************************2081+# Copyright (C) 2010 Florent Hivert <[email protected]>,2082+#2083+# Distributed under the terms of the GNU General Public License (GPL)2084+# as published by the Free Software Foundation; either version 2 of2085+# the License, or (at your option) any later version.2086+# http://www.gnu.org/licenses/2087+#*****************************************************************************2088+from sage.structure.list_clone import ClonableArray, ClonableList2089+from sage.structure.parent import Parent2090+from sage.structure.unique_representation import UniqueRepresentation2091+from sage.misc.classcall_metaclass import ClasscallMetaclass2092+from sage.misc.lazy_attribute import lazy_class_attribute2093+from sage.combinat.abstract_tree import (AbstractClonableTree,2094+ AbstractLabelledClonableTree)2095+2096+class OrderedTree(AbstractClonableTree, ClonableList):2097+ """2098+ The class for (ordered rooted) Trees2099+2100+ An ordered tree is a constructed from a node called the root on which one2101+ has grafted a possibly empty list of trees. There is a total order on the2102+ children of a node which is given by the the order of the element in the2103+ list. Note that there is no empty ordered tree.2104+2105+ One can create a tree from any list (or more generally iterable) of trees2106+ or objects convertible to a tree.2107+2108+ EXAMPLES::2109+2110+ sage: x = OrderedTree([])2111+ sage: x1 = OrderedTree([x,x])2112+ sage: x2 = OrderedTree([[],[]])2113+ sage: x1 == x22114+ True2115+ sage: tt1 = OrderedTree([x,x1,x2])2116+ sage: tt2 = OrderedTree([[], [[], []], x2])2117+ sage: tt1 == tt22118+ True2119+2120+ sage: OrderedTree([]) == OrderedTree()2121+ True2122+2123+ TESTS::2124+2125+ sage: x1.__hash__() == x2.__hash__()2126+ True2127+ sage: tt1.__hash__() == tt2.__hash__()2128+ True2129+2130+ Trees are usually immutable. However they inherits from2131+ :class:`sage.structure.list_clone.ClonableList`. So that they can be2132+ modified using the clone protocol:2133+2134+ Trying to modify a non mutable tree raise an error::2135+2136+ sage: tt1[1] = tt22137+ Traceback (most recent call last):2138+ ...2139+ ValueError: object is immutable; please change a copy instead.2140+2141+ Here is the correct way to do it::2142+2143+ sage: with tt2.clone() as tt2:2144+ ... tt2[1] = tt12145+ sage: tt22146+ [[], [[], [[], []], [[], []]], [[], []]]2147+2148+ It is also possible to append a child to a tree::2149+2150+ sage: with tt2.clone() as tt3:2151+ ... tt3.append(OrderedTree([]))2152+ sage: tt32153+ [[], [[], [[], []], [[], []]], [[], []], []]2154+2155+ Or to insert a child in a tree::2156+2157+ sage: with tt2.clone() as tt3:2158+ ... tt3.insert(2, OrderedTree([]))2159+ sage: tt32160+ [[], [[], [[], []], [[], []]], [], [[], []]]2161+2162+ We check that ``tt1`` is not modified and that everything is correct with2163+ respect to equality::2164+2165+ sage: tt12166+ [[], [[], []], [[], []]]2167+ sage: tt1 == tt22168+ False2169+ sage: tt1.__hash__() == tt2.__hash__()2170+ False2171+2172+ TESTS::2173+2174+ sage: tt1bis = OrderedTree(tt1)2175+ sage: with tt1.clone() as tt1:2176+ ... tt1[1] = tt1bis2177+ sage: tt12178+ [[], [[], [[], []], [[], []]], [[], []]]2179+ sage: tt1 == tt22180+ True2181+ sage: tt1.__hash__() == tt2.__hash__()2182+ True2183+ sage: len(tt1)2184+ 32185+ sage: tt1[2]2186+ [[], []]2187+ sage: tt1[3]2188+ Traceback (most recent call last):2189+ ...2190+ IndexError: list index out of range2191+ sage: tt1[1:2]2192+ [[[], [[], []], [[], []]]]2193+2194+ Various tests involving construction, equality and hashing::2195+2196+ sage: OrderedTree() == OrderedTree()2197+ True2198+ sage: t1 = OrderedTree([[],[[]]])2199+ sage: t2 = OrderedTree([[],[[]]])2200+ sage: t1 == t22201+ True2202+ sage: t2 = OrderedTree(t1)2203+ sage: t1 == t22204+ True2205+ sage: t1 = OrderedTree([[],[[]]])2206+ sage: t2 = OrderedTree([[[]],[]])2207+ sage: t1 == t22208+ False2209+2210+ sage: t1 = OrderedTree([[],[[]]])2211+ sage: t2 = OrderedTree([[],[[]]])2212+ sage: t1.__hash__() == t2.__hash__()2213+ True2214+ sage: t2 = OrderedTree([[[]],[]])2215+ sage: t1.__hash__() == t2.__hash__()2216+ False2217+ sage: OrderedTree().__hash__() == OrderedTree([]).__hash__()2218+ True2219+ sage: tt1 = OrderedTree([t1,t2,t1])2220+ sage: tt2 = OrderedTree([t1, [[[]],[]], t1])2221+ sage: tt1.__hash__() == tt2.__hash__()2222+ True2223+2224+ Check that the hash value is correctly updated after modification::2225+2226+ sage: with tt2.clone() as tt2:2227+ ... tt2[1,1] = tt12228+ sage: tt1.__hash__() == tt2.__hash__()2229+ False2230+ """2231+2232+ __metaclass__ = ClasscallMetaclass2233+2234+ @staticmethod2235+ def __classcall_private__(cls, *args, **opts):2236+ """2237+ Ensure that trees created by the enumerated sets and directly2238+ are the same and that they are instance of :class:`OrderedTree`2239+2240+ TESTS::2241+2242+ sage: issubclass(OrderedTrees().element_class, OrderedTree)2243+ True2244+ sage: t0 = OrderedTree([[],[[], []]])2245+ sage: t0.parent()2246+ Ordered trees2247+ sage: type(t0)2248+ <class 'sage.combinat.ordered_tree.OrderedTrees_all_with_category.element_class'>2249+2250+ sage: t1 = OrderedTrees()([[],[[], []]])2251+ sage: t1.parent() is t0.parent()2252+ True2253+ sage: type(t1) is type(t0)2254+ True2255+2256+ sage: t1 = OrderedTrees(4)([[],[[]]])2257+ sage: t1.parent() is t0.parent()2258+ True2259+ sage: type(t1) is type(t0)2260+ True2261+ """2262+ return cls._auto_parent.element_class(cls._auto_parent, *args, **opts)2263+2264+ @lazy_class_attribute2265+ def _auto_parent(cls):2266+ """2267+ The automatic parent of the element of this class2268+2269+ When calling the constructor of an element of this class, one need a2270+ parent. This class attribute specifies which parent is used.2271+2272+ EXAMPLES::2273+2274+ sage: OrderedTree([[],[[]]])._auto_parent2275+ Ordered trees2276+ sage: OrderedTree([[],[[]]]).parent()2277+ Ordered trees2278+2279+ .. note::2280+2281+ It is possible to bypass the automatic parent mechanism using:2282+2283+ sage: t1 = OrderedTree.__new__(OrderedTree, Parent(), [])2284+ sage: t1.__init__(Parent(), [])2285+ sage: t12286+ []2287+ sage: t1.parent()2288+ <type 'sage.structure.parent.Parent'>2289+ """2290+ return OrderedTrees_all()2291+2292+ def __init__(self, parent=None, children=[], check=True):2293+ """2294+ TESTS::2295+2296+ sage: t1 = OrderedTrees(4)([[],[[]]])2297+ sage: TestSuite(t1).run()2298+ """2299+ if (children.__class__ is self.__class__ and2300+ children.parent() == parent):2301+ children = list(children)2302+ else:2303+ children = [self.__class__(parent, x) for x in children]2304+ ClonableArray.__init__(self, parent, children, check=check)2305+2306+ def is_empty(self):2307+ """2308+ Return if ``self`` is the empty tree2309+2310+ For ordered trees, returns always ``False``2311+2312+ .. note:: this is different from ``bool(t)`` which returns whether2313+ ``t`` has some child or not.2314+2315+ EXAMPLES::2316+2317+ sage: t = OrderedTrees(4)([[],[[]]])2318+ sage: t.is_empty()2319+ False2320+ sage: bool(t)2321+ True2322+ """2323+ return False2324+2325+from sage.categories.sets_cat import Sets, EmptySetError2326+from sage.rings.integer import Integer2327+from sage.sets.non_negative_integers import NonNegativeIntegers2328+from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets2329+from sage.sets.family import Family2330+from sage.misc.cachefunc import cached_method2331+2332+# Abstract class to serve as a Factory no instance are created.2333+class OrderedTrees(UniqueRepresentation, Parent):2334+ """2335+ Factory for ordered trees2336+2337+ INPUT:2338+2339+ - ``size`` -- (optional) an integer2340+2341+ OUPUT:2342+2343+ - the set of all ordered trees (of the given ``size`` if specified)2344+2345+ EXAMPLES::2346+2347+ sage: OrderedTrees()2348+ Ordered trees2349+2350+ sage: OrderedTrees(2)2351+ Ordered trees of size 22352+2353+ .. note:: this in a factory class whose constructor returns instances of2354+ subclasses.2355+2356+ .. note:: the fact that OrderedTrees is a class instead a simple callable2357+ is an implementation detail. It could be changed in the future2358+ and one should not rely on it.2359+ """2360+ @staticmethod2361+ def __classcall_private__(cls, n=None):2362+ """2363+ TESTS::2364+2365+ sage: from sage.combinat.ordered_tree import OrderedTrees_all, OrderedTrees_size2366+ sage: isinstance(OrderedTrees(2), OrderedTrees)2367+ True2368+ sage: isinstance(OrderedTrees(), OrderedTrees)2369+ True2370+ sage: OrderedTrees(2) is OrderedTrees_size(2)2371+ True2372+ sage: OrderedTrees(5).cardinality()2373+ 142374+ sage: OrderedTrees() is OrderedTrees_all()2375+ True2376+ """2377+ if n is None:2378+ return OrderedTrees_all()2379+ else:2380+ assert (isinstance(n, (Integer, int)) and n >= 0), "n must be a non negative integer"2381+ return OrderedTrees_size(Integer(n))2382+2383+ @cached_method2384+ def leaf(self):2385+ """2386+ Return a leaf tree with ``self`` as parent2387+2388+ EXAMPLES::2389+2390+ sage: OrderedTrees().leaf()2391+ []2392+2393+ TEST::2394+2395+ sage: (OrderedTrees().leaf() is2396+ ... sage.combinat.ordered_tree.OrderedTrees_all().leaf())2397+ True2398+ """2399+ return self([])2400+2401+class OrderedTrees_all(DisjointUnionEnumeratedSets, OrderedTrees):2402+ """2403+ The set of all ordered trees2404+2405+ EXAMPLES::2406+2407+ sage: OT = OrderedTrees(); OT2408+ Ordered trees2409+ sage: OT.cardinality()2410+ +Infinity2411+ """2412+2413+ def __init__(self):2414+ """2415+ TESTS::2416+2417+ sage: from sage.combinat.ordered_tree import OrderedTrees_all2418+ sage: B = OrderedTrees_all()2419+ sage: B.cardinality()2420+ +Infinity2421+2422+ sage: it = iter(B)2423+ sage: (it.next(), it.next(), it.next(), it.next(), it.next())2424+ ([], [[]], [[], []], [[[]]], [[], [], []])2425+ sage: it.next().parent()2426+ Ordered trees2427+ sage: B([])2428+ []2429+2430+ sage: B is OrderedTrees_all()2431+ True2432+ sage: TestSuite(B).run()2433+ """2434+ DisjointUnionEnumeratedSets.__init__(2435+ self, Family(NonNegativeIntegers(), OrderedTrees_size),2436+ facade=True, keepkey=False)2437+2438+ def _repr_(self):2439+ """2440+ TEST::2441+2442+ sage: OrderedTrees() # indirect doctest2443+ Ordered trees2444+ """2445+ return "Ordered trees"2446+2447+ def __contains__(self, x):2448+ """2449+ TESTS::2450+2451+ sage: T = OrderedTrees()2452+ sage: 1 in T2453+ False2454+ sage: T([]) in T2455+ True2456+ """2457+ return isinstance(x, self.element_class)2458+2459+ def unlabelled_trees(self):2460+ """2461+ Returns the set of unlabelled trees associated to ``self``2462+2463+ EXAMPLES::2464+2465+ sage: OrderedTrees().unlabelled_trees()2466+ Ordered trees2467+ """2468+ return self2469+2470+ def labelled_trees(self):2471+ """2472+ Returns the set of unlabelled trees associated to ``self``2473+2474+ EXAMPLES::2475+2476+ sage: OrderedTrees().labelled_trees()2477+ Labelled ordered trees2478+ """2479+ return LabelledOrderedTrees()2480+2481+ def _element_constructor_(self, *args, **keywords):2482+ """2483+ EXAMPLES::2484+2485+ sage: T = OrderedTrees()2486+ sage: T([]) # indirect doctest2487+ []2488+ """2489+ return self.element_class(self, *args, **keywords)2490+2491+ Element = OrderedTree2492+2493+2494+2495+from sage.misc.lazy_attribute import lazy_attribute2496+from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets2497+from combinat import catalan_number2498+from sage.combinat.composition import Compositions2499+from sage.combinat.cartesian_product import CartesianProduct2500+#################################################################2501+# Enumerated set of binary trees of a given size2502+#################################################################2503+class OrderedTrees_size(OrderedTrees):2504+ """2505+ The enumerated sets of binary trees of a given size2506+2507+ EXAMPLES::2508+2509+ sage: S = OrderedTrees(3); S2510+ Ordered trees of size 32511+ sage: S.cardinality()2512+ 22513+ sage: S.list()2514+ [[[], []], [[[]]]]2515+ """2516+ def __init__(self, size):2517+ """2518+ TESTS::2519+2520+ sage: from sage.combinat.ordered_tree import OrderedTrees_size2521+ sage: TestSuite(OrderedTrees_size(0)).run()2522+ sage: for i in range(6): TestSuite(OrderedTrees_size(i)).run()2523+ """2524+ super(OrderedTrees_size, self).__init__(category = FiniteEnumeratedSets())2525+ self._size = size2526+2527+ def _repr_(self):2528+ """2529+ TESTS::2530+2531+ sage: OrderedTrees(3) # indirect doctest2532+ Ordered trees of size 32533+ """2534+ return "Ordered trees of size %s"%(self._size)2535+2536+ def __contains__(self, x):2537+ """2538+ TESTS::2539+2540+ sage: T = OrderedTrees(3)2541+ sage: 1 in T2542+ False2543+ sage: T([[],[]]) in T2544+ True2545+ """2546+ return isinstance(x, self.element_class) and x.node_number() == self._size2547+2548+ def _an_element_(self):2549+ """2550+ TESTS::2551+2552+ sage: OrderedTrees(3).an_element() # indirect doctest2553+ [[], []]2554+ """2555+ if self._size == 0:2556+ raise EmptySetError2557+ return self.first()2558+2559+ def cardinality(self):2560+ """2561+ The cardinality of ``self``2562+2563+ This is a Catalan number2564+2565+ TESTS::2566+2567+ sage: OrderedTrees(0).cardinality()2568+ 02569+ sage: OrderedTrees(1).cardinality()2570+ 12571+ sage: OrderedTrees(6).cardinality()2572+ 422573+ """2574+ if self._size == 0:2575+ return Integer(0)2576+ else:2577+ return catalan_number(self._size-1)2578+2579+ def __iter__(self):2580+ """2581+ A basic generator2582+2583+ .. todo:: could be optimized.2584+2585+ TESTS::2586+2587+ sage: OrderedTrees(0).list()2588+ []2589+ sage: OrderedTrees(1).list()2590+ [[]]2591+ sage: OrderedTrees(2).list()2592+ [[[]]]2593+ sage: OrderedTrees(3).list()2594+ [[[], []], [[[]]]]2595+ sage: OrderedTrees(4).list()2596+ [[[], [], []], [[], [[]]], [[[]], []], [[[], []]], [[[[]]]]]2597+ """2598+ if self._size == 0:2599+ return2600+ else:2601+ for c in Compositions(self._size-1):2602+ for lst in CartesianProduct(*(map(self.__class__, c))):2603+ yield self._element_constructor_(lst)2604+2605+ @lazy_attribute2606+ def _parent_for(self):2607+ """2608+ Return the parent of the element generated by ``self``2609+2610+ TESTS::2611+2612+ sage: OrderedTrees(3)._parent_for2613+ Ordered trees2614+ """2615+ return OrderedTrees_all()2616+2617+ @lazy_attribute2618+ def element_class(self):2619+ """2620+ The class of the element of ``self``2621+2622+ EXAMPLES::2623+2624+ sage: from sage.combinat.ordered_tree import OrderedTrees_size, OrderedTrees_all2625+ sage: S = OrderedTrees_size(3)2626+ sage: S.element_class is OrderedTrees().element_class2627+ True2628+ sage: S.first().__class__ == OrderedTrees_all().first().__class__2629+ True2630+ """2631+ return self._parent_for.element_class2632+2633+ def _element_constructor_(self, *args, **keywords):2634+ """2635+ EXAMPLES::2636+2637+ sage: S = OrderedTrees(0)2638+ sage: S([]) # indirect doctest2639+ Traceback (most recent call last):2640+ ...2641+ ValueError: Wrong number of nodes2642+2643+ sage: S = OrderedTrees(1) # indirect doctest2644+ sage: S([])2645+ []2646+ """2647+ res = self.element_class(self._parent_for, *args, **keywords)2648+ if res.node_number() != self._size:2649+ raise ValueError, "Wrong number of nodes"2650+ return res2651+2652+2653+class LabelledOrderedTree(AbstractLabelledClonableTree, OrderedTree):2654+ """2655+ Labelled ordered trees2656+2657+ A labellel ordered tree is an ordered tree with a label attached at each2658+ node2659+2660+ INPUT:2661+2662+ - ``children`` -- a list or tuple or more generally any iterable2663+ of trees or object convertible to trees2664+ - ``label`` -- any Sage object default to ``None``2665+2666+ EXAMPLES::2667+2668+ sage: x = LabelledOrderedTree([], label = 3); x2669+ 3[]2670+ sage: LabelledOrderedTree([x, x, x], label = 2)2671+ 2[3[], 3[], 3[]]2672+ sage: LabelledOrderedTree((x, x, x), label = 2)2673+ 2[3[], 3[], 3[]]2674+ sage: LabelledOrderedTree([[],[[], []]], label = 3)2675+ 3[None[], None[None[], None[]]]2676+ """2677+ __metaclass__ = ClasscallMetaclass2678+2679+ @staticmethod2680+ def __classcall_private__(cls, *args, **opts):2681+ """2682+ Ensure that trees created by the sets and directly are the same and2683+ that they are instance of :class:`LabelledOrderedTree`2684+2685+ TESTS::2686+2687+ sage: issubclass(LabelledOrderedTrees().element_class, LabelledOrderedTree)2688+ True2689+ sage: t0 = LabelledOrderedTree([[],[[], []]], label = 3)2690+ sage: t0.parent()2691+ Labelled ordered trees2692+ sage: type(t0)2693+ <class 'sage.combinat.ordered_tree.LabelledOrderedTrees_with_category.element_class'>2694+ """2695+ return cls._auto_parent.element_class(cls._auto_parent, *args, **opts)2696+2697+ @lazy_class_attribute2698+ def _auto_parent(cls):2699+ """2700+ The automatic parent of the element of this class2701+2702+ When calling the constructor of an element of this class, one need a2703+ parent. This class attribute specifies which parent is used.2704+2705+ EXAMPLES::2706+2707+ sage: LabelledOrderedTree._auto_parent2708+ Labelled ordered trees2709+ sage: LabelledOrderedTree([], label = 3).parent()2710+ Labelled ordered trees2711+ """2712+ return LabelledOrderedTrees()2713+2714+ _UnLabelled = OrderedTree2715+2716+2717+from sage.rings.infinity import Infinity2718+class LabelledOrderedTrees(UniqueRepresentation, Parent):2719+ """2720+ This is a parent stub to serve as a factory class for trees with various2721+ labels constraints2722+2723+ EXAMPLES::2724+2725+ sage: LOT = LabelledOrderedTrees(); LOT2726+ Labelled ordered trees2727+ sage: x = LOT([], label = 3); x2728+ 3[]2729+ sage: x.parent() is LOT2730+ True2731+ sage: y = LOT([x, x, x], label = 2); y2732+ 2[3[], 3[], 3[]]2733+ sage: y.parent() is LOT2734+ True2735+ """2736+ def __init__(self, category=None):2737+ """2738+ TESTS::2739+2740+ sage: TestSuite(LabelledOrderedTrees()).run()2741+ """2742+ if category is None:2743+ category = Sets()2744+ Parent.__init__(self, category = category)2745+2746+ def _repr_(self):2747+ """2748+ TESTS::2749+2750+ sage: LabelledOrderedTrees() # indirect doctest2751+ Labelled ordered trees2752+ """2753+ return "Labelled ordered trees"2754+2755+ def cardinality(self):2756+ """2757+ Returns the cardinality of `self`2758+2759+ EXAMPLE::2760+2761+ sage: LabelledOrderedTrees().cardinality()2762+ +Infinity2763+ """2764+ return Infinity2765+2766+ def _an_element_(self):2767+ """2768+ Returns a labelled tree2769+2770+ EXAMPLE::2771+2772+ sage: LabelledOrderedTrees().an_element() # indirect doctest2773+ toto[3[], 42[3[], 3[]], 5[None[]]]2774+ """2775+ LT = self._element_constructor_2776+ t = LT([], label = 3)2777+ t1 = LT([t,t], label = 42)2778+ t2 = LT([[]], label = 5)2779+ return LT([t,t1,t2], label = "toto")2780+2781+ def _element_constructor_(self, *args, **keywords):2782+ """2783+ EXAMPLES::2784+2785+ sage: T = LabelledOrderedTrees()2786+ sage: T([], label=2) # indirect doctest2787+ 2[]2788+ """2789+ return self.element_class(self, *args, **keywords)2790+2791+ def unlabelled_trees(self):2792+ """2793+ Returns the set of unlabelled trees associated to ``self``2794+2795+ EXAMPLES::2796+2797+ sage: LabelledOrderedTrees().unlabelled_trees()2798+ Ordered trees2799+ """2800+ return OrderedTrees_all()2801+2802+ def labelled_trees(self):2803+ """2804+ Returns the set of labelled trees associated to ``self``2805+2806+ EXAMPLES::2807+2808+ sage: LabelledOrderedTrees().labelled_trees()2809+ Labelled ordered trees2810+ sage: LOT = LabelledOrderedTrees()2811+ sage: x = LOT([], label = 3)2812+ sage: y = LOT([x, x, x], label = 2)2813+ sage: y.canonical_labelling()2814+ 1[2[], 3[], 4[]]2815+ """2816+ return self2817+2818+ Element = LabelledOrderedTree2819+2820diff --git a/sage/combinat/permutation.py b/sage/combinat/permutation.py2821--- a/sage/combinat/permutation.py2822+++ b/sage/combinat/permutation.py2823@@ -2930,6 +2930,68 @@ class Permutation_class(CombinatorialObj2824"""2825return RSK(self)[1]28262827+ def increasing_tree(self, compare=min):2828+ """2829+ Return the increasing tree associated to ``self``2830+2831+ EXAMPLES::2832+2833+ sage: Permutation([1,4,3,2]).increasing_tree()2834+ 1[., 2[3[4[., .], .], .]]2835+ sage: Permutation([4,1,3,2]).increasing_tree()2836+ 1[4[., .], 2[3[., .], .]]2837+2838+ By passing the option ``compare=max`` one can have the decreasing2839+ tree instead::2840+2841+ sage: Permutation([2,3,4,1]).increasing_tree(max)2842+ 4[3[2[., .], .], 1[., .]]2843+ sage: Permutation([2,3,1,4]).increasing_tree(max)2844+ 4[3[2[., .], 1[., .]], .]2845+ """2846+ from sage.combinat.binary_tree import LabelledBinaryTree as LBT2847+ def rec(perm):2848+ if len(perm) == 0: return LBT(None)2849+ mn = compare(perm)2850+ k = perm.index(mn)2851+ return LBT([rec(perm[:k]), rec(perm[k+1:])], label = mn)2852+ return rec(self)2853+2854+ def binary_search_tree(self, left_to_right=True):2855+ """2856+ Return the binary search tree associated to ``self``2857+2858+ EXAMPLES::2859+2860+ sage: Permutation([1,4,3,2]).binary_search_tree()2861+ 1[., 4[3[2[., .], .], .]]2862+ sage: Permutation([4,1,3,2]).binary_search_tree()2863+ 4[1[., 3[2[., .], .]], .]2864+2865+ By passing the option ``compare=max`` one can have the decreasing2866+ tree instead::2867+2868+ sage: Permutation([1,4,3,2]).binary_search_tree(False)2869+ 2[1[., .], 3[., 4[., .]]]2870+ sage: Permutation([4,1,3,2]).binary_search_tree(False)2871+ 2[1[., .], 3[., 4[., .]]]2872+2873+ TESTS::2874+2875+ sage: Permutation([]).binary_search_tree()2876+ .2877+ """2878+ from sage.combinat.binary_tree import LabelledBinaryTree as LBT2879+ res = LBT(None)2880+ if left_to_right:2881+ gen = self2882+ else:2883+ gen = self[::-1]2884+ for i in gen:2885+ res = res.binary_search_insert(i)2886+ return res2887+2888+2889@combinatorial_map(name='Robinson-Schensted tableau shape')2890def RS_partition(self):2891"""2892diff --git a/sage/misc/all.py b/sage/misc/all.py2893--- a/sage/misc/all.py2894+++ b/sage/misc/all.py2895@@ -160,8 +160,6 @@ from lazy_import import lazy_import28962897from abstract_method import abstract_method28982899-from binary_tree import BinaryTree2900-2901from randstate import seed, set_random_seed, initial_seed, current_randstate29022903from prandom import *2904diff --git a/sage/misc/binary_tree.pyx b/sage/misc/binary_tree.pyx2905--- a/sage/misc/binary_tree.pyx2906+++ b/sage/misc/binary_tree.pyx2907@@ -197,6 +197,7 @@ cdef class BinaryTree:29082909EXAMPLES::29102911+ sage: from sage.misc.binary_tree import BinaryTree2912sage: t = BinaryTree()2913sage: t.insert(1)2914sage: t.insert(0)2915@@ -220,6 +221,7 @@ cdef class BinaryTree:29162917EXAMPLES::29182919+ sage: from sage.misc.binary_tree import BinaryTree2920sage: t = BinaryTree()2921sage: t.insert(3,3)2922sage: t.insert(1,1)2923@@ -261,6 +263,7 @@ cdef class BinaryTree:29242925EXAMPLES::29262927+ sage: from sage.misc.binary_tree import BinaryTree2928sage: t = BinaryTree()2929sage: t.insert(0,Matrix([[0,0],[1,1]]))2930sage: t.insert(0,1)2931@@ -279,6 +282,7 @@ cdef class BinaryTree:29322933EXAMPLES::29342935+ sage: from sage.misc.binary_tree import BinaryTree2936sage: t = BinaryTree()2937sage: t.contains(1)2938False2939@@ -322,6 +326,7 @@ cdef class BinaryTree:29402941EXAMPLES::29422943+ sage: from sage.misc.binary_tree import BinaryTree2944sage: t = BinaryTree()2945sage: t.insert(4,'e')2946sage: t.insert(2,'c')2947@@ -361,6 +366,7 @@ cdef class BinaryTree:29482949EXAMPLES::29502951+ sage: from sage.misc.binary_tree import BinaryTree2952sage: t = BinaryTree()2953sage: t.insert(4,'e')2954sage: t.insert(2,'c')2955@@ -399,6 +405,7 @@ cdef class BinaryTree:29562957EXAMPLES::29582959+ sage: from sage.misc.binary_tree import BinaryTree2960sage: t = BinaryTree()2961sage: t.is_empty()2962True2963diff --git a/sage/structure/list_clone.pyx b/sage/structure/list_clone.pyx2964--- a/sage/structure/list_clone.pyx2965+++ b/sage/structure/list_clone.pyx2966@@ -146,10 +146,9 @@ cdef class ClonableElement(Element):2967"""2968Abstract class for elements with clone protocol29692970- This class is a subclasse of2971- :class:`Element<sage.structure.element.Element>` and implements the2972- "prototype" design pattern (see [Pro]_, [GOF]_). The role of this class2973- is:2974+ This class is a subclass of :class:`Element<sage.structure.element.Element>`2975+ and implements the "prototype" design pattern (see [Pro]_, [GOF]_). The role2976+ of this class is:29772978- to manage copy and mutability and hashing of elements2979- to ensure that at the end of a piece of code an object is restored in a298029812982