寻找有关理解特定组合优化问题的建议

时间:2011-02-21 16:08:40

标签: algorithm optimization combinatorics knapsack-problem bin-packing

给定一组项目(大小在1到100之间)和多个箱子(1到15个)。每个项目都有一个箱子集可以分配项目,以及哪个箱子的偏好排序最好,仅次于此,等等。项目也有一个自然顺序,下面用命名表示,例如item2之前的item1。每个箱子的容量在1到5之间(每个物品具有相同的重量,即1。)

示例输入可以是三个箱子和六个物品( - 表示箱子不在物品的可用设置中,即不能用它包装):

      | bin1  bin2  bin3                        |  bin1  bin2  bin3   
------------------------               ----------------------------
item1 |    1     2     -               capacity |     4     4     5
item2 |    -     1     2               
item3 |    2     1     3
item4 |    1     2     3
item5 |    1     -     2
item6 |    1     2     3

目标是(按照每个目标在发生冲突时完全覆盖任何较低目标的顺序,例如,无论使用多少个箱子或忽略偏好,包装五个项目总是好于四个):

  1. 最大化包装物品数量​​
  2. 以自然顺序打包物品,例如,如果总箱容量为1且有两个物品,则物品1将被打包而物品2不会
  3. 尽量减少使用的垃圾箱数量
  4. 根据其首选项和自然顺序打包每个项目,即第一个首选项中的item1和第二个中的item2优于第二个中的item1和第一个中的item2
  5. 在两个解决方案无法通过这些目标区分的情况下,任何一种解决方案都可以接受更高的排名,例如,作为实施的副作用或只是任意打破平局。
  6. 因此上面的输入将打包为:

          | bin1  bin2  bin3
    ------------------------
    item1 |    x            
    item2 |          x     
    item3 |          x     
    item4 |    x          
    item5 |    x      
    item6 |    x   
    

    接下来的问题是阅读/评论什么来帮助我提出解决这个问题的算法思路,使用第一段的输入大小和几秒钟的时间约束,即不是暴力(或者至少我迄今为止所构想的任何蛮力。)我正在使用Ruby和C,但语言在这个阶段的树林里磕磕绊绊并不过分。

    我会感激任何阅读建议,关于算法组合的想法,或只是澄清问题陈述的想法......

    更新1

    虽然不太清楚,虽然有许多算法涵盖了这一部分,但我的困难在于找到(或者可能识别)处理所有标准的信息,特别是在容量过剩和冲突时最小化使用的箱数item-to-bin集和项目首选项,希望在以下示例中更清楚地显示:

    
          | bin1  bin2  bin3                        |  bin1  bin2  bin3   
    ------------------------               ----------------------------
    item1 |    1     2     3               capacity |     3     2     3
    item2 |    1     2     3          
    item3 |    -     1     2
    

    虽然bin1是最受欢迎的,但是item3根本不能放在其中,而bin2是所有项目的下一个最优选项目,它只能容纳三个项目中的两个。所以正确的赋值集(x)实际上是最不喜欢的bin:

          | bin1  bin2  bin3
    ------------------------
    item1 |               x  
    item2 |               x  
    item3 |               x  
    

    更新2 我使用有关目标如何关联的信息重新描述了描述并删除了bin优先级的变量,因为它只会使得找到答案的可能性降低,并且可以在我正在处理的系统中的其他地方解决。

3 个答案:

答案 0 :(得分:1)

这让我想起曾经将医学院毕业生安置在住院医师计划中的"Match" algorithm。如果您将学生这样的项目,他们的箱子偏好(如等级列表)和像医院这样的箱子一起对待会怎么样?

基本上,您浏览项目列表,并为每个项目找到它最喜欢的bin。用箱子检查:你有这个项目的空间吗?如果没有,你比你现有的任何物品更喜欢它吗? 如果不是,请将此bin从项目列表中移除,然后移至项目的下一个选项 如果是,请将此项目放入垃圾箱,并将移位的项目(如果有)放回不匹配的池中。

您的问题与居住匹配之间的区别在于您不会预先修复垃圾箱的偏好。相反,您将使用一个规则,该规则更喜欢使垃圾箱最接近100%满的物品。

我唯一担心的是这种修改可能会使算法不稳定。但它是一个如此简单的算法,它可能值得尝试。

答案 1 :(得分:1)

这是一个二分匹配问题,可以在多项式时间内求解。

http://en.wikipedia.org/wiki/Matching_(graph_theory)#Maximum_matchings_in_bipartite_graphs

答案 2 :(得分:1)

假设有n个项目和b个bin,每个bin的大小为s。您添加的约束的排序实际上简化了问题。

它们特别指的是我们应该总是选择项目1,2,...,m,以获得最大的m <= n,这将适合分配的数量的箱子(因为选择较小的数量必然会产生更糟的解决方案按规则1)。物品将按此顺序装在箱子中,可能还有一些箱子未完全填满(因为在箱子内或箱子之间重新安排物品会因规则2而产生更糟糕的解决方案)。有两种情况:

  1. m&lt; n,意思是我们不能适应所有项目。在这种情况下,所有b箱将按顺序紧紧包装第1个m项,我们就完成了。
  2. m = n,在这种情况下,我们可以适合所有项目。我们现在考虑这个案例的子句。
  3. 在这种情况下,紧密的包装箱可能会留下0 <0的最终块。 e <= b的箱子完全空了。在这种情况下,丢弃那些最后的空箱并继续进行(因为使用更多的箱会因规则3而产生更糟的解决方案)。在任何情况下,调用最后剩余的垃圾箱数r。 (r = b - e。)

    我们现在确切地知道我们将使用哪些物品和哪些箱子。我们也知道必须包装物品的顺序。由于排序约束,我们可以将关于哪些箱子未完全填充的决定视为如何将“start-next-bin”指令注入有序列表1,2,...... n的问题。项目。我们最多可以注入r-1条指令。

    使用动态编程可以在O(nrs)时间内解决此问题。基本上我们计算函数:

    f(i,j,k)=第一个i项占据前j个框的最佳解的得分,第j个框中恰好有k个项。

    重现是:

    f(i, j, 0)     = max(f(i, j-1, k)) over all 0 <= k <= s
    f(i, j, k > 0) = f(i-1, j, k-1) + q(i, j)
    

    其中q(i,j)是将项目i分配给方框j的质量分数。 (正如我在你的帖子评论中所提到的,你需要决定某种方式将任何项目i的位置分配到任何方框j中,大概是基于我的偏好得到满足。如果它更容易使用“错误“值不是质量值,只需将max()更改为min(),将-infinity边界值更改为infinity。)

    第一个等式表示最右边的bin为空的第一个i项的解的最佳分数等于通过考虑没有该bin的第一个i项的每个解的最佳分数。这些候选解决方案包括前一个bin可以打包的所有方式,包括将其留空。

    第二个等式表示,对于最右边的箱子不为空的第一个i项目的最佳分数,只需添加质量分数,将最后一个项目放入最佳分数,以便将第一个i-1项目放在同一个项目中箱数。

    边界条件是:

    f(0, 0, 0) = 0
    f(i, 0, k) = -infinity for all other i and k
    

    在计算每个0&lt; = i&lt; = n,0&lt; = j&lt; = r和0&lt; = k&lt; = s并且存储它们的f(i,j,k)的值之后在表格中,f(n,r,s)将给出最终解的最佳分数。虽然这只给出了最大分数,但是通过从末尾追溯f(i,j,k)矩阵可以找到实际的最优解,在每个k = 0步骤寻找前趋状态(即必须导致当前状态的max()下的替代方案。 (可能会发生max()下的几个替代方案给出相同的分数,在这种情况下,存在多个最优解,并且可以遵循这些路径中的任何一个来找到其中一个。)