Ticket #8288: search_forest_depth_and_breath_improvement-nb.patch

File search_forest_depth_and_breath_improvement-nb.patch, 24.0 KB (added by nborie, 11 years ago)

One more time, my english is still bad... Feel free to point them and thus, make my english increasing....

  • sage/combinat/backtrack.py

    # HG changeset patch
    # User Nicolas Borie <nicolas.borie at math.u-psud.fr>
    # Date 1267809751 -3600
    # Node ID 5ac9cd855353b5540a976650e373b5d973c41580
    # Parent  d890cebb543a499d2d131a3ecdf944ee051f602e
    #8288: SearchForest improvements
    
    diff -r d890cebb543a -r 5ac9cd855353 sage/combinat/backtrack.py
    a b  
    55elements can be enumerated by exploring a search space with a (lazy)
    66tree or graph structure.
    77
    8 - :class:`~sage.combinat.backtrack.SearchForest`: Depth first search through a
    9   tree described by a ``children`` function.
     8- :class:`~sage.combinat.backtrack.SearchForest`: Depth and Breath first
     9  search through a tree described by a ``children`` function.
    1010- :class:`~sage.combinat.backtrack.GenericBacktracker`: Depth first search
    1111  through a tree described by a ``children`` function, with branch pruning,
    1212  etc.
     
    2929#*****************************************************************************
    3030#       Copyright (C) 2008 Mike Hansen <mhansen@gmail.com>,
    3131#                     2009 Nicolas M. Thiery <nthiery at users.sf.net>
     32#                     2010 Nicolas Borie <nicolas.borie at math.u-psud.fr>
    3233#
    3334#  Distributed under the terms of the GNU General Public License (GPL)
    3435#
     
    100101                stack.append( self._rec(obj, state) )
    101102
    102103
    103 def search_forest_iterator(roots, children):
     104def search_forest_iterator(roots, children, method="depth"):
    104105    r"""
    105106    Returns an iterator on the nodes of the forest having the given
    106107    roots, and where ``children(x)`` returns the children of the node ``x``
     
    111112
    112113    - ``roots``: a list (or iterable)
    113114    - ``children``: a function returning a list (or iterable)
    114        
     115    - ``method``: ``"depth"`` or ``"breadth"``
     116
    115117    EXAMPLES:
    116    
     118
    117119    Search tree where leaves are binary sequences of length 3::
    118120
    119121        sage: from sage.combinat.backtrack import search_forest_iterator
     
    125127        sage: from sage.combinat.backtrack import search_forest_iterator
    126128        sage: list(search_forest_iterator([[]], lambda l: [l + [i] for i in range(4) if i not in l] if len(l) < 2 else []))
    127129        [[], [0], [0, 1], [0, 2], [0, 3], [1], [1, 0], [1, 2], [1, 3], [2], [2, 0], [2, 1], [2, 3], [3], [3, 0], [3, 1], [3, 2]]
     130
     131    We show how to set the enumeration method::
     132
     133        sage: from sage.combinat.backtrack import search_forest_iterator
     134        sage: list(search_forest_iterator([[]], lambda l: [l+[0], l+[1]] if len(l) < 3 else [], method="breadth"))
     135        [[], [0], [1], [0, 0], [0, 1], [1, 0], [1, 1], [0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]]
    128136    """
    129    
     137    #Set the position according the method depth/breadth   
     138    if method == "depth":
     139        position = -1
     140    else:
     141        position = 0
     142
    130143    #Invariant: stack[i] contains an iterator for the siblings of the i-th node of the current branch
    131144    stack = [iter(roots)]
    132145    while len(stack) > 0:
    133146        # Try to get the next node at this depth
    134147        try:
    135             node = stack[-1].next()
     148            node = stack[position].next()
    136149        except StopIteration:
    137150            #If there are no more, go back up the tree
    138151            # We also need to check if we've exhausted all
    139152            # possibilities
    140             stack.pop()
     153            stack.pop(position)
    141154            continue
    142155
    143156        yield node
    144157        stack.append( iter(children(node)) )
    145158
     159# We define a pickable function for the TestSuite of SearchForest
     160def pick_children(x):
     161    r"""
     162    pick_children is example of pickable function of children.
     163    A SearchForest instance is pickable if and only if it is
     164    defined with pickable functions.
     165
     166    EXAMPLES::
     167   
     168        sage: from sage.combinat.backtrack import pick_children
     169        sage: unpickable_children = lambda x: [x+1]
     170        sage: pick_children(1)
     171        [2]
     172        sage: pick_children(2)
     173        [3]
     174        sage: pick_children(3)
     175        [4]
     176        sage: for i in range(20):
     177        ...       assert pick_children(i) == unpickable_children(i)
     178    """
     179    return [x+1]
     180
     181
    146182from sage.combinat.combinat import CombinatorialClass
    147183class SearchForest(CombinatorialClass):
    148184    r"""
     
    157193
    158194    - ``roots``: a list (or iterable)
    159195    - ``children``: a function returning a list (or iterable)
    160    
     196    - ``father``: a function returning an element of ``self`` (optional)
     197    - ``next_brother``: a function returning an element of ``self`` (optional)
     198
    161199    EXAMPLES:
    162200
    163201    A generator object for binary sequences of length 3, listed::
    164202
    165         sage: list(SearchForest([[]], lambda l: [l+[0], l+[1]] if len(l) < 3 else []))
     203        sage: list(SearchForest( [[]],
     204        ...                      lambda l: [l+[0], l+[1]] if len(l) < 3 else []))
    166205        [[], [0], [0, 0], [0, 0, 0], [0, 0, 1], [0, 1], [0, 1, 0], [0, 1, 1], [1], [1, 0], [1, 0, 0], [1, 0, 1], [1, 1], [1, 1, 0], [1, 1, 1]]
    167206
    168207    A generator object for ordered sequences of length 2 from a 4-set, sampled::
    169208
    170         sage: tb = SearchForest([[]], lambda l: [l + [i] for i in range(4) if i not in l] if len(l) < 2 else [])
     209        sage: tb = SearchForest( [[]],
     210        ...            lambda l: [l + [i] for i in range(4) if i not in l]
     211        ...                      if len(l) < 2 else [] )
    171212        sage: tb[0]
    172213        []
    173214        sage: tb[16]
    174215        [3, 2]
     216
     217    By default, element are enumerated in a depth first search way. It is
     218    possible to get a breadth first search iterator via the
     219    ``breadth_first_search_iterator`` method::
     220
     221        sage: I = SearchForest([(0,0)],
     222        ...                    lambda l: [(l[0]+1, l[1]), (l[0], 1)]
     223        ...                              if l[1] == 0 else [(l[0], l[1]+1)])
     224        sage: depth_search = I.depth_first_search_iterator()
     225        sage: [depth_search.next() for i in range(15)]
     226        [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (6, 0), (7, 0), (8, 0), (9, 0), (10, 0), (11, 0), (12, 0), (13, 0), (14, 0)]
     227        sage: breadth_search = I.breadth_first_search_iterator()
     228        sage: [breadth_search.next() for i in range(15)]
     229        [(0, 0), (1, 0), (0, 1), (2, 0), (1, 1), (0, 2), (3, 0), (2, 1), (1, 2), (0, 3), (4, 0), (3, 1), (2, 2), (1, 3), (0, 4)]
     230
     231    Warning: A SearchForest instance is pickable if and only if it is
     232    defined with pickable functions. If you want pickable object, don't
     233    defined your argument function on the fly.
     234
     235        sage: from sage.combinat.backtrack import pick_children
     236        sage: I = SearchForest((1,), pick_children)
     237        sage: TestSuite(I).run()
     238        sage: I = SearchForest((1,), lambda x: [x+1])
     239        sage: TestSuite(I).run()
     240        Failure in _test_pickling:
     241        Traceback ...
     242        ...
     243        PicklingError: Can't pickle <type 'function'>: ...
     244        ------------------------------------------------------------
     245        The following tests failed: _test_pickling
     246
     247    TESTS::
     248   
     249        sage: # The following test an empty set defined with no roots...
     250        sage: father = lambda l : l[:-1]
     251        sage: I = SearchForest([], lambda l: (l+[i] for i in range(l[-1])), father = father)
     252        sage: I.first()
     253        sage: list(I)
     254        []
     255        sage: I.first_element_of_depth(0)
     256        sage: I.first_element_of_depth(1)
     257        sage: I.first_element_of_depth(2)
     258        sage: list(I.element_of_depth_iterator(0))
     259        []
     260        sage: list(I.element_of_depth_iterator(1))
     261        []
     262        sage: list(I.element_of_depth_iterator(2))
     263        []
    175264    """
    176     def __init__(self, roots, children):
     265    def __init__(self, roots, children, father=None, next_brother=None):
    177266        r"""
    178267        TESTS::
    179268
    180             sage: C = SearchForest((1,), lambda x: [x+1])
     269            sage: from sage.combinat.backtrack import pick_children
     270            sage: C = SearchForest((1,), pick_children)
    181271            sage: C._roots
    182272            (1,)
    183273            sage: C._children
    184             <function <lambda> at ...>
     274            <function pick_children at ...>
    185275
     276       Tests that pickling is supported if the pickling of children is::
     277
     278           sage: def succ(l):
     279           ...        return [l+[0], l+[1]]
     280           sage: import __main__
     281           sage: __main__.succ = succ # just because succ has been defined interactively
     282           sage: C = SearchForest(([],), succ)
     283           sage: TestSuite(C).run()
    186284        """
    187285        self._roots = roots
    188286        self._children = children
     287        self._father = father
     288        self._next_brother = next_brother
    189289
    190290    def _repr_(self):
    191291        r"""
     
    196296        """
    197297        return "An enumerated set"
    198298
     299    def roots(self):
     300        r"""
     301        Returns an iterable over the roots of ``self``.
     302
     303        EXAMPLES::
     304
     305            sage: I = SearchForest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)])
     306            sage: [i for i in I.roots()]
     307            [(0, 0)]
     308            sage: I = SearchForest([(0,0),(1,1)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)])
     309            sage: [i for i in I.roots()]
     310            [(0, 0), (1, 1)]
     311        """
     312        return iter(self._roots)
     313
     314    def children(self, x):
     315        r"""
     316        Returns an iterable over the children of the element ``x``.
     317
     318        EXAMPLES::
     319
     320            sage: I = SearchForest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)])
     321            sage: [i for i in I.children((0,0))]
     322            [(1, 0), (0, 1)]
     323            sage: [i for i in I.children((1,0))]
     324            [(2, 0), (1, 1)]
     325            sage: [i for i in I.children((1,1))]
     326            [(1, 2)]
     327            sage: [i for i in I.children((4,1))]
     328            [(4, 2)]
     329            sage: [i for i in I.children((4,0))]
     330            [(5, 0), (4, 1)]
     331        """
     332        return iter(self._children(x))
     333
     334    def father(self, x):
     335        r"""
     336        Returns the father of the element ``x`` if a fonction ``father``
     337        was given in argument. If not raise an ``AssertionError``.
     338
     339        EXAMPLES::
     340
     341            sage: father = lambda t: (t[0]-1,0) if t[1] == 0 else (t[0],t[1]-1)
     342            sage: I = SearchForest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)], father=father)
     343            sage: I.father((2,3))
     344            (2, 2)
     345            sage: I.father(_)
     346            (2, 1)
     347            sage: I.father(_)
     348            (2, 0)
     349            sage: I.father(_)
     350            (1, 0)
     351            sage: I.father(_)
     352            (0, 0)
     353        """
     354        assert self._father != None, "No 'father' function given"
     355        return self._father(x)
     356
     357    def next_brother(self, x, father=None):
     358        r"""
     359
     360        Returns the next brother of the element ``x`` if it exist, returns
     361        ``None`` otherwise.
     362
     363        If a function ``_next_brother`` was given at the creation of ``self``,
     364        the methods ``next_brother`` simply returns its results, otherwise it
     365        returns the next children of the father of ``x``.
     366
     367        EXAMPLES::
     368
     369            sage: father = lambda t: (t[0]-1,0) if t[1] == 0 else (t[0],t[1]-1)
     370            sage: I = SearchForest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)], father=father)
     371            sage: I.next_brother((1,0))
     372            (0, 1)
     373            sage: I.next_brother((0,1))
     374            sage: I.next_brother((3,0))
     375            (2, 1)
     376            sage: I.next_brother((2,1))
     377            sage: brother = lambda t: (t[0]-1,1) if t[1] == 0 else None
     378            sage: I = SearchForest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)], next_brother=brother)
     379            sage: I.next_brother((1,0))
     380            (0, 1)
     381            sage: I.next_brother((0,1))
     382            sage: I.next_brother((3,0))
     383            (2, 1)
     384            sage: I.next_brother((2,1))
     385        """
     386        # If the function next_brother was given in argument of ``self.__init__``,
     387        # we use it firstly.
     388        if self._next_brother != None:
     389            return self._next_brother(x)
     390        else:
     391            # If we have no next_brother method, we search for the father and
     392            # mainly the father given in argument, otherwise the father method.
     393            if father == None:
     394                father = self.father(x)
     395            children = self.children(father)
     396            brother = children.next()
     397            while brother != x:
     398                brother = children.next()
     399            try:
     400                next =  children.next()
     401            except StopIteration:
     402                next = None
     403            return next
     404
    199405    def __iter__(self):
    200406        r"""
    201         Returns an iterator on the elements of self.
     407        Returns an iterator on the elements of ``self``.
    202408
    203409        EXAMPLES::
    204410
     
    213419            [0]
    214420            sage: f.next()
    215421            [0, 0]
    216 
    217             sage: import __main__
    218             sage: __main__.succ = succ # just because succ has been defined interactively
    219             sage: loads(dumps(C))
    220             An enumerated set
    221422        """
    222423        return search_forest_iterator(self._roots, self._children)
    223424
     425    def depth_first_search_iterator(self):
     426        r"""
     427        Returns an iterator on the elements of ``self`` exploring the tree by depth.
     428
     429        EXAMPLES::
     430
     431            sage: f = SearchForest([[]],
     432            ...                    lambda l: [l+[0], l+[1]] if len(l) < 3 else [])
     433            sage: list(f.depth_first_search_iterator())
     434            [[], [0], [0, 0], [0, 0, 0], [0, 0, 1], [0, 1], [0, 1, 0], [0, 1, 1], [1], [1, 0], [1, 0, 0], [1, 0, 1], [1, 1], [1, 1, 0], [1, 1, 1]]
     435        """
     436        return search_forest_iterator(self._roots, self._children, method="depth")
     437
     438    def breadth_first_search_iterator(self):
     439        r"""
     440        Returns an iterator on the elements of ``self`` exploring the
     441        tree by breadth first search.
     442
     443        EXAMPLES::
     444
     445            sage: f = SearchForest([[]],
     446            ...                    lambda l: [l+[0], l+[1]] if len(l) < 3 else [])
     447            sage: list(f.breadth_first_search_iterator())
     448            [[], [0], [1], [0, 0], [0, 1], [1, 0], [1, 1], [0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]]
     449        """
     450        return search_forest_iterator(self._roots, self._children, method="breadth")
     451
     452    def next_generation_iterator(self, fathers):
     453        r"""
     454        From an iterator ``it`` over some elements of ``self``, return an iterator
     455        over all children of elements generated by ``it`.
     456
     457        EXAMPLES::
     458
     459            sage: I = SearchForest([(0,0)],
     460            ...           lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0
     461            ...                     else [(l[0], l[1]+1)])
     462            sage: list(I.next_generation_iterator(I.roots()))
     463            [(1, 0), (0, 1)]
     464            sage: I = SearchForest([[]],
     465            ...                    lambda l: [l+[0], l+[1]] if len(l) < 3 else [])
     466            sage: list(I.next_generation_iterator(I.roots()))
     467            [[0], [1]]
     468        """
     469        for father in fathers:
     470            for child in self.children(father):
     471                yield child
     472
     473    def _next_element_by_father(self, x):
     474        r"""
     475        Returns the next element of ``self`` by breadth enumeration using
     476        ``father`` and ``next_brother`` method.
     477
     478        EXAMPLES::
     479
     480            sage: def children(t):
     481            ...       if t[2] == 0:
     482            ...           if t[1] == 0:
     483            ...               return [(t[0]+1,t[1],t[2]),(t[0],t[1]+1,t[2]),(t[0],t[1],t[2]+1)]
     484            ...           else:
     485            ...               return [(t[0],t[1]+1,t[2]),(t[0],t[1],t[2]+1)]
     486            ...       else:
     487            ...           return [(t[0],t[1],t[2]+1)]
     488            sage: def father(t):
     489            ...       if t[2] == 0:
     490            ...           if t[1] == 0:
     491            ...               return (t[0]-1,0,0)
     492            ...           else:
     493            ...               return (t[0],t[1]-1,0)
     494            ...       else:
     495            ...           return (t[0],t[1],t[2]-1)
     496            sage: I = SearchForest([(0,0,0)], children, father=father)
     497            sage: I.first()
     498            (0, 0, 0)
     499            sage: I._next_element_by_father(_)
     500            (1, 0, 0)
     501            sage: I._next_element_by_father(_)
     502            (0, 1, 0)
     503            sage: I._next_element_by_father(_)
     504            (0, 0, 1)
     505            sage: I._next_element_by_father(_)
     506            (2, 0, 0)
     507            sage: I._next_element_by_father(_)
     508            (1, 1, 0)
     509            sage: I._next_element_by_father(_)
     510            (1, 0, 1)
     511            sage: I._next_element_by_father(_)
     512            (0, 2, 0)
     513            sage: I._next_element_by_father(_)
     514            (0, 1, 1)
     515            sage: I._next_element_by_father(_)
     516            (0, 0, 2)
     517            sage: I._next_element_by_father(_)
     518            (3, 0, 0)
     519            sage: I._next_element_by_father(_)
     520            (2, 1, 0)
     521            sage: I._next_element_by_father(_)
     522            (2, 0, 1)
     523            sage: I._next_element_by_father(_)
     524            (1, 2, 0)
     525            sage: I._next_element_by_father(_)
     526            (1, 1, 1)
     527        """
     528        roots = list(self.roots())
     529        for i in range(len(roots)):
     530            if x == roots[i]:
     531                if i < len(roots)-1:
     532                    return roots[i+1]
     533                else:
     534                    return self.children(roots[0]).next()
     535        brother = self.next_brother(x)
     536        if brother != None:
     537            return brother
     538        else:
     539            next_father = self._next_element_by_father(self.father(x))
     540            while x != next_father:
     541                try:
     542                    return self.children(next_father).next()
     543                except StopIteration:
     544                    next_father = self._next_element_by_father(next_father)
     545                    continue
     546            try:
     547                return self.children(next_father).next()
     548            except StopIteration:
     549                return None
     550
     551    def _iter_from_to(self, start, end):
     552        r"""
     553        Returns an iterator starting with the element ``start`` and stopping
     554        just before the element ``end``.
     555
     556        EXAMPLES::
     557
     558            sage: father = lambda t: (t[0]-1,0) if t[1] == 0 else (t[0],t[1]-1)
     559            sage: I = SearchForest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)], father=father)
     560            sage: [i for i in I._iter_from_to((3,0),(5,0))]
     561            [(3, 0), (2, 1), (1, 2), (0, 3), (4, 0), (3, 1), (2, 2), (1, 3), (0, 4)]
     562            sage: [i for i in I._iter_from_to((6,0),(6,1))]
     563            [(6, 0), (5, 1), (4, 2), (3, 3), (2, 4), (1, 5), (0, 6), (7, 0)]
     564        """
     565        node = start
     566        while node != end:
     567            yield node
     568            node = self._next_element_by_father(node)
     569
     570    def first_element_of_depth(self, depth, father_with_depth=None):
     571        r"""
     572        Returns the first element of given ``depth``.
     573
     574        EXAMPLES::
     575
     576            sage: father = lambda l : l[:-1]
     577            sage: I = SearchForest([[3]], lambda l: (l+[i] for i in range(l[-1])), father = father)
     578            sage: I.first_element_of_depth(0)
     579            [3]
     580            sage: I.first_element_of_depth(1)
     581            [3, 0]
     582            sage: I.first_element_of_depth(2)
     583            [3, 1, 0]
     584            sage: I.first_element_of_depth(3)
     585            [3, 2, 1, 0]
     586            sage: I.first_element_of_depth(4)
     587            sage: I.first_element_of_depth(5)
     588        """
     589        if depth == 0:
     590            try:
     591                return self.roots().next()
     592            except StopIteration:
     593                return None
     594        else:
     595            if father_with_depth == None:
     596                try:
     597                    next_father =  self.roots().next()
     598                    return self.first_element_of_depth(depth, father_with_depth=(next_father,0))
     599                except StopIteration:
     600                    return None
     601            else:
     602                father = father_with_depth[0]
     603                depth_father = father_with_depth[1]
     604                try:
     605                    next_father = self.children(father).next()
     606                    if depth == depth_father+1:
     607                        return next_father
     608                    else:
     609                        return self.first_element_of_depth(depth, father_with_depth=(next_father,depth_father+1))
     610                except StopIteration:
     611                    next_father = self._next_element_by_father(father)
     612                    if next_father == None:
     613                        return None
     614                    else:
     615                        return self.first_element_of_depth(depth, father_with_depth=(next_father,depth_father))
     616       
     617    def element_of_depth_iterator(self, depth=0, method="full_generation"):
     618        r"""
     619        Returns an iterator on the elements of ``self`` of given depth.
     620        An element of depth `n` can be obtained applying `n` times the
     621        children function from a root.
     622
     623        INPUT:
     624
     625        - ``depth``: a non negative integer
     626        - ``method``: optional string.
     627
     628
     629        By default ``method`` is ``"full_generation"``. This means the
     630        algorithm start from the roots and generate all elements until the
     631        given depth is reached.
     632
     633        If ``method`` is different of ``"full_generation"``, the algorithm
     634        makes use of ``father`` and ``next_brother`` methods. This reduces the
     635        number of calls to the ``children`` method.
     636
     637        EXAMPLES::
     638
     639            sage: I = SearchForest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)])
     640            sage: list(I.element_of_depth_iterator(8))
     641            [(8, 0), (7, 1), (6, 2), (5, 3), (4, 4), (3, 5), (2, 6), (1, 7), (0, 8)]
     642            sage: I = SearchForest([[]], lambda l: [l+[0], l+[1]] if len(l) < 3 else [])
     643            sage: list(I.element_of_depth_iterator(0))
     644            [[]]
     645            sage: list(I.element_of_depth_iterator(1))
     646            [[0], [1]]
     647            sage: list(I.element_of_depth_iterator(2))
     648            [[0, 0], [0, 1], [1, 0], [1, 1]]
     649            sage: list(I.element_of_depth_iterator(3))
     650            [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]]
     651            sage: list(I.element_of_depth_iterator(4))
     652            []
     653            sage: father = lambda t: (t[0]-1,0) if t[1] == 0 else (t[0],t[1]-1)
     654            sage: I = SearchForest([(0,0)], lambda l: [(l[0]+1, l[1]), (l[0], 1)] if l[1] == 0 else [(l[0], l[1]+1)], father=father)
     655            sage: list(I.element_of_depth_iterator(10, method="father"))
     656            [(10, 0), (9, 1), (8, 2), (7, 3), (6, 4), (5, 5), (4, 6), (3, 7), (2, 8), (1, 9), (0, 10)]
     657            sage: father = lambda l : l[:-1]
     658            sage: I = SearchForest([[3]], lambda l: (l+[i] for i in range(l[-1])), father = father)
     659            sage: list(I.element_of_depth_iterator(0, method="father"))
     660            [[3]]
     661            sage: list(I.element_of_depth_iterator(1, method="father"))
     662            [[3, 0], [3, 1], [3, 2]]
     663            sage: for i in range(8):
     664            ...       assert list(I.element_of_depth_iterator(i)) == list(I.element_of_depth_iterator(i, method="father"))
     665        """       
     666        if method == "full_generation":
     667            iter = self.roots()
     668            for i in range(depth):
     669                iter = self.next_generation_iterator(iter)
     670            return iter
     671        else:
     672            # Another way to enumerate all children of given depth is to
     673            # use father and next_brother method...
     674            node = self.first_element_of_depth(depth)
     675            # node is now the starting point for the enumeration
     676            if node == None:
     677                return [].__iter__()
     678            else:
     679                end_node = self.first_element_of_depth(depth+1, father_with_depth=(node,depth))
     680                return self._iter_from_to(node, end_node)
     681
     682
    224683class TransitiveIdeal():
    225684    r"""
    226685    Generic tool for constructing ideals of a relation.