【发布时间】:2018-08-26 01:50:06
【问题描述】:
我正在研究一个调度优化问题,其中我们有一组需要在特定时间范围内完成的任务。
每个任务都有一个时间表,该时间表指定了可以执行的时间段列表。每个任务的时间表可能因工作日而异。
这里是小样本(减少了任务数量和时隙):
task_availability_map = {
"T1" : [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"T2" : [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"T3" : [0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"T4" : [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"T5" : [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
"T6" : [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0],
"T7" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
"T8" : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
"T9" : [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
"T10": [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]
}
限制是在同一时隙内最多只能并行执行 N 个任务(如果它们重叠)。无论是执行 1 还是 N,这组并行任务总是花费相同的时间。
目标是最小化时隙数。
我尝试了一种蛮力方法,可以生成所有时隙索引排列。对于给定排列中的每个索引,获取所有可以调度的任务并将它们添加到要在下一次迭代中排除的任务列表中。完成给定排列的所有迭代后,将时隙数和索引组合添加到列表中。
def get_tasks_by_timeslot(timeslot, tasks_to_exclude):
for task in task_availability_map.keys():
if task in tasks_to_exclude:
continue
if task_availability_map[task][timeslot] == 1:
yield task
total_timeslot_count = len(task_availability_map.values()[0]) # 17
timeslot_indices = range(total_timeslot_count)
timeslot_index_permutations = list(itertools.permutations(timeslot_indices))
possible_schedules = []
for timeslot_variation in timeslot_index_permutations:
tasks_already_scheduled = []
current_schedule = []
for t in timeslot_variation:
tasks = list(get_tasks_by_timeslot(t, tasks_already_scheduled))
if len(tasks) == 0:
continue
elif len(tasks) > MAX_PARALLEL_TASKS:
break
tasks_already_scheduled += tasks
current_schedule.append(tasks)
time_slot_count = np.sum([len(t) for t in current_schedule])
possible_schedules.append([time_slot_count, timeslot_variation])
...
按时隙数对可能的时间表进行排序,这就是解决方案。然而,该算法的复杂性随着时隙的数量呈指数增长。鉴于有数百个任务和数百个时隙,我需要一种不同的方法。
有人建议使用 LP MIP(例如 Google OR Tools),但我对它不是很熟悉,并且很难在代码中制定约束。非常感谢 LP 或其他可以帮助我朝着正确方向开始的解决方案的任何帮助(不必是 Python,甚至可以是 Excel)。
【问题讨论】:
-
尝试约束规划,它可能看起来比 LP 更直观,并且可以轻松解决此类问题。
-
如果你想坚持使用 python,你可以查看 numberjack 来解决 CSP:github.com/eomahony/Numberjack
-
我假设每个任务的持续时间为 1 个时隙。您的矩阵显示允许将任务分配给插槽。这看起来像是一个广义分配问题 (
x[i,t]= 1 if task i is assigned to time slot t and 0 otherwise),并且很容易建模为 MIP。我不认为CP在这里有很大的优势。蛮力(或完整枚举)对我来说看起来不是很有希望。
标签: python algorithm linear-programming job-scheduling minimization