[英]How to get the shortest path between two nodes in a set of routes using NetworkX?
I am using NetworkX graphs to represent a set of routes, as seen in the image below. 我正在使用NetworkX图形表示一组路由,如下图所示。
I know that NetworkX provides shortest_path() to find the shortest path between two nodes in a graph, but I want to find the shortest path considering the set of routes I have available. 我知道NetworkX提供shortest_path()来找到图中两个节点之间的最短路径,但是我想考虑我现有的一组路由来找到最短路径。 There's also weight associated with changing from one route to another.
从一条路线更改为另一条路线也会带来重担。
Right now I'm using different graphs to represent each route, but I'm not sure that's the best approach. 现在,我正在使用不同的图来表示每条路线,但是我不确定这是最好的方法。
For example: the shortest path between nodes 3 and 2 could be using only one route [3, 5, 2]
or using two routes [3, 1]
and [1, 2]
with a cost between them. 例如:节点3和2之间的最短路径可能仅使用一条路由
[3, 5, 2]
或使用两条路由[3, 1]
和[1, 2]
,并且它们之间的开销很大。
Is it possible to achieve this using NetworkX shortest_path
? 是否有可能实现这一目标使用NetworkX
shortest_path
?
Following your idea of having multiple graphs, I'm going to create a large graph consisting of copies of each of the graphs, but also including edges between the corresponding nodes of the graphs you have. 按照您拥有多个图的想法,我将创建一个大型图,该图不仅包含每个图的副本,而且还包含您具有的图的相应节点之间的边。 So for each edge color, there is a graph with all of those edges, and for each node in the original graph there are edges between all of its copies, with some cost associated.
因此,对于每种边缘颜色,都有一个包含所有这些边缘的图形,并且对于原始图形中的每个节点,其所有副本之间都存在边缘,并附带了一些成本。 Now we'll look for paths through this bigger network.
现在,我们将寻找通过这个更大网络的路径。 It's not perfect in the sense that the code is a bit unclean, but it'll work.
从代码有点不干净的意义上来说,这并不是完美的,但是它会起作用。
import networkx as nx
nodes = [0,1,2,3,4, 5, 10, 11]
rednodes = ['r{}'.format(node) for node in nodes] #['r0', 'r1', ...]
rededges = [('r0', 'r1'), ('r1', 'r4'), ('r4', 'r3'), ('r3', 'r5'), ('r5', 'r2')]
bluenodes = ['b{}'.format(node) for node in nodes]
blueedges = [('b1', 'b2')]
orangenodes = ['o{}'.format(node) for node in nodes]
orangeedges = [('o1', 'o3'), ('o3', 'o11'), ('o11', 'o10')]
G = nx.Graph()
G.add_nodes_from(rednodes+bluenodes+orangenodes)
G.add_edges_from(rededges + blueedges + orangeedges, weight = 1)
#here we add edges between the copies of each node
rb_edges = [('r{}'.format(node), 'b{}'.format(node)) for node in nodes]
ro_edges = [('r{}'.format(node), 'o{}'.format(node)) for node in nodes]
bo_edges = [('b{}'.format(node), 'o{}'.format(node)) for node in nodes]
G.add_edges_from(rb_edges+ro_edges+bo_edges, weight = 0.2)
#This next step is a bit of a hack.
#we want a short path from 0 to 11, but I can't be sure which of the colors I should
#start in. So I create a new 0 and 11 node, which connect to its copies with 0 cost.
temporary_edges = [(0, '{}0'.format(c)) for c in ['r', 'b', 'o']] + [(11, '{}11'.format(c)) for c in ['r', 'b', 'o']]
G.add_edges_from(temporary_edges, weight = 0)
best_option = nx.shortest_path(G, 0, 11, weight = 'weight')
G.remove_edges_from(temporary_edges) #get rid of those edges
G.remove_nodes_from([0, 11])
print(best_option)
> [0, 'r0', 'r1', 'o1', 'o3', 'o11', 11]
That helped. 有帮助。 =) I actually created a generic function to create an extended graph, as the number of routes and the routes itself can be different.
=)我实际上创建了一个通用函数来创建扩展图,因为路由数量和路由本身可以不同。 Not sure if it's written in the best way but maybe it can help anyone:
不知道它是否以最佳方式编写,但也许可以帮助任何人:
def create_extended_graph(graph, route_set, transfer_weight):
extended_graph = nx.Graph()
indexes = dict([(node, 0) for node in graph.nodes()])
for route in route_set:
for node in route:
current_node = str(node) + '-' + str(indexes[node])
current_node_index = node
extended_graph.add_node(current_node, original_node=node, index=indexes[node], pos=graph.nodes()[node]['pos'])
if route.index(node) > 0:
tup = tuple(sorted((previous_node_index, current_node_index)))
extended_graph.add_edge(current_node, previous_node, weight=nx.get_edge_attributes(graph, 'weight')[tup])
indexes[node] += 1
previous_node = current_node
previous_node_index = current_node_index
for node in graph.nodes():
extended_nodes = get_list_nodes_from_att(extended_graph, 'original_node', node)
list_combinations = combinations(extended_nodes, 2)
for comb in list_combinations:
extended_graph.add_edge(comb[0], comb[1], weight=transfer_weight)
return extended_graph
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.