寻求资源分配算法

时间:2014-11-01 11:51:56

标签: algorithm resources

对于我的一个项目(不,不是作业或考试问题,虽然我认为它会很好),但我需要一个算法。这个问题看起来很熟悉,也很普遍,我很自信它已经在文献中得到了解决,但是我没有方便的算法书籍,也不清楚用什么术语来描述它,所以谷歌搜索的用途有限

除去了无关的细节,问题如下:给你一组资源{R_1,R_2,... R_n}和一组任务{T_1,T_2,... T_m}。每个任务都可以使用任何一组备选资源TR_m = {{R_1m1,R_1m2,...},{R2m1,R_2m2,...},...}来完成。每个资源一次只能由一个任务使用。问题是看是否可以同时完成所有任务,或者如果不可能,可以同时完成最大数量的任务(从T_1开始)。

只是为每个任务分配第一组可用资源的天真算法有时会不必要地失败:想想TR_1 = {{R_1,R_2},{R_1}}和TR_2 = {{R_1},{R_2} }。 T_1将抓住R_1,R_2和T_2将失败,而TR_1可能刚刚取得R_1而TR_2可能占用R_2。

我正在寻找一种优雅而简单的算法,可以做得更好。

就重要而言,资源主要由可互换的子集组成,而任务通常只需要每个集合中的一个或多个资源,因此天真算法通常会成功,但并非总是如此。

此外,通常只有不到12个任务和资源,问题(目前在Python 3中编码)不是实时的,所以蛮力通常是一个可接受的解决方案,但我正在寻找更好的东西。

有任何建议或链接吗?

2 个答案:

答案 0 :(得分:1)

假设所有任务都相同。

然后你的问题等同于已知的NP-complete maximum set packing problem

所以你的问题肯定是NP难的,你不太可能找到一个完美的算法。

答案 1 :(得分:1)

使用可以使用Branch and Bound

你的分支是“for tasks i,我选择哪一套?”,首先选择最大的一组,以尽可能地在树中导致失败,以节省工作。对于初始解决方案,您可以快速翻转以快速找到合理(但不是最佳)的解决方案,最终通过在以后的实际搜索中修剪更多来节省工作。

你也可以在以下模型的s[q,t]上分支,该模型最接近0.5(在某种程度上,选择它是“最不确定的”)。

绑定可以基于此ILP模型的线性松弛:

maximize sum of x[t] over all t

variables:
0 <= x[t] <= 1  ; x[t] decides whether task t is scheduled or not
0 <= r[i,t] <= 1 ; r[i,t] decides whether task t uses resource i
0 <= s[q,t] <= 1 ; s[q,t] decides whether set q of task t is used

constraints:
1. for all tasks t: (sum s[q,t] over all valid q) - x[t] = 0
2. for all sets s[q,t]: (sum r[i,t] over all i in the set) - size_of_set * s[q,t] >= 0
3. for all resources i: sum r[i,t] over all t <= 1
  1. 强制将1组资源与所选的任何任务相关联。
  2. 通过任务t使用任务t来选择set q来强制使用资源(&gt; = 0因为集合可能重叠)
  3. 强制所有资源使用不超过一次。
  4. 我可能在模型中犯了错误,我不确定它有多好。无论如何,用线性编程来解决它(毫无疑问它有一个用于Python的库),然后做一些Gomory削减以获得良好的衡量标准(它们可能看起来很可怕,但它们实际上非常简单,但是不是太多) ,试图获得只有Gomory削减的全整数解决方案通常收敛非常缓慢。做其中一些是改善解决方案的廉价方法。

    这将为您提供估算,让您修剪一些搜索空间。实际修剪多少取决于它与实际解决方案的接近程度。我预测它将倾向于选择属于某个任务的几个集合,其中某个因子介于0和1之间,因为选择一个“只有一点”的集合允许它为多个任务使用相同的资源。它必须选择几个集合,因为它必须每个任务总共使用1个集合,但这也意味着它有更多的资源选择,因此它可以做到这一点。线性编程是那种偷偷摸摸的方式,在某种意义上总是试图给你最烦人的答案:)

    当然,在此模型中,您将排除任何不再可能的可能性(分配的资源以及包含它们的集合和可能具有零集的任务),并跳过已调度的任务。

    如果这太复杂了,你可以计算一个更简单的界限:对于所有任务t,取其最小集s[t]的大小。检查您可以采取多少,直到总大小大于未分配资源的数量(所以采取最小的,添加下一个最小的,依此类推 - 对它们进行排序或使用最小堆)。

    当然,如果使用目前分配的资源,那么现在很多任务都没有任何可能的设置(包括已经安排的那些)你到目前为止你得不到的最佳解决方案,你可以放弃在递归树的当前分支上。

    对于初始解决方案,您可以尝试使用您描述的贪婪算法但只需进行一项更改:采用仅包含未分配资源的最小集。这样它就会试图“避开”进一步的任务,但显然你可以构建一个比选择第一个可能的集更差的情况。

    编辑:当然,如果任务集的集合中有一个集合,该集合是该集合中其他集合的超集,则只需将其删除即可。使用超集是不是更好。这恰好修复了OP中给出的示例,但它通常不会。