algorithm - Variation of the backpack ... in python -


i have conceptual problem have several packages, each package contains number of elements inside. elements of type a or type b. want distribute packages in finite number of bins in such way distribution between a , b not differ wildly among bins.

the problem quite complex, hence try explain hard constraints , conceptual example.

constraints

a package can used once package must used entirely bins should have relatively equal distributions between `a` , `b` (max 5% deviation original ratio) package can spread across bins in given batch want end little batches (size <= 3 bins) possible 

example (conceptual)

plate 1: 92 * `a` plate 2: 92 * `a` plate 3: 64 * `a` plate 4: 42 * `a`, 50 * `b` plate 5: 12 * `a`, 49 * `b` plate 6: 92 * `b` 

total distribution such 302 * a , 191 * b yielding 493 samples in total, resulting ratios 61.25% of a , 38.75% of b

desired result:

a minimized set of batches, each batch contains @ 3 bins (length <= 92) let's between 52 , 60 of type a , between 32 , 40 of type b (the combined total not above 92) per bin.

question

what algorithm or method 1 suggest tackle problem, simple suggested scheme (considering have been trying far (see below) not far)

the idea behind attempts far

data = ... # list containg values in tuple format of `(unit, [(type, location)])` format while len(data) > 0:    batch = []    counter1 = 0    counter2 = 0    in data:       j in i[1]:          if j[0] == 'a':             counter1 += 1          else:             counter2 += 1    ratio1 = counter1/(counter1+counter2)    ratio2 = counter2/(counter1+counter2)    # know maximum number of , b per batch    counter3 = 0 # keeps track of howmany type `a` have in current batch    counter4 = 0 # keeps track of howmany type `b` have in current batch    while counter3 < ratio1:       in data:          j in i[1]:             if counter(elem[0] elem in j)['a'] < (ratio1 - counter3) , counter(elem[0] elem in j)['b'] < (ratio2 - counter4):                # add unit (from data) batch                batch.append(i)                counter3 += counter(elem[0] elem in j)['a']                counter4 += counter(elem[0] elem in j)['b']                # remove used unit data 

this stuck, not attempt minimize number of bins, nor check ratios. additionally, have nagging idea way trying no near smart way of solving such problem.

#quick generator rotate bin numbers def getbin(maxbin):     number = -1     while true:         number +=1          if number >= maxbin:             number = 0         yield number  batches = [] data = ....  #calculate minimum number of bins need numberofbins = (len(data))/ 92 + 1   abinplacement = getbin(numberofbins) bbinplacement = getbin(numberofbins)  bins = numberofbins * [[]]  #the ratio maintained because rotate bins type datum in data:     if datum[0] == 'a':         bins[abinplacement.next()].append(datum)     else:         bins[bbinplacement.next()].append(datum)  batches.extend(bins) 

Comments