# HG changeset patch
# User darij grinberg
# Date 1362209209 28800
# Node ID b80acf19629092f84fa6e075de752561a342651d
# Parent f170c8e4be2d04eff3d085b3aa6865d511b73332
trac #8703 minor details (review patch by dg)
diff git a/sage/combinat/abstract_tree.py b/sage/combinat/abstract_tree.py
 a/sage/combinat/abstract_tree.py
+++ b/sage/combinat/abstract_tree.py
@@ 247,7 +247,7 @@ class AbstractTree(object):
The actual canonical labelling is currently unspecified. However, it
is guaranteed to have labels in `1...n` where `n` is the number of
nodes of the tree. Moreover, two (unlabelled) trees compare as equal if
 and only if they canonical labelled trees compare as equal.
+ and only if their canonical labelled trees compare as equal.
EXAMPLES::
@@ 266,11 +266,11 @@ class AbstractTree(object):
.
"""
LTR = self.parent().labelled_trees()
 liste=[]
 deca=1
+ liste = []
+ deca = 1
for subtree in self:
 liste=liste+[subtree.canonical_labelling(shift+deca)]
 deca=deca+subtree.node_number()
+ liste += [subtree.canonical_labelling(shift+deca)]
+ deca += subtree.node_number()
return LTR._element_constructor_(liste,label=shift)
def tree_factorial(self):
@@ 284,8 +284,8 @@ class AbstractTree(object):
EXAMPLES::
 sage: LT=LabelledOrderedTrees()
 sage: t=LT([LT([],label=6),LT([],label=1)],label=9)
+ sage: LT = LabelledOrderedTrees()
+ sage: t = LT([LT([],label=6),LT([],label=1)],label=9)
sage: t.tree_factorial()
3
@@ 394,7 +394,7 @@ class AbstractClonableTree(AbstractTree)
:class:`~sage.structure.list_clone.ClonableList` depending wether one
wants to build trees where adding a child is allowed.
 .. note:: Due to the limitation of Cython inheritance, one cannot inherit
+ .. NOTE:: Due to the limitation of Cython inheritance, one cannot inherit
here from :class:`~sage.structure.list_clone.ClonableElement`, because
it would prevent us to inherit later from
:class:`~sage.structure.list_clone.ClonableArray` or
@@ 511,8 +511,8 @@ class AbstractClonableTree(AbstractTree)
sage: x
[[[], [[], []]], [[[], []], [[], []]]]
"""
 assert isinstance(value, self.__class__)

+ if not isinstance(value, self.__class__):
+ raise TypeError('the given value is not a tree')
if isinstance(idx, tuple):
self.__setitem_rec__(idx, 0, value)
else:
@@ 663,11 +663,11 @@ class AbstractLabelledTree(AbstractTree)
EXAMPLES::
 sage: t=LabelledOrderedTree([[],[]], label = 3)
+ sage: t = LabelledOrderedTree([[],[]], label = 3)
sage: t.label()
3
sage: t[0].label()
 sage: t=LabelledOrderedTree([LabelledOrderedTree([], 5),[]], label = 3)
+ sage: t = LabelledOrderedTree([LabelledOrderedTree([], 5),[]], label = 3)
sage: t.label()
3
sage: t[0].label()
@@ 810,13 +810,19 @@ class AbstractLabelledTree(AbstractTree)
def as_digraph(self):
"""
 Returns a directed graph version of ``self``
+ Returns a directed graph version of ``self``.
+
+ .. WARNING::
+
+ At this time, the output makes sense only if ``self`` is a
+ labelled binary tree with no repeated labels and no "None"
+ labels.
EXAMPLES::
 sage: LT=LabelledOrderedTrees()
 sage: ko=LT([LT([],label=6),LT([],label=1)],label=9)
 sage: ko.as_digraph()
+ sage: LT = LabelledOrderedTrees()
+ sage: t1 = LT([LT([],label=6),LT([],label=1)],label=9)
+ sage: t1.as_digraph()
Digraph on 3 vertices
sage: t = BinaryTree([[None, None],[[],None]]);
@@ 825,12 +831,12 @@ class AbstractLabelledTree(AbstractTree)
Digraph on 4 vertices
"""
from sage.graphs.digraph import DiGraph
 resu=dict([[self.label(),
+ resu = dict([[self.label(),
[t.label() for t in self if not t.is_empty()]]])
 resu=DiGraph(resu)
+ resu = DiGraph(resu)
for t in self:
if not t.is_empty():
 resu=resu.union(t.as_digraph())
+ resu = resu.union(t.as_digraph())
return resu
@@ 841,7 +847,7 @@ class AbstractLabelledClonableTree(Abstr
This class take care of modification for the label by the clone protocol.
 .. note:: Due to the limitation of Cython inheritance, one cannot inherit
+ .. NOTE:: Due to the limitation of Cython inheritance, one cannot inherit
here from :class:`ClonableArray`, because it would prevent us to
inherit later from :class:`~sage.structure.list_clone.ClonableList`.
"""
@@ 853,7 +859,7 @@ class AbstractLabelledClonableTree(Abstr
OUPUT: ``None``, ``self`` is modified in place
 .. note::
+ .. NOTE::
``self`` must be in a mutable state. See
:mod:`sage.structure.list_clone` for more details about
@@ 861,7 +867,7 @@ class AbstractLabelledClonableTree(Abstr
EXAMPLES::
 sage: t=LabelledOrderedTree([[],[[],[]]])
+ sage: t = LabelledOrderedTree([[],[[],[]]])
sage: t.set_root_label(3)
Traceback (most recent call last):
...
@@ 875,7 +881,7 @@ class AbstractLabelledClonableTree(Abstr
This also work for binary trees::
 sage: bt=LabelledBinaryTree([[],[]])
+ sage: bt = LabelledBinaryTree([[],[]])
sage: bt.set_root_label(3)
Traceback (most recent call last):
...
@@ 914,7 +920,7 @@ class AbstractLabelledClonableTree(Abstr
OUPUT: Nothing, ``self`` is modified in place
 .. note::
+ .. NOTE::
``self`` must be in a mutable state. See
:mod:`sage.structure.list_clone` for more details about
@@ 922,7 +928,7 @@ class AbstractLabelledClonableTree(Abstr
EXAMPLES::
 sage: t=LabelledOrderedTree([[],[[],[]]])
+ sage: t = LabelledOrderedTree([[],[[],[]]])
sage: t.set_label((0,), 4)
Traceback (most recent call last):
...
@@ 936,7 +942,7 @@ class AbstractLabelledClonableTree(Abstr
sage: t
None[4[], None[42[], None[]]]
 .. todo::
+ .. TODO::
Do we want to implement the following syntactic sugar::
diff git a/sage/combinat/binary_tree.py b/sage/combinat/binary_tree.py
 a/sage/combinat/binary_tree.py
+++ b/sage/combinat/binary_tree.py
@@ 2,93 +2,12 @@
Binary trees
This module deals with binary trees as mathematical (in particular immmutable)
objects.
+objects.
.. note :: If you need the datastructure for example to represent sets or hash
+.. NOTE :: If you need the datastructure for example to represent sets or hash
tables with AVL trees, you should have a look at
:mod:`sage.misc.sagex_ds`.
On the use of Factories to query a database of counting algorithms


**The problem we try to solve**

A common problem in combinatorics is to enumerate or count some standard
mathematical objects satisfying a set of constraints. For instance, one can be
interested in the :mod:`partitions ` of an integer `n`
of length `7` and parts of size at least `3` and at most `8`, [...]

For partitions, the number of different parameters available is actually quite
large :

 The length of the partition (i.e. partitions in `k` parts, or in "at least"
 `k_1` parts "at most" `k_2` parts).

 The sum of the partition (i.e. the integer `n`).

 The min/max size of a part, or even a set of integers such that the partition
 should only use integers from the given set.

 The min/max slope of the partition.

 An inner and outer profile.

 A min/max value for the lexicographical ordering of the partition.

One may in particular be interested in enumerating/counting the partitions
satisfying *some arbitrary combination* of constraints using the parameters
listed above.

This all means that there is a real need of unifying a large family of
algorithms, so that users do not have to find their way through a library
of 50 different counting/enumeration algorithms *all* dealing with partitions
with different set of parameters.

**How we solve it**

We try to build a *database* of algorithms that the user can query easily in
order to use the best implementation for his needs.

Namely, in the case of :mod:`partitions `, we want to
define a class factory named ``Partitions`` and accepting any combination of
constraints as an input. The role of the ``Partitions`` class factory is in this
situation to identify the counting/enumeration algorithm corresponding to this
set of constraint, and to return a handmade object with the best set of
methods.

**The design**

For each combination of constraints that has specific enumeration/counting
algorithms in Sage, we want to create a corresponding class. The result will be
 if we stick with the example of partitions  a brand new Zoo with weird things
inside :

 ``PartitionsWithFixedSlopeAndOuterProfile(slope, outer_profile)`` 
 representing the partitions with slope ``slope`` and outer profile
 ``outer_profile``

 ``PartitionsWithRestrictedPartsAndBoundedLength(part_set, length)`` 
 represeting the partitions with a set of allowed parts and given length.

 ...

Each of these classes should define methods like ``__iter__`` (so that we can
iterate on its elements) or ``cardinality``.

The main class ``Partitions`` will then take as arguments *all of the*
*combinations of parameters the user may like*, and query the database for the
best secialized class implemented. The user then receives an instance of this
specialized class that he can use with the best algorithms implemented.

Of course, it may happen that there is actually no algorithm able to enumerate
partitions with the set of constraints specified. In this case, the best way is
to build a class enumerating a larger set of partitions, and to check for each
of them whether is also satisfies the more restrictive set of constraints. This
is costly, but it is the best way available, and the library should also be able
to answer the question *"what is the best implementation available to list the
partitions asked by the user ?"*. We then need to make sure we enumerate as few
unnecessary elements as possible.

**AUTHORS:**
 Florent Hivert (20102011): initial implementation.
@@ 101,7 +20,7 @@ unnecessary elements as possible.
# the License, or (at your option) any later version.
# http://www.gnu.org/licenses/
#*****************************************************************************
from sage.structure.list_clone import ClonableArray, ClonableList
+from sage.structure.list_clone import ClonableArray
from sage.combinat.abstract_tree import (AbstractClonableTree,
AbstractLabelledClonableTree)
from sage.combinat.ordered_tree import LabelledOrderedTrees
@@ 113,24 +32,31 @@ class BinaryTree(AbstractClonableTree, C
"""
The class of binary trees
+ Binary trees here mean ordered (a.k.a. plane) binary trees,
+ meaning that the children of each node are ordered.
+
INPUT:
 ``children``  ``None`` (default) or a list, tuple or iterable of
 length 2 of binary trees or convertible objects. Alternatively a string
 is also accepted. The syntax is the same as for printing: empty trees
 are denoted by `.` and children are grouped by square brackets.
+ length 2 of binary trees or convertible objects. This corresponds to
+ the standard recursive definition of a binary tree as either a leaf
+ or a pair of binary trees. Syntactic sugar allows leaving out all
+ but the outermost calls of the ``BinaryTree()`` constructor, so that,
+ e. g., ``BinaryTree([BinaryTree(None),BinaryTree(None)])`` can be
+ simplified to ``BinaryTree([None,None])``. It is also allowed to
+ abbreviate ``[None, None]`` by ``[]``.
 ``check``  (default to ``True``) whether check for binary should be
performed or not.
 .. warning:: despite what the HTML documentation may say, ``BinaryTree``
 does not have any ``parent`` argument, as the examples below
 show.

EXAMPLES::
sage: BinaryTree()
.
+ sage: BinaryTree(None)
+ .
+ sage: BinaryTree([])
+ [., .]
sage: BinaryTree([None, None])
[., .]
sage: BinaryTree([None, []])
@@ 143,7 +69,7 @@ class BinaryTree(AbstractClonableTree, C
sage: BinaryTree([[], None, []])
Traceback (most recent call last):
...
 AssertionError: This is not a binary tree
+ ValueError: this is not a binary tree
TESTS::
@@ 204,7 +130,7 @@ class BinaryTree(AbstractClonableTree, C
"""
return BinaryTrees_all()
 def __init__(self, parent, children = None, check=True):
+ def __init__(self, parent, children = None, check = True):
"""
TESTS::
@@ 215,17 +141,18 @@ class BinaryTree(AbstractClonableTree, C
sage: BinaryTree("[.,.,.]")
Traceback (most recent call last):
...
 AssertionError: This is not a binary tree
+ ValueError: this is not a binary tree
sage: all(BinaryTree(repr(bt)) == bt for i in range(6) for bt in BinaryTrees(i))
True
"""
 if(type(children) is str):
+ if (type(children) is str): # if the input is the repr of a binary tree
children = children.replace(".","None")
 import ast
 children = ast.literal_eval(children)
+ from ast import literal_eval
+ children = literal_eval(children)
if children is None:
children = []
 elif children == [] or isinstance(children, (Integer, int)):
+ elif (children == [] or children == ()
+ or isinstance(children, (Integer, int))):
children = [None, None]
if (children.__class__ is self.__class__ and
children.parent() == parent):
@@ 245,13 +172,14 @@ class BinaryTree(AbstractClonableTree, C
sage: BinaryTree([[], [], []]) # indirect doctest
Traceback (most recent call last):
...
 AssertionError: This is not a binary tree
+ ValueError: this is not a binary tree
sage: BinaryTree([[]]) # indirect doctest
Traceback (most recent call last):
...
 AssertionError: This is not a binary tree
+ ValueError: this is not a binary tree
"""
 assert (not self or len(self) == 2), "This is not a binary tree"
+ if not (not self or len(self) == 2):
+ raise ValueError("this is not a binary tree")
def _repr_(self):
"""
@@ 355,9 +283,9 @@ class BinaryTree(AbstractClonableTree, C
 ``child_list``  a pair of binary trees (or objects convertible to)
 .. note:: ``self`` must be in a mutable state.
+ .. NOTE:: ``self`` must be in a mutable state.
 .. seealso::
+ .. SEEALSO::
:meth:`make_leaf `
EXAMPLES::
@@ 374,7 +302,8 @@ class BinaryTree(AbstractClonableTree, C
sage: with t.clone() as t:
... t.make_node([BinaryTree(), BinaryTree(), BinaryTree([])])
Traceback (most recent call last):
 AssertionError: the list must have length 2
+ ...
+ ValueError: the list must have length 2
sage: with t1.clone() as t2:
... t2.make_node([t1, t1])
sage: with t2.clone() as t3:
@@ 384,14 +313,15 @@ class BinaryTree(AbstractClonableTree, C
"""
self._require_mutable()
child_lst = [self.__class__(self.parent(), x) for x in child_list]
 assert(len(child_lst) == 2), "the list must have length 2"
+ if not(len(child_lst) == 2):
+ raise ValueError("the list must have length 2")
self.__init__(self.parent(), child_lst, check=False)
def make_leaf(self):
"""
Modify ``self`` so that it became a leaf
 .. note:: ``self`` must be in a mutable state.
+ .. NOTE:: ``self`` must be in a mutable state.
.. seealso::
:meth:`make_node `
@@ 437,7 +367,7 @@ class BinaryTree(AbstractClonableTree, C
 a leaf is associated to the empty Dyck Word
 a tree with chidren `l,r` is associated to the Dyck word
 `1 T(l) 0 T(r)` where `T(l)` and `T(r)` are the trees
+ `1 T(l) 0 T(r)` where `T(l)` and `T(r)` are the Dyck words
associated to `l` and `r`.
EXAMPLES::
@@ 459,7 +389,7 @@ class BinaryTree(AbstractClonableTree, C
The *canopee* of a non empty binary tree `T` with `n` internal nodes is
the list `l` of `0` and `1` of length `n1` obtained by going along the
leaves of `T` from left to right except the two extremal ones, writing
 `0` if the leaf is a right leaf and `1` is a left leaf.
+ `0` if the leaf is a right leaf and `1` if the leaf is a left leaf.
EXAMPLES::
@@ 510,7 +440,7 @@ class BinaryTree(AbstractClonableTree, C
Formal Power Series and Algebraic Combinatorics, 1994.
"""
if not self:
 raise ValueError, "canopee is only defined for non empty binary trees"
+ raise ValueError("canopee is only defined for non empty binary trees")
res = []
def add_leaf_rec(tr):
for i in range(2):
@@ 553,10 +483,10 @@ class BinaryTrees(UniqueRepresentation,
sage: BinaryTrees(2)
Binary trees of size 2
 .. note:: this in a factory class whose constructor returns instances of
+ .. NOTE:: this in a factory class whose constructor returns instances of
subclasses.
 .. note:: the fact that OrderedTrees is a class instead a simple callable
+ .. NOTE:: the fact that OrderedTrees is a class instead a simple callable
is an implementation detail. It could be changed in the future
and one should not rely on it.
"""
@@ 580,7 +510,8 @@ class BinaryTrees(UniqueRepresentation,
if n is None:
return BinaryTrees_all()
else:
 assert (isinstance(n, (Integer, int)) and n >= 0), "n must be a non negative integer"
+ if not (isinstance(n, (Integer, int)) and n >= 0):
+ raise ValueError("n must be a non negative integer")
return BinaryTrees_size(Integer(n))
@cached_method
@@ 702,7 +633,6 @@ class BinaryTrees_all(DisjointUnionEnume
Element = BinaryTree
from sage.misc.lazy_attribute import lazy_attribute
from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
from combinat import catalan_number
#################################################################
@@ 780,7 +710,7 @@ class BinaryTrees_size(BinaryTrees):
"""
A basic generator.
 .. todo:: could be optimized.
+ .. TODO:: could be optimized.
TESTS::
@@ 833,7 +763,7 @@ class BinaryTrees_size(BinaryTrees):
sage: S([]) # indirect doctest
Traceback (most recent call last):
...
 ValueError: Wrong number of nodes
+ ValueError: wrong number of nodes
sage: S(None) # indirect doctest
.
@@ 843,7 +773,7 @@ class BinaryTrees_size(BinaryTrees):
"""
res = self.element_class(self._parent_for, *args, **keywords)
if res.node_number() != self._size:
 raise ValueError, "Wrong number of nodes"
+ raise ValueError("wrong number of nodes")
return res
@@ 921,7 +851,7 @@ class LabelledBinaryTree(AbstractLabelle
 ``letter``  any object comparable with the label of ``self``
 .. note:: ``self`` is supposed to be a binary search tree. No check is
+ .. NOTE:: ``self`` is supposed to be a binary search tree. No check is
performed.
EXAMPLES::
diff git a/sage/combinat/ordered_tree.py b/sage/combinat/ordered_tree.py
 a/sage/combinat/ordered_tree.py
+++ b/sage/combinat/ordered_tree.py
@@ 26,9 +26,9 @@ class OrderedTree(AbstractClonableTree,
"""
The class for (ordered rooted) Trees
 An ordered tree is a constructed from a node called the root on which one
+ An ordered tree is constructed from a node called the root on which one
has grafted a possibly empty list of trees. There is a total order on the
 children of a node which is given by the the order of the element in the
+ children of a node which is given by the order of the element in the
list. Note that there is no empty ordered tree.
INPUT:
@@ 209,7 +209,7 @@ class OrderedTree(AbstractClonableTree,
sage: OrderedTree([[],[[]]]).parent()
Ordered trees
 .. note::
+ .. NOTE::
It is possible to bypass the automatic parent mechanism using:
@@ 248,7 +248,7 @@ class OrderedTree(AbstractClonableTree,
For ordered trees, returns always ``False``
 .. note:: this is different from ``bool(t)`` which returns whether
+ .. NOTE:: this is different from ``bool(t)`` which returns whether
``t`` has some child or not.
EXAMPLES::
@@ 289,10 +289,10 @@ class OrderedTrees(UniqueRepresentation,
sage: OrderedTrees(2)
Ordered trees of size 2
 .. note:: this in a factory class whose constructor returns instances of
+ .. NOTE:: this in a factory class whose constructor returns instances of
subclasses.
 .. note:: the fact that OrderedTrees is a class instead a simple callable
+ .. NOTE:: the fact that OrderedTrees is a class instead a simple callable
is an implementation detail. It could be changed in the future
and one should not rely on it.
"""
@@ 316,7 +316,8 @@ class OrderedTrees(UniqueRepresentation,
if n is None:
return OrderedTrees_all()
else:
 assert (isinstance(n, (Integer, int)) and n >= 0), "n must be a non negative integer"
+ if not (isinstance(n, (Integer, int)) and n >= 0):
+ raise ValueError("n must be a non negative integer")
return OrderedTrees_size(Integer(n))
@cached_method
@@ 519,7 +520,7 @@ class OrderedTrees_size(OrderedTrees):
"""
A basic generator
 .. todo:: could be optimized.
+ .. TODO:: could be optimized.
TESTS::
@@ 593,7 +594,7 @@ class LabelledOrderedTree(AbstractLabell
"""
Labelled ordered trees
 A labellel ordered tree is an ordered tree with a label attached at each
+ A labelled ordered tree is an ordered tree with a label attached at each
node
INPUT:
@@ 755,4 +756,3 @@ class LabelledOrderedTrees(UniqueReprese
return self
Element = LabelledOrderedTree
