前言
最大流问题(maximum flow problem),一种组合最优化问题,就是要讨论如何充分利用装置的能力,使得运输的流量最大,以取得最好的效果。求最大流的标号算法最早由福特和福克逊于1956年提出,20世纪50年代Ford,Fulkerson建立的“网络流理论”,是网络应用的重要组成成分。下图为一个简单的网络流问题示意,共5个节点,编号为0、1、2、3、4,节点相连的边为可以通过的最大流量,箭头所指为流向,现欲求从节点0到节点4的最大流量。
代码
or-tools中提供了求解网络流问题的标准接口,本文自行建模并采用线性规划求解器进行求解,print(solver.ExportModelAsLpFormat(False)) 可将模型输出,用于验证模型正确性。
from ortools.linear_solver import pywraplp
solver = pywraplp.Solver.CreateSolver('GLOP')
# 数据
# capacity[i][j]:节点i到接待你j的最大流量
source = 0
target = 4
num_node = 5
capacity = [[0, 20, 30, 10, 0], [0, 0, 40, 0, 30], [0, 0, 0, 10, 20], [0, 0, 5, 0, 20], [0, 0, 0, 0, 0]]
# 变量
x = [[solver.NumVar(0, solver.infinity(), 'x[{}][{}]'.format(i, j)) for j in range(num_node)] for i in range(num_node)]
# 目标
solver.Maximize(sum([x[i][target] for i in range(num_node)]))
# 约束
# 1 容量约束
for i in range(num_node):
for j in range(num_node):
solver.Add(x[i][j] <= capacity[i][j], 'capacity_constraints[{}][{}]'.format(i, j))
# 2 平衡约束
for i in range(num_node):
if i != source and i != target:
solver.Add(sum([x[i][j] for j in range(num_node)]) == sum([x[j][i] for j in range(num_node)]),
'balance_constraints[{}]'.format(i))
# 求解
print(solver.ExportModelAsLpFormat(False)) # 输出结果
status = solver.Solve()
# 结果
if status == solver.OPTIMAL:
print('objective=', solver.Objective().Value())
else:
print('no optimal solution found')
结果
\ Generated by MPModelProtoExporter
\ Name :
\ Format : Free
\ Constraints : 28
\ Variables : 25
\ Binary : 0
\ Integer : 0
\ Continuous : 25
Maximize
Obj: +1 x[0][4] +1 x[1][4] +1 x[2][4] +1 x[3][4] +1 x[4][4]
Subject to
capacity_constraints[0][0]: +1 x[0][0] <= 0
capacity_constraints[0][1]: +1 x[0][1] <= 20
capacity_constraints[0][2]: +1 x[0][2] <= 30
capacity_constraints[0][3]: +1 x[0][3] <= 10
capacity_constraints[0][4]: +1 x[0][4] <= 0
capacity_constraints[1][0]: +1 x[1][0] <= 0
capacity_constraints[1][1]: +1 x[1][1] <= 0
capacity_constraints[1][2]: +1 x[1][2] <= 40
capacity_constraints[1][3]: +1 x[1][3] <= 0
capacity_constraints[1][4]: +1 x[1][4] <= 30
capacity_constraints[2][0]: +1 x[2][0] <= 0
capacity_constraints[2][1]: +1 x[2][1] <= 0
capacity_constraints[2][2]: +1 x[2][2] <= 0
capacity_constraints[2][3]: +1 x[2][3] <= 10
capacity_constraints[2][4]: +1 x[2][4] <= 20
capacity_constraints[3][0]: +1 x[3][0] <= 0
capacity_constraints[3][1]: +1 x[3][1] <= 0
capacity_constraints[3][2]: +1 x[3][2] <= 5
capacity_constraints[3][3]: +1 x[3][3] <= 0
capacity_constraints[3][4]: +1 x[3][4] <= 20
capacity_constraints[4][0]: +1 x[4][0] <= 0
capacity_constraints[4][1]: +1 x[4][1] <= 0
capacity_constraints[4][2]: +1 x[4][2] <= 0
capacity_constraints[4][3]: +1 x[4][3] <= 0
capacity_constraints[4][4]: +1 x[4][4] <= 0
balance_constraints[1]: -1 x[0][1] +1 x[1][0] +1 x[1][2] +1 x[1][3] +1 x[1][4] -1 x[2][1] -1 x[3][1] -1 x[4][1] = 0
balance_constraints[2]: -1 x[0][2] -1 x[1][2] +1 x[2][0] +1 x[2][1] +1 x[2][3] +1 x[2][4] -1 x[3][2] -1 x[4][2] = 0
balance_constraints[3]: -1 x[0][3] -1 x[1][3] -1 x[2][3] +1 x[3][0] +1 x[3][1] +1 x[3][2] +1 x[3][4] -1 x[4][3] = 0
Bounds
0 <= x[0][0]
0 <= x[0][1]
0 <= x[0][2]
0 <= x[0][3]
0 <= x[0][4]
0 <= x[1][0]
0 <= x[1][1]
0 <= x[1][2]
0 <= x[1][3]
0 <= x[1][4]
0 <= x[2][0]
0 <= x[2][1]
0 <= x[2][2]
0 <= x[2][3]
0 <= x[2][4]
0 <= x[3][0]
0 <= x[3][1]
0 <= x[3][2]
0 <= x[3][3]
0 <= x[3][4]
0 <= x[4][0]
0 <= x[4][1]
0 <= x[4][2]
0 <= x[4][3]
0 <= x[4][4]
End
objective= 60.0