[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/saeedt/PythonGraphSearch/master/MTDalgorithm.py [Back]  [Original]

# Multi Threaded Dijkstra's (MTD) algorithm
import heapq
from os import path
import pandas as pd  # 'pip install pandas' if you get No module named 'pandas' error
# on Python 3.9, pip install pipwin and pipwin install pandas

# loading the graph from the json file located in .\graph folder
dirName = path.dirname(__file__)
fileName = path.join(dirName, 'graph/graph.json')
graph = pd.read_json(fileName)
print('Graph has '+str(len(graph))+' nodes.')
# We only need id, neighbors, and distances columns
graph = graph[['id', 'nbrs', 'dists']]


def findMedian(nodes, weights):  # MTD algorithm
    success = False
    bestDist = float('inf')
    bestId = -1
    # for each node, we use a bit to represent its visited status in each thread
    vis = [0 for i in range(len(graph))]
    # stores distance of the nodes from each of the demand points
    dists = [[0 for i in range(len(nodes))] for j in range(len(graph))]
    maxVis = pow(2, len(nodes))-1  # constant used to verify a node is visited in all threads
    # creating and initializing the priority queue
    pq = []
    index = 0
    for node in nodes:
        heapq.heappush(pq, (0, index, node))
        index += 1
    while (len(pq) > 0 and not success):
        cNode = heapq.heappop(pq)
        vis[cNode[2]] |= pow(2, cNode[1])  # Setting the node visited in its thread
        dists[cNode[2]][cNode[1]] = cNode[0]  # storing the weighted distance
        if (vis[cNode[2]] == maxVis):  # if the node is visited in all threads
            if (sum(dists[cNode[2]]) < bestDist):
                bestDist = sum(dists[cNode[2]])
                bestId = cNode[2]
        if bestDist < cNode[0]:  # optimality criteria
            success = True
            break
        else:
            nbrs = list(zip(graph.iloc[cNode[2], 1], graph.iloc[cNode[2], 2]))
            for id, dist in nbrs:  # iterate over its neighbors
                if (((vis[id] & (pow(2, cNode[1]))) >> cNode[1]) == 0):  # only check unvisited nodes
                    #print([cNode[1], id])
                    nInd = isInQ(pq, cNode[1], id)
                    # if the new node is in the priority queue, we update its weight if the new weight is lower
                    if ((nInd[0] >= 0)):
                        if ((nInd[1] > cNode[0]+weights[cNode[1]]*dist)):
                            pq[nInd[0]] = (cNode[0]+weights[cNode[1]]*dist, cNode[1], id)
                            # if the new weight is less than the current weight, move up and swap with the parent if needed
                            heapq._siftdown(pq, 0, nInd[0])
                    else:  # if the new node is not the priority queue, we push it in
                        heapq.heappush(pq, (cNode[0]+weights[cNode[1]]*dist, cNode[1], id))
    return (bestId, bestDist, dists[bestId])

# searches the queue for an element and if available, returns the (index, weight), otherwise retuns (-1,-1)


def isInQ(q, thread, element):
    index = 0
    while index < len(q):
        if (q[index][1] == thread) and (q[index][2] == element):
            return (index, q[index][0])
        index += 1
    return (-1, -1)


# this is how to call the median function
print(findMedian([0, 4, 2], [1, 1, 1]))

Web Proxy Viewer  |  New URL  |  Original Page