0

I want to compute the Dijkstra's shortest path in a weighted graph to compute the average value of the weights. I didn't found anything useful in the web, so please help me because I think this could be useful not just for me.

I have a list of dictionaries:

list_of_dictionaries=  [
    {"RA":"1","RB":"2","SPEED":"100"}
    ...
    {"RA":"1","RB":"8250","SPEED":"150"}
    {"RA":"2","RB":"3","SPEED":"120"}
    ...
    {"RA":"2","RB":"8250","SPEED":"150"}
    ...
    ...
    {"RA":"350","RB":"351","SPEED":"130"}
    ...
    ...        
]

I create a weighted undirected graph and then use Dijkstra shortest path to compute the average speed (not the total speed). Let's start:

import networkx as nx
graph = nx.Graph()
for row in list_of_dictionaries:
     source = row['RA']
     target = row['RB']
     if not graph.has_node(source):
        graph.add_node(source)
     if not graph.has_node(target):
        graph.add_node(target)
     graph.add_edge(source, target, speed=float(row['SPEED']))

I have checked that the graph is CONNECTED and it is! Now I first get the path which contains the list of nodes (not edges), then I take two nodes at a time, I check into the graph the weight (speed) of the edge created with the two nodes. I repeat this procedure for all the nodes in the path and then I compute the average speed.

This is of course very time consuming and inefficient

tot_speed = 0.0
path = nx.dijkstra_path(graph, source, target, 'speed')

for k, node in enumerate(path[:-1]):
    n1 = path[k]
    n2 = path[k + 1]
    speed = graph[n1][n2]['speed']
    tot_speed += speed
avg_speed = tot_speed / len(path)-1 

As you can see this is not a good way of doing and there are two main issues:

1) if I try nx.dijkstra_path(graph, 1, 1, 'speed') I have troubles because the denominator in the avg_speed formula is zero.

2) The for loop is really a messy

If you have a better idea, please let me know your point of view. Thanks.

piezzoritro
  • 141
  • 2
  • 14
  • Why do you want to use Dijkstra's algorithm? You want to take the average speed values over all edges, so just iterate over the edges: `sum(d["SPEED"] for d in list_of_dictionaries) / len(list_of_dictionaries)` – pschill May 04 '17 at 10:31
  • no because actually the list is composed by N rows and I want to compute the average speed just among a subset of N – piezzoritro May 04 '17 at 10:34
  • Ah, so you want to compute the average speed values over the edges of a given path. Only a single path? Or all shortest paths between all pairs of nodes? – pschill May 04 '17 at 11:07
  • exactly! only one given path – piezzoritro May 04 '17 at 11:24
  • 1
    I do not think you can get much better performance from an algorithmic point of view. To address your second issue: The for loop could be replaced with `tot_speed = sum(graph[a][b]["speed"] for a, b in zip(path[:-1], path[1:]))`. – pschill May 04 '17 at 11:40
  • Ok I'll try later, then I'll give you a feedback. Thank you for now! – piezzoritro May 04 '17 at 11:44
  • @pschill I tried and it works pretty well. Thank you – piezzoritro May 04 '17 at 22:35

0 Answers0