2011-09-12 31 views
6

Para una aplicación en la que estoy trabajando Necesito algo así como un algoritmo de empaquetado implementado en Python see here for more details. La idea básica es que tengo n objetos de diferentes tamaños que necesito para encajar en contenedores n, donde el número de contenedores es limitado y el tamaño de ambos objetos y contenedores es fijo. Los objetos/contenedores pueden ser 1d o 2d, interesados ​​en ver ambos. (Creo que los objetos 3D es probablemente más de lo que necesito).Python Implementations of Packing Algorithm

Sé que hay una variedad de algoritmos que abordan este problema, como Best Fit Decreasing y First Fit Decreasing, pero esperaba que pudiera haber una implementación en Python (o PHP/C++/Java, realmente no soy tan exigente). ¿Algunas ideas?

+0

¿Es esto en 2D? que tipo de formas? limitado a rectángulos? – jterrace

+0

Ayudaría si pudiera responder estas preguntas: 1. ¿Cuál es la cantidad máxima de objetos? 2. ¿Cuál es el número máximo de contenedores? 3. ¿Cuál es el ancho/alto máximo de un objeto? – pravin

+0

No puedo darle un número exacto para la cantidad máxima de objetos o contenedores, pero estoy pensando que el máximo sería de alrededor de 20-30 (para cada uno). En lo que respecta al ancho/alto, no podemos darte el máximo en este momento. – tchaymore

Respuesta

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

Bueno, esto es falso con 'aList = [5, 4, 4, 3, 2, 2]' y 'maxValue = 10'. Da resultado con 3 cuadros, pero la respuesta verdadera debería ser 2 ([4, 4, 2], [5, 3, 2]). – aemdy

+1

@aemdy dice quién? El algoritmo FFD daría [5 4], [4 3 2], [2 2]. El embalaje óptimo es NP-difícil y los algoritmos exactos para hacer eso son más complicados. – krapht

+1

Esto funciona bien; Modifiqué esto para simplificar la compra de materiales lineales: https://github.com/ninowalker/linear-pack –