def __init__(self, edges=[]): self.vertexList = VertexList(edges) for e in edges: self.addEdge(e) self.addEdge((e[1], e[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)
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
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