我正在尝试解决调度问题。作为输入,我有工人的数量和班次的数量。
之后,我放置了所有约束,包括:
- 每个人都必须围绕相同数量的轮班工作,
- 每个人都必须度过所有给定的假期,
- ...ETC。
然后我尝试最大化给定的班次序列。
例如,我可以收到序列:123BBBB。这意味着我必须在他们的日历中为每个工人最大化这个序列的外观。
- 1 表示工人工作 1 班,
- 2 代表班次 2,
- 3 表示第 3 班次,以及
- B 代表休息。
我计算每个工人全年的时间表(比如说 365 天)。我试图为每个可能的序列制作布尔值:所以对于范围(1,长度(序列)),范围(2,长度(序列)))等的天数。
然后我添加一个约束,即从今天到的变化总和len(sequence)
是len(sequence)
。因此,我也将班次表示为布尔值(shifts[(w, d, s)]
),这对于shifts[(0, 3, 0)]
第 3 天的工人 1 工作班次 1 来说意味着。
给定序列的约束是 OnlyEnforcedIf 为该序列创建的 bool 为真。然后我尝试最大化为每个序列创建的布尔值的总和。
问题:我尝试运行它,运行 8 小时后我放弃了。它为我找到了大约 62 个序列,但是花了很长时间才停下来或找到另一个。我的问题是:如何更有效地做到这一点?
编码:
shift_requests = []
requiredShift = "111222333BBBBBB"
appearences_for_1 = 0
appearences_for_2 = 0
appearences_for_3 = 0
appearences_for_L = 0
for i in requiredShift:
if i == '1':
appearences_for_1 += 1
for i in requiredShift:
if i == '2':
appearences_for_2 += 1
for i in requiredShift:
if i == '3':
appearences_for_3 += 1
for i in requiredShift:
if i == 'B':
appearences_for_B += 1
print(appearences_for_1, appearences_for_2, appearences_for_3, appearences_for_B)
for w in range(worker):
shift_requests.append([])
poz = 0
dayz = 1
while dayz + len(requiredShift) <= 365:
shift_requests[w].append(model.NewBoolVar(f'{w}_{dayz}_{dayz + len(requiredShift)}'))
first_range = dayz + appearences_for_1
second_range = first_range + appearences_for_2
third_range = second_range + appearences_for_3
fourth_range = third_range + appearences_for_B
#shift = 5 ( 0 is shift 1, 1 is shift 2, 2 is shift 3, 3 is break, 4 is holiday)
model.Add(sum(shifts[(w, d, shift - 2 - 3)] for d in range(dayz, first_range))+
sum(shifts[(w, d, shift - 2 - 2)] for d in range(first_range, second_range))+
sum(shifts[(w, d, shift - 2 - 1)] for d in range(second_range, third_range))+
sum(shifts[(w, d, shift - 2)] for d in range(third_range, fourth_range)) == len(requiredShift))\
.OnlyEnforceIf(shift_requests[w][poz])
dayz += 1
poz += 1
model.Maximize(sum(shift_requests[w][poz] for w in range(worker) for poz in range(len(shift_requests[w]))))