实验目的
运用各种编程语言实现基于 Dijkstra 算法的路由软件。
实验环境
系统:Mac OS X 10.13.1
语言:Python 3.6.5
平台:pycharm
外部库:networkx,matplotlib
实验过程
代码设计
现Dijkstra算法的方法有很多种,为了在最短的代码内实现最好的效果,我选择了python来实现,借助networkx的有向图类DiGrapg接口实现了图的存储,通过自己实现的Dijkstra算法完成了搜索。
图的构造
我们这里借助networkx库里的DiGraph类来构造有向图。DiGraph存储有向图的边的形式为形如(s,d,w)的三元组形式,其中:
s: 边的起点;
d: 边的终点;
w: 边的代价.
考虑到操作的便捷性,我们使用一个path.txt文件来实现图的各个边的三元组的存储,path.txt的格式如下:
定义好边的数据结构之后,我们利用networkx中的函数add_edge()来实现边的输入和图的构建
1 | for line in open("path.txt","r"): #按行读取文件 |
Dijkstra算法
算法实现的流程图如下:
演示部分
networkx库同样集成了图的绘制函数,我们通过与matplotlib库的协同操作来完成图的搜索演示。
通过以下代码来实现图的分屏:1
2
3plt.figure(figsize=(14, 6))
plt.subplot(121)
plt.subplot(122)
通过以下代码来实现初始图的绘制:1
2pos = nx.spring_layout(G)
nx.draw_networkx(G, pos,node_size=300,node_color='#FFB5C5')
通过以下代码来实现图上搜索路径的绘制:1
2
3
4
5
6# 绘制非路径上的边
edges_not_in_path = list(set(G.edges()) - set(edges))
edgewidth = [G.get_edge_data(edge[0], edge[1])['weight']/30 for edge in edges_not_in_path]
nx.draw_networkx_edges(G, pos, edgelist=edges_not_in_path, edge_color='b',width=edgewidth)
# 绘制路径上的边
edgewidth = [G.get_edge_data(edge[0], edge[1])['weight']/30 for edge in edges]
nx.draw_networkx_edges(G,pos,edgelist=edges,edge_color='r',width=edgewidth)
执行结果
我们这里把网络类比为一个有向图,事实上路由的传输方向可以是双向的。
其中,图‘Test Graph’即为初始图;
对于图‘The shortest path from 0 to 6’:
红色边:通过Dijkstra算法搜索到的最小代价路径;
蓝色边:未采纳的边;
边的粗细程度:边的权值,越细代表权值越小.
为了验证我们得到的路径是否是正确的答案,我们使用networkx库中标准的函数进行检验,代码如下:answer=nx.dijkstra_path(G,source=start_node,target=end_node)
可以得到输出的answer路径如下,与我们的代码所得出的答案相同:
代码附录
1 | import networkx as nx |