Я пытаюсь сделать планировщик с помощью or-tool. В настоящее время я застрял со следующей проблемой. Я хочу, чтобы сотрудники работали не менее n дней подряд.
Я пробовал это:
for n in all_nurses:
for d in all_days:
if sum([shifts[(n, d, 0)], shifts[(n, d, 1)], shifts[(n, (d), 2)]]) == 1: # if employee works this day, then he should works the 2 days after too
model.Add(sum([shifts[(n, d+1, 0)], shifts[(n, (d+1), 1)], shifts[(n, (d+1), 2)]]) == 1)
model.Add(sum([shifts[(n, d+2, 0)], shifts[(n, (d+2), 1)], shifts[(n, (d+2), 2)]]) == 1)
Он работает с 3 сотрудниками, но если я добавлю больше сотрудников (10), модель не найдет никаких решений.
У вас есть идея?
РЕДАКТИРОВАТЬ:
Я попытался реализовать пример на https://github.com/google/or-tools/blob/39f44709bba203f5ff3bc18fab8098739f189a6d/examples/python/shift_scheduling_sat.py#L61
Но я не смог ..
Вот моя попытка:
for n in all_nurses:
works = [sum(shifts[n, d, s] for s in all_shifts) for d in all_days]
print (works)
for length in range(3, 4):
for start in range(len(works) - length - 1):
model.AddBoolOr(negated_bounded_span(works, start, length))
for start in range(len(works) - 5 - 1):
model.AddBoolOr([works[i].Not() for i in range(start, start + hard_max + 1)])
Я получаю ошибку:
AttributeError: '_SumArray' object has no attribute 'Not'
Я вынужден составлять сумму смен дня, поскольку мне нужны последовательные дни работы, но не в конкретную смену.
Кроме того, если у кого-то есть хорошее объяснение о том, как работает метод здесь: https://github.com/google/or-tools/blob/39f44709bba203f5ff3bc18fab8098739f189a6d/examples/python
Потому что я действительно не понимаю, как AddBoolOr гарантирует, что у нас есть последовательность истинных последовательных логических значений
РЕДАКТИРОВАТЬ 2:
Мне удалось реализовать решение на github.
Но у меня все еще есть проблема.
Я создал зеркало моих дней / смен, как это:
shifts = {}
mirrors = {}
for n in all_nurses:
for d in all_days:
mirrors[(n,d)] = model.NewBoolVar('mirror_n%id%i' % (n, d))
for s in all_shifts:
shifts[(n, d, s)] = model.NewBoolVar('shift_n%id%is%i' % (n, d,
s))
#Creation du mirroir
for n in all_nurses:
for d in all_days:
model.Add(sum(shifts[(n, d, s)] for s in all_shifts) == mirrors[(n,d)])
Так, что для медсестры 1: 0010 0100 0010 1000 0000 0000 0000
Зеркало будет: 1 1 1 1 0 0 0
Затем я применил метод, чтобы несколько дней подряд работал над моим зеркалом, поскольку он связан с моей основной таблицей.
for n in all_nurses:
works = [mirrors[n,d] for d in range(num_days)]
for length in range(1, 3):
for start in range(len(works) - length - 1):
model.AddBoolOr(negated_bounded_span(works, start, length))
for start in range(len(works) - 5 - 1):
model.AddBoolOr([works[i].Not() for i in range(start, start + 5 + 1)])
Теперь я ожидаю, что результат не будет иметь никакого периода работы, который не будет между 3 и 5.
Но, тем не менее, когда я печатаю решение, для одной медсестры я получил следующий результат:
0010 0010 0010 0010 0010 0000 0000 0000 0001 0000
А для зеркала это:
1111100010
Это не должно быть возможно, поскольку период работы составляет от 3 до 5.
У вас есть идея?
Спасибо!