Exemple #1
0
    def prioritySearch_PQbinaryHeap(self):
        """
            This algorithm executes a prioritySearch 
            based on the genericSearch of a graph. 
            It uses a list to represent the visit of the graph and
             a Binary Heap as priority queue for the nodes to explore.
            :return: the list of the exploration.
            """
        pq = PQbinaryHeap()
        exploredNodes = []
        enqueuedVertices = []

        s = self.maxWeight()
        ID = s[0]
        KEY = -(s[1])
        pq.insert(ID, KEY)
        enqueuedVertices.append(ID)

        while not pq.isEmpty():
            u = pq.findMin()
            pq.deleteMin()

            exploredNodes.append(u)

            for ID in self.getAdj(u):
                node = self.getNode(ID)
                KEY = -(node.getWeight())
                if ID not in enqueuedVertices:
                    pq.insert(ID, KEY)
                    enqueuedVertices.append(ID)

        return exploredNodes
Exemple #2
0
    def prim(graph):
        """Algoritmo di Prim per la ricerca del minimo albero ricoprente.

        Variante che utilizza un albero binario per la gestione della frontiera
        tramite coda con priorita'.
        """
        n = len(graph.nodes)
        currentWeight = n * [INFINITE]  #imposta il peso degli archi a infinito
        pq = PriorityQueue()  #rappresenta la frontiera dell'albero generato
        root = 0  #scelgo arbitrariamente il nodo 0 come radice
        currentWeight[root] = 0

        mstNodes = set()  #insieme dei nodi correnti inclusi nella soluzione

        #inizializzazione dell'albero
        treeNode = TreeArrayListNode(root)
        tree = TreeMod(treeNode)
        mstNodes.add(root)

        #inizializzazione pq
        pq.insert((root, Edge(root, root, 0)), 0)  #triviale
        mstWeight = 0

        while not pq.isEmpty():
            vertex = pq.findMin()
            pq.deleteMin()
            if (vertex[0]) not in mstNodes:  #nodo non ancora aggiunto al mst
                #aggiornare albero e peso mst
                connectingEdge = vertex[1]
                treeNode = TreeArrayListNode(vertex[0])
                father = tree.foundNodeByElem(connectingEdge.tail)
                father.sons.append(treeNode)
                treeNode.father = father
                mstNodes.add(vertex[0])
                mstWeight += connectingEdge.weight
            #print(currentWeight)

            currNode = graph.inc[vertex[0]].getFirstRecord()
            while currNode != None:  #scorre tutti gli archi incidenti
                #semplici variabili per semplificare il codice
                edge = currNode.elem
                head = edge.head
                tail = edge.tail
                weight = edge.weight
                currWeight = currentWeight[head]

                if head not in mstNodes:  #inserisco solo i nodi che portano
                    #verso vertici non ancora scelti
                    pq.insert((head, edge), weight)
                    if currWeight == INFINITE:
                        currentWeight[head] = weight
                    elif weight < currWeight:
                        currentWeight[head] = weight
                currNode = currNode.next
        return mstWeight, tree
Exemple #3
0
    def Dijkstra(graph, root):
        n = len(graph.nodes)
        currentWeight = n * [INFINITE]  #imposta il peso degli archi a infinito
        pq = PriorityQueue()  #rappresenta la frontiera dell'albero generato
        currentWeight[root] = 0

        mstNodes = set()  #insieme dei nodi correnti inclusi nella soluzione

        #inizializzazione dell'albero
        treeNode = TreeArrayListNode(root)
        tree = TreeMod(treeNode)
        mstNodes.add(root)

        #inizializzazione pq
        pq.insert((root, Edge(root, root, 0)), 0)  #triviale
        mstWeight = 0

        while not pq.isEmpty():
            vertex = pq.findMin()
            pq.deleteMin()
            if (vertex[0]) not in mstNodes:  #nodo non ancora aggiunto
                #aggiornare albero e peso mst
                connectingEdge = vertex[1]
                treeNode = TreeArrayListNode(vertex[0])
                father = tree.foundNodeByElem(connectingEdge.tail)
                father.sons.append(treeNode)
                treeNode.father = father
                mstNodes.add(vertex[0])
                mstWeight += connectingEdge.weight
            #print(currentWeight)

            currNode = graph.inc[vertex[0]].getFirstRecord()
            while currNode != None:  #scorre tutti gli archi incidenti
                #semplici variabili per semplificare il codice
                edge = currNode.elem
                head = edge.head
                tail = edge.tail
                weight = edge.weight
                currWeight = currentWeight[head]
                distTail = currentWeight[tail]
                if head not in mstNodes:  #inserisco solo i nodi che portano
                    #verso vertici non ancora scelti
                    pq.insert((head, edge), distTail + weight)
                    if currWeight == INFINITE:
                        currentWeight[head] = distTail + weight
                    elif distTail + weight < currWeight:
                        currentWeight[head] = distTail + weight
                currNode = currNode.next
        return currentWeight
Exemple #4
0
def prim(graph):
    """
    Prim's algorithm is a greedy algorithm for the computation of the
    Minimum Spanning Tree (MST).
    The algorithm assumes a graph implemented as incidence list.
    This implementation leverages the BinaryTree and PriorityQueue data
    structures.
    ---
    Time Complexity: O(|E|*log(|V|)
    Memory Complexity: O(|E|)

    :param graph: the graph.
    :return the MST, represented as a tree.
    """
    # initialize the root
    root = 0

    # initialize the tree
    tree = Tree(TreeNode(root))  # MST as a tree
    mst_nodes = {root}  # nodes added to MST

    # initialize weights
    current_weight = len(graph.nodes) * [INFINITE]
    current_weight[root] = 0
    mst_weight = 0

    # initialize the frontier (priority-queue)
    pq = PriorityQueue()
    pq.insert((root, Edge(root, root, 0)), 0)

    # while the frontier is not empty ...
    while not pq.isEmpty():
        # pop from the priority queue the node u with the minimum weight
        pq_elem = pq.popMin()
        node = pq_elem[0]
        # if node u not yet in MST, update the tree
        if node not in mst_nodes:
            edge = pq_elem[1]
            tree_node = TreeNode(node)
            tree_father = tree.foundNodeByElem(edge.tail)
            tree_father.sons.append(tree_node)
            tree_node.father = tree_father
            mst_nodes.add(node)
            mst_weight += edge.weight

        # for every edge (u,v) ...
        curr = graph.inc[node].getFirstRecord()
        while curr is not None:
            edge = curr.elem  # the edge
            head = edge.head  # the head node of the edge
            # if node v not yet added into the tree, push it into the priority
            # queue and apply the relaxation step
            if head not in mst_nodes:
                weight = edge.weight
                pq.insert((head, edge), weight)
                # relaxation step
                if current_weight[head] > weight:
                    current_weight[head] = weight
            curr = curr.next

    return mst_weight, tree
def Dijkstra(graph, root):
    """
    Dijkstra's algorithm for the computation of the shortest path.
    The algorithm assumes a graph implemented as incidence list.
    This implementation leverages the BinaryTree and PriorityQueue data
    structures.
    ---
    Time Complexity: O(|E|*log(|V|))
    Memory Complexity: O()

    :param graph: the graph.
    :param root: the root node to start from.
    :return: the shortest path.
    """
    n = len(graph.nodes)

    # initialize weights:
    # d[i] = inf for every i in E
    # d[i] = 0, if i == root
    currentWeight = n * [INFINITE]
    currentWeight[root] = 0

    # initialize the tree
    tree = Tree(TreeNode(root))
    mstNodes = {root}
    mstWeight = 0

    # initialize the frontier (priority queue)
    pq = PriorityQueue()
    pq.insert((root, Edge(root, root, 0)), 0)

    # while the frontier is not empty ...
    while not pq.isEmpty():
        # pop from the priority queue the node u with the minimum weight
        pq_elem = pq.popMin()
        node = pq_elem[0]
        # if node not yet in the tree, update the tree
        if node not in mstNodes:
            edge = pq_elem[1]
            treeNode = TreeNode(node)
            father = tree.foundNodeByElem(edge.tail)
            father.sons.append(treeNode)
            treeNode.father = father
            mstNodes.add(node)
            mstWeight += edge.weight

        # for every edge (u,v) ...
        curr = graph.inc[node].getFirstRecord()
        while curr is not None:
            edge = curr.elem  # the edge
            head = edge.head  # the head node of the edge
            # if node v not yet added into the tree, push it into the priority
            # queue and apply the relaxation step
            if head not in mstNodes:
                tail = edge.tail
                weight = edge.weight
                currWeight = currentWeight[head]
                distTail = currentWeight[tail]
                pq.insert((head, edge), distTail + weight)
                # relaxation step
                if currWeight == INFINITE:
                    currentWeight[head] = distTail + weight
                elif distTail + weight < currWeight:
                    currentWeight[head] = distTail + weight
            curr = curr.next

    return currentWeight
Exemple #6
0
def prioritySearchDraw(graph):
    """
    Implementazione modificata di visitaInPriorita' 
    (implementata con binary heap),
    converte il grafo nella struttura Graph della libreria 
    networkx e crea un set di immagini del grafo, tramite
    la libreria matplotlib, evidenziando passo passo i nodi visitati.
    """

    edges = graph.getEdges()
    nodes = graph.getNodes()

    name = 'graphPictures/figure'
    name_n = 0

    edgeCouples = []
    nodesID = []

    for edge in edges:
        edgeCouples.append((edge.head, edge.tail))

    for node in nodes:
        nodesID.append(node.id)

    G = networkx.Graph()
    for nodeID in nodesID:
        G.add_node(nodeID, w=(graph.getNode(0)).getWeight())
    G.add_edges_from(edgeCouples)

    labels = dict.fromkeys(nodesID, 0)
    for key in labels.keys():
        labels[key] = graph.nodes[key].getWeight()

    pos = networkx.spring_layout(G)

    networkx.draw_networkx(G,
                           pos,
                           arrows=True,
                           with_labels=True,
                           node_size=500,
                           labels=labels)

    plt.axis('off')
    outputName = name + str(name_n) + '.png'
    plt.savefig(outputName)
    name_n += 1

    pq = PQbinaryHeap()
    exploredNodes = []

    s = graph.maxWeight()
    ID = s[0]
    KEY = -(s[1])
    pq.insert(ID, KEY)

    while not pq.isEmpty():
        u = pq.findMin()
        pq.deleteMin()

        exploredNodes.append(u)
        networkx.draw_networkx(G,
                               pos,
                               arrows=True,
                               with_labels=True,
                               node_size=500,
                               labels=labels)
        networkx.draw_networkx_nodes(G,
                                     pos,
                                     nodelist=exploredNodes,
                                     node_color='b',
                                     node_size=500)

        plt.axis('off')
        outputName = name + str(name_n) + '.png'
        plt.savefig(outputName)
        name_n += 1

        for vertex in graph.getAdj(u):
            ID = vertex
            KEY = -(graph.getNodes()[vertex].getWeight())
            if ID not in exploredNodes:
                pq.insert(ID, KEY)

    return exploredNodes