Ticket #14498: trac_14498_trees_EliX-jbp.patch

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

    # HG changeset patch
    # User Jean-Baptiste Priez <jbp@kerios.fr>
    # Date 1367061665 -7200
    # Node ID 2567f2c80dff342d2830df5b8b5a7e4ec4a066e5
    # Parent  3e91cc3ca6facc277fea4dad9eb017c7ac7dddd9
    several algorithms for trees and latex output
    
    diff --git a/sage/combinat/abstract_tree.py b/sage/combinat/abstract_tree.py
    a b incoherent with the data structure. 
    6767from sage.structure.list_clone import ClonableArray
    6868from sage.rings.integer import Integer
    6969from sage.misc.misc_c import prod
     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################################################################################
    7076
    7177# Unfortunately Cython forbids multiple inheritance. Therefore, we do not
    7278# inherits from SageObject to be able to inherits from Element or a subclass
    class AbstractTree(object): 
    493499        else:
    494500            return nb*prod(s.tree_factorial() for s in self)
    495501
    496     latex_unit_length   = "4mm"
    497     latex_node_diameter = "0.5"
    498     latex_root_diameter = "0.7"
    499 
    500502    def _latex_(self):
    501         """
    502         Returns a LaTeX version of ``self``
    503 
    504         EXAMPLES::
    505 
    506             sage: print(OrderedTree([[],[]])._latex_())
    507             \vcenter{\hbox{{\setlength\unitlength{4mm}
    508             \begin{picture}(4,3)
    509             \put(1,1){\circle*{0.5}}
    510             \put(2,2){\circle*{0.5}}
    511             \put(3,1){\circle*{0.5}}
    512             \put(2,2){\line(-1,-1){1}}
    513             \put(2,2){\line(1,-1){1}}
    514             \put(2,2){\circle*{0.7}}
    515             \end{picture}}}}
    516 
     503        '''
     504        Nice output which can be easily modified
     505       
    517506        TESTS::
    518 
    519             sage: OrderedTree([])._latex_()
    520             '\\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}}}}'
    521             sage: OrderedTree([[]])._latex_()
    522             '\\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}}}}'
    523             sage: OrderedTree([[], [[], [[], []], [[], []]], [[], []]])._latex_()
    524             '\\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}}}}'
    525         """
    526         from sage.misc.latex import latex
    527         drawing = [""] # allows modification of  in rec...
    528         x = [1]        # allows modification of x[0] in rec...
    529         max_label_width = [0] # allows modification of x[0] in rec...
    530         maxy = self.depth()
    531 
    532         def rec(t, y):
    533             """
    534             Draw the subtree t on the drawing, below y (included) and to
    535             the right of x[0] (included). Update x[0]. Returns the horizontal
    536             position of the root
    537             """
    538             if t.node_number() == 0 : return -1
    539             n = len(t)
    540             posChild = [rec(t[i], y+1) for i in range(n // 2)]
    541             i = n // 2
    542             if n % 2 == 1:
    543                 xc = rec(t[i], y+1)
    544                 posChild.append(xc)
    545                 i += 1
    546             else:
    547                 xc = x[0]
    548                 x[0] +=1
    549             drawing[0] = drawing[0] + "\\put(%s,%s){\\circle*{%s}}\n"%(
    550                 xc, maxy-y, self.latex_node_diameter)
    551             try:
    552                 lbl = t.label()
    553             except AttributeError:
    554                 pass
    555             else:
    556                 max_label_width[0] = 1 # TODO find a better heuristic
    557                 drawing[0] = drawing[0] + "\\put(%s,%s){$\scriptstyle %s$}"%(
    558                     xc+0.3, maxy-y-0.3, latex(lbl))
    559             posChild += [rec(t[j], y+1) for j in range(i, n)]
    560             for i in range(n):
    561                 if posChild[i] != -1:
    562                     drawing[0] = (drawing[0] +
    563                         "\\put(%s,%s){\\line(%s,-1){%s}}\n"%(
    564                             xc, maxy-y, posChild[i]-xc,
    565                             max(abs(posChild[i]-xc), 1)))
    566             return xc
    567 
    568         res = rec(self, 0)
    569         drawing[0] = drawing[0] + "\\put(%s,%s){\\circle*{%s}}\n"%(
    570             res, maxy, self.latex_root_diameter)
    571         return "\\vcenter{\hbox{{\setlength\unitlength{%s}\n\\begin{picture}(%s,%s)\n%s\\end{picture}}}}"%(
    572             self.latex_unit_length,
    573             x[0] + max_label_width[0],
    574             maxy + 1,
    575             drawing[0])
     507       
     508            sage: latex(BinaryTree([[[],[]],[[],None]]))
     509            { \newcommand{\nodea}{\node[draw,circle] (a) {$$}
     510            ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$$}
     511            ;}\newcommand{\nodec}{\node[draw,circle] (c) {$$}
     512            ;}\newcommand{\noded}{\node[draw,circle] (d) {$$}
     513            ;}\newcommand{\nodee}{\node[draw,circle] (e) {$$}
     514            ;}\newcommand{\nodef}{\node[draw,circle] (f) {$$}
     515            ;}\begin{tikzpicture}[auto]
     516            \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     517                     \&         \&         \& \nodea  \&         \&         \&         \\
     518                     \& \nodeb  \&         \&         \&         \& \nodee  \&         \\
     519             \nodec  \&         \& \noded  \&         \& \nodef  \&         \&         \\
     520            };
     521           
     522            \path[ultra thick, red] (b) edge (c) edge (d)
     523                (e) edge (f)
     524                (a) edge (b) edge (e);
     525            \end{tikzpicture}}
     526        '''
     527        # latex environnement : TikZ
     528        begin_env = "\\begin{tikzpicture}[auto]\n"
     529        end_env = "\\end{tikzpicture}"
     530        # it uses matrix trick to place each node
     531        matrix_begin = "\\matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{\n"
     532        matrix_end = "\\\\\n};\n"
     533        # a basic path to each edges
     534        path_begin = "\\path[ultra thick, red] "
     535        path_end = ";\n"
     536        # to make a pretty output, it creates one LaTeX command for
     537        # each node
     538        cmd = "\\node"
     539        new_cmd1 = "\\newcommand{" + cmd
     540        new_cmd2 = "}{\\node[draw,circle] ("
     541        new_cmd3 = ") {$"
     542        new_cmd4 = "$}\n;}"
     543        # some variables to simplify code
     544        sep = "\\&"
     545        space = " "*9
     546        sepspace = sep + space
     547        spacesep = space + sep
     548        node_to_str = lambda node : " " + node + " "*(len(space)-1-len(node))
     549        ## TODO:: modify how to create nodes --> new_cmd : \\node[...] in create_node
     550        num = [0]
     551        def resolve( self ):
     552            nodes = []; matrix = []; edges = []
     553           
     554            def create_node( self ):
     555                '''
     556                create a name (infixe reading)
     557                 -> ex: b
     558                create a new command:
     559                 -> ex: \newcommand{\nodeb}{\node[draw,circle] (b) {$$};
     560                return the name and the command to build:
     561                  . the matrix
     562                  . and the edges
     563                '''
     564                name = reduce(
     565                    lambda x,y: x+y,
     566                    map(
     567                        lambda x: chr(ord(x)+49),
     568                        list( str( num[0] ) ) ),
     569                    "")
     570                node = cmd + name
     571                nodes.append( (name,
     572                    (str( self.label() ) if hasattr( self, "label" ) else "") )
     573                )
     574                num[0] += 1
     575                return node, name
     576           
     577            def empty_tree():
     578                '''
     579                TESTS::
     580                   
     581                    sage: t = BinaryTree()
     582                    sage: print latex(t)
     583                    {\begin{tikzpicture}[auto]
     584                    \end{tikzpicture}}
     585                '''
     586                matrix.append( space )
     587            def one_node_tree( self ):
     588                '''
     589                TESTS::
     590               
     591                    sage: t = BinaryTree([]); print latex(t)
     592                    { \newcommand{\nodea}{\node[draw,circle] (a) {$$}
     593                    ;}\begin{tikzpicture}[auto]
     594                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     595                     \nodea  \\
     596                    };
     597                    \end{tikzpicture}}
     598                    sage: t = OrderedTree([]); print latex(t)
     599                    {\newcommand{\nodeb}{\node[draw,circle] (b) {$$}
     600                    ;}\begin{tikzpicture}[auto]
     601                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     602                    \nodeb\\
     603                    };
     604                    \end{tikzpicture}}
     605                '''
     606                node, _ = create_node( self )
     607                matrix.append( node_to_str ( node ))
     608            def concat_matrix( mat, mat2 ):
     609                lmat = len( mat ); lmat2 = len( mat2 )
     610                for i in range( max( lmat, lmat2 ) ):
     611                    # mat[i] --> n & n & ...
     612                    # mat2[i] -> n' & n' & ...
     613                    # ==> n & n & ... & n' & n' & ...
     614                    try: mat[i] += sep + mat2[i]
     615                    except:
     616                        if i >= lmat:
     617                            if i != 0:
     618                                # mat[i] doesn't exist but
     619                                # mat[0] has k "&"
     620                                # mat2[i] -> n' & n' & ...
     621                                # ==> (_ &)*k+1 n' & n' & ...
     622                                nb_of_and = mat[0].count( sep ) - mat2[0].count( sep )
     623                                mat.append( spacesep*(nb_of_and) + mat2[i] )
     624                            else:
     625                                # mat is empty
     626                                # mat2[i] -> n' & n' & ...
     627                                # ==> mat2
     628                                mat.extend( mat2 )
     629                                return
     630                        else:
     631                            # mat[i] -> n & n & ...
     632                            # mat2[i] doesn't exist but mat2[0] exists
     633                            ## and has k "&"
     634                            # NOTE:: i != 0 because that is a no-empty subtree.
     635                            # ==> n & n & ... (& _)*k+1
     636                            nb_of_and = mat2[0].count( sep )
     637                            mat[i] += sepspace*(nb_of_and+1)
     638            def tmp( subtree, edge, nodes, edges, matrix ):
     639                if not subtree.is_empty():
     640                    ## create representation of the subtree
     641                    nodes_st, matrix_st, edges_st = resolve( subtree )
     642                    ## add its nodes to the "global" nodes set
     643                    nodes.extend( nodes_st )
     644                    ## create a new edge between the root and the subtree
     645                    edge.append( nodes_st[0][0] )
     646                    ## add the subtree edges to the "global" edges set
     647                    edges.extend( edges_st )
     648                    ## build a new matrix by concatenation
     649                    concat_matrix(matrix, matrix_st)
     650                else: concat_matrix(matrix, [ space ])   
     651            def pair_nodes_tree( self, nodes, edges, matrix ):
     652                """
     653                TESTS::
     654               
     655                    sage: t = OrderedTree([[[],[]],[[],[]]]).canonical_labelling(); print latex(t)
     656                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
     657                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
     658                    ;}\newcommand{\nodec}{\node[draw,circle] (c) {$3$}
     659                    ;}\newcommand{\noded}{\node[draw,circle] (d) {$4$}
     660                    ;}\newcommand{\nodee}{\node[draw,circle] (e) {$5$}
     661                    ;}\newcommand{\nodef}{\node[draw,circle] (f) {$6$}
     662                    ;}\newcommand{\nodeg}{\node[draw,circle] (g) {$7$}
     663                    ;}\begin{tikzpicture}[auto]
     664                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     665                             \&         \&         \& \nodea  \&         \&         \&         \\
     666                             \& \nodeb  \&         \&         \&         \& \nodee  \&         \\
     667                     \nodec  \&         \& \noded  \&         \& \nodef  \&         \& \nodeg  \\
     668                    };
     669                    <BLANKLINE>
     670                    \path[ultra thick, red] (b) edge (c) edge (d)
     671                        (e) edge (f) edge (g)
     672                        (a) edge (b) edge (e);
     673                    \end{tikzpicture}}
     674                    sage: t = BinaryTree([[],[[],[]]]); print latex(t)
     675                    { \newcommand{\nodea}{\node[draw,circle] (a) {$$}
     676                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$$}
     677                    ;}\newcommand{\nodec}{\node[draw,circle] (c) {$$}
     678                    ;}\newcommand{\noded}{\node[draw,circle] (d) {$$}
     679                    ;}\newcommand{\nodee}{\node[draw,circle] (e) {$$}
     680                    ;}\begin{tikzpicture}[auto]
     681                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     682                             \& \nodea  \&         \&         \&         \\
     683                     \nodeb  \&         \&         \& \nodec  \&         \\
     684                             \&         \& \noded  \&         \& \nodee  \\
     685                    };
     686                    <BLANKLINE>
     687                    \path[ultra thick, red] (c) edge (d) edge (e)
     688                        (a) edge (b) edge (c);
     689                    \end{tikzpicture}}
     690                """
     691                # build all subtree matrices.
     692                node, name = create_node( self )
     693                edge = [name]
     694                split = int(len( self )/2)
     695                # the left part
     696                for i in range( split ):
     697                    tmp( self[i], edge, nodes, edges, matrix )
     698                ## prepare the root line
     699                nb_of_and = matrix[0].count( sep )
     700                # the middle
     701                for i in range( len( matrix ) ): matrix[i] += sepspace
     702                # the right part   
     703                for i in range( split, len( self ) ):
     704                    tmp( self[i], edge, nodes, edges, matrix )
     705               
     706                ## create the root line
     707                root_line = ( spacesep*(nb_of_and+1) + node_to_str(node) +
     708                    sepspace*(matrix[0].count(sep) - nb_of_and - 1) )
     709                matrix.insert(0, root_line)
     710                # add edges from the root
     711                edges.append( edge )
     712            def odd_nodes_tree( self, nodes, edges, matrix):
     713                '''
     714                TESTS::
     715               
     716                    sage: t = OrderedTree([[]]).canonical_labelling(); print latex(t)
     717                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
     718                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
     719                    ;}\begin{tikzpicture}[auto]
     720                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     721                     \nodea  \\
     722                     \nodeb  \\
     723                    };
     724                    <BLANKLINE>
     725                    \path[ultra thick, red] (a) edge (b);
     726                    \end{tikzpicture}}
     727                    sage: t = OrderedTree([[[],[]]]).canonical_labelling(); print latex(t)
     728                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
     729                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
     730                    ;}\newcommand{\nodec}{\node[draw,circle] (c) {$3$}
     731                    ;}\newcommand{\noded}{\node[draw,circle] (d) {$4$}
     732                    ;}\begin{tikzpicture}[auto]
     733                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     734                             \& \nodea  \&         \\
     735                             \& \nodeb  \&         \\
     736                     \nodec  \&         \& \noded  \\
     737                    };
     738                   
     739                    \path[ultra thick, red] (b) edge (c) edge (d)
     740                        (a) edge (b);
     741                    \end{tikzpicture}}
     742                    sage: t = OrderedTree([[[],[],[]]]).canonical_labelling(); print latex(t)
     743                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
     744                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
     745                    ;}\newcommand{\nodec}{\node[draw,circle] (c) {$3$}
     746                    ;}\newcommand{\noded}{\node[draw,circle] (d) {$4$}
     747                    ;}\newcommand{\nodee}{\node[draw,circle] (e) {$5$}
     748                    ;}\begin{tikzpicture}[auto]
     749                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     750                             \& \nodea  \&         \\
     751                             \& \nodeb  \&         \\
     752                     \nodec  \& \noded  \& \nodee  \\
     753                    };
     754                    <BLANKLINE>
     755                    \path[ultra thick, red] (b) edge (c) edge (d) edge (e)
     756                        (a) edge (b);
     757                    \end{tikzpicture}}
     758                    sage: t = OrderedTree([[[],[],[]],[],[]]).canonical_labelling(); print latex(t)
     759                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
     760                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
     761                    ;}\newcommand{\nodec}{\node[draw,circle] (c) {$3$}
     762                    ;}\newcommand{\noded}{\node[draw,circle] (d) {$4$}
     763                    ;}\newcommand{\nodee}{\node[draw,circle] (e) {$5$}
     764                    ;}\newcommand{\nodef}{\node[draw,circle] (f) {$6$}
     765                    ;}\newcommand{\nodeg}{\node[draw,circle] (g) {$7$}
     766                    ;}\begin{tikzpicture}[auto]
     767                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     768                             \&         \&         \& \nodea  \&         \\
     769                             \& \nodeb  \&         \& \nodef  \& \nodeg  \\
     770                     \nodec  \& \noded  \& \nodee  \&         \&         \\
     771                    };
     772                    <BLANKLINE>
     773                    \path[ultra thick, red] (b) edge (c) edge (d) edge (e)
     774                        (a) edge (b) edge (f) edge (g);
     775                    \end{tikzpicture}}
     776                '''
     777                # build all subtree matrices.
     778                node, name = create_node( self )
     779                edge = [name]
     780                split = int(len( self )/2)
     781                # the left part
     782                for i in range( split ):
     783                    tmp( self[i], edge, nodes, edges, matrix )
     784                ## prepare the root line
     785                if len( matrix ) != 0:
     786                    nb_of_and = matrix[0].count( sep )
     787                    sizetmp = len( matrix[0] )
     788                else:
     789                    nb_of_and = 0
     790                    sizetmp = 0
     791                # the middle
     792                tmp( self[split], edge, nodes, edges, matrix )
     793                nb_of_and += matrix[0][sizetmp:].split("node")[0].count( sep )
     794               
     795                # the right part   
     796                for i in range( split+1, len( self ) ):
     797                    tmp( self[i], edge, nodes, edges, matrix )
     798               
     799                ## create the root line
     800                root_line = ( spacesep*(nb_of_and) + node_to_str(node) +
     801                    sepspace*(matrix[0].count(sep) - nb_of_and) )
     802                matrix.insert(0, root_line)
     803                # add edges from the root
     804                edges.append( edge )
     805            if self.is_empty():
     806                empty_tree()
     807            elif len( self ) == 0 or all(subtree.is_empty() for subtree in self):
     808                one_node_tree( self )
     809            elif len( self ) % 2 == 0:
     810                pair_nodes_tree( self, nodes, edges, matrix )
     811            else:
     812                odd_nodes_tree( self, nodes, edges, matrix )
     813            return nodes, matrix, edges
     814       
     815        nodes, matrix, edges = resolve( self )
     816        def make_cmd(nodes):
     817            cmds = []
     818            for name, label in nodes:
     819                cmds.append(new_cmd1 + name + new_cmd2 +
     820                    name + new_cmd3 +
     821                    label + new_cmd4)
     822            return cmds
     823        def make_edges(edges):
     824            all_paths = []
     825            for edge in edges:
     826                path = "(" + edge[0] + ")"
     827                for i in range(1,len(edge)):
     828                    path += " edge (%s)"%edge[i]
     829                all_paths.append(path)
     830            return all_paths
     831        return ("{ " +
     832            "".join(make_cmd( nodes )) +
     833            begin_env +
     834                (matrix_begin +
     835                    "\\\\ \n".join( matrix ) +
     836                matrix_end +
     837                ("\n" +
     838                path_begin +
     839                    "\n\t".join( make_edges( edges ) ) +
     840                path_end if len(edges)>0 else "")
     841                if len(matrix) > 0 else "") +
     842            end_env +
     843            "}")
    576844
    577845class AbstractClonableTree(AbstractTree):
    578846    """
  • sage/combinat/abstract_tree.py

    # HG changeset patch
    # User Jean-Baptiste Priez <jbp@kerios.fr>
    # Date 1371904624 -7200
    # Node ID 65a277b0a89183ae4ed11500348ee3d3833a2412
    # Parent  d243efe6b1de2eaacf83ba1e4248ce2e90f6ce71
    new version with all tests tests pass of classical algorithms on trees
    (I remove the method canonical permutation)
    
    diff --git a/sage/combinat/abstract_tree.py b/sage/combinat/abstract_tree.py
    a b class AbstractTree(object): 
    107107        sage: TestSuite(BinaryTree()).run()
    108108    """
    109109
     110    def pre_order_traversal(self, action=lambda node: None):
     111        '''
     112        The depth first pre-order traversal algorithm.
     113
     114        INPUT:
     115
     116        - ``action`` -- a specific function which takes a node in input and do
     117        something during the exploration.
     118
     119        For example on the following binary tree `b`::
     120
     121              ___3____
     122             /        \
     123            1         _7_
     124             \       /   \
     125              2     5     8
     126                   / \
     127                  4   6
     128
     129        the ``depth first pre-order traversal algorithm`` explores `b` in the
     130        following order of nodes `3,1,2,7,5,4,6,8`.
     131
     132        The algorithm is::
     133
     134            manipulate the root
     135            then explore each subtrees (by the algorithm)
     136
     137        An other example::
     138
     139                __1____
     140               /  /   /
     141              2  6   8_
     142              |  |  / /
     143              3_ 7 9 10
     144             / /
     145            4 5
     146
     147        The algorithm explores this tree in the following order:
     148        `1,2,3,4,5,6,7,8,9,10`.
     149
     150        TESTS::
     151
     152            sage: l = []
     153            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).\
     154            ....:     canonical_labelling(); b
     155            3[1[., 2[., .]], 7[5[4[., .], 6[., .]], 8[., .]]]
     156            sage: b.pre_order_traversal(lambda node: l.append(node.label()))
     157            sage: l
     158            [3, 1, 2, 7, 5, 4, 6, 8]
     159            sage: t = OrderedTree([[[[],[]]],[[]],[[],[]]]).\
     160            ....:     canonical_labelling(); t
     161            1[2[3[4[], 5[]]], 6[7[]], 8[9[], 10[]]]
     162            sage: l = []
     163            sage: t.pre_order_traversal(lambda node: l.append(node.label()))
     164            sage: l
     165            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
     166            sage: l = []
     167            sage: BinaryTree().canonical_labelling().\
     168            ....:     pre_order_traversal(lambda node: l.append(node.label()))
     169            sage: l
     170            []
     171            sage: OrderedTree([]).canonical_labelling().\
     172            ....:     pre_order_traversal(lambda node: l.append(node.label()))
     173            sage: l
     174            [1]
     175        '''
     176        if self.is_empty(): return
     177        stack = []
     178        stack.append(self)
     179        while len(stack) > 0:
     180            node = stack.pop()
     181            action(node)
     182            for i in range(len(node)):
     183                subtree = node[-i - 1]
     184                if not subtree.is_empty():
     185                    stack.append(subtree)
     186
     187    def post_order_traversal(self, action=lambda node: None):
     188        '''
     189        The depth first post-order traversal algorithm.
     190
     191        INPUT:
     192
     193        - ``action`` -- a specific function which takes a node in input and do
     194        something during the exploration.
     195
     196        For example on the following binary tree `b`::
     197
     198              ___3____
     199             /        \
     200            1         _7_
     201             \       /   \
     202              2     5     8
     203                   / \
     204                  4   6
     205
     206        the ``depth first post-order traversal algorithm`` explores `b` in the
     207        following order of nodes `2,1,4,6,5,8,7,3`.
     208
     209        The algorithm is::
     210
     211            explore each subtrees (by the algorithm)
     212            then manipulate the root
     213
     214        Another example::
     215
     216                __1____
     217               /  /   /
     218              2  6   8_
     219              |  |  / /
     220              3_ 7 9 10
     221             / /
     222            4 5
     223
     224        The algorithm explorer this tree in the following order:
     225        `4,5,3,2,7,6,9,10,8,1`.
     226
     227        TESTS::
     228
     229            sage: l = []
     230            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).\
     231            ....:     canonical_labelling(); b
     232            3[1[., 2[., .]], 7[5[4[., .], 6[., .]], 8[., .]]]
     233            sage: b.post_order_traversal(lambda node: l.append(node.label()))
     234            sage: l
     235            [2, 1, 4, 6, 5, 8, 7, 3]
     236            sage: t = OrderedTree([[[[],[]]],[[]],[[],[]]]).\
     237            ....:     canonical_labelling(); t
     238            1[2[3[4[], 5[]]], 6[7[]], 8[9[], 10[]]]
     239            sage: l = []
     240            sage: t.post_order_traversal(lambda node: l.append(node.label()))
     241            sage: l
     242            [4, 5, 3, 2, 7, 6, 9, 10, 8, 1]
     243            sage: l = []
     244            sage: BinaryTree().canonical_labelling().\
     245            ....:     post_order_traversal(lambda node: l.append(node.label()))
     246            sage: l
     247            []
     248            sage: OrderedTree([]).canonical_labelling().\
     249            ....:     post_order_traversal(lambda node: l.append(node.label()))
     250            sage: l
     251            [1]
     252        '''
     253        if self.is_empty(): return
     254        for subtree in self:
     255            subtree.post_order_traversal(action)
     256        action(self)
     257
     258    def breadth_first_order_traversal(self, action=lambda node: None):
     259        '''
     260        The breadth first order traversal algorithm.
     261
     262        INPUT:
     263
     264        - ``action`` -- a specific function which takes a node in input and do
     265        something during the exploration.
     266
     267        For example on the following binary tree `b`::
     268
     269              ___3____
     270             /        \
     271            1         _7_
     272             \       /   \
     273              2     5     8
     274                   / \
     275                  4   6
     276
     277        the ``breadth first order traversal algorithm`` explores `b` in the
     278        following order of nodes `3,1,7,2,5,8,4,6`.
     279
     280        The algorithm is::
     281
     282            queue <- ( root )
     283            while the queue is not empty:
     284                node <- pop( queue )
     285                manipulate the node
     286                append in the queue all subtrees of the node
     287
     288        TESTS::
     289
     290            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).\
     291            ....:     canonical_labelling()
     292            sage: l = []
     293            sage: b.breadth_first_order_traversal(
     294            ....:     lambda node: l.append(node.label()))
     295            sage: l
     296            [3, 1, 7, 2, 5, 8, 4, 6]
     297            sage: t = OrderedTree([[[[],[]]],[[]],[[],[]]]).\
     298            ....:     canonical_labelling(); t
     299            1[2[3[4[], 5[]]], 6[7[]], 8[9[], 10[]]]
     300            sage: l = []
     301            sage: t.breadth_first_order_traversal(
     302            ....:     lambda node: l.append(node.label()))
     303            sage: l
     304            [1, 2, 6, 8, 3, 7, 9, 10, 4, 5]
     305            sage: l = []
     306            sage: BinaryTree().canonical_labelling().\
     307            ....:     breadth_first_order_traversal(
     308            ....:         lambda node: l.append(node.label()))
     309            sage: l
     310            []
     311            sage: OrderedTree([]).canonical_labelling().\
     312            ....:     breadth_first_order_traversal(
     313            ....:         lambda node: l.append(node.label()))
     314            sage: l
     315            [1]
     316        '''
     317        if self.is_empty(): return
     318        queue = []
     319        queue.append(self)
     320        while len(queue) > 0:
     321            node = queue.pop()
     322            action(node)
     323            for subtree in node:
     324                if not subtree.is_empty():
     325                    queue.insert(0, subtree)
     326
    110327    def subtrees(self):
    111328        """
    112329        Returns a generator for all subtrees of ``self``
  • sage/combinat/binary_tree.py

    diff --git a/sage/combinat/binary_tree.py b/sage/combinat/binary_tree.py
    a b class BinaryTree(AbstractClonableTree, C 
    131131         """
    132132        return BinaryTrees_all()
    133133
    134     def __init__(self, parent, children = None, check = True):
     134    def __init__(self, parent, children=None, check=True):
    135135        """
    136136        TESTS::
    137137
    class BinaryTree(AbstractClonableTree, C 
    147147            True
    148148        """
    149149        if (type(children) is str):  # if the input is the repr of a binary tree
    150             children = children.replace(".","None")
     150            children = children.replace(".", "None")
    151151            from ast import literal_eval
    152152            children = literal_eval(children)
    153153        if children is None:
    class BinaryTree(AbstractClonableTree, C 
    195195            return "."
    196196        else:
    197197            return super(BinaryTree, self)._repr_()
    198        
    199     def _ascii_art_( self ):
     198
     199    def _ascii_art_(self):
    200200        r"""
    201201        TESTS::
    202202
    class BinaryTree(AbstractClonableTree, C 
    349349                o   o   o   o
    350350        """
    351351        node_to_str = lambda bt: str(bt.label()) if hasattr(bt, "label") else "o"
    352        
     352
    353353        if self.is_empty():
    354354            from sage.misc.ascii_art import empty_ascii_art
    355355            return empty_ascii_art
    356356
    357357        from sage.misc.ascii_art import AsciiArt
    358358        if self[0].is_empty() and self[1].is_empty():
    359             bt_repr = AsciiArt( [node_to_str(self)] )
     359            bt_repr = AsciiArt([node_to_str(self)])
    360360            bt_repr._root = 1
    361361            return bt_repr
    362362        if self[0].is_empty():
    363363            node = node_to_str(self)
    364364            rr_tree = self[1]._ascii_art_()
    365365            if rr_tree._root > 2:
    366                 f_line = " " ** Integer( rr_tree._root - 3 ) + node
    367                 s_line = " " ** Integer( len( node ) + rr_tree._root - 3 ) + "\\"
    368                 t_repr = AsciiArt( [f_line, s_line] ) * rr_tree
     366                f_line = " " ** Integer(rr_tree._root - 3) + node
     367                s_line = " " ** Integer(len(node) + rr_tree._root - 3) + "\\"
     368                t_repr = AsciiArt([f_line, s_line]) * rr_tree
    369369                t_repr._root = rr_tree._root - 2
    370370            else:
    371371                f_line = node
    372372                s_line = " " + "\\"
    373                 t_line = " " ** Integer( len( node ) + 1 )
    374                 t_repr = AsciiArt( [f_line, s_line] ) * ( AsciiArt( [t_line] ) + rr_tree )
     373                t_line = " " ** Integer(len(node) + 1)
     374                t_repr = AsciiArt([f_line, s_line]) * (AsciiArt([t_line]) + rr_tree)
    375375                t_repr._root = rr_tree._root
    376376            t_repr._baseline = t_repr._h - 1
    377377            return t_repr
    378378        if self[1].is_empty():
    379379            node = node_to_str(self)
    380380            lr_tree = self[0]._ascii_art_()
    381             f_line = " " ** Integer( lr_tree._root + 1 ) + node
    382             s_line = " " ** Integer( lr_tree._root ) + "/"
    383             t_repr = AsciiArt( [f_line, s_line] ) * lr_tree
     381            f_line = " " ** Integer(lr_tree._root + 1) + node
     382            s_line = " " ** Integer(lr_tree._root) + "/"
     383            t_repr = AsciiArt([f_line, s_line]) * lr_tree
    384384            t_repr._root = lr_tree._root + 2
    385385            t_repr._baseline = t_repr._h - 1
    386386            return t_repr
    class BinaryTree(AbstractClonableTree, C 
    388388        lr_tree = self[0]._ascii_art_()
    389389        rr_tree = self[1]._ascii_art_()
    390390        nb_ = lr_tree._l - lr_tree._root + rr_tree._root - 1
    391         nb_L = int( nb_ / 2 )
    392         nb_R = nb_L + ( 1 if nb_ % 2 == 1 else 0 )
    393         f_line = " " ** Integer( lr_tree._root + 1 ) + "_" ** Integer( nb_L ) + node
    394         f_line += "_" ** Integer( nb_R )
    395         s_line = " " ** Integer( lr_tree._root ) + "/" + " " ** Integer( len( node ) + rr_tree._root - 1 + ( lr_tree._l - lr_tree._root ) ) + "\\"
    396         t_repr = AsciiArt( [f_line, s_line] ) * ( lr_tree + AsciiArt( [" " ** Integer( len( node ) + 2 )] ) + rr_tree )
     391        nb_L = int(nb_ / 2)
     392        nb_R = nb_L + (1 if nb_ % 2 == 1 else 0)
     393        f_line = " " ** Integer(lr_tree._root + 1) + "_" ** Integer(nb_L) + node
     394        f_line += "_" ** Integer(nb_R)
     395        s_line = " " ** Integer(lr_tree._root) + "/" + " " ** Integer(len(node) + rr_tree._root - 1 + (lr_tree._l - lr_tree._root)) + "\\"
     396        t_repr = AsciiArt([f_line, s_line]) * (lr_tree + AsciiArt([" " ** Integer(len(node) + 2)]) + rr_tree)
    397397        t_repr._root = lr_tree._root + nb_L + 2
    398398        t_repr._baseline = t_repr._h - 1
    399399        return t_repr
    class BinaryTree(AbstractClonableTree, C 
    435435            if not tr:
    436436                return
    437437            else:
    438                 nbl = 2*tr[0].node_number() + 1
    439                 res.add_edges([[idx,idx+1], [idx,idx+1+nbl]])
     438                nbl = 2 * tr[0].node_number() + 1
     439                res.add_edges([[idx, idx + 1], [idx, idx + 1 + nbl]])
    440440                rec(tr[0], idx + 1)
    441441                rec(tr[1], idx + nbl + 1)
    442442        rec(self, 0)
    443443        return res
    444444
    445     def canonical_labelling(self,shift=1):
     445    def canonical_labelling(self, shift=1):
    446446        """
    447447        Return a labelled version of ``self``.
    448448
    class BinaryTree(AbstractClonableTree, C 
    464464        if self:
    465465            sz0 = self[0].node_number()
    466466            return LTR([self[0].canonical_labelling(shift),
    467                         self[1].canonical_labelling(shift+1+sz0)],
    468                        label=shift+sz0)
     467                        self[1].canonical_labelling(shift + 1 + sz0)],
     468                       label=shift + sz0)
    469469        else:
    470470            return LTR(None)
    471471
    class BinaryTree(AbstractClonableTree, C 
    478478        """
    479479        self.graph().show(layout='tree', tree_root=0, tree_orientation="down")
    480480
    481     def make_node(self, child_list = [None, None]):
     481    def make_node(self, child_list=[None, None]):
    482482        """
    483483        Modify ``self`` so that it becomes a node with children ``childlist``
    484484
    class BinaryTree(AbstractClonableTree, C 
    563563            w = []
    564564            for l in usemap:
    565565                if l == "L": w += self[0]._to_dyck_word_rec(usemap)
    566                 elif l == "R": w+=self[1]._to_dyck_word_rec(usemap)
    567                 elif l == "1": w+=[1]
    568                 elif l == "0": w+=[0]
     566                elif l == "R": w += self[1]._to_dyck_word_rec(usemap)
     567                elif l == "1": w += [1]
     568                elif l == "0": w += [0]
    569569            return w
    570570        else:
    571571            return []
    572572
    573     @combinatorial_map(name = "to the Tamari corresponding Dyck path")
     573    @combinatorial_map(name="to the Tamari corresponding Dyck path")
    574574    def to_dyck_word_tamari(self):
    575575        r"""
    576576        Return the Dyck word associated with ``self`` in consistency with
    class BinaryTree(AbstractClonableTree, C 
    649649        """
    650650        from sage.combinat.dyck_word import DyckWord
    651651        if usemap not in ["1L0R", "1R0L", "L1R0", "R1L0"]:
    652             raise ValueError, "%s is not a correct map"%(usemap)
     652            raise ValueError, "%s is not a correct map" % (usemap)
    653653        return DyckWord(self._to_dyck_word_rec(usemap))
    654        
     654
    655655    def _to_ordered_tree(self, bijection="left", root=None):
    656656        r"""
    657657        Internal recursive method to obtain an ordered tree from a binary
    class BinaryTree(AbstractClonableTree, C 
    680680            root = OrderedTree().clone()
    681681            close_root = True
    682682        if(self):
    683             left, right = self[0],self[1]
     683            left, right = self[0], self[1]
    684684            if(bijection == "left"):
    685                 root = left._to_ordered_tree(bijection=bijection,root=root)
    686                 root.append(right._to_ordered_tree(bijection=bijection,root=None))
    687             elif(bijection =="right"):
     685                root = left._to_ordered_tree(bijection=bijection, root=root)
     686                root.append(right._to_ordered_tree(bijection=bijection, root=None))
     687            elif(bijection == "right"):
    688688                root.append(left._to_ordered_tree(bijection=bijection, root=None))
    689                 root = right._to_ordered_tree(bijection=bijection,root=root)
     689                root = right._to_ordered_tree(bijection=bijection, root=root)
    690690            else:
    691691                raise ValueError("the bijection argument should be either left or right")
    692692        if(close_root):
    class BinaryTree(AbstractClonableTree, C 
    713713            [[], [[], []], [[], [[]]]]
    714714        """
    715715        return self._to_ordered_tree()
    716    
     716
    717717    @combinatorial_map(name="To ordered tree, right child = right brother")
    718718    def to_ordered_tree_right_branch(self):
    719719        r"""
    class BinaryTree(AbstractClonableTree, C 
    734734            [[[[]], [[]]], [[]], []]
    735735        """
    736736        return self._to_ordered_tree(bijection="right")
    737    
    738     @combinatorial_map(order = 2, name="Left-right symmetry")
     737
     738    @combinatorial_map(order=2, name="Left-right symmetry")
    739739    def left_right_symmetry(self):
    740740        r"""
    741741        Return the left-right symmetrized tree of ``self``.
    class BinaryTree(AbstractClonableTree, C 
    752752        """
    753753        if not self:
    754754            return None
    755         tree = [self[1].left_right_symmetry(),self[0].left_right_symmetry()]
     755        tree = [self[1].left_right_symmetry(), self[0].left_right_symmetry()]
    756756        if(not self in LabelledBinaryTrees()):
    757757            return BinaryTree(tree)
    758         return LabelledBinaryTree(tree, label = self.label())
     758        return LabelledBinaryTree(tree, label=self.label())
    759759
    760760    @combinatorial_map(order=2, name="Left border symmetry")
    761761    def left_border_symmetry(self):
    class BinaryTree(AbstractClonableTree, C 
    793793        tree = BinaryTree()
    794794        for r in border:
    795795            if labelled:
    796                 tree = LabelledBinaryTree([tree,r],label=labels.pop(0))
     796                tree = LabelledBinaryTree([tree, r], label=labels.pop(0))
    797797            else:
    798                 tree = BinaryTree([tree,r])
     798                tree = BinaryTree([tree, r])
    799799        return tree
    800800
    801801    def canopee(self):
    class BinaryTree(AbstractClonableTree, C 
    863863                if tr[i]:
    864864                    add_leaf_rec(tr[i])
    865865                else:
    866                     res.append(1-i)
     866                    res.append(1 - i)
    867867        add_leaf_rec(self)
    868868        return res[1:-1]
    869        
     869
     870    def in_order_traversal(self,
     871        node_action=lambda node: None,
     872        leaf_action=lambda leaf: None
     873    ):
     874        '''
     875        The depth first infix-order traversal algorithm.
     876
     877        For example on the following binary tree `b` where we denote leafs by
     878        `a,b,c...` and nodes by `1,2,3...`::
     879
     880                ____3____
     881               /         \
     882              1          __7__
     883             / \        /     \
     884            a   2      _5_     8
     885               / \    /   \   / \
     886              b   c  4     6 h   i
     887                    / \   / \
     888                   d   e f   g
     889
     890        the ``depth first infixe-order traversal algorithm`` explores `b` in
     891        the following order of nodes `a,1,b,2,c,3,d,4,e,5,f,6,g,7,h,8,i`.
     892
     893        The algorithm is::
     894
     895            explore the left subtree
     896            manipulate the root
     897            explore the right subtree
     898
     899        TESTS::
     900
     901            sage: nb_leaf = 0
     902            sage: def l_action(_):
     903            ....:    global nb_leaf
     904            ....:    nb_leaf += 1
     905            sage: nb_node = 0
     906            sage: def n_action(_):
     907            ....:    global nb_node
     908            ....:    nb_node += 1
     909            sage: BinaryTree().in_order_traversal(n_action, l_action)
     910            sage: nb_leaf, nb_node
     911            (1, 0)
     912            sage: nb_leaf, nb_node = 0, 0
     913            sage: b = BinaryTree([[],[[],[]]]); b
     914            [[., .], [[., .], [., .]]]
     915            sage: b.in_order_traversal(n_action, l_action)
     916            sage: nb_leaf, nb_node
     917            (6, 5)
     918            sage: nb_leaf, nb_node = 0, 0
     919            sage: b = b.canonical_labelling()
     920            sage: b.in_order_traversal(n_action, l_action)
     921            sage: nb_leaf, nb_node
     922            (6, 5)
     923            sage: l = []
     924            sage: b.in_order_traversal(lambda node: l.append( node.label() ))
     925            sage: l
     926            [1, 2, 3, 4, 5]
     927            sage: leaf = 'a'
     928            sage: l = []
     929            sage: def l_action(_):
     930            ....:    global leaf, l
     931            ....:    l.append(leaf)
     932            ....:    leaf = chr( ord(leaf)+1 )
     933            sage: n_action = lambda node: l.append( node.label() )
     934            sage: b = BinaryTree([[None,[]],[[[],[]],[]]]).\
     935            ....:     canonical_labelling()
     936            sage: b.in_order_traversal(n_action, l_action)
     937            sage: l
     938            ['a', 1, 'b', 2, 'c', 3, 'd', 4, 'e', 5, 'f', 6, 'g', 7, 'h', 8, 'i']
     939        '''
     940        if self.is_empty():
     941            leaf_action(self)
     942            return
     943        self[0].in_order_traversal(node_action, leaf_action)
     944        node_action(self)
     945        self[1].in_order_traversal(node_action, leaf_action)
     946
     947    def right_rotate(self):
     948        '''
     949        Right rotation operation of tree::
     950
     951                o                     _o_
     952               /                     /   \
     953              o    -right-rotate->  o     o
     954             / \                         /
     955            o   o                       o
     956            <BLANKLINE>
     957                  __o__                         _o__
     958                 /     \                       /    \
     959                o       o  -right-rotate->    o     _o_
     960               / \                           /     /   \
     961              o   o                         o     o     o
     962             /     \                               \
     963            o       o                               o
     964
     965        TESTS::
     966
     967            sage: b = BinaryTree([[[],[]], None]); ascii_art(b)
     968                o
     969               /
     970              o
     971             / \
     972            o   o
     973            sage: ascii_art(b.right_rotate())
     974              _o_
     975             /   \
     976            o     o
     977                 /
     978                o
     979            sage: b = BinaryTree([[[[],None],[None,[]]], []]);ascii_art(b)
     980                  __o__
     981                 /     \
     982                o       o
     983               / \
     984              o   o
     985             /     \
     986            o       o
     987            sage: ascii_art(b.right_rotate())
     988                _o__
     989               /    \
     990              o     _o_
     991             /     /   \
     992            o     o     o
     993                   \
     994                    o
     995        '''
     996        B = self.parent()._element_constructor_
     997        return B([self[0][0], B([self[0][1], self[1]])])
     998
     999    def left_rotate(self):
     1000        '''
     1001        Left rotation operation of tree::
     1002
     1003              _o_                        o
     1004             /   \                      /
     1005            o     o  -left-rotate->    o
     1006                 /                    / \
     1007                o                    o   o
     1008            <BLANKLINE>
     1009                  __o__                            o
     1010                 /     \                          /
     1011                o       o  -left-rotate->        o
     1012               / \                              /
     1013              o   o                            o
     1014             /     \                          / \
     1015            o       o                        o   o
     1016                                            /     \
     1017                                           o       o
     1018
     1019
     1020        TESTS::
     1021
     1022            sage: b = BinaryTree([[],[[],None]]); ascii_art(b)
     1023              _o_
     1024             /   \
     1025            o     o
     1026                 /
     1027                o
     1028            sage: ascii_art(b.left_rotate())
     1029                o
     1030               /
     1031              o
     1032             / \
     1033            o   o
     1034            sage: b.left_rotate().right_rotate() == b
     1035            True
     1036        '''
     1037        B = self.parent()._element_constructor_
     1038        return B([B([self[0], self[1][0]]), self[1][1]])
    8701039
    8711040
    8721041from sage.structure.parent import Parent
    class BinaryTrees_all(DisjointUnionEnume 
    9771146            """
    9781147        DisjointUnionEnumeratedSets.__init__(
    9791148            self, Family(NonNegativeIntegers(), BinaryTrees_size),
    980             facade=True, keepkey = False)
     1149            facade=True, keepkey=False)
    9811150
    9821151    def _repr_(self):
    9831152        """
    class BinaryTrees_size(BinaryTrees): 
    10751244            sage: S is BinaryTrees(3)
    10761245            True
    10771246        """
    1078         super(BinaryTrees_size, self).__init__(category = FiniteEnumeratedSets())
     1247        super(BinaryTrees_size, self).__init__(category=FiniteEnumeratedSets())
    10791248        self._size = size
    10801249
    10811250    def _repr_(self):
    class BinaryTrees_size(BinaryTrees): 
    10851254            sage: BinaryTrees(3)   # indirect doctest
    10861255            Binary trees of size 3
    10871256        """
    1088         return "Binary trees of size %s"%(self._size)
     1257        return "Binary trees of size %s" % (self._size)
    10891258
    10901259    def __contains__(self, x):
    10911260        """
    class BinaryTrees_size(BinaryTrees): 
    11431312        else:
    11441313            for i in range(0, self._size):
    11451314                for lft in self.__class__(i):
    1146                     for rgt in self.__class__(self._size-1-i):
     1315                    for rgt in self.__class__(self._size - 1 - i):
    11471316                        yield self._element_constructor_([lft, rgt])
    11481317
    11491318    @lazy_attribute
    class LabelledBinaryTree(AbstractLabelle 
    12581427            else:
    12591428                return "."
    12601429        else:
    1261             return "%s%s"%(self._label, self[:])
     1430            return "%s%s" % (self._label, self[:])
    12621431
    12631432    def binary_search_insert(self, letter):
    12641433        """
    class LabelledBinaryTree(AbstractLabelle 
    12881457        """
    12891458        LT = self.parent()._element_constructor_
    12901459        if not self:
    1291             return LT([], label = letter)
     1460            return LT([], label=letter)
    12921461        else:
    12931462            if letter <= self.label():
    12941463                fils = self[0].binary_search_insert(letter)
    class LabelledBinaryTree(AbstractLabelle 
    12971466                fils = self[1].binary_search_insert(letter)
    12981467                return LT([self[0], fils], label=self.label())
    12991468
     1469    def right_rotate(self):
     1470        '''
     1471        Right rotation operation of tree::
     1472
     1473                y                      x
     1474               / \                    / \
     1475              x   C -right-rotate->  A   y
     1476             / \                        / \
     1477            A   B                      B   C
     1478
     1479        TESTS::
     1480
     1481            sage: LB = LabelledBinaryTree
     1482            sage: b = LB([LB([LB([],"A"), LB([],"B")],"x"),LB([],"C")], "y"); b
     1483            y[x[A[., .], B[., .]], C[., .]]
     1484            sage: b.right_rotate()
     1485            x[A[., .], y[B[., .], C[., .]]]
     1486        '''
     1487        B = self.parent()._element_constructor_
     1488        return B([
     1489            self[0][0],
     1490            B([self[0][1], self[1]], self.label())
     1491        ], self[0].label())
     1492
     1493    def left_rotate(self):
     1494        '''
     1495        Right rotation operation of tree::
     1496
     1497                y                    x
     1498               / \                  / \
     1499              x   C <-left-rotate- A   y
     1500             / \                      / \
     1501            A   B                    B   C
     1502
     1503
     1504        TESTS::
     1505
     1506            sage: LB = LabelledBinaryTree
     1507            sage: b = LB([LB([LB([],"A"), LB([],"B")],"x"),LB([],"C")], "y"); b
     1508            y[x[A[., .], B[., .]], C[., .]]
     1509            sage: b == b.right_rotate().left_rotate()
     1510            True
     1511        '''
     1512        B = self.parent()._element_constructor_
     1513        return B([
     1514            B([self[0], self[1][0]], self.label()),
     1515            self[1][1]
     1516        ], self[1].label())
     1517
    13001518    _UnLabelled = BinaryTree
    13011519
    13021520
    class LabelledBinaryTrees(LabelledOrdere 
    13241542            toto[42[3[., .], 3[., .]], 5[None[., .], None[., .]]]
    13251543        """
    13261544        LT = self._element_constructor_
    1327         t  = LT([], label = 3)
    1328         t1 = LT([t,t], label = 42)
    1329         t2  = LT([[], []], label = 5)
    1330         return LT([t1,t2], label = "toto")
     1545        t = LT([], label=3)
     1546        t1 = LT([t, t], label=42)
     1547        t2 = LT([[], []], label=5)
     1548        return LT([t1, t2], label="toto")
    13311549
    13321550    def unlabelled_trees(self):
    13331551        """
  • sage/combinat/abstract_tree.py

    # HG changeset patch
    # User Jean-Baptiste Priez <jbp@kerios.fr>
    # Date 1371912857 -7200
    # Node ID 2fcaf474f25b268239721eb249e849728b69a547
    # Parent  a2e8776e2971460fcbba65f26fb49234e8f3813c
    documentation + test for trees algorithms
    + pep8 latex
    
    diff --git a/sage/combinat/abstract_tree.py b/sage/combinat/abstract_tree.py
    a b incoherent with the data structure. 
    6161
    6262- Florent Hivert (2010-2011): initial revision
    6363- Frédéric Chapoton (2011): contributed some methods
     64- Jean-Baptiste Priez (2013): several transversal algorithms
    6465"""
    6566
    6667from sage.structure.list_clone import ClonableArray
    class AbstractTree(object): 
    137138
    138139        The algorithm is::
    139140
    140             manipulate the root
     141            manipulate the root with function `action`
    141142            then explore each subtrees (by the algorithm)
    142143
    143144        An other example::
    class AbstractTree(object): 
    215216        The algorithm is::
    216217
    217218            explore each subtrees (by the algorithm)
    218             then manipulate the root
     219            then manipulate the root with function `action`
    219220
    220221        Another example::
    221222
    class AbstractTree(object): 
    288289            queue <- ( root )
    289290            while the queue is not empty:
    290291                node <- pop( queue )
    291                 manipulate the node
     292                manipulate the node with function `action`
    292293                append in the queue all subtrees of the node
    293294
    294295        TESTS::
    class AbstractTree(object): 
    641642    def _latex_(self):
    642643        '''
    643644        Nice output which can be easily modified
    644        
     645
    645646        TESTS::
    646        
     647
    647648            sage: latex(BinaryTree([[[],[]],[[],None]]))
    648649            { \newcommand{\nodea}{\node[draw,circle] (a) {$$}
    649650            ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$$}
    class AbstractTree(object): 
    653654            ;}\newcommand{\nodef}{\node[draw,circle] (f) {$$}
    654655            ;}\begin{tikzpicture}[auto]
    655656            \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
    656                      \&         \&         \& \nodea  \&         \&         \&         \\ 
    657                      \& \nodeb  \&         \&         \&         \& \nodee  \&         \\ 
     657                     \&         \&         \& \nodea  \&         \&         \&         \\
     658                     \& \nodeb  \&         \&         \&         \& \nodee  \&         \\
    658659             \nodec  \&         \& \noded  \&         \& \nodef  \&         \&         \\
    659660            };
    660            
     661            <BLANKLINE>
    661662            \path[ultra thick, red] (b) edge (c) edge (d)
    662663                (e) edge (f)
    663664                (a) edge (b) edge (e);
    class AbstractTree(object): 
    684685        space = " "*9
    685686        sepspace = sep + space
    686687        spacesep = space + sep
    687         node_to_str = lambda node : " " + node + " "*(len(space)-1-len(node))
     688        node_to_str = lambda node: " " + node + " " * (len(space) - 1 - len(node))
    688689        ## TODO:: modify how to create nodes --> new_cmd : \\node[...] in create_node
    689690        num = [0]
    690         def resolve( self ):
     691
     692        def resolve(self):
    691693            nodes = []; matrix = []; edges = []
    692            
    693             def create_node( self ):
     694
     695            def create_node(self):
    694696                '''
    695697                create a name (infixe reading)
    696698                 -> ex: b
    class AbstractTree(object): 
    701703                  . and the edges
    702704                '''
    703705                name = reduce(
    704                     lambda x,y: x+y,
     706                    lambda x, y: x + y,
    705707                    map(
    706                         lambda x: chr(ord(x)+49),
    707                         list( str( num[0] ) ) ),
     708                        lambda x: chr(ord(x) + 49),
     709                        list(str(num[0]))),
    708710                    "")
    709711                node = cmd + name
    710                 nodes.append( (name,
    711                     (str( self.label() ) if hasattr( self, "label" ) else "") )
     712                nodes.append((name,
     713                    (str(self.label()) if hasattr(self, "label") else ""))
    712714                )
    713715                num[0] += 1
    714716                return node, name
    715            
     717
    716718            def empty_tree():
    717719                '''
    718720                TESTS::
    719                    
     721
    720722                    sage: t = BinaryTree()
    721                     sage: print latex(t)
    722                     {\begin{tikzpicture}[auto]
     723                    sage: print latex(t)
     724                    { \begin{tikzpicture}[auto]
     725                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
     726                             \\
     727                    };
    723728                    \end{tikzpicture}}
    724729                '''
    725                 matrix.append( space )
    726             def one_node_tree( self ):
     730                matrix.append(space)
     731
     732            def one_node_tree(self):
    727733                '''
    728734                TESTS::
    729                
     735
    730736                    sage: t = BinaryTree([]); print latex(t)
    731737                    { \newcommand{\nodea}{\node[draw,circle] (a) {$$}
    732738                    ;}\begin{tikzpicture}[auto]
    class AbstractTree(object): 
    735741                    };
    736742                    \end{tikzpicture}}
    737743                    sage: t = OrderedTree([]); print latex(t)
    738                     {\newcommand{\nodeb}{\node[draw,circle] (b) {$$}
     744                    { \newcommand{\nodea}{\node[draw,circle] (a) {$$}
    739745                    ;}\begin{tikzpicture}[auto]
    740746                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
    741                     \nodeb\\
     747                     \nodea  \\
    742748                    };
    743749                    \end{tikzpicture}}
    744750                '''
    745                 node, _ = create_node( self )
    746                 matrix.append( node_to_str ( node ))
    747             def concat_matrix( mat, mat2 ):
    748                 lmat = len( mat ); lmat2 = len( mat2 )
    749                 for i in range( max( lmat, lmat2 ) ):
     751                node, _ = create_node(self)
     752                matrix.append(node_to_str (node))
     753
     754            def concat_matrix(mat, mat2):
     755                lmat = len(mat); lmat2 = len(mat2)
     756                for i in range(max(lmat, lmat2)):
    750757                    # mat[i] --> n & n & ...
    751758                    # mat2[i] -> n' & n' & ...
    752759                    # ==> n & n & ... & n' & n' & ...
    753                     try: mat[i] += sep + mat2[i]
     760                    try:
     761                        mat[i] += sep + mat2[i]
    754762                    except:
    755763                        if i >= lmat:
    756764                            if i != 0:
    class AbstractTree(object): 
    758766                                # mat[0] has k "&"
    759767                                # mat2[i] -> n' & n' & ...
    760768                                # ==> (_ &)*k+1 n' & n' & ...
    761                                 nb_of_and = mat[0].count( sep ) - mat2[0].count( sep )
    762                                 mat.append( spacesep*(nb_of_and) + mat2[i] )
    763                             else: 
     769                                nb_of_and = mat[0].count(sep) - mat2[0].count(sep)
     770                                mat.append(spacesep * (nb_of_and) + mat2[i])
     771                            else:
    764772                                # mat is empty
    765773                                # mat2[i] -> n' & n' & ...
    766774                                # ==> mat2
    767                                 mat.extend( mat2 )
     775                                mat.extend(mat2)
    768776                                return
    769777                        else:
    770778                            # mat[i] -> n & n & ...
    class AbstractTree(object): 
    772780                            ## and has k "&"
    773781                            # NOTE:: i != 0 because that is a no-empty subtree.
    774782                            # ==> n & n & ... (& _)*k+1
    775                             nb_of_and = mat2[0].count( sep )
    776                             mat[i] += sepspace*(nb_of_and+1)
    777             def tmp( subtree, edge, nodes, edges, matrix ):
     783                            nb_of_and = mat2[0].count(sep)
     784                            mat[i] += sepspace * (nb_of_and + 1)
     785
     786            def tmp(subtree, edge, nodes, edges, matrix):
    778787                if not subtree.is_empty():
    779788                    ## create representation of the subtree
    780                     nodes_st, matrix_st, edges_st = resolve( subtree )
     789                    nodes_st, matrix_st, edges_st = resolve(subtree)
    781790                    ## add its nodes to the "global" nodes set
    782                     nodes.extend( nodes_st )
     791                    nodes.extend(nodes_st)
    783792                    ## create a new edge between the root and the subtree
    784                     edge.append( nodes_st[0][0] )
     793                    edge.append(nodes_st[0][0])
    785794                    ## add the subtree edges to the "global" edges set
    786                     edges.extend( edges_st )
     795                    edges.extend(edges_st)
    787796                    ## build a new matrix by concatenation
    788797                    concat_matrix(matrix, matrix_st)
    789                 else: concat_matrix(matrix, [ space ])   
    790             def pair_nodes_tree( self, nodes, edges, matrix ):
     798                else:
     799                    concat_matrix(matrix, [space])
     800
     801            def pair_nodes_tree(self, nodes, edges, matrix):
    791802                """
    792803                TESTS::
    793                
    794                     sage: t = OrderedTree([[[],[]],[[],[]]]).canonical_labelling(); print latex(t)
     804
     805                    sage: t = OrderedTree([[[],[]],[[],[]]]).\
     806                    ....:     canonical_labelling(); print latex(t)
    795807                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
    796808                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
    797809                    ;}\newcommand{\nodec}{\node[draw,circle] (c) {$3$}
    class AbstractTree(object): 
    818830                    ;}\newcommand{\nodee}{\node[draw,circle] (e) {$$}
    819831                    ;}\begin{tikzpicture}[auto]
    820832                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
    821                              \& \nodea  \&         \&         \&         \\ 
    822                      \nodeb  \&         \&         \& \nodec  \&         \\ 
     833                             \& \nodea  \&         \&         \&         \\
     834                     \nodeb  \&         \&         \& \nodec  \&         \\
    823835                             \&         \& \noded  \&         \& \nodee  \\
    824836                    };
    825837                    <BLANKLINE>
    class AbstractTree(object): 
    828840                    \end{tikzpicture}}
    829841                """
    830842                # build all subtree matrices.
    831                 node, name = create_node( self )
     843                node, name = create_node(self)
    832844                edge = [name]
    833                 split = int(len( self )/2)
     845                split = int(len(self) / 2)
    834846                # the left part
    835                 for i in range( split ):
    836                     tmp( self[i], edge, nodes, edges, matrix )
     847                for i in range(split):
     848                    tmp(self[i], edge, nodes, edges, matrix)
    837849                ## prepare the root line
    838                 nb_of_and = matrix[0].count( sep )
     850                nb_of_and = matrix[0].count(sep)
    839851                # the middle
    840                 for i in range( len( matrix ) ): matrix[i] += sepspace
    841                 # the right part   
    842                 for i in range( split, len( self ) ):
    843                     tmp( self[i], edge, nodes, edges, matrix )
    844                
     852                for i in range(len(matrix)):
     853                    matrix[i] += sepspace
     854                # the right part
     855                for i in range(split, len(self)):
     856                    tmp(self[i], edge, nodes, edges, matrix)
     857
    845858                ## create the root line
    846                 root_line = ( spacesep*(nb_of_and+1) + node_to_str(node) +
    847                     sepspace*(matrix[0].count(sep) - nb_of_and - 1) )
     859                root_line = (spacesep * (nb_of_and + 1) + node_to_str(node) +
     860                    sepspace * (matrix[0].count(sep) - nb_of_and - 1))
    848861                matrix.insert(0, root_line)
    849862                # add edges from the root
    850                 edges.append( edge )
     863                edges.append(edge)
     864
    851865            def odd_nodes_tree( self, nodes, edges, matrix):
    852866                '''
    853867                TESTS::
    854                
    855                     sage: t = OrderedTree([[]]).canonical_labelling(); print latex(t)
     868
     869                    sage: t = OrderedTree([[]]).canonical_labelling()
     870                    sage: print latex(t)
    856871                    { \newcommand{\nodea}{\node[draw,circle] (a) {$1$}
    857872                    ;}\newcommand{\nodeb}{\node[draw,circle] (b) {$2$}
    858873                    ;}\begin{tikzpicture}[auto]
    859874                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
    860                      \nodea  \\ 
     875                     \nodea  \\
    861876                     \nodeb  \\
    862877                    };
    863878                    <BLANKLINE>
    class AbstractTree(object): 
    870885                    ;}\newcommand{\noded}{\node[draw,circle] (d) {$4$}
    871886                    ;}\begin{tikzpicture}[auto]
    872887                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
    873                              \& \nodea  \&         \\ 
    874                              \& \nodeb  \&         \\ 
     888                             \& \nodea  \&         \\
     889                             \& \nodeb  \&         \\
    875890                     \nodec  \&         \& \noded  \\
    876891                    };
    877                    
     892                    <BLANKLINE>
    878893                    \path[ultra thick, red] (b) edge (c) edge (d)
    879894                        (a) edge (b);
    880895                    \end{tikzpicture}}
    class AbstractTree(object): 
    886901                    ;}\newcommand{\nodee}{\node[draw,circle] (e) {$5$}
    887902                    ;}\begin{tikzpicture}[auto]
    888903                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
    889                              \& \nodea  \&         \\ 
    890                              \& \nodeb  \&         \\ 
     904                             \& \nodea  \&         \\
     905                             \& \nodeb  \&         \\
    891906                     \nodec  \& \noded  \& \nodee  \\
    892907                    };
    893908                    <BLANKLINE>
    class AbstractTree(object): 
    904919                    ;}\newcommand{\nodeg}{\node[draw,circle] (g) {$7$}
    905920                    ;}\begin{tikzpicture}[auto]
    906921                    \matrix[column sep=.3cm, row sep=.3cm,ampersand replacement=\&]{
    907                              \&         \&         \& \nodea  \&         \\ 
    908                              \& \nodeb  \&         \& \nodef  \& \nodeg  \\ 
     922                             \&         \&         \& \nodea  \&         \\
     923                             \& \nodeb  \&         \& \nodef  \& \nodeg  \\
    909924                     \nodec  \& \noded  \& \nodee  \&         \&         \\
    910925                    };
    911926                    <BLANKLINE>
    class AbstractTree(object): 
    914929                    \end{tikzpicture}}
    915930                '''
    916931                # build all subtree matrices.
    917                 node, name = create_node( self )
     932                node, name = create_node(self)
    918933                edge = [name]
    919                 split = int(len( self )/2)
     934                split = int(len(self) / 2)
    920935                # the left part
    921                 for i in range( split ):
    922                     tmp( self[i], edge, nodes, edges, matrix )
     936                for i in range(split):
     937                    tmp(self[i], edge, nodes, edges, matrix)
    923938                ## prepare the root line
    924                 if len( matrix ) != 0:
    925                     nb_of_and = matrix[0].count( sep )
    926                     sizetmp = len( matrix[0] )
     939                if len(matrix) != 0:
     940                    nb_of_and = matrix[0].count(sep)
     941                    sizetmp = len(matrix[0])
    927942                else:
    928943                    nb_of_and = 0
    929944                    sizetmp = 0
    930945                # the middle
    931                 tmp( self[split], edge, nodes, edges, matrix )
    932                 nb_of_and += matrix[0][sizetmp:].split("node")[0].count( sep )
    933                
    934                 # the right part   
    935                 for i in range( split+1, len( self ) ):
    936                     tmp( self[i], edge, nodes, edges, matrix )
    937                
     946                tmp(self[split], edge, nodes, edges, matrix)
     947                nb_of_and += matrix[0][sizetmp:].split("node")[0].count(sep)
     948
     949                # the right part
     950                for i in range(split + 1, len(self)):
     951                    tmp(self[i], edge, nodes, edges, matrix)
     952
    938953                ## create the root line
    939                 root_line = ( spacesep*(nb_of_and) + node_to_str(node) +
    940                     sepspace*(matrix[0].count(sep) - nb_of_and) )
     954                root_line = (spacesep * (nb_of_and) + node_to_str(node) +
     955                    sepspace * (matrix[0].count(sep) - nb_of_and))
    941956                matrix.insert(0, root_line)
    942957                # add edges from the root
    943                 edges.append( edge )
     958                edges.append(edge)
    944959            if self.is_empty():
    945960                empty_tree()
    946             elif len( self ) == 0 or all(subtree.is_empty() for subtree in self):
    947                 one_node_tree( self )
    948             elif len( self ) % 2 == 0:
    949                 pair_nodes_tree( self, nodes, edges, matrix )
    950             else:
    951                 odd_nodes_tree( self, nodes, edges, matrix )
     961            elif len(self) == 0 or all(subtree.is_empty()
     962                    for subtree in self):
     963                one_node_tree(self)
     964            elif len(self) % 2 == 0:
     965                pair_nodes_tree(self, nodes, edges, matrix)
     966            else:
     967                odd_nodes_tree(self, nodes, edges, matrix)
    952968            return nodes, matrix, edges
    953        
    954         nodes, matrix, edges = resolve( self )
     969
     970        nodes, matrix, edges = resolve(self)
     971
    955972        def make_cmd(nodes):
    956973            cmds = []
    957974            for name, label in nodes:
    958                 cmds.append(new_cmd1 + name + new_cmd2 + 
    959                     name + new_cmd3 + 
     975                cmds.append(new_cmd1 + name + new_cmd2 +
     976                    name + new_cmd3 +
    960977                    label + new_cmd4)
    961978            return cmds
     979
    962980        def make_edges(edges):
    963981            all_paths = []
    964982            for edge in edges:
    965983                path = "(" + edge[0] + ")"
    966                 for i in range(1,len(edge)):
    967                     path += " edge (%s)"%edge[i]
     984                for i in range(1, len(edge)):
     985                    path += " edge (%s)" % edge[i]
    968986                all_paths.append(path)
    969             return all_paths 
    970         return ("{ " + 
    971             "".join(make_cmd( nodes )) +
     987            return all_paths
     988        return ("{ " +
     989            "".join(make_cmd(nodes)) +
    972990            begin_env +
    973991                (matrix_begin +
    974                     "\\\\ \n".join( matrix ) +
     992                    "\\\\ \n".join(matrix) +
    975993                matrix_end +
    976                 ("\n" + 
     994                ("\n" +
    977995                path_begin +
    978                     "\n\t".join( make_edges( edges ) ) +
    979                 path_end if len(edges)>0 else "")
     996                    "\n\t".join(make_edges(edges)) +
     997                path_end if len(edges) > 0 else "")
    980998                if len(matrix) > 0 else "") +
    981             end_env + 
    982             "}") 
     999            end_env +
     1000            "}")
    9831001
    9841002class AbstractClonableTree(AbstractTree):
    9851003    """
  • sage/combinat/binary_tree.py

    diff --git a/sage/combinat/binary_tree.py b/sage/combinat/binary_tree.py
    a b objects. 
    1111**AUTHORS:**
    1212
    1313- Florent Hivert (2010-2011): initial implementation.
     14- Jean-Baptiste Priez (2013):
     15      -> several classical algorithms
     16      -> some research algorithms from _[LodayRonco]
     17
     18References
     19----------
     20
     21.. [LodayRonco] Hopf algebra of the planar binary trees,
     22    Jean-Louis Loday and
     23    Maria O. Ronco
    1424"""
    1525#*****************************************************************************
    1626#       Copyright (C) 2010 Florent Hivert <Florent.Hivert@univ-rouen.fr>,
    class BinaryTree(AbstractClonableTree, C 
    874884        '''
    875885        The depth first infix-order traversal algorithm.
    876886
     887        INPUT:
     888
     889        - ``node_action`` -- a specific function which takes a node in input
     890        and do something during the exploration.
     891        - ``leaf_action`` -- a specific function which takes a leaf in input
     892        and do something during the exploration.
     893
    877894        For example on the following binary tree `b` where we denote leafs by
    878895        `a,b,c...` and nodes by `1,2,3...`::
    879896
    880                 ____3____
    881                /         \
    882               1          __7__
    883              / \        /     \
    884             a   2      _5_     8
    885                / \    /   \   / \
    886               b   c  4     6 h   i
    887                     / \   / \
    888                    d   e f   g
     897            |     ____3____          |
     898            |    /         \         |
     899            |   1          __7__     |
     900            |  / \        /     \    |
     901            | a   2      _5_     8   |
     902            |    / \    /   \   / \  |
     903            |   b   c  4     6 h   i |
     904            |         / \   / \      |
     905            |        d   e f   g     |
    889906
    890907        the ``depth first infixe-order traversal algorithm`` explores `b` in
    891908        the following order of nodes `a,1,b,2,c,3,d,4,e,5,f,6,g,7,h,8,i`.
    class BinaryTree(AbstractClonableTree, C 
    893910        The algorithm is::
    894911
    895912            explore the left subtree
    896             manipulate the root
     913            manipulate the root with function `node_action` if the root is
     914                a node and with function `leaf_action` if it is a leaf
    897915            explore the right subtree
    898916
    899917        TESTS::
    class BinaryTree(AbstractClonableTree, C 
    948966        '''
    949967        Right rotation operation of tree::
    950968
    951                 o                     _o_
    952                /                     /   \
    953               o    -right-rotate->  o     o
    954              / \                         /
    955             o   o                       o
     969            |     o                     _o_   |
     970            |    /                     /   \  |
     971            |   o    -right-rotate->  o     o |
     972            |  / \                         /  |
     973            | o   o                       o   |
    956974            <BLANKLINE>
    957                   __o__                         _o__
    958                  /     \                       /    \
    959                 o       o  -right-rotate->    o     _o_
    960                / \                           /     /   \
    961               o   o                         o     o     o
    962              /     \                               \
    963             o       o                               o
     975            |       __o__                         _o__      |
     976            |      /     \                       /    \     |
     977            |     o       o  -right-rotate->    o     _o_   |
     978            |    / \                           /     /   \  |
     979            |   o   o                         o     o     o |
     980            |  /     \                               \      |
     981            | o       o                               o     |
    964982
    965983        TESTS::
    966984
    967             sage: b = BinaryTree([[[],[]], None]); ascii_art(b)
    968                 o
    969                /
    970               o
    971              / \
    972             o   o
    973             sage: ascii_art(b.right_rotate())
    974               _o_
    975              /   \
    976             o     o
    977                  /
    978                 o
    979             sage: b = BinaryTree([[[[],None],[None,[]]], []]);ascii_art(b)
    980                   __o__
    981                  /     \
    982                 o       o
    983                / \
    984               o   o
    985              /     \
    986             o       o
    987             sage: ascii_art(b.right_rotate())
    988                 _o__
    989                /    \
    990               o     _o_
    991              /     /   \
    992             o     o     o
    993                    \
    994                     o
     985            sage: b = BinaryTree([[[],[]], None]); ascii_art([b])
     986            [     o ]
     987            [    /  ]
     988            [   o   ]
     989            [  / \  ]
     990            [ o   o ]
     991            sage: ascii_art([b.right_rotate()])
     992            [   _o_   ]
     993            [  /   \  ]
     994            [ o     o ]
     995            [      /  ]
     996            [     o   ]
     997            sage: b = BinaryTree([[[[],None],[None,[]]], []]);ascii_art([b])
     998            [       __o__   ]
     999            [      /     \  ]
     1000            [     o       o ]
     1001            [    / \        ]
     1002            [   o   o       ]
     1003            [  /     \      ]
     1004            [ o       o     ]
     1005            sage: ascii_art([b.right_rotate()])
     1006            [     _o__      ]
     1007            [    /    \     ]
     1008            [   o     _o_   ]
     1009            [  /     /   \  ]
     1010            [ o     o     o ]
     1011            [        \      ]
     1012            [         o     ]
    9951013        '''
    9961014        B = self.parent()._element_constructor_
    9971015        return B([self[0][0], B([self[0][1], self[1]])])
    class BinaryTree(AbstractClonableTree, C 
    10001018        '''
    10011019        Left rotation operation of tree::
    10021020
    1003               _o_                        o
    1004              /   \                      /
    1005             o     o  -left-rotate->    o
    1006                  /                    / \
    1007                 o                    o   o
     1021            |   _o_                        o |
     1022            |  /   \                      /  |
     1023            | o     o  -left-rotate->    o   |
     1024            |      /                    / \  |
     1025            |     o                    o   o |
    10081026            <BLANKLINE>
    1009                   __o__                            o
    1010                  /     \                          /
    1011                 o       o  -left-rotate->        o
    1012                / \                              /
    1013               o   o                            o
    1014              /     \                          / \
    1015             o       o                        o   o
    1016                                             /     \
    1017                                            o       o
     1027            |       __o__                            o |
     1028            |      /     \                          /  |
     1029            |     o       o  -left-rotate->        o   |
     1030            |    / \                              /    |
     1031            |   o   o                            o     |
     1032            |  /     \                          / \    |
     1033            | o       o                        o   o   |
     1034            |                                 /     \  |
     1035            |                                o       o |
    10181036
    10191037
    10201038        TESTS::
    10211039
    1022             sage: b = BinaryTree([[],[[],None]]); ascii_art(b)
    1023               _o_
    1024              /   \
    1025             o     o
    1026                  /
    1027                 o
    1028             sage: ascii_art(b.left_rotate())
    1029                 o
    1030                /
    1031               o
    1032              / \
    1033             o   o
     1040            sage: b = BinaryTree([[],[[],None]]); ascii_art([b])
     1041            [   _o_   ]
     1042            [  /   \  ]
     1043            [ o     o ]
     1044            [      /  ]
     1045            [     o   ]
     1046            sage: ascii_art([b.left_rotate()])
     1047            [     o ]
     1048            [    /  ]
     1049            [   o   ]
     1050            [  / \  ]
     1051            [ o   o ]
    10341052            sage: b.left_rotate().right_rotate() == b
    10351053            True
    10361054        '''
    10371055        B = self.parent()._element_constructor_
    10381056        return B([B([self[0], self[1][0]]), self[1][1]])
    10391057
     1058    def sylvestrohedron_greater(self):
     1059        '''
     1060        The list of all trees greater than ''self''.
     1061        This is the transitive ideal of its successors.
     1062
     1063        The tree::
     1064
     1065            |     __o__   |
     1066            |    /     \  |
     1067            |   o       o |
     1068            |  / \     /  |
     1069            | o   o   o   |
     1070
     1071        has these trees greater than it::
     1072
     1073            |o          , o        , o        , o        ,  o       ,   o      ,|
     1074            | \            \          \          \           \           \      |
     1075            |  o            o          o           o         _o_        __o__   |
     1076            |   \            \          \           \       /   \      /     \  |
     1077            |    o            o          o          _o_    o     o    o       o |
     1078            |     \            \        / \        /   \    \     \    \     /  |
     1079            |      o            o      o   o      o     o    o     o    o   o   |
     1080            |       \            \          \          /                        |
     1081            |        o            o          o        o                         |
     1082            |         \          /                                              |
     1083            |          o        o                                               |
     1084            <BLANKLINE>
     1085            |   o        ,   o      ,   _o_      ,   _o__     ,   __o__    ,   ___o___  ,|
     1086            |  / \          / \        /   \        /    \       /     \      /       \  |
     1087            | o   o        o   o      o     o      o     _o_    o       o    o         o |
     1088            |      \            \          / \          /   \    \       \    \       /  |
     1089            |       o            o        o   o        o     o    o       o    o     o   |
     1090            |        \            \            \            /      \            \        |
     1091            |         o            o            o          o        o            o       |
     1092            |          \          /                                                      |
     1093            |           o        o                                                       |
     1094            <BLANKLINE>
     1095            |     _o_    ,     __o__  |
     1096            |    /   \        /     \ |
     1097            |   o     o      o       o|
     1098            |  / \     \    / \     / |
     1099            | o   o     o  o   o   o  |
     1100
     1101        TESTS::
     1102
     1103            sage: B = BinaryTree
     1104            sage: b = B([None, B([None, B([None, B([])])])]);b
     1105            [., [., [., [., .]]]]
     1106            sage: b.sylvestrohedron_greater()
     1107            [[., [., [., [., .]]]]]
     1108            sage: b = B([B([B([B([]), None]), None]), None]);b
     1109            [[[[., .], .], .], .]
     1110            sage: b.sylvestrohedron_greater()
     1111            [[., [., [., [., .]]]], [., [., [[., .], .]]], [., [[., .], [., .]]], [., [[., [., .]], .]], [., [[[., .], .], .]], [[., .], [., [., .]]], [[., .], [[., .], .]], [[., [., .]], [., .]], [[., [., [., .]]], .], [[., [[., .], .]], .], [[[., .], .], [., .]], [[[., .], [., .]], .], [[[., [., .]], .], .], [[[[., .], .], .], .]]
     1112        '''
     1113        from sage.combinat.tools import transitive_ideal
     1114        return transitive_ideal(lambda x: x.sylvestrohedron_succ(), self)
     1115
     1116    def sylvestrohedron_pred(self):
     1117        '''
     1118        Compute the list of predecessor of ''self'' in the
     1119        sylvestrohedron.
     1120        This list is computed by all left rotate possible on
     1121        its nodes.
     1122
     1123        For this tree::
     1124
     1125            |     __o__   |
     1126            |    /     \  |
     1127            |   o       o |
     1128            |  / \     /  |
     1129            | o   o   o   |
     1130
     1131        the list is::
     1132
     1133            |        o ,       _o_   |
     1134            |       /         /   \  |
     1135            |     _o_        o     o |
     1136            |    /   \      /     /  |
     1137            |   o     o    o     o   |
     1138            |  / \        /          |
     1139            | o   o      o           |
     1140
     1141        TESTS::
     1142
     1143            sage: B = BinaryTree
     1144            sage: b = B([B([B([B([]), None]), None]), None]);b
     1145            [[[[., .], .], .], .]
     1146            sage: b.sylvestrohedron_pred()
     1147            []
     1148            sage: b = B([None, B([None, B([None, B([])])])]);b
     1149            [., [., [., [., .]]]]
     1150            sage: b.sylvestrohedron_pred()
     1151            [[[., .], [., [., .]]], [., [[., .], [., .]]], [., [., [[., .], .]]]]
     1152        '''
     1153        res = []
     1154        if self.is_empty():
     1155            return []
     1156        if not self[1].is_empty():
     1157            res.append(self.left_rotate())
     1158        B = self.parent()._element_constructor_
     1159        return (res +
     1160                [B([g, self[1]]) for g in self[0].sylvestrohedron_pred()] +
     1161                [B([self[0], d]) for d in self[1].sylvestrohedron_pred()])
     1162
     1163    def sylvestrohedron_smaller(self):
     1164        '''
     1165        The list of all trees smaller than ''self''.
     1166        This is the transitive ideal of its predecessors.
     1167
     1168        The tree::
     1169
     1170            |     __o__   |
     1171            |    /     \  |
     1172            |   o       o |
     1173            |  / \     /  |
     1174            | o   o   o   |
     1175
     1176        has these trees smaller than it::
     1177
     1178            |    __o__  ,       _o_  ,        o ,         o,         o,           o |
     1179            |   /     \        /   \         /           /          /            /  |
     1180            |  o       o      o     o      _o_          o          o            o   |
     1181            | / \     /      /     /      /   \        / \        /            /    |
     1182            |o   o   o      o     o      o     o      o   o      o            o     |
     1183            |              /            / \          /          /            /      |
     1184            |             o            o   o        o          o            o       |
     1185            |                                      /          / \          /        |
     1186            |                                     o          o   o        o         |
     1187            |                                                            /          |
     1188            |                                                           o           |
     1189
     1190        TESTS::
     1191
     1192            sage: B = BinaryTree
     1193            sage: b = B([None, B([None, B([None, B([])])])]);b
     1194            [., [., [., [., .]]]]
     1195            sage: b.sylvestrohedron_smaller()
     1196            [[., [., [., [., .]]]], [., [., [[., .], .]]], [., [[., .], [., .]]], [., [[., [., .]], .]], [., [[[., .], .], .]], [[., .], [., [., .]]], [[., .], [[., .], .]], [[., [., .]], [., .]], [[., [., [., .]]], .], [[., [[., .], .]], .], [[[., .], .], [., .]], [[[., .], [., .]], .], [[[., [., .]], .], .], [[[[., .], .], .], .]]
     1197            sage: b = B([B([B([B([]), None]), None]), None]);b
     1198            [[[[., .], .], .], .]
     1199            sage: b.sylvestrohedron_smaller()
     1200            [[[[[., .], .], .], .]]
     1201        '''
     1202        from sage.combinat.tools import transitive_ideal
     1203        return transitive_ideal(lambda x: x.sylvestrohedron_pred(), self)
     1204
     1205    def sylvestrohedron_succ(self):
     1206        '''
     1207        Compute the list of successors of ''self'' in the sylvestrohedron.
     1208        There is the list of all trees obtains by a right rotate of
     1209        one of its nodes.
     1210
     1211        The list of successor of::
     1212
     1213            |     __o__   |
     1214            |    /     \  |
     1215            |   o       o |
     1216            |  / \     /  |
     1217            | o   o   o   |
     1218
     1219        is::
     1220
     1221            |   _o__     ,   ___o___  ,     _o_     |
     1222            |  /    \       /       \      /   \    |
     1223            | o     _o_    o         o    o     o   |
     1224            |      /   \    \       /    / \     \  |
     1225            |     o     o    o     o    o   o     o |
     1226            |          /      \                     |
     1227            |         o        o                    |
     1228
     1229        TESTS::
     1230
     1231            sage: B = BinaryTree
     1232            sage: b = B([B([B([B([]), None]), None]), None]);b
     1233            [[[[., .], .], .], .]
     1234            sage: b.sylvestrohedron_succ()
     1235            [[[[., .], .], [., .]], [[[., .], [., .]], .], [[[., [., .]], .], .]]
     1236        '''
     1237        res = []
     1238        if self.is_empty():
     1239            return []
     1240        B = self.parent()._element_constructor_
     1241        if not self[0].is_empty():
     1242            res.append(self.right_rotate())
     1243        return (res +
     1244             [B([g, self[1]]) for g in self[0].sylvestrohedron_succ()] +
     1245             [B([self[0], d]) for d in self[1].sylvestrohedron_succ()])
     1246
     1247    def q_hook_length_formula(self):
     1248        '''
     1249        Compute the ``q-hook length formula`` of a binary tree.
     1250
     1251        If `q=1` then ``q-hook length formula`` computes the number of
     1252        permutations such that the shape of binary search tree associated is
     1253        *self*.
     1254
     1255        .. MATH::
     1256
     1257            f_{q} (T) = \\frac{[\\mid T\\mid]_q !}{\\prod_{t\\in T}
     1258            q^{right(t)}[\\mid t\\mid]_q}
     1259
     1260        where `\\mid T\\mid` is the node number of `T`, `t\\in T` the set
     1261        of all subtree of `T` and `right(t)` the number of node of the right
     1262        subtree of `t`.
     1263
     1264        There is 20 permutations which give this shape binary tree::
     1265
     1266            |     __o__   |
     1267            |    /     \  |
     1268            |   o       o |
     1269            |  / \     /  |
     1270            | o   o   o   |
     1271
     1272        by the binary search insertion algorithm.
     1273
     1274        TESTS::
     1275
     1276            sage: b = BinaryTree([[[],[]],[[],None]]); b
     1277            [[[., .], [., .]], [[., .], .]]
     1278            sage: b.q_hook_length_formula()(q=1)
     1279            20
     1280            sage: BinaryTree([[],[]]).q_hook_length_formula()
     1281            (((q + 2)*q + 2)*q + 1)*q/((q + 1)*q + 1)
     1282        '''
     1283        from sage.combinat.q_analogues import q_factorial, q_int
     1284        from sage.symbolic.ring import SymbolicRing
     1285
     1286        q = SymbolicRing().var('q')
     1287
     1288        def product_of_subtrees(b):
     1289            if b.is_empty():
     1290                return q ** 0
     1291            return (q ** (-b[0].node_number()) * q_int(b.node_number())) * \
     1292                product_of_subtrees(b[0]) * product_of_subtrees(b[1])
     1293
     1294        return q_factorial(self.node_number()) / product_of_subtrees(self)
     1295
     1296    def over(self, bt):
     1297        '''
     1298        The ``over`` (`/`) operation defined by Loday-Ronco [LodayRonco]_::
     1299
     1300            |   o       __o__       _o_         |
     1301            |  / \  /  /     \  =  /   \        |
     1302            | o   o   o       o   o     o       |
     1303            |          \     /           \      |
     1304            |           o   o           __o__   |
     1305            |                          /     \  |
     1306            |                         o       o |
     1307            |                          \     /  |
     1308            |                           o   o   |
     1309
     1310        EXAMPLES::
     1311
     1312            sage: b1 = BinaryTree([[],[[],[]]])
     1313            sage: b2 = BinaryTree([[None, []],[]])
     1314            sage: ascii_art((b1, b2, b1/b2))
     1315            (   _o_        _o_      _o_           )
     1316            (  /   \      /   \    /   \          )
     1317            ( o     o    o     o  o     o_        )
     1318            (      / \    \            /  \       )
     1319            (     o   o,   o    ,     o    o      )
     1320            (                               \     )
     1321            (                               _o_   )
     1322            (                              /   \  )
     1323            (                             o     o )
     1324            (                              \      )
     1325            (                               o     )
     1326
     1327        TESTS::
     1328
     1329            sage: b1 = BinaryTree([[],[]]); ascii_art([b1])
     1330            [   o   ]
     1331            [  / \  ]
     1332            [ o   o ]
     1333            sage: b2 = BinaryTree([[None,[]],[[],None]]); ascii_art([b2])
     1334            [   __o__   ]
     1335            [  /     \  ]
     1336            [ o       o ]
     1337            [  \     /  ]
     1338            [   o   o   ]
     1339            sage: ascii_art([b1.over(b2)])
     1340            [   _o_         ]
     1341            [  /   \        ]
     1342            [ o     o       ]
     1343            [        \      ]
     1344            [       __o__   ]
     1345            [      /     \  ]
     1346            [     o       o ]
     1347            [      \     /  ]
     1348            [       o   o   ]
     1349        '''
     1350        B = self.parent()._element_constructor_
     1351        if self.is_empty():
     1352            return bt
     1353        lab = None
     1354        if hasattr(self, "label"):
     1355            lab = self.label()
     1356        else:
     1357            return B([self[0], self[1].over(bt)], lab)
     1358
     1359    def __div__(self, bt):
     1360        '''
     1361        The ``over`` operation on trees.
     1362        .. see ::method::*over*.
     1363
     1364        TESTS::
     1365
     1366            sage: b1 = BinaryTree([[],[]])
     1367            sage: b2 = BinaryTree([[None,[]],[[],None]])
     1368            sage: b1/b2
     1369            [[., .], [., [[., [., .]], [[., .], .]]]]
     1370        '''
     1371        return self.over(bt)
     1372
     1373    def under(self, bt):
     1374        r'''
     1375        The ``under`` (`\backslash`) operation defined by Loday-Ronco
     1376        [LodayRonco]_.
     1377
     1378        EXAMPLES::
     1379
     1380            sage: b1 = BinaryTree([[],[]])
     1381            sage: b2 = BinaryTree([None,[]])
     1382            sage: ascii_art((b1, b2, b1 \ b2))
     1383            (   o    o        _o_   )
     1384            (  / \    \      /   \  )
     1385            ( o   o,   o,   o     o )
     1386            (              / \      )
     1387            (             o   o     )
     1388
     1389        TESTS::
     1390
     1391            sage: b1 = BinaryTree([[],[[None,[]],None]]); ascii_art([b1])
     1392            [   _o_   ]
     1393            [  /   \  ]
     1394            [ o     o ]
     1395            [      /  ]
     1396            [     o   ]
     1397            [      \  ]
     1398            [       o ]
     1399            sage: b2 = BinaryTree([[],[None,[]]]); ascii_art([b2])
     1400            [   o     ]
     1401            [  / \    ]
     1402            [ o   o   ]
     1403            [      \  ]
     1404            [       o ]
     1405            sage: ascii_art([b1.under(b2)])
     1406            [        o_     ]
     1407            [       /  \    ]
     1408            [      o    o   ]
     1409            [     /      \  ]
     1410            [   _o_       o ]
     1411            [  /   \        ]
     1412            [ o     o       ]
     1413            [      /        ]
     1414            [     o         ]
     1415            [      \        ]
     1416            [       o       ]
     1417        '''
     1418        B = self.parent()._element_constructor_
     1419        if bt.is_empty():
     1420            return self
     1421        lab = None
     1422        if hasattr(bt, "label"):
     1423            lab = bt.label()
     1424        else:
     1425            return B([self.under(bt[0]), bt[1]], lab)
     1426
     1427    def _backslash_(self, bt):
     1428        '''
     1429        The ``under`` operation on trees.
     1430        .. see ::method::*under*.
     1431
     1432        TESTS::
     1433
     1434            sage: b1 = BinaryTree([[],[[None,[]],None]])
     1435            sage: b2 = BinaryTree([[],[None,[]]])
     1436            sage: b1\b2
     1437            [[[[., .], [[., [., .]], .]], .], [., [., .]]]
     1438        '''
     1439        return self.under(bt)
     1440
    10401441
    10411442from sage.structure.parent import Parent
    10421443from sage.structure.unique_representation import UniqueRepresentation
  • sage/combinat/abstract_tree.py

    # HG changeset patch
    # User Jean-Baptiste Priez <jbp@kerios.fr>
    # Date 1371913590 -7200
    # Node ID 9a0b4ff87ee4c1a5ceab2b733ff52e0c584f0c0f
    # Parent  2fcaf474f25b268239721eb249e849728b69a547
    pep8 and documentation abstract trees
    
    diff --git a/sage/combinat/abstract_tree.py b/sage/combinat/abstract_tree.py
    a b class AbstractTree(object): 
    125125
    126126        For example on the following binary tree `b`::
    127127
    128               ___3____
    129              /        \
    130             1         _7_
    131              \       /   \
    132               2     5     8
    133                    / \
    134                   4   6
     128            |   ___3____      |
     129            |  /        \     |
     130            | 1         _7_   |
     131            |  \       /   \  |
     132            |   2     5     8 |
     133            |        / \      |
     134            |       4   6     |
    135135
    136136        the ``depth first pre-order traversal algorithm`` explores `b` in the
    137137        following order of nodes `3,1,2,7,5,4,6,8`.
    class AbstractTree(object): 
    143143
    144144        An other example::
    145145
    146                 __1____
    147                /  /   /
    148               2  6   8_
    149               |  |  / /
    150               3_ 7 9 10
    151              / /
    152             4 5
     146            |     __1____ |
     147            |    /  /   / |
     148            |   2  6   8_ |
     149            |   |  |  / / |
     150            |   3_ 7 9 10 |
     151            |  / /        |
     152            | 4 5         |
    153153
    154154        The algorithm explores this tree in the following order:
    155155        `1,2,3,4,5,6,7,8,9,10`.
    class AbstractTree(object): 
    202202
    203203        For example on the following binary tree `b`::
    204204
    205               ___3____
    206              /        \
    207             1         _7_
    208              \       /   \
    209               2     5     8
    210                    / \
    211                   4   6
     205            |   ___3____      |
     206            |  /        \     |
     207            | 1         _7_   |
     208            |  \       /   \  |
     209            |   2     5     8 |
     210            |        / \      |
     211            |       4   6     |
    212212
    213213        the ``depth first post-order traversal algorithm`` explores `b` in the
    214214        following order of nodes `2,1,4,6,5,8,7,3`.
    class AbstractTree(object): 
    220220
    221221        Another example::
    222222
    223                 __1____
    224                /  /   /
    225               2  6   8_
    226               |  |  / /
    227               3_ 7 9 10
    228              / /
    229             4 5
     223            |     __1____ |
     224            |    /  /   / |
     225            |   2  6   8_ |
     226            |   |  |  / / |
     227            |   3_ 7 9 10 |
     228            |  / /        |
     229            | 4 5         |
    230230
    231231        The algorithm explorer this tree in the following order:
    232232        `4,5,3,2,7,6,9,10,8,1`.
    class AbstractTree(object): 
    273273
    274274        For example on the following binary tree `b`::
    275275
    276               ___3____
    277              /        \
    278             1         _7_
    279              \       /   \
    280               2     5     8
    281                    / \
    282                   4   6
     276            |   ___3____      |
     277            |  /        \     |
     278            | 1         _7_   |
     279            |  \       /   \  |
     280            |   2     5     8 |
     281            |        / \      |
     282            |       4   6     |
    283283
    284284        the ``breadth first order traversal algorithm`` explores `b` in the
    285285        following order of nodes `3,1,7,2,5,8,4,6`.
    class AbstractTree(object): 
    464464            return Integer(1 + max(i.depth() for i in self))
    465465        else:
    466466            return Integer(0 if self.is_empty() else 1)
    467        
     467
    468468    def _ascii_art_(self):
    469469        r"""
    470470        TESTS::
    class AbstractTree(object): 
    480480            sage: aa.get_baseline()
    481481            2
    482482            sage: tt1 = OrderedTree([[],[[],[],[[[[]]]]],[[[],[],[],[]]]])
    483             sage: ascii_art(tt1)
    484               _____o_______
    485              /    /       /   
    486             o   _o__     o
    487                / / /     |
    488               o o o    __o___
    489                   |   / / / /
    490                   o  o o o o
    491                   |
    492                   o
    493                   |
    494                   o
    495             sage: ascii_art(tt1.canonical_labelling())
    496               ______1_______
    497              /    /        /     
    498             2   _3__      10
    499                / / /      |
    500               4 5 6    ___11____
    501                   |   /  /  /  /
    502                   7  12 13 14 15
    503                   |
    504                   8
    505                   |
    506                   9
    507             sage: ascii_art(OrderedTree([[],[[]]]))
    508                   o_
    509                  / /
    510                 o o
    511                   |
    512                   o
     483            sage: ascii_art([tt1])
     484            [   _____o_______    ]
     485            [  /    /       /    ]
     486            [ o   _o__     o     ]
     487            [    / / /     |     ]
     488            [   o o o    __o___  ]
     489            [       |   / / / /  ]
     490            [       o  o o o o   ]
     491            [       |            ]
     492            [       o            ]
     493            [       |            ]
     494            [       o            ]
     495            sage: ascii_art([tt1.canonical_labelling()])
     496            [   ______1_______       ]
     497            [  /    /        /       ]
     498            [ 2   _3__      10       ]
     499            [    / / /      |        ]
     500            [   4 5 6    ___11____   ]
     501            [       |   /  /  /  /   ]
     502            [       7  12 13 14 15   ]
     503            [       |                ]
     504            [       8                ]
     505            [       |                ]
     506            [       9                ]
     507            sage: ascii_art([OrderedTree([[],[[]]])])
     508            [   o_ ]
     509            [  / / ]
     510            [ o o  ]
     511            [   |  ]
     512            [   o  ]
    513513            sage: t = OrderedTree([[[],[[[],[]]],[[]]],[[[[[],[]]]]],[[],[]]])
    514             sage: ascii_art(t)
    515                   _____o_______
    516                  /       /    /
    517               __o____   o    o_
    518              /   /  /   |   / /
    519             o   o  o    o  o o
    520                 |  |    |
    521                 o_ o    o
    522                / /      |
    523               o o       o_
    524                        / /
    525                       o o
    526             sage: ascii_art(t.canonical_labelling())
    527                   ______1________
    528                  /       /      /   
    529               __2____   10     16_
    530              /   /  /   |     /  /
    531             3   4  8    11   17 18
    532                 |  |    |   
    533                 5_ 9    12 
    534                / /      |   
    535               6 7       13_
    536                        /  /
    537                       14 15
     514            sage: ascii_art([t])
     515            [       _____o_______  ]
     516            [      /       /    /  ]
     517            [   __o____   o    o_  ]
     518            [  /   /  /   |   / /  ]
     519            [ o   o  o    o  o o   ]
     520            [     |  |    |        ]
     521            [     o_ o    o        ]
     522            [    / /      |        ]
     523            [   o o       o_       ]
     524            [            / /       ]
     525            [           o o        ]
     526            sage: ascii_art([t.canonical_labelling()])
     527            [       ______1________    ]
     528            [      /       /      /    ]
     529            [   __2____   10     16_   ]
     530            [  /   /  /   |     /  /   ]
     531            [ 3   4  8    11   17 18   ]
     532            [     |  |    |            ]
     533            [     5_ 9    12           ]
     534            [    / /      |            ]
     535            [   6 7       13_          ]
     536            [            /  /          ]
     537            [           14 15          ]
    538538        """
    539539        node_to_str = lambda t: str(t.label()) if hasattr(t, "label") else "o"
    540540
    class AbstractTree(object): 
    544544
    545545        from sage.misc.ascii_art import AsciiArt
    546546        if len(self) == 0:
    547             t_repr = AsciiArt( [node_to_str(self)] )
     547            t_repr = AsciiArt([node_to_str(self)])
    548548            t_repr._root = 1
    549549            return t_repr
    550550        if len(self) == 1:
    551551            repr_child = self[0]._ascii_art_()
    552             sep = AsciiArt( [" "*(repr_child._root-1)] )
    553             t_repr = AsciiArt( [node_to_str(self)] )
     552            sep = AsciiArt([" " * (repr_child._root - 1)])
     553            t_repr = AsciiArt([node_to_str(self)])
    554554            t_repr._root = 1
    555             repr_root = (sep + t_repr)*(sep + AsciiArt( ["|"] ))
     555            repr_root = (sep + t_repr) * (sep + AsciiArt(["|"]))
    556556            t_repr = repr_root * repr_child
    557557            t_repr._root = repr_child._root
    558             t_repr._baseline = t_repr._h - 1 
     558            t_repr._baseline = t_repr._h - 1
    559559            return t_repr
    560560        # General case
    561561        l_repr = [subtree._ascii_art_() for subtree in self]
    562562        acc = l_repr.pop(0)
    563563        whitesep = acc._root+1
    564         lf_sep = " "*(acc._root+1) + "_"*(acc._l-acc._root)
    565         ls_sep = " "*(acc._root) + "/" + " "*(acc._l-acc._root)
     564        lf_sep = " " * (acc._root + 1) + "_" * (acc._l - acc._root)
     565        ls_sep = " " * (acc._root) + "/" + " " * (acc._l - acc._root)
    566566        while len(l_repr) > 0:
    567567            t_repr = l_repr.pop(0)
    568568            acc += AsciiArt([" "]) + t_repr
    569             if len(l_repr) == 0: lf_sep += "_"*(t_repr._root+1)
    570             else: lf_sep += "_"*(t_repr._l+1)
    571             ls_sep += " "*(t_repr._root) + "/" + " "*(t_repr._l-t_repr._root)
    572         mid = whitesep + int((len(lf_sep)-whitesep)/2)
    573         node = node_to_str( self )
    574         t_repr = AsciiArt([lf_sep[:mid-1] + node + lf_sep[mid+len(node)-1:], ls_sep]) * acc
     569            if len(l_repr) == 0: lf_sep += "_" * (t_repr._root + 1)
     570            else: lf_sep += "_" * (t_repr._l + 1)
     571            ls_sep += " " * (t_repr._root) + "/" + \
     572                      " " * (t_repr._l - t_repr._root)
     573        mid = whitesep + int((len(lf_sep) - whitesep) / 2)
     574        node = node_to_str(self)
     575        t_repr = AsciiArt([lf_sep[:mid - 1] + node + \
     576                           lf_sep[mid + len(node) - 1:], ls_sep]) * acc
    575577        t_repr._root = mid
    576578        t_repr._baseline = t_repr._h - 1
    577579        return t_repr
    578580
    579     def canonical_labelling(self,shift=1):
     581    def canonical_labelling(self, shift=1):
    580582        """
    581583        Returns a labelled version of ``self``
    582584
  • sage/combinat/abstract_tree.py

    # HG changeset patch
    # User Jean-Baptiste Priez <jbp@kerios.fr>
    # Date 1371914316 -7200
    # Node ID 6cafbb0b9d9f48625496d32892e3308602a0ca09
    # Parent  9a0b4ff87ee4c1a5ceab2b733ff52e0c584f0c0f
    pep8 + doc for abstract trees
    
    diff --git a/sage/combinat/abstract_tree.py b/sage/combinat/abstract_tree.py
    a b class AbstractTree(object): 
    115115    """
    116116
    117117    def pre_order_traversal(self, action=lambda node: None):
    118         '''
     118        r'''
    119119        The depth first pre-order traversal algorithm.
    120120
    121121        INPUT:
    class AbstractTree(object): 
    192192                    stack.append(subtree)
    193193
    194194    def post_order_traversal(self, action=lambda node: None):
    195         '''
     195        r'''
    196196        The depth first post-order traversal algorithm.
    197197
    198198        INPUT:
    class AbstractTree(object): 
    263263        action(self)
    264264
    265265    def breadth_first_order_traversal(self, action=lambda node: None):
    266         '''
     266        r'''
    267267        The breadth first order traversal algorithm.
    268268
    269269        INPUT:
  • sage/combinat/binary_tree.py

    # HG changeset patch
    # User Jean-Baptiste Priez <jbp@kerios.fr>
    # Date 1371915749 -7200
    # Node ID 834cd270e607b1ba4f5a32591ff614ad26eddb4b
    # Parent  6cafbb0b9d9f48625496d32892e3308602a0ca09
    canonical permutation
    
    diff --git a/sage/combinat/binary_tree.py b/sage/combinat/binary_tree.py
    a b class BinaryTree(AbstractClonableTree, C 
    14381438        '''
    14391439        return self.under(bt)
    14401440
     1441    def canonical_permutation(self, left_to_right=True):
     1442        r'''
     1443        Compute the ``canonical permutation`` associated to the binary search
     1444        tree insertion from the `right` or the `left` of the permutation.
     1445
     1446        A ``canonical permutation`` `\sigma` of a tree `t` is the permutation
     1447        such that the shape of the binary search tree of `\sigma` is `t`.
     1448
     1449        TESTS::
     1450
     1451            sage: b = BinaryTree([[[],[]],[[],None]])
     1452            sage: b.canonical_permutation(False)
     1453            [1, 3, 2, 5, 6, 4]
     1454            sage: b.canonical_permutation(True)
     1455            [4, 2, 1, 3, 6, 5]
     1456            sage: b.canonical_permutation()
     1457            [4, 2, 1, 3, 6, 5]
     1458            sage: b.canonical_permutation().binary_search_tree().shape() == b
     1459            True
     1460            sage: b.canonical_permutation(False).binary_search_tree(False).\
     1461            ....:     shape() == b
     1462            True
     1463            sage: b.canonical_permutation(False).binary_search_tree().\
     1464            ....:     shape() == b
     1465            False
     1466            sage: b.canonical_permutation().binary_search_tree(False).\
     1467            ....:     shape() == b
     1468            False
     1469        '''
     1470        from sage.combinat.permutation import Permutation
     1471        assert(isinstance(left_to_right, bool))
     1472        l = []
     1473        if left_to_right:
     1474            self.canonical_labelling().pre_order_traversal(
     1475                lambda node: l.append(node.label())
     1476            )
     1477        else:
     1478            self.canonical_labelling().post_order_traversal(
     1479                lambda node: l.append(node.label())
     1480            )
     1481        return Permutation(l)
     1482
    14411483
    14421484from sage.structure.parent import Parent
    14431485from sage.structure.unique_representation import UniqueRepresentation