资源分配算法

Resource allocation algorithm

我知道算法存在,但我在命名它和找到合适的解决方案时遇到问题。

我的问题如下:

我的目标: 安排作业以最小化 运行 时间 and/or 最大化资源利用率的最佳方式。

我不确定这个想法有多好,但您可以将其建模为整数线性程序,如下所示(未测试)

定义一些常量,

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

约束是,

// every job must start exactly once
(1). for every j, sum[t](x[j,t]) = 1
// a resource can only be used up to its capacity
(2). r[i,t] <= Capacity[i]
// if a job is running, it uses resources
(3). r[i,t] = sum[j | s <= t && s + Time[j] >= t] (x[j,s] * Use[j,i])
// if a job is running, then the time slot is used
(4). slot[t] >= x[j,s] iff s <= t && s + Time[j] >= t

第三个约束意味着,如果一个作业最近才开始,它仍然是 运行,那么它的资源使用量将添加到当前使用的资源中。第四个约束意味着,如果一个作业最近才开始,它仍然是 运行,那么将使用这个时间段。

objective函数是slots的加权和,后面的slots权重高,所以优先填充前面的slots。从理论上讲,权重必须呈指数增长,以确保使用较晚的时隙总是比仅使用较早时隙的任何配置都差,但求解器不喜欢这样,在实践中,您可能可以使用增长较慢的权重。

您将需要足够的插槽以便存在一个解决方案,但最好不要比您最终需要的更多,所以我建议您从一个贪婪的解决方案开始,希望为您提供一个非平凡的数字上限时隙(显然还有所有任务长度的总和)。

有很多方法可以得到贪婪的解决方案,例如,只需将作业一个一个地安排在最早的时间段内。将它们按 "hardness" 的某种度量排序并将困难的放在第一位可能会更好,例如,您可以根据他们使用资源的严重程度给他们打分(例如 [=13 的总和) =],或者可能是最大值?谁知道呢,尝试一些东西)然后按该分数降序排列。

作为奖励,如果您只解决线性松弛(允许变量取分数值,而不仅仅是 0 或 1) 你得到一个下界,近似贪婪的解决方案给出了上界。如果它们足够接近,您可以跳过代价高昂的整数阶段并采用贪婪的解决方案。在某些情况下,如果线性松弛的向上舍入 objective 与贪婪解的 objective 相同,这甚至可以证明贪婪解是最优的。

这可能是 Dykstra's Algorithm 的工作。对于您的情况,如果您想最大限度地利用资源,那么搜索 space 中的每个节点都是将作业添加到您将立即执行的作业列表中的结果。边缘将成为您将工作添加到您将要做的工作列表时剩下的资源。

然后,目标是找到到具有最小值的传入边的节点的路径。

另一种更直接的方法是将其视为 knapsack problem

要将此问题构造为背包问题的实例,我将执行以下操作:

假设我有 J 个工作、j_1, j_2, ..., j_nR 资源,我想找到 J 的子集,以便在安排该子集时,R 被最小化(我称之为 J')。

在伪代码中:

def knapsack(J, R, J`):
  potential_solutions = []
  for j in J:
    if R > resources_used_by(j):
      potential_solutions.push( knapsack(J - j, R - resources_used_by(j), J' + j) )
    else:
      return J', R
  return best_solution_of(potential_solutions)