小书匠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. 三元组[01 Trie计数]

    也许更好的阅读体验 \(\mathcal{Description}\) \(\mathcal{Solution}\) 有两种方法都可以拿到满分 \(Solution\ 1\) 考虑枚举\(y\) 建两 ...

  2. Spring Cloud Alibaba学习笔记(4) - Feign配置与使用

    什么是Feign Feign是一个声明式Web Service客户端. 使用Feign能让编写Web Service客户端更加简单, 它的使用方法是定义一个接口,然后在上面添加注解,同时也支持JAX- ...

  3. iview的table组件中加入超链接组件,可编辑组件,选择组件,日期组件

    这篇文章主要介绍了iview的table组件中使用选择框,日期,可编辑表格,超链接等组件. 1.select选择组件 // tableColumn数组响应对象需要传入一个固定的option数组,如果该 ...

  4. 【转载】如何自己DIY组装一台台式电脑

    针对很多懂计算机的人员来说,有时候都希望自己DIY组装一台台式机,来达到自己的个性化要求以及省钱.其实自己DIY组装一台电脑也很简单,将相应的CPU处理器.主板.内存条.硬盘.固态硬盘.电脑机箱.屏幕 ...

  5. 13 个 JS 数组精简技巧

    来自 https://juejin.im/post/5db62f1bf265da4d560906ab 侵删 数组是 JS 最常见的一种数据结构,咱们在开发中也经常用到,在这篇文章中,提供一些小技巧,帮 ...

  6. you might not need jquery

    What's the oldest version of IE you need to support? IE10 /**json**/ var request = new XMLHttpReques ...

  7. stm32 视频小车

    1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 ...

  8. 对比centos7的systemctl和其他service+chkconfig

    syetemctl就是service和chkconfig这两个命令的整合,在CentOS 7就开始被使用了.systemctl 是系统服务管理器命令,它实际上将 service 和 chkconfig ...

  9. 【leetcode】544. Output Contest Matches

    原题 During the NBA playoffs, we always arrange the rather strong team to play with the rather weak te ...

  10. Pycharm 社区版本Database Navigator 安装教程

    虽然Pycharm有专业版和社区版这两个版本,但是在大多数情况下我们都会选择社区版进行下载安装.为啥呢?因为社区版免费呗,而且能够基本满足我们的日常需求(这也就意味着社区版会比专业版少一些功能).针对 ...