networkx MultiDiGraph access keys of edges making the shortest path

Question:

Using the networkx library, I define a MultDiGraph. I then calculate the shortest path between two given nodes. As my graph holds parallel edges, I would like to know the keys of the edges that make up the shortest path. Here’s an example:

import networkx as nx

G = nx.MultiDiGraph()
G.add_edge('a', 'b', key=0, weight=1)
G.add_edge('a', 'b', key=1, weight=2)
G.add_edge('b', 'c', key=0, weight=1)

shortest_path = nx.shortest_path(G, source='a', target='c')
shortest_path_length = nx.shortest_path_length(G, source='a', target='c')
    
print(shortest_path)
print(shortest_path_length)

The result looks like this:

[‘a’, ‘b’, ‘c’]
2

This is only correct if the shortest path between nodes ‘a’ and ‘b’ is via the key=0 (weight=1). I couldn’t find anything in the docs that would allow me to retrieve the keys of the actual edges involved in the shortest path. How could I get to this information?

Asked By: Johngoldenboy

||

Answers:

Short answer is you cannot. Networkx does not have a functionality that returns the edges that comprise the shortest path. At most it can return the nodes that are in that shortest path.

A work around this is to assume that the edges in the shortest path are the shortest ones, therefore if two nodes in the path can form an edge with a key of either 1 or 0, assume it is the shortest one.

I have faced the same issue as you in: How does osmnx know which edges to plot in shortest path

I used a library called OSMNx and the feature I wanted needed to know which edges make the shortest path. The feature makes the same assumption as I have stated above (you can see the answer to the question)

Answered By: DPM
shortest_path = nx.shortest_path(G, source='a', target='c', weight='weigth')
node_edges = []
for p in nx.utils.pairwise(shortest_path):
    step1 = (G.get_edge_data(*p).items())
    step2 = min([d.get('weight') for k, d in step1])
    node_edges.extend( (k, d) for k, d in step1 if d.get('weight') == step2)
print(note_edges) 

The output is the edge data:

[(0, {‘weight’: 0}), (0, {‘weight’: 1})]

Firstly, nx.utils.pairwise(shortest_path) gets you tuples of node pairs from the list of nodes in the shortest_path, which you can use to get edge data.
In step1 get all possible edges between the nodes.
In step2 find the min weight. In your example the sorting key for weight is easy, a simple min() would do, but a custom sorting based on a different edge attribute is also possible.
Lastly, find the edge where the edge attribute matches step2 and add it to the list of node_edges.
If anyone has a quicker, simpler idea, please let me know.

Answered By: grazynaB
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.