-1

I am Solving a Multiple Knapsacks Problem in python :

The problem is to pack a subset of the items into five bins, each of which has a maximum capacity of 100, so that the total packed value is a maximum.

data = {}
data['weights'] = [
    48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36
]
data['values'] = [
    10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25
]
assert len(data['weights']) == len(data['values'])
data['num_items'] = len(data['weights'])
data['all_items'] = range(data['num_items'])

data['bin_capacities'] = [100, 100, 100, 100, 100]
data['num_bins'] = len(data['bin_capacities'])
data['all_bins'] = range(data['num_bins'])

The data includes the following:

weights: A vector containing the weights of the items. values: A vector containing the values of the items. capacities: A vector containing the capacities of the bins.

The following code declares the MIP solver.

solver = pywraplp.Solver.CreateSolver('SCIP')
if solver is None:
    print('SCIP solver unavailable.')
    return

The following code creates the variables for the problem.

# x[i, b] = 1 if item i is packed in bin b.
x = {}
for i in data['all_items']:
    for b in data['all_bins']:
        x[i, b] = solver.BoolVar(f'x_{i}_{b}')

The following code defines the constraints for the problem:

Each x[(i, j)] is a 0-1 variable, where i is an item and j is a bin. In the solution, x[(i, j)] will be 1 if item i is placed in bin j, and 0 otherwise.

# Each item is assigned to at most one bin.
for i in data['all_items']:
    solver.Add(sum(x[i, b] for b in data['all_bins']) <= 1)

# The amount packed in each bin cannot exceed its capacity.
for b in data['all_bins']:
    solver.Add(
        sum(x[i, b] * data['weights'][i]
            for i in data['all_items']) <= data['bin_capacities'][b])



# Maximize total value of packed items.
objective = solver.Objective()
for i in data['all_items']:
    for b in data['all_bins']:
        objective.SetCoefficient(x[i, b], data['values'][i])
objective.SetMaximization()

I Try to add another contraint which consist that all items in the same bag should have the same weight, but I struggle to do it in python . Can you help me to code it?

Thanks

bonbon84
  • 5
  • 3

1 Answers1

0

Just a sketch. Think about it... Maybe fix it (it's just an idea).

What you have: Assignment-matrix A items <-> bins

item     0   1   2   3   4   5   6   7   8   9   10   11   12   13   14
   0
   1
   2
   3
   4 
        <=1 <=1 <=1 ...
  bin

What you should add: Assignment-matrix B item-classes <-> bins

Item-class: set of all items of same weight

e.g.:

import numpy as np
weights = np.array([48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36])
unique_weights = set(weights)
partition = [np.where(weights == i)[0] for i in unique_weights]

# [array([ 3,  4,  8, 13, 14]), array([ 2,  6,  7, 12]), array([0, 5]), array([9]), array([ 1, 10, 11])]

Additional assignment-matrix:

item-class    0   1   2   3   4 
   0                             <=1
   1                             <=1
   2                             <=1
   3                             <=1
   4                             <=1
  bin

Then: Link/Channel those

Sum of assigned items to bin of class C is 0 if class C is not UNIQUELY assigned to this bin, unbounded (big-M) otherwise.

Something like:

for b in range(n_bins):
    for c in range(n_partitions):
        sum(A[b, all_indices_of_items_in_class(c)]) <= B[b, c] * len(all_indices_of_items_in_class(c))

Remarks

Obviously, this is more of some addition to the status quo.

It might make more sense to not model A as big boolean-mat, but just introduce cardinality-constraints (how much identical items are picked) as we already have variables expressing "what" we pick.

sascha
  • 32,238
  • 6
  • 68
  • 110
  • @sasha thanks so much, i have a question : partition contains what kind of value? – bonbon84 Dec 23 '21 at 18:02
  • It's shown in grey in the code-block. Types don't matter much. Conceptionally: A partition is a list of lists of indices into your item-vector. `partition[0] = 3, 4, 8, 13, 14 (5 items of weight = 36)` Each partition-item contains a weight-equal set of item indices. – sascha Dec 23 '21 at 18:04
  • @sasha So i have to change all the code , in order to code A, B ... . ? there is not other solution more easy to adopt ? thanks – bonbon84 Dec 23 '21 at 18:39
  • Not if you understand the concept. Let's be honest: If someone is willing to tackle the task, there is enough information to proceed. Assuming that one can copy-paste an example, ask for missing pieces and paste those too is ambitious. There is some investment needed on your end, for sure. – sascha Dec 23 '21 at 18:57
  • @sasha , thank you so much for your help. I still struggle with **all_indices_of_items_in_class(c)]** How can i extract indices with python? I didnt find a function to do. Thank you. Regards – bonbon84 Dec 27 '21 at 19:08