连续工作日

时间:2019-04-16 00:22:35

标签: constraint-programming or-tools

我正在尝试使用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之间。

你有个主意吗? 谢谢!

1 个答案:

答案 0 :(得分:0)

这是shift_scheduling_sat.py中的软版本。

请参阅:https://github.com/google/or-tools/blob/39f44709bba203f5ff3bc18fab8098739f189a6d/examples/python/shift_scheduling_sat.py#L61

    # 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))