打编程之026:职员时序安排模型

打编程之026:职员时序安排模型

这是一个经典的循环排班问题,也称为覆盖问题。

打编程系列里的数据和代码都被全部共享出来,没有额外的限制!

职员时序安排问题 是不同于之前的打编程之019:人员排班问题, 这个是更简单的一类问题,只有两个简单的要求,一是员工不能连续工作5天,二是需要满足一天的用工数量!

问题描述

一项工作一周七天都需要有人,每天(周一至周日)所需的最少职员数见下表:

周一 周二 周三 周四 周五 周六 周日
20 16 13 16 19 14 12
  • 每个员工每周上班 5 天,且必须是连续的 5 天(余下的 2 天休息)。

  • 要求:安排最少的员工总数,使得每天的人员安排满足/超过需求。

试求每周所需最少的职员数,并给出安排.

LINGO求解

我算是理解了,为什么那么多人选择LINGO来求解一些优化问题了。简单,易于上手编程,不需要注重背后的算法的选择,只需要鼠标点击操作即可,而且还有丰富的函数可用。

尤其是在每年的数学建模竞赛中,那是求解优化问题的首先选择!

之前的文章已经详细介绍了LINDO系列的算法:

为了图方便快捷,你也可以使用LINGO来处理,其代码如下(复制到LINGO中,运行即可!):

model:
!定义集合;
sets:
  days/Mon..Sun/:required,start;
endsets
!输入数据;
data:
!每天所需的最少职员数;
  required=20 16 13 16 19 14 12;
enddata
!最小化每周所需职员数; 
min=@sum(days:start);
!约束条件:连续工作5天;
@for(days(J):
@sum(days(I)|I#le#5:
start(@wrap(J+I+2,7)))>=required(J));   
end

其中,LINGO中的函数:

@WRAP(INDEX, LIMIT) 返回的是 INDEX - K * LIMIT, 其中K是一个整数,它使得返回值落到[1,LIMIT]上;

DBS25.lg4
得到的结果是:

START( MON)  = 8.000000
START( TUE)  = 2.000000
START( WED)  = 0.000000
START( THU)  = 6.000000 
START( FRI)  = 3.000000
START( SAT)  = 3.000000
START( SUN)  = 0.000000

可以计算得到,一共有 $22$ 位员工!

优化模型

没有明确有多少个职员,只是要求:

  • 每个职员一周连续工作5天,
  • 满足每天的用工需求,

然后问每周所需最少的职员数!

值得注意的是:这好像是问最少招聘多少个职员,才能满足生产需求!

1、第一个急需要解决的问题:未知变量的设置!

首先,把哪个数据设置为未知变量 $x$?

根据要求,我们可以设置未知变量:

  • $x_1$: 周一开始连上 5 天(周一~周五)的员工数

  • $x_2$: 周二开始 (周二~周六)的员工数

  • $x_3$: 周三开始 (周三~周日)的员工数

  • $x_4$: 周四开始 (周四~下周一)的员工数

  • $x_5$: 周五开始 (周五~下周二)的员工数

  • $x_6$: 周六开始 (周六~下周三)的员工数

  • $x_7$: 周日开始 (周日~下周四)的员工数

详细的解释如下:

变量 开始工作日 连续工作日区间 含义说明
x₁ 周一 周一 ~ 周五 周一开始连上5天的员工数
x₂ 周二 周二 ~ 周六 周二开始连续5天上班的员工数
x₃ 周三 周三 ~ 周日 周三开始连续5天上班的员工数
x₄ 周四 周四 ~ 下周一 周四开始连续5天上班的员工数
x₅ 周五 周五 ~ 下周二 周五开始连续5天上班的员工数
x₆ 周六 周六 ~ 下周三 周六开始连续5天上班的员工数
x₇ 周日 周日 ~ 下周四 周日开始连续5天上班的员工数

2、第二个急需要解决的问题:未知变量的约束条件!

也就是要解决,每天的需求人数。我们首先看一看周一的情况,其需求人数为$20$. 于是,我们需要统计在周一工作的员工,再根据变量的设置含义,我们得到,

周一上班人数约束

$x_1 + x_4 + x_5 + x_6 + x_7 \geq 20$.

同理,我们可得到周二上班人数约束
$x_1 + x_2 + x_5 + x_6 + x_7 \geq 16$

周三上班人数约束

$x_1 + x_2 + x_3 + x_6 + x_7 \geq 13$

周四上班人数约束

$x_1 + x_2 + x_3 + x_4 + x_7 \geq 16$

周五上班人数约束

$x_1 + x_2 + x_3 + x_4 + x_5 \geq 19$

周六上班人数约束

$x_2 + x_3 + x_4 + x_5 + x_6 \geq 14$

周日上班人数约束

$x_3 + x_4 + x_5 + x_6 + x_7 \geq 12$

3、第二个容易解决的问题:目标函数的表达式!

根据题设“安排最少的员工总数”,我们得到目标函数为:

$\max Z = x_1 + x_2 + x_3 + x_4 + x_5 + x_6 + x_7$

于是,我们得到如下的优化模型:

$$
\begin{aligned}
\max Z = x_1 + x_2 + x_3 + x_4 + x_5 + x_6 + x_7 \
\rm{s.t} ~
\begin{cases}
x_1 + x_4 + x_5 + x_6 + x_7 \geq 20 \
x_1 + x_2 + x_5 + x_6 + x_7 \geq 16 \
x_1 + x_2 + x_3 + x_6 + x_7 \geq 13\
x_1 + x_2 + x_3 + x_4 + x_7 \geq 16 \
x_1 + x_2 + x_3 + x_4 + x_5 \geq 19 \
x_2 + x_3 + x_4 + x_5 + x_6 \geq 14 \
x_3 + x_4 + x_5 + x_6 + x_7 \geq 12
\end{cases}
\end{aligned}
$$

模型求解

首先,数据准备如下:

#定义个类型为 String 的数据
Weekc=["周一";"周二";"周三";"周四";"周五";"周六";"周日"];
Week=["Monday";"Tuesday";"Wednesday";"Thursday";"Friday";"Saturday";"Sunday"];
#每天需求员工数量
D = [20;16;13;16;19;14;12]

其次,建立优化模型

# 导入建模语言
using JuMP
# 导入混合整数线性求解器
using HiGHS
# 建立具体的优化模型
DBS26 = Model(HiGHS.Optimizer)

最后,构建变量、约束条件和目标函数

# 创建 整数 变量
@variable(DBS26,x[Week],Int);
# 约束条件
@constraint(DBS26,MaxCap,
sum( x[i]*W[i] for i in Week ) <= M);
# 增加目标函数
@objective(DBS25,Min,
sum( x[i] for i in Week ) );

接下来,我们求解 0-1 背包问题

# 求解模型
optimize!(DBS26)
# 输出结果
value.(x)

结果是,

julia> value.(x)
5-element Vector{Float64}:
 1.0
 1.0
 1.0
 0.0
 1.0

以上是利用软件求解的,当然了,也可以采取其他算法来求解,我们后续待续.....

如有疑问,尽可联系

boyogala@outlook.com

文字的的待审核、检查和批复

本文由mdnice多平台发布

posted @ 2025-08-13 12:09  博優旮旯  阅读(41)  评论(0)    收藏  举报