OR-Tools CP-SAT 求解器:计算连续出现的 NewBool​​Var

OR-Tools CP-SAT solver: count successive NewBoolVar occurrences

在一个简单的范围内,我尝试获取变量的连续赋值量。值应介于 6-12 之间或应为 0。例如,医院有 24 个班次,员工应工作 6 到 12 小时或根本不工作。

# Build shifts
shifts = {}
for n in all_nurses:
    for d in all_days:
        for s in all_shifts:
            shifts[(n, d, s)] = model.NewBoolVar('shift_n%id%is%i' % (n, d, s))

# Count successive occurrences
for e_count in all_nurses:
    s_count = 0
    while s_count < len(all_shifts):
        model.Add(sum(shifts[e_count, s_count] for s in range(e_count, e_count + 6 == 6) #min
        model.Add(sum(shifts[e_count, s_count] for s in range(e_count, e_count + 12 <= 12) #min

不幸的是,这不起作用,因为它只增加了一个值,检查是否分配了多少小时并使用该值增加 s_count 的最佳方法是什么?

如果你只是想限制总和,你应该使用this method

model.AddLinearExpressionInDomain(sum(bool_vars), cp_model.Domain.FromIntervals([0, 0], [6, 12]))

如果你想限制一个序列的长度,你应该看看the shift_scheduling example

特别是软序列约束。 想法如下,对于每个起点,你想禁止 010、0110、01110、...、0111110 和 01111111111110(0110 表示 work[start] 为假,work[start + 1] 为真,work[start + 2] 为真,work[start + 3] 为假。

要禁止序列,只需添加一个 nogood,即一个子句(或包含模式否定的 AddBoolOr。

在我的示例中 bool_or(work[start], work[start + 1].Not(), work[start + 2].Not(), work[start + 3]).

遍历所有起点和所有模式。并注意边界条件。