def test_extend(self): heap = Heap(lambda a, b: a <= b) sequence = [5, 9, 3, 4, 6, 2, 0, 8, 7, 1] copy = [x for x in sequence] heap.extend(sequence) self.assertEqual(10, len(heap)) heap.extend(sequence) self.assertEqual(20, len(heap)) for i in range(10): self.assertEqual(i, heap.peek()) self.assertEqual(i, heap.extract()) self.assertEqual(20 - 2 * i - 1, len(heap)) self.assertEqual(i, heap.peek()) self.assertEqual(i, heap.extract()) self.assertEqual(20 - 2 * i - 2, len(heap)) self.assertEqual(copy, sequence)
def test_extract(self): heap = Heap(lambda a, b: a <= b) sequence = [5, 9, 3, 4, 6, 2, 0, 8, 7, 1] self.assertRaises(IndexError, heap.extract) for item in sequence: heap.insert(item) for index in range(len(sequence)): self.assertEqual(index, heap.extract()) self.assertRaises(IndexError, heap.extract)
def test_clear(self): heap = Heap(lambda a, b: a <= b) sequence = [5, 9, 3, 4, 6, 2, 0, 8, 7, 1] heap.extend(sequence) self.assertFalse(heap.is_empty()) heap.clear() self.assertTrue(heap.is_empty()) self.assertRaises(IndexError, heap.peek) self.assertRaises(IndexError, heap.extract) heap.insert(9) self.assertEqual(1, len(heap)) self.assertEqual(9, heap.peek()) self.assertEqual(9, heap.extract()) self.assertTrue(heap.is_empty())
def test_replace(self): heap = Heap(lambda a, b: a < b) sequence = [5, 9, 3, 4, 6, 2, 0, 8, 7, 1] self.assertRaises(IndexError, heap.peek) self.assertEqual(4, heap.replace(4)) self.assertRaises(IndexError, heap.peek) heap.extend(sequence) for result, item in zip(range(5), range(5, 10)): self.assertEqual(result, heap.replace(item)) for item in range(5): self.assertEqual(item, heap.replace(item)) self.assertEqual(5, heap.extract()) heap = Heap(lambda a, b: a > b) sequence = [5, 9, 3, 4, 6, 2, 0, 8, 7, 1] self.assertRaises(IndexError, heap.peek) self.assertEqual(4, heap.replace(4)) self.assertRaises(IndexError, heap.peek) heap.extend(sequence) for item, result in zip(reversed(range(5)), reversed(range(5, 10))): self.assertEqual(result, heap.replace(item)) for item in range(5, 10): self.assertEqual(item, heap.replace(item)) self.assertEqual(4, heap.extract())
def dijkstra(graph, source, sink): if not(source in graph and sink in graph): raise ValueError('source and/or sink does not exist in graph') def compareVertex(vertex1, vertex2): if(vertex1.dist == vertex2.dist): return vertex1.key < vertex2.key else: return vertex1.dist > vertex2.dist path = [] unvisitedQ = Heap("min", compareVertex) for vertex in graph: if vertex.availability == True: vertex.dist = math.inf vertex.prev = None unvisitedQ.insert(vertex) source.dist = 0 unvisitedQ.update(unvisitedQ.heap.index(source)) while not unvisitedQ.isEmpty(): u = unvisitedQ.extract() for k, adjVertex in u.adjList.items(): if adjVertex['availability'] == True and adjVertex['k'].availability == True: alt = u.dist + adjVertex['weight'] else: alt = math.inf if alt < adjVertex['k'].dist: adjVertex['k'].dist = alt adjVertex['k'].prev = u unvisitedQ.update(unvisitedQ.heap.index(adjVertex['k'])) if sink.prev != None: vertex = sink while vertex != source: path.insert(0, vertex) vertex = vertex.prev path.insert(0, source) else: path = None return path
def approxMVC(graph): def compareVertex(vertex1, vertex2): if(vertex1.current_degree == vertex2.current_degree): return vertex1.key < vertex2.key else: return vertex1.current_degree > vertex2.current_degree #Priority queue to select the heap with the highest degree vertexHeap = Heap("max", compareVertex) #Vertices that have been visted vistedList = [] #Vertex Cover vertexCover = [] #Set the current degree of each vertex, this is what will be used to sort for vertex in graph: vertex.current_degree = len(vertex.adjList) - 1 vertexHeap.insert(vertex) print("Heap: " + ','.join(["("+ str(i.key) + "," + str(i.current_degree) + ")" for i in vertexHeap.heap])) while not vertexHeap.isEmpty() and vertexHeap.heap[0].current_degree > 0: vertex = vertexHeap.extract() vistedList.append(vertex) vertexCover.append(vertex) print("Visiting vertex: " + vertex.key + ", Visisted = {" + ",".join([vertex.key for vertex in vistedList]) + "}") for k, adjVertex in vertex.adjList.items(): if not (adjVertex['k'] in vistedList) and adjVertex['k'].current_degree != 0: #If it hasn't been adjVertex['k'].current_degree = adjVertex['k'].current_degree - 1 print(" Updating degree of vertex " + k + " to " + str(adjVertex['k'].current_degree)) vertexHeap.update(vertexHeap.heap.index(adjVertex['k'])) print("Heap: " + ','.join(["("+ str(i.key) + "," + str(i.current_degree) + ")" for i in vertexHeap.heap])) print() print("VERTEX COVER = " + ",".join([vertex.key for vertex in vertexCover])) return set(vertexCover)
class Huffman: def __init__(self, S): self.huff = S self.node = None self.heap = Heap() self.l = [] self.cont = 0 #build Tree of heap Max def buildTree(self): while len(self.huff)-1 > 0: self.node = Node() P1 = self.heap.extract(self.huff) P2 = self.heap.extract(self.huff) if(P1.frequence > P2.frequence): self.node.left = P2 self.node.right = P1 else: self.node.left = P1 self.node.right = P2 self.node.frequence = P1.frequence + P2.frequence self.node.data = -1 self.huff.append(self.node) self.heap.heapUp(self.huff, len(self.huff)-1) return self.heap.extract(self.huff) #....................................................... def returnHuff(self): return self.buildTree() #go through the tree, build the codification and add in a dictionary #this method build the code of each pixel def goThroughTree(self, H, cod=''): if H.left == None and H.right == None: self.l.append((H.data, cod)) else: self.goThroughTree(H.left, cod=cod + '0') self.goThroughTree(H.right, cod=cod + '1') d = dict(self.l) return d #.................................................... def compressOp(self, image, weight, height, dic): bitstring = '' for i in range(height): for j in range(weight): bitstring = bitstring + dic[image[i][j]] arr = [0]*((len(bitstring)//8)+1) index = 0 bitcont = 0 for i in range(len(bitstring)): arr[index] = int(arr[index]) << 1 | int(bitstring[i]) bitcont += 1 if (bitcont == 8): bitcont = 0 index += 1 return arr, index #............................................ #operations to decompress def returnValue(self, H, value): t = value[self.cont] if(H.left == None and H.right == None): self.cont = 0 return H.data else: if(value[self.cont]== '0'): self.cont += 1 self.returnValue(H.left, value) else: self.cont += 1 self.returnValue(H.right, value) def decompressOp(self, file, H): l = [] value = '' filedata = file.readline() for i in filedata: if i != ' ': value = value + i continue a = self.returnValue(H, bin(int(value))) l.append(a) value = '' return l
def yenKSP(graph, source, sink, K): #A is a list containing the shortest path A[0] to A[K -1] A = [] #B is a list containing potential k'th shortest path B = Heap("min", lambda x,y: calcPathCost(x) > calcPathCost(y)) # Determine the shortest path from source to sink A.append(dijkstra(graph,source,sink)) print("k: 0") print(" Shortest path: " + '->'.join([node.key for node in A[0]]) + ", cost = " + str(calcPathCost(A[0]))) for k in range(1, K): print("k: " + str(k)) # The spur node ranges from the first node to the next to last last node in the previous k-shortest path for i in range(len(A[k - 1]) - 1): #spur node is retrieved from the previous k-shortest path, k - 1 spurNode = A[k-1][i] print(" Spur Node: " + spurNode.key) # The sequence of nodes from the source to the spur node of the previous k-shortest path rootPath = A[k-1][0:i+1] print(" Root path: " + '->'.join([node.key for node in rootPath]) + ", cost = " + str(calcPathCost(rootPath))) for path in A: if rootPath == path[0:i+1]: # Remove the links that are part of the previous shortest paths which share the same root path. if path[i].adjList[path[i+1].key]['availability'] == True: path[i].adjList[path[i+1].key]['availability'] = False print(" Removing edge: " + path[i].key + "->" + path[i].adjList[path[i+1].key]['k'].key) for rootPathNode in rootPath: #remove each node in the rootpath excep spur node if rootPathNode != spurNode: rootPathNode.availability = False #Calculate the spur path from the spur node to the sink spurPath = dijkstra(graph, spurNode, sink) if(spurPath != None): print(" Spur path: " + '->'.join([node.key for node in spurPath]) + ", cost = " + str(calcPathCost(spurPath))) spurPath = spurPath[1:] totalPath = rootPath + spurPath print(" Total path: " + '->'.join([node.key for node in totalPath]) + ", cost = " + str(calcPathCost(totalPath))) if not totalPath in B.heap: print(" Inserting Total Path to heap") B.insert(totalPath) else: print(" Path already exists") else: print(" No Spur path found") print() #Resstore edge and nodes that were remove from the graph for vertex in graph: vertex.availability = True for key, adjVertex in vertex.adjList.items(): adjVertex['availability'] = True if len(B.heap) == 0: # This handles the case of there being no spur paths, or no spur paths left. # This could happen if the spur paths have already been exhausted (added to A), # or there are no spur paths at all - such as when both the source and sink vertices # line alone a "dead end" break if len(B.heap) >= K - k + 1: print(" Heap has more than required k path: " + str(len(B.heap))) for _ in range(0, K - k): A.append(B.extract()) break A.append(B.extract()) print(" Shortest path: " + '->'.join([node.key for node in A[k]]) + ", cost = " + str(calcPathCost(A[k]))) return A