约束相同值的背包
Knapsack with constraint same value
我正在解决 python 中的多个背包问题:
问题是将物品的一个子集打包到五个箱子中,每个箱子的最大容量为 100,因此总的打包值是最大值。
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'])
数据包括以下内容:
权重:包含项目权重的向量。
值:包含项目值的向量。
capacity:包含 bin 容量的向量。
以下代码声明了 MIP 求解器。
solver = pywraplp.Solver.CreateSolver('SCIP')
if solver is None:
print('SCIP solver unavailable.')
return
以下代码为问题创建了变量。
# 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}')
以下代码定义了问题的约束条件:
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()
我尝试添加另一个约束,即同一包中的所有物品都应具有相同的重量,但我很难在 python 中做到这一点。你能帮我编码吗?
谢谢
只是一个草图。考虑一下...也许修复它(这只是一个想法)。
你有什么:赋值矩阵 A 项 <-> 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
你应该添加什么:Assignment-matrix B item-classes <-> bins
物品-class:一组相同重量的所有物品
例如:
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])]
附加赋值矩阵:
item-class 0 1 2 3 4
0 <=1
1 <=1
2 <=1
3 <=1
4 <=1
bin
然后:Link/Channel那些
如果 class C 没有唯一分配给此 bin,则分配给 class C 的 bin 的项目总和为 0,否则为无界(big-M)。
类似于:
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))
备注
显然,这更多是对现状的补充。
不将 A 建模为大布尔垫可能更有意义,而只是引入基数约束(选择了多少相同的项目),因为我们已经有了表示我们选择“什么”的变量。
我正在解决 python 中的多个背包问题:
问题是将物品的一个子集打包到五个箱子中,每个箱子的最大容量为 100,因此总的打包值是最大值。
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'])
数据包括以下内容:
权重:包含项目权重的向量。 值:包含项目值的向量。 capacity:包含 bin 容量的向量。
以下代码声明了 MIP 求解器。
solver = pywraplp.Solver.CreateSolver('SCIP')
if solver is None:
print('SCIP solver unavailable.')
return
以下代码为问题创建了变量。
# 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}')
以下代码定义了问题的约束条件:
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()
我尝试添加另一个约束,即同一包中的所有物品都应具有相同的重量,但我很难在 python 中做到这一点。你能帮我编码吗?
谢谢
只是一个草图。考虑一下...也许修复它(这只是一个想法)。
你有什么:赋值矩阵 A 项 <-> 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
你应该添加什么:Assignment-matrix B item-classes <-> bins
物品-class:一组相同重量的所有物品
例如:
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])]
附加赋值矩阵:
item-class 0 1 2 3 4
0 <=1
1 <=1
2 <=1
3 <=1
4 <=1
bin
然后:Link/Channel那些
如果 class C 没有唯一分配给此 bin,则分配给 class C 的 bin 的项目总和为 0,否则为无界(big-M)。
类似于:
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))
备注
显然,这更多是对现状的补充。
不将 A 建模为大布尔垫可能更有意义,而只是引入基数约束(选择了多少相同的项目),因为我们已经有了表示我们选择“什么”的变量。