Exemple #1
0
 def __init__(self, edges=[]):
     self.vertexList = VertexList(edges)
     for e in edges:
         self.addEdge(e)
         self.addEdge((e[1], e[0]))
Exemple #2
0
class DiGraph:
    def __init__(self,edges=[]):
        self.vertexList = VertexList(edges)
        for e in edges:
            self.addEdge(e)
            ## Modification
            # for directed graph, we only need to store one direction - (in, out)
            # self.addEdge((e[1],e[0])) 

    def addEdge(self,edge):
        # locate the related vertex according to the edge given
        vertex = self.vertexList.locate(edge[0]) # edge[0] is the incoming vertex
        edgelist = vertex.edges # get the edgelist object for this incoming vertex
        if edgelist != None:
            # add outcoming vertex to the edgelist
            edgelist.add(edge[1])
        else:
            # construct a new Edgelist object if this vertex has no edgelist yet
            edgelist = EdgeList(edge[1])
        vertex.setEdges(edgelist)

    def __iter__(self):
        vertices = self.vertexList
        for v in vertices:
            x = vertices.locate(v)
            y = x.edges
            if y != None:
                for z in y:
                    yield (v,z)

    def insertVertex(self,item):
        if not (item in self.vertexList):
            self.vertexList.append(item)

    def deleteVertex(self,item):
        return self.vertexList.remove(item)

    def insertEdge(self,edge):
        self.vertexList.addVertex(edge)
        self.addEdge(edge)
        ## Modification, only one direction now
        # self.addEdge((edge[1],edge[0]))

    def deleteEdge(self,edge):
        self.__deleteEdge(edge)
        ## Modification, only one direction now
        # self.__deleteEdge((edge[1],edge[0]))

    def __deleteEdge(self,edge):
        if not (edge[0] in self.vertexList):
            print("There is no edge", edge)
            return False
        vertexlocation = self.vertexList.locate(edge[0])
        edgelist = vertexlocation.getEdges()
        if edgelist == None:
            print("There is no edge", edge)
            return False
        res = edgelist.remove(edge[1])
        if res == False:
            print("There is no edge", edge)
        return res

    def outgoingEdges(self,item):
        vertex = self.vertexList.locate(item)
        if vertex == None:
            print("There is no vertex", item)
            return []
        edgelist = vertex.getEdges()
        if edgelist == None:
            return []
        res = []
        for v in edgelist:
            res.append((item,v))
        return res

    def bfs(self,vertex):
        if not (vertex in self.vertexList):
            print("There is no vertex", vertex)
            return None
        length = self.vertexList.getlength()
        distance = [None] * length
        parent = [None] * length
        index = self.vertexList.index(vertex)
        distance[index] = 0
        parent[index] = vertex
        currentlayer = Fifo(length)
        currentlayer.pushback(vertex)
        nextlayer = Fifo(length)
        for l in range(length):
            for u in currentlayer:
                print(u)
                loc = self.vertexList.locate(u)
                edgelist = loc.getEdges()
                if edgelist != None:
                    for v in edgelist:
                        idx = self.vertexList.index(v)
                        if parent[idx] == None:
                            nextlayer.pushback(v)
                            distance[idx] = l + 1
                            parent[idx] = u
            currentlayer = nextlayer
            nextlayer = Fifo(length)
        return (distance,parent)

    #DFS traverse using recursion
    def allDFS(self):
        numVertices = self.vertexList.getlength()
        initlist = [None]* numVertices
        self.tree = PyList(initlist,numVertices)
        for i in range(numVertices):
            newgraph = DiGraph([])
            self.tree[i] = newgraph
        for s in self.vertexList:
            self.mark = [None] * numVertices
            self.dfsPos = 1
            self.dfsNum = [1] * numVertices
            self.finishingTime = 1
            self.finishTime = [1] * numVertices
            idx = self.vertexList.index(s)
            if self.mark[idx] == None:
                self.mark[idx] = s
                self.dfsNum[idx] = self.dfsPos
                self.dfsPos += 1
                self.dfs(s,idx)

    def dfs(self,vertex,index):
        for e in self.outgoingEdges(vertex):
            idx = self.vertexList.index(e[1])
            if self.mark[idx] == None:
                self.tree[index].insertEdge(e)
                self.__traverseTreeEdge(e)
                self.mark[idx] = e[1]
                self.dfs(e[1],index)
        self.backtrack(vertex)

    def __traverseTreeEdge(self,e):
        idx = self.vertexList.index(e[1])
        self.dfsNum[idx] = self.dfsPos
        self.dfsPos += 1

    def backtrack(self,vertex):
        idx = self.vertexList.index(vertex)
        self.finishTime[idx] = self.finishingTime
        self.finishingTime += 1

    def reachable(self,vertex1,vertex2):
        ret=self.bfs_for_path(vertex1)
        distance=ret[0]
        parent=ret[1]
        loc = self.vertexList.index(vertex2)
        if parent[loc]==None:
            return False
        else:
            return True

    def path(self,vertex1,vertex2):
        ret=self.bfs_for_path(vertex1)
        distance=ret[0]
        parent=ret[1]
        loc = self.vertexList.index(vertex2)
        if parent[loc]==None:
            return None
        p=parent[loc]
        c=vertex2
        path=PyList()
        while p!=vertex1:
            loc = self.vertexList.index(c)
            p=parent[loc]
            path.insert(0,(p,c))
            c=p
        path.append((p,c))
        return path

    def bfs_for_path(self,vertex):
        if not (vertex in self.vertexList):
            print("There is no vertex", vertex)
            return None
        length = self.vertexList.getlength()
        distance = [None] * length
        parent = [None] * length
        index = self.vertexList.index(vertex)
        distance[index] = 0
        parent[index] = vertex
        queue = Fifo(length)
        queue.pushback(vertex)
        for l in range(length):
            for u in queue:
                # print(u)
                loc = self.vertexList.locate(u)
                edgelist = loc.getEdges()
                if edgelist != None:
                    for v in edgelist:
                        idx = self.vertexList.index(v)
                        if parent[idx] == None:
                            queue.pushback(v)
                            distance[idx] = l + 1
                            parent[idx] = u
        return (distance,parent)
Exemple #3
0
class Graph:
    def __init__(self, edges=[]):
        self.vertexList = VertexList(edges)
        for e in edges:
            self.addEdge(e)
            self.addEdge((e[1], e[0]))

    def addEdge(self, edge):
        vertex = self.vertexList.locate(edge[0])
        edgelist = vertex.edges
        if edgelist != None:
            edgelist.add(edge[1])
        else:
            edgelist = EdgeList(edge[1])
        vertex.setEdges(edgelist)

    def __iter__(self):
        vertices = self.vertexList
        for v in vertices:
            x = vertices.locate(v)
            y = x.edges
            if y != None:
                for z in y:
                    yield (v, z)

    def insertVertex(self, item):
        if not (item in self.vertexList):
            self.vertexList.append(item)

    def deleteVertex(self, item):
        return self.vertexList.remove(item)

    def insertEdge(self, edge):
        self.vertexList.addVertex(edge)
        self.addEdge(edge)
        self.addEdge((edge[1], edge[0]))

    def deleteEdge(self, edge):
        self.__deleteEdge(edge)
        self.__deleteEdge((edge[1], edge[0]))

    def __deleteEdge(self, edge):
        if not (edge[0] in self.vertexList):
            print("There is no edge", edge)
            return False
        vertexlocation = self.vertexList.locate(edge[0])
        edgelist = vertexlocation.getEdges()
        if edgelist == None:
            print("There is no edge", edge)
            return False
        res = edgelist.remove(edge[1])
        if res == False:
            print("There is no edge", edge)
        return res

    def outgoingEdges(self, item):
        vertex = self.vertexList.locate(item)
        if vertex == None:
            print("There is no vertex", item)
            return []
        edgelist = vertex.getEdges()
        if edgelist == None:
            return []
        res = []
        for v in edgelist:
            res.append((item, v))
        return res
        # yield (item,v) # If we replace the above two lines with this line, then this methods works as an iterator.

    def bfs_KD(self, vertex):
        if not (vertex in self.vertexList):
            print("There is no vertex", vertex)
            return None
        length = self.vertexList.getlength()
        distance = [None] * length
        parent = [None] * length
        index = self.vertexList.index(vertex)
        distance[index] = 0
        parent[index] = vertex
        currentlayer = Fifo(length)
        currentlayer.pushback(vertex)
        nextlayer = Fifo(length)
        for l in range(length):
            for u in currentlayer:
                # print(u)
                loc = self.vertexList.locate(u)
                edgelist = loc.getEdges()
                if edgelist != None:
                    for v in edgelist:
                        idx = self.vertexList.index(v)
                        if parent[idx] == None:
                            nextlayer.pushback(v)
                            distance[idx] = l + 1
                            parent[idx] = u
            currentlayer = nextlayer
            nextlayer = Fifo(length)
        return (distance, parent)

    def bfs(self, vertex, index):
        if not (vertex in self.vertexList):
            print("There is no vertex", vertex)
            return None
        length = self.vertexList.getlength()
        self.distance[index] = 0
        self.parent[index] = vertex
        queue = []
        queue.append(vertex)
        head = 0  # head index of queue
        while head < len(queue):
            u = queue[head]
            index = self.vertexList.index(u)
            cur_distance = self.distance[index]
            loc = self.vertexList.locate(u)
            edgelist = loc.getEdges()
            if edgelist != None:
                for v in edgelist:
                    idx = self.vertexList.index(v)
                    if self.parent[idx] == None:
                        queue.append(v)
                        self.distance[idx] = cur_distance + 1
                        self.parent[idx] = u
                    else:
                        # TODO leave space to handle if meet other vertex in the same subset
                        pass
            head += 1

    def allBFS(self):
        numVertices = self.vertexList.getlength()
        self.distance = [None] * numVertices
        self.parent = [None] * numVertices
        for s in self.vertexList:
            idx = self.vertexList.index(s)
            if self.distance[idx] == None:
                self.bfs(s, idx)
        return (self.distance, self.parent)

    #DFS traverse using recursion
    def allDFS(self):
        numVertices = self.vertexList.getlength()
        initlist = [None] * numVertices
        self.tree = PyList(initlist, numVertices)
        for i in range(numVertices):
            newgraph = Graph([])
            self.tree[i] = newgraph
        self.mark = [None] * numVertices
        self.dfsPos = 1
        self.dfsNum = [1] * numVertices
        self.finishingTime = 1
        self.finishTime = [1] * numVertices
        for s in self.vertexList:
            idx = self.vertexList.index(s)
            if self.mark[idx] == None:
                self.mark[idx] = s
                self.dfsNum[idx] = self.dfsPos
                self.dfsPos += 1
                self.dfs(s, idx)

    def dfs(self, vertex, index):
        for e in self.outgoingEdges(vertex):
            idx = self.vertexList.index(e[1])
            if self.mark[idx] == None:
                self.tree[index].insertEdge(e)
                self.__traverseTreeEdge(e)
                self.mark[idx] = e[1]
                self.dfs(e[1], index)
        self.backtrack(vertex)

    def __traverseTreeEdge(self, e):
        idx = self.vertexList.index(e[1])
        self.dfsNum[idx] = self.dfsPos
        self.dfsPos += 1

    def backtrack(self, vertex):
        idx = self.vertexList.index(vertex)
        self.finishTime[idx] = self.finishingTime
        self.finishingTime += 1
Exemple #4
0
class WGraph:
    def __init__(self, edges=[]):
        self.vertexList = VertexList(edges)
        for e in edges:
            self.addEdge(e)
            self.addEdge((e[1], e[0], e[2]))

    def addEdge(self, edge):
        vertex = self.vertexList.locate(edge[0])
        edgelist = vertex.edges
        if edgelist != None:
            edgelist.add(edge[1], edge[2])
        else:
            edgelist = WEdgeList(edge[1], edge[2])
        vertex.setEdges(edgelist)

    def __iter__(self):
        vertices = self.vertexList
        for v in vertices:
            x = vertices.locate(v)
            y = x.edges
            if y != None:
                for z in y:
                    yield (v, z[0], z[1])

    def insertVertex(self, item):
        if not (item in self.vertexList):
            self.vertexList.append(item)

    def deleteVertex(self, item):
        return self.vertexList.remove(item)

    def insertEdge(self, edge):
        self.vertexList.addVertex(edge)
        self.addEdge(edge)
        self.addEdge((edge[1], edge[0], edge[2]))

    def deleteEdge(self, edge):
        self.__deleteEdge(edge)
        self.__deleteEdge((edge[1], edge[0], edge[2]))

    def __deleteEdge(self, edge):
        if not (edge[0] in self.vertexList):
            print("There is no edge", edge)
            return False
        vertexlocation = self.vertexList.locate(edge[0])
        edgelist = vertexlocation.getEdges()
        if edgelist == None:
            print("There is no edge", edge)
            return False
        res = edgelist.remove(edge[1])
        if res == False:
            print("There is no edge", edge)
        return res

    def outgoingEdges(self, item):
        vertex = self.vertexList.locate(item)
        if vertex == None:
            print("There is no vertex", item)
            return []
        edgelist = vertex.getEdges()
        if edgelist == None:
            return []
        res = []
        for v in edgelist:
            res.append((item, v[0], v[1]))
        return res
        # yield (item,v[0],v[1]) # If we replace the above two lines with this line, then this methods works as an iterator.

    def bfs_KD(self, vertex):
        if not (vertex in self.vertexList):
            print("There is no vertex", vertex)
            return None
        length = self.vertexList.getlength()
        distance = [None] * length
        parent = [None] * length
        index = self.vertexList.index(vertex)
        distance[index] = 0
        parent[index] = vertex
        currentlayer = Fifo(length)
        currentlayer.pushback(vertex)
        nextlayer = Fifo(length)
        for l in range(length):
            for u in currentlayer:
                # print(u)
                loc = self.vertexList.locate(u)
                edgelist = loc.getEdges()
                if edgelist != None:
                    for v in edgelist:
                        idx = self.vertexList.index(v[0])
                        if parent[idx] == None:
                            nextlayer.pushback(v[0])
                            distance[idx] = l + 1
                            parent[idx] = u
            currentlayer = nextlayer
            nextlayer = Fifo(length)
        return (distance, parent)

    def bfs(self, vertex, index):
        if not (vertex in self.vertexList):
            print("There is no vertex", vertex)
            return None
        length = self.vertexList.getlength()
        self.distance[index] = 0
        self.parent[index] = vertex
        queue = []
        queue.append(vertex)
        head = 0  # head index of queue
        while head < len(queue):
            u = queue[head]
            index = self.vertexList.index(u)
            cur_distance = self.distance[index]
            loc = self.vertexList.locate(u)
            edgelist = loc.getEdges()
            if edgelist != None:
                for v in edgelist:
                    idx = self.vertexList.index(v[0])
                    if self.parent[idx] == None:
                        queue.append(v[0])
                        self.distance[idx] = cur_distance + 1
                        self.parent[idx] = u
                    else:
                        # TODO handle if meet other vertex in the same subset
                        pass
            head += 1

    def allBFS(self):
        numVertices = self.vertexList.getlength()
        self.distance = [None] * numVertices
        self.parent = [None] * numVertices
        for s in self.vertexList:
            idx = self.vertexList.index(s)
            if self.distance[idx] == None:
                self.bfs(s, idx)
        return (self.distance, self.parent)

    #DFS traverse using recursion
    def allDFS(self):
        numVertices = self.vertexList.getlength()
        initlist = [None] * numVertices
        self.tree = PyList(initlist, numVertices)
        for i in range(numVertices):
            newgraph = WGraph([])
            self.tree[i] = newgraph
        self.mark = [None] * numVertices
        self.dfsPos = 1
        self.dfsNum = [1] * numVertices
        self.finishingTime = 1
        self.finishTime = [1] * numVertices
        for s in self.vertexList:
            idx = self.vertexList.index(s)
            if self.mark[idx] == None:
                self.mark[idx] = s
                self.dfsNum[idx] = self.dfsPos
                self.dfsPos += 1
                self.dfs(s, idx)

    def dfs(self, vertex, index):
        for e in self.outgoingEdges(vertex):
            idx = self.vertexList.index(e[1])
            if self.mark[idx] == None:
                self.tree[index].insertEdge(e)
                self.__traverseTreeEdge(e)
                self.mark[idx] = e[1]
                self.dfs(e[1], index)
        self.backtrack(vertex)

    def __traverseTreeEdge(self, e):
        idx = self.vertexList.index(e[1])
        self.dfsNum[idx] = self.dfsPos
        self.dfsPos += 1

    def backtrack(self, vertex):
        idx = self.vertexList.index(vertex)
        self.finishTime[idx] = self.finishingTime
        self.finishingTime += 1

    def kruskal(self):
        """
        An algorithm to find the minimal spanning tree within a graph.

        Using a disjoined set to maintain the connected components.

        The time complexity is in O(mlogn)

        :return: a set of edges of the minimal spanning tree.
        """
        raise AttributeError(
            "member function kruskal(self) is reserved until the deadline of assignment 8"
        )
        pass

    def prim(self):
        """
        An algorithm to find the minimal spanning tree within a graph.

        The result cannot cross connected components.

        The modified version of prim algorithm is prim_modified(), which

        is able to cross connected components.

        :return: a set of edges of the minimal spanning tree.
        """
        raise AttributeError(
            "member function prim(self) is reserved until the deadline of assignment 8"
        )
        pass

    def prim_modified(self):
        """
        A modified prim algorithm to find the minimal spanning tree of a graph.

        This algorithm is able to locate all the disconnected components.

        The main idea is to use a disjoint set to manage the connected components,

        if there are more than 1 components then build a dummy bridge between them,

        then apply prim algorithm.

        :return: a set of edges of the minimal spanning tree.
        """
        raise AttributeError(
            "member function prim_modified(self) is reserved until the deadline of assignment 8"
        )
        pass

    def max_spanning_tree(self):
        '''
            This function is the modification of kruskal, only where marked

            @core is modified, please refer to kruskal for better comments

            and comprehension
        '''
        raise AttributeError(
            "member function max_spanning_tree(self) is reserved until the deadline of assignment 8"
        )
        pass

    def max_spanning_insert(self, e):
        '''
            maintain a minimum spanning tree if edges are presented serially and once

            use greedy algorithms

            insert the edge when new vertices appear or it connects two not-connected components

            otherwise, find the circle formed by the insertion and remove the longest path
        '''
        raise AttributeError(
            "member function max_spanning_insert(self) is reserved until the deadline of assignment 8"
        )
        pass