Ticket #8703: trac_8703-trees-fh.patch

File trac_8703-trees-fh.patch, 96.0 KB (added by stumpc5, 6 years ago)
  • doc/en/reference/combinat/index.rst

    # HG changeset patch
    # User Christian Stump <christian.stump at gmail.com>
    # Date 1360780816 -3600
    # Node ID eb6ebc1b21eddde998ddcad84913aebc803ecd96
    # Parent  ec3d06ee4270a3254822c862740c10ed4b0a15f5
    #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.
    
    diff --git a/doc/en/reference/combinat/index.rst b/doc/en/reference/combinat/index.rst
    a b Combinatorics 
    4242   ../sage/combinat/sidon_sets
    4343   ../sage/combinat/set_partition_ordered
    4444   ../sage/combinat/set_partition
     45   ../sage/combinat/abstract_tree
     46   ../sage/combinat/ordered_tree
     47   ../sage/combinat/binary_tree
    4548   ../sage/combinat/skew_partition
    4649   ../sage/combinat/subset
    4750   ../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"""
     2Abstract Recursive Trees
     3
     4The purpose of this class is to help implement trees with a specific structure
     5on the children of each node. For instance, one could want to define a tree in
     6which each node sees its children as linearly (see the :mod:`Ordered Trees
     7<sage.combinat.ordered_tree>` module) or cyclically ordered.
     8
     9**Tree structures**
     10
     11Conceptually, one can define a tree structure from any object that can contain
     12others. Indeed, a list can contain lists which contain lists which contain
     13lists, and thus define a tree ... The same can be done with sets, or any kind
     14of iterable objects.
     15
     16While any iterable is sufficient to encode trees, it can prove useful to have
     17other methods available like isomorphism tests (see next section), conversions
     18to DiGraphs objects (see :meth:`~.AbstractLabelledTree.as_digraph`) or
     19computation of the number of automorphisms constrained by the structure on
     20children. Providing such methods is the whole purpose of the
     21:class:`AbstractTree` class.
     22
     23As a result, the :class:`AbstractTree` class is not meant to be
     24instantiated, but extended. It is expected that classes extending this one may
     25also inherit from classes representing iterables, for instance
     26:class:`ClonableArray` or :class:`~sage.structure.list_clone.ClonableList`
     27
     28**Constrained Trees**
     29
     30The tree built from a specific container will reflect the properties of the
     31container. Indeed, if ``A`` is an iterable class whose elements are linearly
     32ordered, a class ``B`` extending both of :class:`AbstractTree` and ``A`` will
     33be such that the children of a node will be linearly ordered. If ``A`` behaves
     34like a set (i.e. if there is no order on the elements it contains), then two
     35trees will be considered as equal if one can be obtained from the other
     36through permutations between the children of a same node (see next section).
     37
     38**Paths and ID**
     39
     40It is expected that each element of a set of children should be identified by
     41its index in the container. This way, any node of the tree can be identified
     42by a word describing a path from the root node.
     43
     44**Canonical labellings**
     45
     46Equality between instances of classes extending both of :class:`AbstractTree`
     47and ``A`` is entirely defined by the equality defined on the elements of
     48``A``. A canonical labelling of such a tree however, should be such that two
     49trees ``a`` and ``b`` satisfying ``a == b`` should have the same canonical
     50labellings. On the other hand, the canonical labellings of trees ``a`` and
     51``b`` satisfying ``a != b`` are expected to be different.
     52
     53For this reason, the values returned by the :meth:`canonical_labelling
     54<AbstractTree.canonical_labelling>` method heavily
     55depend on the data structure used for a node's children and **should be**
     56**overridden** by most of the classes extending :class:`AbstractTree` if it is
     57incoherent with the data structure.
     58
     59**Authors**
     60
     61- Florent Hivert (2010-2011): initial revision
     62- Frederic Chapoton (2011): contributed some methods
     63"""
     64
     65from sage.structure.list_clone import ClonableArray
     66from sage.rings.integer import Integer
     67from sage.misc.misc_c import prod
     68
     69# Unfortunately Cython forbids multiple inheritance. Therefore, we do not
     70# inherits from SageObject to be able to inherits from Element or a subclass
     71# of it later.
     72class AbstractTree(object):
     73    """
     74    Abstract Tree
     75
     76    There is no data structure defined here, as this class is meant to be
     77    extended, not instantiated.
     78
     79    .. rubric:: How should this class be extended ?
     80
     81    A class extending :class:`AbstractTree
     82    <sage.combinat.abstract_tree.AbstractTree>` should respect several
     83    assumptions:
     84
     85    * For a tree ``T``, the call ``iter(T)`` should return an iterator on the
     86      children of the root ``T``.
     87
     88    * The :meth:`canonical_labelling
     89      <AbstractTree.canonical_labelling>` method
     90      should return the same value for trees that are considered equal (see the
     91      "canonical labellings" section in the documentation of the
     92      :class:`AbstractTree <sage.combinat.abstract_tree.AbstractTree>` module).
     93
     94    * For a tree ``T`` the call ``T.parent().labelled_trees()`` should return
     95      a parent for labelled trees of the same kind: for example,
     96
     97      - if ``T`` is a binary tree, ``T.parent()`` is ``BinaryTrees()`` and
     98        ``T.parent().labelled_trees()`` is ``LabelledBinaryTrees()``
     99
     100      - if ``T`` is an ordered tree, ``T.parent()`` is ``OrderedTrees()`` and
     101        ``T.parent().labelled_trees()`` is ``LabelledOrderedTrees()``
     102
     103    TESTS::
     104
     105        sage: TestSuite(OrderedTree()).run()
     106        sage: TestSuite(BinaryTree()).run()
     107    """
     108
     109    def subtrees(self):
     110        """
     111        Returns a generator for all subtrees of ``self``
     112
     113        The number of subtrees of a tree is its number of elements.
     114
     115        EXAMPLES::
     116
     117            sage: list(OrderedTree([]).subtrees())
     118            [[]]
     119            sage: list(OrderedTree([[],[[]]]).subtrees())
     120            [[[], [[]]], [], [[]], []]
     121
     122            sage: list(BinaryTree([[],[[],[]]]).subtrees())
     123            [[[., .], [[., .], [., .]]], [., .], [[., .], [., .]], [., .], [., .]]
     124
     125        TESTS::
     126
     127            sage: t = OrderedTree([[], [[], [[], []], [[], []]], [[], []]])
     128            sage: t.node_number() == len(list(t.subtrees()))
     129            True
     130            sage: list(BinaryTree().subtrees())
     131            []
     132            sage: bt = BinaryTree([[],[[],[]]])
     133            sage: bt.node_number() == len(list(bt.subtrees()))
     134            True
     135        """
     136        if not self.is_empty():
     137            yield self
     138            for i in self:
     139                for t in i.subtrees():
     140                    yield t
     141
     142    def paths(self):
     143        """
     144        Returns a generator for all paths to nodes of ``self``
     145
     146        OUTPUT:
     147
     148        This method returns a list of sequences of integers. Each of these
     149        sequences represents a path from the root node to another one : `(1, 3,
     150        2, 5, 3)` represents the node obtained by chosing the 1st children of
     151        the root node (in the ordering returned by ``iter``), then the 3rd of
     152        its children, then the 2nd of this element, etc.
     153
     154        The root element is represented by the empty tuple ``()``.
     155
     156        EXAMPLES::
     157
     158            sage: list(OrderedTree([]).paths())
     159            [()]
     160            sage: list(OrderedTree([[],[[]]]).paths())
     161            [(), (0,), (1,), (1, 0)]
     162
     163            sage: list(BinaryTree([[],[[],[]]]).paths())
     164            [(), (0,), (1,), (1, 0), (1, 1)]
     165
     166        TESTS::
     167
     168            sage: t = OrderedTree([[], [[], [[], []], [[], []]], [[], []]])
     169            sage: t.node_number() == len(list(t.paths()))
     170            True
     171            sage: list(BinaryTree().paths())
     172            []
     173            sage: bt = BinaryTree([[],[[],[]]])
     174            sage: bt.node_number() == len(list(bt.paths()))
     175            True
     176        """
     177        if not self.is_empty():
     178            yield ()
     179            for i, t in enumerate(self):
     180                for p in t.paths():
     181                    yield (i,)+p
     182
     183    def node_number(self):
     184        """
     185        The number of nodes of ``self``
     186
     187        EXAMPLES::
     188
     189            sage: OrderedTree().node_number()
     190            1
     191            sage: OrderedTree([]).node_number()
     192            1
     193            sage: OrderedTree([[],[]]).node_number()
     194            3
     195            sage: OrderedTree([[],[[]]]).node_number()
     196            4
     197            sage: OrderedTree([[], [[], [[], []], [[], []]], [[], []]]).node_number()
     198            13
     199
     200        EXAMPLE::
     201
     202            sage: BinaryTree(None).node_number()
     203            0
     204            sage: BinaryTree([]).node_number()
     205            1
     206            sage: BinaryTree([[], None]).node_number()
     207            2
     208            sage: BinaryTree([[None, [[], []]], None]).node_number()
     209            5
     210        """
     211        if self.is_empty():
     212            return 0
     213        else:
     214            return sum((i.node_number() for i in self), Integer(1))
     215
     216    def depth(self):
     217        """
     218        The depth of ``self``
     219
     220        EXAMPLES::
     221
     222            sage: OrderedTree().depth()
     223            1
     224            sage: OrderedTree([]).depth()
     225            1
     226            sage: OrderedTree([[],[]]).depth()
     227            2
     228            sage: OrderedTree([[],[[]]]).depth()
     229            3
     230            sage: OrderedTree([[], [[], [[], []], [[], []]], [[], []]]).depth()
     231            4
     232
     233            sage: BinaryTree().depth()
     234            0
     235            sage: BinaryTree([[],[[],[]]]).depth()
     236            3
     237        """
     238        if self:
     239            return Integer(1 + max(i.depth() for i in self))
     240        else:
     241            return Integer(0 if self.is_empty() else 1)
     242
     243    def canonical_labelling(self,shift=1):
     244        """
     245        Returns a labelled version of ``self``
     246
     247        The actual canonical labelling is currently unspecified. However, it
     248        is guaranteed to have labels in `1...n` where `n` is the number of
     249        nodes of the tree. Moreover, two (unlabelled) trees compare as equal if
     250        and only if they canonical labelled trees compare as equal.
     251
     252        EXAMPLES::
     253
     254            sage: t = OrderedTree([[], [[], [[], []], [[], []]], [[], []]])
     255            sage: t.canonical_labelling()
     256            1[2[], 3[4[], 5[6[], 7[]], 8[9[], 10[]]], 11[12[], 13[]]]
     257
     258            sage: BinaryTree([]).canonical_labelling()
     259            1[., .]
     260            sage: BinaryTree([[],[[],[]]]).canonical_labelling()
     261            2[1[., .], 4[3[., .], 5[., .]]]
     262
     263        TESTS::
     264
     265            sage: BinaryTree().canonical_labelling()
     266            .
     267        """
     268        LTR = self.parent().labelled_trees()
     269        liste=[]
     270        deca=1
     271        for subtree in self:
     272            liste=liste+[subtree.canonical_labelling(shift+deca)]
     273            deca=deca+subtree.node_number()
     274        return LTR._element_constructor_(liste,label=shift)
     275
     276    def tree_factorial(self):
     277        """
     278        Returns the tree-factorial of ``self``
     279
     280        Definition:
     281
     282        The tree-factorial `T!` of a tree `T` is the product `\prod_{v\in
     283        T}\#\mbox{children}(v)`.
     284
     285        EXAMPLES::
     286
     287            sage: LT=LabelledOrderedTrees()
     288            sage: t=LT([LT([],label=6),LT([],label=1)],label=9)
     289            sage: t.tree_factorial()
     290            3
     291
     292            sage: BinaryTree([[],[[],[]]]).tree_factorial()
     293            15
     294
     295        TESTS::
     296
     297            sage: BinaryTree().tree_factorial()
     298            1
     299        """
     300        nb = self.node_number()
     301        if nb <= 1:
     302            return 1
     303        else:
     304            return nb*prod(s.tree_factorial() for s in self)
     305
     306    latex_unit_length   = "4mm"
     307    latex_node_diameter = "0.5"
     308    latex_root_diameter = "0.7"
     309
     310    def _latex_(self):
     311        """
     312        Returns a LaTeX version of ``self``
     313
     314        EXAMPLES::
     315
     316            sage: print(OrderedTree([[],[]])._latex_())
     317            \vcenter{\hbox{{\setlength\unitlength{4mm}
     318            \begin{picture}(4,3)
     319            \put(1,1){\circle*{0.5}}
     320            \put(2,2){\circle*{0.5}}
     321            \put(3,1){\circle*{0.5}}
     322            \put(2,2){\line(-1,-1){1}}
     323            \put(2,2){\line(1,-1){1}}
     324            \put(2,2){\circle*{0.7}}
     325            \end{picture}}}}
     326
     327        TESTS::
     328
     329            sage: OrderedTree([])._latex_()
     330            '\\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}}}}'
     331            sage: OrderedTree([[]])._latex_()
     332            '\\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}}}}'
     333            sage: OrderedTree([[], [[], [[], []], [[], []]], [[], []]])._latex_()
     334            '\\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}}}}'
     335        """
     336        from sage.misc.latex import latex
     337        drawing = [""] # allows modification of  in rec...
     338        x = [1]        # allows modification of x[0] in rec...
     339        max_label_width = [0] # allows modification of x[0] in rec...
     340        maxy = self.depth()
     341
     342        def rec(t, y):
     343            """
     344            Draw the subtree t on the drawing, below y (included) and to
     345            the right of x[0] (included). Update x[0]. Returns the horizontal
     346            position of the root
     347            """
     348            if t.node_number() == 0 : return -1
     349            n = len(t)
     350            posChild = [rec(t[i], y+1) for i in range(n // 2)]
     351            i = n // 2
     352            if n % 2 == 1:
     353                xc = rec(t[i], y+1)
     354                posChild.append(xc)
     355                i += 1
     356            else:
     357                xc = x[0]
     358                x[0] +=1
     359            drawing[0] = drawing[0] + "\\put(%s,%s){\\circle*{%s}}\n"%(
     360                xc, maxy-y, self.latex_node_diameter)
     361            try:
     362                lbl = t.label()
     363            except AttributeError:
     364                pass
     365            else:
     366                max_label_width[0] = 1 # TODO find a better heuristic
     367                drawing[0] = drawing[0] + "\\put(%s,%s){$\scriptstyle %s$}"%(
     368                    xc+0.3, maxy-y-0.3, latex(lbl))
     369            posChild += [rec(t[j], y+1) for j in range(i, n)]
     370            for i in range(n):
     371                if posChild[i] != -1:
     372                    drawing[0] = (drawing[0] +
     373                        "\\put(%s,%s){\\line(%s,-1){%s}}\n"%(
     374                            xc, maxy-y, posChild[i]-xc,
     375                            max(abs(posChild[i]-xc), 1)))
     376            return xc
     377
     378        res = rec(self, 0)
     379        drawing[0] = drawing[0] + "\\put(%s,%s){\\circle*{%s}}\n"%(
     380            res, maxy, self.latex_root_diameter)
     381        return "\\vcenter{\hbox{{\setlength\unitlength{%s}\n\\begin{picture}(%s,%s)\n%s\\end{picture}}}}"%(
     382            self.latex_unit_length,
     383            x[0] + max_label_width[0],
     384            maxy + 1,
     385            drawing[0])
     386
     387class AbstractClonableTree(AbstractTree):
     388    """
     389    Abstract Clonable Tree
     390
     391    An abstract class for trees with clone protocol (see
     392    :mod:`~sage.structure.list_clone`). It is expected that classes extending
     393    this one may also inherit from classes like :class:`ClonableArray` or
     394    :class:`~sage.structure.list_clone.ClonableList` depending wether one
     395    wants to build trees where adding a child is allowed.
     396
     397    .. note:: Due to the limitation of Cython inheritance, one cannot inherit
     398       here from :class:`~sage.structure.list_clone.ClonableElement`, because
     399       it would prevent us to inherit later from
     400       :class:`~sage.structure.list_clone.ClonableArray` or
     401       :class:`~sage.structure.list_clone.ClonableList`.
     402
     403    .. rubric:: How should this class be extended ?
     404
     405    A class extending :class:`AbstractTree
     406    <sage.combinat.abstract_tree.AbstractTree>` should the following
     407    assumptions:
     408
     409    * An instantiable class extending :class:`AbstractTree
     410      <sage.combinat.abstract_tree.AbstractTree>` should also extend the
     411      :class:`ClonableElement <sage.structure.list_clone.ClonableElement>`
     412      class or one of its subclass generally at least :class:`ClonableArray
     413      <sage.structure.list_clone.ClonableArray>`.
     414
     415
     416    * To respect the Clone protocol, the :meth:`AbstractClonableTree.check`
     417      method should be overridden by the new class.
     418    """
     419    def check(self):
     420        """
     421        Check that ``self`` is a correct tree
     422
     423        This method does nothing. It is implemented here because many
     424        extensions of :class:`AbstractTree
     425        <sage.combinat.abstract_tree.AbstractTree>` also extend
     426        :class:`sage.structure.list_clone.ClonableElement`, which requires it.
     427
     428        It should be overriden in subclass is order to chech that the
     429        invariant of the kind of tree holds (eg: two children for binary
     430        trees).
     431
     432        EXAMPLES::
     433
     434            sage: OrderedTree([[],[[]]]).check()
     435            sage: BinaryTree([[],[[],[]]]).check()
     436        """
     437        pass
     438
     439    def __setitem__(self, idx, value):
     440        """
     441        Substitute a subtree
     442
     443        .. NOTE::
     444
     445            The tree ``self`` must be in a mutable state. See
     446            :mod:`sage.structure.list_clone` for more details about
     447            mutability.  The default implementation here assume that the
     448            container of the node implement a method `_setitem` with signature
     449            `self._setitem(idx, value)`. It is usually provided by inheriting
     450            from :class:`~sage.structure.list_clone.ClonableArray`.
     451
     452        INPUT:
     453
     454        - ``idx`` -- a valid path in ``self`` identifying a node
     455
     456        - ``value`` -- the tree to be substituted
     457
     458        EXAMPLES:
     459
     460        Trying to modify a non mutable tree raise an error::
     461
     462            sage: x = OrderedTree([])
     463            sage: x[0] =  OrderedTree([[]])
     464            Traceback (most recent call last):
     465            ...
     466            ValueError: object is immutable; please change a copy instead.
     467
     468        Here is the correct way to do it::
     469
     470            sage: x = OrderedTree([[],[[]]])
     471            sage: with x.clone() as x:
     472            ...    x[0] = OrderedTree([[]])
     473            sage: x
     474            [[[]], [[]]]
     475
     476        One can also substitute at any depths::
     477
     478            sage: y = OrderedTree(x)
     479            sage: with x.clone() as x:
     480            ...    x[0,0] = OrderedTree([[]])
     481            sage: x
     482            [[[[]]], [[]]]
     483            sage: y
     484            [[[]], [[]]]
     485            sage: with y.clone() as y:
     486            ...    y[(0,)] = OrderedTree([])
     487            sage: y
     488            [[], [[]]]
     489
     490        This works for binary trees as well::
     491
     492            sage: bt = BinaryTree([[],[[],[]]]); bt
     493            [[., .], [[., .], [., .]]]
     494            sage: with bt.clone() as bt1:
     495            ...    bt1[0,0] = BinaryTree([[[], []], None])
     496            sage: bt1
     497            [[[[[., .], [., .]], .], .], [[., .], [., .]]]
     498
     499        TESTS::
     500
     501            sage: x = OrderedTree([])
     502            sage: with x.clone() as x:
     503            ...    x[0] = OrderedTree([[]])
     504            Traceback (most recent call last):
     505            ...
     506            IndexError: list assignment index out of range
     507
     508            sage: x = OrderedTree([]); x = OrderedTree([x,x]);x = OrderedTree([x,x]); x = OrderedTree([x,x])
     509            sage: with x.clone() as x:
     510            ...    x[0,0] = OrderedTree()
     511            sage: x
     512            [[[], [[], []]], [[[], []], [[], []]]]
     513        """
     514        assert isinstance(value, self.__class__)
     515
     516        if isinstance(idx, tuple):
     517            self.__setitem_rec__(idx, 0, value)
     518        else:
     519            self._setitem(idx, value)
     520
     521    def __setitem_rec__(self, idx, i, value):
     522        """
     523        TESTS::
     524
     525            sage: x = OrderedTree([[[], []],[[]]])
     526            sage: with x.clone() as x:
     527            ...    x[0,1] = OrderedTree([[[]]]) # indirect doctest
     528            sage: x
     529            [[[], [[[]]]], [[]]]
     530        """
     531        if i == len(idx) - 1:
     532            self._setitem(idx[-1], value)
     533        else:
     534            with self[idx[i]].clone() as child:
     535                child.__setitem_rec__(idx, i+1, value)
     536            self[idx[i]] = child
     537
     538    def __getitem__(self, idx):
     539        """
     540        INPUT:
     541
     542        - ``idx`` -- a valid path in ``self`` identifying a node
     543
     544        ..note::
     545
     546            The default implementation here assume that the container of the
     547            node inherits from
     548            :class:`~sage.structure.list_clone.ClonableArray`.
     549
     550        EXAMPLES::
     551
     552            sage: x = OrderedTree([[],[[]]])
     553            sage: x[1,0]
     554            []
     555            sage: x = OrderedTree([[],[[]]])
     556            sage: x[()]
     557            [[], [[]]]
     558            sage: x[(0,)]
     559            []
     560            sage: x[0,0]
     561            Traceback (most recent call last):
     562            ...
     563            IndexError: list index out of range
     564        """
     565        if isinstance(idx, slice):
     566            return ClonableArray.__getitem__(self, idx)
     567        try:
     568            i = int(idx)
     569        except TypeError:
     570            res = self
     571            # idx is supposed to be an iterable of ints
     572            for i in idx:
     573                res = ClonableArray._getitem(res, i)
     574            return res
     575        else:
     576            return ClonableArray._getitem(self, i)
     577
     578
     579class AbstractLabelledTree(AbstractTree):
     580    """
     581    Abstract Labelled Tree
     582
     583    Typically a class for labelled tree is contructed by inheriting from a
     584    class for unlabelled trees and :class:`AbstractLabelledTree`
     585
     586    .. rubric:: How should this class be extended ?
     587
     588    A class extending :class:`AbstractLabelledTree
     589    <sage.combinat.abstract_tree.AbstractLabelledTree>` should respect the
     590    following assumptions:
     591
     592    * For a labelled tree ``T`` the call ``T.parent().unlabelled_trees()``
     593      should return a parent for labelled trees of the same kind: for example,
     594
     595      - if ``T`` is a binary labelled tree, ``T.parent()`` is
     596        ``LabelledBinaryTrees()`` and ``T.parent().unlabelled_trees()`` is
     597        ``BinaryTrees()``
     598
     599      - if ``T`` is an ordered labelled tree, ``T.parent()`` is
     600        ``LabelledOrderedTrees()`` and ``T.parent().unlabelled_trees()`` is
     601        ``OrderedTrees()``
     602
     603    * In the same vein, the class of ``T`` should contains an attribute
     604      ``_Unlabelled`` which should be the class for the corresponding
     605      unlabelled trees.
     606
     607    .. SEEALSO:: :class:`AbstractTree`
     608    """
     609    def __init__(self, parent, children, label = None, check = True):
     610        """
     611        TESTS::
     612
     613            sage: LabelledOrderedTree([])
     614            None[]
     615            sage: LabelledOrderedTree([], 3)
     616            3[]
     617            sage: LT = LabelledOrderedTree
     618            sage: t = LT([LT([LT([], label=42), LT([], 21)])], label=1)
     619            sage: t
     620            1[None[42[], 21[]]]
     621            sage: LabelledOrderedTree(OrderedTree([[],[[],[]],[]]))
     622            None[None[], None[None[], None[]], None[]]
     623        """
     624        # We must initialize the label before the subtrees to allows rooted
     625        # trees canonization. Indeed it needs that ``self``._hash_() is working
     626        # at the end of the call super(..., self).__init__(...)
     627        if isinstance(children, self.__class__):
     628            if label is None:
     629                self._label = children._label
     630            else:
     631                self._label = label
     632        else:
     633            self._label = label
     634        super(AbstractLabelledTree, self).__init__(parent, children, check=check)
     635
     636    def _repr_(self):
     637        """
     638        Returns the string representation of ``self``
     639
     640        TESTS::
     641
     642            sage: LabelledOrderedTree([])            # indirect doctest
     643            None[]
     644            sage: LabelledOrderedTree([], label=3)   # indirect doctest
     645            3[]
     646            sage: LabelledOrderedTree([[],[[]]])     # indirect doctest
     647            None[None[], None[None[]]]
     648            sage: LabelledOrderedTree([[],LabelledOrderedTree([[]], label=2)], label=3)
     649            3[None[], 2[None[]]]
     650        """
     651        return "%s%s"%(self._label, self[:])
     652
     653    def label(self, path=None):
     654        """
     655        Returns the label of ``self``
     656
     657        INPUT:
     658
     659        - ``path`` -- None (default) or a path (list or tuple of children index
     660                     in the tree)
     661
     662        OUTPUT: the label of the subtree at indexed by ``path``
     663
     664        EXAMPLES::
     665
     666            sage: t=LabelledOrderedTree([[],[]], label = 3)
     667            sage: t.label()
     668            3
     669            sage: t[0].label()
     670            sage: t=LabelledOrderedTree([LabelledOrderedTree([], 5),[]], label = 3)
     671            sage: t.label()
     672            3
     673            sage: t[0].label()
     674            5
     675            sage: t[1].label()
     676            sage: t.label([0])
     677            5
     678        """
     679        if path is None:
     680            return self._label
     681        else:
     682            tr = self
     683            for i in path:
     684                tr = tr[i]
     685            return tr._label
     686
     687    def labels(self):
     688        """
     689        Returns the list of labels of ``self``
     690
     691        EXAMPLES::
     692
     693            sage: LT = LabelledOrderedTree
     694            sage: t = LT([LT([],label='b'),LT([],label='c')],label='a')
     695            sage: t.labels()
     696            ['a', 'b', 'c']
     697
     698            sage: LBT = LabelledBinaryTree
     699            sage: LBT([LBT([],label=1),LBT([],label=4)],label=2).labels()
     700            [2, 1, 4]
     701        """
     702        return [t.label() for t in self.subtrees()]
     703
     704    def leaf_labels(self):
     705        """
     706        Returns the list of labels of the leaves of ``self``
     707
     708        EXAMPLES::
     709
     710            sage: LT = LabelledOrderedTree
     711            sage: t = LT([LT([],label='b'),LT([],label='c')],label='a')
     712            sage: t.leaf_labels()
     713            ['b', 'c']
     714
     715            sage: LBT = LabelledBinaryTree
     716            sage: bt = LBT([LBT([],label='b'),LBT([],label='c')],label='a')
     717            sage: bt.leaf_labels()
     718            ['b', 'c']
     719            sage: LBT([], label='1').leaf_labels()
     720            ['1']
     721            sage: LBT(None).leaf_labels()
     722            []
     723        """
     724        return [t.label() for t in self.subtrees() if t.node_number()==1]
     725
     726    def __eq__(self, other):
     727        """
     728        Tests if ``self`` is equal to ``other``
     729
     730        TESTS::
     731
     732            sage  LabelledOrderedTree() == LabelledOrderedTree()
     733            True
     734            sage  LabelledOrderedTree([]) == LabelledOrderedTree()
     735            False
     736            sage: t1 = LabelledOrderedTree([[],[[]]])
     737            sage: t2 = LabelledOrderedTree([[],[[]]])
     738            sage: t1 == t2
     739            True
     740            sage: t2 = LabelledOrderedTree(t1)
     741            sage: t1 == t2
     742            True
     743            sage: t1 = LabelledOrderedTree([[],[[]]])
     744            sage: t2 = LabelledOrderedTree([[[]],[]])
     745            sage: t1 == t2
     746            False
     747        """
     748        return ( super(AbstractLabelledTree, self).__eq__(other) and
     749                 self._label == other._label )
     750
     751    def _hash_(self):
     752        """
     753        Returns the hash value for ``self``
     754
     755        TESTS::
     756
     757            sage: t1 = LabelledOrderedTree([[],[[]]], label = 1); t1hash = t1.__hash__()
     758            sage: LabelledOrderedTree([[],[[]]], label = 1).__hash__() == t1hash
     759            True
     760            sage: LabelledOrderedTree([[[]],[]], label = 1).__hash__() == t1hash
     761            False
     762            sage: LabelledOrderedTree(t1, label = 1).__hash__() == t1hash
     763            True
     764            sage: LabelledOrderedTree([[],[[]]], label = 25).__hash__() == t1hash
     765            False
     766            sage: LabelledOrderedTree(t1, label = 25).__hash__() == t1hash
     767            False
     768
     769            sage: LabelledBinaryTree([[],[[],[]]], label = 25).__hash__() #random
     770            8544617749928727644
     771
     772        We check that the hash value depend on the value of the labels of the
     773        subtrees::
     774
     775            sage: LBT = LabelledBinaryTree
     776            sage: t1 = LBT([], label = 1)
     777            sage: t2 = LBT([], label = 2)
     778            sage: t3 = LBT([], label = 3)
     779            sage: t12 = LBT([t1, t2], label = "a")
     780            sage: t13 = LBT([t1, t3], label = "a")
     781            sage: t12.__hash__() != t13.__hash__()
     782            True
     783        """
     784        return self._UnLabelled._hash_(self) ^ hash(self._label)
     785
     786    def shape(self):
     787        """
     788        Returns the unlabelled tree associated to ``self``
     789
     790        EXAMPLES::
     791
     792            sage: t = LabelledOrderedTree([[],[[]]], label = 25).shape(); t
     793            [[], [[]]]
     794
     795            sage: LabelledBinaryTree([[],[[],[]]], label = 25).shape()
     796            [[., .], [[., .], [., .]]]
     797
     798        TESTS::
     799
     800            sage: t.parent()
     801            Ordered trees
     802            sage: type(t)
     803            <class 'sage.combinat.ordered_tree.OrderedTrees_all_with_category.element_class'>
     804        """
     805        TR = self.parent().unlabelled_trees()
     806        if not self:
     807            return TR.leaf()
     808        else:
     809            return TR._element_constructor_([i.shape() for i in self])
     810
     811    def as_digraph(self):
     812        """
     813        Returns a directed graph version of ``self``
     814
     815        EXAMPLES::
     816
     817           sage: LT=LabelledOrderedTrees()
     818           sage: ko=LT([LT([],label=6),LT([],label=1)],label=9)
     819           sage: ko.as_digraph()
     820           Digraph on 3 vertices
     821
     822           sage: t = BinaryTree([[None, None],[[],None]]);
     823           sage: lt = t.canonical_labelling()
     824           sage: lt.as_digraph()
     825           Digraph on 4 vertices
     826        """
     827        from sage.graphs.digraph import DiGraph
     828        resu=dict([[self.label(),
     829                    [t.label() for t in self if not t.is_empty()]]])
     830        resu=DiGraph(resu)
     831        for t in self:
     832            if not t.is_empty():
     833                resu=resu.union(t.as_digraph())
     834        return resu
     835
     836
     837class AbstractLabelledClonableTree(AbstractLabelledTree,
     838                                   AbstractClonableTree):
     839    """
     840    Abstract Labelled Clonable Tree
     841
     842    This class take care of modification for the label by the clone protocol.
     843
     844    .. note:: Due to the limitation of Cython inheritance, one cannot inherit
     845       here from :class:`ClonableArray`, because it would prevent us to
     846       inherit later from :class:`~sage.structure.list_clone.ClonableList`.
     847    """
     848    def set_root_label(self, label):
     849        """
     850        Sets the label of the root of ``self``
     851
     852        INPUT: ``label`` -- any Sage object
     853
     854        OUPUT: ``None``, ``self`` is modified in place
     855
     856        .. note::
     857
     858            ``self`` must be in a mutable state. See
     859            :mod:`sage.structure.list_clone` for more details about
     860            mutability.
     861
     862        EXAMPLES::
     863
     864            sage: t=LabelledOrderedTree([[],[[],[]]])
     865            sage: t.set_root_label(3)
     866            Traceback (most recent call last):
     867            ...
     868            ValueError: object is immutable; please change a copy instead.
     869            sage: with t.clone() as t:
     870            ...    t.set_root_label(3)
     871            sage: t.label()
     872            3
     873            sage: t
     874            3[None[], None[None[], None[]]]
     875
     876        This also work for binary trees::
     877
     878            sage: bt=LabelledBinaryTree([[],[]])
     879            sage: bt.set_root_label(3)
     880            Traceback (most recent call last):
     881            ...
     882            ValueError: object is immutable; please change a copy instead.
     883            sage: with bt.clone() as bt:
     884            ...    bt.set_root_label(3)
     885            sage: bt.label()
     886            3
     887            sage: bt
     888            3[None[., .], None[., .]]
     889
     890        TESTS::
     891
     892            sage: with t.clone() as t:
     893            ...    t[0] = LabelledOrderedTree(t[0], label = 4)
     894            sage: t
     895            3[4[], None[None[], None[]]]
     896            sage: with t.clone() as t:
     897            ...    t[1,0] = LabelledOrderedTree(t[1,0], label = 42)
     898            sage: t
     899            3[4[], None[42[], None[]]]
     900            """
     901        self._require_mutable()
     902        self._label = label
     903
     904    def set_label(self, path, label):
     905        """
     906        Changes the label of subtree indexed by ``path`` to ``label``
     907
     908        INPUT:
     909
     910        - ``path`` -- ``None`` (default) or a path (list or tuple of children
     911                      index in the tree)
     912
     913        - ``label`` -- any sage object
     914
     915        OUPUT: Nothing, ``self`` is modified in place
     916
     917        .. note::
     918
     919            ``self`` must be in a mutable state. See
     920            :mod:`sage.structure.list_clone` for more details about
     921            mutability.
     922
     923        EXAMPLES::
     924
     925            sage: t=LabelledOrderedTree([[],[[],[]]])
     926            sage: t.set_label((0,), 4)
     927            Traceback (most recent call last):
     928            ...
     929            ValueError: object is immutable; please change a copy instead.
     930            sage: with t.clone() as t:
     931            ...    t.set_label((0,), 4)
     932            sage: t
     933            None[4[], None[None[], None[]]]
     934            sage: with t.clone() as t:
     935            ...    t.set_label((1,0), label = 42)
     936            sage: t
     937            None[4[], None[42[], None[]]]
     938
     939        .. todo::
     940
     941            Do we want to implement the following syntactic sugar::
     942
     943                with t.clone() as tt:
     944                    tt.labels[1,2] = 3 ?
     945        """
     946        self._require_mutable()
     947        path = tuple(path)
     948        if path == ():
     949            self._label = label
     950        else:
     951            with self[path[0]].clone() as child:
     952                child.set_label(path[1:], label)
     953            self[path[0]] = child
     954
     955    def map_labels(self, f):
     956        """
     957        Applies the function `f` to the labels of ``self``
     958
     959        This method returns a copy of ``self`` on which the function `f` has
     960        been applied on all labels (a label `x` is replaced by `f(x)`).
     961
     962        EXAMPLES::
     963
     964            sage: LT = LabelledOrderedTree
     965            sage: t = LT([LT([],label=1),LT([],label=7)],label=3); t
     966            3[1[], 7[]]
     967            sage: t.map_labels(lambda z:z+1)
     968            4[2[], 8[]]
     969
     970            sage: LBT = LabelledBinaryTree
     971            sage: bt = LBT([LBT([],label=1),LBT([],label=4)],label=2); bt
     972            2[1[., .], 4[., .]]
     973            sage: bt.map_labels(lambda z:z+1)
     974            3[2[., .], 5[., .]]
     975        """
     976        if self.is_empty():
     977            return self
     978        return self.parent()([t.map_labels(f) for t in self],
     979                             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
     11On the use of Factories to query a database of counting algorithms
     12------------------------------------------------------------------
     13
     14**The problem we try to solve**
     15
     16A common problem in combinatorics is to enumerate or count some standard
     17mathematical objects satisfying a set of constraints. For instance, one can be
     18interested in the :mod:`partitions <sage.combinat.partition>` of an integer `n`
     19of length `7` and parts of size at least `3` and at most `8`, [...]
     20
     21For partitions, the number of different parameters available is actually quite
     22large :
     23
     24- The length of the partition (i.e. partitions in `k` parts, or in "at least"
     25  `k_1` parts "at most" `k_2` parts).
     26
     27- The sum of the partition (i.e. the integer `n`).
     28
     29- The min/max size of a part, or even a set of integers such that the partition
     30  should only use integers from the given set.
     31
     32- The min/max slope of the partition.
     33
     34- An inner and outer profile.
     35
     36- A min/max value for the lexicographical ordering of the partition.
     37
     38One may in particular be interested in enumerating/counting the partitions
     39satisfying *some arbitrary combination* of constraints using the parameters
     40listed above.
     41
     42This all means that there is a real need of unifying a large family of
     43algorithms, so that users do not have to find their way through a library
     44of 50 different counting/enumeration algorithms *all* dealing with partitions
     45with different set of parameters.
     46
     47**How we solve it**
     48
     49We try to build a *database* of algorithms that the user can query easily in
     50order to use the best implementation for his needs.
     51
     52Namely, in the case of :mod:`partitions <sage.combinat.partition>`, we want to
     53define a class factory named ``Partitions`` and accepting any combination of
     54constraints as an input. The role of the ``Partitions`` class factory is in this
     55situation to identify the counting/enumeration algorithm corresponding to this
     56set of constraint, and to return a hand-made object with the best set of
     57methods.
     58
     59**The design**
     60
     61For each combination of constraints that has specific enumeration/counting
     62algorithms in Sage, we want to create a corresponding class. The result will be
     63-- if we stick with the example of partitions -- a brand new Zoo with weird things
     64inside :
     65
     66- ``PartitionsWithFixedSlopeAndOuterProfile(slope, outer_profile)`` --
     67  representing the partitions with slope ``slope`` and outer profile
     68  ``outer_profile``
     69
     70- ``PartitionsWithRestrictedPartsAndBoundedLength(part_set, length)`` --
     71  represeting the partitions with a set of allowed parts and given length.
     72
     73- ...
     74
     75Each of these classes should define methods like ``__iter__`` (so that we can
     76iterate on its elements) or ``cardinality``.
     77
     78The main class ``Partitions`` will then take as arguments *all of the*
     79*combinations of parameters the user may like*, and query the database for the
     80best secialized class implemented. The user then receives an instance of this
     81specialized class that he can use with the best algorithms implemented.
     82
     83Of course, it may happen that there is actually no algorithm able to enumerate
     84partitions with the set of constraints specified. In this case, the best way is
     85to build a class enumerating a larger set of partitions, and to check for each
     86of them whether is also satisfies the more restrictive set of constraints. This
     87is costly, but it is the best way available, and the library should also be able
     88to answer the question *"what is the best implementation available to list the
     89partitions asked by the user ?"*. We then need to make sure we enumerate as few
     90unnecessary elements as possible.
     91
     92**AUTHORS:**
     93
     94- Florent Hivert (2010-2011): initial implementation.
     95"""
     96#*****************************************************************************
     97#       Copyright (C) 2010 Florent Hivert <Florent.Hivert@univ-rouen.fr>,
     98#
     99#  Distributed under the terms of the GNU General Public License (GPL)
     100#  as published by the Free Software Foundation; either version 2 of
     101#  the License, or (at your option) any later version.
     102#                  http://www.gnu.org/licenses/
     103#*****************************************************************************
     104from sage.structure.list_clone import ClonableArray, ClonableList
     105from sage.combinat.abstract_tree import (AbstractClonableTree,
     106                                         AbstractLabelledClonableTree)
     107from sage.combinat.ordered_tree import LabelledOrderedTrees
     108from sage.rings.integer import Integer
     109from sage.misc.classcall_metaclass import ClasscallMetaclass
     110from sage.misc.lazy_attribute import lazy_attribute, lazy_class_attribute
     111
     112class BinaryTree(AbstractClonableTree, ClonableArray):
     113    """
     114    The class of binary trees
     115
     116    INPUT:
     117
     118    - ``children`` -- ``None`` (default) or a list, tuple or iterable of
     119      length 2 of binary trees or convertible objects.
     120
     121    - ``check`` -- (default to ``True``) whether check for binary should be
     122      performed or not.
     123
     124    .. warning:: despite what the HTML documentation may say, ``BinaryTree``
     125                 does not have any ``parent`` argument, as the examples below
     126                 show.
     127
     128    EXAMPLES::
     129
     130        sage: BinaryTree()
     131        .
     132        sage: BinaryTree([None, None])
     133        [., .]
     134        sage: BinaryTree([None, []])
     135        [., [., .]]
     136        sage: BinaryTree([[], None])
     137        [[., .], .]
     138        sage: BinaryTree([[], None, []])
     139        Traceback (most recent call last):
     140        ...
     141        AssertionError: This is not a binary tree
     142
     143    TESTS::
     144
     145        sage: t1 = BinaryTree([[None, [[],[[], None]]],[[],[]]])
     146        sage: t2 = BinaryTree([[[],[]],[]])
     147        sage: with t1.clone() as t1c:
     148        ...       t1c[1,1,1] = t2
     149        sage: t1 == t1c
     150        False
     151    """
     152    __metaclass__ = ClasscallMetaclass
     153
     154    @staticmethod
     155    def __classcall_private__(cls, *args, **opts):
     156        """
     157        Ensure that binary trees created by the enumerated sets and directly
     158        are the same and that they are instances of :class:`BinaryTree`
     159
     160        TESTS::
     161
     162            sage: from sage.combinat.binary_tree import BinaryTrees_all
     163            sage: issubclass(BinaryTrees_all().element_class, BinaryTree)
     164            True
     165            sage: t0 = BinaryTree([[],[[], None]])
     166            sage: t0.parent()
     167            Binary trees
     168            sage: type(t0)
     169            <class 'sage.combinat.binary_tree.BinaryTrees_all_with_category.element_class'>
     170
     171            sage: t1 = BinaryTrees()([[],[[], None]])
     172            sage: t1.parent() is t0.parent()
     173            True
     174            sage: type(t1) is type(t0)
     175            True
     176
     177            sage: t1 = BinaryTrees(4)([[],[[], None]])
     178            sage: t1.parent() is t0.parent()
     179            True
     180            sage: type(t1) is type(t0)
     181            True
     182        """
     183        return cls._auto_parent.element_class(cls._auto_parent, *args, **opts)
     184
     185    @lazy_class_attribute
     186    def _auto_parent(cls):
     187        """
     188        The automatic parent of the element of this class
     189
     190        When calling the constructor of an element of this class, one needs a
     191        parent. This class attribute specifies which parent is used.
     192
     193        EXAMPLES::
     194
     195            sage: BinaryTree._auto_parent
     196            Binary trees
     197            sage: BinaryTree([None, None]).parent()
     198            Binary trees
     199         """
     200        return BinaryTrees_all()
     201
     202    def __init__(self, parent, children = None, check=True):
     203        """
     204        TESTS::
     205
     206            sage: BinaryTree([None, None]).parent()
     207            Binary trees
     208        """
     209        if children is None:
     210            children = []
     211        elif children == [] or isinstance(children, (Integer, int)):
     212            children = [None, None]
     213        if (children.__class__ is self.__class__ and
     214            children.parent() == parent):
     215            children = list(children)
     216        else:
     217            children = [self.__class__(parent, x) for x in children]
     218        ClonableArray.__init__(self, parent, children, check=check)
     219
     220    def check(self):
     221        """
     222        Checks that ``self`` is a binary tree
     223
     224        EXAMPLES::
     225
     226            sage: BinaryTree([[], []])     # indirect doctest
     227            [[., .], [., .]]
     228            sage: BinaryTree([[], [], []]) # indirect doctest
     229            Traceback (most recent call last):
     230            ...
     231            AssertionError: This is not a binary tree
     232            sage: BinaryTree([[]])         # indirect doctest
     233            Traceback (most recent call last):
     234            ...
     235            AssertionError: This is not a binary tree
     236        """
     237        assert (not self or len(self) == 2), "This is not a binary tree"
     238
     239    def _repr_(self):
     240        """
     241        TESTS::
     242
     243            sage: t1 = BinaryTree([[], None]); t1  # indirect doctest
     244            [[., .], .]
     245            sage: BinaryTree([[None, t1], None])   # indirect doctest
     246            [[., [[., .], .]], .]
     247        """
     248        if not self:
     249            return "."
     250        else:
     251            return super(BinaryTree, self)._repr_()
     252
     253    def is_empty(self):
     254        """
     255        Returns whether ``self`` is  empty.
     256
     257        EXAMPLES::
     258
     259            sage: BinaryTree().is_empty()
     260            True
     261            sage: BinaryTree([]).is_empty()
     262            False
     263            sage: BinaryTree([[], None]).is_empty()
     264            False
     265        """
     266        return not self
     267
     268    def graph(self):
     269        """
     270        Convert ``self`` to a digraph
     271
     272        EXAMPLE::
     273
     274            sage: t1 = BinaryTree([[], None])
     275            sage: t1.graph()
     276            Digraph on 5 vertices
     277
     278            sage: t1 = BinaryTree([[], [[], None]])
     279            sage: t1.graph()
     280            Digraph on 9 vertices
     281            sage: t1.graph().edges()
     282            [(0, 1, None), (0, 4, None), (1, 2, None), (1, 3, None), (4, 5, None), (4, 8, None), (5, 6, None), (5, 7, None)]
     283        """
     284        from sage.graphs.graph import DiGraph
     285        res = DiGraph()
     286        def rec(tr, idx):
     287            if not tr:
     288                return
     289            else:
     290                nbl = 2*tr[0].node_number() + 1
     291                res.add_edges([[idx,idx+1], [idx,idx+1+nbl]])
     292                rec(tr[0], idx + 1)
     293                rec(tr[1], idx + nbl + 1)
     294        rec(self, 0)
     295        return res
     296
     297    def canonical_labelling(self,shift=1):
     298        """
     299        Returns a labelled version of ``self``.
     300
     301        The actual canonical labelling is currently unspecified. However, it
     302        is guaranteed to have labels in `1...n` where `n` is the number of
     303        node of the tree. Moreover, two (unlabelled) trees compare as equal if
     304        and only if they canonical labelled trees compare as equal.
     305
     306        EXAMPLES::
     307
     308            sage: BinaryTree().canonical_labelling()
     309            .
     310            sage: BinaryTree([]).canonical_labelling()
     311            1[., .]
     312            sage: BinaryTree([[[], [[], None]], [[], []]]).canonical_labelling()
     313            5[2[1[., .], 4[3[., .], .]], 7[6[., .], 8[., .]]]
     314        """
     315        LTR = self.parent().labelled_trees()
     316        if self:
     317            sz0 = self[0].node_number()
     318            return LTR([self[0].canonical_labelling(shift),
     319                        self[1].canonical_labelling(shift+1+sz0)],
     320                       label=shift+sz0)
     321        else:
     322            return LTR(None)
     323
     324    def show(self):
     325        """
     326        TESTS::
     327
     328            sage: t1 = BinaryTree([[], [[], None]])
     329            sage: t1.show()
     330        """
     331        self.graph().show(layout='tree', tree_root=0, tree_orientation="down")
     332
     333    def make_node(self, child_list = [None, None]):
     334        """
     335        Modify ``self`` so that it becomes a node with children ``childlist``
     336
     337        INPUT:
     338
     339        - ``child_list`` -- a pair of binary trees (or objects convertible to)
     340
     341        .. note:: ``self`` must be in a mutable state.
     342
     343        .. seealso::
     344            :meth:`make_leaf <sage.combinat.binary_tree.BinaryTree.make_leaf>`
     345
     346        EXAMPLES::
     347
     348            sage: t = BinaryTree()
     349            sage: t.make_node([None, None])
     350            Traceback (most recent call last):
     351            ...
     352            ValueError: object is immutable; please change a copy instead.
     353            sage: with t.clone() as t1:
     354            ...    t1.make_node([None, None])
     355            sage: t, t1
     356            (., [., .])
     357            sage: with t.clone() as t:
     358            ...    t.make_node([BinaryTree(), BinaryTree(), BinaryTree([])])
     359            Traceback (most recent call last):
     360            AssertionError: the list must have length 2
     361            sage: with t1.clone() as t2:
     362            ...    t2.make_node([t1, t1])
     363            sage: with t2.clone() as t3:
     364            ...    t3.make_node([t1, t2])
     365            sage: t1, t2, t3
     366            ([., .], [[., .], [., .]], [[., .], [[., .], [., .]]])
     367        """
     368        self._require_mutable()
     369        child_lst = [self.__class__(self.parent(), x) for x in child_list]
     370        assert(len(child_lst) == 2), "the list must have length 2"
     371        self.__init__(self.parent(), child_lst, check=False)
     372
     373    def make_leaf(self):
     374        """
     375        Modify ``self`` so that it became a leaf
     376
     377        .. note:: ``self`` must be in a mutable state.
     378
     379        .. seealso::
     380            :meth:`make_node <sage.combinat.binary_tree.BinaryTree.make_node>`
     381
     382        EXAMPLES::
     383
     384            sage: t = BinaryTree([None, None])
     385            sage: t.make_leaf()
     386            Traceback (most recent call last):
     387            ...
     388            ValueError: object is immutable; please change a copy instead.
     389            sage: with t.clone() as t1:
     390            ...    t1.make_leaf()
     391            sage: t, t1
     392            ([., .], .)
     393        """
     394        self._require_mutable()
     395        self.__init__(self.parent(), None)
     396
     397    def _to_dyck_word_rec(self):
     398        r"""
     399        EXAMPLES::
     400
     401            sage: BinaryTree()._to_dyck_word_rec()
     402            []
     403            sage: BinaryTree([])._to_dyck_word_rec()
     404            [1, 0]
     405            sage: BinaryTree([[[], [[], None]], [[], []]])._to_dyck_word_rec()
     406            [1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0]
     407        """
     408        if self:
     409            return ([1]+self[0]._to_dyck_word_rec()+
     410                    [0]+self[1]._to_dyck_word_rec())
     411        else:
     412            return []
     413
     414    def to_dyck_word(self):
     415        r"""
     416        Return the Dyck word associated to ``self``
     417
     418        The bijection is defined recursively as follows:
     419
     420        - a leaf is associated to the empty Dyck Word
     421
     422        - a tree with chidren `l,r` is associated to the Dyck word
     423          `1 T(l) 0 T(r)` where `T(l)` and `T(r)` are the trees
     424          associated to `l` and `r`.
     425
     426        EXAMPLES::
     427
     428            sage: BinaryTree().to_dyck_word()
     429            []
     430            sage: BinaryTree([]).to_dyck_word()
     431            [1, 0]
     432            sage: BinaryTree([[[], [[], None]], [[], []]]).to_dyck_word()
     433            [1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0]
     434        """
     435        from sage.combinat.dyck_word import DyckWord
     436        return DyckWord(self._to_dyck_word_rec())
     437
     438    def canopee(self):
     439        """
     440        Returns the canopee of ``self``
     441
     442        The *canopee* of a non empty binary tree `T` with `n` internal nodes is
     443        the list `l` of `0` and `1` of length `n-1` obtained by going along the
     444        leaves of `T` from left to right except the two extremal ones, writing
     445        `0` if the leaf is a right leaf and `1` is a left leaf.
     446
     447        EXAMPLES::
     448
     449            sage: BinaryTree([]).canopee()
     450            []
     451            sage: BinaryTree([None, []]).canopee()
     452            [1]
     453            sage: BinaryTree([[], None]).canopee()
     454            [0]
     455            sage: BinaryTree([[], []]).canopee()
     456            [0, 1]
     457            sage: BinaryTree([[[], [[], None]], [[], []]]).canopee()
     458            [0, 1, 0, 0, 1, 0, 1]
     459
     460        The number of pairs `(t_1, t_2)` of binary trees of size `n` such that
     461        the canopee of `t_1` is the complementary of the canopee of `t_2` is
     462        also the number of Baxter permutations (see [DG]_, see also sequences
     463        A001181 in Sloane's database). We check this in small cases::
     464
     465            sage: [len([(u,v) for u in BinaryTrees(n) for v in BinaryTrees(n)
     466            ...       if map(lambda x:1-x, u.canopee()) == v.canopee()])
     467            ...    for n in range(1, 5)]
     468            [1, 2, 6, 22]
     469
     470        Here is a less trivial implementation of this::
     471
     472            sage: from sage.sets.finite_set_map_cy import fibers
     473            sage: from sage.misc.all import attrcall
     474            sage: def baxter(n):
     475            ...      f = fibers(lambda t: tuple(t.canopee()),
     476            ...                   BinaryTrees(n))
     477            ...      return sum(len(f[i])*len(f[tuple(1-x for x in i)])
     478            ...                 for i in f)
     479            sage: [baxter(n) for n in range(1, 7)]
     480            [1, 2, 6, 22, 92, 422]
     481
     482        TESTS::
     483
     484            sage: t = BinaryTree().canopee()
     485            Traceback (most recent call last):
     486            ...
     487            ValueError: canopee is only defined for non empty binary trees
     488
     489        REFERENCES:
     490
     491            .. [DG] S. Dulucq and O, Guibert. Mots de piles, tableaux
     492               standards et permutations de Baxter, proceedings of
     493               Formal Power Series and Algebraic Combinatorics, 1994.
     494        """
     495        if not self:
     496            raise ValueError, "canopee is only defined for non empty binary trees"
     497        res = []
     498        def add_leaf_rec(tr):
     499            for i in range(2):
     500                if tr[i]:
     501                    add_leaf_rec(tr[i])
     502                else:
     503                    res.append(1-i)
     504        add_leaf_rec(self)
     505        return res[1:-1]
     506
     507
     508from sage.structure.parent import Parent
     509from sage.structure.unique_representation import UniqueRepresentation
     510from sage.misc.classcall_metaclass import ClasscallMetaclass
     511
     512from sage.sets.non_negative_integers import NonNegativeIntegers
     513from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets
     514from sage.sets.family import Family
     515from sage.misc.cachefunc import cached_method
     516
     517
     518# Abstract class to serve as a Factory no instance are created.
     519class BinaryTrees(UniqueRepresentation, Parent):
     520    """
     521    Factory for binary trees.
     522
     523    INPUT:
     524
     525    - ``size`` -- (optional) an integer
     526
     527    OUPUT:
     528
     529    - the set of all binary trees (of the given ``size`` if specified)
     530
     531    EXAMPLES::
     532
     533        sage: BinaryTrees()
     534        Binary trees
     535
     536        sage: BinaryTrees(2)
     537        Binary trees of size 2
     538
     539    .. note:: this in a factory class whose constructor returns instances of
     540              subclasses.
     541
     542    .. note:: the fact that OrderedTrees is a class instead a simple callable
     543              is an implementation detail. It could be changed in the future
     544              and one should not rely on it.
     545    """
     546    @staticmethod
     547    def __classcall_private__(cls, n=None):
     548        """
     549        TESTS::
     550
     551            sage: from sage.combinat.binary_tree import BinaryTrees_all, BinaryTrees_size
     552            sage: isinstance(BinaryTrees(2), BinaryTrees)
     553            True
     554            sage: isinstance(BinaryTrees(), BinaryTrees)
     555            True
     556            sage: BinaryTrees(2) is BinaryTrees_size(2)
     557            True
     558            sage: BinaryTrees(5).cardinality()
     559            42
     560            sage: BinaryTrees() is BinaryTrees_all()
     561            True
     562        """
     563        if n is None:
     564            return BinaryTrees_all()
     565        else:
     566            assert (isinstance(n, (Integer, int)) and n >= 0), "n must be a non negative integer"
     567            return BinaryTrees_size(Integer(n))
     568
     569    @cached_method
     570    def leaf(self):
     571        """
     572        Return a left tree with ``self`` as parent.
     573
     574        EXAMPLES::
     575
     576            sage: BinaryTrees().leaf()
     577            .
     578
     579        TEST::
     580
     581            sage: (BinaryTrees().leaf() is
     582            ...    sage.combinat.binary_tree.BinaryTrees_all().leaf())
     583            True
     584        """
     585        return self(None)
     586
     587#################################################################
     588# Enumerated set of all binary trees
     589#################################################################
     590class BinaryTrees_all(DisjointUnionEnumeratedSets, BinaryTrees):
     591
     592    def __init__(self):
     593        """
     594        TESTS::
     595
     596            sage: from sage.combinat.binary_tree import BinaryTrees_all
     597            sage: B = BinaryTrees_all()
     598            sage: B.cardinality()
     599            +Infinity
     600
     601            sage: it = iter(B)
     602            sage: (it.next(), it.next(), it.next(), it.next(), it.next())
     603            (., [., .], [., [., .]], [[., .], .], [., [., [., .]]])
     604            sage: it.next().parent()
     605            Binary trees
     606            sage: B([])
     607            [., .]
     608
     609            sage: B is BinaryTrees_all()
     610            True
     611            sage: TestSuite(B).run()
     612            """
     613        DisjointUnionEnumeratedSets.__init__(
     614            self, Family(NonNegativeIntegers(), BinaryTrees_size),
     615            facade=True, keepkey = False)
     616
     617    def _repr_(self):
     618        """
     619        TEST::
     620
     621            sage: BinaryTrees()   # indirect doctest
     622            Binary trees
     623        """
     624        return "Binary trees"
     625
     626    def __contains__(self, x):
     627        """
     628        TESTS::
     629
     630            sage: S = BinaryTrees()
     631            sage: 1 in S
     632            False
     633            sage: S([]) in S
     634            True
     635        """
     636        return isinstance(x, self.element_class)
     637
     638    def __call__(self, x=None, *args, **keywords):
     639        """
     640        Ensure that ``None`` instead of ``0`` is passed by default.
     641
     642        TESTS::
     643
     644            sage: B = BinaryTrees()
     645            sage: B()
     646            .
     647        """
     648        return super(BinaryTrees, self).__call__(x, *args, **keywords)
     649
     650    def unlabelled_trees(self):
     651        """
     652        Returns the set of unlabelled trees associated to ``self``
     653
     654        EXAMPLES::
     655
     656            sage: BinaryTrees().unlabelled_trees()
     657            Binary trees
     658        """
     659        return self
     660
     661    def labelled_trees(self):
     662        """
     663        Returns the set of labelled trees associated to ``self``
     664
     665        EXAMPLES::
     666
     667            sage: BinaryTrees().labelled_trees()
     668            Labelled binary trees
     669        """
     670        return LabelledBinaryTrees()
     671
     672    def _element_constructor_(self, *args, **keywords):
     673        """
     674        EXAMPLES::
     675
     676            sage: B = BinaryTrees()
     677            sage: B._element_constructor_([])
     678            [., .]
     679            sage: B([[],[]]) # indirect doctest
     680            [[., .], [., .]]
     681            sage: B(None)    # indirect doctest
     682            .
     683        """
     684        return self.element_class(self, *args, **keywords)
     685
     686    Element = BinaryTree
     687
     688from sage.misc.lazy_attribute import lazy_attribute
     689from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
     690from combinat import catalan_number
     691#################################################################
     692# Enumerated set of binary trees of a given size
     693#################################################################
     694class BinaryTrees_size(BinaryTrees):
     695    """
     696    The enumerated sets of binary trees of given size
     697
     698    TESTS::
     699
     700        sage: from sage.combinat.binary_tree import BinaryTrees_size
     701        sage: for i in range(6): TestSuite(BinaryTrees_size(i)).run()
     702    """
     703    def __init__(self, size):
     704        """
     705        TESTS::
     706
     707            sage: S = BinaryTrees(3)
     708            sage: S == loads(dumps(S))
     709            True
     710
     711            sage: S is BinaryTrees(3)
     712            True
     713        """
     714        super(BinaryTrees_size, self).__init__(category = FiniteEnumeratedSets())
     715        self._size = size
     716
     717    def _repr_(self):
     718        """
     719        TESTS::
     720
     721            sage: BinaryTrees(3)   # indirect doctest
     722            Binary trees of size 3
     723        """
     724        return "Binary trees of size %s"%(self._size)
     725
     726    def __contains__(self, x):
     727        """
     728        TESTS::
     729
     730            sage: S = BinaryTrees(3)
     731            sage: 1 in S
     732            False
     733            sage: S([[],[]]) in S
     734            True
     735        """
     736        return isinstance(x, self.element_class) and x.node_number() == self._size
     737
     738    def _an_element_(self):
     739        """
     740        TESTS::
     741
     742            sage: BinaryTrees(0).an_element()  # indirect doctest
     743            .
     744        """
     745        return self.first()
     746
     747    def cardinality(self):
     748        """
     749        The cardinality of self
     750
     751        This is a Catalan number.
     752
     753        TESTS::
     754
     755            sage: BinaryTrees(0).cardinality()
     756            1
     757            sage: BinaryTrees(5).cardinality()
     758            42
     759        """
     760        return catalan_number(self._size)
     761
     762    def __iter__(self):
     763        """
     764        A basic generator.
     765
     766        .. todo:: could be optimized.
     767
     768        TESTS::
     769
     770            sage: BinaryTrees(0).list()
     771            [.]
     772            sage: BinaryTrees(1).list()
     773            [[., .]]
     774            sage: BinaryTrees(3).list()
     775            [[., [., [., .]]], [., [[., .], .]], [[., .], [., .]], [[., [., .]], .], [[[., .], .], .]]
     776        """
     777        if self._size == 0:
     778            yield self._element_constructor_()
     779        else:
     780            for i in range(0, self._size):
     781                for lft in self.__class__(i):
     782                    for rgt in self.__class__(self._size-1-i):
     783                        yield self._element_constructor_([lft, rgt])
     784
     785    @lazy_attribute
     786    def _parent_for(self):
     787        """
     788        The parent of the element generated by ``self``
     789
     790        TESTS::
     791
     792            sage: S = BinaryTrees(3)
     793            sage: S._parent_for
     794            Binary trees
     795        """
     796        return BinaryTrees_all()
     797
     798    @lazy_attribute
     799    def element_class(self):
     800        """
     801        TESTS::
     802
     803            sage: S = BinaryTrees(3)
     804            sage: S.element_class
     805            <class 'sage.combinat.binary_tree.BinaryTrees_all_with_category.element_class'>
     806            sage: S.first().__class__ == BinaryTrees().first().__class__
     807            True
     808        """
     809        return self._parent_for.element_class
     810
     811    def _element_constructor_(self, *args, **keywords):
     812        """
     813        EXAMPLES::
     814
     815            sage: S = BinaryTrees(0)
     816            sage: S([])   # indirect doctest
     817            Traceback (most recent call last):
     818            ...
     819            ValueError: Wrong number of nodes
     820            sage: S(None)   # indirect doctest
     821            .
     822
     823            sage: S = BinaryTrees(1)   # indirect doctest
     824            sage: S([])
     825            [., .]
     826        """
     827        res = self.element_class(self._parent_for, *args, **keywords)
     828        if res.node_number() != self._size:
     829            raise ValueError, "Wrong number of nodes"
     830        return res
     831
     832
     833
     834class LabelledBinaryTree(AbstractLabelledClonableTree, BinaryTree):
     835    """
     836    The class of labelled binary tree
     837
     838    EXAMPLE::
     839
     840        sage: LBT = LabelledBinaryTree
     841        sage: t1 = LBT([[LBT([], label=2), None], None], label=4); t1
     842        4[None[2[., .], .], .]
     843    """
     844    __metaclass__ = ClasscallMetaclass
     845
     846    @staticmethod
     847    def __classcall_private__(cls, *args, **opts):
     848        """
     849        Ensure that trees created by the sets and directly are the same and
     850        that they are instance of :class:`LabelledTree`
     851
     852        TESTS::
     853
     854            sage: issubclass(LabelledBinaryTrees().element_class, LabelledBinaryTree)
     855            True
     856            sage: t0 = LabelledBinaryTree([[],[[], None]], label = 3)
     857            sage: t0.parent()
     858            Labelled binary trees
     859            sage: type(t0)
     860            <class 'sage.combinat.binary_tree.LabelledBinaryTrees_with_category.element_class'>
     861        """
     862        return cls._auto_parent.element_class(cls._auto_parent, *args, **opts)
     863
     864    @lazy_class_attribute
     865    def _auto_parent(cls):
     866        """
     867        The automatic parent of the element of this class
     868
     869        When calling the constructor of an element of this class, one need a
     870        parent. This class attribute specifies which parent is used.
     871
     872        EXAMPLES::
     873
     874            sage: LabelledBinaryTree._auto_parent
     875            Labelled binary trees
     876            sage: LabelledBinaryTree([], label = 3).parent()
     877            Labelled binary trees
     878         """
     879        return LabelledBinaryTrees()
     880
     881    def _repr_(self):
     882        """
     883        TESTS::
     884
     885            sage: LBT = LabelledBinaryTree
     886            sage: t1 = LBT([[LBT([], label=2), None], None], label=4); t1
     887            4[None[2[., .], .], .]
     888            sage: LBT([[],[[], None]], label = 3)   # indirect doctest
     889            3[None[., .], None[None[., .], .]]
     890        """
     891        if not self:
     892            if self._label is not None:
     893                return repr(self._label)
     894            else:
     895                return "."
     896        else:
     897            return "%s%s"%(self._label, self[:])
     898
     899    def binary_search_insert(self, letter):
     900        """
     901        Insert a letter in a binary search tree
     902
     903        INPUT:
     904
     905        - ``letter`` -- any object comparable with the label of ``self``
     906
     907        .. note:: ``self`` is supposed to be a binary search tree. No check is
     908                  performed.
     909
     910        EXAMPLES::
     911
     912            sage: LBT = LabelledBinaryTree
     913            sage: LBT(None).binary_search_insert(3)
     914            3[., .]
     915            sage: LBT([], label = 1).binary_search_insert(3)
     916            1[., 3[., .]]
     917            sage: LBT([], label = 3).binary_search_insert(1)
     918            3[1[., .], .]
     919            sage: res = LBT(None)
     920            sage: for i in [3,1,5,2,4,6]:
     921            ...       res = res.binary_search_insert(i)
     922            sage: res
     923            3[1[., 2[., .]], 5[4[., .], 6[., .]]]
     924        """
     925        LT = self.parent()._element_constructor_
     926        if not self:
     927            return LT([], label = letter)
     928        else:
     929            if letter <= self.label():
     930                fils = self[0].binary_search_insert(letter)
     931                return LT([fils, self[1]], label=self.label())
     932            else:
     933                fils = self[1].binary_search_insert(letter)
     934                return LT([self[0], fils], label=self.label())
     935
     936    _UnLabelled = BinaryTree
     937
     938
     939class LabelledBinaryTrees(LabelledOrderedTrees):
     940    """
     941    This is a parent stub to serve as a factory class for trees with various
     942    labels constraints
     943    """
     944    def _repr_(self):
     945        """
     946        TESTS::
     947
     948            sage: LabelledBinaryTrees()   # indirect doctest
     949            Labelled binary trees
     950        """
     951        return "Labelled binary trees"
     952
     953    def _an_element_(self):
     954        """
     955        Returns a labelled binary tree
     956
     957        EXAMPLE::
     958
     959            sage: LabelledBinaryTrees().an_element()   # indirect doctest
     960            toto[42[3[., .], 3[., .]], 5[None[., .], None[., .]]]
     961        """
     962        LT = self._element_constructor_
     963        t  = LT([], label = 3)
     964        t1 = LT([t,t], label = 42)
     965        t2  = LT([[], []], label = 5)
     966        return LT([t1,t2], label = "toto")
     967
     968    def unlabelled_trees(self):
     969        """
     970        Returns the set of unlabelled trees associated to ``self``
     971
     972        EXAMPLES::
     973
     974            sage: LabelledBinaryTrees().unlabelled_trees()
     975            Binary trees
     976
     977        This is used to compute the shape::
     978
     979            sage: t = LabelledBinaryTrees().an_element().shape(); t
     980            [[[., .], [., .]], [[., .], [., .]]]
     981            sage: t.parent()
     982            Binary trees
     983
     984        TESTS::
     985
     986            sage: t = LabelledBinaryTrees().an_element()
     987            sage: t.canonical_labelling()
     988            4[2[1[., .], 3[., .]], 6[5[., .], 7[., .]]]
     989        """
     990        return BinaryTrees_all()
     991
     992    def labelled_trees(self):
     993        """
     994        Returns the set of labelled trees associated to ``self``
     995
     996        EXAMPLES::
     997
     998            sage: LabelledBinaryTrees().labelled_trees()
     999            Labelled binary trees
     1000        """
     1001        return self
     1002
     1003    Element = LabelledBinaryTree
     1004
     1005
     1006
     1007################################################################
     1008# Interface attempt with species...
     1009#
     1010# Kept here for further reference when species will be improved
     1011################################################################
     1012# from sage.combinat.species.library import (
     1013#     CombinatorialSpecies, EmptySetSpecies, SingletonSpecies)
     1014
     1015# BT = CombinatorialSpecies()
     1016# F =  EmptySetSpecies()
     1017# N =  SingletonSpecies()
     1018# BT.define(F+N*(BT*BT))
     1019# # b3 = BT.isotypes(range(3))
     1020# # tr = b3.list()[1]
     1021
     1022# def BTsp_to_bintrees(bt):
     1023#     """
     1024#     sage: from sage.combinat.binary_tree import BT, BTsp_to_bintrees
     1025#     sage: BTsp_to_bintrees(BT.isotypes(range(5))[0])
     1026#     [., [., [., [., [., .]]]]]
     1027#     sage: def spls(size):
     1028#     ...    return map(BTsp_to_bintrees, BT.isotypes(range(size)).list())
     1029#     sage: spls(3)
     1030#     [[., [., [., .]]], [., [[., .], .]], [[., .], [., .]], [[., [., .]], .], [[[., .], .], .]]
     1031#     sage: all(spls(i) == BinaryTrees(i).list() for i in range(5))
     1032#     True
     1033#     """
     1034#     if len(bt) == 0:
     1035#         return BinaryTree()
     1036#     elif len(bt) == 2 and len(bt[1]) == 2:
     1037#         return BinaryTree(map(BTsp_to_bintrees, list(bt[1])))
     1038#     else:
     1039#         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 a 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 the order of the element in the
     32    list. Note that there is no empty ordered tree.
     33
     34    One can create a tree from any list (or more generally iterable) of trees
     35    or objects convertible to a tree.
     36
     37    EXAMPLES::
     38
     39        sage: x = OrderedTree([])
     40        sage: x1 = OrderedTree([x,x])
     41        sage: x2 = OrderedTree([[],[]])
     42        sage: x1 == x2
     43        True
     44        sage: tt1 = OrderedTree([x,x1,x2])
     45        sage: tt2 = OrderedTree([[], [[], []], x2])
     46        sage: tt1 == tt2
     47        True
     48
     49        sage: OrderedTree([]) == OrderedTree()
     50        True
     51
     52    TESTS::
     53
     54        sage: x1.__hash__() == x2.__hash__()
     55        True
     56        sage: tt1.__hash__() == tt2.__hash__()
     57        True
     58
     59    Trees are usually immutable. However they inherits from
     60    :class:`sage.structure.list_clone.ClonableList`. So that they can be
     61    modified using the clone protocol:
     62
     63    Trying to modify a non mutable tree raise an error::
     64
     65        sage: tt1[1] = tt2
     66        Traceback (most recent call last):
     67        ...
     68        ValueError: object is immutable; please change a copy instead.
     69
     70    Here is the correct way to do it::
     71
     72        sage: with tt2.clone() as tt2:
     73        ...    tt2[1] = tt1
     74        sage: tt2
     75        [[], [[], [[], []], [[], []]], [[], []]]
     76
     77    It is also possible to append a child to a tree::
     78
     79        sage: with tt2.clone() as tt3:
     80        ...    tt3.append(OrderedTree([]))
     81        sage: tt3
     82        [[], [[], [[], []], [[], []]], [[], []], []]
     83
     84    Or to insert a child in a tree::
     85
     86        sage: with tt2.clone() as tt3:
     87        ...    tt3.insert(2, OrderedTree([]))
     88        sage: tt3
     89        [[], [[], [[], []], [[], []]], [], [[], []]]
     90
     91    We check that ``tt1`` is not modified and that everything is correct with
     92    respect to equality::
     93
     94        sage: tt1
     95        [[], [[], []], [[], []]]
     96        sage: tt1 == tt2
     97        False
     98        sage: tt1.__hash__() == tt2.__hash__()
     99        False
     100
     101    TESTS::
     102
     103        sage: tt1bis = OrderedTree(tt1)
     104        sage: with tt1.clone() as tt1:
     105        ...    tt1[1] = tt1bis
     106        sage: tt1
     107        [[], [[], [[], []], [[], []]], [[], []]]
     108        sage: tt1 == tt2
     109        True
     110        sage: tt1.__hash__() == tt2.__hash__()
     111        True
     112        sage: len(tt1)
     113        3
     114        sage: tt1[2]
     115        [[], []]
     116        sage: tt1[3]
     117        Traceback (most recent call last):
     118        ...
     119        IndexError: list index out of range
     120        sage: tt1[1:2]
     121        [[[], [[], []], [[], []]]]
     122
     123    Various tests involving construction, equality and hashing::
     124
     125        sage: OrderedTree() == OrderedTree()
     126        True
     127        sage: t1 = OrderedTree([[],[[]]])
     128        sage: t2 = OrderedTree([[],[[]]])
     129        sage: t1 == t2
     130        True
     131        sage: t2 = OrderedTree(t1)
     132        sage: t1 == t2
     133        True
     134        sage: t1 = OrderedTree([[],[[]]])
     135        sage: t2 = OrderedTree([[[]],[]])
     136        sage: t1 == t2
     137        False
     138
     139        sage: t1 = OrderedTree([[],[[]]])
     140        sage: t2 = OrderedTree([[],[[]]])
     141        sage: t1.__hash__() == t2.__hash__()
     142        True
     143        sage: t2 = OrderedTree([[[]],[]])
     144        sage: t1.__hash__() == t2.__hash__()
     145        False
     146        sage: OrderedTree().__hash__() == OrderedTree([]).__hash__()
     147        True
     148        sage: tt1 = OrderedTree([t1,t2,t1])
     149        sage: tt2 = OrderedTree([t1, [[[]],[]], t1])
     150        sage: tt1.__hash__() == tt2.__hash__()
     151        True
     152
     153    Check that the hash value is correctly updated after modification::
     154
     155        sage: with tt2.clone() as tt2:
     156        ...    tt2[1,1] = tt1
     157        sage: tt1.__hash__() == tt2.__hash__()
     158        False
     159    """
     160
     161    __metaclass__ = ClasscallMetaclass
     162
     163    @staticmethod
     164    def __classcall_private__(cls, *args, **opts):
     165        """
     166        Ensure that trees created by the enumerated sets and directly
     167        are the same and that they are instance of :class:`OrderedTree`
     168
     169        TESTS::
     170
     171            sage: issubclass(OrderedTrees().element_class, OrderedTree)
     172            True
     173            sage: t0 = OrderedTree([[],[[], []]])
     174            sage: t0.parent()
     175            Ordered trees
     176            sage: type(t0)
     177            <class 'sage.combinat.ordered_tree.OrderedTrees_all_with_category.element_class'>
     178
     179            sage: t1 = OrderedTrees()([[],[[], []]])
     180            sage: t1.parent() is t0.parent()
     181            True
     182            sage: type(t1) is type(t0)
     183            True
     184
     185            sage: t1 = OrderedTrees(4)([[],[[]]])
     186            sage: t1.parent() is t0.parent()
     187            True
     188            sage: type(t1) is type(t0)
     189            True
     190        """
     191        return cls._auto_parent.element_class(cls._auto_parent, *args, **opts)
     192
     193    @lazy_class_attribute
     194    def _auto_parent(cls):
     195        """
     196        The automatic parent of the element of this class
     197
     198        When calling the constructor of an element of this class, one need a
     199        parent. This class attribute specifies which parent is used.
     200
     201        EXAMPLES::
     202
     203            sage: OrderedTree([[],[[]]])._auto_parent
     204            Ordered trees
     205            sage: OrderedTree([[],[[]]]).parent()
     206            Ordered trees
     207
     208        .. note::
     209
     210            It is possible to bypass the automatic parent mechanism using:
     211
     212                sage: t1 = OrderedTree.__new__(OrderedTree, Parent(), [])
     213                sage: t1.__init__(Parent(), [])
     214                sage: t1
     215                []
     216                sage: t1.parent()
     217                <type 'sage.structure.parent.Parent'>
     218        """
     219        return OrderedTrees_all()
     220
     221    def __init__(self, parent=None, children=[], check=True):
     222        """
     223        TESTS::
     224
     225            sage: t1 = OrderedTrees(4)([[],[[]]])
     226            sage: TestSuite(t1).run()
     227        """
     228        if (children.__class__ is self.__class__ and
     229            children.parent() == parent):
     230            children = list(children)
     231        else:
     232            children = [self.__class__(parent, x) for x in children]
     233        ClonableArray.__init__(self, parent, children, check=check)
     234
     235    def is_empty(self):
     236        """
     237        Return if ``self`` is the empty tree
     238
     239        For ordered trees, returns always ``False``
     240
     241        .. note:: this is different from ``bool(t)`` which returns whether
     242                  ``t`` has some child or not.
     243
     244        EXAMPLES::
     245
     246            sage: t = OrderedTrees(4)([[],[[]]])
     247            sage: t.is_empty()
     248            False
     249            sage: bool(t)
     250            True
     251        """
     252        return False
     253
     254from sage.categories.sets_cat import Sets, EmptySetError
     255from sage.rings.integer import Integer
     256from sage.sets.non_negative_integers import NonNegativeIntegers
     257from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets
     258from sage.sets.family import Family
     259from sage.misc.cachefunc import cached_method
     260
     261# Abstract class to serve as a Factory no instance are created.
     262class OrderedTrees(UniqueRepresentation, Parent):
     263    """
     264    Factory for ordered trees
     265
     266    INPUT:
     267
     268    - ``size`` -- (optional) an integer
     269
     270    OUPUT:
     271
     272    - the set of all ordered trees (of the given ``size`` if specified)
     273
     274    EXAMPLES::
     275
     276        sage: OrderedTrees()
     277        Ordered trees
     278
     279        sage: OrderedTrees(2)
     280        Ordered trees of size 2
     281
     282    .. note:: this in a factory class whose constructor returns instances of
     283              subclasses.
     284
     285    .. note:: the fact that OrderedTrees is a class instead a simple callable
     286              is an implementation detail. It could be changed in the future
     287              and one should not rely on it.
     288    """
     289    @staticmethod
     290    def __classcall_private__(cls, n=None):
     291        """
     292        TESTS::
     293
     294            sage: from sage.combinat.ordered_tree import OrderedTrees_all, OrderedTrees_size
     295            sage: isinstance(OrderedTrees(2), OrderedTrees)
     296            True
     297            sage: isinstance(OrderedTrees(), OrderedTrees)
     298            True
     299            sage: OrderedTrees(2) is OrderedTrees_size(2)
     300            True
     301            sage: OrderedTrees(5).cardinality()
     302            14
     303            sage: OrderedTrees() is OrderedTrees_all()
     304            True
     305        """
     306        if n is None:
     307            return OrderedTrees_all()
     308        else:
     309            assert (isinstance(n, (Integer, int)) and n >= 0), "n must be a non negative integer"
     310            return OrderedTrees_size(Integer(n))
     311
     312    @cached_method
     313    def leaf(self):
     314        """
     315        Return a leaf tree with ``self`` as parent
     316
     317        EXAMPLES::
     318
     319            sage: OrderedTrees().leaf()
     320            []
     321
     322        TEST::
     323
     324            sage: (OrderedTrees().leaf() is
     325            ...    sage.combinat.ordered_tree.OrderedTrees_all().leaf())
     326            True
     327        """
     328        return self([])
     329
     330class OrderedTrees_all(DisjointUnionEnumeratedSets, OrderedTrees):
     331    """
     332    The set of all ordered trees
     333
     334    EXAMPLES::
     335
     336        sage: OT = OrderedTrees(); OT
     337        Ordered trees
     338        sage: OT.cardinality()
     339        +Infinity
     340    """
     341
     342    def __init__(self):
     343        """
     344        TESTS::
     345
     346            sage: from sage.combinat.ordered_tree import OrderedTrees_all
     347            sage: B = OrderedTrees_all()
     348            sage: B.cardinality()
     349            +Infinity
     350
     351            sage: it = iter(B)
     352            sage: (it.next(), it.next(), it.next(), it.next(), it.next())
     353            ([], [[]], [[], []], [[[]]], [[], [], []])
     354            sage: it.next().parent()
     355            Ordered trees
     356            sage: B([])
     357            []
     358
     359            sage: B is OrderedTrees_all()
     360            True
     361            sage: TestSuite(B).run()
     362            """
     363        DisjointUnionEnumeratedSets.__init__(
     364            self, Family(NonNegativeIntegers(), OrderedTrees_size),
     365            facade=True, keepkey=False)
     366
     367    def _repr_(self):
     368        """
     369        TEST::
     370
     371            sage: OrderedTrees()   # indirect doctest
     372            Ordered trees
     373        """
     374        return "Ordered trees"
     375
     376    def __contains__(self, x):
     377        """
     378        TESTS::
     379
     380            sage: T = OrderedTrees()
     381            sage: 1 in T
     382            False
     383            sage: T([]) in T
     384            True
     385        """
     386        return isinstance(x, self.element_class)
     387
     388    def unlabelled_trees(self):
     389        """
     390        Returns the set of unlabelled trees associated to ``self``
     391
     392        EXAMPLES::
     393
     394            sage: OrderedTrees().unlabelled_trees()
     395            Ordered trees
     396        """
     397        return self
     398
     399    def labelled_trees(self):
     400        """
     401        Returns the set of unlabelled trees associated to ``self``
     402
     403        EXAMPLES::
     404
     405            sage: OrderedTrees().labelled_trees()
     406            Labelled ordered trees
     407        """
     408        return LabelledOrderedTrees()
     409
     410    def _element_constructor_(self, *args, **keywords):
     411        """
     412        EXAMPLES::
     413
     414            sage: T = OrderedTrees()
     415            sage: T([])     # indirect doctest
     416            []
     417        """
     418        return self.element_class(self, *args, **keywords)
     419
     420    Element = OrderedTree
     421
     422
     423
     424from sage.misc.lazy_attribute import lazy_attribute
     425from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
     426from combinat import catalan_number
     427from sage.combinat.composition import Compositions
     428from sage.combinat.cartesian_product import CartesianProduct
     429#################################################################
     430# Enumerated set of binary trees of a given size
     431#################################################################
     432class OrderedTrees_size(OrderedTrees):
     433    """
     434    The enumerated sets of binary trees of a given size
     435
     436    EXAMPLES::
     437
     438        sage: S = OrderedTrees(3); S
     439        Ordered trees of size 3
     440        sage: S.cardinality()
     441        2
     442        sage: S.list()
     443        [[[], []], [[[]]]]
     444    """
     445    def __init__(self, size):
     446        """
     447        TESTS::
     448
     449            sage: from sage.combinat.ordered_tree import OrderedTrees_size
     450            sage: TestSuite(OrderedTrees_size(0)).run()
     451            sage: for i in range(6): TestSuite(OrderedTrees_size(i)).run()
     452        """
     453        super(OrderedTrees_size, self).__init__(category = FiniteEnumeratedSets())
     454        self._size = size
     455
     456    def _repr_(self):
     457        """
     458        TESTS::
     459
     460            sage: OrderedTrees(3)   # indirect doctest
     461            Ordered trees of size 3
     462        """
     463        return "Ordered trees of size %s"%(self._size)
     464
     465    def __contains__(self, x):
     466        """
     467        TESTS::
     468
     469            sage: T = OrderedTrees(3)
     470            sage: 1 in T
     471            False
     472            sage: T([[],[]]) in T
     473            True
     474        """
     475        return isinstance(x, self.element_class) and x.node_number() == self._size
     476
     477    def _an_element_(self):
     478        """
     479        TESTS::
     480
     481            sage: OrderedTrees(3).an_element()   # indirect doctest
     482            [[], []]
     483        """
     484        if self._size == 0:
     485            raise EmptySetError
     486        return self.first()
     487
     488    def cardinality(self):
     489        """
     490        The cardinality of ``self``
     491
     492        This is a Catalan number
     493
     494        TESTS::
     495
     496            sage: OrderedTrees(0).cardinality()
     497            0
     498            sage: OrderedTrees(1).cardinality()
     499            1
     500            sage: OrderedTrees(6).cardinality()
     501            42
     502        """
     503        if self._size == 0:
     504            return Integer(0)
     505        else:
     506            return catalan_number(self._size-1)
     507
     508    def __iter__(self):
     509        """
     510        A basic generator
     511
     512        .. todo:: could be optimized.
     513
     514        TESTS::
     515
     516            sage: OrderedTrees(0).list()
     517            []
     518            sage: OrderedTrees(1).list()
     519            [[]]
     520            sage: OrderedTrees(2).list()
     521            [[[]]]
     522            sage: OrderedTrees(3).list()
     523            [[[], []], [[[]]]]
     524            sage: OrderedTrees(4).list()
     525            [[[], [], []], [[], [[]]], [[[]], []], [[[], []]], [[[[]]]]]
     526        """
     527        if self._size == 0:
     528            return
     529        else:
     530            for c in Compositions(self._size-1):
     531                for lst in CartesianProduct(*(map(self.__class__, c))):
     532                    yield self._element_constructor_(lst)
     533
     534    @lazy_attribute
     535    def _parent_for(self):
     536        """
     537        Return the parent of the element generated by ``self``
     538
     539        TESTS::
     540
     541            sage: OrderedTrees(3)._parent_for
     542            Ordered trees
     543        """
     544        return OrderedTrees_all()
     545
     546    @lazy_attribute
     547    def element_class(self):
     548        """
     549        The class of the element of ``self``
     550
     551        EXAMPLES::
     552
     553            sage: from sage.combinat.ordered_tree import OrderedTrees_size, OrderedTrees_all
     554            sage: S = OrderedTrees_size(3)
     555            sage: S.element_class is OrderedTrees().element_class
     556            True
     557            sage: S.first().__class__ == OrderedTrees_all().first().__class__
     558            True
     559        """
     560        return self._parent_for.element_class
     561
     562    def _element_constructor_(self, *args, **keywords):
     563        """
     564        EXAMPLES::
     565
     566            sage: S = OrderedTrees(0)
     567            sage: S([])   # indirect doctest
     568            Traceback (most recent call last):
     569            ...
     570            ValueError: Wrong number of nodes
     571
     572            sage: S = OrderedTrees(1)   # indirect doctest
     573            sage: S([])
     574            []
     575        """
     576        res = self.element_class(self._parent_for, *args, **keywords)
     577        if res.node_number() != self._size:
     578            raise ValueError, "Wrong number of nodes"
     579        return res
     580
     581
     582class LabelledOrderedTree(AbstractLabelledClonableTree, OrderedTree):
     583    """
     584    Labelled ordered trees
     585
     586    A labellel ordered tree is an ordered tree with a label attached at each
     587    node
     588
     589    INPUT:
     590
     591    - ``children`` -- a list or tuple or more generally any iterable
     592                      of trees or object convertible to trees
     593    - ``label`` -- any Sage object default to ``None``
     594
     595    EXAMPLES::
     596
     597        sage: x = LabelledOrderedTree([], label = 3); x
     598        3[]
     599        sage: LabelledOrderedTree([x, x, x], label = 2)
     600        2[3[], 3[], 3[]]
     601        sage: LabelledOrderedTree((x, x, x), label = 2)
     602        2[3[], 3[], 3[]]
     603        sage: LabelledOrderedTree([[],[[], []]], label = 3)
     604        3[None[], None[None[], None[]]]
     605    """
     606    __metaclass__ = ClasscallMetaclass
     607
     608    @staticmethod
     609    def __classcall_private__(cls, *args, **opts):
     610        """
     611        Ensure that trees created by the sets and directly are the same and
     612        that they are instance of :class:`LabelledOrderedTree`
     613
     614        TESTS::
     615
     616            sage: issubclass(LabelledOrderedTrees().element_class, LabelledOrderedTree)
     617            True
     618            sage: t0 = LabelledOrderedTree([[],[[], []]], label = 3)
     619            sage: t0.parent()
     620            Labelled ordered trees
     621            sage: type(t0)
     622            <class 'sage.combinat.ordered_tree.LabelledOrderedTrees_with_category.element_class'>
     623        """
     624        return cls._auto_parent.element_class(cls._auto_parent, *args, **opts)
     625
     626    @lazy_class_attribute
     627    def _auto_parent(cls):
     628        """
     629        The automatic parent of the element of this class
     630
     631        When calling the constructor of an element of this class, one need a
     632        parent. This class attribute specifies which parent is used.
     633
     634        EXAMPLES::
     635
     636            sage: LabelledOrderedTree._auto_parent
     637            Labelled ordered trees
     638            sage: LabelledOrderedTree([], label = 3).parent()
     639            Labelled ordered trees
     640         """
     641        return LabelledOrderedTrees()
     642
     643    _UnLabelled = OrderedTree
     644
     645
     646from sage.rings.infinity import Infinity
     647class LabelledOrderedTrees(UniqueRepresentation, Parent):
     648    """
     649    This is a parent stub to serve as a factory class for trees with various
     650    labels constraints
     651
     652    EXAMPLES::
     653
     654        sage: LOT = LabelledOrderedTrees(); LOT
     655        Labelled ordered trees
     656        sage: x = LOT([], label = 3); x
     657        3[]
     658        sage: x.parent() is LOT
     659        True
     660        sage: y = LOT([x, x, x], label = 2); y
     661        2[3[], 3[], 3[]]
     662        sage: y.parent() is LOT
     663        True
     664    """
     665    def __init__(self, category=None):
     666        """
     667        TESTS::
     668
     669            sage: TestSuite(LabelledOrderedTrees()).run()
     670        """
     671        if category is None:
     672            category = Sets()
     673        Parent.__init__(self, category = category)
     674
     675    def _repr_(self):
     676        """
     677        TESTS::
     678
     679            sage: LabelledOrderedTrees()   # indirect doctest
     680            Labelled ordered trees
     681        """
     682        return "Labelled ordered trees"
     683
     684    def cardinality(self):
     685        """
     686        Returns the cardinality of `self`
     687
     688        EXAMPLE::
     689
     690            sage: LabelledOrderedTrees().cardinality()
     691            +Infinity
     692        """
     693        return Infinity
     694
     695    def _an_element_(self):
     696        """
     697        Returns a labelled tree
     698
     699        EXAMPLE::
     700
     701            sage: LabelledOrderedTrees().an_element()   # indirect doctest
     702            toto[3[], 42[3[], 3[]], 5[None[]]]
     703        """
     704        LT = self._element_constructor_
     705        t  = LT([], label = 3)
     706        t1 = LT([t,t], label = 42)
     707        t2  = LT([[]], label = 5)
     708        return LT([t,t1,t2], label = "toto")
     709
     710    def _element_constructor_(self, *args, **keywords):
     711        """
     712        EXAMPLES::
     713
     714            sage: T = LabelledOrderedTrees()
     715            sage: T([], label=2)     # indirect doctest
     716            2[]
     717        """
     718        return self.element_class(self, *args, **keywords)
     719
     720    def unlabelled_trees(self):
     721        """
     722        Returns the set of unlabelled trees associated to ``self``
     723
     724        EXAMPLES::
     725
     726            sage: LabelledOrderedTrees().unlabelled_trees()
     727            Ordered trees
     728        """
     729        return OrderedTrees_all()
     730
     731    def labelled_trees(self):
     732        """
     733        Returns the set of labelled trees associated to ``self``
     734
     735        EXAMPLES::
     736
     737            sage: LabelledOrderedTrees().labelled_trees()
     738            Labelled ordered trees
     739            sage: LOT = LabelledOrderedTrees()
     740            sage: x = LOT([], label = 3)
     741            sage: y = LOT([x, x, x], label = 2)
     742            sage: y.canonical_labelling()
     743            1[2[], 3[], 4[]]
     744        """
     745        return self
     746
     747    Element = LabelledOrderedTree
     748
  • sage/combinat/permutation.py

    diff --git a/sage/combinat/permutation.py b/sage/combinat/permutation.py
    a b class Permutation_class(CombinatorialObj 
    30063006        S=PerfectMatchings(n)([(2*i+1,2*i+2) for i in range(n//2)])
    30073007        return S.loop_type(S.conjugate_by_permutation(self))
    30083008
     3009    def increasing_tree(self, compare=min):
     3010        """
     3011        Return the increasing tree associated to ``self``
     3012
     3013        EXAMPLES::
     3014
     3015            sage: Permutation([1,4,3,2]).increasing_tree()
     3016            1[., 2[3[4[., .], .], .]]
     3017            sage: Permutation([4,1,3,2]).increasing_tree()
     3018            1[4[., .], 2[3[., .], .]]
     3019
     3020        By passing the option ``compare=max`` one can have the decreasing
     3021        tree instead::
     3022
     3023            sage: Permutation([2,3,4,1]).increasing_tree(max)
     3024            4[3[2[., .], .], 1[., .]]
     3025            sage: Permutation([2,3,1,4]).increasing_tree(max)
     3026            4[3[2[., .], 1[., .]], .]
     3027        """
     3028        from sage.combinat.binary_tree import LabelledBinaryTree as LBT
     3029        def rec(perm):
     3030            if len(perm) == 0: return LBT(None)
     3031            mn = compare(perm)
     3032            k = perm.index(mn)
     3033            return LBT([rec(perm[:k]), rec(perm[k+1:])], label = mn)
     3034        return rec(self)
     3035
     3036    def binary_search_tree(self, left_to_right=True):
     3037        """
     3038        Return the binary search tree associated to ``self``
     3039
     3040        EXAMPLES::
     3041
     3042            sage: Permutation([1,4,3,2]).binary_search_tree()
     3043            1[., 4[3[2[., .], .], .]]
     3044            sage: Permutation([4,1,3,2]).binary_search_tree()
     3045            4[1[., 3[2[., .], .]], .]
     3046
     3047        By passing the option ``compare=max`` one can have the decreasing
     3048        tree instead::
     3049
     3050            sage: Permutation([1,4,3,2]).binary_search_tree(False)
     3051            2[1[., .], 3[., 4[., .]]]
     3052            sage: Permutation([4,1,3,2]).binary_search_tree(False)
     3053            2[1[., .], 3[., 4[., .]]]
     3054
     3055        TESTS::
     3056
     3057            sage: Permutation([]).binary_search_tree()
     3058            .
     3059        """
     3060        from sage.combinat.binary_tree import LabelledBinaryTree as LBT
     3061        res = LBT(None)
     3062        if left_to_right:
     3063            gen = self
     3064        else:
     3065            gen = self[::-1]
     3066        for i in gen:
     3067            res = res.binary_search_insert(i)
     3068        return res
     3069
    30093070################################################################
    30103071
    30113072def Arrangements(mset, k):
  • sage/misc/all.py

    diff --git a/sage/misc/all.py b/sage/misc/all.py
    a b from lazy_import import lazy_import 
    160160
    161161from abstract_method import abstract_method
    162162
    163 from binary_tree import BinaryTree
    164 
    165163from randstate import seed, set_random_seed, initial_seed, current_randstate
    166164
    167165from 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