Python线性规划——连续夜班的调度优化约束

问题描述

我正在尝试编写一个程序来安排一个 8 人的团队轮班。

我想知道如何建模每个人必须每个人至少有一个夜班休息时间不能连续工作两班,我们想要确保每个人的夜班次数和班次总数尽可能接近相同

我在下面用 PuLP 编写了一个演示程序,但很想知道是否有人对任何 python 包(scipygurobi 等)有想法

更具体地说,我有以下问题:

  • 8 个人
  • 每天 3 个班次(上午、下午、晚上)
  • 18 天

我想将个人分配到轮班以满足以下条件:

  1. 每班必须有 3 人
  2. 每个人每天必须工作 1 个班次
  3. 每个人每天不得超过 2 个班次
  4. 每个人都必须至少有一个夜班休息时间,最好是两个
  5. 我们应该尽可能均匀地分配这些轮班,尤其是夜班,还有轮班总数。
  6. 每个人不得连续轮班工作(例如第 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 (将#修改为@)