简体   繁体   中英

Knapsack with constraint same value

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

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

eg:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM