问题描述
我想知道如何建模每个人必须每个人至少有一个夜班休息时间,不能连续工作两班,我们想要确保每个人的夜班次数和班次总数尽可能接近相同。
我在下面用 PuLP 编写了一个演示程序,但很想知道是否有人对任何 python 包(scipy
、gurobi
等)有想法
更具体地说,我有以下问题:
- 8 个人
- 每天 3 个班次(上午、下午、晚上)
- 18 天
我想将个人分配到轮班以满足以下条件:
- 每班必须有 3 人
- 每个人每天必须工作 1 个班次
- 每个人每天不得超过 2 个班次
- 每个人都必须至少有一个夜班休息时间,最好是两个
- 我们应该尽可能均匀地分配这些轮班,尤其是夜班,还有轮班总数。
- 每个人不得连续轮班工作(例如第 1 天的夜班和第 2 天的早班)
我需要知道如何将这些写为约束 (.addConstraint()
) 或以其他方式将它们包含在目标函数中。
作为目标函数:我已经考虑过最小化夜班次数的最大差异,或者,最小化总班次的最大差异。但我不知道如何将其编码到 PuLP 中。任何帮助将不胜感激!
## Todo: HOW TO ENCODE THE NUMBER OF RESTS FROM NIGHT SHIFT >= 1
## Todo: HOW TO ENCODE NO CONSECUTIVE SHIFTS
我为我的程序编写了以下代码:
import itertools
import pulp.value
from pulp import LpProblem
from pulp import LpVariable,LpBinary,LpMinimize
import numpy as np
from collections import defaultdict
import pandas as pd
from pandas.api.types import CategoricalDtype
# Data
N_DAYS = 5
all_people = ["clinton","tommy","callum","bonface","rose","dennis","geoffrey","sebastian"]
all_shifts = ["morning","afternoon","night"]
all_days = np.arange(N_DAYS)
index = np.array(list(itertools.product(all_days,all_shifts,all_people)))
df = pd.DataFrame(index,columns=["day","shift","person"])
# Create the Variable (LpVariable: LpBinary) that the Solver can change
to_assign = {
(day,shift,person): LpVariable(f"{person} on day {day} {shift}",cat=LpBinary)
for day in all_days
for shift in all_shifts
for person in all_people
}
# Initialise the Problem
allocation_model = LpProblem("Allocation",LpMinimize)
## Todo: HOW TO ENCODE THE MINIMISATION FUNCTION?
# Add Constraints
## Todo: HOW TO ENCODE THE NUMBER OF RESTS FROM NIGHT SHIFT >= 1
## Todo: HOW TO ENCODE NO CONSECUTIVE SHIFTS
# add people constraints
# assign each person to max 2 shifts per day
for day in all_days:
for person in all_people:
allocation_model.addConstraint(
sum(to_assign[(day,person)] for shift in all_shifts) <= 2
)
# assign each person to minimum 1 shift per day
for day in all_days:
for person in all_people:
allocation_model.addConstraint(
sum(to_assign[(day,person)] for shift in all_shifts) == 1
)
# add shift constraints
# assign all shifts to three people
for day in all_days:
for shift in all_shifts:
allocation_model.addConstraint(
sum(to_assign[(day,person)] for person in all_people) == 3
)
# Solve and get results:
# solve
solver = None
allocation_model.solve()
if allocation_model.status == 1:
print("Solution Found.")
results = defaultdict(list)
for (day,person),assigned in sorted(to_assign.items()):
if pulp.value(assigned):
# print(f"Day {day}: Assign {person} to {shift}")
results["day"].append(day)
results["person"].append(person)
results["shift"].append(shift)
df = pd.DataFrame(results)
cat_type = CategoricalDtype(categories=["morning","night"],ordered=True)
df = df.astype({"shift": cat_type})
df = df.sort_values(["day","shift"])
# print solution
print("Calendar Assignment")
print("-" * 50)
print(df)
# test equity of solution
print()
print(f"How many shifts for each individual? \n{'-'*50}\n",df.groupby("person").count()["shift"])
print()
print(f"How many days does each individual work? \n{'-'*50}\n",df.groupby("person").nunique()["day"])
print()
print(f"How many night shifts per individual? \n{'-'*50}\n",df.loc[df["shift"] == "night"].groupby("person").count()["shift"])
我的课程目前不符合标准 4. 5. 或 6..
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)