我不确定这个想法有多好,但你可以将其建模为整数线性规划,如下所示(未测试)
定义一些常量,
Use[j,i] = amount of resource i used by job j
Time[j] = length of job j
Capacity[i] = amount of resource i available
定义一些变量,
x[j,t] = job j starts at time t
r[i,t] = amount of resource of type i used at time t
slot[t] = is time slot t used
限制条件包括:
(1). for every j, sum[t](x[j,t]) = 1
(2). r[i,t] <= Capacity[i]
(3). r[i,t] = sum[j | s <= t && s + Time[j] >= t] (x[j,s] * Use[j,i])
(4). slot[t] >= x[j,s] iff s <= t && s + Time[j] >= t
第三个限制条件是,如果一个作业最近被启动并仍在运行,则它的资源使用量将添加到当前使用的资源中。第四个限制条件是,如果一个作业最近被启动并仍在运行,则使用这个时间段。
目标函数是时间段的加权和,后面的时间段具有更高的权重,因此它倾向于填充早期时间段。理论上,权重必须呈指数增长,以确保使用较晚的时间段始终比仅使用较早的时间段的任何配置都差,但求解器不喜欢这种方式,在实践中,您可以使用增长缓慢的权重来代替。
您需要足够多的时间段以便存在可行的解,但最好不要比您最终需要的时间段多得太多,因此建议您从贪心解决方案开始,以便为您提供一个希望非平凡的时间段上界(显然还有所有任务长度的总和)。
有许多方法可以获得贪心解决方案,例如只需按最早的时间段一次安排一个作业。可能更好的做法是根据某些“难度”度量对它们进行排序,并首先处理难的作业,例如,您可以根据它们对资源的使用情况(例如
Use[j,i] / Capacity[i]
的总和或最大值)给它们打分,然后按得分从高到低排序。
作为额外的奖励,您可能不必总是解决完整的ILP问题(这是NP难的,因此有时可能需要一段时间),如果您只解决线性松弛问题(允许变量取分数值,而不仅仅是0或1),则可以获得下界,近似贪心解提供上界。如果它们足够接近,则可以跳过昂贵的整数阶段并采用贪心解决方案。在某些情况下,如果线性松弛舍入后的目标与贪心解决方案的目标相同,则甚至可以证明贪心解是最优的。