前言
指派问题是生产生活中的常见问题,假设我们有m个工人,需要完成n项工作,每个工人最多完成一项任务,且每项任务必须指定一个工人完成,目标是最小化完成所有任务的成本。下图为指派问题的一个简单示意,左侧为工人,右侧为任务,连接标注了对应 工人完成对应任务的成本,表格为工人完成任务的成本的具体数据,行代表工人,列代表任务,共5个工人,4个任务。
代码
from ortools.linear_solver import pywraplp
# 求解器
solver = pywraplp.Solver.CreateSolver('SCIP')
# 数据
worker_number = 5
task_number = 4
cost = [[90, 80, 75, 70], [35, 85, 55, 65], [125, 95, 90, 95], [45, 110, 95, 115], [50, 100, 90, 100]]
# 决策变量
x = [[solver.IntVar(0, 1, '') for j in range(task_number)] for i in range(worker_number)]
# 目标函数
expression = 0
for i in range(worker_number):
for j in range(task_number):
expression += cost[i][j] * x[i][j]
solver.Minimize(expression)
# 约束
for i in range(worker_number):
expression = 0
for j in range(task_number):
expression += x[i][j]
solver.Add(expression <= 1) # 对于每个工人,最多完成一项任务
for j in range(task_number):
expression = 0
for i in range(worker_number):
expression += x[i][j]
solver.Add(expression == 1) # 对于每项任务,有且仅有一个工人完成
# 求解
status = solver.Solve()
# 结果
if status == solver.OPTIMAL:
for i in range(worker_number):
for j in range(task_number):
if x[i][j].solution_value():
print('work {} complete the task {}'.format(i + 1, j + 1))
print('total cost = ', solver.Objective().Value())
else:
print('no optimal solution found')