Ticket #8703: trac_8703-trees-rebased.patch

File trac_8703-trees-rebased.patch, 94.3 KB (added by tscrim, 6 years ago)
  • doc/en/reference/combinat/index.rst

    # HG changeset patch
    # User Florent Hivert <Florent.Hivert@lri.fr>
    # Date 1365675327 -7200
    # Node ID 2ff51d1ccbcb2ed4933afd9859921ab70458abeb
    # Parent c8ae9724d3cfad1837a130d50ac5c83a811ec221
    #8703: Enumerated sets and data structure for ordered and binary trees
    - The Class Abstract[Labelled]Tree allows for inheritance from different
      Cython classes.
    - Added shape on labelled trees.
    - Add a new function as_digraph() that maps a tree to the associated directed
      graph, with edges oriented away from from the root
    - Added canopee to binary trees.
    - Decreasing and increasing Binary tree of a permutations.
    - Added Binary tree insertion.
    - Added Binary search tree of a permutation
    - removed sage.misc.sagex_ds.BinaryTree from the interface.
    - Increase number of matches to "tree" in sagedoc.py doctest (#14433)
    
    diff --git a/doc/en/reference/combinat/index.rst b/doc/en/reference/combinat/index.rst
    a b Combinatorics 
    4343   sage/combinat/sidon_sets
    4444   sage/combinat/set_partition_ordered
    4545   sage/combinat/set_partition
     46   sage/combinat/abstract_tree
     47   sage/combinat/ordered_tree
     48   sage/combinat/binary_tree
    4649   sage/combinat/skew_partition
    4750   sage/combinat/subset
    4851   sage/combinat/subsets_pairwise
  • new file sage/combinat/abstract_tree.py

    diff --git a/sage/combinat/abstract_tree.py b/sage/combinat/abstract_tree.py
    new file mode 100644
    - +  
     1# -*- coding: utf-8 -*-
     2r"""
     3Abstract Recursive Trees
     4
     5The purpose of this class is to help implement trees with a specific structure
     6on the children of each node. For instance, one could want to define a tree in
     7which each node sees its children as linearly (see the :mod:`Ordered Trees
     8<sage.combinat.ordered_tree>` module) or cyclically ordered.
     9
     10**Tree structures**
     11
     12Conceptually, one can define a tree structure from any object that can contain
     13others. Indeed, a list can contain lists which contain lists which contain
     14lists, and thus define a tree ... The same can be done with sets, or any kind
     15of iterable objects.
     16
     17While any iterable is sufficient to encode trees, it can prove useful to have
     18other methods available like isomorphism tests (see next section), conversions
     19to DiGraphs objects (see :meth:`~.AbstractLabelledTree.as_digraph`) or
     20computation of the number of automorphisms constrained by the structure on
     21children. Providing such methods is the whole purpose of the
     22:class:`AbstractTree` class.
     23
     24As a result, the :class:`AbstractTree` class is not meant to be
     25instantiated, but extended. It is expected that classes extending this one may
     26also inherit from classes representing iterables, for instance
     27:class:`ClonableArray` or :class:`~sage.structure.list_clone.ClonableList`
     28
     29**Constrained Trees**
     30
     31The tree built from a specific container will reflect the properties of the
     32container. Indeed, if ``A`` is an iterable class whose elements are linearly
     33ordered, a class ``B`` extending both of :class:`AbstractTree` and ``A`` will
     34be such that the children of a node will be linearly ordered. If ``A`` behaves
     35like a set (i.e. if there is no order on the elements it contains), then two
     36trees will be considered as equal if one can be obtained from the other
     37through permutations between the children of a same node (see next section).
     38
     39**Paths and ID**
     40
     41It is expected that each element of a set of children should be identified by
     42its index in the container. This way, any node of the tree can be identified
     43by a word describing a path from the root node.
     44
     45**Canonical labellings**
     46
     47Equality between instances of classes extending both of :class:`AbstractTree`
     48and ``A`` is entirely defined by the equality defined on the elements of
     49``A``. A canonical labelling of such a tree however, should be such that two
     50trees ``a`` and ``b`` satisfying ``a == b`` should have the same canonical
     51labellings. On the other hand, the canonical labellings of trees ``a`` and
     52``b`` satisfying ``a != b`` are expected to be different.
     53
     54For this reason, the values returned by the :meth:`canonical_labelling
     55<AbstractTree.canonical_labelling>` method heavily
     56depend on the data structure used for a node's children and **should be**
     57**overridden** by most of the classes extending :class:`AbstractTree` if it is
     58incoherent with the data structure.
     59
     60**Authors**
     61
     62- Florent Hivert (2010-2011): initial revision
     63- Frédéric Chapoton (2011): contributed some methods
     64"""
     65
     66from sage.structure.list_clone import ClonableArray
     67from sage.rings.integer import Integer
     68from sage.misc.misc_c import prod
     69
     70# Unfortunately Cython forbids multiple inheritance. Therefore, we do not
     71# inherits from SageObject to be able to inherits from Element or a subclass
     72# of it later.
     73class AbstractTree(object):
     74    """
     75    Abstract Tree
     76
     77    There is no data structure defined here, as this class is meant to be
     78    extended, not instantiated.
     79
     80    .. rubric:: How should this class be extended ?
     81
     82    A class extending :class:`AbstractTree
     83    <sage.combinat.abstract_tree.AbstractTree>` should respect several
     84    assumptions:
     85
     86    * For a tree ``T``, the call ``iter(T)`` should return an iterator on the
     87      children of the root ``T``.
     88
     89    * The :meth:`canonical_labelling
     90      <AbstractTree.canonical_labelling>` method
     91      should return the same value for trees that are considered equal (see the
     92      "canonical labellings" section in the documentation of the
     93      :class:`AbstractTree <sage.combinat.abstract_tree.AbstractTree>` module).
     94
     95    * For a tree ``T`` the call ``T.parent().labelled_trees()`` should return
     96      a parent for labelled trees of the same kind: for example,
     97
     98      - if ``T`` is a binary tree, ``T.parent()`` is ``BinaryTrees()`` and
     99        ``T.parent().labelled_trees()`` is ``LabelledBinaryTrees()``
     100
     101      - if ``T`` is an ordered tree, ``T.parent()`` is ``OrderedTrees()`` and
     102        ``T.parent().labelled_trees()`` is ``LabelledOrderedTrees()``
     103
     104    TESTS::
     105
     106        sage: TestSuite(OrderedTree()).run()
     107        sage: TestSuite(BinaryTree()).run()
     108    """
     109
     110    def subtrees(self):
     111        """
     112        Returns a generator for all subtrees of ``self``
     113
     114        The number of subtrees of a tree is its number of elements.
     115
     116        EXAMPLES::
     117
     118            sage: list(OrderedTree([]).subtrees())
     119            [[]]
     120            sage: list(OrderedTree([[],[[]]]).subtrees())
     121            [[[], [[]]], [], [[]], []]
     122
     123            sage: list(BinaryTree([[],[[],[]]]).subtrees())
     124            [[[., .], [[., .], [., .]]], [., .], [[., .], [., .]], [., .], [., .]]
     125
     126        TESTS::
     127
     128            sage: t = OrderedTree([[], [[], [[], []], [[], []]], [[], []]])
     129            sage: t.node_number() == len(list(t.subtrees()))
     130            True
     131            sage: list(BinaryTree().subtrees())
     132            []
     133            sage: bt = BinaryTree([[],[[],[]]])
     134            sage: bt.node_number() == len(list(bt.subtrees()))
     135            True
     136        """
     137        if not self.is_empty():
     138            yield self
     139            for i in self:
     140                for t in i.subtrees():
     141                    yield t
     142
     143    def paths(self):
     144        """
     145        Returns a generator for all paths to nodes of ``self``
     146
     147        OUTPUT:
     148
     149        This method returns a list of sequences of integers. Each of these
     150        sequences represents a path from the root node to another one : `(1, 3,
     151        2, 5, 3)` represents the node obtained by chosing the 1st children of
     152        the root node (in the ordering returned by ``iter``), then the 3rd of
     153        its children, then the 2nd of this element, etc.
     154
     155        The root element is represented by the empty tuple ``()``.
     156
     157        EXAMPLES::
     158
     159            sage: list(OrderedTree([]).paths())
     160            [()]
     161            sage: list(OrderedTree([[],[[]]]).paths())
     162            [(), (0,), (1,), (1, 0)]
     163
     164            sage: list(BinaryTree([[],[[],[]]]).paths())
     165            [(), (0,), (1,), (1, 0), (1, 1)]
     166
     167        TESTS::
     168
     169            sage: t = OrderedTree([[], [[], [[], []], [[], []]], [[], []]])
     170            sage: t.node_number() == len(list(t.paths()))
     171            True
     172            sage: list(BinaryTree().paths())
     173            []
     174            sage: bt = BinaryTree([[],[[],[]]])
     175            sage: bt.node_number() == len(list(bt.paths()))
     176            True
     177        """
     178        if not self.is_empty():
     179            yield ()
     180            for i, t in enumerate(self):
     181                for p in t.paths():
     182                    yield (i,)+p
     183
     184    def node_number(self):
     185        """
     186        The number of nodes of ``self``
     187
     188        EXAMPLES::
     189
     190            sage: OrderedTree().node_number()
     191            1
     192            sage: OrderedTree([]).node_number()
     193            1
     194            sage: OrderedTree([[],[]]).node_number()
     195            3
     196            sage: OrderedTree([[],[[]]]).node_number()
     197            4
     198            sage: OrderedTree([[], [[], [[], []], [[], []]], [[], []]]).node_number()
     199            13
     200
     201        EXAMPLE::
     202
     203            sage: BinaryTree(None).node_number()
     204            0
     205            sage: BinaryTree([]).node_number()
     206            1
     207            sage: BinaryTree([[], None]).node_number()
     208            2
     209            sage: BinaryTree([[None, [[], []]], None]).node_number()
     210            5
     211        """
     212        if self.is_empty():
     213            return 0
     214        else:
     215            return sum((i.node_number() for i in self), Integer(1))
     216
     217    def depth(self):
     218        """
     219        The depth of ``self``
     220
     221        EXAMPLES::
     222
     223            sage: OrderedTree().depth()
     224            1
     225            sage: OrderedTree([]).depth()
     226            1
     227            sage: OrderedTree([[],[]]).depth()
     228            2
     229            sage: OrderedTree([[],[[]]]).depth()
     230            3
     231            sage: OrderedTree([[], [[], [[], []], [[], []]], [[], []]]).depth()
     232            4
     233
     234            sage: BinaryTree().depth()
     235            0
     236            sage: BinaryTree([[],[[],[]]]).depth()
     237            3
     238        """
     239        if self:
     240            return Integer(1 + max(i.depth() for i in self))
     241        else:
     242            return Integer(0 if self.is_empty() else 1)
     243
     244    def canonical_labelling(self,shift=1):
     245        """
     246        Returns a labelled version of ``self``
     247
     248        The actual canonical labelling is currently unspecified. However, it
     249        is guaranteed to have labels in `1...n` where `n` is the number of
     250        nodes of the tree. Moreover, two (unlabelled) trees compare as equal if
     251        and only if their canonical labelled trees compare as equal.
     252
     253        EXAMPLES::
     254
     255            sage: t = OrderedTree([[], [[], [[], []], [[], []]], [[], []]])
     256            sage: t.canonical_labelling()
     257            1[2[], 3[4[], 5[6[], 7[]], 8[9[], 10[]]], 11[12[], 13[]]]
     258
     259            sage: BinaryTree([]).canonical_labelling()
     260            1[., .]
     261            sage: BinaryTree([[],[[],[]]]).canonical_labelling()
     262            2[1[., .], 4[3[., .], 5[., .]]]
     263
     264        TESTS::
     265
     266            sage: BinaryTree().canonical_labelling()
     267            .
     268        """
     269        LTR = self.parent().labelled_trees()
     270        liste = []
     271        deca = 1
     272        for subtree in self:
     273            liste += [subtree.canonical_labelling(shift+deca)]
     274            deca += subtree.node_number()
     275        return LTR._element_constructor_(liste,label=shift)
     276
     277    def tree_factorial(self):
     278        """
     279        Returns the tree-factorial of ``self``
     280
     281        Definition:
     282
     283        The tree-factorial `T!` of a tree `T` is the product `\prod_{v\in
     284        T}\#\mbox{children}(v)`.
     285
     286        EXAMPLES::
     287
     288            sage: LT = LabelledOrderedTrees()
     289            sage: t = LT([LT([],label=6),LT([],label=1)],label=9)
     290            sage: t.tree_factorial()
     291            3
     292
     293            sage: BinaryTree([[],[[],[]]]).tree_factorial()
     294            15
     295
     296        TESTS::
     297
     298            sage: BinaryTree().tree_factorial()
     299            1
     300        """
     301        nb = self.node_number()
     302        if nb <= 1:
     303            return 1
     304        else:
     305            return nb*prod(s.tree_factorial() for s in self)
     306
     307    latex_unit_length   = "4mm"
     308    latex_node_diameter = "0.5"
     309    latex_root_diameter = "0.7"
     310
     311    def _latex_(self):
     312        """
     313        Returns a LaTeX version of ``self``
     314
     315        EXAMPLES::
     316
     317            sage: print(OrderedTree([[],[]])._latex_())
     318            \vcenter{\hbox{{\setlength\unitlength{4mm}
     319            \begin{picture}(4,3)
     320            \put(1,1){\circle*{0.5}}
     321            \put(2,2){\circle*{0.5}}
     322            \put(3,1){\circle*{0.5}}
     323            \put(2,2){\line(-1,-1){1}}
     324            \put(2,2){\line(1,-1){1}}
     325            \put(2,2){\circle*{0.7}}
     326            \end{picture}}}}
     327
     328        TESTS::
     329
     330            sage: OrderedTree([])._latex_()
     331            '\\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}}}}'
     332            sage: OrderedTree([[]])._latex_()
     333            '\\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}}}}'
     334            sage: OrderedTree([[], [[], [[], []], [[], []]], [[], []]])._latex_()
     335            '\\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}}}}'
     336        """
     337        from sage.misc.latex import latex
     338        drawing = [""] # allows modification of  in rec...
     339        x = [1]        # allows modification of x[0] in rec...
     340        max_label_width = [0] # allows modification of x[0] in rec...
     341        maxy = self.depth()
     342
     343        def rec(t, y):
     344            """
     345            Draw the subtree t on the drawing, below y (included) and to
     346            the right of x[0] (included). Update x[0]. Returns the horizontal
     347            position of the root
     348            """
     349            if t.node_number() == 0 : return -1
     350            n = len(t)
     351            posChild = [rec(t[i], y+1) for i in range(n // 2)]
     352            i = n // 2
     353            if n % 2 == 1:
     354                xc = rec(t[i], y+1)
     355                posChild.append(xc)
     356                i += 1
     357            else:
     358                xc = x[0]
     359                x[0] +=1
     360            drawing[0] = drawing[0] + "\\put(%s,%s){\\circle*{%s}}\n"%(
     361                xc, maxy-y, self.latex_node_diameter)
     362            try:
     363                lbl = t.label()
     364            except AttributeError:
     365                pass
     366            else:
     367                max_label_width[0] = 1 # TODO find a better heuristic
     368                drawing[0] = drawing[0] + "\\put(%s,%s){$\scriptstyle %s$}"%(
     369                    xc+0.3, maxy-y-0.3, latex(lbl))
     370            posChild += [rec(t[j], y+1) for j in range(i, n)]
     371            for i in range(n):
     372                if posChild[i] != -1:
     373                    drawing[0] = (drawing[0] +
     374                        "\\put(%s,%s){\\line(%s,-1){%s}}\n"%(
     375                            xc, maxy-y, posChild[i]-xc,
     376                            max(abs(posChild[i]-xc), 1)))
     377            return xc
     378
     379        res = rec(self, 0)
     380        drawing[0] = drawing[0] + "\\put(%s,%s){\\circle*{%s}}\n"%(
     381            res, maxy, self.latex_root_diameter)
     382        return "\\vcenter{\hbox{{\setlength\unitlength{%s}\n\\begin{picture}(%s,%s)\n%s\\end{picture}}}}"%(
     383            self.latex_unit_length,
     384            x[0] + max_label_width[0],
     385            maxy + 1,
     386            drawing[0])
     387
     388class AbstractClonableTree(AbstractTree):
     389    """
     390    Abstract Clonable Tree
     391
     392    An abstract class for trees with clone protocol (see
     393    :mod:`~sage.structure.list_clone`). It is expected that classes extending
     394    this one may also inherit from classes like :class:`ClonableArray` or
     395    :class:`~sage.structure.list_clone.ClonableList` depending wether one
     396    wants to build trees where adding a child is allowed.
     397
     398    .. NOTE:: Due to the limitation of Cython inheritance, one cannot inherit
     399       here from :class:`~sage.structure.list_clone.ClonableElement`, because
     400       it would prevent us to inherit later from
     401       :class:`~sage.structure.list_clone.ClonableArray` or
     402       :class:`~sage.structure.list_clone.ClonableList`.
     403
     404    .. rubric:: How should this class be extended ?
     405
     406    A class extending :class:`AbstractTree
     407    <sage.combinat.abstract_tree.AbstractTree>` should the following
     408    assumptions:
     409
     410    * An instantiable class extending :class:`AbstractTree
     411      <sage.combinat.abstract_tree.AbstractTree>` should also extend the
     412      :class:`ClonableElement <sage.structure.list_clone.ClonableElement>`
     413      class or one of its subclass generally at least :class:`ClonableArray
     414      <sage.structure.list_clone.ClonableArray>`.
     415
     416
     417    * To respect the Clone protocol, the :meth:`AbstractClonableTree.check`
     418      method should be overridden by the new class.
     419    """
     420    def check(self):
     421        """
     422        Check that ``self`` is a correct tree
     423
     424        This method does nothing. It is implemented here because many
     425        extensions of :class:`AbstractTree
     426        <sage.combinat.abstract_tree.AbstractTree>` also extend
     427        :class:`sage.structure.list_clone.ClonableElement`, which requires it.
     428
     429        It should be overriden in subclass in order to check that the
     430        invariant of the kind of tree holds (eg: two children for binary
     431        trees).
     432
     433        EXAMPLES::
     434
     435            sage: OrderedTree([[],[[]]]).check()
     436            sage: BinaryTree([[],[[],[]]]).check()
     437        """
     438        pass
     439
     440    def __setitem__(self, idx, value):
     441        """
     442        Substitute a subtree
     443
     444        .. NOTE::
     445
     446            The tree ``self`` must be in a mutable state. See
     447            :mod:`sage.structure.list_clone` for more details about
     448            mutability.  The default implementation here assume that the
     449            container of the node implement a method `_setitem` with signature
     450            `self._setitem(idx, value)`. It is usually provided by inheriting
     451            from :class:`~sage.structure.list_clone.ClonableArray`.
     452
     453        INPUT:
     454
     455        - ``idx`` -- a valid path in ``self`` identifying a node
     456
     457        - ``value`` -- the tree to be substituted
     458
     459        EXAMPLES:
     460
     461        Trying to modify a non mutable tree raises an error::
     462
     463            sage: x = OrderedTree([])
     464            sage: x[0] =  OrderedTree([[]])
     465            Traceback (most recent call last):
     466            ...
     467            ValueError: object is immutable; please change a copy instead.
     468
     469        Here is the correct way to do it::
     470
     471            sage: x = OrderedTree([[],[[]]])
     472            sage: with x.clone() as x:
     473            ...    x[0] = OrderedTree([[]])
     474            sage: x
     475            [[[]], [[]]]
     476
     477        One can also substitute at any depth::
     478
     479            sage: y = OrderedTree(x)
     480            sage: with x.clone() as x:
     481            ...    x[0,0] = OrderedTree([[]])
     482            sage: x
     483            [[[[]]], [[]]]
     484            sage: y
     485            [[[]], [[]]]
     486            sage: with y.clone() as y:
     487            ...    y[(0,)] = OrderedTree([])
     488            sage: y
     489            [[], [[]]]
     490
     491        This works for binary trees as well::
     492
     493            sage: bt = BinaryTree([[],[[],[]]]); bt
     494            [[., .], [[., .], [., .]]]
     495            sage: with bt.clone() as bt1:
     496            ...    bt1[0,0] = BinaryTree([[[], []], None])
     497            sage: bt1
     498            [[[[[., .], [., .]], .], .], [[., .], [., .]]]
     499
     500        TESTS::
     501
     502            sage: x = OrderedTree([])
     503            sage: with x.clone() as x:
     504            ...    x[0] = OrderedTree([[]])
     505            Traceback (most recent call last):
     506            ...
     507            IndexError: list assignment index out of range
     508
     509            sage: x = OrderedTree([]); x = OrderedTree([x,x]);x = OrderedTree([x,x]); x = OrderedTree([x,x])
     510            sage: with x.clone() as x:
     511            ...    x[0,0] = OrderedTree()
     512            sage: x
     513            [[[], [[], []]], [[[], []], [[], []]]]
     514        """
     515        if not isinstance(value, self.__class__):
     516            raise TypeError('the given value is not a tree')
     517        if isinstance(idx, tuple):
     518            self.__setitem_rec__(idx, 0, value)
     519        else:
     520            self._setitem(idx, value)
     521
     522    def __setitem_rec__(self, idx, i, value):
     523        """
     524        TESTS::
     525
     526            sage: x = OrderedTree([[[], []],[[]]])
     527            sage: with x.clone() as x:
     528            ...    x[0,1] = OrderedTree([[[]]]) # indirect doctest
     529            sage: x
     530            [[[], [[[]]]], [[]]]
     531        """
     532        if i == len(idx) - 1:
     533            self._setitem(idx[-1], value)
     534        else:
     535            with self[idx[i]].clone() as child:
     536                child.__setitem_rec__(idx, i+1, value)
     537            self[idx[i]] = child
     538
     539    def __getitem__(self, idx):
     540        """
     541        INPUT:
     542
     543        - ``idx`` -- a valid path in ``self`` identifying a node
     544
     545        .. NOTE::
     546
     547            The default implementation here assumes that the container of the
     548            node inherits from
     549            :class:`~sage.structure.list_clone.ClonableArray`.
     550
     551        EXAMPLES::
     552
     553            sage: x = OrderedTree([[],[[]]])
     554            sage: x[1,0]
     555            []
     556            sage: x = OrderedTree([[],[[]]])
     557            sage: x[()]
     558            [[], [[]]]
     559            sage: x[(0,)]
     560            []
     561            sage: x[0,0]
     562            Traceback (most recent call last):
     563            ...
     564            IndexError: list index out of range
     565        """
     566        if isinstance(idx, slice):
     567            return ClonableArray.__getitem__(self, idx)
     568        try:
     569            i = int(idx)
     570        except TypeError:
     571            res = self
     572            # idx is supposed to be an iterable of ints
     573            for i in idx:
     574                res = ClonableArray._getitem(res, i)
     575            return res
     576        else:
     577            return ClonableArray._getitem(self, i)
     578
     579
     580class AbstractLabelledTree(AbstractTree):
     581    """
     582    Abstract Labelled Tree
     583
     584    Typically a class for labelled tree is contructed by inheriting from a
     585    class for unlabelled trees and :class:`AbstractLabelledTree`
     586
     587    .. rubric:: How should this class be extended ?
     588
     589    A class extending :class:`AbstractLabelledTree
     590    <sage.combinat.abstract_tree.AbstractLabelledTree>` should respect the
     591    following assumptions:
     592
     593    * For a labelled tree ``T`` the call ``T.parent().unlabelled_trees()``
     594      should return a parent for labelled trees of the same kind: for example,
     595
     596      - if ``T`` is a binary labelled tree, ``T.parent()`` is
     597        ``LabelledBinaryTrees()`` and ``T.parent().unlabelled_trees()`` is
     598        ``BinaryTrees()``
     599
     600      - if ``T`` is an ordered labelled tree, ``T.parent()`` is
     601        ``LabelledOrderedTrees()`` and ``T.parent().unlabelled_trees()`` is
     602        ``OrderedTrees()``
     603
     604    * In the same vein, the class of ``T`` should contain an attribute
     605      ``_Unlabelled`` which should be the class for the corresponding
     606      unlabelled trees.
     607
     608    .. SEEALSO:: :class:`AbstractTree`
     609    """
     610    def __init__(self, parent, children, label = None, check = True):
     611        """
     612        TESTS::
     613
     614            sage: LabelledOrderedTree([])
     615            None[]
     616            sage: LabelledOrderedTree([], 3)
     617            3[]
     618            sage: LT = LabelledOrderedTree
     619            sage: t = LT([LT([LT([], label=42), LT([], 21)])], label=1)
     620            sage: t
     621            1[None[42[], 21[]]]
     622            sage: LabelledOrderedTree(OrderedTree([[],[[],[]],[]]))
     623            None[None[], None[None[], None[]], None[]]
     624        """
     625        # We must initialize the label before the subtrees to allows rooted
     626        # trees canonization. Indeed it needs that ``self``._hash_() is working
     627        # at the end of the call super(..., self).__init__(...)
     628        if isinstance(children, self.__class__):
     629            if label is None:
     630                self._label = children._label
     631            else:
     632                self._label = label
     633        else:
     634            self._label = label
     635        super(AbstractLabelledTree, self).__init__(parent, children, check=check)
     636
     637    def _repr_(self):
     638        """
     639        Returns the string representation of ``self``
     640
     641        TESTS::
     642
     643            sage: LabelledOrderedTree([])            # indirect doctest
     644            None[]
     645            sage: LabelledOrderedTree([], label=3)   # indirect doctest
     646            3[]
     647            sage: LabelledOrderedTree([[],[[]]])     # indirect doctest
     648            None[None[], None[None[]]]
     649            sage: LabelledOrderedTree([[],LabelledOrderedTree([[]], label=2)], label=3)
     650            3[None[], 2[None[]]]
     651        """
     652        return "%s%s"%(self._label, self[:])
     653
     654    def label(self, path=None):
     655        """
     656        Returns the label of ``self``
     657
     658        INPUT:
     659
     660        - ``path`` -- None (default) or a path (list or tuple of children index
     661                     in the tree)
     662
     663        OUTPUT: the label of the subtree indexed by ``path``
     664
     665        EXAMPLES::
     666
     667            sage: t = LabelledOrderedTree([[],[]], label = 3)
     668            sage: t.label()
     669            3
     670            sage: t[0].label()
     671            sage: t = LabelledOrderedTree([LabelledOrderedTree([], 5),[]], label = 3)
     672            sage: t.label()
     673            3
     674            sage: t[0].label()
     675            5
     676            sage: t[1].label()
     677            sage: t.label([0])
     678            5
     679        """
     680        if path is None:
     681            return self._label
     682        else:
     683            tr = self
     684            for i in path:
     685                tr = tr[i]
     686            return tr._label
     687
     688    def labels(self):
     689        """
     690        Returns the list of labels of ``self``
     691
     692        EXAMPLES::
     693
     694            sage: LT = LabelledOrderedTree
     695            sage: t = LT([LT([],label='b'),LT([],label='c')],label='a')
     696            sage: t.labels()
     697            ['a', 'b', 'c']
     698
     699            sage: LBT = LabelledBinaryTree
     700            sage: LBT([LBT([],label=1),LBT([],label=4)],label=2).labels()
     701            [2, 1, 4]
     702        """
     703        return [t.label() for t in self.subtrees()]
     704
     705    def leaf_labels(self):
     706        """
     707        Returns the list of labels of the leaves of ``self``
     708
     709        EXAMPLES::
     710
     711            sage: LT = LabelledOrderedTree
     712            sage: t = LT([LT([],label='b'),LT([],label='c')],label='a')
     713            sage: t.leaf_labels()
     714            ['b', 'c']
     715
     716            sage: LBT = LabelledBinaryTree
     717            sage: bt = LBT([LBT([],label='b'),LBT([],label='c')],label='a')
     718            sage: bt.leaf_labels()
     719            ['b', 'c']
     720            sage: LBT([], label='1').leaf_labels()
     721            ['1']
     722            sage: LBT(None).leaf_labels()
     723            []
     724        """
     725        return [t.label() for t in self.subtrees() if t.node_number()==1]
     726
     727    def __eq__(self, other):
     728        """
     729        Tests if ``self`` is equal to ``other``
     730
     731        TESTS::
     732
     733            sage  LabelledOrderedTree() == LabelledOrderedTree()
     734            True
     735            sage  LabelledOrderedTree([]) == LabelledOrderedTree()
     736            False
     737            sage: t1 = LabelledOrderedTree([[],[[]]])
     738            sage: t2 = LabelledOrderedTree([[],[[]]])
     739            sage: t1 == t2
     740            True
     741            sage: t2 = LabelledOrderedTree(t1)
     742            sage: t1 == t2
     743            True
     744            sage: t1 = LabelledOrderedTree([[],[[]]])
     745            sage: t2 = LabelledOrderedTree([[[]],[]])
     746            sage: t1 == t2
     747            False
     748        """
     749        return ( super(AbstractLabelledTree, self).__eq__(other) and
     750                 self._label == other._label )
     751
     752    def _hash_(self):
     753        """
     754        Returns the hash value for ``self``
     755
     756        TESTS::
     757
     758            sage: t1 = LabelledOrderedTree([[],[[]]], label = 1); t1hash = t1.__hash__()
     759            sage: LabelledOrderedTree([[],[[]]], label = 1).__hash__() == t1hash
     760            True
     761            sage: LabelledOrderedTree([[[]],[]], label = 1).__hash__() == t1hash
     762            False
     763            sage: LabelledOrderedTree(t1, label = 1).__hash__() == t1hash
     764            True
     765            sage: LabelledOrderedTree([[],[[]]], label = 25).__hash__() == t1hash
     766            False
     767            sage: LabelledOrderedTree(t1, label = 25).__hash__() == t1hash
     768            False
     769
     770            sage: LabelledBinaryTree([[],[[],[]]], label = 25).__hash__() #random
     771            8544617749928727644
     772
     773        We check that the hash value depends on the value of the labels of the
     774        subtrees::
     775
     776            sage: LBT = LabelledBinaryTree
     777            sage: t1 = LBT([], label = 1)
     778            sage: t2 = LBT([], label = 2)
     779            sage: t3 = LBT([], label = 3)
     780            sage: t12 = LBT([t1, t2], label = "a")
     781            sage: t13 = LBT([t1, t3], label = "a")
     782            sage: t12.__hash__() != t13.__hash__()
     783            True
     784        """
     785        return self._UnLabelled._hash_(self) ^ hash(self._label)
     786
     787    def shape(self):
     788        """
     789        Returns the unlabelled tree associated to ``self``
     790
     791        EXAMPLES::
     792
     793            sage: t = LabelledOrderedTree([[],[[]]], label = 25).shape(); t
     794            [[], [[]]]
     795
     796            sage: LabelledBinaryTree([[],[[],[]]], label = 25).shape()
     797            [[., .], [[., .], [., .]]]
     798
     799        TESTS::
     800
     801            sage: t.parent()
     802            Ordered trees
     803            sage: type(t)
     804            <class 'sage.combinat.ordered_tree.OrderedTrees_all_with_category.element_class'>
     805        """
     806        TR = self.parent().unlabelled_trees()
     807        if not self:
     808            return TR.leaf()
     809        else:
     810            return TR._element_constructor_([i.shape() for i in self])
     811
     812    def as_digraph(self):
     813        """
     814        Returns a directed graph version of ``self``.
     815
     816        .. WARNING::
     817
     818            At this time, the output makes sense only if ``self`` is a
     819            labelled binary tree with no repeated labels and no ``None``
     820            labels.
     821
     822        EXAMPLES::
     823
     824           sage: LT = LabelledOrderedTrees()
     825           sage: t1 = LT([LT([],label=6),LT([],label=1)],label=9)
     826           sage: t1.as_digraph()
     827           Digraph on 3 vertices
     828
     829           sage: t = BinaryTree([[None, None],[[],None]]);
     830           sage: lt = t.canonical_labelling()
     831           sage: lt.as_digraph()
     832           Digraph on 4 vertices
     833        """
     834        from sage.graphs.digraph import DiGraph
     835        resu = dict([[self.label(),
     836                    [t.label() for t in self if not t.is_empty()]]])
     837        resu = DiGraph(resu)
     838        for t in self:
     839            if not t.is_empty():
     840                resu = resu.union(t.as_digraph())
     841        return resu
     842
     843
     844class AbstractLabelledClonableTree(AbstractLabelledTree,
     845                                   AbstractClonableTree):
     846    """
     847    Abstract Labelled Clonable Tree
     848
     849    This class takes care of modification for the label by the clone protocol.
     850
     851    .. NOTE:: Due to the limitation of Cython inheritance, one cannot inherit
     852       here from :class:`ClonableArray`, because it would prevent us to
     853       inherit later from :class:`~sage.structure.list_clone.ClonableList`.
     854    """
     855    def set_root_label(self, label):
     856        """
     857        Sets the label of the root of ``self``
     858
     859        INPUT: ``label`` -- any Sage object
     860
     861        OUPUT: ``None``, ``self`` is modified in place
     862
     863        .. NOTE::
     864
     865            ``self`` must be in a mutable state. See
     866            :mod:`sage.structure.list_clone` for more details about
     867            mutability.
     868
     869        EXAMPLES::
     870
     871            sage: t = LabelledOrderedTree([[],[[],[]]])
     872            sage: t.set_root_label(3)
     873            Traceback (most recent call last):
     874            ...
     875            ValueError: object is immutable; please change a copy instead.
     876            sage: with t.clone() as t:
     877            ...    t.set_root_label(3)
     878            sage: t.label()
     879            3
     880            sage: t
     881            3[None[], None[None[], None[]]]
     882
     883        This also works for binary trees::
     884
     885            sage: bt = LabelledBinaryTree([[],[]])
     886            sage: bt.set_root_label(3)
     887            Traceback (most recent call last):
     888            ...
     889            ValueError: object is immutable; please change a copy instead.
     890            sage: with bt.clone() as bt:
     891            ...    bt.set_root_label(3)
     892            sage: bt.label()
     893            3
     894            sage: bt
     895            3[None[., .], None[., .]]
     896
     897        TESTS::
     898
     899            sage: with t.clone() as t:
     900            ...    t[0] = LabelledOrderedTree(t[0], label = 4)
     901            sage: t
     902            3[4[], None[None[], None[]]]
     903            sage: with t.clone() as t:
     904            ...    t[1,0] = LabelledOrderedTree(t[1,0], label = 42)
     905            sage: t
     906            3[4[], None[42[], None[]]]
     907            """
     908        self._require_mutable()
     909        self._label = label
     910
     911    def set_label(self, path, label):
     912        """
     913        Changes the label of subtree indexed by ``path`` to ``label``
     914
     915        INPUT:
     916
     917        - ``path`` -- ``None`` (default) or a path (list or tuple of children
     918                      index in the tree)
     919
     920        - ``label`` -- any sage object
     921
     922        OUPUT: Nothing, ``self`` is modified in place
     923
     924        .. NOTE::
     925
     926            ``self`` must be in a mutable state. See
     927            :mod:`sage.structure.list_clone` for more details about
     928            mutability.
     929
     930        EXAMPLES::
     931
     932            sage: t = LabelledOrderedTree([[],[[],[]]])
     933            sage: t.set_label((0,), 4)
     934            Traceback (most recent call last):
     935            ...
     936            ValueError: object is immutable; please change a copy instead.
     937            sage: with t.clone() as t:
     938            ...    t.set_label((0,), 4)
     939            sage: t
     940            None[4[], None[None[], None[]]]
     941            sage: with t.clone() as t:
     942            ...    t.set_label((1,0), label = 42)
     943            sage: t
     944            None[4[], None[42[], None[]]]
     945
     946        .. TODO::
     947
     948            Do we want to implement the following syntactic sugar::
     949
     950                with t.clone() as tt:
     951                    tt.labels[1,2] = 3 ?
     952        """
     953        self._require_mutable()
     954        path = tuple(path)
     955        if path == ():
     956            self._label = label
     957        else:
     958            with self[path[0]].clone() as child:
     959                child.set_label(path[1:], label)
     960            self[path[0]] = child
     961
     962    def map_labels(self, f):
     963        """
     964        Applies the function `f` to the labels of ``self``
     965
     966        This method returns a copy of ``self`` on which the function `f` has
     967        been applied on all labels (a label `x` is replaced by `f(x)`).
     968
     969        EXAMPLES::
     970
     971            sage: LT = LabelledOrderedTree
     972            sage: t = LT([LT([],label=1),LT([],label=7)],label=3); t
     973            3[1[], 7[]]
     974            sage: t.map_labels(lambda z:z+1)
     975            4[2[], 8[]]
     976
     977            sage: LBT = LabelledBinaryTree
     978            sage: bt = LBT([LBT([],label=1),LBT([],label=4)],label=2); bt
     979            2[1[., .], 4[., .]]
     980            sage: bt.map_labels(lambda z:z+1)
     981            3[2[., .], 5[., .]]
     982        """
     983        if self.is_empty():
     984            return self
     985        return self.parent()([t.map_labels(f) for t in self],
     986                             label=f(self.label()))
  • sage/combinat/all.py

    diff --git a/sage/combinat/all.py b/sage/combinat/all.py
    a b from alternating_sign_matrix import Alte 
    8181# Non Decreasing Parking Functions
    8282from non_decreasing_parking_function import NonDecreasingParkingFunctions, NonDecreasingParkingFunction
    8383
     84from ordered_tree import (OrderedTree, OrderedTrees,
     85                          LabelledOrderedTree, LabelledOrderedTrees)
     86from binary_tree import (BinaryTree, BinaryTrees,
     87                         LabelledBinaryTree, LabelledBinaryTrees)
    8488
    8589from combination import Combinations
    8690from cartesian_product import CartesianProduct
  • new file sage/combinat/binary_tree.py

    diff --git a/sage/combinat/binary_tree.py b/sage/combinat/binary_tree.py
    new file mode 100644
    - +  
     1"""
     2Binary trees
     3
     4This module deals with binary trees as mathematical (in particular immmutable)
     5objects.
     6
     7.. NOTE :: If you need the data-structure for example to represent sets or hash
     8           tables with AVL trees, you should have a look at
     9           :mod:`sage.misc.sagex_ds`.
     10
     11**AUTHORS:**
     12
     13- Florent Hivert (2010-2011): initial implementation.
     14"""
     15#*****************************************************************************
     16#       Copyright (C) 2010 Florent Hivert <Florent.Hivert@univ-rouen.fr>,
     17#
     18#  Distributed under the terms of the GNU General Public License (GPL)
     19#  as published by the Free Software Foundation; either version 2 of
     20#  the License, or (at your option) any later version.
     21#                  http://www.gnu.org/licenses/
     22#*****************************************************************************
     23from sage.structure.list_clone import ClonableArray
     24from sage.combinat.abstract_tree import (AbstractClonableTree,
     25                                         AbstractLabelledClonableTree)
     26from sage.combinat.ordered_tree import LabelledOrderedTrees
     27from sage.rings.integer import Integer
     28from sage.misc.classcall_metaclass import ClasscallMetaclass
     29from sage.misc.lazy_attribute import lazy_attribute, lazy_class_attribute
     30
     31class BinaryTree(AbstractClonableTree, ClonableArray):
     32    """
     33    The class of binary trees
     34
     35    Binary trees here mean ordered (a.k.a. plane) binary trees,
     36    meaning that the children of each node are ordered.
     37
     38    INPUT:
     39
     40    - ``children`` -- ``None`` (default) or a list, tuple or iterable of
     41      length 2 of binary trees or convertible objects. This corresponds to
     42      the standard recursive definition of a binary tree as either a leaf
     43      or a pair of binary trees. Syntactic sugar allows leaving out all
     44      but the outermost calls of the ``BinaryTree()`` constructor, so that,
     45      e. g., ``BinaryTree([BinaryTree(None),BinaryTree(None)])`` can be
     46      simplified to ``BinaryTree([None,None])``. It is also allowed to
     47      abbreviate ``[None, None]`` by ``[]``.
     48
     49    - ``check`` -- (default to ``True``) whether check for binary should be
     50      performed or not.
     51
     52    EXAMPLES::
     53
     54        sage: BinaryTree()
     55        .
     56        sage: BinaryTree(None)
     57        .
     58        sage: BinaryTree([])
     59        [., .]
     60        sage: BinaryTree([None, None])
     61        [., .]
     62        sage: BinaryTree([None, []])
     63        [., [., .]]
     64        sage: BinaryTree([[], None])
     65        [[., .], .]
     66        sage: BinaryTree("[[], .]")
     67        [[., .], .]
     68
     69        sage: BinaryTree([[], None, []])
     70        Traceback (most recent call last):
     71        ...
     72        ValueError: this is not a binary tree
     73
     74    TESTS::
     75
     76        sage: t1 = BinaryTree([[None, [[],[[], None]]],[[],[]]])
     77        sage: t2 = BinaryTree([[[],[]],[]])
     78        sage: with t1.clone() as t1c:
     79        ...       t1c[1,1,1] = t2
     80        sage: t1 == t1c
     81        False
     82    """
     83    __metaclass__ = ClasscallMetaclass
     84
     85    @staticmethod
     86    def __classcall_private__(cls, *args, **opts):
     87        """
     88        Ensure that binary trees created by the enumerated sets and directly
     89        are the same and that they are instances of :class:`BinaryTree`
     90
     91        TESTS::
     92
     93            sage: from sage.combinat.binary_tree import BinaryTrees_all
     94            sage: issubclass(BinaryTrees_all().element_class, BinaryTree)
     95            True
     96            sage: t0 = BinaryTree([[],[[], None]])
     97            sage: t0.parent()
     98            Binary trees
     99            sage: type(t0)
     100            <class 'sage.combinat.binary_tree.BinaryTrees_all_with_category.element_class'>
     101
     102            sage: t1 = BinaryTrees()([[],[[], None]])
     103            sage: t1.parent() is t0.parent()
     104            True
     105            sage: type(t1) is type(t0)
     106            True
     107
     108            sage: t1 = BinaryTrees(4)([[],[[], None]])
     109            sage: t1.parent() is t0.parent()
     110            True
     111            sage: type(t1) is type(t0)
     112            True
     113        """
     114        return cls._auto_parent.element_class(cls._auto_parent, *args, **opts)
     115
     116    @lazy_class_attribute
     117    def _auto_parent(cls):
     118        """
     119        The automatic parent of the element of this class
     120
     121        When calling the constructor of an element of this class, one needs a
     122        parent. This class attribute specifies which parent is used.
     123
     124        EXAMPLES::
     125
     126            sage: BinaryTree._auto_parent
     127            Binary trees
     128            sage: BinaryTree([None, None]).parent()
     129            Binary trees
     130         """
     131        return BinaryTrees_all()
     132
     133    def __init__(self, parent, children = None, check = True):
     134        """
     135        TESTS::
     136
     137            sage: BinaryTree([None, None]).parent()
     138            Binary trees
     139            sage: BinaryTree("[., [., [., .]]]")
     140            [., [., [., .]]]
     141            sage: BinaryTree("[.,.,.]")
     142            Traceback (most recent call last):
     143            ...
     144            ValueError: this is not a binary tree
     145            sage: all(BinaryTree(repr(bt)) == bt for i in range(6) for bt in BinaryTrees(i))
     146            True
     147        """
     148        if (type(children) is str):  # if the input is the repr of a binary tree
     149            children = children.replace(".","None")
     150            from ast import literal_eval
     151            children = literal_eval(children)
     152        if children is None:
     153            children = []
     154        elif (children == [] or children == ()
     155              or isinstance(children, (Integer, int))):
     156            children = [None, None]
     157        if (children.__class__ is self.__class__ and
     158            children.parent() == parent):
     159            children = list(children)
     160        else:
     161            children = [self.__class__(parent, x) for x in children]
     162        ClonableArray.__init__(self, parent, children, check=check)
     163
     164    def check(self):
     165        """
     166        Checks that ``self`` is a binary tree
     167
     168        EXAMPLES::
     169
     170            sage: BinaryTree([[], []])     # indirect doctest
     171            [[., .], [., .]]
     172            sage: BinaryTree([[], [], []]) # indirect doctest
     173            Traceback (most recent call last):
     174            ...
     175            ValueError: this is not a binary tree
     176            sage: BinaryTree([[]])         # indirect doctest
     177            Traceback (most recent call last):
     178            ...
     179            ValueError: this is not a binary tree
     180        """
     181        if not (not self or len(self) == 2):
     182            raise ValueError("this is not a binary tree")
     183
     184    def _repr_(self):
     185        """
     186        TESTS::
     187
     188            sage: t1 = BinaryTree([[], None]); t1  # indirect doctest
     189            [[., .], .]
     190            sage: BinaryTree([[None, t1], None])   # indirect doctest
     191            [[., [[., .], .]], .]
     192        """
     193        if not self:
     194            return "."
     195        else:
     196            return super(BinaryTree, self)._repr_()
     197
     198    def is_empty(self):
     199        """
     200        Returns whether ``self`` is  empty.
     201
     202        EXAMPLES::
     203
     204            sage: BinaryTree().is_empty()
     205            True
     206            sage: BinaryTree([]).is_empty()
     207            False
     208            sage: BinaryTree([[], None]).is_empty()
     209            False
     210        """
     211        return not self
     212
     213    def graph(self):
     214        """
     215        Convert ``self`` to a digraph
     216
     217        EXAMPLE::
     218
     219            sage: t1 = BinaryTree([[], None])
     220            sage: t1.graph()
     221            Digraph on 5 vertices
     222
     223            sage: t1 = BinaryTree([[], [[], None]])
     224            sage: t1.graph()
     225            Digraph on 9 vertices
     226            sage: t1.graph().edges()
     227            [(0, 1, None), (0, 4, None), (1, 2, None), (1, 3, None), (4, 5, None), (4, 8, None), (5, 6, None), (5, 7, None)]
     228        """
     229        from sage.graphs.graph import DiGraph
     230        res = DiGraph()
     231        def rec(tr, idx):
     232            if not tr:
     233                return
     234            else:
     235                nbl = 2*tr[0].node_number() + 1
     236                res.add_edges([[idx,idx+1], [idx,idx+1+nbl]])
     237                rec(tr[0], idx + 1)
     238                rec(tr[1], idx + nbl + 1)
     239        rec(self, 0)
     240        return res
     241
     242    def canonical_labelling(self,shift=1):
     243        """
     244        Returns a labelled version of ``self``.
     245
     246        The actual canonical labelling is currently unspecified. However, it
     247        is guaranteed to have labels in `1...n` where `n` is the number of
     248        nodes of the tree. Moreover, two (unlabelled) trees compare as equal if
     249        and only if their canonical labelled trees compare as equal.
     250
     251        EXAMPLES::
     252
     253            sage: BinaryTree().canonical_labelling()
     254            .
     255            sage: BinaryTree([]).canonical_labelling()
     256            1[., .]
     257            sage: BinaryTree([[[], [[], None]], [[], []]]).canonical_labelling()
     258            5[2[1[., .], 4[3[., .], .]], 7[6[., .], 8[., .]]]
     259        """
     260        LTR = self.parent().labelled_trees()
     261        if self:
     262            sz0 = self[0].node_number()
     263            return LTR([self[0].canonical_labelling(shift),
     264                        self[1].canonical_labelling(shift+1+sz0)],
     265                       label=shift+sz0)
     266        else:
     267            return LTR(None)
     268
     269    def show(self):
     270        """
     271        TESTS::
     272
     273            sage: t1 = BinaryTree([[], [[], None]])
     274            sage: t1.show()
     275        """
     276        self.graph().show(layout='tree', tree_root=0, tree_orientation="down")
     277
     278    def make_node(self, child_list = [None, None]):
     279        """
     280        Modify ``self`` so that it becomes a node with children ``childlist``
     281
     282        INPUT:
     283
     284        - ``child_list`` -- a pair of binary trees (or objects convertible to)
     285
     286        .. NOTE:: ``self`` must be in a mutable state.
     287
     288        .. SEEALSO::
     289            :meth:`make_leaf <sage.combinat.binary_tree.BinaryTree.make_leaf>`
     290
     291        EXAMPLES::
     292
     293            sage: t = BinaryTree()
     294            sage: t.make_node([None, None])
     295            Traceback (most recent call last):
     296            ...
     297            ValueError: object is immutable; please change a copy instead.
     298            sage: with t.clone() as t1:
     299            ...    t1.make_node([None, None])
     300            sage: t, t1
     301            (., [., .])
     302            sage: with t.clone() as t:
     303            ...    t.make_node([BinaryTree(), BinaryTree(), BinaryTree([])])
     304            Traceback (most recent call last):
     305            ...
     306            ValueError: the list must have length 2
     307            sage: with t1.clone() as t2:
     308            ...    t2.make_node([t1, t1])
     309            sage: with t2.clone() as t3:
     310            ...    t3.make_node([t1, t2])
     311            sage: t1, t2, t3
     312            ([., .], [[., .], [., .]], [[., .], [[., .], [., .]]])
     313        """
     314        self._require_mutable()
     315        child_lst = [self.__class__(self.parent(), x) for x in child_list]
     316        if not(len(child_lst) == 2):
     317            raise ValueError("the list must have length 2")
     318        self.__init__(self.parent(), child_lst, check=False)
     319
     320    def make_leaf(self):
     321        """
     322        Modify ``self`` so that it became a leaf
     323
     324        .. NOTE:: ``self`` must be in a mutable state.
     325
     326        .. SEEALSO::
     327            :meth:`make_node <sage.combinat.binary_tree.BinaryTree.make_node>`
     328
     329        EXAMPLES::
     330
     331            sage: t = BinaryTree([None, None])
     332            sage: t.make_leaf()
     333            Traceback (most recent call last):
     334            ...
     335            ValueError: object is immutable; please change a copy instead.
     336            sage: with t.clone() as t1:
     337            ...    t1.make_leaf()
     338            sage: t, t1
     339            ([., .], .)
     340        """
     341        self._require_mutable()
     342        self.__init__(self.parent(), None)
     343
     344    def _to_dyck_word_rec(self):
     345        r"""
     346        EXAMPLES::
     347
     348            sage: BinaryTree()._to_dyck_word_rec()
     349            []
     350            sage: BinaryTree([])._to_dyck_word_rec()
     351            [1, 0]
     352            sage: BinaryTree([[[], [[], None]], [[], []]])._to_dyck_word_rec()
     353            [1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0]
     354        """
     355        if self:
     356            return ([1]+self[0]._to_dyck_word_rec()+
     357                    [0]+self[1]._to_dyck_word_rec())
     358        else:
     359            return []
     360
     361    def to_dyck_word(self):
     362        r"""
     363        Return the Dyck word associated to ``self``
     364
     365        The bijection is defined recursively as follows:
     366
     367        - a leaf is associated to the empty Dyck Word
     368
     369        - a tree with chidren `l,r` is associated to the Dyck word
     370          `1 T(l) 0 T(r)` where `T(l)` and `T(r)` are the Dyck words
     371          associated to `l` and `r`.
     372
     373        EXAMPLES::
     374
     375            sage: BinaryTree().to_dyck_word()
     376            []
     377            sage: BinaryTree([]).to_dyck_word()
     378            [1, 0]
     379            sage: BinaryTree([[[], [[], None]], [[], []]]).to_dyck_word()
     380            [1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0]
     381        """
     382        from sage.combinat.dyck_word import DyckWord
     383        return DyckWord(self._to_dyck_word_rec())
     384
     385    def canopee(self):
     386        """
     387        Returns the canopee of ``self``
     388
     389        The *canopee* of a non empty binary tree `T` with `n` internal nodes is
     390        the list `l` of `0` and `1` of length `n-1` obtained by going along the
     391        leaves of `T` from left to right except the two extremal ones, writing
     392        `0` if the leaf is a right leaf and `1` if the leaf is a left leaf.
     393
     394        EXAMPLES::
     395
     396            sage: BinaryTree([]).canopee()
     397            []
     398            sage: BinaryTree([None, []]).canopee()
     399            [1]
     400            sage: BinaryTree([[], None]).canopee()
     401            [0]
     402            sage: BinaryTree([[], []]).canopee()
     403            [0, 1]
     404            sage: BinaryTree([[[], [[], None]], [[], []]]).canopee()
     405            [0, 1, 0, 0, 1, 0, 1]
     406
     407        The number of pairs `(t_1, t_2)` of binary trees of size `n` such that
     408        the canopee of `t_1` is the complementary of the canopee of `t_2` is
     409        also the number of Baxter permutations (see [DG]_, see
     410        also :oeis:`A001181`). We check this in small cases::
     411
     412            sage: [len([(u,v) for u in BinaryTrees(n) for v in BinaryTrees(n)
     413            ...       if map(lambda x:1-x, u.canopee()) == v.canopee()])
     414            ...    for n in range(1, 5)]
     415            [1, 2, 6, 22]
     416
     417        Here is a less trivial implementation of this::
     418
     419            sage: from sage.sets.finite_set_map_cy import fibers
     420            sage: from sage.misc.all import attrcall
     421            sage: def baxter(n):
     422            ...      f = fibers(lambda t: tuple(t.canopee()),
     423            ...                   BinaryTrees(n))
     424            ...      return sum(len(f[i])*len(f[tuple(1-x for x in i)])
     425            ...                 for i in f)
     426            sage: [baxter(n) for n in range(1, 7)]
     427            [1, 2, 6, 22, 92, 422]
     428
     429        TESTS::
     430
     431            sage: t = BinaryTree().canopee()
     432            Traceback (most recent call last):
     433            ...
     434            ValueError: canopee is only defined for non empty binary trees
     435
     436        REFERENCES:
     437
     438            .. [DG] S. Dulucq and O, Guibert. Mots de piles, tableaux
     439               standards et permutations de Baxter, proceedings of
     440               Formal Power Series and Algebraic Combinatorics, 1994.
     441        """
     442        if not self:
     443            raise ValueError("canopee is only defined for non empty binary trees")
     444        res = []
     445        def add_leaf_rec(tr):
     446            for i in range(2):
     447                if tr[i]:
     448                    add_leaf_rec(tr[i])
     449                else:
     450                    res.append(1-i)
     451        add_leaf_rec(self)
     452        return res[1:-1]
     453
     454
     455from sage.structure.parent import Parent
     456from sage.structure.unique_representation import UniqueRepresentation
     457from sage.misc.classcall_metaclass import ClasscallMetaclass
     458
     459from sage.sets.non_negative_integers import NonNegativeIntegers
     460from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets
     461from sage.sets.family import Family
     462from sage.misc.cachefunc import cached_method
     463
     464
     465# Abstract class to serve as a Factory no instance are created.
     466class BinaryTrees(UniqueRepresentation, Parent):
     467    """
     468    Factory for binary trees.
     469
     470    INPUT:
     471
     472    - ``size`` -- (optional) an integer
     473
     474    OUPUT:
     475
     476    - the set of all binary trees (of the given ``size`` if specified)
     477
     478    EXAMPLES::
     479
     480        sage: BinaryTrees()
     481        Binary trees
     482
     483        sage: BinaryTrees(2)
     484        Binary trees of size 2
     485
     486    .. NOTE:: this in a factory class whose constructor returns instances of
     487              subclasses.
     488
     489    .. NOTE:: the fact that OrderedTrees is a class instead of a simple callable
     490              is an implementation detail. It could be changed in the future
     491              and one should not rely on it.
     492    """
     493    @staticmethod
     494    def __classcall_private__(cls, n=None):
     495        """
     496        TESTS::
     497
     498            sage: from sage.combinat.binary_tree import BinaryTrees_all, BinaryTrees_size
     499            sage: isinstance(BinaryTrees(2), BinaryTrees)
     500            True
     501            sage: isinstance(BinaryTrees(), BinaryTrees)
     502            True
     503            sage: BinaryTrees(2) is BinaryTrees_size(2)
     504            True
     505            sage: BinaryTrees(5).cardinality()
     506            42
     507            sage: BinaryTrees() is BinaryTrees_all()
     508            True
     509        """
     510        if n is None:
     511            return BinaryTrees_all()
     512        else:
     513            if not (isinstance(n, (Integer, int)) and n >= 0):
     514                raise ValueError("n must be a non negative integer")
     515            return BinaryTrees_size(Integer(n))
     516
     517    @cached_method
     518    def leaf(self):
     519        """
     520        Return a left tree with ``self`` as parent.
     521
     522        EXAMPLES::
     523
     524            sage: BinaryTrees().leaf()
     525            .
     526
     527        TEST::
     528
     529            sage: (BinaryTrees().leaf() is
     530            ...    sage.combinat.binary_tree.BinaryTrees_all().leaf())
     531            True
     532        """
     533        return self(None)
     534
     535#################################################################
     536# Enumerated set of all binary trees
     537#################################################################
     538class BinaryTrees_all(DisjointUnionEnumeratedSets, BinaryTrees):
     539
     540    def __init__(self):
     541        """
     542        TESTS::
     543
     544            sage: from sage.combinat.binary_tree import BinaryTrees_all
     545            sage: B = BinaryTrees_all()
     546            sage: B.cardinality()
     547            +Infinity
     548
     549            sage: it = iter(B)
     550            sage: (it.next(), it.next(), it.next(), it.next(), it.next())
     551            (., [., .], [., [., .]], [[., .], .], [., [., [., .]]])
     552            sage: it.next().parent()
     553            Binary trees
     554            sage: B([])
     555            [., .]
     556
     557            sage: B is BinaryTrees_all()
     558            True
     559            sage: TestSuite(B).run()
     560            """
     561        DisjointUnionEnumeratedSets.__init__(
     562            self, Family(NonNegativeIntegers(), BinaryTrees_size),
     563            facade=True, keepkey = False)
     564
     565    def _repr_(self):
     566        """
     567        TEST::
     568
     569            sage: BinaryTrees()   # indirect doctest
     570            Binary trees
     571        """
     572        return "Binary trees"
     573
     574    def __contains__(self, x):
     575        """
     576        TESTS::
     577
     578            sage: S = BinaryTrees()
     579            sage: 1 in S
     580            False
     581            sage: S([]) in S
     582            True
     583        """
     584        return isinstance(x, self.element_class)
     585
     586    def __call__(self, x=None, *args, **keywords):
     587        """
     588        Ensure that ``None`` instead of ``0`` is passed by default.
     589
     590        TESTS::
     591
     592            sage: B = BinaryTrees()
     593            sage: B()
     594            .
     595        """
     596        return super(BinaryTrees, self).__call__(x, *args, **keywords)
     597
     598    def unlabelled_trees(self):
     599        """
     600        Returns the set of unlabelled trees associated to ``self``
     601
     602        EXAMPLES::
     603
     604            sage: BinaryTrees().unlabelled_trees()
     605            Binary trees
     606        """
     607        return self
     608
     609    def labelled_trees(self):
     610        """
     611        Returns the set of labelled trees associated to ``self``
     612
     613        EXAMPLES::
     614
     615            sage: BinaryTrees().labelled_trees()
     616            Labelled binary trees
     617        """
     618        return LabelledBinaryTrees()
     619
     620    def _element_constructor_(self, *args, **keywords):
     621        """
     622        EXAMPLES::
     623
     624            sage: B = BinaryTrees()
     625            sage: B._element_constructor_([])
     626            [., .]
     627            sage: B([[],[]]) # indirect doctest
     628            [[., .], [., .]]
     629            sage: B(None)    # indirect doctest
     630            .
     631        """
     632        return self.element_class(self, *args, **keywords)
     633
     634    Element = BinaryTree
     635
     636from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
     637from combinat import catalan_number
     638#################################################################
     639# Enumerated set of binary trees of a given size
     640#################################################################
     641class BinaryTrees_size(BinaryTrees):
     642    """
     643    The enumerated sets of binary trees of given size
     644
     645    TESTS::
     646
     647        sage: from sage.combinat.binary_tree import BinaryTrees_size
     648        sage: for i in range(6): TestSuite(BinaryTrees_size(i)).run()
     649    """
     650    def __init__(self, size):
     651        """
     652        TESTS::
     653
     654            sage: S = BinaryTrees(3)
     655            sage: S == loads(dumps(S))
     656            True
     657
     658            sage: S is BinaryTrees(3)
     659            True
     660        """
     661        super(BinaryTrees_size, self).__init__(category = FiniteEnumeratedSets())
     662        self._size = size
     663
     664    def _repr_(self):
     665        """
     666        TESTS::
     667
     668            sage: BinaryTrees(3)   # indirect doctest
     669            Binary trees of size 3
     670        """
     671        return "Binary trees of size %s"%(self._size)
     672
     673    def __contains__(self, x):
     674        """
     675        TESTS::
     676
     677            sage: S = BinaryTrees(3)
     678            sage: 1 in S
     679            False
     680            sage: S([[],[]]) in S
     681            True
     682        """
     683        return isinstance(x, self.element_class) and x.node_number() == self._size
     684
     685    def _an_element_(self):
     686        """
     687        TESTS::
     688
     689            sage: BinaryTrees(0).an_element()  # indirect doctest
     690            .
     691        """
     692        return self.first()
     693
     694    def cardinality(self):
     695        """
     696        The cardinality of ``self``
     697
     698        This is a Catalan number.
     699
     700        TESTS::
     701
     702            sage: BinaryTrees(0).cardinality()
     703            1
     704            sage: BinaryTrees(5).cardinality()
     705            42
     706        """
     707        return catalan_number(self._size)
     708
     709    def __iter__(self):
     710        """
     711        A basic generator.
     712
     713        .. TODO:: could be optimized.
     714
     715        TESTS::
     716
     717            sage: BinaryTrees(0).list()
     718            [.]
     719            sage: BinaryTrees(1).list()
     720            [[., .]]
     721            sage: BinaryTrees(3).list()
     722            [[., [., [., .]]], [., [[., .], .]], [[., .], [., .]], [[., [., .]], .], [[[., .], .], .]]
     723        """
     724        if self._size == 0:
     725            yield self._element_constructor_()
     726        else:
     727            for i in range(0, self._size):
     728                for lft in self.__class__(i):
     729                    for rgt in self.__class__(self._size-1-i):
     730                        yield self._element_constructor_([lft, rgt])
     731
     732    @lazy_attribute
     733    def _parent_for(self):
     734        """
     735        The parent of the element generated by ``self``
     736
     737        TESTS::
     738
     739            sage: S = BinaryTrees(3)
     740            sage: S._parent_for
     741            Binary trees
     742        """
     743        return BinaryTrees_all()
     744
     745    @lazy_attribute
     746    def element_class(self):
     747        """
     748        TESTS::
     749
     750            sage: S = BinaryTrees(3)
     751            sage: S.element_class
     752            <class 'sage.combinat.binary_tree.BinaryTrees_all_with_category.element_class'>
     753            sage: S.first().__class__ == BinaryTrees().first().__class__
     754            True
     755        """
     756        return self._parent_for.element_class
     757
     758    def _element_constructor_(self, *args, **keywords):
     759        """
     760        EXAMPLES::
     761
     762            sage: S = BinaryTrees(0)
     763            sage: S([])   # indirect doctest
     764            Traceback (most recent call last):
     765            ...
     766            ValueError: wrong number of nodes
     767            sage: S(None)   # indirect doctest
     768            .
     769
     770            sage: S = BinaryTrees(1)   # indirect doctest
     771            sage: S([])
     772            [., .]
     773        """
     774        res = self.element_class(self._parent_for, *args, **keywords)
     775        if res.node_number() != self._size:
     776            raise ValueError("wrong number of nodes")
     777        return res
     778
     779
     780
     781class LabelledBinaryTree(AbstractLabelledClonableTree, BinaryTree):
     782    """
     783    The class of labelled binary tree
     784
     785    EXAMPLE::
     786
     787        sage: LBT = LabelledBinaryTree
     788        sage: t1 = LBT([[LBT([], label=2), None], None], label=4); t1
     789        4[None[2[., .], .], .]
     790    """
     791    __metaclass__ = ClasscallMetaclass
     792
     793    @staticmethod
     794    def __classcall_private__(cls, *args, **opts):
     795        """
     796        Ensure that trees created by the sets and directly are the same and
     797        that they are instances of :class:`LabelledTree`
     798
     799        TESTS::
     800
     801            sage: issubclass(LabelledBinaryTrees().element_class, LabelledBinaryTree)
     802            True
     803            sage: t0 = LabelledBinaryTree([[],[[], None]], label = 3)
     804            sage: t0.parent()
     805            Labelled binary trees
     806            sage: type(t0)
     807            <class 'sage.combinat.binary_tree.LabelledBinaryTrees_with_category.element_class'>
     808        """
     809        return cls._auto_parent.element_class(cls._auto_parent, *args, **opts)
     810
     811    @lazy_class_attribute
     812    def _auto_parent(cls):
     813        """
     814        The automatic parent of the element of this class
     815
     816        When calling the constructor of an element of this class, one needs a
     817        parent. This class attribute specifies which parent is used.
     818
     819        EXAMPLES::
     820
     821            sage: LabelledBinaryTree._auto_parent
     822            Labelled binary trees
     823            sage: LabelledBinaryTree([], label = 3).parent()
     824            Labelled binary trees
     825         """
     826        return LabelledBinaryTrees()
     827
     828    def _repr_(self):
     829        """
     830        TESTS::
     831
     832            sage: LBT = LabelledBinaryTree
     833            sage: t1 = LBT([[LBT([], label=2), None], None], label=4); t1
     834            4[None[2[., .], .], .]
     835            sage: LBT([[],[[], None]], label = 3)   # indirect doctest
     836            3[None[., .], None[None[., .], .]]
     837        """
     838        if not self:
     839            if self._label is not None:
     840                return repr(self._label)
     841            else:
     842                return "."
     843        else:
     844            return "%s%s"%(self._label, self[:])
     845
     846    def binary_search_insert(self, letter):
     847        """
     848        Insert a letter in a binary search tree
     849
     850        INPUT:
     851
     852        - ``letter`` -- any object comparable with the label of ``self``
     853
     854        .. NOTE:: ``self`` is supposed to be a binary search tree. No check is
     855                  performed.
     856
     857        EXAMPLES::
     858
     859            sage: LBT = LabelledBinaryTree
     860            sage: LBT(None).binary_search_insert(3)
     861            3[., .]
     862            sage: LBT([], label = 1).binary_search_insert(3)
     863            1[., 3[., .]]
     864            sage: LBT([], label = 3).binary_search_insert(1)
     865            3[1[., .], .]
     866            sage: res = LBT(None)
     867            sage: for i in [3,1,5,2,4,6]:
     868            ...       res = res.binary_search_insert(i)
     869            sage: res
     870            3[1[., 2[., .]], 5[4[., .], 6[., .]]]
     871        """
     872        LT = self.parent()._element_constructor_
     873        if not self:
     874            return LT([], label = letter)
     875        else:
     876            if letter <= self.label():
     877                fils = self[0].binary_search_insert(letter)
     878                return LT([fils, self[1]], label=self.label())
     879            else:
     880                fils = self[1].binary_search_insert(letter)
     881                return LT([self[0], fils], label=self.label())
     882
     883    _UnLabelled = BinaryTree
     884
     885
     886class LabelledBinaryTrees(LabelledOrderedTrees):
     887    """
     888    This is a parent stub to serve as a factory class for trees with various
     889    labels constraints
     890    """
     891    def _repr_(self):
     892        """
     893        TESTS::
     894
     895            sage: LabelledBinaryTrees()   # indirect doctest
     896            Labelled binary trees
     897        """
     898        return "Labelled binary trees"
     899
     900    def _an_element_(self):
     901        """
     902        Returns a labelled binary tree
     903
     904        EXAMPLE::
     905
     906            sage: LabelledBinaryTrees().an_element()   # indirect doctest
     907            toto[42[3[., .], 3[., .]], 5[None[., .], None[., .]]]
     908        """
     909        LT = self._element_constructor_
     910        t  = LT([], label = 3)
     911        t1 = LT([t,t], label = 42)
     912        t2  = LT([[], []], label = 5)
     913        return LT([t1,t2], label = "toto")
     914
     915    def unlabelled_trees(self):
     916        """
     917        Returns the set of unlabelled trees associated to ``self``
     918
     919        EXAMPLES::
     920
     921            sage: LabelledBinaryTrees().unlabelled_trees()
     922            Binary trees
     923
     924        This is used to compute the shape::
     925
     926            sage: t = LabelledBinaryTrees().an_element().shape(); t
     927            [[[., .], [., .]], [[., .], [., .]]]
     928            sage: t.parent()
     929            Binary trees
     930
     931        TESTS::
     932
     933            sage: t = LabelledBinaryTrees().an_element()
     934            sage: t.canonical_labelling()
     935            4[2[1[., .], 3[., .]], 6[5[., .], 7[., .]]]
     936        """
     937        return BinaryTrees_all()
     938
     939    def labelled_trees(self):
     940        """
     941        Returns the set of labelled trees associated to ``self``
     942
     943        EXAMPLES::
     944
     945            sage: LabelledBinaryTrees().labelled_trees()
     946            Labelled binary trees
     947        """
     948        return self
     949
     950    Element = LabelledBinaryTree
     951
     952
     953
     954################################################################
     955# Interface attempt with species...
     956#
     957# Kept here for further reference when species will be improved
     958################################################################
     959# from sage.combinat.species.library import (
     960#     CombinatorialSpecies, EmptySetSpecies, SingletonSpecies)
     961
     962# BT = CombinatorialSpecies()
     963# F =  EmptySetSpecies()
     964# N =  SingletonSpecies()
     965# BT.define(F+N*(BT*BT))
     966# # b3 = BT.isotypes(range(3))
     967# # tr = b3.list()[1]
     968
     969# def BTsp_to_bintrees(bt):
     970#     """
     971#     sage: from sage.combinat.binary_tree import BT, BTsp_to_bintrees
     972#     sage: BTsp_to_bintrees(BT.isotypes(range(5))[0])
     973#     [., [., [., [., [., .]]]]]
     974#     sage: def spls(size):
     975#     ...    return map(BTsp_to_bintrees, BT.isotypes(range(size)).list())
     976#     sage: spls(3)
     977#     [[., [., [., .]]], [., [[., .], .]], [[., .], [., .]], [[., [., .]], .], [[[., .], .], .]]
     978#     sage: all(spls(i) == BinaryTrees(i).list() for i in range(5))
     979#     True
     980#     """
     981#     if len(bt) == 0:
     982#         return BinaryTree()
     983#     elif len(bt) == 2 and len(bt[1]) == 2:
     984#         return BinaryTree(map(BTsp_to_bintrees, list(bt[1])))
     985#     else:
     986#         raise ValueError
  • new file sage/combinat/ordered_tree.py

    diff --git a/sage/combinat/ordered_tree.py b/sage/combinat/ordered_tree.py
    new file mode 100644
    - +  
     1"""
     2Ordered Rooted Trees
     3
     4AUTHORS:
     5
     6- Florent Hivert (2010-2011): initial revision
     7- Frederic Chapoton (2010): contributed some methods
     8"""
     9#*****************************************************************************
     10#       Copyright (C) 2010 Florent Hivert <Florent.Hivert@univ-rouen.fr>,
     11#
     12#  Distributed under the terms of the GNU General Public License (GPL)
     13#  as published by the Free Software Foundation; either version 2 of
     14#  the License, or (at your option) any later version.
     15#                  http://www.gnu.org/licenses/
     16#*****************************************************************************
     17from sage.structure.list_clone import ClonableArray, ClonableList
     18from sage.structure.parent import Parent
     19from sage.structure.unique_representation import UniqueRepresentation
     20from sage.misc.classcall_metaclass import ClasscallMetaclass
     21from sage.misc.lazy_attribute import lazy_class_attribute
     22from sage.combinat.abstract_tree import (AbstractClonableTree,
     23                                         AbstractLabelledClonableTree)
     24
     25class OrderedTree(AbstractClonableTree, ClonableList):
     26    """
     27    The class for (ordered rooted) Trees
     28
     29    An ordered tree is constructed from a node called the root on which one
     30    has grafted a possibly empty list of trees. There is a total order on the
     31    children of a node which is given by the order of the elements in the
     32    list. Note that there is no empty ordered tree.
     33
     34    INPUT:
     35
     36    One can create a tree from any list (or more generally iterable) of trees
     37    or objects convertible to a tree. Alternatively a string is also
     38    accepted. The syntax is the same as for printing: children are grouped by
     39    square brackets.
     40
     41    EXAMPLES::
     42
     43        sage: x = OrderedTree([])
     44        sage: x1 = OrderedTree([x,x])
     45        sage: x2 = OrderedTree([[],[]])
     46        sage: x1 == x2
     47        True
     48        sage: tt1 = OrderedTree([x,x1,x2])
     49        sage: tt2 = OrderedTree([[], [[], []], x2])
     50        sage: tt1 == tt2
     51        True
     52
     53        sage: OrderedTree([]) == OrderedTree()
     54        True
     55
     56    TESTS::
     57
     58        sage: x1.__hash__() == x2.__hash__()
     59        True
     60        sage: tt1.__hash__() == tt2.__hash__()
     61        True
     62
     63    Trees are usually immutable. However they inherits from
     64    :class:`sage.structure.list_clone.ClonableList`. So that they can be
     65    modified using the clone protocol:
     66
     67    Trying to modify a non mutable tree raises an error::
     68
     69        sage: tt1[1] = tt2
     70        Traceback (most recent call last):
     71        ...
     72        ValueError: object is immutable; please change a copy instead.
     73
     74    Here is the correct way to do it::
     75
     76        sage: with tt2.clone() as tt2:
     77        ...    tt2[1] = tt1
     78        sage: tt2
     79        [[], [[], [[], []], [[], []]], [[], []]]
     80
     81    It is also possible to append a child to a tree::
     82
     83        sage: with tt2.clone() as tt3:
     84        ...    tt3.append(OrderedTree([]))
     85        sage: tt3
     86        [[], [[], [[], []], [[], []]], [[], []], []]
     87
     88    Or to insert a child in a tree::
     89
     90        sage: with tt2.clone() as tt3:
     91        ...    tt3.insert(2, OrderedTree([]))
     92        sage: tt3
     93        [[], [[], [[], []], [[], []]], [], [[], []]]
     94
     95    We check that ``tt1`` is not modified and that everything is correct with
     96    respect to equality::
     97
     98        sage: tt1
     99        [[], [[], []], [[], []]]
     100        sage: tt1 == tt2
     101        False
     102        sage: tt1.__hash__() == tt2.__hash__()
     103        False
     104
     105    TESTS::
     106
     107        sage: tt1bis = OrderedTree(tt1)
     108        sage: with tt1.clone() as tt1:
     109        ...    tt1[1] = tt1bis
     110        sage: tt1
     111        [[], [[], [[], []], [[], []]], [[], []]]
     112        sage: tt1 == tt2
     113        True
     114        sage: tt1.__hash__() == tt2.__hash__()
     115        True
     116        sage: len(tt1)
     117        3
     118        sage: tt1[2]
     119        [[], []]
     120        sage: tt1[3]
     121        Traceback (most recent call last):
     122        ...
     123        IndexError: list index out of range
     124        sage: tt1[1:2]
     125        [[[], [[], []], [[], []]]]
     126
     127    Various tests involving construction, equality and hashing::
     128
     129        sage: OrderedTree() == OrderedTree()
     130        True
     131        sage: t1 = OrderedTree([[],[[]]])
     132        sage: t2 = OrderedTree([[],[[]]])
     133        sage: t1 == t2
     134        True
     135        sage: t2 = OrderedTree(t1)
     136        sage: t1 == t2
     137        True
     138        sage: t1 = OrderedTree([[],[[]]])
     139        sage: t2 = OrderedTree([[[]],[]])
     140        sage: t1 == t2
     141        False
     142
     143        sage: t1 = OrderedTree([[],[[]]])
     144        sage: t2 = OrderedTree([[],[[]]])
     145        sage: t1.__hash__() == t2.__hash__()
     146        True
     147        sage: t2 = OrderedTree([[[]],[]])
     148        sage: t1.__hash__() == t2.__hash__()
     149        False
     150        sage: OrderedTree().__hash__() == OrderedTree([]).__hash__()
     151        True
     152        sage: tt1 = OrderedTree([t1,t2,t1])
     153        sage: tt2 = OrderedTree([t1, [[[]],[]], t1])
     154        sage: tt1.__hash__() == tt2.__hash__()
     155        True
     156
     157    Check that the hash value is correctly updated after modification::
     158
     159        sage: with tt2.clone() as tt2:
     160        ...    tt2[1,1] = tt1
     161        sage: tt1.__hash__() == tt2.__hash__()
     162        False
     163    """
     164
     165    __metaclass__ = ClasscallMetaclass
     166
     167    @staticmethod
     168    def __classcall_private__(cls, *args, **opts):
     169        """
     170        Ensure that trees created by the enumerated sets and directly
     171        are the same and that they are instances of :class:`OrderedTree`
     172
     173        TESTS::
     174
     175            sage: issubclass(OrderedTrees().element_class, OrderedTree)
     176            True
     177            sage: t0 = OrderedTree([[],[[], []]])
     178            sage: t0.parent()
     179            Ordered trees
     180            sage: type(t0)
     181            <class 'sage.combinat.ordered_tree.OrderedTrees_all_with_category.element_class'>
     182
     183            sage: t1 = OrderedTrees()([[],[[], []]])
     184            sage: t1.parent() is t0.parent()
     185            True
     186            sage: type(t1) is type(t0)
     187            True
     188
     189            sage: t1 = OrderedTrees(4)([[],[[]]])
     190            sage: t1.parent() is t0.parent()
     191            True
     192            sage: type(t1) is type(t0)
     193            True
     194        """
     195        return cls._auto_parent.element_class(cls._auto_parent, *args, **opts)
     196
     197    @lazy_class_attribute
     198    def _auto_parent(cls):
     199        """
     200        The automatic parent of the element of this class
     201
     202        When calling the constructor of an element of this class, one needs a
     203        parent. This class attribute specifies which parent is used.
     204
     205        EXAMPLES::
     206
     207            sage: OrderedTree([[],[[]]])._auto_parent
     208            Ordered trees
     209            sage: OrderedTree([[],[[]]]).parent()
     210            Ordered trees
     211
     212        .. NOTE::
     213
     214            It is possible to bypass the automatic parent mechanism using:
     215
     216                sage: t1 = OrderedTree.__new__(OrderedTree, Parent(), [])
     217                sage: t1.__init__(Parent(), [])
     218                sage: t1
     219                []
     220                sage: t1.parent()
     221                <type 'sage.structure.parent.Parent'>
     222        """
     223        return OrderedTrees_all()
     224
     225    def __init__(self, parent=None, children=[], check=True):
     226        """
     227        TESTS::
     228
     229            sage: t1 = OrderedTrees(4)([[],[[]]])
     230            sage: TestSuite(t1).run()
     231            sage: OrderedTrees()("[]") # indirect doctest
     232            []
     233            sage: all(OrderedTree(repr(tr)) == tr for i in range(6) for tr in OrderedTrees(i))
     234            True
     235        """
     236        if type(children) is str:
     237            children = eval(children)
     238        if (children.__class__ is self.__class__ and
     239            children.parent() == parent):
     240            children = list(children)
     241        else:
     242            children = [self.__class__(parent, x) for x in children]
     243        ClonableArray.__init__(self, parent, children, check=check)
     244
     245    def is_empty(self):
     246        """
     247        Return if ``self`` is the empty tree
     248
     249        For ordered trees, returns always ``False``
     250
     251        .. NOTE:: this is different from ``bool(t)`` which returns whether
     252                  ``t`` has some child or not.
     253
     254        EXAMPLES::
     255
     256            sage: t = OrderedTrees(4)([[],[[]]])
     257            sage: t.is_empty()
     258            False
     259            sage: bool(t)
     260            True
     261        """
     262        return False
     263
     264from sage.categories.sets_cat import Sets, EmptySetError
     265from sage.rings.integer import Integer
     266from sage.sets.non_negative_integers import NonNegativeIntegers
     267from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets
     268from sage.sets.family import Family
     269from sage.misc.cachefunc import cached_method
     270
     271# Abstract class to serve as a Factory no instance are created.
     272class OrderedTrees(UniqueRepresentation, Parent):
     273    """
     274    Factory for ordered trees
     275
     276    INPUT:
     277
     278    - ``size`` -- (optional) an integer
     279
     280    OUPUT:
     281
     282    - the set of all ordered trees (of the given ``size`` if specified)
     283
     284    EXAMPLES::
     285
     286        sage: OrderedTrees()
     287        Ordered trees
     288
     289        sage: OrderedTrees(2)
     290        Ordered trees of size 2
     291
     292    .. NOTE:: this is a factory class whose constructor returns instances of
     293              subclasses.
     294
     295    .. NOTE:: the fact that OrderedTrees is a class instead of a simple callable
     296              is an implementation detail. It could be changed in the future
     297              and one should not rely on it.
     298    """
     299    @staticmethod
     300    def __classcall_private__(cls, n=None):
     301        """
     302        TESTS::
     303
     304            sage: from sage.combinat.ordered_tree import OrderedTrees_all, OrderedTrees_size
     305            sage: isinstance(OrderedTrees(2), OrderedTrees)
     306            True
     307            sage: isinstance(OrderedTrees(), OrderedTrees)
     308            True
     309            sage: OrderedTrees(2) is OrderedTrees_size(2)
     310            True
     311            sage: OrderedTrees(5).cardinality()
     312            14
     313            sage: OrderedTrees() is OrderedTrees_all()
     314            True
     315        """
     316        if n is None:
     317            return OrderedTrees_all()
     318        else:
     319            if not (isinstance(n, (Integer, int)) and n >= 0):
     320                raise ValueError("n must be a non negative integer")
     321            return OrderedTrees_size(Integer(n))
     322
     323    @cached_method
     324    def leaf(self):
     325        """
     326        Return a leaf tree with ``self`` as parent
     327
     328        EXAMPLES::
     329
     330            sage: OrderedTrees().leaf()
     331            []
     332
     333        TEST::
     334
     335            sage: (OrderedTrees().leaf() is
     336            ...    sage.combinat.ordered_tree.OrderedTrees_all().leaf())
     337            True
     338        """
     339        return self([])
     340
     341class OrderedTrees_all(DisjointUnionEnumeratedSets, OrderedTrees):
     342    """
     343    The set of all ordered trees
     344
     345    EXAMPLES::
     346
     347        sage: OT = OrderedTrees(); OT
     348        Ordered trees
     349        sage: OT.cardinality()
     350        +Infinity
     351    """
     352
     353    def __init__(self):
     354        """
     355        TESTS::
     356
     357            sage: from sage.combinat.ordered_tree import OrderedTrees_all
     358            sage: B = OrderedTrees_all()
     359            sage: B.cardinality()
     360            +Infinity
     361
     362            sage: it = iter(B)
     363            sage: (it.next(), it.next(), it.next(), it.next(), it.next())
     364            ([], [[]], [[], []], [[[]]], [[], [], []])
     365            sage: it.next().parent()
     366            Ordered trees
     367            sage: B([])
     368            []
     369
     370            sage: B is OrderedTrees_all()
     371            True
     372            sage: TestSuite(B).run()
     373            """
     374        DisjointUnionEnumeratedSets.__init__(
     375            self, Family(NonNegativeIntegers(), OrderedTrees_size),
     376            facade=True, keepkey=False)
     377
     378    def _repr_(self):
     379        """
     380        TEST::
     381
     382            sage: OrderedTrees()   # indirect doctest
     383            Ordered trees
     384        """
     385        return "Ordered trees"
     386
     387    def __contains__(self, x):
     388        """
     389        TESTS::
     390
     391            sage: T = OrderedTrees()
     392            sage: 1 in T
     393            False
     394            sage: T([]) in T
     395            True
     396        """
     397        return isinstance(x, self.element_class)
     398
     399    def unlabelled_trees(self):
     400        """
     401        Returns the set of unlabelled trees associated to ``self``
     402
     403        EXAMPLES::
     404
     405            sage: OrderedTrees().unlabelled_trees()
     406            Ordered trees
     407        """
     408        return self
     409
     410    def labelled_trees(self):
     411        """
     412        Returns the set of unlabelled trees associated to ``self``
     413
     414        EXAMPLES::
     415
     416            sage: OrderedTrees().labelled_trees()
     417            Labelled ordered trees
     418        """
     419        return LabelledOrderedTrees()
     420
     421    def _element_constructor_(self, *args, **keywords):
     422        """
     423        EXAMPLES::
     424
     425            sage: T = OrderedTrees()
     426            sage: T([])     # indirect doctest
     427            []
     428        """
     429        return self.element_class(self, *args, **keywords)
     430
     431    Element = OrderedTree
     432
     433
     434
     435from sage.misc.lazy_attribute import lazy_attribute
     436from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
     437from combinat import catalan_number
     438from sage.combinat.composition import Compositions
     439from sage.combinat.cartesian_product import CartesianProduct
     440#################################################################
     441# Enumerated set of binary trees of a given size
     442#################################################################
     443class OrderedTrees_size(OrderedTrees):
     444    """
     445    The enumerated sets of binary trees of a given size
     446
     447    EXAMPLES::
     448
     449        sage: S = OrderedTrees(3); S
     450        Ordered trees of size 3
     451        sage: S.cardinality()
     452        2
     453        sage: S.list()
     454        [[[], []], [[[]]]]
     455    """
     456    def __init__(self, size):
     457        """
     458        TESTS::
     459
     460            sage: from sage.combinat.ordered_tree import OrderedTrees_size
     461            sage: TestSuite(OrderedTrees_size(0)).run()
     462            sage: for i in range(6): TestSuite(OrderedTrees_size(i)).run()
     463        """
     464        super(OrderedTrees_size, self).__init__(category = FiniteEnumeratedSets())
     465        self._size = size
     466
     467    def _repr_(self):
     468        """
     469        TESTS::
     470
     471            sage: OrderedTrees(3)   # indirect doctest
     472            Ordered trees of size 3
     473        """
     474        return "Ordered trees of size %s"%(self._size)
     475
     476    def __contains__(self, x):
     477        """
     478        TESTS::
     479
     480            sage: T = OrderedTrees(3)
     481            sage: 1 in T
     482            False
     483            sage: T([[],[]]) in T
     484            True
     485        """
     486        return isinstance(x, self.element_class) and x.node_number() == self._size
     487
     488    def _an_element_(self):
     489        """
     490        TESTS::
     491
     492            sage: OrderedTrees(3).an_element()   # indirect doctest
     493            [[], []]
     494        """
     495        if self._size == 0:
     496            raise EmptySetError
     497        return self.first()
     498
     499    def cardinality(self):
     500        """
     501        The cardinality of ``self``
     502
     503        This is a Catalan number
     504
     505        TESTS::
     506
     507            sage: OrderedTrees(0).cardinality()
     508            0
     509            sage: OrderedTrees(1).cardinality()
     510            1
     511            sage: OrderedTrees(6).cardinality()
     512            42
     513        """
     514        if self._size == 0:
     515            return Integer(0)
     516        else:
     517            return catalan_number(self._size-1)
     518
     519    def __iter__(self):
     520        """
     521        A basic generator
     522
     523        .. TODO:: could be optimized.
     524
     525        TESTS::
     526
     527            sage: OrderedTrees(0).list()
     528            []
     529            sage: OrderedTrees(1).list()
     530            [[]]
     531            sage: OrderedTrees(2).list()
     532            [[[]]]
     533            sage: OrderedTrees(3).list()
     534            [[[], []], [[[]]]]
     535            sage: OrderedTrees(4).list()
     536            [[[], [], []], [[], [[]]], [[[]], []], [[[], []]], [[[[]]]]]
     537        """
     538        if self._size == 0:
     539            return
     540        else:
     541            for c in Compositions(self._size-1):
     542                for lst in CartesianProduct(*(map(self.__class__, c))):
     543                    yield self._element_constructor_(lst)
     544
     545    @lazy_attribute
     546    def _parent_for(self):
     547        """
     548        Return the parent of the element generated by ``self``
     549
     550        TESTS::
     551
     552            sage: OrderedTrees(3)._parent_for
     553            Ordered trees
     554        """
     555        return OrderedTrees_all()
     556
     557    @lazy_attribute
     558    def element_class(self):
     559        """
     560        The class of the element of ``self``
     561
     562        EXAMPLES::
     563
     564            sage: from sage.combinat.ordered_tree import OrderedTrees_size, OrderedTrees_all
     565            sage: S = OrderedTrees_size(3)
     566            sage: S.element_class is OrderedTrees().element_class
     567            True
     568            sage: S.first().__class__ == OrderedTrees_all().first().__class__
     569            True
     570        """
     571        return self._parent_for.element_class
     572
     573    def _element_constructor_(self, *args, **keywords):
     574        """
     575        EXAMPLES::
     576
     577            sage: S = OrderedTrees(0)
     578            sage: S([])   # indirect doctest
     579            Traceback (most recent call last):
     580            ...
     581            ValueError: wrong number of nodes
     582
     583            sage: S = OrderedTrees(1)   # indirect doctest
     584            sage: S([])
     585            []
     586        """
     587        res = self.element_class(self._parent_for, *args, **keywords)
     588        if res.node_number() != self._size:
     589            raise ValueError("wrong number of nodes")
     590        return res
     591
     592
     593class LabelledOrderedTree(AbstractLabelledClonableTree, OrderedTree):
     594    """
     595    Labelled ordered trees
     596
     597    A labelled ordered tree is an ordered tree with a label attached at each
     598    node.
     599
     600    INPUT:
     601
     602    - ``children`` -- a list or tuple or more generally any iterable
     603                      of trees or object convertible to trees
     604    - ``label`` -- any Sage object default to ``None``
     605
     606    EXAMPLES::
     607
     608        sage: x = LabelledOrderedTree([], label = 3); x
     609        3[]
     610        sage: LabelledOrderedTree([x, x, x], label = 2)
     611        2[3[], 3[], 3[]]
     612        sage: LabelledOrderedTree((x, x, x), label = 2)
     613        2[3[], 3[], 3[]]
     614        sage: LabelledOrderedTree([[],[[], []]], label = 3)
     615        3[None[], None[None[], None[]]]
     616    """
     617    __metaclass__ = ClasscallMetaclass
     618
     619    @staticmethod
     620    def __classcall_private__(cls, *args, **opts):
     621        """
     622        Ensure that trees created by the sets and directly are the same and
     623        that they are instances of :class:`LabelledOrderedTree`
     624
     625        TESTS::
     626
     627            sage: issubclass(LabelledOrderedTrees().element_class, LabelledOrderedTree)
     628            True
     629            sage: t0 = LabelledOrderedTree([[],[[], []]], label = 3)
     630            sage: t0.parent()
     631            Labelled ordered trees
     632            sage: type(t0)
     633            <class 'sage.combinat.ordered_tree.LabelledOrderedTrees_with_category.element_class'>
     634        """
     635        return cls._auto_parent.element_class(cls._auto_parent, *args, **opts)
     636
     637    @lazy_class_attribute
     638    def _auto_parent(cls):
     639        """
     640        The automatic parent of the element of this class
     641
     642        When calling the constructor of an element of this class, one needs a
     643        parent. This class attribute specifies which parent is used.
     644
     645        EXAMPLES::
     646
     647            sage: LabelledOrderedTree._auto_parent
     648            Labelled ordered trees
     649            sage: LabelledOrderedTree([], label = 3).parent()
     650            Labelled ordered trees
     651         """
     652        return LabelledOrderedTrees()
     653
     654    _UnLabelled = OrderedTree
     655
     656
     657from sage.rings.infinity import Infinity
     658class LabelledOrderedTrees(UniqueRepresentation, Parent):
     659    """
     660    This is a parent stub to serve as a factory class for trees with various
     661    labels constraints
     662
     663    EXAMPLES::
     664
     665        sage: LOT = LabelledOrderedTrees(); LOT
     666        Labelled ordered trees
     667        sage: x = LOT([], label = 3); x
     668        3[]
     669        sage: x.parent() is LOT
     670        True
     671        sage: y = LOT([x, x, x], label = 2); y
     672        2[3[], 3[], 3[]]
     673        sage: y.parent() is LOT
     674        True
     675    """
     676    def __init__(self, category=None):
     677        """
     678        TESTS::
     679
     680            sage: TestSuite(LabelledOrderedTrees()).run()
     681        """
     682        if category is None:
     683            category = Sets()
     684        Parent.__init__(self, category = category)
     685
     686    def _repr_(self):
     687        """
     688        TESTS::
     689
     690            sage: LabelledOrderedTrees()   # indirect doctest
     691            Labelled ordered trees
     692        """
     693        return "Labelled ordered trees"
     694
     695    def cardinality(self):
     696        """
     697        Returns the cardinality of `self`
     698
     699        EXAMPLE::
     700
     701            sage: LabelledOrderedTrees().cardinality()
     702            +Infinity
     703        """
     704        return Infinity
     705
     706    def _an_element_(self):
     707        """
     708        Returns a labelled tree
     709
     710        EXAMPLE::
     711
     712            sage: LabelledOrderedTrees().an_element()   # indirect doctest
     713            toto[3[], 42[3[], 3[]], 5[None[]]]
     714        """
     715        LT = self._element_constructor_
     716        t  = LT([], label = 3)
     717        t1 = LT([t,t], label = 42)
     718        t2  = LT([[]], label = 5)
     719        return LT([t,t1,t2], label = "toto")
     720
     721    def _element_constructor_(self, *args, **keywords):
     722        """
     723        EXAMPLES::
     724
     725            sage: T = LabelledOrderedTrees()
     726            sage: T([], label=2)     # indirect doctest
     727            2[]
     728        """
     729        return self.element_class(self, *args, **keywords)
     730
     731    def unlabelled_trees(self):
     732        """
     733        Returns the set of unlabelled trees associated to ``self``
     734
     735        EXAMPLES::
     736
     737            sage: LabelledOrderedTrees().unlabelled_trees()
     738            Ordered trees
     739        """
     740        return OrderedTrees_all()
     741
     742    def labelled_trees(self):
     743        """
     744        Returns the set of labelled trees associated to ``self``
     745
     746        EXAMPLES::
     747
     748            sage: LabelledOrderedTrees().labelled_trees()
     749            Labelled ordered trees
     750            sage: LOT = LabelledOrderedTrees()
     751            sage: x = LOT([], label = 3)
     752            sage: y = LOT([x, x, x], label = 2)
     753            sage: y.canonical_labelling()
     754            1[2[], 3[], 4[]]
     755        """
     756        return self
     757
     758    Element = LabelledOrderedTree
  • sage/combinat/permutation.py

    diff --git a/sage/combinat/permutation.py b/sage/combinat/permutation.py
    a b class Permutation_class(CombinatorialObj 
    29462946        """
    29472947        return self.robinson_schensted()[1]
    29482948
     2949    def increasing_tree(self, compare=min):
     2950        """
     2951        Return the increasing tree associated to ``self``
     2952
     2953        EXAMPLES::
     2954
     2955            sage: Permutation([1,4,3,2]).increasing_tree()
     2956            1[., 2[3[4[., .], .], .]]
     2957            sage: Permutation([4,1,3,2]).increasing_tree()
     2958            1[4[., .], 2[3[., .], .]]
     2959
     2960        By passing the option ``compare=max`` one can have the decreasing
     2961        tree instead::
     2962
     2963            sage: Permutation([2,3,4,1]).increasing_tree(max)
     2964            4[3[2[., .], .], 1[., .]]
     2965            sage: Permutation([2,3,1,4]).increasing_tree(max)
     2966            4[3[2[., .], 1[., .]], .]
     2967        """
     2968        from sage.combinat.binary_tree import LabelledBinaryTree as LBT
     2969        def rec(perm):
     2970            if len(perm) == 0: return LBT(None)
     2971            mn = compare(perm)
     2972            k = perm.index(mn)
     2973            return LBT([rec(perm[:k]), rec(perm[k+1:])], label = mn)
     2974        return rec(self)
     2975
     2976    def binary_search_tree(self, left_to_right=True):
     2977        """
     2978        Return the binary search tree associated to ``self``
     2979
     2980        EXAMPLES::
     2981
     2982            sage: Permutation([1,4,3,2]).binary_search_tree()
     2983            1[., 4[3[2[., .], .], .]]
     2984            sage: Permutation([4,1,3,2]).binary_search_tree()
     2985            4[1[., 3[2[., .], .]], .]
     2986
     2987        By passing the option ``compare=max`` one can have the decreasing
     2988        tree instead::
     2989
     2990            sage: Permutation([1,4,3,2]).binary_search_tree(False)
     2991            2[1[., .], 3[., 4[., .]]]
     2992            sage: Permutation([4,1,3,2]).binary_search_tree(False)
     2993            2[1[., .], 3[., 4[., .]]]
     2994
     2995        TESTS::
     2996
     2997            sage: Permutation([]).binary_search_tree()
     2998            .
     2999        """
     3000        from sage.combinat.binary_tree import LabelledBinaryTree as LBT
     3001        res = LBT(None)
     3002        if left_to_right:
     3003            gen = self
     3004        else:
     3005            gen = self[::-1]
     3006        for i in gen:
     3007            res = res.binary_search_insert(i)
     3008        return res
     3009
     3010
    29493011    @combinatorial_map(name='Robinson-Schensted tableau shape')
    29503012    def RS_partition(self):
    29513013        """
  • sage/misc/all.py

    diff --git a/sage/misc/all.py b/sage/misc/all.py
    a b from lazy_import import lazy_import 
    162162
    163163from abstract_method import abstract_method
    164164
    165 from binary_tree import BinaryTree
    166 
    167165from randstate import seed, set_random_seed, initial_seed, current_randstate
    168166
    169167from prandom import *
  • sage/misc/binary_tree.pyx

    diff --git a/sage/misc/binary_tree.pyx b/sage/misc/binary_tree.pyx
    a b cdef class BinaryTree: 
    197197
    198198        EXAMPLES::
    199199
     200            sage: from sage.misc.binary_tree import BinaryTree
    200201            sage: t = BinaryTree()
    201202            sage: t.insert(1)
    202203            sage: t.insert(0)
    cdef class BinaryTree: 
    220221
    221222        EXAMPLES::
    222223
     224            sage: from sage.misc.binary_tree import BinaryTree
    223225            sage: t = BinaryTree()
    224226            sage: t.insert(3,3)
    225227            sage: t.insert(1,1)
    cdef class BinaryTree: 
    261263
    262264        EXAMPLES::
    263265
     266            sage: from sage.misc.binary_tree import BinaryTree
    264267            sage: t = BinaryTree()
    265268            sage: t.insert(0,Matrix([[0,0],[1,1]]))
    266269            sage: t.insert(0,1)
    cdef class BinaryTree: 
    279282
    280283        EXAMPLES::
    281284
     285            sage: from sage.misc.binary_tree import BinaryTree
    282286            sage: t = BinaryTree()
    283287            sage: t.contains(1)
    284288            False
    cdef class BinaryTree: 
    322326
    323327        EXAMPLES::
    324328
     329            sage: from sage.misc.binary_tree import BinaryTree
    325330            sage: t = BinaryTree()
    326331            sage: t.insert(4,'e')
    327332            sage: t.insert(2,'c')
    cdef class BinaryTree: 
    361366
    362367        EXAMPLES::
    363368
     369            sage: from sage.misc.binary_tree import BinaryTree
    364370            sage: t = BinaryTree()
    365371            sage: t.insert(4,'e')
    366372            sage: t.insert(2,'c')
    cdef class BinaryTree: 
    399405
    400406        EXAMPLES::
    401407
     408            sage: from sage.misc.binary_tree import BinaryTree
    402409            sage: t = BinaryTree()
    403410            sage: t.is_empty()
    404411            True
  • sage/structure/list_clone.pyx

    diff --git a/sage/structure/list_clone.pyx b/sage/structure/list_clone.pyx
    a b cdef class ClonableElement(Element): 
    146146    """
    147147    Abstract class for elements with clone protocol
    148148
    149     This class is a subclasse of
    150     :class:`Element<sage.structure.element.Element>` and implements the
    151     "prototype" design pattern (see [Pro]_, [GOF]_). The role of this class
    152     is:
     149    This class is a subclass of :class:`Element<sage.structure.element.Element>`
     150    and implements the "prototype" design pattern (see [Pro]_, [GOF]_). The role
     151    of this class is:
    153152
    154153    - to manage copy and mutability and hashing of elements
    155154    - to ensure that at the end of a piece of code an object is restored in a