Ticket #14498: trac_14498-algorithms_trees-rebased.2.patch

File trac_14498-algorithms_trees-rebased.2.patch, 75.3 KB (added by tscrim, 6 years ago)

minor docstring fix

  • sage/combinat/abstract_tree.py

    # HG changeset patch
    # User Jean-Baptiste Priez <jbp@kerios.fr>
    # Date 1373370155 -7200
    # Node ID 7892e4001368e7c253758d994b66c03d80117df3
    # Parent a4ceec897407e8554290be762946e1283d7329d1
    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): 
    7785    There is no data structure defined here, as this class is meant to be
    7886    extended, not instantiated.
    7987
    80     .. rubric:: How should this class be extended ?
     88    .. rubric:: How should this class be extended?
    8189
    8290    A class extending :class:`AbstractTree
    8391    <sage.combinat.abstract_tree.AbstractTree>` should respect several
    class AbstractTree(object): 
    106114        sage: TestSuite(OrderedTree()).run()
    107115        sage: TestSuite(BinaryTree()).run()
    108116    """
     117    def pre_order_traversal_iter(self):
     118        r"""
     119        The depth-first pre-order traversal iterator.
     120
     121        This method iters each node following the depth-first pre-order
     122        traversal algorithm (recursive implementation).
     123
     124        For example, on the following binary tree `b`::
     125
     126            |   ___3____      |
     127            |  /        \     |
     128            | 1         _7_   |
     129            |  \       /   \  |
     130            |   2     5     8 |
     131            |        / \      |
     132            |       4   6     |
     133
     134        the ``depth-first pre-order traversal algorithm`` explores `b` in the
     135        following order of nodes: `3,1,2,7,5,4,6,8`.
     136
     137        The algorithm is::
     138
     139            manipulate the root,
     140            then explore each subtree (by the algorithm).
     141
     142        Another example::
     143
     144            |     __1____ |
     145            |    /  /   / |
     146            |   2  6   8_ |
     147            |   |  |  / / |
     148            |   3_ 7 9 10 |
     149            |  / /        |
     150            | 4 5         |
     151
     152        The algorithm explores this tree in the following order:
     153        `1,2,3,4,5,6,7,8,9,10`.
     154
     155        TESTS::
     156
     157            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).canonical_labelling()
     158            sage: ascii_art([b])
     159            [   ___3____      ]
     160            [  /        \     ]
     161            [ 1         _7_   ]
     162            [  \       /   \  ]
     163            [   2     5     8 ]
     164            [        / \      ]
     165            [       4   6     ]
     166            sage: [n.label() for n in b.pre_order_traversal_iter()]
     167            [3, 1, 2, 7, 5, 4, 6, 8]
     168            sage: t = OrderedTree([[[[],[]]],[[]],[[],[]]]).canonical_labelling()
     169            sage: ascii_art([t])
     170            [     __1____   ]
     171            [    /  /   /   ]
     172            [   2  6   8_   ]
     173            [   |  |  / /   ]
     174            [   3_ 7 9 10   ]
     175            [  / /          ]
     176            [ 4 5           ]
     177            sage: [n.label() for n in t.pre_order_traversal_iter()]
     178            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     179        """
     180        if self.is_empty():
     181            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=None):
     194        r"""
     195        The depth-first pre-order traversal algorithm (iterative
     196        implementation).
     197
     198        INPUT:
     199
     200        - ``action`` -- (optional) a function which takes a node in input
     201          and does something during the exploration
     202
     203        .. SEEALSO::
     204
     205            - :meth:`~sage.combinat.abstract_tree.AbstractTree.pre_order_traversal_iter()`
     206            - :meth:`~sage.combinat.abstract_tree.AbstractTree.pre_order_traversal()`
     207
     208        TESTS::
     209
     210            sage: l = []
     211            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).canonical_labelling()
     212            sage: b
     213            3[1[., 2[., .]], 7[5[4[., .], 6[., .]], 8[., .]]]
     214            sage: b.iterative_pre_order_traversal(lambda node: l.append(node.label()))
     215            sage: l
     216            [3, 1, 2, 7, 5, 4, 6, 8]
     217            sage: t = OrderedTree([[[[],[]]],[[]],[[],[]]]).canonical_labelling()
     218            sage: t
     219            1[2[3[4[], 5[]]], 6[7[]], 8[9[], 10[]]]
     220            sage: l = []
     221            sage: t.iterative_pre_order_traversal(lambda node: l.append(node.label()))
     222            sage: l
     223            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     224            sage: l = []
     225            sage: BinaryTree().canonical_labelling().\
     226            ....:     pre_order_traversal(lambda node: l.append(node.label()))
     227            sage: l
     228            []
     229            sage: OrderedTree([]).canonical_labelling().\
     230            ....:     iterative_pre_order_traversal(lambda node: l.append(node.label()))
     231            sage: l
     232            [1]
     233        """
     234        if self.is_empty():
     235            return
     236        if action is None:
     237            action = lambda x: None
     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=None):
     249        r"""
     250        The depth-first pre-order traversal algorithm (recursive
     251        implementation).
     252
     253        INPUT:
     254
     255        - ``action`` -- (optional) a function which takes a node in input
     256          and does 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        Another 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        .. SEEALSO::
     290
     291            - :meth:`~sage.combinat.abstract_tree.AbstractTree.pre_order_traversal_iter()`
     292            - :meth:`~sage.combinat.abstract_tree.AbstractTree.iterative_pre_order_traversal()`
     293
     294        TESTS::
     295
     296            sage: l = []
     297            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).canonical_labelling()
     298            sage: 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(lambda node: li.append(node.label()))
     305            sage: l == li
     306            True
     307            sage: t = OrderedTree([[[[],[]]],[[]],[[],[]]]).canonical_labelling()
     308            sage: t
     309            1[2[3[4[], 5[]]], 6[7[]], 8[9[], 10[]]]
     310            sage: l = []
     311            sage: t.pre_order_traversal(lambda node: l.append(node.label()))
     312            sage: l
     313            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     314            sage: li = []
     315            sage: t.iterative_pre_order_traversal(lambda node: li.append(node.label()))
     316            sage: l == li
     317            True
     318            sage: l = []
     319            sage: BinaryTree().canonical_labelling().\
     320            ....:     pre_order_traversal(lambda node: l.append(node.label()))
     321            sage: l
     322            []
     323            sage: OrderedTree([]).canonical_labelling().\
     324            ....:     pre_order_traversal(lambda node: l.append(node.label()))
     325            sage: l
     326            [1]
     327        """
     328        if action is None:
     329            action = lambda x: None
     330        for node in self.pre_order_traversal_iter():
     331            action(node)
     332
     333    def post_order_traversal_iter(self):
     334        r"""
     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,[]],[[[],[]],[]]]).canonical_labelling()
     374            sage: 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([[[[],[]]],[[]],[[],[]]]).canonical_labelling()
     385            sage: 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():
     403            return
     404        # TODO:: PYTHON 3
     405        # import itertools
     406        # yield from itertools.chain(map(
     407        #     lambda c: c.post_order_traversal_iter(),
     408        #     self
     409        # ))
     410        for children in self:
     411            for node in children.post_order_traversal_iter():
     412                yield node
     413        yield self
     414
     415    def post_order_traversal(self, action=None):
     416        r"""
     417        The depth-first post-order traversal algorithm (recursive
     418        implementation).
     419
     420        INPUT:
     421
     422        - ``action`` -- (optional) a function which takes a node in
     423          input and does something during the exploration
     424
     425        .. SEEALSO::
     426
     427            - :meth:`~sage.combinat.abstract_tree.AbstractTree.post_order_traversal_iter()`
     428            - :meth:`~sage.combinat.abstract_tree.AbstractTree.iterative_post_order_traversal()`
     429
     430        TESTS::
     431
     432            sage: l = []
     433            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).canonical_labelling()
     434            sage: b
     435            3[1[., 2[., .]], 7[5[4[., .], 6[., .]], 8[., .]]]
     436            sage: b.post_order_traversal(lambda node: l.append(node.label()))
     437            sage: l
     438            [2, 1, 4, 6, 5, 8, 7, 3]
     439            sage: t = OrderedTree([[[[],[]]],[[]],[[],[]]]).\
     440            ....:     canonical_labelling(); t
     441            1[2[3[4[], 5[]]], 6[7[]], 8[9[], 10[]]]
     442            sage: l = []
     443            sage: t.post_order_traversal(lambda node: l.append(node.label()))
     444            sage: l
     445            [4, 5, 3, 2, 7, 6, 9, 10, 8, 1]
     446            sage: l = []
     447            sage: BinaryTree().canonical_labelling().\
     448            ....:     post_order_traversal(lambda node: l.append(node.label()))
     449            sage: l
     450            []
     451            sage: OrderedTree([]).canonical_labelling().\
     452            ....:     post_order_traversal(lambda node: l.append(node.label()))
     453            sage: l
     454            [1]
     455        """
     456        if action is None:
     457            action = lambda x: None
     458        for node in self.post_order_traversal_iter():
     459            action(node)
     460
     461    def iterative_post_order_traversal(self, action=None):
     462        r"""
     463        The depth-first post-order traversal algorithm (iterative
     464        implementation).
     465
     466        INPUT:
     467
     468        - ``action`` -- (optional) a function which takes a node in input and
     469          does something during the exploration
     470
     471        .. SEEALSO::
     472
     473            - :meth:`~sage.combinat.abstract_tree.AbstractTree.post_order_traversal_iter()`
     474
     475        TESTS::
     476
     477            sage: l = []
     478            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).canonical_labelling()
     479            sage: b
     480            3[1[., 2[., .]], 7[5[4[., .], 6[., .]], 8[., .]]]
     481            sage: b.iterative_post_order_traversal(lambda node: l.append(node.label()))
     482            sage: l
     483            [8, 6, 4, 5, 7, 2, 1, 3]
     484            sage: t = OrderedTree([[[[],[]]],[[]],[[],[]]]).canonical_labelling()
     485            sage: t
     486            1[2[3[4[], 5[]]], 6[7[]], 8[9[], 10[]]]
     487            sage: l = []
     488            sage: t.iterative_post_order_traversal(lambda node: l.append(node.label()))
     489            sage: l
     490            [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
     491            sage: l = []
     492            sage: BinaryTree().canonical_labelling().\
     493            ....:     iterative_post_order_traversal(
     494            ....:         lambda node: l.append(node.label()))
     495            sage: l
     496            []
     497            sage: OrderedTree([]).canonical_labelling().\
     498            ....:     iterative_post_order_traversal(
     499            ....:         lambda node: l.append(node.label()))
     500            sage: l
     501            [1]
     502        """
     503        if self.is_empty():
     504            return
     505        if action is None:
     506            action = lambda x: None
     507        stack = [self]
     508        mark = []
     509        while len(stack) > 0:
     510            node = stack[-1]
     511            if node in mark:
     512                stack.pop()
     513                action(node)
     514            else:
     515                mark.append(node)
     516                stack.extend(filter(lambda n: not n.is_empty(), node))
     517
     518    def breadth_first_order_traversal(self, action=None):
     519        r"""
     520        The breadth-first order traversal algorithm.
     521
     522        INPUT:
     523
     524        - ``action`` -- (optional) a function which takes a node in input and
     525          does omething during the exploration
     526
     527        For example, on the following binary tree `b`::
     528
     529            |   ___3____      |
     530            |  /        \     |
     531            | 1         _7_   |
     532            |  \       /   \  |
     533            |   2     5     8 |
     534            |        / \      |
     535            |       4   6     |
     536
     537        the ``breadth-first order traversal algorithm`` explores `b` in the
     538        following order of nodes: `3,1,7,2,5,8,4,6`.
     539
     540        The algorithm is::
     541
     542            queue <- ( root )
     543            while the queue is not empty:
     544                node <- pop( queue )
     545                manipulate the node
     546                append in the queue all subtrees of the node
     547
     548        TESTS::
     549
     550            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).canonical_labelling()
     551            sage: l = []
     552            sage: b.breadth_first_order_traversal(lambda node: l.append(node.label()))
     553            sage: l
     554            [3, 1, 7, 2, 5, 8, 4, 6]
     555            sage: t = OrderedTree([[[[],[]]],[[]],[[],[]]]).canonical_labelling()
     556            sage: t
     557            1[2[3[4[], 5[]]], 6[7[]], 8[9[], 10[]]]
     558            sage: l = []
     559            sage: t.breadth_first_order_traversal(lambda node: l.append(node.label()))
     560            sage: l
     561            [1, 2, 6, 8, 3, 7, 9, 10, 4, 5]
     562            sage: l = []
     563            sage: BinaryTree().canonical_labelling().\
     564            ....:     breadth_first_order_traversal(
     565            ....:         lambda node: l.append(node.label()))
     566            sage: l
     567            []
     568            sage: OrderedTree([]).canonical_labelling().\
     569            ....:     breadth_first_order_traversal(
     570            ....:         lambda node: l.append(node.label()))
     571            sage: l
     572            [1]
     573        """
     574        if self.is_empty():
     575            return
     576        if action is None:
     577            action = lambda x: None
     578        queue = []
     579        queue.append(self)
     580        while len(queue) > 0:
     581            node = queue.pop()
     582            action(node)
     583            for subtree in node:
     584                if not subtree.is_empty():
     585                    queue.insert(0, subtree)
    109586
    110587    def subtrees(self):
    111588        """
    112         Returns a generator for all subtrees of ``self``
     589        Return a generator for all subtrees of ``self``.
    113590
    114591        The number of subtrees of a tree is its number of elements.
    115592
    class AbstractTree(object): 
    134611            sage: bt.node_number() == len(list(bt.subtrees()))
    135612            True
    136613        """
    137         if not self.is_empty():
    138             yield self
    139             for i in self:
    140                 for t in i.subtrees():
    141                     yield t
     614        return self.pre_order_traversal_iter()
    142615
    143616    def paths(self):
    144617        """
    145         Returns a generator for all paths to nodes of ``self``
     618        Return a generator for all paths to nodes of ``self``.
    146619
    147620        OUTPUT:
    148621
    class AbstractTree(object): 
    412885        nb = self.node_number()
    413886        if nb <= 1:
    414887            return 1
    415         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"
     888        return nb * prod(s.tree_factorial() for s in self)
    421889
    422890    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}}}}
     891        r"""
     892        Nice output which can be easily modified
    438893
    439894        TESTS::
    440895
    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}}}}'
     896            sage: latex(BinaryTree([[[],[]],[[],None]]))
     897            { \newcommand{\nodea}{\node[draw,circle] (a) {$$}
     898            ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$$}
     899            ;}\newcommand{\nodec}{\node[draw,circle] (c) {$$}
     900            ;}\newcommand{\noded}{\node[draw,circle] (d) {$$}
     901            ;}\newcommand{\nodee}{\node[draw,circle] (e) {$$}
     902            ;}\newcommand{\nodef}{\node[draw,circle] (f) {$$}
     903            ;}\begin{tikzpicture}[auto]
     904            \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     905                     \&         \&         \& \nodea  \&         \&         \&         \\
     906                     \& \nodeb  \&         \&         \&         \& \nodee  \&         \\
     907             \nodec  \&         \& \noded  \&         \& \nodef  \&         \&         \\
     908            };
     909            <BLANKLINE>
     910            \path[ultra thick, red] (b) edge (c) edge (d)
     911                (e) edge (f)
     912                (a) edge (b) edge (e);
     913            \end{tikzpicture}}
    447914        """
    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()
     915        # latex environnement : TikZ
     916        begin_env = "\\begin{tikzpicture}[auto]\n"
     917        end_env = "\\end{tikzpicture}"
     918        # it uses matrix trick to place each node
     919        matrix_begin = "\\matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{\n"
     920        matrix_end = "\\\\\n};\n"
     921        # a basic path to each edges
     922        path_begin = "\\path[ultra thick, red] "
     923        path_end = ";\n"
     924        # to make a pretty output, it creates one LaTeX command for
     925        # each node
     926        cmd = "\\node"
     927        new_cmd1 = "\\newcommand{" + cmd
     928        new_cmd2 = "}{\\node[draw,circle] ("
     929        new_cmd3 = ") {$"
     930        new_cmd4 = "$}\n;}"
     931        # some variables to simplify code
     932        sep = "\\&"
     933        space = " "*9
     934        sepspace = sep + space
     935        spacesep = space + sep
     936        node_to_str = lambda node: " " + node + " " * (len(space) - 1 - len(node))
     937        # # TODO:: modify how to create nodes --> new_cmd : \\node[...] in create_node
     938        num = [0]
    453939
    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
     940        def resolve(self):
     941            nodes = []; matrix = []; edges = []
     942
     943            def create_node(self):
     944                r"""
     945                create a name (infixe reading)
     946                 -> ex: b
     947                create a new command:
     948                 -> ex: \newcommand{\nodeb}{\node[draw,circle] (b) {$$};
     949                return the name and the command to build:
     950                  . the matrix
     951                  . and the edges
     952                """
     953                name = reduce(
     954                    lambda x, y: x + y,
     955                    map(
     956                        lambda x: chr(ord(x) + 49),
     957                        list(str(num[0]))),
     958                    "")
     959                node = cmd + name
     960                nodes.append((name,
     961                    (str(self.label()) if hasattr(self, "label") else ""))
     962                )
     963                num[0] += 1
     964                return node, name
     965
     966            def empty_tree():
     967                r"""
     968                TESTS::
     969
     970                    sage: t = BinaryTree()
     971                    sage: print latex(t)
     972                    { \begin{tikzpicture}[auto]
     973                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     974                             \\
     975                    };
     976                    \end{tikzpicture}}
     977                """
     978                matrix.append(space)
     979
     980            def one_node_tree(self):
     981                r"""
     982                TESTS::
     983
     984                    sage: t = BinaryTree([]); print latex(t)
     985                    { \newcommand{\nodea}{\node[draw,circle] (a) {$$}
     986                    ;}\begin{tikzpicture}[auto]
     987                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     988                     \nodea  \\
     989                    };
     990                    \end{tikzpicture}}
     991                    sage: t = OrderedTree([]); print latex(t)
     992                    { \newcommand{\nodea}{\node[draw,circle] (a) {$$}
     993                    ;}\begin{tikzpicture}[auto]
     994                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     995                     \nodea  \\
     996                    };
     997                    \end{tikzpicture}}
     998                """
     999                node, _ = create_node(self)
     1000                matrix.append(node_to_str(node))
     1001
     1002            def concat_matrix(mat, mat2):
     1003                lmat = len(mat); lmat2 = len(mat2)
     1004                for i in range(max(lmat, lmat2)):
     1005                    # mat[i] --> n & n & ...
     1006                    # mat2[i] -> n' & n' & ...
     1007                    # ==> n & n & ... & n' & n' & ...
     1008                    try:
     1009                        mat[i] += sep + mat2[i]
     1010                    except:
     1011                        if i >= lmat:
     1012                            if i != 0:
     1013                                # mat[i] doesn't exist but
     1014                                # mat[0] has k "&"
     1015                                # mat2[i] -> n' & n' & ...
     1016                                # ==> (_ &)*k+1 n' & n' & ...
     1017                                nb_of_and = mat[0].count(sep) - mat2[0].count(sep)
     1018                                mat.append(spacesep * (nb_of_and) + mat2[i])
     1019                            else:
     1020                                # mat is empty
     1021                                # mat2[i] -> n' & n' & ...
     1022                                # ==> mat2
     1023                                mat.extend(mat2)
     1024                                return
     1025                        else:
     1026                            # mat[i] -> n & n & ...
     1027                            # mat2[i] doesn't exist but mat2[0] exists
     1028                            # # and has k "&"
     1029                            # NOTE:: i != 0 because that is a no-empty subtree.
     1030                            # ==> n & n & ... (& _)*k+1
     1031                            nb_of_and = mat2[0].count(sep)
     1032                            mat[i] += sepspace * (nb_of_and + 1)
     1033
     1034            def tmp(subtree, edge, nodes, edges, matrix):
     1035                if not subtree.is_empty():
     1036                    # # create representation of the subtree
     1037                    nodes_st, matrix_st, edges_st = resolve(subtree)
     1038                    # # add its nodes to the "global" nodes set
     1039                    nodes.extend(nodes_st)
     1040                    # # create a new edge between the root and the subtree
     1041                    edge.append(nodes_st[0][0])
     1042                    # # add the subtree edges to the "global" edges set
     1043                    edges.extend(edges_st)
     1044                    # # build a new matrix by concatenation
     1045                    concat_matrix(matrix, matrix_st)
     1046                else:
     1047                    concat_matrix(matrix, [space])
     1048
     1049            def pair_nodes_tree(self, nodes, edges, matrix):
     1050                r"""
     1051                TESTS::
     1052
     1053                    sage: t = OrderedTree([[[],[]],[[],[]]]).\
     1054                    ....:     canonical_labelling(); print latex(t)
     1055                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
     1056                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
     1057                    ;}\newcommand{\nodec}{\node[draw,circle] (c) {$3$}
     1058                    ;}\newcommand{\noded}{\node[draw,circle] (d) {$4$}
     1059                    ;}\newcommand{\nodee}{\node[draw,circle] (e) {$5$}
     1060                    ;}\newcommand{\nodef}{\node[draw,circle] (f) {$6$}
     1061                    ;}\newcommand{\nodeg}{\node[draw,circle] (g) {$7$}
     1062                    ;}\begin{tikzpicture}[auto]
     1063                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     1064                             \&         \&         \& \nodea  \&         \&         \&         \\
     1065                             \& \nodeb  \&         \&         \&         \& \nodee  \&         \\
     1066                     \nodec  \&         \& \noded  \&         \& \nodef  \&         \& \nodeg  \\
     1067                    };
     1068                    <BLANKLINE>
     1069                    \path[ultra thick, red] (b) edge (c) edge (d)
     1070                        (e) edge (f) edge (g)
     1071                        (a) edge (b) edge (e);
     1072                    \end{tikzpicture}}
     1073                    sage: t = BinaryTree([[],[[],[]]]); print latex(t)
     1074                    { \newcommand{\nodea}{\node[draw,circle] (a) {$$}
     1075                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$$}
     1076                    ;}\newcommand{\nodec}{\node[draw,circle] (c) {$$}
     1077                    ;}\newcommand{\noded}{\node[draw,circle] (d) {$$}
     1078                    ;}\newcommand{\nodee}{\node[draw,circle] (e) {$$}
     1079                    ;}\begin{tikzpicture}[auto]
     1080                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     1081                             \& \nodea  \&         \&         \&         \\
     1082                     \nodeb  \&         \&         \& \nodec  \&         \\
     1083                             \&         \& \noded  \&         \& \nodee  \\
     1084                    };
     1085                    <BLANKLINE>
     1086                    \path[ultra thick, red] (c) edge (d) edge (e)
     1087                        (a) edge (b) edge (c);
     1088                    \end{tikzpicture}}
     1089                """
     1090                # build all subtree matrices.
     1091                node, name = create_node(self)
     1092                edge = [name]
     1093                split = int(len(self) / 2)
     1094                # the left part
     1095                for i in range(split):
     1096                    tmp(self[i], edge, nodes, edges, matrix)
     1097                # # prepare the root line
     1098                nb_of_and = matrix[0].count(sep)
     1099                # the middle
     1100                for i in range(len(matrix)):
     1101                    matrix[i] += sepspace
     1102                # the right part
     1103                for i in range(split, len(self)):
     1104                    tmp(self[i], edge, nodes, edges, matrix)
     1105
     1106                # # create the root line
     1107                root_line = (spacesep * (nb_of_and + 1) + node_to_str(node) +
     1108                    sepspace * (matrix[0].count(sep) - nb_of_and - 1))
     1109                matrix.insert(0, root_line)
     1110                # add edges from the root
     1111                edges.append(edge)
     1112
     1113            def odd_nodes_tree(self, nodes, edges, matrix):
     1114                r"""
     1115                TESTS::
     1116
     1117                    sage: t = OrderedTree([[]]).canonical_labelling()
     1118                    sage: print latex(t)
     1119                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
     1120                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
     1121                    ;}\begin{tikzpicture}[auto]
     1122                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     1123                     \nodea  \\
     1124                     \nodeb  \\
     1125                    };
     1126                    <BLANKLINE>
     1127                    \path[ultra thick, red] (a) edge (b);
     1128                    \end{tikzpicture}}
     1129                    sage: t = OrderedTree([[[],[]]]).canonical_labelling(); print latex(t)
     1130                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
     1131                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
     1132                    ;}\newcommand{\nodec}{\node[draw,circle] (c) {$3$}
     1133                    ;}\newcommand{\noded}{\node[draw,circle] (d) {$4$}
     1134                    ;}\begin{tikzpicture}[auto]
     1135                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     1136                             \& \nodea  \&         \\
     1137                             \& \nodeb  \&         \\
     1138                     \nodec  \&         \& \noded  \\
     1139                    };
     1140                    <BLANKLINE>
     1141                    \path[ultra thick, red] (b) edge (c) edge (d)
     1142                        (a) edge (b);
     1143                    \end{tikzpicture}}
     1144                    sage: t = OrderedTree([[[],[],[]]]).canonical_labelling(); print latex(t)
     1145                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
     1146                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
     1147                    ;}\newcommand{\nodec}{\node[draw,circle] (c) {$3$}
     1148                    ;}\newcommand{\noded}{\node[draw,circle] (d) {$4$}
     1149                    ;}\newcommand{\nodee}{\node[draw,circle] (e) {$5$}
     1150                    ;}\begin{tikzpicture}[auto]
     1151                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     1152                             \& \nodea  \&         \\
     1153                             \& \nodeb  \&         \\
     1154                     \nodec  \& \noded  \& \nodee  \\
     1155                    };
     1156                    <BLANKLINE>
     1157                    \path[ultra thick, red] (b) edge (c) edge (d) edge (e)
     1158                        (a) edge (b);
     1159                    \end{tikzpicture}}
     1160                    sage: t = OrderedTree([[[],[],[]],[],[]]).canonical_labelling(); print latex(t)
     1161                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
     1162                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
     1163                    ;}\newcommand{\nodec}{\node[draw,circle] (c) {$3$}
     1164                    ;}\newcommand{\noded}{\node[draw,circle] (d) {$4$}
     1165                    ;}\newcommand{\nodee}{\node[draw,circle] (e) {$5$}
     1166                    ;}\newcommand{\nodef}{\node[draw,circle] (f) {$6$}
     1167                    ;}\newcommand{\nodeg}{\node[draw,circle] (g) {$7$}
     1168                    ;}\begin{tikzpicture}[auto]
     1169                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     1170                             \&         \&         \& \nodea  \&         \\
     1171                             \& \nodeb  \&         \& \nodef  \& \nodeg  \\
     1172                     \nodec  \& \noded  \& \nodee  \&         \&         \\
     1173                    };
     1174                    <BLANKLINE>
     1175                    \path[ultra thick, red] (b) edge (c) edge (d) edge (e)
     1176                        (a) edge (b) edge (f) edge (g);
     1177                    \end{tikzpicture}}
     1178                """
     1179                # build all subtree matrices.
     1180                node, name = create_node(self)
     1181                edge = [name]
     1182                split = int(len(self) / 2)
     1183                # the left part
     1184                for i in range(split):
     1185                    tmp(self[i], edge, nodes, edges, matrix)
     1186                # # prepare the root line
     1187                if len(matrix) != 0:
     1188                    nb_of_and = matrix[0].count(sep)
     1189                    sizetmp = len(matrix[0])
     1190                else:
     1191                    nb_of_and = 0
     1192                    sizetmp = 0
     1193                # the middle
     1194                tmp(self[split], edge, nodes, edges, matrix)
     1195                nb_of_and += matrix[0][sizetmp:].split("node")[0].count(sep)
     1196
     1197                # the right part
     1198                for i in range(split + 1, len(self)):
     1199                    tmp(self[i], edge, nodes, edges, matrix)
     1200
     1201                # # create the root line
     1202                root_line = (spacesep * (nb_of_and) + node_to_str(node) +
     1203                    sepspace * (matrix[0].count(sep) - nb_of_and))
     1204                matrix.insert(0, root_line)
     1205                # add edges from the root
     1206                edges.append(edge)
     1207            if self.is_empty():
     1208                empty_tree()
     1209            elif len(self) == 0 or all(subtree.is_empty()
     1210                    for subtree in self):
     1211                one_node_tree(self)
     1212            elif len(self) % 2 == 0:
     1213                pair_nodes_tree(self, nodes, edges, matrix)
    4681214            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
     1215                odd_nodes_tree(self, nodes, edges, matrix)
     1216            return nodes, matrix, edges
    4891217
    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])
     1218        nodes, matrix, edges = resolve(self)
     1219
     1220        def make_cmd(nodes):
     1221            cmds = []
     1222            for name, label in nodes:
     1223                cmds.append(new_cmd1 + name + new_cmd2 +
     1224                    name + new_cmd3 +
     1225                    label + new_cmd4)
     1226            return cmds
     1227
     1228        def make_edges(edges):
     1229            all_paths = []
     1230            for edge in edges:
     1231                path = "(" + edge[0] + ")"
     1232                for i in range(1, len(edge)):
     1233                    path += " edge (%s)" % edge[i]
     1234                all_paths.append(path)
     1235            return all_paths
     1236        return ("{ " +
     1237            "".join(make_cmd(nodes)) +
     1238            begin_env +
     1239                (matrix_begin +
     1240                    "\\\\ \n".join(matrix) +
     1241                matrix_end +
     1242                ("\n" +
     1243                path_begin +
     1244                    "\n\t".join(make_edges(edges)) +
     1245                path_end if len(edges) > 0 else "")
     1246                if len(matrix) > 0 else "") +
     1247            end_env +
     1248            "}")
     1249
    4981250
    4991251class AbstractClonableTree(AbstractTree):
    5001252    """
  • sage/combinat/binary_tree.py

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