基于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夜班。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ToBeWritten之让响应团队参与并做好沟通

也许每个人出生的时候都以为这世界都是为他一个人而存在的&#xff0c;当他发现自己错的时候&#xff0c;他便开始长大 少走了弯路&#xff0c;也就错过了风景&#xff0c;无论如何&#xff0c;感谢经历 转移发布平台通知&#xff1a;将不再在CSDN博客发布新文章&#xff0c;敬…

数据结构与算法-前缀树

数据结构与算法-前缀树详解 1 何为前缀树 2 前缀树的代码表示及相关操作 1 何为前缀树 前缀树 又称之为字典树,是一种多路查找树,多路树形结构,是哈希树的变种&#xff0c;和hash效率有一拼&#xff0c;是一种用于快速检索的多叉树结构。 性质&#xff1a;不同字符串的相同…

力扣 -- 5. 最长回文子串

解题步骤&#xff1a; 参考代码&#xff1a; class Solution { public:string longestPalindrome(string s) {int ns.size();vector<vector<bool>> dp(n,vector<bool>(n));//最长回文串的起始位置int start0;//最长回文串的长度int len0;for(int in-1;i>…

一道经典的指针笔试题!!!!

文章目录 写在前面1. 笔试题代码2. 代码解释3. 代码执行运行结果总结 写在前面 本篇文章讲解了一道关于指针和数组的经典笔试题。 前两篇关于指针和数组的讲解&#xff0c;链接如下&#xff1a; 详解C语言指针&#xff08;一&#xff09; 详解C语言指针&#xff08;二&#xf…

紧固行业内卷严重,张友君的飞沃科技能独善其身吗?

文&#xff5c;新熔财经 作者&#xff5c;文泽 “历经转折”的飞沃科技(301232.SZ)于今年6月&#xff0c;登陆资本市场。 公开资料显示&#xff0c;飞沃科技主要从事风电类高强度紧固件业务&#xff0c;主要产品包括预埋螺套、整机螺栓、锚栓组件。公司的实际控制人是张友君…

端口隔离 MAC地址安全配置

二、知识点 目前网络中以太网技术的应用非常广泛。然而&#xff0c;各种网络攻击的存在&#xff08;例如针对ARP、DHCP等协议的攻击&#xff09;&#xff0c;不仅造成了网络合法用户无法正常访问网络资源&#xff0c;而且对网络信息安全构成严重威胁&#xff0c;因此以太网交…

美容美甲小程序商城的作用是什么

美容院往往有很高需求&#xff0c;女性悦己经济崛起&#xff0c;加之爱美化程度提升&#xff0c;无论线下环境还是线上互联网信息冲击&#xff0c;美容服务、化妆产品等市场规格一直稳增不减。 通过【雨科】平台制作美容美甲商城&#xff0c;售卖相关服务/产品&#xff0c;模块…

【多级缓存】

文章目录 1. JVM进程缓存2. Lua语法3. 实现多级缓存3.1 反向代理流程3.2 OpenResty快速入门 4. 查询Tomcat4.1 发送http请求的API4.2 封装http工具4.3 基于ID负载均衡4.4 流程小结 5. Redis缓存查询5.1 实现Redis查询 6. Nginx本地缓存6.1 本地缓存API6.2 实现本地缓存查询 7. …

一文教你如何快速备考云计算HCIE 3.0 !

大家好&#xff0c;在誉天实验辅导老师的耐心帮助下&#xff0c;本人在9月21日的云计算HCIE 3.0考试已顺利通过&#xff0c;很高兴有这个机会给大家分享备考的经历&#xff0c;希望对还在备考的同学能有一定的帮助。 备考准备 在云计算HCIE3.0的课程学习结束之后&#xff0c;就…

Flink--8、时间语义、水位线(事件和窗口、水位线和窗口的工作原理、生产水位线、水位线的传递、迟到数据的处理)

星光下的赶路人star的个人主页 将自己生命力展开的人&#xff0c;他的存在&#xff0c;对别人就是愈疗 文章目录 1、时间语义1.1 Flink中的时间语义1.2 哪种时间语义更重要 2、水位线&#xff08;Watermark&#xff09;2.1 事件时间和窗口2.2 什么是水位线1.3 水位线和窗口的工…

zabbix监控,zabbix部署

目录 zabbix监控 zabbix概述 zabbix 监控原理 zabbix 6.0功能组件 1、Zabbix Server 2、数据库 3.、Web 界面 4、Zabbix Agent 5、Zabbix Proxy 6、Java Gateway Zabbix部署 部署 zabbix 服务端 zabbix的客户端部署 自我监控 添加zabbix的其他客户端主机 zabbix…

React核心原理与实际开发

学习目标 React是啥&#xff1f; 官方定义&#xff1a;将前端请求获取到的数据渲染为HTML视图的JavaScript库。 一、React入门 1、React项目创建 直接创建react&#xff0c;使用初始化会创建package.json npm init -y再安装 2、React基本使用 使用纯JS创建ReactDOM&#…

项目_数据可视化| 折线图.散点图.随机漫步

安装matplotlib 在正式开始编写程序之前&#xff0c;需要先安装pip、matplotlib模块&#xff0c;苹果系统的安装问题在之前的文章中有相关介绍内容&#xff0c;如果pycharm运行模块报错&#xff0c;可以再次检查是否版本兼容问题。 绘制折线图 调用subplot&#xff08;&#x…

C++设计模式-单件(Singleton)

目录 C设计模式-单件&#xff08;Singleton&#xff09; 一、意图 二、适用性 三、结构 四、参与者 五、代码 C设计模式-单件&#xff08;Singleton&#xff09; 一、意图 保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。 二、适用性 当类只能有一…

机器学习 不均衡数据采样方法:imblearn 库的使用

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…

BigDecimal使用方法

文章目录 引入BigDecimaBigDecima的使用舍入模式updownCEILINGFLOORhalf_UPhalf_UP BigDecimal存储原理总结 引入 知识引入:如下图 0.266小数部分二进制需要55位存储,如果我们double接收那么将丢掉最后三位,所以我们在代码中进行小鼠的加减运算结果有时候并不是我们想要的 Bi…

如何实现chatGPT批量问答,不用token

3分钟&#xff0c;教你做个GPT批量问答还不用token | 有源码 解压压缩包&#xff1b;在Pycharm打开这个文件夹 执行 pip install undetected_chromedriver 和 pip install selenium 执行第1到63行代码&#xff0c;后台会自动打开浏览器&#xff0c;需要手动登录账号和点掉系…

Visual Studio自定义模板参数、备注

模板路径&#xff1a; VS2022 x64&#xff1a;C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\ItemTemplatesVS2022 x86&#xff1a;C:\Program Files (x86)\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\ItemTemplates 一、声明和启用模板…

想升级macOS Big Sur,但是MacBook内存空间不够该怎么办?

随着使用时间的增长&#xff0c;我们会发现Mac电脑的存储空间越来越少&#xff0c;这时候我们就需要对Mac电脑进行清理&#xff0c;以释放更多的存储空间。那么&#xff0c;Mac空间不足怎么解决呢&#xff1f; 1.清理垃圾文件 Mac空间不足怎么解决&#xff1f;首先要做的就是清…

Tomcat服务器下载、安装、配置环境变量教程(超详细)

请先配置安装好Java的环境&#xff0c;若没有安装&#xff0c;请参照如下博客上的步骤进行安装&#xff01; 安装Java环境教程Windows配置Java环境变量(下载、安装、配置环境)_第三女神程忆难的博客-CSDN博客 Tomcat部署Web项目&#xff08;一&#xff09;内嵌 Tomcat部署网站…