有什么方法可以使用自定义权重从OSMNX图形计算NetworkX Dijkstra的算法?

时间:2019-12-13 11:47:40

标签: python networkx openstreetmap dijkstra osmnx

我有以下问题:我想从以前从OSMNX提取的图中获取最短的dijkstra_path。默认情况下,NetworkX的dijkstra_path函数使用OSM边的长度作为权重以获取最短路径。

在我的情况下,我不想使用我添加到OSM边缘的自定义权重获得最短的距离路径,而是最短的路径。

我与您分享代码:

import osmnx as ox
import networkx as nx
import numpy as np

city_graph = ox.graph_from_place('Barcelona, Catalunya, Spain', network_type='bike')
city_nodes, city_edges = ox.graph_to_gdfs(city_graph)

然后,我们添加两个自定义(随机)权重作为新的edge属性,然后考虑不同权重来计算dijkstra最短路径。源节点和目标节点要充分分开,以避免两个节点之间都有唯一的可能路径:

city_edges['test1'] = np.random.randint(1, 30000, city_edges.shape[0])
city_edges['test2'] = np.random.randint(200, 75000, city_edges.shape[0])

length_path = nx.dijkstra_path(city_graph, source = 30237607, target = 30254084, weight = 'length')
test1_path = nx.dijkstra_path(city_graph, source = 30237607, target = 30254084, weight = 'test1')
test2_path = nx.dijkstra_path(city_graph, source = 30237607, target = 30254084, weight = 'test2')

接下来,我们将计算返回路线的三条路线的总重量,以检查路线是否不同:

# LENGTH_PATH

total_length = 0
total_test1 = 0
total_test2 = 0

for i in range(len(length_path)-1):
    total_length = total_length + city_edges.at[city_edges[(city_edges['u']==length_path[i])&(city_edges['v']==length_path[i+1])].index[0], 'length']
    total_test1 = total_test1 + city_edges.at[city_edges[(city_edges['u']==length_path[i])&(city_edges['v']==length_path[i+1])].index[0], 'test1']
    total_test2 = total_test2 + city_edges.at[city_edges[(city_edges['u']==length_path[i])&(city_edges['v']==length_path[i+1])].index[0], 'test2']


# TEST1_PATH

t1_length = 0
t1_test1 = 0
t1_test2 = 0

for i in range(len(test1_path)-1):
    t1_length = t1_length + city_edges.at[city_edges[(city_edges['u']==test1_path[i])&(city_edges['v']==test1_path[i+1])].index[0], 'length']
    t1_test1 = t1_test1 + city_edges.at[city_edges[(city_edges['u']==test1_path[i])&(city_edges['v']==test1_path[i+1])].index[0], 'test1']
    t1_test2 = t1_test2 + city_edges.at[city_edges[(city_edges['u']==test1_path[i])&(city_edges['v']==test1_path[i+1])].index[0], 'test2']


# TEST2_PATH

t2_length = 0
t2_test1 = 0
t2_test2 = 0

for i in range(len(test2_path)-1):
    t2_length = t2_length + city_edges.at[city_edges[(city_edges['u']==test2_path[i])&(city_edges['v']==test2_path[i+1])].index[0], 'length']
    t2_test1 = t2_test1 + city_edges.at[city_edges[(city_edges['u']==test2_path[i])&(city_edges['v']==test2_path[i+1])].index[0], 'test1']
    t2_test2 = t2_test2 + city_edges.at[city_edges[(city_edges['u']==test2_path[i])&(city_edges['v']==test2_path[i+1])].index[0], 'test2']

最后,我们打印这三种路线的结果以检查dijkstra的性能:

print(total_length)
print(t1_length)
print(t2_length)

enter image description here

print(total_test1)
print(t1_test1)
print(t2_test1)

enter image description here

print(total_test2)
print(t1_test2)
print(t2_test2)

enter image description here

因此,如您所见,在weight ='length'和自定义随机权重之间,dijkstra的性能有所不同。但是,当考虑到两个不同的自定义权重时返回的路径是完全相同的,这没有任何意义。我尝试了多个源节点和目标节点,还尝试了不同类型的自定义权重,并且在所有情况下都得到了相同的结果。

要解决此问题,我想知道是否有人可以解释我为什么会发生这种情况,以及在使用两种不同的自定义权重时如何获得两种不同的路径和沿途的总成本。是networkX是从OSM边缘获取自定义最短路径的最佳库,还是我应该使用其他库/软件来这样做?

谢谢!

2 个答案:

答案 0 :(得分:0)

错误不在networks中,而是在创建方式中分配了自定义长度。您无需将自定义长度添加到networkxcity_graph中,而是添加到其他一些变量中。 因此,在执行具有两个自定义长度的Dijkstra算法时,networks不会找到具有给定标签的任何边缘权重,而是采用默认值1,这导致相同的最短路径。

尝试以下最小示例中的方法:

import networkx as nx
import random

random.seed(42)

city_graph = nx.complete_graph(10)

for u,v in city_graph.edges:
    city_graph[u][v]["custom_length"] = random.randint(1, 10)

print(list(city_graph.edges(data=True))[0])
# (0, 1, {'custom_length': 2})

答案 1 :(得分:0)

您需要创建一个包含所有“自定义权重”的新图,然后使用它。 新图(updated_city_graph)可以通过以下方式创建:

updated_city_graph = ox.gdfs_to_graph(city_nodes, city_edges)

然后将其与nx.dijkstra_path()一起使用。

test1_path = nx.dijkstra_path(updated_city_graph, source = 30237607, target = 30254084, weight = 'test1')
test2_path = nx.dijkstra_path(updated_city_graph, source = 30237607, target = 30254084, weight = 'test2')

希望这会有所帮助。