我正在尝试使用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之间。
你有个主意吗? 谢谢!
答案 0 :(得分:0)
这是shift_scheduling_sat.py中的软版本。
在
# Forbid sequences that are too short.
for length in range(1, hard_min):
for start in range(len(works) - length - 1):
model.AddBoolOr(negated_bounded_span(works, start, length))