OR-Tools CP-SAT 求解器:计算连续出现的 NewBoolVar
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]).
遍历所有起点和所有模式。并注意边界条件。
在一个简单的范围内,我尝试获取变量的连续赋值量。值应介于 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]).
遍历所有起点和所有模式。并注意边界条件。