NetworkX系列教程(10)-算法之一:最短路径问题

摘要:
将库文件导入。11.图相关算法11.1最短路径11.1.1无向图和有向图#定义并绘制图G=nx。路径_图形(5)nx.add _路径(G,fontproperties=myfont)plt。轴(“on”)plt。xticks([])plt公司。催化([])树脂。show()#计算最短路径打印('0节点到4节点最短路径:
小书匠Graph图论

重头戏部分来了,写到这里我感觉得仔细认真点了,可能在NetworkX中,实现某些算法就一句话的事,但是这个算法是做什么的,用在什么地方,原理是怎么样的,不清除,所以,我决定先把图论中常用算法弄个明白在写这部分.

图论常用算法看我的博客:

下面我将使用NetworkX实现上面的算法,建议不清楚的部分打开两篇博客对照理解.
我将图论的经典问题及常用算法的总结写在下面两篇博客中:
图论---问题篇
图论---算法篇

目录:


注意:如果代码出现找不库,请返回第一个教程,把库文件导入.

11.Graph相关算法

11.1最短路径

11.1.1无向图和有向图

  1. #定义并画出该图 

  2. G = nx.path_graph(5) 

  3. nx.add_path(G,[0,5,2]) 

  4. nx.add_path(G,[0,6,4]) 

  5. nx.draw(G,with_labels=True) 

  6. plt.title('无向图',fontproperties=myfont) 

  7. plt.axis('on') 

  8. plt.xticks([]) 

  9. plt.yticks([]) 

  10. plt.show() 

  11.  

  12. #计算最短路径 

  13. print('0节点到4节点最短路径: ',nx.shortest_path(G, source=0, target=4)) 

  14. p1 = nx.shortest_path(G, source=0) 

  15. print('0节点到所有节点最短路径: ',p1) 

  16.  

  17. #计算图中所有的最短路径 

  18. print('计算图中节点0到节点2的所有最短路径: ',[p for p in nx.all_shortest_paths(G, source=0, target=2)]) 

  19.  

  20. #计算最短路径长度 

  21. p2=nx.shortest_path_length(G, source=0, target=2) #最短路径长度 

  22. p3=nx.average_shortest_path_length(G) #计算平均最短路径长度 

  23. print('节点0到节点2的最短路径长度:',p2,' 平均最短路径长度: ',p3) 

  24.  

  25. #检测是否有路径 

  26. print('检测节点0到节点2是否有路径',nx.has_path(G,0,2)) 

无向图和有向图最短路径示例
无向图和有向图最短路径示例

输出:

  1. 0节点到4节点最短路径: [0, 6, 4] 

  2. 0节点到所有节点最短路径: {0: [0], 1: [0, 1], 2: [0, 1, 2], 3: [0, 1, 2, 3], 4: [0, 6, 4], 5: [0, 5], 6: [0, 6]} 

  3. 计算图中节点0到节点2的所有最短路径: [[0, 1, 2], [0, 5, 2]] 

  4. 节点0到节点2的最短路径长度: 2 平均最短路径长度: 1.8095238095238095 

  5. 检测节点0到节点2是否有路径 True 


11.1.2无权图

  1. G = nx.path_graph(3) 

  2. nx.draw(G,with_labels=True) 

  3. plt.title('无权图',fontproperties=myfont) 

  4. plt.axis('on') 

  5. plt.xticks([]) 

  6. plt.yticks([]) 

  7. plt.show() 

  8.  

  9. path1 = nx.single_source_shortest_path(G, 0) #计算当前源与所有可达节点的最短路径 

  10. length1 = nx.single_source_shortest_path_length(G, 0) #计算当前源与所有可达节点的最短路径的长度 

  11. path2 = dict(nx.all_pairs_shortest_path(G)) #计算graph两两节点之间的最短路径 

  12. length2 = dict(nx.all_pairs_shortest_path_length(G)) #计算graph两两节点之间的最短路径的长度 

  13. prede1=nx.predecessor(G, 0) #返回G中从源到所有节点最短路径的前驱 

  14.  

  15. print('当前源与所有可达节点的最短路径: ',path1,' 当前源与所有可达节点的最短路径的长度: ',length1) 

  16. print(' graph两两节点之间的最短路径: ',path2,' graph两两节点之间的最短路径的长度: ',length2) 

  17. print(' G中从源到所有节点最短路径的前驱: ',prede1) 

无权图
无权图

输出:

  1. 当前源与所有可达节点的最短路径: {0: [0], 1: [0, 1], 2: [0, 1, 2]}  

  2. 当前源与所有可达节点的最短路径的长度: {0: 0, 1: 1, 2: 2} 

  3. graph两两节点之间的最短路径: {0: {0: [0], 1: [0, 1], 2: [0, 1, 2]}, 1: {0: [1, 0], 1: [1], 2: [1, 2]}, 2: {0: [2, 1, 0], 1: [2, 1], 2: [2]}}  

  4. graph两两节点之间的最短路径的长度: {0: {0: 0, 1: 1, 2: 2}, 1: {0: 1, 1: 0, 2: 1}, 2: {0: 2, 1: 1, 2: 0}} 

  5. G中从源到所有节点最短路径的前驱: {0: [], 1: [0], 2: [1]} 


11.1.3有权图(迪杰斯特拉)

  1. G = nx.path_graph(5, create_using = nx.DiGraph())  

  2. nx.draw(G,with_labels=True) 

  3. plt.title('有向图',fontproperties=myfont) 

  4. plt.axis('on') 

  5. plt.xticks([]) 

  6. plt.yticks([]) 

  7. plt.show() 

  8.  

  9. #计算加权图最短路径长度和前驱 

  10. pred, dist = nx.dijkstra_predecessor_and_distance(G, 0) 

  11. print(' 加权图最短路径长度和前驱: ',pred, dist) 

  12.  

  13. #返回G中从源到目标的最短加权路径,要求边权重必须为数值 

  14. print(' G中从源0到目标4的最短加权路径: ',nx.dijkstra_path(G,0,4)) 

  15. print(' G中从源0到目标4的最短加权路径的长度: ',nx.dijkstra_path_length(G,0,4)) #最短路径长度 

  16.  

  17. #单源节点最短加权路径和长度。 

  18. length1, path1 = nx.single_source_dijkstra(G, 0) 

  19. print(' 单源节点最短加权路径和长度: ',length1, path1) 

  20. #下面两条和是前面的分解 

  21. # path2=nx.single_source_dijkstra_path(G,0) 

  22. # length2 = nx.single_source_dijkstra_path_length(G, 0) 

  23. #print(length1,'$', path1,'$',length2,'$',path2) 

  24.  

  25. #多源节点最短加权路径和长度。 

  26. path1 = nx.multi_source_dijkstra_path(G, {0, 4}) 

  27. length1 = nx.multi_source_dijkstra_path_length(G, {0, 4}) 

  28.  

  29. print(' 多源节点最短加权路径和长度:', path1,length1) 

  30.  

  31. #两两节点之间最短加权路径和长度。 

  32. path1 = dict(nx.all_pairs_dijkstra_path(G)) 

  33. length1 = dict(nx.all_pairs_dijkstra_path_length(G)) 

  34. print(' 两两节点之间最短加权路径和长度: ',path1,length1) 

  35.  

  36. #双向搜索的迪杰斯特拉 

  37. length, path = nx.bidirectional_dijkstra(G, 0, 4) 

  38. print(' 双向搜索的迪杰斯特拉:',length, path) 

迪杰斯特拉算法使用
迪杰斯特拉算法使用

输出:

  1. 加权图最短路径长度和前驱: {0: [], 1: [0], 2: [1], 3: [2], 4: [3]} {0: 0, 1: 1, 2: 2, 3: 3, 4: 4} 

  2. G中从源0到目标4的最短加权路径: [0, 1, 2, 3, 4] 

  3. G中从源0到目标4的最短加权路径的长度: 4 

  4. 单源节点最短加权路径和长度: {0: 0, 1: 1, 2: 2, 3: 3, 4: 4} {0: [0], 1: [0, 1], 2: [0, 1, 2], 3: [0, 1, 2, 3], 4: [0, 1, 2, 3, 4]} 

  5. 多源节点最短加权路径和长度: {0: [0], 1: [0, 1], 2: [0, 1, 2], 3: [0, 1, 2, 3], 4: [4]} {0: 0, 1: 1, 2: 2, 3: 3, 4: 0} 

  6. 两两节点之间最短加权路径和长度: {0: {0: [0], 1: [0, 1], 2: [0, 1, 2], 3: [0, 1, 2, 3], 4: [0, 1, 2, 3, 4]}, 1: {1: [1], 2: [1, 2], 3: [1, 2, 3], 4: [1, 2, 3, 4]}, 2: {2: [2], 3: [2, 3], 4: [2, 3, 4]}, 3: {3: [3], 4: [3, 4]}, 4: {4: [4]}} {0: {0: 0, 1: 1, 2: 2, 3: 3, 4: 4}, 1: {1: 0, 2:1, 3: 2, 4: 3}, 2: {2: 0, 3: 1, 4: 2}, 3: {3: 0, 4: 1}, 4: {4: 0}} 

  7. 双向搜索的迪杰斯特拉: 4 [0, 1, 2, 3, 4] 


11.1.4贝尔曼-福特(Bellman-Ford)算法

  1. G = nx.path_graph(5, create_using = nx.DiGraph())  

  2. nx.draw(G,with_labels=True) 

  3. plt.title('有权图',fontproperties=myfont) 

  4. plt.axis('on') 

  5. plt.xticks([]) 

  6. plt.yticks([]) 

  7. plt.show() 

  8.  

  9. print('G中从源到目标的最短加权路径: ',nx.bellman_ford_path(G, 0, 4)) 

  10. print(' G中从源到目标的最短加权路径的长度:',nx.bellman_ford_path_length(G,0,4)) 

  11.  

  12. path1=nx.single_source_bellman_ford_path(G,0) 

  13. length1 = dict(nx.single_source_bellman_ford_path_length(G, 0)) 

  14. print(' 单源节点最短加权路径和长度: ',path1,' 单源节点最短加权路径和长度: ',length1) 

  15.  

  16. path2 = dict(nx.all_pairs_bellman_ford_path(G)) 

  17. length2 = dict(nx.all_pairs_bellman_ford_path_length(G)) 

  18. print(' 两两节点之间最短加权路径和长度: ',path2,length2) 

  19.  

  20. length, path = nx.single_source_bellman_ford(G, 0) 

  21. pred, dist = nx.bellman_ford_predecessor_and_distance(G, 0) 

  22. print(' 加权图最短路径长度和前驱: ',pred,dist) 

贝尔曼-福特(Bellman-Ford)算法使用示例
贝尔曼-福特(Bellman-Ford)算法使用示例

输出:

  1. G中从源到目标的最短加权路径: [0, 1, 2, 3, 4] 

  2. G中从源到目标的最短加权路径的长度: 4 

  3. 单源节点最短加权路径和长度: {0: [0], 1: [0, 1], 2: [0, 1, 2], 3: [0, 1, 2, 3], 4: [0, 1, 2, 3, 4]}  

  4. 单源节点最短加权路径和长度: {0: 0, 1: 1, 2: 2, 3: 3, 4: 4} 

  5. 两两节点之间最短加权路径和长度: {0: {0: [0], 1: [0, 1], 2: [0, 1, 2], 3: [0, 1, 2, 3], 4: [0, 1, 2, 3, 4]}, 1: {1: [1], 2: [1, 2], 3: [1, 2, 3], 4: 

[1, 2, 3, 4]}, 2: {2: [2], 3: [2, 3], 4: [2, 3, 4]}, 3: {3: [3], 4:
[3, 4]}, 4: {4: [4]}} {0: {0: 0, 1: 1, 2: 2, 3: 3, 4: 4}, 1: {1: 0, 2:
1, 3: 2, 4: 3}, 2: {2: 0, 3: 1, 4: 2}, 3: {3: 0, 4: 1}, 4: {4: 0}}
加权图最短路径长度和前驱: {0: [None], 1: [0], 2: [1], 3: [2], 4: [3]} {0: 0, 1: 1, 2: 2, 3: 3, 4: 4}


11.1.5检测负权重边

  1. #定义并画出该图 

  2. G = nx.cycle_graph(5, create_using = nx.DiGraph()) 

  3.  

  4. #添加负权重边前后 

  5. print(nx.negative_edge_cycle(G)) 

  6. G[1][2]['weight'] = -7 

  7. print(nx.negative_edge_cycle(G)) 

输出:

  1. False 

  2. True 


11.1.6使用约翰逊(Johnson)的算法

  1. #生成graph 

  2. G = nx.DiGraph() 

  3. G.add_weighted_edges_from([('0', '3', 3), ('0', '1', -5),('0', '2', 2), ('1', '2', 4), ('2', '3', 1)]) 

  4.  

  5. #边和节点信息 

  6. edge_labels = nx.get_edge_attributes(G,'weight')  

  7. labels={'0':'0','1':'1','2':'2','3':'3'} 

  8.  

  9. #生成节点位置  

  10. pos=nx.spring_layout(G)  

  11.  

  12. #把节点画出来  

  13. nx.draw_networkx_nodes(G,pos,node_color='g',node_size=500,alpha=0.8)  

  14.  

  15. #把边画出来  

  16. nx.draw_networkx_edges(G,pos,width=1.0,alpha=0.5,edge_color='b')  

  17.  

  18. #把节点的标签画出来  

  19. nx.draw_networkx_labels(G,pos,labels,font_size=16)  

  20.  

  21. #把边权重画出来  

  22. nx.draw_networkx_edge_labels(G, pos, edge_labels)  

  23.  

  24. #显示graph 

  25. plt.title('有权图',fontproperties=myfont) 

  26. plt.axis('on') 

  27. plt.xticks([]) 

  28. plt.yticks([]) 

  29. plt.show() 

  30.  

  31. #使用johnson算法计算最短路径 

  32. paths = nx.johnson(G, weight='weight') 

  33.  

  34. print(paths) 

约翰逊(Johnson)的算法使用示例
约翰逊(Johnson)的算法使用示例

输出:

  1. {'2': {'2': ['2'], '3': ['2', '3']}, '3': {'3': ['3']}, '0': {'2': ['0', '1', '2'], '3': ['0', '1', '2', '3'], '0': ['0'], '1': ['0','1']}, '1': {'2': ['1', '2'], '3': ['1', '2', '3'], '1': ['1']}} 


11.1.7弗洛伊德算法(Floyd-Warshall)

  1. #使用Floyd算法找到所有对最短路径长度。 

  2. G = nx.DiGraph() 

  3. G.add_weighted_edges_from([('0', '3', 3), ('0', '1', -5),('0', '2', 2), ('1', '2', 4), ('2', '3', 1)]) 

  4.  

  5. #边和节点信息 

  6. edge_labels = nx.get_edge_attributes(G,'weight')  

  7. labels={'0':'0','1':'1','2':'2','3':'3'} 

  8.  

  9. #生成节点位置  

  10. pos=nx.spring_layout(G)  

  11.  

  12. #把节点画出来  

  13. nx.draw_networkx_nodes(G,pos,node_color='g',node_size=500,alpha=0.8)  

  14.  

  15. #把边画出来  

  16. nx.draw_networkx_edges(G,pos,width=1.0,alpha=0.5,edge_color='b')  

  17.  

  18. #把节点的标签画出来  

  19. nx.draw_networkx_labels(G,pos,labels,font_size=16)  

  20.  

  21. #把边权重画出来  

  22. nx.draw_networkx_edge_labels(G, pos, edge_labels)  

  23.  

  24. #显示graph 

  25. plt.title('有权图',fontproperties=myfont) 

  26. plt.axis('on') 

  27. plt.xticks([]) 

  28. plt.yticks([]) 

  29. plt.show() 

  30.  

  31. #计算最短路径长度 

  32. lenght=nx.floyd_warshall(G, weight='weight') 

  33.  

  34. #计算最短路径上的前驱与路径长度 

  35. predecessor,distance1=nx.floyd_warshall_predecessor_and_distance(G, weight='weight') 

  36.  

  37. #计算两两节点之间的最短距离,并以numpy矩阵形式返回 

  38. distance2=nx.floyd_warshall_numpy(G, weight='weight') 

  39.  

  40. print(list(lenght)) 

  41. print(predecessor) 

  42. print(list(distance1)) 

  43. print(distance2) 

弗洛伊德算法(Floyd-Warshall)使用示例
弗洛伊德算法(Floyd-Warshall)使用示例

输出:

  1. ['2', '3', '0', '1'] 

  2. {'2': {'3': '2'}, '0': {'2': '1', '3': '2', '1': '0'}, '1': {'2': '1', '3': '2'}} 

  3. ['2', '3', '0', '1'] 

  4. [[ 0. 1. inf inf] 

  5. [inf 0. inf inf] 

  6. [-1. 0. 0. -5.] 

  7. [ 4. 5. inf 0.]] 

注:输出中的矩阵不是按照节点0,1,2,3排序,而是2,1,3,0,即如图:

NetworkX系列教程(10)-算法之一:最短路径问题第7张
两点之间的最短距离


11.1.8A*算法

  1. G = nx.path_graph(5) 

  2.  

  3. #显示graph 

  4. nx.draw(G,with_labels=True) 

  5. plt.title('有x向图',fontproperties=myfont) 

  6. plt.axis('on') 

  7. plt.xticks([]) 

  8. plt.yticks([]) 

  9. plt.show() 

  10.  

  11. #直接输出路径和长度 

  12. print(nx.astar_path(G, 0, 4)) 

  13. print(nx.astar_path_length(G, 0, 4)) 

A*算法
A*算法

输出:

  1. [0, 1, 2, 3, 4] 

  2. 4 

免责声明:文章转载自《NetworkX系列教程(10)-算法之一:最短路径问题》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇接口回调之简要理解SmartTimer——一种基于STM32的轻量级时钟调度器下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Python——常用模块

模块,就是一堆实现了某个功能的代码的集合。 一、time & datetime time.time() 返回当前时间的时间戳,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。 1473344512.2949986 time.sleep(秒数) 使用该方法可以让程序休眠n秒,n可以是小数。 time.clock() 计算CPU...

Arcmap10.1下安装ArcBrutile0.2.2 (Win7)(转)

前阵子换了高级新电脑,用的win7旗舰版装了Arcgis10.1,一直没试过ArcBrutile0.2.2能不能用,今天想用的时候发现自己竟然忘记怎么加载这个工具了!!!   网上搜了一下,度娘今天不乖,半天没搜到,于是只好自己回忆一下步骤,记录下来免得又忘记了 (1)当然先是setup.exe,装arcbrutile0.2.2,随便装哪个盘都木有影响,...

JavaScript核心之事件详解(EventTarget接口,js事件传播,Event对象)

事件是一种异步编程的实现方式,本质上是程序各个组成部分之间传递的特定消息。DOM支持大量的事件,本节介绍DOM的事件编程。 1 EventTarget接口DOM的事件操作(监听和触发),都定义在EventTarget接口。Element节点、document节点和window对象,都部署了这个接口。此外,XMLHttpRequest、AudioNode、A...

网格搜素算法的使用

GridSearchCV网格搜索算法, 经常用于调优模型参数,遍历多个模型参数,带入模型,进行训练,从中找出评分最高的模型。 GridSearchCV(参数1,参数2,参数3,参数4=none) 参数1:模型算法   参数2:需要调优的参数 参数3:评分标准 参数4:k折交叉验证法,默认为空 GridSearchCV的方法: grid.best_estim...

传统磁盘I/O调度算法

目前来说,传统的磁盘仍然是主流的存储设备,从传统的硬盘上读取数据分为以下3个步骤。 将磁头移动到磁盘表面的正确位置,花费的时间叫寻道时间。 等待磁盘旋转,需要的数据会移动到磁头下面,花费的时间取决于磁盘的转速,转速越高的磁盘需要的时间越短。 磁盘继续旋转,直到所有需要的数据都经过磁头。 磁盘在做这样动作的时候的快慢可以归结为两个因素:访问时间(步骤1和...

java加解密算法--常见加解密算法

什么是加密算法?百度百科给出的解释如下: 数据加密的基本过程就是对原来为明文的文件或数据按某种算法进行处理,使其成为不可读的一段代码,通常称为“密文”,使其只能在输入相应的密钥之后才能显示出本来内容,通过这样的途径来达到保护数据不被非法人窃取、阅读的目的。该过程的逆过程为解密,即将该编码信息转化为其原来数据的过程。 简单来说,就是把某一段数据(明文),按照...