コード例 #1
0
    def dfs(self,
            vertex_set=None,
            raise_if_cyclic=False,
            enter_vertex=None,
            leave_vertex=None):
        """ dfs(self,vertex_set=None,raise_if_cyclic=False,enter_vertex=None,
                leave_vertex=None) -> (discovery, parent, finish)
        Performs a depth-first search on a graph and returns three dictionaries with
        relevant information. If vertex_set is not None, then it is used as
        the list of ids to perform the DFS on.
        
        See CLRS p. 541.

        enter_vertex, when present, is called just before visiting a vertex
        for the first time (and only once) with the vertex id as a parameter.

        leave_vertex, when present, is called just after visiting a vertex
        for the first time (and only once) with the vertex id as a parameter.
        """

        if not vertex_set:
            vertex_set = self.vertices

        # Ugly ugly python
        # http://mail.python.org/pipermail/python-list/2006-April/378964.html

        # We cannot explicitly "del data":
        # http://www.python.org/dev/peps/pep-0227/

        class Closure(object):
            
            def clear(self):
                del self.discovery
                del self.parent
                del self.finish
                del self.t
        
        # Straight CLRS p.541
        data = Closure()
        data.discovery = {} # d in CLRS
        data.parent = {} # \pi in CLRS
        data.finish = {}  # f in CLRS
        data.t = 0

        (enter, leave, back, other) = xrange(4)

        # inspired by http://www.ics.uci.edu/~eppstein/PADS/DFS.py

        def handle(v, w, edgetype):
            data.t += 1
            if edgetype == enter:
                data.discovery[v] = data.t
                if enter_vertex:
                    enter_vertex(w)
                if v != w:
                    data.parent[w] = v
            elif edgetype == leave:
                data.finish[w] = data.t
                if leave_vertex:
                    leave_vertex(w)
            elif edgetype == back and raise_if_cyclic:
                raise self.GraphContainsCycles(v, w)
        
        visited = set()
        gray = set()
        # helper function to build stack structure
        def st(v): return (v, iter(self.adjacency_list[v]))
        for vertex in vertex_set:
            if vertex not in visited:
                handle(vertex, vertex, enter)
                visited.add(vertex)
                stack = Stack()
                stack.push(st(vertex))
                gray.add(vertex)
                while stack.size:
                    parent, children = stack.top()
                    try:
                        child, _ = children.next()
                        if child in visited:
                            handle(parent, child, (child in gray
                                                   and back
                                                   or other))
                        else:
                            handle(parent, child, enter)
                            visited.add(child)
                            stack.push(st(child))
                            gray.add(child)
                    except StopIteration:
                        gray.remove(parent)
                        stack.pop()
                        if stack.size:
                            handle(stack.top()[0], parent, leave)
                handle(vertex, vertex, leave)

        result = (data.discovery, data.parent, data.finish)
        data.clear()
        return result
コード例 #2
0
ファイル: graph.py プロジェクト: hjanime/VisTrails
    def dfs(self,
            vertex_set=None,
            raise_if_cyclic=False,
            enter_vertex=None,
            leave_vertex=None):
        """ dfs(self,vertex_set=None,raise_if_cyclic=False,enter_vertex=None,
                leave_vertex=None) -> (discovery, parent, finish)
        Performs a depth-first search on a graph and returns three dictionaries with
        relevant information. If vertex_set is not None, then it is used as
        the list of ids to perform the DFS on.

        See CLRS p. 541.

        enter_vertex, when present, is called just before visiting a vertex
        for the first time (and only once) with the vertex id as a parameter.

        leave_vertex, when present, is called just after visiting a vertex
        for the first time (and only once) with the vertex id as a parameter.
        """

        if not vertex_set:
            vertex_set = self.vertices

        # Straight CLRS p.541
        discovery = {} # d in CLRS
        parents = {} # \pi in CLRS
        finish = {}  # f in CLRS
        t = [0]

        (enter, leave, back, other) = xrange(4)

        # inspired by http://www.ics.uci.edu/~eppstein/PADS/DFS.py

        def handle(v, w, edgetype):
            t[0] += 1
            if edgetype == enter:
                discovery[v] = t[0]
                if enter_vertex:
                    enter_vertex(w)
                if v != w:
                    parents[w] = v
            elif edgetype == leave:
                finish[w] = t[0]
                if leave_vertex:
                    leave_vertex(w)
            elif edgetype == back and raise_if_cyclic:
                raise GraphContainsCycles(v, w)

        visited = set()
        gray = set()
        # helper function to build stack structure
        def st(v): return (v, iter(self.adjacency_list[v]))
        for vertex in vertex_set:
            if vertex not in visited:
                handle(vertex, vertex, enter)
                visited.add(vertex)
                stack = Stack()
                stack.push(st(vertex))
                gray.add(vertex)
                while stack.size:
                    parent, children = stack.top()
                    try:
                        child, _ = children.next()
                        if child in visited:
                            handle(parent, child, (child in gray
                                                   and back
                                                   or other))
                        else:
                            handle(parent, child, enter)
                            visited.add(child)
                            stack.push(st(child))
                            gray.add(child)
                    except StopIteration:
                        gray.remove(parent)
                        stack.pop()
                        if stack.size:
                            handle(stack.top()[0], parent, leave)
                handle(vertex, vertex, leave)

        return discovery, parents, finish
コード例 #3
0
ファイル: graph.py プロジェクト: licode/VisTrails
    def dfs(self,
            vertex_set=None,
            raise_if_cyclic=False,
            enter_vertex=None,
            leave_vertex=None):
        """ dfs(self,vertex_set=None,raise_if_cyclic=False,enter_vertex=None,
                leave_vertex=None) -> (discovery, parent, finish)
        Performs a depth-first search on a graph and returns three dictionaries with
        relevant information. If vertex_set is not None, then it is used as
        the list of ids to perform the DFS on.
        
        See CLRS p. 541.

        enter_vertex, when present, is called just before visiting a vertex
        for the first time (and only once) with the vertex id as a parameter.

        leave_vertex, when present, is called just after visiting a vertex
        for the first time (and only once) with the vertex id as a parameter.
        """

        if not vertex_set:
            vertex_set = self.vertices

        # Ugly ugly python
        # http://mail.python.org/pipermail/python-list/2006-April/378964.html

        # We cannot explicitly "del data":
        # http://www.python.org/dev/peps/pep-0227/

        class Closure(object):
            def clear(self):
                del self.discovery
                del self.parent
                del self.finish
                del self.t

        # Straight CLRS p.541
        data = Closure()
        data.discovery = {}  # d in CLRS
        data.parent = {}  # \pi in CLRS
        data.finish = {}  # f in CLRS
        data.t = 0

        (enter, leave, back, other) = xrange(4)

        # inspired by http://www.ics.uci.edu/~eppstein/PADS/DFS.py

        def handle(v, w, edgetype):
            data.t += 1
            if edgetype == enter:
                data.discovery[v] = data.t
                if enter_vertex:
                    enter_vertex(w)
                if v != w:
                    data.parent[w] = v
            elif edgetype == leave:
                data.finish[w] = data.t
                if leave_vertex:
                    leave_vertex(w)
            elif edgetype == back and raise_if_cyclic:
                raise self.GraphContainsCycles(v, w)

        visited = set()
        gray = set()

        # helper function to build stack structure
        def st(v):
            return (v, iter(self.adjacency_list[v]))

        for vertex in vertex_set:
            if vertex not in visited:
                handle(vertex, vertex, enter)
                visited.add(vertex)
                stack = Stack()
                stack.push(st(vertex))
                gray.add(vertex)
                while stack.size:
                    parent, children = stack.top()
                    try:
                        child, _ = children.next()
                        if child in visited:
                            handle(parent, child,
                                   (child in gray and back or other))
                        else:
                            handle(parent, child, enter)
                            visited.add(child)
                            stack.push(st(child))
                            gray.add(child)
                    except StopIteration:
                        gray.remove(parent)
                        stack.pop()
                        if stack.size:
                            handle(stack.top()[0], parent, leave)
                handle(vertex, vertex, leave)

        result = (data.discovery, data.parent, data.finish)
        data.clear()
        return result
コード例 #4
0
    def dfs(self,
            vertex_set=None,
            raise_if_cyclic=False,
            enter_vertex=None,
            leave_vertex=None):
        """ dfs(self,vertex_set=None,raise_if_cyclic=False,enter_vertex=None,
                leave_vertex=None) -> (discovery, parent, finish)
        Performs a depth-first search on a graph and returns three dictionaries with
        relevant information. If vertex_set is not None, then it is used as
        the list of ids to perform the DFS on.

        See CLRS p. 541.

        enter_vertex, when present, is called just before visiting a vertex
        for the first time (and only once) with the vertex id as a parameter.

        leave_vertex, when present, is called just after visiting a vertex
        for the first time (and only once) with the vertex id as a parameter.
        """

        if not vertex_set:
            vertex_set = self.vertices

        # Straight CLRS p.541
        discovery = {}  # d in CLRS
        parents = {}  # \pi in CLRS
        finish = {}  # f in CLRS
        t = [0]

        (enter, leave, back, other) = xrange(4)

        # inspired by http://www.ics.uci.edu/~eppstein/PADS/DFS.py

        def handle(v, w, edgetype):
            t[0] += 1
            if edgetype == enter:
                discovery[v] = t[0]
                if enter_vertex:
                    enter_vertex(w)
                if v != w:
                    parents[w] = v
            elif edgetype == leave:
                finish[w] = t[0]
                if leave_vertex:
                    leave_vertex(w)
            elif edgetype == back and raise_if_cyclic:
                raise GraphContainsCycles(v, w)

        visited = set()
        gray = set()

        # helper function to build stack structure
        def st(v):
            return (v, iter(self.adjacency_list[v]))

        for vertex in vertex_set:
            if vertex not in visited:
                handle(vertex, vertex, enter)
                visited.add(vertex)
                stack = Stack()
                stack.push(st(vertex))
                gray.add(vertex)
                while stack.size:
                    parent, children = stack.top()
                    try:
                        child, _ = children.next()
                        if child in visited:
                            handle(parent, child,
                                   (child in gray and back or other))
                        else:
                            handle(parent, child, enter)
                            visited.add(child)
                            stack.push(st(child))
                            gray.add(child)
                    except StopIteration:
                        gray.remove(parent)
                        stack.pop()
                        if stack.size:
                            handle(stack.top()[0], parent, leave)
                handle(vertex, vertex, leave)

        return discovery, parents, finish