Reputation: 79
In a simple range I try to get the amount of successive assignments for a variable. The values should be between 6-12 or should be 0. For example in the case a hospital has 24 shifts and an employee should work between 6 and 12 hours or not at all.
# 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
Unfortunately this doesn't work since it increases the value with only one, what would be the best approach to check if how many hours have been assigned and increase s_count
with that value?
Upvotes: 0
Views: 596
Reputation: 11034
If you just want to constrain the sum, you should use this method
model.AddLinearExpressionInDomain(sum(bool_vars), cp_model.Domain.FromIntervals([0, 0], [6, 12]))
If you want to constrain the length of a sequence, you should look at the shift_scheduling example
In particular, the soft sequence constraint. The idea is the following, for every starting point, you want to forbid 010, 0110, 01110, ..., 0111110 and 01111111111110 (0110 means work[start] is false, work[start + 1] is true, work[start + 2] is true, work[start + 3] is false.
To forbid a sequence, just add a nogood, that is a clause (or AddBoolOr containing the negation of the pattern.
in my example bool_or(work[start], work[start + 1].Not(), work[start + 2].Not(), work[start + 3]).
Loop over all starting points and all patterns. And pay attention to the boundary conditions.
Upvotes: 3