示例#1
0
def loops(node, type_):
    '''
    Return all loops from the given node.
    
    Each loop is a list that starts and ends with the given node.
    '''
    stack = [[node]]
    known = set([node])  # avoid getting lost in sub-loops
    while stack:
        ancestors = stack.pop()
        parent = ancestors[-1]
        if isinstance(parent, type_):
            for child in parent:
                family = list(ancestors)
                family.append(child)
                if child is node:
                    yield family
                else:
                    if not safe_in(child, known):
                        stack.append(family)
                        safe_add(known, child)
示例#2
0
def loops(node, type_):
    """
    Return all loops from the given node.
    
    Each loop is a list that starts and ends with the given node.
    """
    stack = [[node]]
    known = set([node])  # avoid getting lost in sub-loops
    while stack:
        ancestors = stack.pop()
        parent = ancestors[-1]
        if isinstance(parent, type_):
            for child in parent:
                family = list(ancestors)
                family.append(child)
                if child is node:
                    yield family
                else:
                    if not safe_in(child, known):
                        stack.append(family)
                        safe_add(known, child)
示例#3
0
def dfs_edges(node, type_):
    '''
    Iterative DFS, based on http://www.ics.uci.edu/~eppstein/PADS/DFS.py
    
    Returns forward and reverse edges.  Also returns root node in correct 
    order for pre- (FORWARD) and post- (BACKWARD) ordering.

    ``type_`` selects which values are iterated over.  Children which are
    not of this type are flagged with LEAF.
    '''
    while isinstance(node, type_):
        try:
            stack = [(node, iter(node), ROOT)]
            yield node, node, FORWARD | ROOT
            visited = set()
            safe_add(visited, node)  # cannot track loops in unhashable objects
            while stack:
                parent, children, ptype = stack[-1]
                try:
                    child = next(children)
                    if isinstance(child, type_):
                        if safe_in(child, visited, False):
                            yield parent, child, NONTREE
                        else:
                            stack.append((child, iter(child), NODE))
                            yield parent, child, FORWARD | NODE
                            safe_add(visited, child)
                    else:
                        stack.append((child, empty(), LEAF))
                        yield parent, child, FORWARD | LEAF
                except StopIteration:
                    stack.pop()
                    if stack:
                        yield stack[-1][0], parent, BACKWARD | ptype
            yield node, node, BACKWARD | ROOT
            return
        except Reset:
            yield  # in response to the throw (ignored by caller)
示例#4
0
def dfs_edges(node, type_):
    """
    Iterative DFS, based on http://www.ics.uci.edu/~eppstein/PADS/DFS.py
    
    Returns forward and reverse edges.  Also returns root node in correct 
    order for pre- (FORWARD) and post- (BACKWARD) ordering.

    ``type_`` selects which values are iterated over.  Children which are
    not of this type are flagged with LEAF.
    """
    while isinstance(node, type_):
        try:
            stack = [(node, iter(node), ROOT)]
            yield node, node, FORWARD | ROOT
            visited = set()
            safe_add(visited, node)  # cannot track loops in unhashable objects
            while stack:
                parent, children, ptype = stack[-1]
                try:
                    child = next(children)
                    if isinstance(child, type_):
                        if safe_in(child, visited, False):
                            yield parent, child, NONTREE
                        else:
                            stack.append((child, iter(child), NODE))
                            yield parent, child, FORWARD | NODE
                            safe_add(visited, child)
                    else:
                        stack.append((child, empty(), LEAF))
                        yield parent, child, FORWARD | LEAF
                except StopIteration:
                    stack.pop()
                    if stack:
                        yield stack[-1][0], parent, BACKWARD | ptype
            yield node, node, BACKWARD | ROOT
            return
        except Reset:
            yield  # in response to the throw (ignored by caller)