【问题标题】:How to get the shortest path between two nodes in a set of routes using NetworkX?如何使用 NetworkX 获得一组路由中两个节点之间的最短路径?
【发布时间】:2018-10-17 20:09:31
【问题描述】:

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

我知道 NetworkX 提供了 shortest_path() 来查找图中两个节点之间的最短路径,但考虑到我可用的一组路线,我想找到最短路径。从一条路线更改为另一条路线也会带来重量。

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

例如:节点 3 和 2 之间的最短路径可能只使用一条路由 [3, 5, 2] 或使用两条路由 [3, 1][1, 2],它们之间存在成本。

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

【问题讨论】:

  • 您能发布输入和所需的输出吗?
  • 我用一个例子编辑了这个问题。我希望我说清楚了。提前谢谢你。 :)
  • 那么使用每条路由会增加 1 的成本?例如使用 [3, 5, 2] 的成本为 1,而使用 [3, 1] + [1, 2] 的成本不是 2?
  • 我很难理解这个问题。基于查看图片,我认为您所说的是有多种边缘类别,我们可以将其视为不同颜色的边缘。每条边都有成本,路径中的每次颜色变化都有成本。你想要最便宜的路径。对吗?
  • @DanielMesejo 不一定,从 [3, 1] + [1, 2] 出发有一个权重,可以认为是路线 [3, 1a, 1b, 2]。

标签: python networkx


【解决方案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]

【讨论】:

    【解决方案2】:

    这有帮助。 =) 我实际上创建了一个通用函数来创建扩展图,因为路线的数量和路线本身可以不同。不确定它是否以最好的方式编写,但也许它可以帮助任何人:

    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
    

    【讨论】:

      猜你喜欢
      • 2017-11-17
      • 2016-03-04
      • 2021-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多