OSMNX中如何实现同时按路径长度与通行时间优化路线?
距离与通行时间联合优化最优路线实现方案
OSMnx的最短路径接口底层依赖NetworkX的单源最短路径算法,仅支持单一边权重输入,要同时优化距离、通行时间两个目标,最易落地的方案是将两个维度的属性做归一化后,按偏好权重融合为单一边权重,再传入最短路径接口计算即可。
核心实现步骤
- 先对边的长度、通行时间做Min-Max归一化,消除两个属性的量纲、数值量级差异,避免某一属性完全主导权重结果
- 根据自身优化偏好设置两个目标的权重占比(两个权重之和为1):
- 偏好更快到达:调高通行时间的权重占比
- 偏好更短路程:调高距离的权重占比
- 两个目标同等重要:两个权重各设为0.5
- 为路网每条边计算融合后的自定义组合权重
- 调用最短路径接口时,将
weight参数指定为自定义的组合权重字段即可
如果需要获取所有严格帕累托最优的路线(即不存在另一条路线同时比当前路线更短、更快),可以将通行时间的权重占比从0到1按固定步长遍历,每次计算对应路线后去重,就能得到帕累托前沿上的所有候选路线。
可直接运行的修改后代码
import numpy as np import osmnx as ox origin = (-33.4667,-70.7208) destiny = (-33.367204, -70.506080) # 若路网未预先计算通行时间属性,先执行以下两行 # graph = ox.add_edge_speeds(graph) # graph = ox.add_edge_travel_times(graph) # -------------------------- # 自定义组合权重计算逻辑 # -------------------------- # 提取全图边的属性值用于归一化 all_edge_lengths = [] all_edge_times = [] for _, _, edge_data in graph.edges(data=True): all_edge_lengths.append(edge_data["length"]) all_edge_times.append(edge_data["time"]) # 计算归一化基准值 len_min, len_max = np.min(all_edge_lengths), np.max(all_edge_lengths) time_min, time_max = np.min(all_edge_times), np.max(all_edge_times) # 设置两个目标的权重占比,可按需调整,二者之和必须为1 alpha = 0.6 # 通行时间权重占比60% beta = 0.4 # 距离权重占比40% # 为每条边生成融合后的组合权重 for _, _, edge_data in graph.edges(data=True): norm_len = (edge_data["length"] - len_min) / (len_max - len_min) norm_time = (edge_data["time"] - time_min) / (time_max - time_min) edge_data["combined_weight"] = alpha * norm_time + beta * norm_len # -------------------------- orig_node = ox.distance.nearest_nodes(graph, origin[1], origin[0]) target_node = ox.distance.nearest_nodes(graph, destiny[1], destiny[0]) # 最短路径计算使用自定义的组合权重 route = ox.distance.shortest_path(graph, orig_node, target_node, weight="combined_weight") length = int(sum(ox.utils_graph.get_route_edge_attributes(graph, route, "length"))) time = int(sum(ox.utils_graph.get_route_edge_attributes(graph, route, "time"))) print('Distancia: ',length/1000,' km') print('Tiempo: ',time/60,' min') ox.folium.plot_route_folium(graph, route, route_map=None, popup_attribute=None, tiles='cartodbpositron', zoom=1, fit_bounds=True)
注意:不可跳过归一化步骤。如果直接将原始单位的长度、时间数值相加,米级的长度数值会远大于秒级的时间数值,最终权重会完全被距离主导,无法达到联合优化的效果。
内容的提问来源于stack exchange,提问作者Jorge Esteban Reyes Marambio
相关产品推荐
相关产品推荐

