文章目录

  • 背景
    • 问题调研
    • 工具查找——找巨人的肩膀
  • Action
    • Code example
      • or-tools的基本用法
      • 参数调整
    • 画甘特图
  • 总结

背景

上次周末碰到女朋友在排班表,花了快一个小时,就想着看用代码帮她节省点时间。

问题调研

上网查了一下,看了几篇论文了解了背景。

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.1030.5363&rep=rep1&type=pdf
https://arxiv.org/pdf/1804.05002.pdf

排班之类的问题都统称为 Nurse Rostering Problem(NRP)问题,就复杂性而言,这是一个NP-hard问题

P问题是在多项式时间内可以被解决的问题,而NP问题是在多项式时间内可以被验证其正确性的问题

多项式时间指的是什么?我理解就是平时计算的算法复杂度

O(1) – constant-time
O(log_2(n)) – logarithmic-time
O(n) – linear-time
O(n^2) – quadratic-time
O(n^k) – polynomial-time
O(k^n) – exponential-time
O(n!) – factorial-time

关于NP问题的描述可以看看我找到的这篇文章

提及复杂性理论,是因为更精准地分析问题后,才能找到合适的工具。

这类问题我们就会想到用计算机科学里面的方法去处理,例如machine learning。

工具查找——找巨人的肩膀

机器学习的技术栈,我学过的就是Python中的scikit-learn、TensorFlow和Keras上去做选择

据我了解,这是一个研究了多年的课题了。既然这样,应该是会有现成训练好的模型去做这类事情。

最后的最后,我就找到了Google开发的OR-Tools(Official Site)。它已经有训练过的模型去处理这类排班问题了。

Action

Code example

官方例子Source Code

主要就是对源码做调整了,以满足现实需求。

or-tools的基本用法

摘抄的伪代码,用于了解工作方式

// 选择和定义一个model,然后设置所需的前置数据和限制条件
model = cp_model.CpModel()
model.NewBoolVar(...)
model.AddExactlyOne(...)
model.Add(...)// 选择和定义一个solver,然后针对model进行optimizate
solver = cp_model.CpSolver()
status = solver.Solve(model, solution_printer)// 创建一个矩阵进行拟合
work = {}
for e in range(num_employees):for s in range(num_shifts):for d in range(num_days):work[e, s, d] = model.NewBoolVar('work%i_%i_%i' % (e, s, d))
// 下面是打印结果的算法
if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:print()header = '          'for w in range(num_weeks):header += 'M T W T F S S 'print(header)for e in range(num_employees):schedule = ''for d in range(num_days):for s in range(num_shifts):if solver.BooleanValue(work[e, s, d]): // NOTE: 获取优化算法出来的结果schedule += shifts[s] + ' 'print('worker %i: %s' % (e, schedule))print()

参数调整

例子源码中参数注释都很清楚地标明了用法了,适当对现实问题的需要作出调整就行了。下面伪代码只是针对参数作了一些说明。

num_employees = 4 // 员工数,改为目标的员工数
num_weeks = 5 // 工作天数,目标是排一个月的班表,改为5周
shifts = ['O', 'M', 'A', 'N'] // 班期,和目标一样# Fixed assignment: (employee, shift, day).
# 固定前两天的,排班前得动态调整下
fixed_assignments = [(0, 0, 0),(1, 1, 0),(2, 2, 0),(3, 3, 0),(0, 0, 1),(1, 1, 1),(2, 2, 1),(3, 3, 1),
]# Request: (employee, shift, day, weight)
# 员工想要固定休息的时间(位置),权重值我理解为代表拟合时可调整的优先级
requests = [# Employee 3 does not want to work on the first Saturday (negative weight for the Off shift).(3, 0, 5, -2),# Employee 2 does not want a night shift on the first Friday (positive weight).(2, 3, 4, 4)
]# Shift constraints on continuous sequence :
#     (shift, hard_min, soft_min, min_penalty,
#             soft_max, hard_max, max_penalty)
# hard_min: 硬性限制,在周期内最少连续要上的班期天数
# soft_min: 软性限制,在周期内最少连续要上的班期天数
# soft_max和hard_max同上去理解
shift_constraints = [# One or two consecutive days of rest, this is a hard constraint.(0, 1, 1, 0, 2, 2, 0),# betweem 2 and 3 consecutive days of night shifts, 1 and 4 are# possible but penalized.(3, 1, 2, 20, 3, 4, 5),
]# Weekly sum constraints on shifts days:
#     (shift, hard_min, soft_min, min_penalty,
#             soft_max, hard_max, max_penalty)
weekly_sum_constraints = [# 每周最少要休息的天数(0, 1, 2, 7, 2, 3, 4),
]# Penalized transitions:
#     (previous_shift, next_shift, penalty (0 means forbidden))
penalized_transitions = [# 尽量避免午班换晚班(2, 3, 4),# 晚班不能接着早班(3, 1, 0),
]# daily demands for work shifts (morning, afternon, night) for each day
# of the week starting on Monday.
# 每个班期最少要有多少人,我这里的现实问题是有一个人就行了
weekly_cover_demands = [(1, 1, 1),  # Monday(1, 1, 1),  # Tuesday(1, 1, 1),  # Wednesday(1, 1, 1),  # Thursday(1, 1, 1),  # Friday(1, 1, 1),  # Saturday(1, 1, 1),  # Sunday
]# Penalty for exceeding the cover constraint per shift type.
excess_cover_penalties = (2, 2, 5)num_days = num_weeks * 7
num_shifts = len(shifts)

画甘特图

技术栈中,选择了matplot去画甘特图,也是现学现卖。

# Generate plot image. [reference: https://www.geeksforgeeks.org/python-basic-gantt-chart-using-matplotlib]shifts_colors = ['white', 'tab:green', 'tab:orange', 'tab:blue']if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:offset = 2# Declaring a figure "gnt"fig, gnt = plt.subplots()# Setting Y-axis limitsgnt.set_ylim(0, num_employees * 15)# Setting X-axis limitsgnt.set_xlim(1, num_days + offset)# Setting labels for x-axis and y-axisgnt.set_xlabel('Dates')gnt.set_ylabel('Employees')# Setting ticks on y-axis# gnt.set_yticks([15, 25, 35, 45])gnt.set_xticks(list(range(1, num_days + offset, 1)))gnt.set_yticks(list(range(15, (num_employees + 1) * 10 + 5, 10)))# Labelling tickes of y-axisgnt.set_yticklabels(employees_names)# Setting graph attributegnt.grid(True)for e in range(num_employees):for d in range(num_days):for s in range(num_shifts):if solver.BooleanValue(work[e, s, d]):gnt.broken_barh([(d+1, d+2)], (10*(e+1), 9),facecolors=(shifts_colors[s]))plt.savefig("gantt1.png")

结果:

总结

  • 业界很强大
  • 充分理解问题才能便于找到工具
  • 幸运的是这个topic已经有研究,通过已经有研究过的课题,熟悉工具和解决方法的思路,才能更好地去解决其他问题

实战代码:https://github.com/pascallin/NRP-solver

排班问题——Nurse Rostering Problem(NRP)实战相关推荐

  1. 干货 | 10分钟给上万客服排好班,携程大规模客服排班算法实践

    作者简介 博天,携程高级研发经理,关注大规模约束优化问题的建模和算法设计. 一.背景 客户服务部门是携程以服务质量赢得客户信赖的基石,其拥有上万名一线的客服,每天进线量巨大:且伴随着业务量的起伏,每一 ...

  2. 2021年中国研究生数学建模竞赛F题——航空公司机组优化排班问题

    一.背景介绍 众所周知,一趟民航航班必须在满足特定的条件下才能起飞,这些条件包括国家法律法规,国际公约,政府的行政条例,和公司自身的政策利益,一些国家的工会组织还会对机组人员的福利偏好有规章约束.所有 ...

  3. 【原创】python语言实现半自动排班系统

    python语言实现半自动排班系统 这里写目录标题 python语言实现半自动排班系统 0. 为什么要做这个软件? 1. 本软件要实现哪些功能? 2. 具体功能实现 2.1 识别文本中的格式不一的时间 ...

  4. 使用.Net Core与Google Optimization Tools实现员工排班计划Scheduling

    上一篇说完<Google Optimization Tools介绍>,让大家初步了解了Google Optimization Tools是一款约束求解(CP)的高效套件.那么我们用.Net ...

  5. 巡检路线排班问题matlab,基于数学建模的巡检线路排班设计

    黄家云:基于数学建模的巡检线路排班设计 49 基于数学建模的巡检线路排班设计 黄家云 夏伟 蒋娜 张磊 (芜湖职业技术学院基础部,安徽芜湖,241003) 摘 要:巡检线路的排班设计是 2017 年全 ...

  6. 课表排班java_初学OptaPlanner-02- 基于Spring Boot实现一个简单课程表排班的实例

    Spring Boot Java quick start 01. 排班目标 作出一个简单的课程表timetable,示例如下: 时间表的类图 02. Opta的常用注解说明, 关键实体类说明 @Pla ...

  7. google or-tools的复杂排班程序深度解读

    在google or-tools的官方例子中有一个复杂的员工排班程序(shift_scheduling_sat.py), 由于官方没有给出问题的需求及代码的解释,所以读者对源代码的理解上可能会出现困难 ...

  8. FullCalendar 日历插件排班表排课表保姆级详解(可拖动排班排课)

    (基于vue)实现效果 文章目录 前言 一.FullCalendar是什么? 二.使用步骤 1.引入库 2.html部分代码 3.css样式代码(样式我单独写个scss文件引入的) 4.逻辑代码部分 ...

  9. c语言排班系统设计报告,C语言课程设计关于排班系统的一些问题

    已结贴√ 问题点数:10 回复次数:5 C语言课程设计关于排班系统的一些问题 小女大一,课程设计是百度排班系统(虽然不知老师干嘛现在布置类似小系统的作业),在论坛中找到个代码,其实只要交了代码就好,但 ...

最新文章

  1. 解决POST数据时因启用Csrf出现的400错误
  2. 深度学习中的最大似然估计简介
  3. Spring之AOP由浅入深
  4. [转]div 让文字或图片居中
  5. git pull 部分文件无法获取
  6. 微服务治理实践:如何对单点异常进行自动摘除
  7. C php反序列化,php反序列化漏洞 - anansec的个人空间 - OSCHINA - 中文开源技术交流社区...
  8. Type interface com.zhaoka.mapper.DatKcardKmMapper is not known to the MapperRegistry
  9. 摄像头拍摄后对图片进行图像处理-python(空域增强)
  10. distinct使SQL查询除去重复的字段
  11. Python3 encode中的unicode-escape和raw_unicode_escape
  12. 02 ARM存储控制器   SDRAM操作 实验
  13. 利用JDBC开发图书管理系统
  14. jenkins配置Windows节点
  15. windows下使用rsync
  16. Unity基础:简易道具生成
  17. dellr420部署os_dell r720服务器OS部署
  18. 用IDEA新建一个工程项目并编写HelloWorld
  19. linux meld
  20. 南怀瑾:“心静出贵人”,中年后这三个地方静,一切都会越来越顺!

热门文章

  1. ESXI 6.7全面系统教程~esxi安装过程
  2. Vue audio音乐列表循环播放
  3. SuperMap制图之瓦片技术
  4. MRD市场澎湃生长,臻和科技MRD技术受关注
  5. 使用树莓派3b+作为黑阈激活器
  6. C#HttpUtility.UrlEncode大写问题
  7. 29.VUE自定义指令directive和inserted
  8. 阿里云服务器 通过JavaMail发送邮箱STMP问题( 25端口被禁用 使用SSL协议465端口)
  9. vscode批量删除
  10. 【算法】查理复用算法(Charlieplexing)