我正在尝试使用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 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之间。
你有什么想法吗?谢谢!
发布于 2019-04-16 09:08:59
这是在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))
https://stackoverflow.com/questions/55698908
复制相似问题