网络流问题介绍:
网络流是指在图中给定源点和汇点的前提下,通过网络中的边传输流量,使得从源点到汇点的流量最大(或最小)的问题。在网络中,每一条边都有一个容量(表示能够通过该边的最大流量),每个点都有一个出入流量的平衡限制。网络流问题的基本特点是将问题转化为图模型,用图论算法解决,如最大流算法、最小割算法、最大权闭合子图等。
网络流问题可以用于许多实际问题的建模,如物流配送问题、交通流量优化问题、电力网络问题等。最大流问题是最基础和常见的网络流问题,例如在一个污染源通过河流将污染物排放到下游地区,但是在不同的时间段污染物的流量不同,如何安排排放时间和量以使得下游受污染的程度最小。求解此问题就可以利用最大流算法,将河流视为一个网络,求解从污染源到下游地区的最大流量,以此来安排污染物的排放时间和量。
在实际应用中,由于复杂度的限制,网络流问题往往需要通过一些优化方法来求解。常见的优化方法有增广路算法、最小费用最大流算法、最大流最小费用算法等。
经典网络流问题:
-
最大流问题:在一张有向图中,给定源点和汇点,每条边都有一个容量限制,求从源点到汇点的最大流量。
-
最小割问题:在一张有向图中,给定源点和汇点,每条边都有一个容量限制,将图中的点分成两个集合S和T,要求源点在S中,汇点在T中,且S和T之间的割的容量最小。
-
二分图最大匹配问题:给定一张二分图,求其中的一个最大匹配,即选择最多的边,使得每个节点最多与一个节点匹配。
-
最大权闭合子图问题:给定一张有向图,每个节点有一个权值,求一个点集S,使得S中的点能够到达所有其他点,并且S中节点权值之和最大。
-
最大流最小花费问题:在一张有向图中,给定源点和汇点,每条边都有一个容量和一个费用,求从源点到汇点的最大流同时满足最小费用。
代码实现:
经典网络流问题(最大流最小花费问题)
给定源点汇点及线路费用:有一些供应商节点(i)及需求节点(j),已知每个供应商产量(Pi),用户需求量(Di),以及每条路径运输成本(Cij)
目标:最小化运输成本
注意:约束条件中不能含有np矩阵,需出现矩阵时增加变量声明
import gurobipy as gp
from gurobipy import *
import numpy as np
# 原始数据
N_i = 3 # 供应节点数
N_j = 4 # 需求节点数
C_ij = np.array([[0.0755, 0.0655, 0.0498, 0.0585],
[0.0276, 0.0163, 0.0960, 0.0224],
[0.0680, 0.0119, 0.0340, 0.0751]
]) # 各线路费用
P_min = np.array([100,50,30]) # 最小出力
P_max = np.array([450,350,500]) # 最大出力
demand = np.array([217,150,145,244]) # 负荷需求
# 模型建立
m = gp.Model("网络流问题")
# 变量声明
x = m.addVars(N_i, N_j, vtype=GRB.CONTINUOUS, lb=0, name="x") # 运输方式
u = m.addVars(N_i,vtype=GRB.BINARY,name="u") # 每个供应商是否出力
# 设置目标函数
m.setObjective(quicksum(C_ij[i,j]*x[i,j] for i in range(N_i) for j in range(N_j)), GRB.MINIMIZE)
# 添加约束
# 输出约束,若 P 不等于 0,则每个 P 在 P_max 与 P_min 之间
m.addConstrs((quicksum(x[i, j] for j in range(N_j)) >= P_min[i] * u[i] for i in range(N_i)), name="con1")
m.addConstrs((quicksum(x[i, j] for j in range(N_j)) <= P_max[i] * u[i] for i in range(N_i)), name="con2")
# 负荷约束
m.addConstrs((quicksum(x[i, j] for i in range(N_i)) >= demand[j] for j in range(N_j)), name="con3")
# 模型求解
m.optimize()
# 输出
m.getVars()
x_c = np.zeros([N_i , N_j], dtype=float)
for j in range(N_j):
for i in range(N_i):
x_c[i,j] = x[i,j].x
print('x_c is',x_c)