如何使用NetworkX获得一组路由中两个节点之间的最短路径?

时间:2018-10-17 20:09:31

标签: python networkx

我正在使用NetworkX图形表示一组路由,如下图所示。

Set of Routes

我知道NetworkX提供shortest_path()来找到图中两个节点之间的最短路径,但是我想考虑我拥有的一组路由来找到最短路径。从一条路线更改为另一条路线也有很大的分量。

现在,我正在使用不同的图形来表示每条路线,但是我不确定这是最好的方法。

例如:节点3和2之间的最短路径可能仅使用一条路由[3, 5, 2],也可能使用两条路由[3, 1][1, 2],它们之间的开销是<。 / em>

是否可以使用NetworkX shortest_path实现这一目标?

2 个答案:

答案 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