基于Or-Tools的指派问题建模求解(PythonAPI)

2023-10-29 01:44

本文主要是介绍基于Or-Tools的指派问题建模求解(PythonAPI),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于Or-Tools的指派问题建模求解(PythonAPI)

  • 指派问题(又称为分配问题,assignment problem)
  • 基于Or-Tools的指派问题建模求解(PythonAPI)
    • 导入pywraplp库
    • 数据准备
    • 声明MIP求解器
    • 初始化决策变量
    • 初始化约束条件
    • 目标函数
    • 调用求解器
    • 打印结果
    • 求解结果
    • 完整代码

指派问题(又称为分配问题,assignment problem)

指派问题(又称为分配问题,assignment problem)可以抽象概括为:将n个任务(或物品)分配给m个员工(或背包)的问题。其中,最简单的平衡指派模型是指任务数量和员工数量相等的情形。然而,现实生活中的问题大多是任务数量大于员工数量且员工能力有限的广义指派问题(generalized assignment problem,GAP)。GAP是经典的组合优化问题,许多领域的容量约束问题都可以被抽象为GAP进行求解,如机器调度问题、有容量约束的设施选址问题、供应链问题及车辆路径问题等。

广义指派模型
GAP问题可以描述为:将n个相互独立的任务分配给m个员工,一个任务智能由一个员工来完成,一个员工可以完成多项任务,但员工完成任务的总时间不得超过给定限制。

对于 i = 1 , . . . , m i=1,...,m i=1,...,m j = 1 , . . . , n j=1,...,n j=1,...,n,定义0-1决策变量x_ij=1,表示任务j分配给员工i。令 I = { i ∣ i = 1 , ⋯ , m } I=\{i | i=1,\cdots,m\} I={ii=1,,m}为员工集合, J = { j ∣ j = 1 , ⋯ , n } J=\{j | j=1, \cdots, n\} J={jj=1,,n}为任务集合, b i b_i bi表示员工自身的工作时长限制, r i j r_{ij} rij表示员工 i i i完成任务 j j j需要的时长, c i j c_{ij} cij表示员工 i i i完成任务 j j j所消耗的资源或产生的收益。最终目标函数为成本最小或收益最大,则GAP可表述为
max ⁡ 或 min ⁡ ∑ i ∈ I ∑ j ∈ J c i j x i j \begin{align} \max 或 \,\min \sum_{i \in I} \sum_{j \in J} c_{ij}x_{ij} \end{align} maxminiIjJcijxij s . t . s.t. s.t.
∑ j ∈ J r i j x i j ≤ b i , ∀ i ∈ I ∑ i ∈ I x i j = 1 , ∀ j ∈ J x i j ∈ { 0 , 1 } , ∀ j ∈ J \begin{align} \sum_{j \in J} r_{ij}x_{ij} \leq b_i, \quad \forall i \in I \\ \sum_{i \in I}x_{ij}=1, \quad \forall j \in J \\ x_{ij} \in \{0,1\}, \quad \forall j \in J \end{align} jJrijxijbi,iIiIxij=1,jJxij{0,1},jJ
具有上述形式的整数规划模型被称为广义指派模型。

基于Or-Tools的指派问题建模求解(PythonAPI)

在这个例子中,有5个工人(编号0-4)和4个任务(编号0-3),将工人分配给任务的成本如下表所示:

目标为最小化总成本,约束为每个工人最多完成一个任务,每个任务只能由一个工人完成。这个问题中由于工人数多于任务数,因此有一个工人分不到任务。

导入pywraplp库

from ortools.linear_solver import pywraplp

数据准备

costs = [[90, 80, 75, 70],[35, 85, 55, 65],[125, 95, 90, 95],[45, 110, 95, 115],[50, 100, 90, 100],
]
num_workers = len(costs)  # 工人数量
num_tasks = len(costs[0])  # 任务数量

声明MIP求解器

solver = pywraplp.Solver.CreateSolver("SCIP")

初始化决策变量

x = {}
for i in range(num_workers):for j in range(num_tasks):x[i, j] = solver.IntVar(0, 1, "")

初始化约束条件

# 每个员工至多完成一项任务
for i in range(num_workers):solver.Add(solver.Sum([x[i, j] for j in range(num_tasks)]) <= 1)# 每项任务只能由一个员工完成
for j in range(num_tasks):solver.Add(solver.Sum([x[i, j] for i in range(num_workers)]) == 1)

目标函数

objective_terms = []
for i in range(num_workers):for j in range(num_tasks):objective_terms.append(costs[i][j] * x[i, j])
solver.Minimize(solver.Sum(objective_terms))

调用求解器

status = solver.Solve()

打印结果

if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:print(f"Total cost = {solver.Objective().Value()}\n")for i in range(num_workers):for j in range(num_tasks):# Test if x[i,j] is 1 (with tolerance for floating point arithmetic).if x[i, j].solution_value() > 0.5:print(f"Worker {i} assigned to task {j}." + f" Cost: {costs[i][j]}")
else:print("No solution found.")

求解结果

Total cost = 265.0
Worker 0 assigned to task 3. Cost = 70
Worker 1 assigned to task 2. Cost = 55
Worker 2 assigned to task 1. Cost = 95
Worker 3 assigned to task 0. Cost = 45

完整代码

from ortools.linear_solver import pywraplpdef main():# Datacosts = [[90, 80, 75, 70],[35, 85, 55, 65],[125, 95, 90, 95],[45, 110, 95, 115],[50, 100, 90, 100],]num_workers = len(costs)num_tasks = len(costs[0])# Solver# Create the mip solver with the SCIP backend.solver = pywraplp.Solver.CreateSolver("SCIP")if not solver:return# Variables# x[i, j] is an array of 0-1 variables, which will be 1# if worker i is assigned to task j.x = {}for i in range(num_workers):for j in range(num_tasks):x[i, j] = solver.IntVar(0, 1, "")# Constraints# Each worker is assigned to at most 1 task.for i in range(num_workers):solver.Add(solver.Sum([x[i, j] for j in range(num_tasks)]) <= 1)# Each task is assigned to exactly one worker.for j in range(num_tasks):solver.Add(solver.Sum([x[i, j] for i in range(num_workers)]) == 1)# Objectiveobjective_terms = []for i in range(num_workers):for j in range(num_tasks):objective_terms.append(costs[i][j] * x[i, j])solver.Minimize(solver.Sum(objective_terms))# Solvestatus = solver.Solve()# Print solution.if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:print(f"Total cost = {solver.Objective().Value()}\n")for i in range(num_workers):for j in range(num_tasks):# Test if x[i,j] is 1 (with tolerance for floating point arithmetic).if x[i, j].solution_value() > 0.5:print(f"Worker {i} assigned to task {j}." + f" Cost: {costs[i][j]}")else:print("No solution found.")if __name__ == "__main__":main()

这篇关于基于Or-Tools的指派问题建模求解(PythonAPI)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

解决Nginx启动报错Job for nginx.service failed because the control process exited with error code问题

《解决Nginx启动报错Jobfornginx.servicefailedbecausethecontrolprocessexitedwitherrorcode问题》Nginx启... 目录一、报错如下二、解决原因三、解决方式总结一、报错如下Job for nginx.service failed bec

SysMain服务可以关吗? 解决SysMain服务导致的高CPU使用率问题

《SysMain服务可以关吗?解决SysMain服务导致的高CPU使用率问题》SysMain服务是超级预读取,该服务会记录您打开应用程序的模式,并预先将它们加载到内存中以节省时间,但它可能占用大量... 在使用电脑的过程中,CPU使用率居高不下是许多用户都遇到过的问题,其中名为SysMain的服务往往是罪魁

MySQ中出现幻读问题的解决过程

《MySQ中出现幻读问题的解决过程》文章解析MySQLInnoDB通过MVCC与间隙锁机制在可重复读隔离级别下解决幻读,确保事务一致性,同时指出性能影响及乐观锁等替代方案,帮助开发者优化数据库应用... 目录一、幻读的准确定义与核心特征幻读 vs 不可重复读二、mysql隔离级别深度解析各隔离级别的实现差异

C++ vector越界问题的完整解决方案

《C++vector越界问题的完整解决方案》在C++开发中,std::vector作为最常用的动态数组容器,其便捷性与性能优势使其成为处理可变长度数据的首选,然而,数组越界访问始终是威胁程序稳定性的... 目录引言一、vector越界的底层原理与危害1.1 越界访问的本质原因1.2 越界访问的实际危害二、基

Python多线程应用中的卡死问题优化方案指南

《Python多线程应用中的卡死问题优化方案指南》在利用Python语言开发某查询软件时,遇到了点击搜索按钮后软件卡死的问题,本文将简单分析一下出现的原因以及对应的优化方案,希望对大家有所帮助... 目录问题描述优化方案1. 网络请求优化2. 多线程架构优化3. 全局异常处理4. 配置管理优化优化效果1.

Linux部署中的文件大小写问题的解决方案

《Linux部署中的文件大小写问题的解决方案》在本地开发环境(Windows/macOS)一切正常,但部署到Linux服务器后出现模块加载错误,核心原因是Linux文件系统严格区分大小写,所以本文给大... 目录问题背景解决方案配置要求问题背景在本地开发环境(Windows/MACOS)一切正常,但部署到

MySQL磁盘空间不足问题解决

《MySQL磁盘空间不足问题解决》本文介绍查看空间使用情况的方式,以及各种空间问题的原因和解决方案,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录查看空间使用情况Binlog日志文件占用过多表上的索引太多导致空间不足大字段导致空间不足表空间碎片太多导致空间不足临时表空间

Mybatis-Plus 3.5.12 分页拦截器消失的问题及快速解决方法

《Mybatis-Plus3.5.12分页拦截器消失的问题及快速解决方法》作为Java开发者,我们都爱用Mybatis-Plus简化CRUD操作,尤其是它的分页功能,几行代码就能搞定复杂的分页查询... 目录一、问题场景:分页拦截器突然 “失踪”二、问题根源:依赖拆分惹的祸三、解决办法:添加扩展依赖四、分页

Java中InputStream重复使用问题的几种解决方案

《Java中InputStream重复使用问题的几种解决方案》在Java开发中,InputStream是用于读取字节流的类,在许多场景下,我们可能需要重复读取InputStream中的数据,这篇文章主... 目录前言1. 使用mark()和reset()方法(适用于支持标记的流)2. 将流内容缓存到字节数组

解决若依微服务框架启动报错的问题

《解决若依微服务框架启动报错的问题》Invalidboundstatement错误通常由MyBatis映射文件未正确加载或Nacos配置未读取导致,需检查XML的namespace与方法ID是否匹配,... 目录ruoyi-system模块报错报错详情nacos文件目录总结ruoyi-systnGLNYpe