2011-09-12 170 views
6

对于我正在处理的应用程序,我需要类似Python see here for more details中实现的打包算法。基本思想是我有n不同尺寸的物体,我需要装入n箱,箱的数量是有限的,物体和箱的尺寸是固定的。物体/箱可以是1d或2d,有兴趣看到两者。 (我认为3D对象可能比我需要的更多。)包装算法的Python实现

我知道有很多算法可以解决这个问题,比如最佳适合度下降和首次适应度下降,但我希望可能会有一个实现在Python中(或者PHP/C++/Java,真的我没那么挑剔)。有任何想法吗?

+0

这是在2D?什么样的形状?限于矩形? – jterrace

+0

如果你能回答这些问题,这将有所帮助 - 1.什么是最大数量的对象? 2.什么是垃圾箱的最大数量? 3.什么是对象的最大宽度/高度? – pravin

+0

我不能给你一个确切数量的物体或箱子的最大数量,但我认为最大值将在20-30左右(每个)。至于宽度/高度,现在不能给你最大值。 – tchaymore

回答

9

https://bitbucket.org/kent37/python-tutor-samples/src/f657aeba5328/BinPacking.py

""" Partition a list into sublists whose sums don't exceed a maximum 
    using a First Fit Decreasing algorithm. See 
    http://www.ams.org/new-in-math/cover/bins1.html 
    for a simple description of the method. 
""" 


class Bin(object): 
    """ Container for items that keeps a running sum """ 
    def __init__(self): 
     self.items = [] 
     self.sum = 0 

    def append(self, item): 
     self.items.append(item) 
     self.sum += item 

    def __str__(self): 
     """ Printable representation """ 
     return 'Bin(sum=%d, items=%s)' % (self.sum, str(self.items)) 


def pack(values, maxValue): 
    values = sorted(values, reverse=True) 
    bins = [] 

    for item in values: 
     # Try to fit item into a bin 
     for bin in bins: 
      if bin.sum + item <= maxValue: 
       #print 'Adding', item, 'to', bin 
       bin.append(item) 
       break 
     else: 
      # item didn't fit into any bin, start a new bin 
      #print 'Making new bin for', item 
      bin = Bin() 
      bin.append(item) 
      bins.append(bin) 

    return bins 


if __name__ == '__main__': 
    import random 

    def packAndShow(aList, maxValue): 
     """ Pack a list into bins and show the result """ 
     print 'List with sum', sum(aList), 'requires at least', (sum(aList)+maxValue-1)/maxValue, 'bins' 

     bins = pack(aList, maxValue) 

     print 'Solution using', len(bins), 'bins:' 
     for bin in bins: 
      print bin 

     print 


    aList = [10,9,8,7,6,5,4,3,2,1] 
    packAndShow(aList, 11) 

    aList = [ random.randint(1, 11) for i in range(100) ] 
    packAndShow(aList, 11) 
+2

呃,这是'aList = [5,4,4,3,2,2]'和'maxValue = 10'的错误。它给出了3个框的结果,但真正的答案应该是2([4,4,2],[5,3,2])。 – aemdy

+1

@aemdy说谁? FFD算法会给出[5 4],[4 3 2],[2 2]。最佳的容器装箱是NP难的,确切的算法要更复杂。 – krapht

+1

这个效果很好;我修改了这个以简化我的直线材料购买:https://github.com/ninowalker/linear-pack –