网络流问题
在数学规划中,网络流问题是指一类基于网络模型的流量分配问题。网络流问题的目标是在网络中分配资源,使得网络的流量满足一定的限制条件,并且使得某些目标函数最小或最大化。网络流问题通常涉及一个有向图,图中每个节点表示一个资源,每条边表示资源之间的关系。边上有一个容量值,表示该边上最多可以流动的资源数量。流量从源节点开始流出,经过一系列中间节点,最终到达汇节点。在这个过程中,需要遵守一定的流量守恒和容量限制条件。
具体而言,网络流问题可以分为最大流和最小割两类。最大流问题是寻找在网络中从源节点到汇节点的最大流量,而最小割问题是寻找一组割,将网络划分为两个部分,并且通过这些割的容量之和最小化。如在有向图中分配流量,使每条边的流量不会超过它的容量约束,同时达到路径长度最小或者花费最小等目标函数的优化问题。
网络流问题在实际应用中非常广泛,如货物运输、通信网络、电力网络等:
- 物流:求解仓网规划问题。
- 制造:求解工厂的排班排产问题。
- 交通:求解车辆和货物的匹配问题。
- 通信:求解网络设施的规划, 通信管道的调优问题。
- 能源:求解石油、天然气、电力的最优配送问题。
接下来我们通过两个案例讲解业务场景中遇到的网络流问题,如何运用数学规划的方法建模、采用 MindOpt APL来建模和调用求解器求解它们。
本篇是第一个案例:交通调度_最大化通行量
1. 交通问题规划
已知有
a
,
b
,
c
,
d
,
e
,
f
,
g
a,b,c,d,e,f,g
a,b,c,d,e,f,g七个站点,每个站点都有若干条进站道路与出站道路,道路旁的数字表示单位时间内此路所能承载的最大车辆数,问如何分配车辆使得单位时间从站点
a
a
a出发,最后到达站点
g
g
g的车辆最多?
2. 数学规划模型
以上问题的数学模型如下。
集合
- 站点集合 S S S
- 中间站点集合 M M M
- 路线集合 R R R,是 S S S站点可连接的集合
参数
- 起点 e = a e=a e=a, a ∈ S a \in S a∈S
- 道路 r ∈ R r \in R r∈R最少能通过的车辆数 l b r lb_r lbr
- 道路 r ∈ R r \in R r∈R最多能通过的车辆数 u b r ub_r ubr
变量
单位时间,道路 r ∈ R r \in R r∈R通过的车辆数 x r x_r xr
目标函数
最大化从起点 e e e站出发的车的数量,即经过该点的道路的车辆数之和: max ∑ e j ∈ R x e j \max \sum_{ej \in R}x_{ej} max∑ej∈Rxej
约束
进入中间站点 k ∈ M k \in M k∈M车的数量等于该站点出去车的数量 ∑ i ∈ S x i k = ∑ j ∈ S x k j \sum_{i \in S} x_{ik}=\sum_{j \in S} x_{kj} ∑i∈Sxik=∑j∈Sxkj
这里我们汇总的数学模型为:
max ∑ e j ∈ R x e j s . t . ∑ i k ∈ R x i k = ∑ k j ∈ R x k j , ∀ k ∈ M u b r ≥ x r ≥ l b r , ∀ r ∈ R \begin{align} \max & \quad \sum_{ej \in R}x_{ej} \\ \rm{s.t.} & \quad \sum_{ik \in R} x_{ik}=\sum_{kj \in R} x_{kj}, \forall k\in M\\ & \quad ub_r \ge x_{r}\ge lb_r,\ \ \forall r \in R \end{align} maxs.t.ej∈R∑xejik∈R∑xik=kj∈R∑xkj,∀k∈Mubr≥xr≥lbr, ∀r∈R
3. MindOpt APL 建模和求解
MindOpt APL是一款代数建模语言,它可以方便地将数学语言描述成程序,然后调用多种求解器求解。MindOpt Solver对网络流的线性规划求解效率很不错,且能支持大规模的问题。
改写上面的数据图和数学模型,如下代码,在Notebook的cell中运行它:
clear model;
# 建模
# net1.mapl
set Station :={"a","b","c","d","e","f","g"};
set Middle := {"b","c","d","e","f"};
set Roads :={<"a","b">,<"b","d">,<"c","d">,<"d","e">,<"e","g">,<"a","c">,<"b","e">,<"c","f">,<"d","f">,<"f","g">};
param entr := "a";
param lb := 0;
param ub[Roads] := <"a","b"> 50, <"b","d"> 40, <"c","d"> 60, <"d","e"> 50, <"e","g"> 70, <"a","c"> 100, <"b","e"> 20, <"c","f"> 20, <"d","f"> 60, <"f","g"> 70;
var x[<i,j> in Roads] >= lb <= ub[i,j];
maximize Total : sum {<entr,j> in Roads } x[entr,j]; #起点进入的最大流量
#流量均衡
subto Balance:
forall <k> in Middle do
sum {<i,k> in Roads} x[i,k] == sum {<k,j> in Roads } x[k,j];
print "-----------------用MindOpt求解---------------";
option solver mindopt; # (可选)指定求解用的求解器,默认是MindOpt
#option mindopt_options 'print=0'; #设置求解器输出级别,减少过程打印
solve; # 求解
print "-----------------Display---------------";
display; # 展示结果
print "经过优化后,最大流量=" ,sum {<entr,j> in Roads } x[entr,j];
运行结果如下:
-----------------用MindOpt求解---------------
Running mindoptampl
wantsol=1
mip_integer_tolerance=1e-9
MindOpt Version 0.24.1 (Build date: 20230423)
Copyright (c) 2020-2023 Alibaba Cloud.
Start license validation (current time : 29-JUN-2023 21:31:04).
License validation terminated. Time : 0.006s
Only one thread allowed -- optimize with Simplex method.
Model summary.
- Num. variables : 10
- Num. constraints : 5
- Num. nonzeros : 16
- Bound range : [2.0e+01,1.0e+02]
- Objective range : [1.0e+00,1.0e+00]
- Matrix range : [1.0e+00,1.0e+00]
Presolver started.
Presolver terminated. Time : 0.000s
Simplex method started.
Model fingerprint: ==gZ3B2didHZ
Iteration Objective Dual Inf. Primal Inf. Time
0 1.30000e+02 0.0000e+00 4.0000e+00 0.01s
2 1.30000e+02 0.0000e+00 0.0000e+00 0.01s
Postsolver started.
Simplex method terminated. Time : 0.001s
OPTIMAL; objective 130.00
2 simplex iterations
Completed.
-----------------Display---------------
Primal Solution:
x@<a,b> = 50.0000
x@<a,c> = 80.0000
x@<b,d> = 30.0000
x@<b,e> = 20.0000
x@<c,d> = 60.0000
x@<c,f> = 20.0000
x@<d,e> = 50.0000
x@<d,f> = 40.0000
x@<e,g> = 70.0000
x@<f,g> = 60.0000
经过优化后,最大流量=130
4. 结果
运行上述代码后,得到结果为:
Primal Solution:
x@<a,b> = 50.0000
x@<a,c> = 80.0000
x@<b,d> = 30.0000
x@<b,e> = 20.0000
x@<c,d> = 60.0000
x@<c,f> = 20.0000
x@<d,e> = 50.0000
x@<d,f> = 40.0000
x@<e,g> = 70.0000
x@<f,g> = 60.0000
最大流量=130
即,从 a a a站最多可出发130辆车。并且分流的流量为,如下图
- a到b是50,到c是80;
- b到d是30,到e是20
- c到d是60,到f是20
- d汇总了90的流量,分流到e是50,到f是40
- e汇总了70的流量
- f汇总了60的流量
-它们都汇总到出口g,总共是130
- d汇总了90的流量,分流到e是50,到f是40