You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于OR-Tools的护士排班休息日约束添加技术问询

Google OR-Tools 护士排班休息日约束实现方案

针对你的需求,下面提供两种直观的实现方式,均基于你的shift[n,d,s]布尔变量(shift[n,d,s]=1表示护士n在第d天第s班次被安排):

方法一:直接强制休息日班次为0(推荐新手)

这是最直观的方式,直接约束护士在休息日当天的所有班次变量必须为0:

from ortools.sat.python import cp_model

# 基础参数
num_nurses = 4
num_days = 3  # 匹配休息日的0/1/2索引
num_shifts = 3  # 根据实际班次数调整

nurse_days_off = [
    [0,2], [1], [1,2], []
]

# 初始化模型与变量
model = cp_model.CpModel()
shift = {}
for n in range(num_nurses):
    for d in range(num_days):
        for s in range(num_shifts):
            shift[(n, d, s)] = model.NewBoolVar(f'shift_n{n}_d{d}_s{s}')

# 原有约束:每个班次仅分配一名护士
for d in range(num_days):
    for s in range(num_shifts):
        model.AddExactlyOne(shift[(n, d, s)] for n in range(num_nurses))

# 添加休息日约束
for nurse_idx in range(num_nurses):
    # 遍历该护士的所有休息日
    for day_off in nurse_days_off[nurse_idx]:
        # 该休息日的所有班次都禁止安排
        for shift_idx in range(num_shifts):
            model.Add(shift[(nurse_idx, day_off, shift_idx)] == 0)

方法二:使用AddForbiddenAssignments

如果你一定要用AddForbiddenAssignments,需明确:该方法第一个参数是变量列表,第二个参数是禁止的取值元组列表(元组长度必须和变量列表长度一致)。对于单个班次变量,我们禁止它取1这个值:

# 替换方法一中的休息日约束部分,其余代码不变
for nurse_idx in range(num_nurses):
    for day_off in nurse_days_off[nurse_idx]:
        for shift_idx in range(num_shifts):
            target_var = shift[(nurse_idx, day_off, shift_idx)]
            # 禁止该变量被设为1
            model.AddForbiddenAssignments([target_var], [(1,)])

关键说明

  • 两种方法效果完全一致,但方法一可读性更强,更适合约束编程新手理解。
  • 确保num_days的取值覆盖你nurse_days_off中的所有日期索引(比如示例中用到0/1/2,所以num_days设为3)。

内容的提问来源于stack exchange,提问作者Mark Seagoe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:05:21