Example #1
0
 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)
Example #2
0
 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)
Example #3
0
 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())
Example #4
0
    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)
Example #7
0
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