我正在使用NetworkX图形表示一组路由,如下图所示。
我知道NetworkX提供shortest_path()来找到图中两个节点之间的最短路径,但是我想考虑我拥有的一组路由来找到最短路径。从一条路线更改为另一条路线也有很大的分量。
现在,我正在使用不同的图形来表示每条路线,但是我不确定这是最好的方法。
例如:节点3和2之间的最短路径可能仅使用一条路由[3, 5, 2]
,也可能使用两条路由[3, 1]
和[1, 2]
,它们之间的开销是<。 / em>
是否可以使用NetworkX shortest_path
实现这一目标?
答案 0 :(得分:1)
按照拥有多个图形的想法,我将创建一个大型图形,该图形既包含每个图形的副本,又包括您所拥有的图形的相应节点之间的边。因此,对于每种边缘颜色,都有一个包含所有这些边缘的图形,并且对于原始图形中的每个节点,其所有副本之间都存在边缘,并附带了一些成本。现在,我们将寻找通过这个更大网络的路径。从代码有点不干净的意义上来说,这并不是完美的,但它会起作用。
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]
答案 1 :(得分:0)
那有帮助。 =)我实际上创建了一个通用函数来创建扩展图,因为路由数量和路由本身可以不同。不知道它是否以最好的方式编写,但也许可以帮助任何人:
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