小书匠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. print('0节点到4节点最短路径: ',nx.shortest_path(G, source=0, target=4)) 

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

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


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

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


  17. #计算最短路径长度 

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

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

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


  21. #检测是否有路径 

  22. 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. path1 = nx.single_source_shortest_path(G, 0) #计算当前源与所有可达节点的最短路径 

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

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

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

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


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

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

  15. print('\nG中从源到所有节点最短路径的前驱: ',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. pred, dist = nx.dijkstra_predecessor_and_distance(G, 0) 

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


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

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

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


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

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

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

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

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

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

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


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

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

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


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


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

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

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

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


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

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

  31. print('\n双向搜索的迪杰斯特拉:',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. print('G中从源到目标的最短加权路径: ',nx.bellman_ford_path(G, 0, 4)) 

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


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

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

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


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

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

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


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

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

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


贝尔曼-福特(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. print(nx.negative_edge_cycle(G)) 

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

  6. 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. edge_labels = nx.get_edge_attributes(G,'weight')  

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


  7. #生成节点位置  

  8. pos=nx.spring_layout(G)  


  9. #把节点画出来  

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


  11. #把边画出来  

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


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

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


  15. #把边权重画出来  

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


  17. #显示graph 

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

  19. plt.axis('on') 

  20. plt.xticks([]) 

  21. plt.yticks([]) 

  22. plt.show() 


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

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


  25. print(paths) 


约翰逊(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. edge_labels = nx.get_edge_attributes(G,'weight')  

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


  7. #生成节点位置  

  8. pos=nx.spring_layout(G)  


  9. #把节点画出来  

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


  11. #把边画出来  

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


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

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


  15. #把边权重画出来  

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


  17. #显示graph 

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

  19. plt.axis('on') 

  20. plt.xticks([]) 

  21. plt.yticks([]) 

  22. plt.show() 


  23. #计算最短路径长度 

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


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

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


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

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


  29. print(list(lenght)) 

  30. print(predecessor) 

  31. print(list(distance1)) 

  32. print(distance2) 


弗洛伊德算法(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,即如图:


两点之间的最短距离

11.1.8A*算法

  1. G = nx.path_graph(5) 


  2. #显示graph 

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

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

  5. plt.axis('on') 

  6. plt.xticks([]) 

  7. plt.yticks([]) 

  8. plt.show() 


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

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

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


A*算法

输出:

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



NetworkX系列教程(10)-算法之一:最短路径问题的更多相关文章

  1. NetworkX系列教程(10)-算法之五:广度优先与深度优先

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

  2. NetworkX系列教程(10)-算法之四:拓扑排序与最大流问题

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

  3. NetworkX系列教程(10)-算法之三:关键路径问题

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

  4. NetworkX系列教程(10)-算法之二:最小/大生成树问题

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

  5. NetworkX系列教程(9)-线性代数相关

    小书匠 Graph 图论  学过线性代数的都了解矩阵,在矩阵上的文章可做的很多,什么特征矩阵,单位矩阵等.grpah存储可以使用矩阵,比如graph的邻接矩阵,权重矩阵等,这节主要是在等到graph后 ...

  6. NetworkX系列教程(2)-graph生成器

    小书匠Graph图论 本节主要讲解如何快速使用内置的方法生成graph,官方的文档在这里,里面包含了networkX的所有graph生成器,下面的内容只是我节选的内容,并将graph画出来而已. 声明 ...

  7. NetworkX系列教程(1)-创建graph

    小书匠Graph图论 研究中经常涉及到图论的相关知识,而且常常面对某些术语时,根本不知道在说什么.前不久接触了NetworkX这个graph处理工具,发现这个工具已经解决绝大部分的图论问题(也许只是我 ...

  8. HTML5游戏开发系列教程10(译)

    原文地址:http://www.script-tutorials.com/html5-game-development-lesson-10/ 最后我们将继续使用canvas来进行HTML5游戏开发系列 ...

  9. Python Twisted系列教程10:增强defer功能的客户端

    作者:dave@http://krondo.com/an-introduction-to-asynchronous-programming-and-twisted/ 译者:杨晓伟(采用意译) 可以从这 ...

随机推荐

  1. .Net DLL类库引用时没有注释信息

    自己编写的类库提供给别人引用时,别人获取不到DLL内部的方法.变量的注释信息,无法了解内部情况和使用方法. 原因:没有随DLL类库一同输出注释文档 解决方案: 在VS界面中选中提供给别人的类库项目 在 ...

  2. Ubuntu安装opencv3.4.4教程

    1 去官网下载opencv 在本教程中选用的是opencv3.4.4,下载链接 http://opencv.org/releases.html ,选择sources. 2 解压 unzip openc ...

  3. ES6-promise实现异步请求

    一.Promise是什么 简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果. ES6规定,Promise对象是一个构造函数,用来生成Promise实例.Promise构 ...

  4. Python 自己实现可迭代对象

    import time from collections import Iterable from collections import Iterator class Classmate(object ...

  5. 基于FTP 的本地Yum服务器配置

    服务器端 环境如下 Vmware14CentOS 7.6 192.168.20.81 server 192.168.20.81 client 1.配置yum源 mount /dev/cdrom /me ...

  6. Elasticsearch 入门,基本概念和操作

    基本概念 Node 与 Cluster Elastic 本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器可以运行多个 Elastic 实例. 单个 Elastic 实例称为一个节点(nod ...

  7. python之第一对象,函数名的应用,闭包

    一.第一对象 在 Python 中万物皆为对象,函数也不例外,函数作为对象可以赋值给一个变量.可以作为元素添加到集合对象中.可作为参数值传递给其它函数, 还可以当做函数的返回值,这些特性就是第一类对象 ...

  8. Mybatis.NET Oracle 线上神奇问题:Value does not fall within the expected range.

    1.错误现象 在向数据库查询一条数据的时候报如下错误: Value does not fall within the expected range. at Oracle.ManagedDataAcce ...

  9. kubernetes Node节点部署(四)

    一.部署kubelet 1.1.二进制包准备 将软件包从linux-node1复制到linux-node2中去 [root@linux-node1 ~]# cd /usr/local/src/kube ...

  10. 【记忆化搜索】[NOIP-2017--普及组] -- 棋盘

    [题目描述] 原题目链接地址:   有一个m × m的棋盘,棋盘上每一个格子可能是红色.黄色或没有任何颜色的.你现在要从棋盘的最左上角走到棋盘的最右下角. 任何一个时刻,你所站在的位置必须是有颜色的( ...