Ticket #14498: trac_14498-algorithms_trees-rebased.patch

File trac_14498-algorithms_trees-rebased.patch, 75.3 KB (added by tscrim, 6 years ago)
  • sage/combinat/abstract_tree.py

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