从理论到实现,需要数据、需要代码、需要运气
以node / link文件表征的道路网络-----dijkstra算法yyds-----基于南京公路公开数据做路径规划(上)
基本讲清楚了最短路算法的基本原理
下面主要做几件事:
①把node和link文件导入
②把有效字段输入算法
③输出我想要的结果
核心算法如下:
import pandas as pd
import numpy as np
import seaborn as sns
sns.set(style="ticks", color_codes=True)
def dijkstra(start, adjacency_matrix):
passed = [start]
nopass = [x for x in range(len(adjacency_matrix)) if x != start]
dis = adjacency_matrix[start]
while len(nopass):
idx = nopass[0]
for i in nopass:
if dis[i] < dis[idx]:
idx = i
nopass.remove(idx)
passed.append(idx)
for i in nopass:
if dis[idx] + adjacency_matrix[idx][i] < dis[i]:
dis[i] = dis[idx] + adjacency_matrix[idx][i]
route_list_index[i].append(idx)
return dis
下面就是些导入数据之类的:
class ReadData:
def __init__(self, node, link): # 类属性
self.node = 'node.csv'
self.link = 'link.csv'
def read_node(self):
self.node_list = []
with open(self.node, "r") as fl_node:
df_node = pd.read_csv(fl_node)
for i in range(0, len(df_node)):
a = Node()
a.node_id = df_node.loc[i, "node_id"]
a.x = df_node.loc[i, "x_coord"]
a.y = df_node.loc[i, "y_coord"]
self.node_list.append(a)
# print("读取的node结果为:")
# print(df_node)
# 看看数据有没有导入成功是个好习惯,后续的该类做法,就作为中间过程,不保留了
def read_link(self):
self.link_list = []
with open(self.link, "r") as fl_link, open(self.node, "r") as fl_node:
df_link = pd.read_csv(fl_link)
df_node = pd.read_csv(fl_node)
# link_uni_lst = list(pd.unique(df_link["link_id"]))
node_uni_lst = list(pd.unique(df_node["node_id"]))
for i in range(0, len(df_link)):
# print("read link", i/len(df_link))
b = Link()
b.link_id = df_link.loc[i, "link_id"]
b.length = df_link.loc[i, "length"]
b.lanes = df_link.loc[i, "lanes"]
b.free_speed = df_link.loc[i, "free_speed"]
b.from_node_id = df_link.loc[i, "from_node_id"]
b.to_node_id = df_link.loc[i, "to_node_id"]
b.spend_time = df_link.loc[i, "length"] / (df_link.loc[i, "free_speed"]/3.6)
from_node = self.node_list[node_uni_lst.index(b.from_node_id)]
from_node.flow_out_link.append(b.link_id)
from_node.flow_out_node.append(b.to_node_id)
to_node = self.node_list[node_uni_lst.index(b.to_node_id)]
to_node.flow_in_link.append(b.link_id)
to_node.flow_in_node.append(b.from_node_id)
self.link_list.append(b)
class Node:
def __init__(self):
self.node_id = None
self.x = None
self.y = None
self.flow_in_link = []
self.flow_out_link = []
self.flow_in_node = []
self.flow_out_node = []
class Link:
def __init__(self):
self.link_id = None
self.length = None
self.lanes = None
self.free_speed = None
self.from_node_id = None
self.to_node_id = None
self.spend_time = None
network = ReadData(0, 0)
print(network.read_node())
print(network.read_link())
print()
node_uni = list(pd.unique(pd.read_csv('node.txt')["node_id"]))
link_uni = list(pd.unique(pd.read_csv('link.txt')["link_id"]))
size = len(node_uni)
dis = np.ones((size, size))*100000
for i in range(0, len(network.link_list)):
dis[node_uni.index(network.link_list[i].from_node_id), node_uni.index(network.link_list[i].to_node_id)] = network.link_list[i].length
for i in range(0, size):
dis[i, i] = 0
start_id = 5653 # 这里是起点编号
end_id = 2916 # 这里是终点编号
start_node_index = node_uni.index(start_id)
end_node_index = node_uni.index(end_id)
route_list_index = [[] for i in range(0, size)]
route_list_id = []
distance_list = dijkstra(start_node_index, dis)
k = route_list_index[end_node_index][0]
while k != start_node_index:
print(node_uni[k])
route_list_id.append(node_uni[k])
if len(route_list_index[k]) != 0:
k = route_list_index[k][0]
else:
k = start_node_index
route_list_id.append(start_id)
route_list_id.reverse()
route_list_id.append(end_id)
至此算法运算结束
那就输出我们想要的结果吧:
print('起点标号:', start_id, ',在储存结构中的索引:', start_node_index)
print('终点标号:', end_id, ',在储存结构中的索引:', end_node_index)
#print('两点之间的距离为', distance_list[end_node_index], '米')
print('两点之间的路径为', route_list_id)
完事儿
下一篇讲我和代码的辛酸故事,代码复现不了的原因,或许在后面