1

I'm using Python 3 and Networkx 1.11.

I make a weighted graph, with weights on the edges and some nodes, but when I calculate the weight of a shortest path, the weight of the node is not taken into account (code below).

Anyone know how to ensure the node weight is considered?

Thanks! Sam

import networkx as nx
from matplotlib import pyplot as plt


# Set up a station map
all_stations = ['a','b','c','d','e']
interchange_stations = ['b']
routes = {'a':{'b':2}, 'c':{'b':2}, 'b':{'d':2}, 'd':{'e':2}}
print(routes)


# Make a network graph
G = nx.Graph()

# Add all the nodes (stations)
for station in all_stations:
    weight = 0
    if station in interchange_stations:
        weight = 5
    G.add_node(station, weight=weight)
print(G.nodes(data=True))


# Iterate through each line and add the time between stations  
for name1, value in routes.items():
    for name2, time in value.items():
        if name1 == name2:
            continue
        G.add_edge(name1, name2, weight=time)
print(G.edges(data=True))


# Work out the minimium distance between all stops
route_times = nx.all_pairs_dijkstra_path_length(G)

# Work out the minimum path between all stops
route = nx.all_pairs_dijkstra_path(G)

print(route['a']['e']) # Returns: ['a', 'b', 'd', 'e']
print(route_times['a']['e']) # Returns: 6 (should be 2+2+2+5)
Sam Short
  • 183
  • 1
  • 1
  • 9
  • I want the algo to consider all the weights, so in this example, +2 for every edge and +5 for node 'b' – Sam Short Mar 06 '18 at 17:19
  • NetworkX has a [shortest_path](https://networkx.github.io/documentation/networkx-1.10/reference/generated/networkx.algorithms.shortest_paths.generic.shortest_path.html#networkx.algorithms.shortest_paths.generic.shortest_path) method that considers weight. – Scott Boston Mar 06 '18 at 17:21
  • err... You answer should be six. Short path is a->b, b->d, d->e, 2+2+2 = 6 – Scott Boston Mar 06 '18 at 17:28
  • My understanding is that `shortest_path` is for unweighted graphs (I also just checked and it returns the correct path, but a weight of 3 => no weights), whereas the the `dijkstra_path` considers the edge weights. I just need a way of also considering the node weights. – Sam Short Mar 06 '18 at 17:28
  • My answer should be 11: 2+2+2+5 (weight of node b is 5) – Sam Short Mar 06 '18 at 17:29
  • Ah... I see. What you want now. – Scott Boston Mar 06 '18 at 17:30
  • You need shortest path considering edge weights and node weights (some attribute associated to node data). You might have to write this as custom function. – Scott Boston Mar 06 '18 at 17:33

1 Answers1

3

In the documentation for dijkstra_path, we have dijkstra_path(G, source, target, weight='weight') where weight could be a function of the two nodes and the edge. Here is the example provided:

The weight function can be used to include node weights.

def func(u, v, d):
    node_u_wt = G.nodes[u].get('node_weight', 1)
    node_v_wt = G.nodes[v].get('node_weight', 1)
    edge_wt = d.get('weight', 1)
    return node_u_wt/2 + node_v_wt/2 + edge_wt

In this example we take the average of start and end node weights of an edge and add it to the weight of the edge.

This will include the full value of every intermediate node and half of the two end nodes.

You can modify the function to be node_u_wt + edge_wt. Then a path will include the weight of each edge and the weight of each node that is the base of an edge encountered in the path. (so it will include the full weight of the start and every intermediate node, but not the final node).


Another workaround is to create a directed graph H where the edge weight for edge u to v is given to be the sum of the weight of u and the weight of the edge in G

Or you can make the weight of the edge be the sum of the weight of v and the weight of the edge, as long as you're consistent about whether you include the base or target. So the path gets that penalty regardless of whether it's added on entering or leaving the node. You may need to be a bit careful about whether the final weight of the path includes the base node or target node.

Joel
  • 22,598
  • 6
  • 69
  • 93