Ticket #14498: trac_14498_algorithms_trees_13_07_09_EliX-jbp.patch

File trac_14498_algorithms_trees_13_07_09_EliX-jbp.patch, 73.5 KB (added by elixyre, 6 years ago)
  • sage/combinat/abstract_tree.py

    # HG changeset patch
    # User Jean-Baptiste Priez <jbp@kerios.fr>
    # Date 1373370155 -7200
    # Node ID 7892e4001368e7c253758d994b66c03d80117df3
    # Parent  0c9ceb4e2ae0b7715ce76deafd2c769d1787f4d9
    algorithms for trees and latex output
     -> several traversal algorithms
     -> some methods added for binary heap
    
    diff --git a/sage/combinat/abstract_tree.py b/sage/combinat/abstract_tree.py
    a b incoherent with the data structure. 
    6666from sage.structure.list_clone import ClonableArray
    6767from sage.rings.integer import Integer
    6868from sage.misc.misc_c import prod
     69from sage.misc import lazy_attribute
     70###############################################################################
     71# # use to load tikz in the preamble (one for *view* and one for *notebook*)
     72from sage.misc.latex import latex
     73latex.add_package_to_preamble_if_available("tikz")
     74latex.add_to_mathjax_avoid_list("tikz")
     75###############################################################################
     76
    6977
    7078# Unfortunately Cython forbids multiple inheritance. Therefore, we do not
    7179# inherits from SageObject to be able to inherits from Element or a subclass
    class AbstractTree(object): 
    107115        sage: TestSuite(BinaryTree()).run()
    108116    """
    109117
     118    def pre_order_traversal_iter(self):
     119        """
     120        The depth first pre-order traversal iterator
     121
     122        This method iters each node following the depth first pre-order
     123        traversal algorithm (recursive implementation).
     124
     125        For example on the following binary tree `b`::
     126
     127            |   ___3____      |
     128            |  /        \     |
     129            | 1         _7_   |
     130            |  \       /   \  |
     131            |   2     5     8 |
     132            |        / \      |
     133            |       4   6     |
     134
     135        the ``depth first pre-order traversal algorithm`` explores `b` in the
     136        following order of nodes `3,1,2,7,5,4,6,8`.
     137
     138        The algorithm is::
     139
     140            manipulate the root
     141            then explore each subtrees (by the algorithm)
     142
     143        An other example::
     144
     145            |     __1____ |
     146            |    /  /   / |
     147            |   2  6   8_ |
     148            |   |  |  / / |
     149            |   3_ 7 9 10 |
     150            |  / /        |
     151            | 4 5         |
     152
     153        The algorithm explores this tree in the following order:
     154        `1,2,3,4,5,6,7,8,9,10`.
     155
     156        TESTS::
     157
     158            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).\
     159            ....:     canonical_labelling(); ascii_art([b])
     160            [   ___3____      ]
     161            [  /        \     ]
     162            [ 1         _7_   ]
     163            [  \       /   \  ]
     164            [   2     5     8 ]
     165            [        / \      ]
     166            [       4   6     ]
     167            sage: [n.label() for n in b.pre_order_traversal_iter()]
     168            [3, 1, 2, 7, 5, 4, 6, 8]
     169            sage: t = OrderedTree([[[[],[]]],[[]],[[],[]]]).\
     170            ....:     canonical_labelling(); ascii_art([t])
     171            [     __1____   ]
     172            [    /  /   /   ]
     173            [   2  6   8_   ]
     174            [   |  |  / /   ]
     175            [   3_ 7 9 10   ]
     176            [  / /          ]
     177            [ 4 5           ]
     178            sage: [n.label() for n in t.pre_order_traversal_iter()]
     179            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     180        """
     181        if self.is_empty(): return
     182        yield self
     183        # TODO:: PYTHON 3
     184        # import itertools
     185        # yield from itertools.chain(map(
     186        #     lambda c: c.pre_order_traversal_iter(),
     187        #     self
     188        # ))
     189        for children in self:
     190            for node in children.pre_order_traversal_iter():
     191                yield node
     192
     193    def iterative_pre_order_traversal(self, action=lambda _: None):
     194        """
     195        The depth first pre-order traversal algorithm (iterative
     196        implementation)
     197
     198        INPUT:
     199
     200        - ``action`` -- a specific function which takes a node in input and do
     201        something during the exploration.
     202
     203        (see :meth:`pre_order_traversal_iter
     204        <sage.combinat.abstract_tree.AbstractTree.pre_order_traversal_iter>`
     205        and :meth:`pre_order_traversal
     206        <sage.combinat.abstract_tree.AbstractTree.pre_order_traversal>`)
     207
     208        TESTS::
     209
     210            sage: l = []
     211            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).\
     212            ....:     canonical_labelling(); b
     213            3[1[., 2[., .]], 7[5[4[., .], 6[., .]], 8[., .]]]
     214            sage: b.iterative_pre_order_traversal(
     215            ....:     lambda node: l.append(node.label()))
     216            sage: l
     217            [3, 1, 2, 7, 5, 4, 6, 8]
     218            sage: t = OrderedTree([[[[],[]]],[[]],[[],[]]]).\
     219            ....:     canonical_labelling(); t
     220            1[2[3[4[], 5[]]], 6[7[]], 8[9[], 10[]]]
     221            sage: l = []
     222            sage: t.iterative_pre_order_traversal(
     223            ....:     lambda node: l.append(node.label()))
     224            sage: l
     225            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     226            sage: l = []
     227            sage: BinaryTree().canonical_labelling().\
     228            ....:     pre_order_traversal(lambda node: l.append(node.label()))
     229            sage: l
     230            []
     231            sage: OrderedTree([]).canonical_labelling().\
     232            ....:     iterative_pre_order_traversal(
     233            ....:         lambda node: l.append(node.label()))
     234            sage: l
     235            [1]
     236        """
     237        if self.is_empty(): return
     238        stack = []
     239        stack.append(self)
     240        while len(stack) > 0:
     241            node = stack.pop()
     242            action(node)
     243            for i in range(len(node)):
     244                subtree = node[-i - 1]
     245                if not subtree.is_empty():
     246                    stack.append(subtree)
     247
     248    def pre_order_traversal(self, action=lambda _: None):
     249        """
     250        The depth first pre-order traversal algorithm (recursive
     251        implementation)
     252
     253        INPUT:
     254
     255        - ``action`` -- a specific function which takes a node in input and do
     256        something during the exploration.
     257
     258        For example on the following binary tree `b`::
     259
     260            |   ___3____      |
     261            |  /        \     |
     262            | 1         _7_   |
     263            |  \       /   \  |
     264            |   2     5     8 |
     265            |        / \      |
     266            |       4   6     |
     267
     268        the ``depth first pre-order traversal algorithm`` explores `b` in the
     269        following order of nodes `3,1,2,7,5,4,6,8`.
     270
     271        The algorithm is::
     272
     273            manipulate the root with function `action`
     274            then explore each subtrees (by the algorithm)
     275
     276        An other example::
     277
     278            |     __1____ |
     279            |    /  /   / |
     280            |   2  6   8_ |
     281            |   |  |  / / |
     282            |   3_ 7 9 10 |
     283            |  / /        |
     284            | 4 5         |
     285
     286        The algorithm explores this tree in the following order:
     287        `1,2,3,4,5,6,7,8,9,10`.
     288
     289        (see :meth:`pre_order_traversal_iter
     290        <sage.combinat.abstract_tree.AbstractTree.pre_order_traversal_iter>`
     291        and :meth:`iterative_pre_order_traversal
     292        <sage.combinat.abstract_tree.AbstractTree.iterative_pre_order_traversal>`)
     293
     294        TESTS::
     295
     296            sage: l = []
     297            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).\
     298            ....:     canonical_labelling(); b
     299            3[1[., 2[., .]], 7[5[4[., .], 6[., .]], 8[., .]]]
     300            sage: b.pre_order_traversal(lambda node: l.append(node.label()))
     301            sage: l
     302            [3, 1, 2, 7, 5, 4, 6, 8]
     303            sage: li = []
     304            sage: b.iterative_pre_order_traversal(
     305            ....:     lambda node: li.append(node.label()))
     306            sage: l == li
     307            True
     308            sage: t = OrderedTree([[[[],[]]],[[]],[[],[]]]).\
     309            ....:     canonical_labelling(); t
     310            1[2[3[4[], 5[]]], 6[7[]], 8[9[], 10[]]]
     311            sage: l = []
     312            sage: t.pre_order_traversal(lambda node: l.append(node.label()))
     313            sage: l
     314            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     315            sage: li = []
     316            sage: t.iterative_pre_order_traversal(
     317            ....:     lambda node: li.append(node.label()))
     318            sage: l == li
     319            True
     320            sage: l = []
     321            sage: BinaryTree().canonical_labelling().\
     322            ....:     pre_order_traversal(lambda node: l.append(node.label()))
     323            sage: l
     324            []
     325            sage: OrderedTree([]).canonical_labelling().\
     326            ....:     pre_order_traversal(lambda node: l.append(node.label()))
     327            sage: l
     328            [1]
     329        """
     330        for node in self.pre_order_traversal_iter():
     331            action(node)
     332
     333    def post_order_traversal_iter(self):
     334        """
     335        The depth first post-order traversal iterator
     336
     337        This method iters each node following the depth first post-order
     338        traversal algorithm (recursive implementation).
     339
     340        For example on the following binary tree `b`::
     341
     342            |   ___3____      |
     343            |  /        \     |
     344            | 1         _7_   |
     345            |  \       /   \  |
     346            |   2     5     8 |
     347            |        / \      |
     348            |       4   6     |
     349
     350        the ``depth first post-order traversal algorithm`` explores `b` in the
     351        following order of nodes `2,1,4,6,5,8,7,3`.
     352
     353        The algorithm is::
     354
     355            explore each subtrees (by the algorithm)
     356            then manipulate the root with function `action`
     357
     358        Another example::
     359
     360            |     __1____ |
     361            |    /  /   / |
     362            |   2  6   8_ |
     363            |   |  |  / / |
     364            |   3_ 7 9 10 |
     365            |  / /        |
     366            | 4 5         |
     367
     368        The algorithm explorer this tree in the following order:
     369        `4,5,3,2,7,6,9,10,8,1`.
     370
     371        TESTS::
     372
     373            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).\
     374            ....:     canonical_labelling(); ascii_art([b])
     375            [   ___3____      ]
     376            [  /        \     ]
     377            [ 1         _7_   ]
     378            [  \       /   \  ]
     379            [   2     5     8 ]
     380            [        / \      ]
     381            [       4   6     ]
     382            sage: [node.label() for node in b.post_order_traversal_iter()]
     383            [2, 1, 4, 6, 5, 8, 7, 3]
     384            sage: t = OrderedTree([[[[],[]]],[[]],[[],[]]]).\
     385            ....:     canonical_labelling(); ascii_art([t])
     386            [     __1____   ]
     387            [    /  /   /   ]
     388            [   2  6   8_   ]
     389            [   |  |  / /   ]
     390            [   3_ 7 9 10   ]
     391            [  / /          ]
     392            [ 4 5           ]
     393            sage: [node.label() for node in t.post_order_traversal_iter()]
     394            [4, 5, 3, 2, 7, 6, 9, 10, 8, 1]
     395            sage: [node.label() for node in BinaryTree().canonical_labelling().\
     396            ....:     post_order_traversal_iter()]
     397            []
     398            sage: [node.label() for node in OrderedTree([]).\
     399            ....:     canonical_labelling().post_order_traversal_iter()]
     400            [1]
     401        """
     402        if self.is_empty(): return
     403        # TODO:: PYTHON 3
     404        # import itertools
     405        # yield from itertools.chain(map(
     406        #     lambda c: c.post_order_traversal_iter(),
     407        #     self
     408        # ))
     409        for children in self:
     410            for node in children.post_order_traversal_iter():
     411                yield node
     412        yield self
     413
     414    def post_order_traversal(self, action=lambda node: None):
     415        """
     416        The depth first post-order traversal algorithm (recursive
     417        implementation)
     418
     419        INPUT:
     420
     421        - ``action`` -- a specific function which takes a node in input and do
     422        something during the exploration.
     423
     424        (see :meth:`post_order_traversal_iter
     425        <sage.combinat.abstract_tree.AbstractTree.post_order_traversal_iter>`
     426        and :meth:`iterative_post_order_traversal
     427        <sage.combinat.abstract_tree.AbstractTree.iterative_post_order_traversal>`)
     428
     429        TESTS::
     430
     431            sage: l = []
     432            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).\
     433            ....:     canonical_labelling(); b
     434            3[1[., 2[., .]], 7[5[4[., .], 6[., .]], 8[., .]]]
     435            sage: b.post_order_traversal(lambda node: l.append(node.label()))
     436            sage: l
     437            [2, 1, 4, 6, 5, 8, 7, 3]
     438            sage: t = OrderedTree([[[[],[]]],[[]],[[],[]]]).\
     439            ....:     canonical_labelling(); t
     440            1[2[3[4[], 5[]]], 6[7[]], 8[9[], 10[]]]
     441            sage: l = []
     442            sage: t.post_order_traversal(lambda node: l.append(node.label()))
     443            sage: l
     444            [4, 5, 3, 2, 7, 6, 9, 10, 8, 1]
     445            sage: l = []
     446            sage: BinaryTree().canonical_labelling().\
     447            ....:     post_order_traversal(lambda node: l.append(node.label()))
     448            sage: l
     449            []
     450            sage: OrderedTree([]).canonical_labelling().\
     451            ....:     post_order_traversal(lambda node: l.append(node.label()))
     452            sage: l
     453            [1]
     454        """
     455        for node in self.post_order_traversal_iter():
     456            action(node)
     457
     458    def iterative_post_order_traversal(self, action=lambda node: None):
     459        """
     460        The depth first post-order traversal algorithm (iterative
     461        implementation)
     462
     463        INPUT:
     464
     465        - ``action`` -- a specific function which takes a node in input and do
     466        something during the exploration.
     467
     468        (see :meth:`post_order_traversal_iter
     469        <sage.combinat.abstract_tree.AbstractTree.post_order_traversal_iter>`)
     470
     471        TESTS::
     472
     473            sage: l = []
     474            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).\
     475            ....:     canonical_labelling(); b
     476            3[1[., 2[., .]], 7[5[4[., .], 6[., .]], 8[., .]]]
     477            sage: b.iterative_post_order_traversal(
     478            ....:     lambda node: l.append(node.label()))
     479            sage: l
     480            [8, 6, 4, 5, 7, 2, 1, 3]
     481            sage: t = OrderedTree([[[[],[]]],[[]],[[],[]]]).\
     482            ....:     canonical_labelling(); t
     483            1[2[3[4[], 5[]]], 6[7[]], 8[9[], 10[]]]
     484            sage: l = []
     485            sage: t.iterative_post_order_traversal(
     486            ....:     lambda node: l.append(node.label()))
     487            sage: l
     488            [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
     489            sage: l = []
     490            sage: BinaryTree().canonical_labelling().\
     491            ....:     iterative_post_order_traversal(
     492            ....:         lambda node: l.append(node.label()))
     493            sage: l
     494            []
     495            sage: OrderedTree([]).canonical_labelling().\
     496            ....:     iterative_post_order_traversal(
     497            ....:         lambda node: l.append(node.label()))
     498            sage: l
     499            [1]
     500        """
     501        if self.is_empty(): return
     502        stack = [self]
     503        mark = []
     504        while len(stack) > 0:
     505            node = stack[-1]
     506            if node in mark:
     507                stack.pop()
     508                action(node)
     509            else:
     510                mark.append(node)
     511                stack.extend(filter(lambda n: not n.is_empty(), node))
     512
     513    def breadth_first_order_traversal(self, action=lambda node: None):
     514        """
     515        The breadth first order traversal algorithm.
     516
     517        INPUT:
     518
     519        - ``action`` -- a specific function which takes a node in input and do
     520        something during the exploration.
     521
     522        For example on the following binary tree `b`::
     523
     524            |   ___3____      |
     525            |  /        \     |
     526            | 1         _7_   |
     527            |  \       /   \  |
     528            |   2     5     8 |
     529            |        / \      |
     530            |       4   6     |
     531
     532        the ``breadth first order traversal algorithm`` explores `b` in the
     533        following order of nodes `3,1,7,2,5,8,4,6`.
     534
     535        The algorithm is::
     536
     537            queue <- ( root )
     538            while the queue is not empty:
     539                node <- pop( queue )
     540                manipulate the node
     541                append in the queue all subtrees of the node
     542
     543        TESTS::
     544
     545            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).\
     546            ....:     canonical_labelling()
     547            sage: l = []
     548            sage: b.breadth_first_order_traversal(
     549            ....:     lambda node: l.append(node.label()))
     550            sage: l
     551            [3, 1, 7, 2, 5, 8, 4, 6]
     552            sage: t = OrderedTree([[[[],[]]],[[]],[[],[]]]).\
     553            ....:     canonical_labelling(); t
     554            1[2[3[4[], 5[]]], 6[7[]], 8[9[], 10[]]]
     555            sage: l = []
     556            sage: t.breadth_first_order_traversal(
     557            ....:     lambda node: l.append(node.label()))
     558            sage: l
     559            [1, 2, 6, 8, 3, 7, 9, 10, 4, 5]
     560            sage: l = []
     561            sage: BinaryTree().canonical_labelling().\
     562            ....:     breadth_first_order_traversal(
     563            ....:         lambda node: l.append(node.label()))
     564            sage: l
     565            []
     566            sage: OrderedTree([]).canonical_labelling().\
     567            ....:     breadth_first_order_traversal(
     568            ....:         lambda node: l.append(node.label()))
     569            sage: l
     570            [1]
     571        """
     572        if self.is_empty(): return
     573        queue = []
     574        queue.append(self)
     575        while len(queue) > 0:
     576            node = queue.pop()
     577            action(node)
     578            for subtree in node:
     579                if not subtree.is_empty():
     580                    queue.insert(0, subtree)
     581
    110582    def subtrees(self):
    111583        """
    112584        Returns a generator for all subtrees of ``self``
    class AbstractTree(object): 
    134606            sage: bt.node_number() == len(list(bt.subtrees()))
    135607            True
    136608        """
    137         if not self.is_empty():
    138             yield self
    139             for i in self:
    140                 for t in i.subtrees():
    141                     yield t
     609        return self.pre_order_traversal_iter()
     610#         if not self.is_empty():
     611#             yield self
     612#             for i in self:
     613#                 for t in i.subtrees():
     614#                     yield t
    142615
    143616    def paths(self):
    144617        """
    class AbstractTree(object): 
    413886        if nb <= 1:
    414887            return 1
    415888        else:
    416             return nb*prod(s.tree_factorial() for s in self)
    417 
    418     latex_unit_length   = "4mm"
    419     latex_node_diameter = "0.5"
    420     latex_root_diameter = "0.7"
     889            return nb * prod(s.tree_factorial() for s in self)
    421890
    422891    def _latex_(self):
    423         """
    424         Returns a LaTeX version of ``self``
    425 
    426         EXAMPLES::
    427 
    428             sage: print(OrderedTree([[],[]])._latex_())
    429             \vcenter{\hbox{{\setlength\unitlength{4mm}
    430             \begin{picture}(4,3)
    431             \put(1,1){\circle*{0.5}}
    432             \put(2,2){\circle*{0.5}}
    433             \put(3,1){\circle*{0.5}}
    434             \put(2,2){\line(-1,-1){1}}
    435             \put(2,2){\line(1,-1){1}}
    436             \put(2,2){\circle*{0.7}}
    437             \end{picture}}}}
     892        '''
     893        Nice output which can be easily modified
    438894
    439895        TESTS::
    440896
    441             sage: OrderedTree([])._latex_()
    442             '\\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}}}}'
    443             sage: OrderedTree([[]])._latex_()
    444             '\\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}}}}'
    445             sage: OrderedTree([[], [[], [[], []], [[], []]], [[], []]])._latex_()
    446             '\\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}}}}'
    447         """
    448         from sage.misc.latex import latex
    449         drawing = [""] # allows modification of  in rec...
    450         x = [1]        # allows modification of x[0] in rec...
    451         max_label_width = [0] # allows modification of x[0] in rec...
    452         maxy = self.depth()
     897            sage: latex(BinaryTree([[[],[]],[[],None]]))
     898            { \newcommand{\nodea}{\node[draw,circle] (a) {$$}
     899            ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$$}
     900            ;}\newcommand{\nodec}{\node[draw,circle] (c) {$$}
     901            ;}\newcommand{\noded}{\node[draw,circle] (d) {$$}
     902            ;}\newcommand{\nodee}{\node[draw,circle] (e) {$$}
     903            ;}\newcommand{\nodef}{\node[draw,circle] (f) {$$}
     904            ;}\begin{tikzpicture}[auto]
     905            \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     906                     \&         \&         \& \nodea  \&         \&         \&         \\
     907                     \& \nodeb  \&         \&         \&         \& \nodee  \&         \\
     908             \nodec  \&         \& \noded  \&         \& \nodef  \&         \&         \\
     909            };
     910            <BLANKLINE>
     911            \path[ultra thick, red] (b) edge (c) edge (d)
     912                (e) edge (f)
     913                (a) edge (b) edge (e);
     914            \end{tikzpicture}}
     915        '''
     916        # latex environnement : TikZ
     917        begin_env = "\\begin{tikzpicture}[auto]\n"
     918        end_env = "\\end{tikzpicture}"
     919        # it uses matrix trick to place each node
     920        matrix_begin = "\\matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{\n"
     921        matrix_end = "\\\\\n};\n"
     922        # a basic path to each edges
     923        path_begin = "\\path[ultra thick, red] "
     924        path_end = ";\n"
     925        # to make a pretty output, it creates one LaTeX command for
     926        # each node
     927        cmd = "\\node"
     928        new_cmd1 = "\\newcommand{" + cmd
     929        new_cmd2 = "}{\\node[draw,circle] ("
     930        new_cmd3 = ") {$"
     931        new_cmd4 = "$}\n;}"
     932        # some variables to simplify code
     933        sep = "\\&"
     934        space = " "*9
     935        sepspace = sep + space
     936        spacesep = space + sep
     937        node_to_str = lambda node: " " + node + " " * (len(space) - 1 - len(node))
     938        # # TODO:: modify how to create nodes --> new_cmd : \\node[...] in create_node
     939        num = [0]
    453940
    454         def rec(t, y):
    455             """
    456             Draw the subtree t on the drawing, below y (included) and to
    457             the right of x[0] (included). Update x[0]. Returns the horizontal
    458             position of the root
    459             """
    460             if t.node_number() == 0 : return -1
    461             n = len(t)
    462             posChild = [rec(t[i], y+1) for i in range(n // 2)]
    463             i = n // 2
    464             if n % 2 == 1:
    465                 xc = rec(t[i], y+1)
    466                 posChild.append(xc)
    467                 i += 1
     941        def resolve(self):
     942            nodes = []; matrix = []; edges = []
     943
     944            def create_node(self):
     945                '''
     946                create a name (infixe reading)
     947                 -> ex: b
     948                create a new command:
     949                 -> ex: \newcommand{\nodeb}{\node[draw,circle] (b) {$$};
     950                return the name and the command to build:
     951                  . the matrix
     952                  . and the edges
     953                '''
     954                name = reduce(
     955                    lambda x, y: x + y,
     956                    map(
     957                        lambda x: chr(ord(x) + 49),
     958                        list(str(num[0]))),
     959                    "")
     960                node = cmd + name
     961                nodes.append((name,
     962                    (str(self.label()) if hasattr(self, "label") else ""))
     963                )
     964                num[0] += 1
     965                return node, name
     966
     967            def empty_tree():
     968                '''
     969                TESTS::
     970
     971                    sage: t = BinaryTree()
     972                    sage: print latex(t)
     973                    { \begin{tikzpicture}[auto]
     974                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     975                             \\
     976                    };
     977                    \end{tikzpicture}}
     978                '''
     979                matrix.append(space)
     980
     981            def one_node_tree(self):
     982                '''
     983                TESTS::
     984
     985                    sage: t = BinaryTree([]); print latex(t)
     986                    { \newcommand{\nodea}{\node[draw,circle] (a) {$$}
     987                    ;}\begin{tikzpicture}[auto]
     988                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     989                     \nodea  \\
     990                    };
     991                    \end{tikzpicture}}
     992                    sage: t = OrderedTree([]); print latex(t)
     993                    { \newcommand{\nodea}{\node[draw,circle] (a) {$$}
     994                    ;}\begin{tikzpicture}[auto]
     995                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     996                     \nodea  \\
     997                    };
     998                    \end{tikzpicture}}
     999                '''
     1000                node, _ = create_node(self)
     1001                matrix.append(node_to_str(node))
     1002
     1003            def concat_matrix(mat, mat2):
     1004                lmat = len(mat); lmat2 = len(mat2)
     1005                for i in range(max(lmat, lmat2)):
     1006                    # mat[i] --> n & n & ...
     1007                    # mat2[i] -> n' & n' & ...
     1008                    # ==> n & n & ... & n' & n' & ...
     1009                    try:
     1010                        mat[i] += sep + mat2[i]
     1011                    except:
     1012                        if i >= lmat:
     1013                            if i != 0:
     1014                                # mat[i] doesn't exist but
     1015                                # mat[0] has k "&"
     1016                                # mat2[i] -> n' & n' & ...
     1017                                # ==> (_ &)*k+1 n' & n' & ...
     1018                                nb_of_and = mat[0].count(sep) - mat2[0].count(sep)
     1019                                mat.append(spacesep * (nb_of_and) + mat2[i])
     1020                            else:
     1021                                # mat is empty
     1022                                # mat2[i] -> n' & n' & ...
     1023                                # ==> mat2
     1024                                mat.extend(mat2)
     1025                                return
     1026                        else:
     1027                            # mat[i] -> n & n & ...
     1028                            # mat2[i] doesn't exist but mat2[0] exists
     1029                            # # and has k "&"
     1030                            # NOTE:: i != 0 because that is a no-empty subtree.
     1031                            # ==> n & n & ... (& _)*k+1
     1032                            nb_of_and = mat2[0].count(sep)
     1033                            mat[i] += sepspace * (nb_of_and + 1)
     1034
     1035            def tmp(subtree, edge, nodes, edges, matrix):
     1036                if not subtree.is_empty():
     1037                    # # create representation of the subtree
     1038                    nodes_st, matrix_st, edges_st = resolve(subtree)
     1039                    # # add its nodes to the "global" nodes set
     1040                    nodes.extend(nodes_st)
     1041                    # # create a new edge between the root and the subtree
     1042                    edge.append(nodes_st[0][0])
     1043                    # # add the subtree edges to the "global" edges set
     1044                    edges.extend(edges_st)
     1045                    # # build a new matrix by concatenation
     1046                    concat_matrix(matrix, matrix_st)
     1047                else:
     1048                    concat_matrix(matrix, [space])
     1049
     1050            def pair_nodes_tree(self, nodes, edges, matrix):
     1051                """
     1052                TESTS::
     1053
     1054                    sage: t = OrderedTree([[[],[]],[[],[]]]).\
     1055                    ....:     canonical_labelling(); print latex(t)
     1056                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
     1057                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
     1058                    ;}\newcommand{\nodec}{\node[draw,circle] (c) {$3$}
     1059                    ;}\newcommand{\noded}{\node[draw,circle] (d) {$4$}
     1060                    ;}\newcommand{\nodee}{\node[draw,circle] (e) {$5$}
     1061                    ;}\newcommand{\nodef}{\node[draw,circle] (f) {$6$}
     1062                    ;}\newcommand{\nodeg}{\node[draw,circle] (g) {$7$}
     1063                    ;}\begin{tikzpicture}[auto]
     1064                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     1065                             \&         \&         \& \nodea  \&         \&         \&         \\
     1066                             \& \nodeb  \&         \&         \&         \& \nodee  \&         \\
     1067                     \nodec  \&         \& \noded  \&         \& \nodef  \&         \& \nodeg  \\
     1068                    };
     1069                    <BLANKLINE>
     1070                    \path[ultra thick, red] (b) edge (c) edge (d)
     1071                        (e) edge (f) edge (g)
     1072                        (a) edge (b) edge (e);
     1073                    \end{tikzpicture}}
     1074                    sage: t = BinaryTree([[],[[],[]]]); print latex(t)
     1075                    { \newcommand{\nodea}{\node[draw,circle] (a) {$$}
     1076                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$$}
     1077                    ;}\newcommand{\nodec}{\node[draw,circle] (c) {$$}
     1078                    ;}\newcommand{\noded}{\node[draw,circle] (d) {$$}
     1079                    ;}\newcommand{\nodee}{\node[draw,circle] (e) {$$}
     1080                    ;}\begin{tikzpicture}[auto]
     1081                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     1082                             \& \nodea  \&         \&         \&         \\
     1083                     \nodeb  \&         \&         \& \nodec  \&         \\
     1084                             \&         \& \noded  \&         \& \nodee  \\
     1085                    };
     1086                    <BLANKLINE>
     1087                    \path[ultra thick, red] (c) edge (d) edge (e)
     1088                        (a) edge (b) edge (c);
     1089                    \end{tikzpicture}}
     1090                """
     1091                # build all subtree matrices.
     1092                node, name = create_node(self)
     1093                edge = [name]
     1094                split = int(len(self) / 2)
     1095                # the left part
     1096                for i in range(split):
     1097                    tmp(self[i], edge, nodes, edges, matrix)
     1098                # # prepare the root line
     1099                nb_of_and = matrix[0].count(sep)
     1100                # the middle
     1101                for i in range(len(matrix)):
     1102                    matrix[i] += sepspace
     1103                # the right part
     1104                for i in range(split, len(self)):
     1105                    tmp(self[i], edge, nodes, edges, matrix)
     1106
     1107                # # create the root line
     1108                root_line = (spacesep * (nb_of_and + 1) + node_to_str(node) +
     1109                    sepspace * (matrix[0].count(sep) - nb_of_and - 1))
     1110                matrix.insert(0, root_line)
     1111                # add edges from the root
     1112                edges.append(edge)
     1113
     1114            def odd_nodes_tree(self, nodes, edges, matrix):
     1115                '''
     1116                TESTS::
     1117
     1118                    sage: t = OrderedTree([[]]).canonical_labelling()
     1119                    sage: print latex(t)
     1120                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
     1121                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
     1122                    ;}\begin{tikzpicture}[auto]
     1123                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     1124                     \nodea  \\
     1125                     \nodeb  \\
     1126                    };
     1127                    <BLANKLINE>
     1128                    \path[ultra thick, red] (a) edge (b);
     1129                    \end{tikzpicture}}
     1130                    sage: t = OrderedTree([[[],[]]]).canonical_labelling(); print latex(t)
     1131                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
     1132                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
     1133                    ;}\newcommand{\nodec}{\node[draw,circle] (c) {$3$}
     1134                    ;}\newcommand{\noded}{\node[draw,circle] (d) {$4$}
     1135                    ;}\begin{tikzpicture}[auto]
     1136                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     1137                             \& \nodea  \&         \\
     1138                             \& \nodeb  \&         \\
     1139                     \nodec  \&         \& \noded  \\
     1140                    };
     1141                    <BLANKLINE>
     1142                    \path[ultra thick, red] (b) edge (c) edge (d)
     1143                        (a) edge (b);
     1144                    \end{tikzpicture}}
     1145                    sage: t = OrderedTree([[[],[],[]]]).canonical_labelling(); print latex(t)
     1146                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
     1147                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
     1148                    ;}\newcommand{\nodec}{\node[draw,circle] (c) {$3$}
     1149                    ;}\newcommand{\noded}{\node[draw,circle] (d) {$4$}
     1150                    ;}\newcommand{\nodee}{\node[draw,circle] (e) {$5$}
     1151                    ;}\begin{tikzpicture}[auto]
     1152                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     1153                             \& \nodea  \&         \\
     1154                             \& \nodeb  \&         \\
     1155                     \nodec  \& \noded  \& \nodee  \\
     1156                    };
     1157                    <BLANKLINE>
     1158                    \path[ultra thick, red] (b) edge (c) edge (d) edge (e)
     1159                        (a) edge (b);
     1160                    \end{tikzpicture}}
     1161                    sage: t = OrderedTree([[[],[],[]],[],[]]).canonical_labelling(); print latex(t)
     1162                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
     1163                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
     1164                    ;}\newcommand{\nodec}{\node[draw,circle] (c) {$3$}
     1165                    ;}\newcommand{\noded}{\node[draw,circle] (d) {$4$}
     1166                    ;}\newcommand{\nodee}{\node[draw,circle] (e) {$5$}
     1167                    ;}\newcommand{\nodef}{\node[draw,circle] (f) {$6$}
     1168                    ;}\newcommand{\nodeg}{\node[draw,circle] (g) {$7$}
     1169                    ;}\begin{tikzpicture}[auto]
     1170                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     1171                             \&         \&         \& \nodea  \&         \\
     1172                             \& \nodeb  \&         \& \nodef  \& \nodeg  \\
     1173                     \nodec  \& \noded  \& \nodee  \&         \&         \\
     1174                    };
     1175                    <BLANKLINE>
     1176                    \path[ultra thick, red] (b) edge (c) edge (d) edge (e)
     1177                        (a) edge (b) edge (f) edge (g);
     1178                    \end{tikzpicture}}
     1179                '''
     1180                # build all subtree matrices.
     1181                node, name = create_node(self)
     1182                edge = [name]
     1183                split = int(len(self) / 2)
     1184                # the left part
     1185                for i in range(split):
     1186                    tmp(self[i], edge, nodes, edges, matrix)
     1187                # # prepare the root line
     1188                if len(matrix) != 0:
     1189                    nb_of_and = matrix[0].count(sep)
     1190                    sizetmp = len(matrix[0])
     1191                else:
     1192                    nb_of_and = 0
     1193                    sizetmp = 0
     1194                # the middle
     1195                tmp(self[split], edge, nodes, edges, matrix)
     1196                nb_of_and += matrix[0][sizetmp:].split("node")[0].count(sep)
     1197
     1198                # the right part
     1199                for i in range(split + 1, len(self)):
     1200                    tmp(self[i], edge, nodes, edges, matrix)
     1201
     1202                # # create the root line
     1203                root_line = (spacesep * (nb_of_and) + node_to_str(node) +
     1204                    sepspace * (matrix[0].count(sep) - nb_of_and))
     1205                matrix.insert(0, root_line)
     1206                # add edges from the root
     1207                edges.append(edge)
     1208            if self.is_empty():
     1209                empty_tree()
     1210            elif len(self) == 0 or all(subtree.is_empty()
     1211                    for subtree in self):
     1212                one_node_tree(self)
     1213            elif len(self) % 2 == 0:
     1214                pair_nodes_tree(self, nodes, edges, matrix)
    4681215            else:
    469                 xc = x[0]
    470                 x[0] +=1
    471             drawing[0] = drawing[0] + "\\put(%s,%s){\\circle*{%s}}\n"%(
    472                 xc, maxy-y, self.latex_node_diameter)
    473             try:
    474                 lbl = t.label()
    475             except AttributeError:
    476                 pass
    477             else:
    478                 max_label_width[0] = 1 # TODO find a better heuristic
    479                 drawing[0] = drawing[0] + "\\put(%s,%s){$\scriptstyle %s$}"%(
    480                     xc+0.3, maxy-y-0.3, latex(lbl))
    481             posChild += [rec(t[j], y+1) for j in range(i, n)]
    482             for i in range(n):
    483                 if posChild[i] != -1:
    484                     drawing[0] = (drawing[0] +
    485                         "\\put(%s,%s){\\line(%s,-1){%s}}\n"%(
    486                             xc, maxy-y, posChild[i]-xc,
    487                             max(abs(posChild[i]-xc), 1)))
    488             return xc
     1216                odd_nodes_tree(self, nodes, edges, matrix)
     1217            return nodes, matrix, edges
    4891218
    490         res = rec(self, 0)
    491         drawing[0] = drawing[0] + "\\put(%s,%s){\\circle*{%s}}\n"%(
    492             res, maxy, self.latex_root_diameter)
    493         return "\\vcenter{\hbox{{\setlength\unitlength{%s}\n\\begin{picture}(%s,%s)\n%s\\end{picture}}}}"%(
    494             self.latex_unit_length,
    495             x[0] + max_label_width[0],
    496             maxy + 1,
    497             drawing[0])
     1219        nodes, matrix, edges = resolve(self)
     1220
     1221        def make_cmd(nodes):
     1222            cmds = []
     1223            for name, label in nodes:
     1224                cmds.append(new_cmd1 + name + new_cmd2 +
     1225                    name + new_cmd3 +
     1226                    label + new_cmd4)
     1227            return cmds
     1228
     1229        def make_edges(edges):
     1230            all_paths = []
     1231            for edge in edges:
     1232                path = "(" + edge[0] + ")"
     1233                for i in range(1, len(edge)):
     1234                    path += " edge (%s)" % edge[i]
     1235                all_paths.append(path)
     1236            return all_paths
     1237        return ("{ " +
     1238            "".join(make_cmd(nodes)) +
     1239            begin_env +
     1240                (matrix_begin +
     1241                    "\\\\ \n".join(matrix) +
     1242                matrix_end +
     1243                ("\n" +
     1244                path_begin +
     1245                    "\n\t".join(make_edges(edges)) +
     1246                path_end if len(edges) > 0 else "")
     1247                if len(matrix) > 0 else "") +
     1248            end_env +
     1249            "}")
     1250
    4981251
    4991252class AbstractClonableTree(AbstractTree):
    5001253    """
  • sage/combinat/binary_tree.py

    diff --git a/sage/combinat/binary_tree.py b/sage/combinat/binary_tree.py
    a b objects. 
    1111**AUTHORS:**
    1212
    1313- Florent Hivert (2010-2011): initial implementation.
     14
     15References
     16----------
     17
     18.. [LodayRonco] Hopf algebra of the planar binary trees,
     19    Jean-Louis Loday and
     20    María O. Ronco
     21   
     22.. [HNT05] The algebra of binary search trees,
     23    Florent Hivert,
     24    Jean-Christophe Novelli and
     25    Jean-Yves Thibon
    1426"""
    1527#*****************************************************************************
    1628#       Copyright (C) 2010 Florent Hivert <Florent.Hivert@univ-rouen.fr>,
    class BinaryTree(AbstractClonableTree, C 
    10641076                if tr[i]:
    10651077                    add_leaf_rec(tr[i])
    10661078                else:
    10671079                    res.append(1-i)
    10681080        add_leaf_rec(self)
    10691081        return res[1:-1]
     1082
     1083    def in_order_traversal_iter(self):
     1084        """
     1085        The depth first infix-order traversal iterator.
     1086
     1087        This method iters each node following the infix order traversal
     1088        algorithm.
     1089
     1090        For example on the following binary tree `T` where we denote leafs by
     1091        `a,b,c...` and nodes by `1,2,3...`::
     1092
     1093            |     ____3____          |
     1094            |    /         \         |
     1095            |   1          __7__     |
     1096            |  / \        /     \    |
     1097            | a   2      _5_     8   |
     1098            |    / \    /   \   / \  |
     1099            |   b   c  4     6 h   i |
     1100            |         / \   / \      |
     1101            |        d   e f   g     |
     1102
     1103        the ``depth first infixe-order traversal algorithm`` explores `T` in
     1104        the following order of nodes `a,1,b,2,c,3,d,4,e,5,f,6,g,7,h,8,i`.
     1105
     1106        The algorithm::
     1107
     1108            explore the left subtree
     1109            manipulate the root with function `node_action` if the root is
     1110                a node and with function `leaf_action` if it is a leaf
     1111            explore the right subtree
     1112
     1113        TESTS::
     1114
     1115            sage: b = BinaryTree([[],[[],[]]]); ascii_art([b])
     1116            [   _o_     ]
     1117            [  /   \    ]
     1118            [ o     o   ]
     1119            [      / \  ]
     1120            [     o   o ]
     1121            sage: ascii_art(list(b.in_order_traversal_iter()))
     1122            [                                       ]
     1123            [ , o, ,   _o_        o      o      o   ]
     1124            [         /   \             / \         ]
     1125            [        o     o           o   o        ]
     1126            [             / \                       ]
     1127            [            o   o, ,  , ,      , ,  ,  ]
     1128            sage: ascii_art(filter(lambda node: node.label() is not None,
     1129            ....:     b.canonical_labelling().in_order_traversal_iter()))
     1130            [                           ]
     1131            [ 1,   _2_      3    4    5 ]
     1132            [     /   \         / \     ]
     1133            [    1     4       3   5    ]
     1134            [         / \               ]
     1135            [        3   5,  ,      ,   ]
     1136        """
     1137        if self.is_empty():
     1138            yield self
     1139            return
     1140        # TODO:: PYTHON 3
     1141        # yield from self[0].in_order_traversal_iter()
     1142        for left_subtree in self[0].in_order_traversal_iter():
     1143            yield left_subtree
     1144        yield self
     1145        # TODO:: PYTHON 3
     1146        # yield from self[1].in_order_traversal_iter()
     1147        for right_subtree in self[1].in_order_traversal_iter():
     1148            yield right_subtree
     1149
     1150    def in_order_traversal(self,
     1151            node_action=lambda _: None,
     1152            leaf_action=lambda _: None):
     1153        r"""
     1154        The depth first infix-order traversal algorithm.
     1155
     1156        (see :meth:`in_order_traversal_iter
     1157        <sage.combinat.binary_tree.BinaryTree.in_order_traversal_iter>`
     1158
     1159        INPUT:
     1160
     1161        - ``node_action`` -- a specific function which takes a node in input
     1162        and do something during the exploration.
     1163        - ``leaf_action`` -- a specific function which takes a leaf in input
     1164        and do something during the exploration.
     1165
     1166        TESTS::
     1167
     1168            sage: nb_leaf = 0
     1169            sage: def l_action(_):
     1170            ....:    global nb_leaf
     1171            ....:    nb_leaf += 1
     1172            sage: nb_node = 0
     1173            sage: def n_action(_):
     1174            ....:    global nb_node
     1175            ....:    nb_node += 1
     1176            sage: BinaryTree().in_order_traversal(n_action, l_action)
     1177            sage: nb_leaf, nb_node
     1178            (1, 0)
     1179            sage: nb_leaf, nb_node = 0, 0
     1180            sage: b = BinaryTree([[],[[],[]]]); b
     1181            [[., .], [[., .], [., .]]]
     1182            sage: b.in_order_traversal(n_action, l_action)
     1183            sage: nb_leaf, nb_node
     1184            (6, 5)
     1185            sage: nb_leaf, nb_node = 0, 0
     1186            sage: b = b.canonical_labelling()
     1187            sage: b.in_order_traversal(n_action, l_action)
     1188            sage: nb_leaf, nb_node
     1189            (6, 5)
     1190            sage: l = []
     1191            sage: b.in_order_traversal(lambda node: l.append( node.label() ))
     1192            sage: l
     1193            [1, 2, 3, 4, 5]
     1194            sage: leaf = 'a'
     1195            sage: l = []
     1196            sage: def l_action(_):
     1197            ....:    global leaf, l
     1198            ....:    l.append(leaf)
     1199            ....:    leaf = chr( ord(leaf)+1 )
     1200            sage: n_action = lambda node: l.append( node.label() )
     1201            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).\
     1202            ....:     canonical_labelling()
     1203            sage: b.in_order_traversal(n_action, l_action)
     1204            sage: l
     1205            ['a', 1, 'b', 2, 'c', 3, 'd', 4, 'e', 5, 'f', 6, 'g', 7, 'h', 8,
     1206             'i']
     1207        """
     1208        for node in self.in_order_traversal_iter():
     1209            if node.is_empty():
     1210                leaf_action(node)
     1211            else:
     1212                node_action(node)
     1213
     1214    def tamari_greater(self):
     1215        """
     1216        The list of all trees greater than ''self''.
     1217        This is the transitive ideal of its successors.
     1218
     1219        The tree::
     1220
     1221            |     __o__   |
     1222            |    /     \  |
     1223            |   o       o |
     1224            |  / \     /  |
     1225            | o   o   o   |
     1226
     1227        has these trees greater than it::
     1228
     1229            |o          , o        , o        , o        ,  o       ,   o      ,|
     1230            | \            \          \          \           \           \      |
     1231            |  o            o          o           o         _o_        __o__   |
     1232            |   \            \          \           \       /   \      /     \  |
     1233            |    o            o          o          _o_    o     o    o       o |
     1234            |     \            \        / \        /   \    \     \    \     /  |
     1235            |      o            o      o   o      o     o    o     o    o   o   |
     1236            |       \            \          \          /                        |
     1237            |        o            o          o        o                         |
     1238            |         \          /                                              |
     1239            |          o        o                                               |
     1240            <BLANKLINE>
     1241            |   o        ,   o      ,   _o_      ,   _o__     ,   __o__    ,   ___o___  ,|
     1242            |  / \          / \        /   \        /    \       /     \      /       \  |
     1243            | o   o        o   o      o     o      o     _o_    o       o    o         o |
     1244            |      \            \          / \          /   \    \       \    \       /  |
     1245            |       o            o        o   o        o     o    o       o    o     o   |
     1246            |        \            \            \            /      \            \        |
     1247            |         o            o            o          o        o            o       |
     1248            |          \          /                                                      |
     1249            |           o        o                                                       |
     1250            <BLANKLINE>
     1251            |     _o_    ,     __o__  |
     1252            |    /   \        /     \ |
     1253            |   o     o      o       o|
     1254            |  / \     \    / \     / |
     1255            | o   o     o  o   o   o  |
     1256
     1257        TESTS::
     1258
     1259            sage: B = BinaryTree
     1260            sage: b = B([None, B([None, B([None, B([])])])]);b
     1261            [., [., [., [., .]]]]
     1262            sage: b.tamari_greater()
     1263            [[., [., [., [., .]]]]]
     1264            sage: b = B([B([B([B([]), None]), None]), None]);b
     1265            [[[[., .], .], .], .]
     1266            sage: b.tamari_greater()
     1267            [[., [., [., [., .]]]], [., [., [[., .], .]]], [., [[., .], [., .]]], [., [[., [., .]], .]], [., [[[., .], .], .]], [[., .], [., [., .]]], [[., .], [[., .], .]], [[., [., .]], [., .]], [[., [., [., .]]], .], [[., [[., .], .]], .], [[[., .], .], [., .]], [[[., .], [., .]], .], [[[., [., .]], .], .], [[[[., .], .], .], .]]
     1268        """
     1269        from sage.combinat.tools import transitive_ideal
     1270        return transitive_ideal(lambda x: x.tamari_succ(), self)
     1271
     1272    def tamari_pred(self):
     1273        """
     1274        Compute the list of predecessor of ''self'' in the tamari poset.
     1275        This list is computed by all left rotate possible on
     1276        its nodes.
     1277
     1278        For this tree::
     1279
     1280            |     __o__   |
     1281            |    /     \  |
     1282            |   o       o |
     1283            |  / \     /  |
     1284            | o   o   o   |
     1285
     1286        the list is::
     1287
     1288            |        o ,       _o_   |
     1289            |       /         /   \  |
     1290            |     _o_        o     o |
     1291            |    /   \      /     /  |
     1292            |   o     o    o     o   |
     1293            |  / \        /          |
     1294            | o   o      o           |
     1295
     1296        TESTS::
     1297
     1298            sage: B = BinaryTree
     1299            sage: b = B([B([B([B([]), None]), None]), None]);b
     1300            [[[[., .], .], .], .]
     1301            sage: b.tamari_pred()
     1302            []
     1303            sage: b = B([None, B([None, B([None, B([])])])]);b
     1304            [., [., [., [., .]]]]
     1305            sage: b.tamari_pred()
     1306            [[[., .], [., [., .]]], [., [[., .], [., .]]], [., [., [[., .], .]]]]
     1307        """
     1308        res = []
     1309        if self.is_empty():
     1310            return []
     1311        if not self[1].is_empty():
     1312            res.append(self.left_rotate())
     1313        B = self.parent()._element_constructor_
     1314        return (res +
     1315                [B([g, self[1]]) for g in self[0].tamari_pred()] +
     1316                [B([self[0], d]) for d in self[1].tamari_pred()])
     1317
     1318    def tamari_smaller(self):
     1319        """
     1320        The list of all trees smaller than ''self''.
     1321        This is the transitive ideal of its predecessors.
     1322
     1323        The tree::
     1324
     1325            |     __o__   |
     1326            |    /     \  |
     1327            |   o       o |
     1328            |  / \     /  |
     1329            | o   o   o   |
     1330
     1331        has these trees smaller than it::
     1332
     1333            |    __o__  ,       _o_  ,        o ,         o,         o,           o |
     1334            |   /     \        /   \         /           /          /            /  |
     1335            |  o       o      o     o      _o_          o          o            o   |
     1336            | / \     /      /     /      /   \        / \        /            /    |
     1337            |o   o   o      o     o      o     o      o   o      o            o     |
     1338            |              /            / \          /          /            /      |
     1339            |             o            o   o        o          o            o       |
     1340            |                                      /          / \          /        |
     1341            |                                     o          o   o        o         |
     1342            |                                                            /          |
     1343            |                                                           o           |
     1344
     1345        TESTS::
     1346
     1347            sage: B = BinaryTree
     1348            sage: b = B([None, B([None, B([None, B([])])])]);b
     1349            [., [., [., [., .]]]]
     1350            sage: b.tamari_smaller()
     1351            [[., [., [., [., .]]]], [., [., [[., .], .]]], [., [[., .], [., .]]], [., [[., [., .]], .]], [., [[[., .], .], .]], [[., .], [., [., .]]], [[., .], [[., .], .]], [[., [., .]], [., .]], [[., [., [., .]]], .], [[., [[., .], .]], .], [[[., .], .], [., .]], [[[., .], [., .]], .], [[[., [., .]], .], .], [[[[., .], .], .], .]]
     1352            sage: b = B([B([B([B([]), None]), None]), None]);b
     1353            [[[[., .], .], .], .]
     1354            sage: b.tamari_smaller()
     1355            [[[[[., .], .], .], .]]
     1356        """
     1357        from sage.combinat.tools import transitive_ideal
     1358        return transitive_ideal(lambda x: x.tamari_pred(), self)
     1359
     1360    def tamari_succ(self):
     1361        """
     1362        Compute the list of successors of ''self'' in the tamari poset.
     1363        There is the list of all trees obtains by a right rotate of
     1364        one of its nodes.
     1365
     1366        The list of successor of::
     1367
     1368            |     __o__   |
     1369            |    /     \  |
     1370            |   o       o |
     1371            |  / \     /  |
     1372            | o   o   o   |
     1373
     1374        is::
     1375
     1376            |   _o__     ,   ___o___  ,     _o_     |
     1377            |  /    \       /       \      /   \    |
     1378            | o     _o_    o         o    o     o   |
     1379            |      /   \    \       /    / \     \  |
     1380            |     o     o    o     o    o   o     o |
     1381            |          /      \                     |
     1382            |         o        o                    |
     1383
     1384        TESTS::
     1385
     1386            sage: B = BinaryTree
     1387            sage: b = B([B([B([B([]), None]), None]), None]);b
     1388            [[[[., .], .], .], .]
     1389            sage: b.tamari_succ()
     1390            [[[[., .], .], [., .]], [[[., .], [., .]], .], [[[., [., .]], .], .]]
     1391        """
     1392        res = []
     1393        if self.is_empty():
     1394            return []
     1395        B = self.parent()._element_constructor_
     1396        if not self[0].is_empty():
     1397            res.append(self.right_rotate())
     1398        return (res +
     1399             [B([g, self[1]]) for g in self[0].tamari_succ()] +
     1400             [B([self[0], d]) for d in self[1].tamari_succ()])
     1401
     1402    def q_hook_length_formula(self):
     1403        """
     1404        Compute the ``q-hook length formula`` of a binary tree.
     1405
     1406        If `q=1` then ``q-hook length formula`` computes the number of
     1407        permutations such that the shape of binary search tree associated is
     1408        *self*.
     1409
     1410        .. MATH::
     1411
     1412            f_{q} (T) = \\frac{[\\mid T\\mid]_q !}{\\prod_{t\\in T}
     1413            q^{right(t)}[\\mid t\\mid]_q}
     1414
     1415        where `\\mid T\\mid` is the node number of `T`, `t\\in T` the set
     1416        of all subtree of `T` and `right(t)` the number of node of the right
     1417        subtree of `t`.
     1418
     1419        There is 20 permutations which give this shape binary tree::
     1420
     1421            |     __o__   |
     1422            |    /     \  |
     1423            |   o       o |
     1424            |  / \     /  |
     1425            | o   o   o   |
     1426
     1427        by the binary search insertion algorithm.
     1428
     1429        TESTS::
     1430
     1431            sage: b = BinaryTree([[[],[]],[[],None]]); b
     1432            [[[., .], [., .]], [[., .], .]]
     1433            sage: b.q_hook_length_formula()(q=1)
     1434            20
     1435            sage: BinaryTree([[],[]]).q_hook_length_formula()
     1436            (((q + 2)*q + 2)*q + 1)*q/((q + 1)*q + 1)
     1437        """
     1438        from sage.combinat.q_analogues import q_factorial, q_int
     1439        from sage.symbolic.ring import SymbolicRing
     1440
     1441        q = SymbolicRing().var('q')
     1442
     1443        def product_of_subtrees(b):
     1444            if b.is_empty():
     1445                return q ** 0
     1446            return (q ** (-b[0].node_number()) * q_int(b.node_number())) * \
     1447                product_of_subtrees(b[0]) * product_of_subtrees(b[1])
     1448
     1449        return q_factorial(self.node_number()) / product_of_subtrees(self)
     1450
     1451    @combinatorial_map(name="Right rotate")
     1452    def right_rotate(self):
     1453        """
     1454        Right rotation operation of tree::
     1455
     1456            |     o                     _o_   |
     1457            |    /                     /   \  |
     1458            |   o    -right-rotate->  o     o |
     1459            |  / \                         /  |
     1460            | o   o                       o   |
     1461            <BLANKLINE>
     1462            |       __o__                         _o__      |
     1463            |      /     \                       /    \     |
     1464            |     o       o  -right-rotate->    o     _o_   |
     1465            |    / \                           /     /   \  |
     1466            |   o   o                         o     o     o |
     1467            |  /     \                               \      |
     1468            | o       o                               o     |
     1469
     1470        TESTS::
     1471
     1472            sage: b = BinaryTree([[[],[]], None]); ascii_art([b])
     1473            [     o ]
     1474            [    /  ]
     1475            [   o   ]
     1476            [  / \  ]
     1477            [ o   o ]
     1478            sage: ascii_art([b.right_rotate()])
     1479            [   _o_   ]
     1480            [  /   \  ]
     1481            [ o     o ]
     1482            [      /  ]
     1483            [     o   ]
     1484            sage: b = BinaryTree([[[[],None],[None,[]]], []]);ascii_art([b])
     1485            [       __o__   ]
     1486            [      /     \  ]
     1487            [     o       o ]
     1488            [    / \        ]
     1489            [   o   o       ]
     1490            [  /     \      ]
     1491            [ o       o     ]
     1492            sage: ascii_art([b.right_rotate()])
     1493            [     _o__      ]
     1494            [    /    \     ]
     1495            [   o     _o_   ]
     1496            [  /     /   \  ]
     1497            [ o     o     o ]
     1498            [        \      ]
     1499            [         o     ]
     1500        """
     1501        B = self.parent()._element_constructor_
     1502        return B([self[0][0], B([self[0][1], self[1]])])
     1503
     1504    @combinatorial_map(name="Left rotate")
     1505    def left_rotate(self):
     1506        """
     1507        Left rotation operation of tree::
     1508
     1509            |   _o_                        o |
     1510            |  /   \                      /  |
     1511            | o     o  -left-rotate->    o   |
     1512            |      /                    / \  |
     1513            |     o                    o   o |
     1514            <BLANKLINE>
     1515            |       __o__                            o |
     1516            |      /     \                          /  |
     1517            |     o       o  -left-rotate->        o   |
     1518            |    / \                              /    |
     1519            |   o   o                            o     |
     1520            |  /     \                          / \    |
     1521            | o       o                        o   o   |
     1522            |                                 /     \  |
     1523            |                                o       o |
     1524
     1525
     1526        TESTS::
     1527
     1528            sage: b = BinaryTree([[],[[],None]]); ascii_art([b])
     1529            [   _o_   ]
     1530            [  /   \  ]
     1531            [ o     o ]
     1532            [      /  ]
     1533            [     o   ]
     1534            sage: ascii_art([b.left_rotate()])
     1535            [     o ]
     1536            [    /  ]
     1537            [   o   ]
     1538            [  / \  ]
     1539            [ o   o ]
     1540            sage: b.left_rotate().right_rotate() == b
     1541            True
     1542        """
     1543        B = self.parent()._element_constructor_
     1544        return B([B([self[0], self[1][0]]), self[1][1]])
     1545
     1546    @combinatorial_map(name="Over operation on Binary Trees")
     1547    def over(self, bt):
     1548        """
     1549        The ``over`` (`/`) operation defined by Loday-Ronco [LodayRonco]_::
     1550
     1551            |   o       __o__       _o_         |
     1552            |  / \  /  /     \  =  /   \        |
     1553            | o   o   o       o   o     o       |
     1554            |          \     /           \      |
     1555            |           o   o           __o__   |
     1556            |                          /     \  |
     1557            |                         o       o |
     1558            |                          \     /  |
     1559            |                           o   o   |
     1560
     1561        EXAMPLES::
     1562
     1563            sage: b1 = BinaryTree([[],[[],[]]])
     1564            sage: b2 = BinaryTree([[None, []],[]])
     1565            sage: ascii_art((b1, b2, b1/b2))
     1566            (   _o_        _o_      _o_           )
     1567            (  /   \      /   \    /   \          )
     1568            ( o     o    o     o  o     o_        )
     1569            (      / \    \            /  \       )
     1570            (     o   o,   o    ,     o    o      )
     1571            (                               \     )
     1572            (                               _o_   )
     1573            (                              /   \  )
     1574            (                             o     o )
     1575            (                              \      )
     1576            (                               o     )
     1577
     1578        TESTS::
     1579
     1580            sage: b1 = BinaryTree([[],[]]); ascii_art([b1])
     1581            [   o   ]
     1582            [  / \  ]
     1583            [ o   o ]
     1584            sage: b2 = BinaryTree([[None,[]],[[],None]]); ascii_art([b2])
     1585            [   __o__   ]
     1586            [  /     \  ]
     1587            [ o       o ]
     1588            [  \     /  ]
     1589            [   o   o   ]
     1590            sage: ascii_art([b1.over(b2)])
     1591            [   _o_         ]
     1592            [  /   \        ]
     1593            [ o     o       ]
     1594            [        \      ]
     1595            [       __o__   ]
     1596            [      /     \  ]
     1597            [     o       o ]
     1598            [      \     /  ]
     1599            [       o   o   ]
     1600        """
     1601        B = self.parent()._element_constructor_
     1602        if self.is_empty():
     1603            return bt
     1604        lab = None
     1605        if hasattr(self, "label"):
     1606            lab = self.label()
     1607        else:
     1608            return B([self[0], self[1].over(bt)], lab)
     1609
     1610    __div__ = over
     1611
     1612    @combinatorial_map(name="Under operation on Binary Trees")
     1613    def under(self, bt):
     1614        r"""
     1615        The ``under`` (`\backslash`) operation defined by Loday-Ronco
     1616        [LodayRonco]_.
     1617
     1618        EXAMPLES::
     1619
     1620            sage: b1 = BinaryTree([[],[]])
     1621            sage: b2 = BinaryTree([None,[]])
     1622            sage: ascii_art((b1, b2, b1 \ b2))
     1623            (   o    o        _o_   )
     1624            (  / \    \      /   \  )
     1625            ( o   o,   o,   o     o )
     1626            (              / \      )
     1627            (             o   o     )
     1628
     1629        TESTS::
     1630
     1631            sage: b1 = BinaryTree([[],[[None,[]],None]]); ascii_art([b1])
     1632            [   _o_   ]
     1633            [  /   \  ]
     1634            [ o     o ]
     1635            [      /  ]
     1636            [     o   ]
     1637            [      \  ]
     1638            [       o ]
     1639            sage: b2 = BinaryTree([[],[None,[]]]); ascii_art([b2])
     1640            [   o     ]
     1641            [  / \    ]
     1642            [ o   o   ]
     1643            [      \  ]
     1644            [       o ]
     1645            sage: ascii_art([b1.under(b2)])
     1646            [        o_     ]
     1647            [       /  \    ]
     1648            [      o    o   ]
     1649            [     /      \  ]
     1650            [   _o_       o ]
     1651            [  /   \        ]
     1652            [ o     o       ]
     1653            [      /        ]
     1654            [     o         ]
     1655            [      \        ]
     1656            [       o       ]
     1657        """
     1658        B = self.parent()._element_constructor_
     1659        if bt.is_empty():
     1660            return self
     1661        lab = None
     1662        if hasattr(bt, "label"):
     1663            lab = bt.label()
     1664        else:
     1665            return B([self.under(bt[0]), bt[1]], lab)
     1666
     1667    _backslash_ = under
     1668
     1669    def sylvester_class(self, left_to_right=False):
     1670        """
     1671        Iterate the sylvester class corresponding to the binary tree.
    10701672       
     1673        The sylvester class is the set of permutations corresponding to the
     1674        canonical binary search tree with same shape of self. (see _[HNT05])
     1675       
     1676        For example the following has the permutations (1,3,2) and (3,1,2)
     1677        associated::
    10711678
     1679            [   o   ]
     1680            [  / \  ]
     1681            [ o   o ]
     1682       
     1683        TESTS::
     1684       
     1685            sage: list(BinaryTree([[],[]]).sylvester_class())
     1686            [[1, 3, 2], [3, 1, 2]]
     1687            sage: bt = BinaryTree([[[],None],[[],[]]])
     1688            sage: l = list(bt.sylvester_class()); l
     1689            [[1, 2, 4, 6, 5, 3],
     1690             [1, 4, 2, 6, 5, 3],
     1691             [1, 4, 6, 2, 5, 3],
     1692             [1, 4, 6, 5, 2, 3],
     1693             [4, 1, 2, 6, 5, 3],
     1694             [4, 1, 6, 2, 5, 3],
     1695             [4, 1, 6, 5, 2, 3],
     1696             [4, 6, 1, 2, 5, 3],
     1697             [4, 6, 1, 5, 2, 3],
     1698             [4, 6, 5, 1, 2, 3],
     1699             [1, 2, 6, 4, 5, 3],
     1700             [1, 6, 2, 4, 5, 3],
     1701             [1, 6, 4, 2, 5, 3],
     1702             [1, 6, 4, 5, 2, 3],
     1703             [6, 1, 2, 4, 5, 3],
     1704             [6, 1, 4, 2, 5, 3],
     1705             [6, 1, 4, 5, 2, 3],
     1706             [6, 4, 1, 2, 5, 3],
     1707             [6, 4, 1, 5, 2, 3],
     1708             [6, 4, 5, 1, 2, 3]]
     1709            sage: len(l) == Integer(bt.q_hook_length_formula()(q=1))
     1710            True
     1711        """
     1712        if self.is_empty():
     1713            yield []
     1714            return
     1715        import itertools
     1716        from sage.combinat.words.word import Word as W
     1717        from sage.combinat.words.shuffle_product import ShuffleProduct_w1w2 \
     1718            as shuffle
     1719
     1720        if left_to_right:
     1721            builder = lambda i, p: [i] + list(p)
     1722        else:
     1723            builder = lambda i, p: list(p) + [i]
     1724
     1725        shift = self[0].node_number() + 1
     1726        for l, r in itertools.product(
     1727                    self[0].sylvester_class(),
     1728                    self[1].sylvester_class()):
     1729           for p in shuffle(W(l), W([shift + ri for ri in r])):
     1730               yield builder(shift, p)
     1731
     1732    def is_full(self):
     1733        """
     1734        A full binary tree is a tree in which every node other than the leaves
     1735        has two children.
     1736
     1737        (Also called *proper binary tree* or *2-tree* or *strictly binary
     1738        tree*)
     1739
     1740        For example::
     1741
     1742            |       __o__   |
     1743            |      /     \  |
     1744            |     o       o |
     1745            |    / \        |
     1746            |   o   o       |
     1747            |  /     \      |
     1748            | o       o     |
     1749
     1750        is not full but the next one is::
     1751
     1752            |         ___o___   |
     1753            |        /       \  |
     1754            |     __o__       o |
     1755            |    /     \        |
     1756            |   o       o       |
     1757            |  / \     / \      |
     1758            | o   o   o   o     |
     1759
     1760        TESTS::
     1761
     1762            sage: BinaryTree([[[[],None],[None,[]]], []]).is_full()
     1763            False
     1764            sage: BinaryTree([[[[],[]],[[],[]]], []]).is_full()
     1765            True
     1766            sage: ascii_art(filter(lambda bt: bt.is_full(), BinaryTrees(5)))
     1767            [   _o_          _o_   ]
     1768            [  /   \        /   \  ]
     1769            [ o     o      o     o ]
     1770            [      / \    / \      ]
     1771            [     o   o, o   o     ]
     1772        """
     1773        if self.is_empty(): return True
     1774        if self[0].is_empty() != self[1].is_empty(): return False
     1775        return self[0].is_full() and self[1].is_full()
     1776
     1777    def is_perfect(self):
     1778        """
     1779        A perfect binary tree is a full tree in which all leaves are at the
     1780        same depth.
     1781
     1782        For example::
     1783
     1784            |         ___o___   |
     1785            |        /       \  |
     1786            |     __o__       o |
     1787            |    /     \        |
     1788            |   o       o       |
     1789            |  / \     / \      |
     1790            | o   o   o   o     |
     1791
     1792        is not perfect but the next one is::
     1793
     1794            |     __o__     |
     1795            |    /     \    |
     1796            |   o       o   |
     1797            |  / \     / \  |
     1798            | o   o   o   o |
     1799
     1800        TESTS::
     1801
     1802            sage: for i in range(10):
     1803            ....:     ascii_art(filter(lambda bt: bt.is_perfect(),
     1804            ....:         BinaryTrees(i)))
     1805            [  ]
     1806            [ o ]
     1807            [  ]
     1808            [   o   ]
     1809            [  / \  ]
     1810            [ o   o ]
     1811            [  ]
     1812            [  ]
     1813            [  ]
     1814            [     __o__     ]
     1815            [    /     \    ]
     1816            [   o       o   ]
     1817            [  / \     / \  ]
     1818            [ o   o   o   o ]
     1819            [  ]
     1820            [  ]
     1821        """
     1822        return 2 ** self.depth() - 1 == self.node_number()
     1823
     1824    def is_complete(self):
     1825        """
     1826        A complete binary tree is a perfect binary tree except possibly in the
     1827        last level.
     1828
     1829        A complete binary tree (also called binary heap) is a binary tree in
     1830        which every level, except possibly the last one (the deepest), is
     1831        completely filled. At depth `n` all nodes must be as far left as
     1832        possible.
     1833
     1834        For example::
     1835
     1836            |         ___o___   |
     1837            |        /       \  |
     1838            |     __o__       o |
     1839            |    /     \        |
     1840            |   o       o       |
     1841            |  / \     / \      |
     1842            | o   o   o   o     |
     1843
     1844        is not complet but the following ones are::
     1845
     1846            |     __o__          _o_            ___o___     |
     1847            |    /     \        /   \          /       \    |
     1848            |   o       o      o     o      __o__       o   |
     1849            |  / \     / \    / \          /     \     / \  |
     1850            | o   o   o   o, o   o    ,   o       o   o   o |
     1851            |                            / \     /          |
     1852            |                           o   o   o           |
     1853
     1854        TESTS::
     1855
     1856            sage: for i in range(9):
     1857            ....:    ascii_art(filter(lambda bt: bt.is_complete(),
     1858            ....:         BinaryTrees(i)))
     1859            [  ]
     1860            [ o ]
     1861            [   o ]
     1862            [  /  ]
     1863            [ o   ]
     1864            [   o   ]
     1865            [  / \  ]
     1866            [ o   o ]
     1867            [     o   ]
     1868            [    / \  ]
     1869            [   o   o ]
     1870            [  /      ]
     1871            [ o       ]
     1872            [     _o_   ]
     1873            [    /   \  ]
     1874            [   o     o ]
     1875            [  / \      ]
     1876            [ o   o     ]
     1877            [     __o__   ]
     1878            [    /     \  ]
     1879            [   o       o ]
     1880            [  / \     /  ]
     1881            [ o   o   o   ]
     1882            [     __o__     ]
     1883            [    /     \    ]
     1884            [   o       o   ]
     1885            [  / \     / \  ]
     1886            [ o   o   o   o ]
     1887            [       __o__     ]
     1888            [      /     \    ]
     1889            [     o       o   ]
     1890            [    / \     / \  ]
     1891            [   o   o   o   o ]
     1892            [  /              ]
     1893            [ o               ]
     1894        """
     1895        if self.is_empty(): return True
     1896        # self := L ^ R
     1897        dL = self[0].depth()
     1898        dR = self[1].depth()
     1899        # if L is perfect
     1900        if self[0].is_perfect():
     1901            # if the depth of R == depth of L then R must be complete
     1902            if dL == dR:
     1903                return self[1].is_complete()
     1904            # else R is perfect with depth equals depth of L - 1
     1905            elif dL == dR + 1:
     1906                return self[1].is_perfect()
     1907            return False
     1908        # L is not perfect then R is perfect and the depth of L = the depth of
     1909        # R + 1
     1910        elif self[0].is_complete():
     1911            return self[1].is_perfect() and dL == dR + 1
    10721912
    10731913from sage.structure.parent import Parent
    10741914from sage.structure.unique_representation import UniqueRepresentation
    class LabelledBinaryTree(AbstractLabelle 
    14982338                fils = self[1].binary_search_insert(letter)
    14992339                return LT([self[0], fils], label=self.label())
    15002340
     2341    def right_rotate(self):
     2342        """
     2343        Right rotation operation of tree::
     2344
     2345            |     y                      x     |
     2346            |    / \                    / \    |
     2347            |   x   C -right-rotate->  A   y   |
     2348            |  / \                        / \  |
     2349            | A   B                      B   C |
     2350
     2351        TESTS::
     2352
     2353            sage: LB = LabelledBinaryTree
     2354            sage: b = LB([LB([LB([],"A"), LB([],"B")],"x"),LB([],"C")], "y"); b
     2355            y[x[A[., .], B[., .]], C[., .]]
     2356            sage: b.right_rotate()
     2357            x[A[., .], y[B[., .], C[., .]]]
     2358        """
     2359        B = self.parent()._element_constructor_
     2360        return B([
     2361            self[0][0],
     2362            B([self[0][1], self[1]], self.label())
     2363        ], self[0].label())
     2364
     2365    def left_rotate(self):
     2366        """
     2367        Right rotation operation of tree::
     2368
     2369           |     y                    x     |
     2370           |    / \                  / \    |
     2371           |   x   C <-left-rotate- A   y   |
     2372           |  / \                      / \  |
     2373           | A   B                    B   C |
     2374
     2375
     2376        TESTS::
     2377
     2378            sage: LB = LabelledBinaryTree
     2379            sage: b = LB([LB([LB([],"A"), LB([],"B")],"x"),LB([],"C")], "y"); b
     2380            y[x[A[., .], B[., .]], C[., .]]
     2381            sage: b == b.right_rotate().left_rotate()
     2382            True
     2383        """
     2384        B = self.parent()._element_constructor_
     2385        return B([
     2386            B([self[0], self[1][0]], self.label()),
     2387            self[1][1]
     2388        ], self[1].label())
     2389
     2390    def heap_insert(self, l):
     2391        """
     2392        Insert a letter in a binary heap (tree)
     2393
     2394        Roughly, a binary heap will be a complete binary tree such that for
     2395        each nodes the label is greater or equals to the label of its children.
     2396
     2397        For example::
     2398
     2399            |     _7_   |
     2400            |    /   \  |
     2401            |   5     6 |
     2402            |  / \      |
     2403            | 3   4     |
     2404
     2405        INPUT:
     2406
     2407        - ``letter`` -- any object comparable with the label of ``self``
     2408
     2409        .. NOTE:: ``self`` is supposed to be a binary heap (tree). No check is
     2410                  performed.
     2411
     2412        TESTS::
     2413
     2414            sage: h = LabelledBinaryTree(None)
     2415            sage: h = h.heap_insert(3); ascii_art([h])
     2416            [ 3 ]
     2417            sage: h = h.heap_insert(4); ascii_art([h])
     2418            [   4 ]
     2419            [  /  ]
     2420            [ 3   ]
     2421            sage: h = h.heap_insert(6); ascii_art([h])
     2422            [   6   ]
     2423            [  / \  ]
     2424            [ 3   4 ]
     2425            sage: h = h.heap_insert(2); ascii_art([h])
     2426            [     6   ]
     2427            [    / \  ]
     2428            [   3   4 ]
     2429            [  /      ]
     2430            [ 2       ]
     2431            sage: ascii_art([h.heap_insert(5)])
     2432            [     _6_   ]
     2433            [    /   \  ]
     2434            [   5     4 ]
     2435            [  / \      ]
     2436            [ 2   3     ]
     2437
     2438
     2439        """
     2440        B = self.parent()._element_constructor_
     2441        if self.is_empty():
     2442            return B([], l)
     2443
     2444        if self.label() < l:
     2445            label_root = l
     2446            label_insert = self.label()
     2447        else:
     2448            label_root = self.label()
     2449            label_insert = l
     2450        L, R = self
     2451        dL = L.depth()
     2452        dR = R.depth()
     2453        # if depth of L is greater than the depth of R
     2454        if dL > dR:
     2455            # if L is perfect we insert in R
     2456            if L.is_perfect():
     2457                return B([L, R.heap_insert(label_insert)], label_root)
     2458            # we insert in L
     2459            else:
     2460                return B([L.heap_insert(label_insert), R], label_root)
     2461        # ==> dL == dR
     2462        else:
     2463            # if R is perfect we have to insert on the most left leaf
     2464            if R.is_perfect():
     2465                # ## TODO:: can be optimized...
     2466                return B([L.heap_insert(label_insert), R], label_root)
     2467            # else we insert on the right
     2468            else:
     2469                return B([L, R.heap_insert(label_insert)], label_root)
     2470
    15012471    _UnLabelled = BinaryTree
    15022472
    15032473