【图与网络数学模型】3.Ford-Fulkerson算法求解网络最大流问题

在这里插入图片描述

【图与网络数学模型】3.Ford-Fulkerson算法求解网络最大流问题

  • 一、网络流模型
    • 1. 概述
    • 2. 可行流
    • 3. 增广链
  • 二、示例
    • 1. 最大流问题
    • 2. Alternate Formulation:最小截量问题
  • 三、Ford-Fulkerson 算法
    • 1. 导入库
    • 2. 初始化残差图
    • 3. 定义查找增广路径
    • 4. 定义循环
    • 5. 程序运行
  • 四、其它发现
  • 参考文献


一、网络流模型

1. 概述

许多系统中包含了流量问题,例如,公路系统中有车辆流,控制系统中有信息流,供水系统中有水流,金融系统中有现金流等。

在生物安全领域和医疗系统中,也包括就诊、挂号、检查、治疗、转院等过程涉及的患者流,医疗设备、药品、医用材料等的采购、配送、使用等过程涉及的医疗资源流,以及医疗质量控制流和医保支付流等等。

对于这样一些包含了流量问题的系统,我们往往要求出其系统的最大流量。给一个带收发点的网络,每条弧的赋权称为容量,在不超过每条弧的容量的前提下,确定每条弧的流量,求出从发点到收点的最大流量,这类问题通常称为最大流问题

2. 可行流

  • 网络流一般在有向图上讨论
  • 定义网络上支路的容量为其最大通过能力,记为 c i j c_{ij} cij,支路上的实际流量记为 f i j f_{ij} fij
  • 图中规定一个发点s,一个收点t
  • 节点没有容量限制,流在节点不会存储
  • 容量限制条件:0 ≤ f i j f_{ij} fij c i j c_{ij} cij
  • 平衡条件:
    ∑ v j ∈ A ( v i ) f i j − ∑ v j ∈ B ( v i ) f j i = { v ( f ) i = s 0 i ≠ s , t − v ( f ) i = t \sum_{v_j \in A\left(v_i\right)} f_{i j}-\sum_{v_j \in B\left(v_i\right)} f_{j i}=\left\{\begin{array}{cc} v(f) & i=s \\ 0 & i \neq s, t \\ -v(f) & i=t \end{array}\right. vjA(vi)fijvjB(vi)fji= v(f)0v(f)i=si=s,ti=t

满足上述条件的网络流称为可行流,总存在最大可行流。

当支路上 f i j = c i j f_{ij}=c_{ij} fij=cij ,称为饱和弧;v( f )为可行流的流量。

最大流问题也是一个线性规划问题。

3. 增广链

设 f 是一个可行流, μ \mu μ v s v_s vs v t v_t vt 到的一条链,若 μ \mu μ 满足下列条件,则 μ \mu μ 是可行流的一条增广链

  1. ( v i , v j ) ∈ μ + \left(v_i, v_j\right) \in \mu^{+} (vi,vj)μ+上, 0 ≤ f i j < c i j 0\leq{f}_{i_j}<c_{i j} 0fij<cij,即 μ + \mu^{+} μ+ 中每一条弧是非饱和弧;
  2. ( v i , v j ) ∈ μ − \left(v_i, v_j\right) \in \mu^{-} (vi,vj)μ上, 0 < f i j ≤ c i j 0<f_{i j} \leq c_{i j} 0<fijcij,即 μ − \mu^{-} μ中每一条弧是非零流孤。

二、示例

1. 最大流问题

给定一个图,该图表示每个边都有一个容量的流网络。此外,给定图中的两个顶点源 ‘s’ 和接收器 ‘t’,使用以下约束找到从 s 到 t 的最大可能流量:

在这里插入图片描述

该问题的最大流量为23:

在这里插入图片描述

2. Alternate Formulation:最小截量问题

  • 把网络分割为两个成分的弧的最小集合,其中一个成分包含 s s s 点,另一个包含 t t t
  • 一般包含 s s s 点的成分中的节点集合用 V V V 表示,包含 t t t 点的成分中的节点集合用 V ˉ \bar{V} Vˉ 表示
  • 截量集容量是指截量集中前向弧的容量之和:
    C ( V , V ˉ ) = ∑ i ∈ V j ∈ V ˉ c i j C(V, \bar{V})=\sum_{\substack{i \in V \\ j \in \bar{V}}} c_{i j} C(V,Vˉ)=iVjVˉcij

福特-富克森定理:网络的最大流等于最小截量集容量。

从原始图中“减去”最大流路径,得到下图:

在这里插入图片描述

标记从 s 到达的所有节点——调用可到达节点集 A:

在这里插入图片描述
将这些节点和其他节点分开:

在这里插入图片描述

从图中删除红色的边,使得删除这些边后,没有从 s 到 t 的路径:

在这里插入图片描述

相应的最大流量路径为:
− s → a → b → t : 11 − s → c → a → b → t : 1 − s → c → d → b → t : 7 − s → c → d → t : 4 \begin{aligned} & -s \rightarrow a \rightarrow b \rightarrow t: 11 \\ & -s \rightarrow c \rightarrow a \rightarrow b \rightarrow t: 1 \\ & -s \rightarrow c \rightarrow d \rightarrow b \rightarrow t: 7 \\ & -s \rightarrow c \rightarrow d \rightarrow t: 4 \end{aligned} sabt:11scabt:1scdbt:7scdt:4

三、Ford-Fulkerson 算法

在1962年,L.R.Ford和D.R.Fulkerson发明了一种解决最大流量问题的有效方法。它是一种沿着由起点到终点的路径逐步增加流量的通用方法,因此它也是同类算法的基础。在经典文献中它被称为Ford-Fulkerson算法,但它也被称为增广路径算法。

Ford-Fulkerson最大流量算法: 网络中的初始流量为零,沿着任意从起点到终点(且不含有饱和的正向边或是空逆向边)的增广路径增大流量,直到网络中不存在这样的路径为止。

1. 导入库

from collections import defaultdict

2. 初始化残差图

初始化残差图(residual graph)以及行数 ROW。

	def __init__(self, graph):self.graph = graph # 残差图self. ROW = len(graph)# self.COL = len(gr[0])

3. 定义查找增广路径

使用广度优先搜索来找到从源点 s 到汇点 t 的一条增广路径,同时更新父节点数组 parent。

	def BFS(self, s, t, parent):visited = [False]*(self.ROW)queue = []queue.append(s)visited[s] = Truewhile queue:u = queue.pop(0)for ind, val in enumerate(self.graph[u]):if visited[ind] == False and val > 0:queue.append(ind)visited[ind] = Trueparent[ind] = uif ind == t:return Truereturn False

4. 定义循环

在 FordFulkerson 方法中,使用 while 循环来不断寻找增广路径,并更新残差图直到没有增广路径为止。

	def FordFulkerson(self, source, sink):parent = [-1]*(self.ROW)max_flow = 0 while self.BFS(source, sink, parent) :path_flow = float("Inf")s = sinkwhile(s != source):path_flow = min (path_flow, self.graph[parent[s]][s])s = parent[s]max_flow += path_flowv = sinkwhile(v != source):u = parent[v]self.graph[u][v] -= path_flowself.graph[v][u] += path_flowv = parent[v]return max_flow

5. 程序运行

from collections import defaultdictclass Graph:def __init__(self, graph):self.graph = graphself. ROW = len(graph)def BFS(self, s, t, parent):visited = [False]*(self.ROW)queue = []queue.append(s)visited[s] = Truewhile queue:u = queue.pop(0)for ind, val in enumerate(self.graph[u]):if visited[ind] == False and val > 0:queue.append(ind)visited[ind] = Trueparent[ind] = uif ind == t:return Truereturn Falsedef FordFulkerson(self, source, sink):parent = [-1]*(self.ROW)max_flow = 0 while self.BFS(source, sink, parent) :path_flow = float("Inf")s = sinkwhile(s != source):path_flow = min (path_flow, self.graph[parent[s]][s])s = parent[s]max_flow += path_flowv = sinkwhile(v != source):u = parent[v]self.graph[u][v] -= path_flowself.graph[v][u] += path_flowv = parent[v]return max_flowgraph = [[0, 16, 13, 0, 0, 0],[0, 0, 10, 12, 0, 0],[0, 4, 0, 0, 14, 0],[0, 0, 9, 0, 0, 20],[0, 0, 0, 7, 0, 4],[0, 0, 0, 0, 0, 0]]g = Graph(graph)source = 0; sink = 5print ("The maximum possible flow is %d " % g.FordFulkerson(source, sink))

运行结果为:

The maximum possible flow is 23

四、其它发现

Edmonds和Karp发明的另一种Ford-Fulkerson算法的实现是优先处理能够将流量增大最多的增广路径。对于这种(以及其他一些)方法,可以通过稍加修改Dijkstra的最短路径算法、由优先队列得到剩余容量最大的正向边或是流量最大的逆向边来实现。或者也可以寻找最长增广路径,或是随机选择增广路径。

各种最大流量算法的分析仍然是一个有趣而活跃的研究领域。从理论角度来说,我们已经得到了各种最大流量算法在最坏情况下的上界,但这些上界大多远远高于实际应用中所观察到的真实成本,而且也比较小的下界(线性级别)高出许多。

“最大流量算法的实际应用仍然既是一门艺术也是一门科学。它的艺术之处在于为特定的应用场景选择最有效的策略;它的科学之处在于对问题本质的理解。”

参考文献

  1. Derigs U, Meier W. Implementing Goldberg’s max-flow-algorithm—A computational investigation[J]. Zeitschrift für Operations Research, 1989, 33(6): 383-403.
  2. Ahuja R K, Kodialam M, Mishra A K, et al. Computational investigations of maximum flow algorithms[J]. European Journal of Operational Research, 1997, 97(3): 509-542.
  3. Cherkassky B V, Goldberg A V. On implementing push-relabel method for the maximum flow problem[C]//International Conference on Integer Programming and Combinatorial Optimization. Springer, Berlin, Heidelberg, 1995: 157-171.
  4. Thomas H. Cormen,Charles E. Leiserson,Ronald L. Rivest,Clifford Stein.算法导论. 美国.麻省理工学院出版社.2009

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

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

相关文章

ubuntu22.04@Jetson Orin Nano之OpenCV安装

ubuntu22.04Jetson Orin Nano之OpenCV安装 1. 源由2. 分析3. 证实3.1 jtop安装3.2 jtop指令3.3 GPU支持情况 4. 安装OpenCV4.1 修改内容4.2 Python2环境【不需要】4.3 ubuntu22.04环境4.4 国内/本地环境问题4.5 cudnn版本问题 5. 总结6. 参考资料 1. 源由 昨天用Jetson跑demo程…

揭秘 LLMs 时代向量数据库的 3 大实用场景

过去一年&#xff0c;ChatGPT 和其他大语言模型&#xff08;LLMs&#xff09;的爆火也带动了向量数据库的发展。 许多用户在搭建检索增强生成&#xff08;RAG&#xff09;系统过程中选择了使用向量数据库 Zilliz Cloud &#xff0c;但 Zilliz Cloud 的功能不止于此&#xff0c;…

Git如何使用 五分钟快速入门

Git如何使用 五分钟快速入门 Git是一个分布式版本控制系统&#xff0c;它可以帮助开发人员跟踪和管理项目的代码变更。与传统的集中式版本控制系统&#xff08;如SVN&#xff09;不同&#xff0c;Git允许开发人员在本地存储完整的代码仓库&#xff0c;并且可以独立地进行代码修…

GEE数据更新——MODIS数据LST地表温度计算案例MODIS/006/ MOD11A1 已弃用并且没有新数据。请改用MODIS/061/ MOD11A1

问题 为什么我无法在下面给出的代码中下载 2024 年的数据?看起来有效期到 2022 年 11 月。你能帮我吗? 差异 MODIS/006/ MOD11A1和MODIS/061/ MOD11A1是两个不同的MODIS地表温度数据集。它们之间的差异主要体现在数据处理方法和时间范围上。目前GEE中已经没有前者的数据。…

《英伟达-本地AI》--NVIDIA Chat with RTX-本机部署

阿丹&#xff1a; 突然发现公司给配置的电脑是NVIDIA RTX 4060的显卡&#xff0c;这不搞一搞本地部署的大模型玩一玩&#xff1f;&#xff1f;&#xff1f; 从0-》1记录一下本地部署的全过程。 本地模型下载地址&#xff1a; Build a Custom LLM with Chat With RTX | NVIDIA…

虚拟机安装Centos7迷你版

虚拟机安装Centos7迷你版 迷你版较常规版精简了很多功能&#xff0c;所以体积也小了很多&#xff0c;喜欢自定义安装的可以选择迷你版 参考文章&#xff1a; VirtualBox虚拟机安装Centos7详细教程图解 网卡配置参考文章 下载Centos迷你版镜像 安装镜像 下载镜像 阿里云Cen…

Python 安装和使用的IDE

安装 安装 Anaconda (包较大), 包含了一些库安装 Miniconda (包较小) 只和 python 打包, 没有其他的包, 用的时候需要自己安装 conda install pandaspython pythonipython 有更多的功能 ipythonjupyter jupyter notebookjupyterlab 可以去 github 查看 conda install -c…

理论学习-ARM-内核

ARM内核 函数的调用加载、存储计算中断异常线程的切换 为了提高学习效率&#xff0c;我们要提前想好学习策略。 首先&#xff0c;使用频率越高的知识点&#xff0c;越要首先学习。假使&#xff0c;我们学习了一个知识点&#xff0c;能覆盖工作中80%的工作量&#xff0c;那是不是…

机器学习基础(四)非监督学习的进阶探索

导语&#xff1a;上一节我们详细探索监督学习的进阶应用&#xff0c;详情可见&#xff1a; 机器学习基础&#xff08;三&#xff09;监督学习的进阶探索-CSDN博客文章浏览阅读296次&#xff0c;点赞13次&#xff0c;收藏11次。监督学习作为机器学习的一个主要分支&#xff0c;…

【C++】vector模拟实现+迭代器失效

vector模拟实现 成员变量定义默认成员函数构造函数 迭代器范围for、对象类型匹配原则 容量操作sizeemptycapacityreserve成员变量未更新memcpy值拷贝 resize内置类型的构造函数 数据访问frontbackoperator[ ] 数据修改操作push_backpop_backswapclearinsertpos位置未更新无返回…

解决缓存失效导致的数据库压力问题(缓存击穿问题)

问题描述 在软件开发过程中&#xff0c;特别是在使用缓存策略优化数据访问性能时&#xff0c;经常会遇到缓存失效引发的问题。具体来说&#xff0c;在一个服务类BaseDataService中&#xff0c;findData方法负责从数据库拉取数据并缓存。这里使用了expireAfterWrite60s的缓存策…

【Linux】Linux调试器-gdb使用

1. 背景 程序的发布方式有两种&#xff0c;debug模式和release模式 Linux gcc/g出来的二进制程序&#xff0c;默认是release模式 要使用gdb调试&#xff0c;必须在源代码生成二进制程序的时候, 加上 -g 选项 2. 开始使用 gdb binFile 退出&#xff1a; ctrl d 或 quit 调…

新建一个flask项目

在Flask中创建一个新的项目&#xff0c;您可以遵循以下步骤&#xff1a; 确保您已经安装了Python环境。如果还未安装Flask&#xff0c;可以通过pip来安装&#xff1a; pip install flask创建一个新的文件夹作为您的项目文件夹&#xff0c;例如myflaskapp&#xff1a; mkdir …

Java 学习和实践笔记(15):面向过程和面象对象其实很简单!

学完这一节&#xff0c;才真正明白了什么叫面向对象和面向过程&#xff0c;其实很简单~ 第一个例子&#xff1a;怎样把大象装进冰箱 这个很清楚很容易地可以列出第一步。 第二个例子&#xff1a;怎样制造一台汽车 这个就很难确定哪一步做第一步。 面向过程和面向对象的区别 …

echarts折线图单位为Bit/s的数据展示

需求&#xff1a;单位为Bit/s的数据需要换算y轴、legend和tooltip的单位&#xff1b; 显示数据时需要换算单位是因为数据以比特每秒&#xff08;Bit/s&#xff09;的形式返回&#xff0c;但是在实际展示中&#xff0c;可能更方便和易读的是使用其他单位&#xff0c;例如Gb/s、M…

8 磁盘存储器的管理

外存的组织方式 连续组织方式&#xff1a;为每一个文件分配一组相邻接的盘块 链接组织方式&#xff1a;多个不连续的盘块 链接指针 隐式链接 显示链接&#xff1a;文件分配表FAT FAT技术&#xff1a; FAT12&#xff08;512B&#xff09;、以簇为单位的FAT12文件系统、FAT16、…

笔记:torch.roll

最近在准备写 swin transformer 的文章&#xff0c;记录下 torch.roll 的用法&#xff1a; >>> x torch.tensor([1, 2, 3, 4, 5, 6, 7, 8]).view(4, 2) >>> x tensor([[1, 2],[3, 4],[5, 6],[7, 8]]) 第0维度向下移1位&#xff0c;多出的[7,8]补充到顶部 &g…

【移动开发】iOS平台 Java编译器 Jedona Compiler 评测

上期编译器评测链接&#xff1a; Java Compiler IDE评测 一、使用平台 该编译器&#xff08;Jedona Compiler&#xff09;在苹果应用市场App Store中下载&#xff0c;笔者使用iPad进行Java代码编写。 应用市场界面&#xff1a; 二、开发界面介绍 开发界面比较简洁&#xf…

【JGit 】简述及学习资料整理

JGit 介绍 [官网](JGit | The Eclipse Foundation): https://www.eclipse.org/jgit/ 用户指南 : https://github.com/eclipse-jgit/jgit/wiki/User-Guide JGit是一个用于Java编程语言的开源Git实现。它提供了一组Java库和API&#xff0c;使开发人员可以在他们的Java应用程序…

python 与 neo4j 交互(py2neo 使用)

参考自&#xff1a;neo4j的python.py2neo操作入门 官方文档&#xff1a;The Py2neo Handbook — py2neo 2021.1 安装&#xff1a;pip install py2neo -i https://pypi.tuna.tsinghua.edu.cn/simple 1 节点 / 关系 / 属性 / 路径 节点(Node)和关系(relationship)是构成图的基础…