当前位置: 首页 > news >正文

基于or-tools的人员排班问题建模求解(JavaAPI)

使用Java调用or-tools实现了阿里mindopt求解器的案例(https://opt.aliyun.com/platform/case)人员排班问题。

这里写目录标题

  • 人员排班问题
  • 问题描述
  • 数学建模
  • 编程求解(ortools+JavaAPI)
  • 求解结果

人员排班问题

随着现在产业的发展,7*24小时服务的需要,人员排班的问题,逐渐成为了企业管理中的重要环节。人员排班在许多行业都具有广泛的应用价值,主要包括以下几个方面:

  • 制造业:生产车间的人员分配、班次安排和轮班计划等,需要根据产线的工作要求和员工的技能特点进行合理的排班。
  • 医疗行业:医院、诊所等机构需要对医生、护士等员工进行排班。
  • 餐饮业:餐厅、咖啡馆等服务场所需要根据客流高峰期和低谷期合理安排员工的工作时间。
  • 零售业:商场、超市等零售场所需要根据营业时间、客流量和节假日等因素进行人员排班。
  • 旅游业:景区、酒店等旅游设施需要根据旅游旺季、淡季和客流量变化对员工进行排班。
  • 客服中心:呼叫中心、在线客服等服务机构需要根据客户咨询需求进行员工排班。

总之,人员排班在各行各业都具有重要的实际应用价值,可以帮助企业和机构提高管理效率、降低成本,同时提升员工的工作满意度和整体效能。总之,人员排班在各行各业都具有重要的实际应用价值,可以帮助企业和机构提高管理效率、降低成本,同时提升员工的工作满意度和整体效能。

运筹学中的数学规划方法是计算人员排班问题的一个好方案。人员排班问题在建模时需要考虑多种约束条件,比如:

  • 用工需求约束:根据各岗位的工作任务和生产要求,保证每个岗位在每个时间段内有足够的员工进行工作。
  • 员工能力约束:不同岗位可能需要不同的技能和经验,需要确保安排到相应岗位的员工具备相关的能力和资质。
  • 工作时间约束:员工的工作时间需要遵守相关法律法规,比如每天工作时间上限、休息时间要求等。此外,还需要考虑员工的工作时间偏好,如部分员工可能只能接受特定时间段的工作安排。
  • 连续工作天数约束:为保证员工的工作质量和身体健康,通常要求连续工作天数不超过一定限制。以及员工在一定时间周期内有休假要求,需要确保他们的休假安排得到满足。
  • 公平性约束:为保障员工的权益,要求在满足以上约束的前提下,尽量平衡各员工的工作时间和任务分配,避免出现工作负担不均衡的情况。
  • 员工偏好:如每个员工有自己更喜欢的上班的时间、岗位、或者协作同事配合等。

我们需要考虑企业内各岗位的需求、员工的工作能力以及工作时间的限制等因素。此外,还需关注企业成本与员工满意度的权衡,以确保在合理控制成本的前提下,最大程度地提高员工的工作满意度。属于一个约束复杂,且多目标的问题。在用数学规划方法进行排班时,建议做一些业务逻辑简化问题,否则容易出现问题太大或者不可解的情况。

下面我们将通过一个简单的例子,讲解如何使用数学规划的方法来做人员排班。

问题描述

个公司有客服岗工作需要安排,不同时间段有不同的用户需求。该公司安排员工上班的班次有三种:早班8-16点、晚班16-24点和夜班0-8点。一周员工最多安排5天上班,最少休息2天。需要保障值班员工能满足需求,且要保障员工休息时间,如前一天安排晚班后,第二天不能安排早班。

请问怎么安排总上班的班次最少,此时的班表是什么样的?

数学建模

在这里插入图片描述
在这里插入图片描述

编程求解(ortools+JavaAPI)

复制代码不能直接运行,需要在IDEA pom.xml中导入阿帕奇读取csv文件的依赖,并且需要导入ortools的maven依赖。
数据可在文章开头阿里mindopt案例地址中获取。

<dependency><groupId>org.apache.commons</groupId><artifactId>commons-csv</artifactId><version>1.7</version></dependency>
package main.java.mindoptdemo;import com.google.ortools.Loader;
import com.google.ortools.sat.*;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVRecord;import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.IntStream;public class EmployeeSchedulingProblem {public int n_shifts;public int n_days;public int n_employees;int[] days;int[] shifts;int[] employees;int[][] demandOfEmployees;public static Logger logger = Logger.getLogger("myLogger");public int getDemandOfEmployees(int day, int shift) {return demandOfEmployees[day][shift];}public EmployeeSchedulingProblem() throws IOException {demandOfEmployees = this.readFile();employees = IntStream.range(0, n_employees).toArray();days = IntStream.range(0, n_days).toArray();shifts = IntStream.range(0, n_shifts).toArray();}public int[][] readFile() throws IOException {this.n_shifts = 0;try (Reader reader = Files.newBufferedReader(Paths.get("src/main/java/mindoptdemo/班次.csv"))) {Iterable<CSVRecord> records = CSVFormat.DEFAULT.parse(reader);records.iterator().next(); // 跳过第一行for (CSVRecord record : records) {String shift = (record.get(0));   // 星期1到星期7,索引为0,故-1n_shifts += 1;}} catch (IOException e) {logger.warning(e.getMessage());}// 调度周期:7天,3班倒this.n_days = (int) Files.lines(Paths.get(new File("src/main/java/mindoptdemo/需求人数.csv").getPath())).count() - 1;int[][] demandOfEmps = new int[n_days][n_shifts];// commons-csv读取csv文件,需要导入依赖try (Reader reader = Files.newBufferedReader(Paths.get("src/main/java/mindoptdemo/需求人数.csv"))) {Iterable<CSVRecord> records = CSVFormat.DEFAULT.parse(reader);records.iterator().next(); // 跳过第一行for (CSVRecord record : records) {int day = Integer.parseInt(record.get(0)) - 1;   // 星期1到星期7,索引为0,故-1int morningShiftEmpNum = Integer.parseInt(record.get(1)); // 早班需要员工的数量int middleShiftEmpNum = Integer.parseInt(record.get(2));  // 中班需要员工的数量int nightShiftEmpNum = Integer.parseInt(record.get(3));   // 晚班需要员工的数量//保存至二维数组,某天某班次需要的员工数量demandOfEmps[day][0] = morningShiftEmpNum;demandOfEmps[day][1] = middleShiftEmpNum;demandOfEmps[day][2] = nightShiftEmpNum;this.n_employees += morningShiftEmpNum + middleShiftEmpNum + nightShiftEmpNum;}this.n_employees = (int) Math.ceil((double) (this.n_employees) / 5) + 1;} catch (IOException e) {logger.info(e.getMessage());}return demandOfEmps;}public void orToolssolve() {Loader.loadNativeLibraries();// 声明模型CpModel model = new CpModel();// 初始化决策变量Literal[][][] x = new Literal[n_employees][n_days][n_shifts];for (int n : employees) {for (int d : days) {for (int s : shifts) {x[n][d][s] = model.newBoolVar("shifts_n" + n + "d" + d + "s" + s);}}}// 约束:每天各个班次在岗的人数符合需求for (int day = 0; day < days.length; day++) {for (int shift = 0; shift < shifts.length; shift++) {LinearExprBuilder numShiftsWorked = LinearExpr.newBuilder();for (int empNum = 0; empNum < n_employees; empNum++) {numShiftsWorked.add(x[empNum][day][shift]);}model.addLinearConstraint(numShiftsWorked, this.getDemandOfEmployees(day, shift), n_employees);}}// 约束:每人每天最多只有一个班次for (int n : employees) {for (int d : days) {List<Literal> work = new ArrayList<>();for (int s : shifts) {work.add(x[n][d][s]);}model.addAtMostOne(work);}}// 约束:前一天是晚班的,第二天不能是早班for (int e : employees) {for (int d : days) {List<Literal> work = new ArrayList<>();work.add(x[e][d][2]);if (d == 6) {work.add(x[e][0][0]);} else {work.add(x[e][d + 1][0]);}model.addAtMostOne(work);}}// 约束:一周工作工作时间不能超过5天for (int empNum = 0; empNum < n_employees; empNum++) {LinearExprBuilder expr = LinearExpr.newBuilder();for (int day = 0; day < days.length; day++) {for (int shift = 0; shift < shifts.length; shift++) {expr.add(x[empNum][day][shift]);}}model.addLinearConstraint(expr, 0, 5);}// 目标:雇佣的员工最少,即有排班的班次总数最少LinearExprBuilder obj = LinearExpr.newBuilder();for (int n : employees) {for (int d : days) {for (int s : shifts) {obj.add(x[n][d][s]);}}}model.minimize(obj);// 求解CpSolver solver = new CpSolver();CpSolverStatus status = solver.solve(model);if (status == CpSolverStatus.OPTIMAL || status == CpSolverStatus.FEASIBLE) {System.out.printf("%-8s", " ");for (int d = 0; d < n_days; d++) {System.out.printf("\t%d", d + 1);}System.out.println();for (int e : employees) {System.out.printf("employee%d\t", e + 1);int shiftCount = 0;for (int d : days) {int shift = 0;for (int s : shifts) {if (solver.booleanValue(x[e][d][s])) {shift = s + 1;shiftCount += 1;}}System.out.printf("%d\t", shift);}System.out.printf("员工%d这周上%d个班次", e + 1, shiftCount);System.out.println();}} else {System.out.printf("No optimal solution found !");}}public static void main(String[] args) throws IOException {EmployeeSchedulingProblem esp = new EmployeeSchedulingProblem();esp.orToolssolve();}
}

求解结果

每个员工在那一天上第几个班,本文or-tools求解结果,如图所示,如员工1-周1-上夜班,员工2-周1-不上班;0不上班、1早班、2晚班、3夜班。

相关文章:

基于or-tools的人员排班问题建模求解(JavaAPI)

使用Java调用or-tools实现了阿里mindopt求解器的案例&#xff08;https://opt.aliyun.com/platform/case&#xff09;人员排班问题。 这里写目录标题 人员排班问题问题描述数学建模编程求解&#xff08;ortoolsJavaAPI&#xff09;求解结果 人员排班问题 随着现在产业的发展&…...

设备管理团队如何做好停机维护工作_基于PreMaint设备数字化平台

在现代工业生产中&#xff0c;设备的正常运行对于企业的生产效率和利润至关重要。而停机维护作为设备管理的重要环节&#xff0c;旨在确保设备的安全性、可靠性和性能稳定。本文将介绍停机维护的概念&#xff0c;讨论如何计划停机维护&#xff0c;并重点探讨如何通过PreMaint设…...

c++ qt--线程(二)(第九部分)

c qt–线程&#xff08;二&#xff09;&#xff08;第九部分&#xff09; 一.线程并发 1.并发问题&#xff1a; ​ 多个线程同时操作同一个资源&#xff08;内存空间、文件句柄、网络句柄&#xff09;&#xff0c;可能会导致结果不一致的问题。发生的前提条件一定是多线程下…...

​企业数据泄露不断,深信服EDR助企业构建数据“安全屋”

随着数字时代不断发展,数据泄露问题愈发严峻,个人信息安全面临着严重的威胁。近日,加拿大电信巨头加拿大贝尔(Bell Canada)对外披露了一起大规模数据泄露事件,该公司承认黑客入侵其系统,并窃取了190万个用户电子邮件地址以及约1700个用户姓名及活跃电话号码信息,相关损失无法估…...

单线复用iptv影响网速吗?

IPTV单线复用对网速有影响吗&#xff1f;这是一个比较常见的问题。如果你家的局域网是老的100M局域网LAN的路由器&#xff0c;走单线复用会影响你上网速度。但是如果你家的局域网是千兆网络&#xff0c;IPTV单线复用叠加上去的这点流量算不上什么&#xff0c;可以认为不占用网速…...

C语言中常用的字符串处理函数(strlen、strcpy、strcat、strcmp)

文章目录 写在前面1. strlen1.1 函数介绍1.2 模拟实现 2. strcpy2.1 函数介绍2.2 模拟实现 3. strcat3.1 函数介绍3.2 模拟实现 4. strcmp4.1 函数介绍4.2 模拟实现 写在前面 本篇文章介绍了C语言中常用的字符串处理函数&#xff0c;包括strlen、strcpy、strcat和strcmp。文章…...

Suricata – 入侵检测、预防和安全工具

一、Suricata介绍 Suricata是一个功能强大、用途广泛的开源威胁检测引擎&#xff0c;提供入侵检测 (IDS)、入侵防御 (IPS) 和网络安全监控功能。它执行深度数据包&#xff08;网络流量&#xff09;检查以及模式匹配&#xff0c;在威胁检测中非常强大。 工作流程&#xff1a; 主…...

vscode 乱码解决

windows 10 系统 vs code 编译运行和调试 C/C_vscode windows编译_雪的期许的博客-CSDN博客 VS Code默认文件编码时UTF-8&#xff0c;这对大多数情况是没有问题的&#xff0c;却偏偏对C/C有问题。如果以UTF-8编码保存C/C代码&#xff0c;那么只能输出英文&#xff0c;另外使用…...

SpringCloud(37):Spring Cloud Alibaba 综合集成架构演示

Spring Cloud是一个较为全面的微服务框架集,集成了如服务注册发现、配置中心、消息总线、负载均衡、断路器、API网关等功能实现。而在网上经常会发现Spring Cloud与阿里巴巴的Dubbo进行选择对比,这样做其实不是很妥当,前者是一套较为完整的架构方案,而Dubbo只是服务治理与R…...

【单片机】15-AD和DA转换

1.AD转换及其相关背景知识 1.基本概念 1.什么是AD转换&#xff1f; A&#xff08;A&#xff0c;analog&#xff0c;模拟的&#xff0c;D&#xff0c;digital&#xff0c;数字的&#xff09; 现实世界是模拟的&#xff0c;连续分布的&#xff0c;无法被分成有限份&#xff1b;…...

基于FPGA的I2C读写EEPROM

文章目录 前言一、I2C协议1.1 I2C协议简介1.2 物理层1.3 协议层 二、EEPROM2.1 型号及硬件规格2.2 各种读写时序 三、状态机设计四、项目源码&#xff1a;五、实现效果参考资料 前言 本次项目所用开发板FPGA芯片型号为&#xff1a;EP4CE6F17C8 EEPROM芯片型号为&#xff1a;24L…...

Viva Employee Communications Communities部署方案

目录 Viva Employee Communications & Communities产品介绍 1. 沟通中心(Communications Center) 2. 新闻和公告(News and Announcements)...

WPF向Avalonia迁移(三、项目结构)

前提&#xff1a; Avalonia版本11.0.0 1.配置文件 1.1 添加配置文件 1.2 读取配置文件 添加System.Configuration.ConfigurationManager using Avalonia.Controls; using System.Configuration;namespace AvaloniaApplication7.Views {public partial class MainWindow : W…...

cvpr24写作模板pdfLaTex编译器注意点小结

文章目录 1 更改作者显示 Anonymous CVPR submission2 \label标签3 换行符// 与换列符&4 \medskip5 首行缩进6 插入图片6.1 单幅图片6.2 并排显示\hfill Reference https://cvpr.thecvf.com/Conferences/2024 1 更改作者显示 Anonymous CVPR submission 这一行开头加上% …...

windows版php扩展包下载

php8有些扩展需自己下载&#xff0c;像redis 看下phpinfo中的PHP Extension Build&#xff0c;确定自己的php版本 windows.php.net - /downloads/pecl/releases/...

计算机竞赛 题目:基于深度学习的中文汉字识别 - 深度学习 卷积神经网络 机器视觉 OCR

文章目录 0 简介1 数据集合2 网络构建3 模型训练4 模型性能评估5 文字预测6 最后 0 简介 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的中文汉字识别 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &a…...

Django跨域访问 nginx转发 开源浏览器

Django跨域访问 https://blog.csdn.net/lonelysnowman/article/details/128086205 nginx转发 https://blog.csdn.net/faye0412/article/details/75200607/ 开源浏览器 https://www.oschina.net/p/chromiumengine 浏览器油猴开发 https://blog.csdn.net/mukes/article/detail…...

Docker Alist 在线网盘部署

文章目录 拉取镜像创建并运行查看容器自动生成的密码在浏览器中进行访问 挂载本地磁盘 拉取镜像 docker pull xhofe/alist-aria2创建并运行 # -v /data/alist:/opt/alist/data 挂载本地目录 docker run -d --restartalways -v /data/alist:/opt/alist/data -p 5244:5244 -e P…...

Jmeter吞吐量控制器使用小结

吞吐量控制器(Throughput Controller)场景: 在同一个线程组里, 有10个并发, 7个做A业务, 3个做B业务,要模拟这种场景,可以通过吞吐量模拟器来实现.。 添加吞吐量控制器 用法1: Percent Executions 在一个线程组内分别建立两个吞吐量控制器, 分别放业务A和业务B 吞吐量控制器采…...

3分钟轻松实现网关网口连接罗克韦尔AB CompactLogix系列PLC

目录 EG网关网口连接罗克韦尔AB CompactLogix系列PLC 一. 准备工作 1.1 在对接前我们需准备如下物品 1.2 EG20网关准备工作 1.3 PLC准备工作 二. EMCP平台设置 2.1 新增EG设备 2.2 远程配置网关 2.3 网关绑定 2.4 通讯参数设置 2.5 创建设备驱动 2.5.1 添加变量 2.…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)

macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 &#x1f37a; 最新版brew安装慢到怀疑人生&#xff1f;别怕&#xff0c;教你轻松起飞&#xff01; 最近Homebrew更新至最新版&#xff0c;每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

Ubuntu系统多网卡多相机IP设置方法

目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机&#xff0c;交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息&#xff0c;系统版本&#xff1a;Ubuntu22.04.5 LTS&#xff1b;内核版本…...