Python数模笔记-NetworkX(2)最短路径


1、最短路径问题的常用算法

最短路径问题是图论研究中的经典算法问题,用于计算图中一个顶点到另一个顶点的最短路径。


欢迎关注 Youcans 原创系列,每周更新数模笔记

Python数模笔记-PuLP库
Python数模笔记-StatsModels统计回归
Python数模笔记-Sklearn
Python数模笔记-NetworkX
Python数模笔记-模拟退火算法


1.1 最短路径长度与最短加权路径长度

在日常生活中,最短路径长度与最短路径距离好像并没什么区别。但在具体的图论问题中却可能是不同的概念和问题,经常会被混淆。

图论中有无权图和有权图,无权图中的边没有权,赋权图的边带有权,可以表示距离、时间、费用或其它指标。在问题文字描述中,往往并不直接指出是无权图还是有权图,这时就要注意最短路径与最短加权路径的区别。路径长度是把每个顶点到相邻顶点的长度记为 1,而不是指这两个顶点之间道路的距离——两个顶点之间的道路距离是连接边的权(weight)。通俗地说,路径长度可以认为是飞行棋的步数,或者公交站点的站数,相邻顶点之间为一步,相隔几个顶点就是几站。路径长度是从路径起点到终点的步数,计算最短路径是要计算从起点到终点步数最小的路径。

如果问题不涉及顶点之间的距离,要求从起点到终点的最短路径及对应的最短长度,是指从这条路线从起点到终点有几站,在图论中称为最短路径长度。但是,如果问题给出顶点之间的道路长度或距离,姑且称为各路段的距离,要求从起点到终点的最短路径及对应的最短距离,显然并不是在找经过最少步数的路径,而是在找路径中各路段的距离之和最小的路径,在图论中称为最短加权路径长度——这里权重是路段距离。

1.2 最短路径的常用算法

求解最短路径长度的常用算法是 Dijkstra 算法、Bellman-Ford 算法和Floyd 算法,另外还有启发式算法 A*。

  • Dijkstra 算法

Dijkstra 算法用于计算有权图中最短路径问题 。该算法从起点开始,采用贪心法策略,每次遍历到起点距离最近且未访问过的顶点的邻接节点, 直到扩展到终点为止。

Dijkstra 算法的时间复杂度为 O(n^2)。如果边数远小于 n^2,可以用堆结构将复杂度降为O((m+n)log(n))。

Dijkstar算法不能处理负权边。

  • Bellman-Ford 算法

Bellman-Ford 算法用于求解单源最短路径问题。算法原理是对图进行 V-1次松弛操作,得到所有可能的最短路径。

Bellman-Ford 算法的时间复杂度高达 O(V*E),V、E 分别是顶点和边的数量。

Bellman-Ford 算法可以处理负权边。其基本操作“拓展”是在深度上搜索,而“松弛”操作则在广度上搜索,因此可以对负权边进行操作而不影响结果。

  • Floyd 算法

Floyd 算法又称插点法,利用动态规划思想求解有权图中多源点之间最短路径问题。算法从图的带权邻接矩阵开始,递归地进行 n 次更新得到图的距离矩阵,进而可以得到最短路径节点矩阵。

Floyd 算法的时间复杂度为 O(n^3),空间复杂度为 O(n^2)。算法时间复杂度较高,不适合计算大量数据。Floyd 算法的优点是可以一次性求解任意两个节点之间的最短距离,对于稠密图的效率高于执行 V 次 Dijkstra算法。

Floyd 算法可以处理负权边。

  • A* 算法

A*算法是一种静态路网中求解最短路径最有效的直接搜索方法。

A*算法是启发式算法,采用最好优先(Best-first)搜索策略,基于估价函数对每个搜索位置的评估结果,猜测最好的位置优先进行搜索。

A*算法极大地减少了低质量的搜索路径,因而搜索效率很高,比传统的路径规划算法实时性更高、灵活性更强;但是,A*算法找到的是相对最优路径,不是绝对的最短路径,适合大规模、实时性高的问题。

1.3 最短路径算法的选择

  1. 需要求解任意两个节点之间的最短距离,使用 Floyd 算法;
  2. 只要求解单源最短路径问题,有负权边时使用 Bellman-Ford 算法,没有负权边时使用 Dijkstra 算法;
  3. A*算法找到的是相对最优路径,适合大规模、实时性高的问题。



2、NetworkX 中的最短路径算法

2.1 无向图和有向图的最短路径求解函数

函数功能
shortest_path(G[, source, target, weight,…])计算图中的最短路径
all_shortest_paths(G, source, target[,…])计算图中所有最短的简单路径
shortest_path_length(G[, source, target, …])计算图中的最短路径长度
average_shortest_path_length(G[, weight, method])计算平均最短路径长度

2.2 无权图最短路径算法

函数功能
single_source_shortest_path(G, source[,cutoff])计算从源到所有可达节点的最短路径
single_source_shortest_path_length(G,source)计算从源到所有可达节点的最短路径长度
single_target_shortest_path(G, target[,cutoff])计算从所有可达节点到目标的最短路径
single_target_shortest_path_length(G,target)计算从所有可达节点到目标的最短路径长度
all_pairs_shortest_path(G[, cutoff])计算所有节点之间的最短路径
all_pairs_shortest_path_length(G[, cutoff])计算所有节点之间的最短路径长度

2.3 有权图最短路径算法

函数功能
dijkstra_path(G, source, target[, weight])计算从源到目标的最短加权路径
dijkstra_path_length(G, source, target[,weight])计算从源到目标的最短加权路径长度
all_pairs_dijkstra_path(G[, cutoff, weight])计算所有节点之间的最短加权路径
all_pairs_dijkstra_path_length(G[, cutoff,… ])计算所有节点之间的最短加权路径长度
bellman_ford_path(G, source, target[, weight])计算从源到目标的最短路径
bellman_ford_path_length(G, source, target)计算从源到目标的最短路径长度
all_pairs_bellman_ford_path(G[, weight])计算所有节点之间的最短路径
all_pairs_bellman_ford_path_length(G[,weight])计算所有节点之间的最短路径长度
floyd_warshall(G[, weight])用 Floyd 法计算所有节点之间的最短路径长度
floyd_warshall_numpy(G[, nodelist, weight])用 Floyd 法计算所有指定节点之间的最短路径长度


3、NetworkX 中的 Dijkstra 算法

NetworkX 中关于 Dijkstra 算法提供了 13 个函数,很多函数的功能是重叠的。这里只介绍最基本的函数 dijkstra_path() 和 dijkstra_path_length()。

3.1 dijkstra_path() 和 dijkstra_path_length() 使用说明

dijkstra_path() 用于计算从源到目标的最短加权路径,dijkstra_path_length() 用于计算从源到目标的最短加权路径长度。

dijkstra_path(G, source, target, weight=‘weight’)

dijkstra_path_length(G, source, target, weight=‘weight’)

主要参数:

  • G(NetworkX graph):图。
  • source (node):起点。
  • target (node):终点。
  • weight (string or function):参数为字符串(string)时,按该字符串查找边的属性作为权重;如果该字符串对应的边属性不存在,则权重置为1;参数为函数时,边的权重是函数的返回值。

返回值:
dijkstra_path() 的返回值是最短加权路径中的节点列表,数据类型为list。
dijkstra_path_length() 的返回值是最短加权路径的长度(路径中的边的权重之和),数据类型为 number。

3.2 dijkstra_path() 算法使用例程

本案例问题来自:司守奎、孙兆亮,数学建模算法与应用(第2版),P43,例4.3,国防工业出版社。

例4.3:无向图的最短路问题。已知如图的有权无向图,求顶点 v1 到 顶点 v11 的最短路径。

# networkX_E2.py
# Demo of shortest path with NetworkX
# Copyright 2021 YouCans, XUPT
# Crated:2021-05-18import matplotlib.pyplot as plt # 导入 Matplotlib 工具包
import networkx as nx  # 导入 NetworkX 工具包# 问题 2:无向图的最短路问题(司守奎,数学建模算法与应用,P43,例4.3)
G2 = nx.Graph()  # 创建:空的 无向图
G2.add_weighted_edges_from([(1,2,2),(1,3,8),(1,4,1),(2,3,6),(2,5,1),(3,4,7),(3,5,5),(3,6,1),(3,7,2),(4,7,9),(5,6,3),(5,8,2),(5,9,9),(6,7,4),(6,9,6),(7,9,3),(7,10,1),(8,9,7),(8,11,9),(9,10,1),(9,11,2),(10,11,4)])  # 向图中添加多条赋权边: (node1,node2,weight)
# 两个指定顶点之间的最短加权路径
minWPath_v1_v11 = nx.dijkstra_path(G2, source=1, target=11)  # 顶点 0 到 顶点 3 的最短加权路径
print("顶点 v1 到 顶点 v11 的最短加权路径: ", minWPath_v1_v11)
# 两个指定顶点之间的最短加权路径的长度
lMinWPath_v1_v11 = nx.dijkstra_path_length(G2, source=1, target=11)  #最短加权路径长度
print("顶点 v1 到 顶点 v11 的最短加权路径长度: ", lMinWPath_v1_v11)
# === 关注 Youcans 原创系列(https://blog.csdn.net/youcans)===
pos = nx.spring_layout(G2)  # 用 FR算法排列节点
nx.draw(G2, pos, with_labels=True, alpha=0.5)
labels = nx.get_edge_attributes(G2,'weight')
nx.draw_networkx_edge_labels(G2, pos, edge_labels = labels)
plt.show()

3.3 程序运行结果

顶点 v1 到 顶点 v11 的最短加权路径:  [1, 2, 5, 6, 3, 7, 10, 9, 11]
顶点 v1 到 顶点 v11 的最短加权路径长度:  13

在这里插入图片描述

3.4 程序说明

  1. 图的输入。本例为稀疏的有权无向图,使用 G.add_weighted_edges_from() 函数可以使用列表向图中添加多条赋权边,每个赋权边以元组 (node1,node2,weight) 表示。
  2. 图的绘制。使用nx.draw()绘图时,默认的节点位置可能并不理想,nx.spring_layout() 使用 Fruchterman-Reingold 力定向算法定位节点。
  3. 绘制边的属性。使用 nx.draw_networkx_edge_labels() 可以绘制边的属性,例程中选择显示权重属性。


4、NetworkX 中的 Bellman-Ford 算法

NetworkX 中关于 Bellman-Ford 算法提供了 13 个函数,很多函数的功能是重叠的。这里只介绍最基本的函数 bellman_ford_path() 和 bellman_ford_path_length()。

4.1 bellman_ford_path() 和 bellman_ford_path_length() 使用说明

bellman_ford_path() 用于计算从源到目标的最短加权路径,bellman_ford_path_length() 用于计算从源到目标的最短加权路径长度。

bellman_ford_path(G, source, target, weight=‘weight’)

bellman_ford_path_length(G, source, target, weight=‘weight’)

主要参数:

  • G(NetworkX graph):图。
  • source (node):起点。
  • target (node):终点。
  • weight (string):按字符串查找边的属性作为权重。默认值为权重 ‘weight’。

返回值:
bellman_ford_path() 的返回值是最短加权路径中的节点列表,数据类型为list。
bellman_ford_path_length() 的返回值是最短加权路径的长度(路径中的边的权重之和),数据类型为 number。

4.2 bellman_ford_path() 算法使用例程

本案例问题来自:司守奎、孙兆亮,数学建模算法与应用(第2版),P41,例4.1,国防工业出版社。

例4.1:城市间机票价格问题。已知 6个城市之间的机票票价如矩阵所示(无穷大表示没有直航),求城市 c1 到其它城市 c2…c6 的票价最便宜的路径及票价。

# networkX_E1.py
# Demo of shortest path with NetworkX
# Copyright 2021 YouCans, XUPT
# Crated:2021-05-18import pandas as pd
import matplotlib.pyplot as plt # 导入 Matplotlib 工具包
import networkx as nx  # 导入 NetworkX 工具包# 问题 1:城市间机票价格问题(司守奎,数学建模算法与应用,P41,例4.1)
# # 从Pandas数据格式(顶点邻接矩阵)创建 NetworkX 图
# # from_pandas_adjacency(df, create_using=None) # 邻接矩阵,n行*n列,矩阵数据表示权重
dfAdj = pd.DataFrame([[0, 50, 0, 40, 25, 10],  # 0 表示不邻接,[50, 0, 15, 20, 0, 25],[0, 15, 0, 10, 20, 0],[40, 20, 10, 0, 10, 25],[25, 0, 20, 10, 0 ,55],[10, 25, 0, 25, 55, 0]])
G1 = nx.from_pandas_adjacency(dfAdj)  # 由 pandas 顶点邻接矩阵 创建 NetworkX 图# 计算最短路径:注意最短路径与最短加权路径的不同
# 两个指定顶点之间的最短路径
minPath03 = nx.shortest_path(G1, source=0, target=3)  # 顶点 0 到 顶点 3 的最短路径
lMinPath03 = nx.shortest_path_length(G1, source=0, target=3)  #最短路径长度
print("顶点 0 到 3 的最短路径为:{},最短路径长度为:{}".format(minPath03, lMinPath03))
# 两个指定顶点之间的最短加权路径
minWPath03 = nx.bellman_ford_path(G1, source=0, target=3)  # 顶点 0 到 顶点 3 的最短加权路径
# 两个指定顶点之间的最短加权路径的长度
lMinWPath03 = nx.bellman_ford_path_length(G1, source=0, target=3)  #最短加权路径长度
print("顶点 0 到 3 的最短加权路径为:{},最短加权路径长度为:{}".format(minWPath03, lMinWPath03))for i in range(1,6):minWPath0 = nx.dijkstra_path(G1, source=0, target=i)  # 顶点 0 到其它顶点的最短加权路径lMinPath0 = nx.dijkstra_path_length(G1, source=0, target=i)  #最短加权路径长度print("城市 0 到 城市 {} 机票票价最低的路线为: {},票价总和为:{}".format(i, minWPath0, lMinPath0))
# === 关注 Youcans 原创系列(https://blog.csdn.net/youcans)===
# nx.draw_networkx(G1) # 默认带边框,顶点标签
nx.draw(G1, with_labels=True, layout=nx.spring_layout(G1))
plt.show()

4.3 程序运行结果

顶点 03 的最短路径为:[0, 3],最短路径长度为:1
顶点 03 的最短加权路径为:[0, 4, 3],最短加权路径长度为:35
城市 0 到 城市 1 机票票价最低的路线为: [0, 5, 1],票价总和为:35
城市 0 到 城市 2 机票票价最低的路线为: [0, 4, 2],票价总和为:45
城市 0 到 城市 3 机票票价最低的路线为: [0, 5, 3],票价总和为:35
城市 0 到 城市 4 机票票价最低的路线为: [0, 4],票价总和为:25
城市 0 到 城市 5 机票票价最低的路线为: [0, 5],票价总和为:10

4.4 程序说明

  1. 图的输入。使用 pandas 中 DataFrame 读取数据文件非常方便,本例中以 pandas 输入顶点邻接矩阵,使用 nx.from_pandas_adjacency(dfAdj) 转换为 NetworkX 的图。
  2. 邻接矩阵。邻接矩阵 dfAdj (i,j) 的值表示连接顶点 i、j 的边的权值, i、j 不相邻 dfAdj (i,j) =0, 本例中表示没有直航。
  3. 最短路径与最短路径长度。nx.shortest_path() 返回最短路径。nx.shortest_path_length() 返回最短路径长度,本例中可以理解为从起点到终点的乘机次数,1 表示直航,2 表示中转一次。
  4. 最短加权路径长度。nx.bellman_ford_path_length() 返回最短加权路径长度,本例中权重为票价,最短加权路径长度即为两点间最便宜的直航或中转的机票票价。
    通过本案例,可以直观地理解最短路径长度与最短加权路径长度的区别。

版权说明:

本文内容及例程为作者原创,并非转载书籍或网络内容。
本文中案例问题来自:
1、司守奎、孙兆亮,数学建模算法与应用(第2版),国防工业出版社。

YouCans 原创作品
Copyright 2021 YouCans, XUPT
Crated:2021-05-18


欢迎关注 Youcans 原创系列,每周更新数模笔记

Python数模笔记-PuLP库(1)线性规划入门
Python数模笔记-PuLP库(2)线性规划进阶
Python数模笔记-PuLP库(3)线性规划实例
Python数模笔记-NetworkX(1)图的操作
Python数模笔记-NetworkX(2)最短路径
Python数模笔记-NetworkX(3)条件最短路径
Python数模笔记-StatsModels 统计回归(1)简介
Python数模笔记-StatsModels 统计回归(2)线性回归
Python数模笔记-StatsModels 统计回归(3)模型数据的准备
Python数模笔记-StatsModels 统计回归(4)可视化
Python数模笔记-Sklearn (1)介绍
Python数模笔记-Sklearn (2)聚类分析
Python数模笔记-Sklearn (3)主成分分析
Python数模笔记-Sklearn (4)线性回归
Python数模笔记-Sklearn (5)支持向量机
Python数模笔记-模拟退火算法(1)多变量函数优化
Python数模笔记-模拟退火算法(2)约束条件的处理
Python数模笔记-模拟退火算法(3)整数规划问题
Python数模笔记-模拟退火算法(4)旅行商问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/566156.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

神经网络向量化

神经网络向量化 在本节,我们将引入神经网络的向量化版本。在前面关于神经网络介绍的章节中,我们已经给出了一个部分向量化的实现,它在一次输入一个训练样本时是非常有效率的。下边我们看看如何实现同时处理多个训练样本的算法。具体来讲&…

Python数模笔记-NetworkX(3)条件最短路径

1、带有条件约束的最短路径问题 最短路径问题是图论中求两个顶点之间的最短路径问题,通常是求最短加权路径。 条件最短路径,指带有约束条件、限制条件的最短路径。例如,顶点约束,包括必经点或禁止点的限制;边的约束&…

简单技能之程序调试入门

简单技能之程序调试入门 黑盒测试 等价类划分

Python数模笔记-NetworkX(4)最小生成树

1、生成树和最小生成树 1.1 生成树 连通的无圈图称为树,就是不包含循环的回路的连通图。 对于无向连通图,生成树(Spanning tree)是原图的极小连通子图,它包含原图中的所有 n 个顶点,并且有保持图连通的最…

Python数模笔记-NetworkX(5)关键路径法

关键路径法(Critical path method,CPM)是一种计划管理方法,通过分析项目过程中工序进度安排寻找关键路径,确定最短工期,广泛应用于系统分析和项目管理。 1、拓扑序列与关键路径 1.1 拓扑序列 一个大型工程…

Python小白的数学建模课-01.新手必读

Python 完全可以满足数学建模的需要。 Python 是数学建模的最佳选择之一,而且在其它工作中也无所不能。 『Python小白的数学建模课 Youcans』 带你从数模小白成为国赛达人。 欢迎关注『Python小白的数学建模课 Youcans』系列,每周持续更新 Python小白…

Python的数学建模课-02.数据导入

数据导入是所有数模编程的第一步,比你想象的更重要。 先要学会一种未必最佳,但是通用、安全、简单、好学的方法。 『Python小白的数学建模课 Youcans』 带你从数模小白成为国赛达人。 1. 数据导入是所有数模编程的第一步 编程求解一个数模问题&#…

UFIDL稀疏自编码代码实现及解释

UFIDL稀疏自编码代码实现及解释 1.今天我们来讲一下UFIDL的第一个练习。 1.我们来看看最难的一个.m文件 %% ---------- YOUR CODE HERE -------------------------------------- % Instructions: Compute the cost/optimization objective J_sparse(W,b) for the Sparse Aut…

Python小白的数学建模课-A2.2021年数维杯C题(运动会优化比赛模式探索)探讨

关注收藏,国赛再会。 运动会优化比赛模式问题,是公平分配问题。 『Python小白的数学建模课 Youcans』带你从数模小白成为国赛达人。 2021第六届数维杯大学生数学建模 赛题已于5月27日公布,C题是"运动会优化比赛模式探索"。本文对…

Python小白的数学建模课-03.线性规划

线性规划是很多数模培训讲的第一个算法,算法很简单,思想很深刻。 要通过线性规划问题,理解如何学习数学建模、如何选择编程算法。 『Python小白的数学建模课 Youcans』带你从数模小白成为国赛达人。 1. 求解方法、算法和编程方案 线性规…

Python小白的数学建模课-A1.国赛赛题类型分析

分析赛题类型,才能有的放矢。 评论区留下邮箱地址,送你国奖论文分析 『Python小白的数学建模课 Youcans』 带你从数模小白成为国赛达人。 1. 数模竞赛国赛 A题类型分析 年份题目要求方法2020A炉温曲线建立温度模型,计算炉温曲线&#xff…

白话(whitening)

白化 Contents [hide]1 介绍2 2D 的例子3 ZCA白化4 正则化5 中英文对照6 中文译者 介绍 我们已经了解了如何使用PCA降低数据维度。在一些算法中还需要一个与之相关的预处理步骤,这个预处理过程称为白化(一些文献中也叫sphering)。举例来说&…

Python小白的数学建模课-04.整数规划

整数规划与线性规划的差别只是变量的整数约束。 问题区别一点点,难度相差千万里。 选择简单通用的编程方案,让求解器去处理吧。 『Python小白的数学建模课 Youcans』带你从数模小白成为国赛达人。 1. 从线性规划到整数规划 1.1 为什么会有整数规划&…

实现主成分分析和白化

实现主成分分析和白化 在这一节里,我们将总结PCA, PCA白化和ZCA白化算法,并描述如何使用高效的线性代数库来实现它们。 首先,我们需要确保数据的均值(近似)为零。对于自然图像,我们通过减去每个图像块(patc…

Python小白的数学建模课-05.0-1规划

0-1 规划不仅是数模竞赛中的常见题型,也具有重要的现实意义。 双十一促销中网购平台要求二选一,就是互斥的决策问题,可以用 0-1规划建模。 小白学习 0-1 规划,首先要学会识别 0-1规划,学习将问题转化为数学模型。 『…

mac下一些终端命令的使用

mac基础终端命令入门作为一名编程人员,(叫程序猿显得屌丝,叫攻城狮感觉还达不到),我经常看到许多大神在终端里面进行一些神操作。鉴于此,我今天就百度了一下,别问我为什么不Google,穷…

Python小白的数学建模课-06.固定费用问题

Python 实例介绍固定费用问题的建模与求解。 学习 PuLP工具包中处理复杂问题的快捷使用方式。 『Python小白的数学建模课 Youcans』带你从数模小白成为国赛达人。 前文讲到几种典型的 0-1 规划问题,给出了 PuLP 求解的案例。由于 0-1 规划问题种类很多&#xff0…

Python小白的数学建模课-07.选址问题

选址问题是要选择设施位置使目标达到最优,是数模竞赛中的常见题型。 小白不一定要掌握所有的选址问题,但要能判断是哪一类问题,用哪个模型。 进一步学习 PuLP工具包中处理复杂问题的字典格式快捷建模方法。 欢迎关注『Python小白的数学建模…

Python小白的数学建模课-09.微分方程模型

小白往往听到微分方程就觉得害怕,其实数学建模中的微分方程模型不仅没那么复杂,而且很容易写出高水平的数模论文。 本文介绍微分方程模型的建模与求解,通过常微分方程、常微分方程组、高阶常微分方程 3个案例手把手教你搞定微分方程。 通过…