이 섹션에서는 MIP solver와 CP-SAT solver를 사용하여 multiple knapsack에 대한 knapsack problem을 어떻게 푸는지에 대해 보여준다.
이 경우, knapsack보다는 bin이라고 containter를 지칭하는 것이 더 흔하다.
다음의 예제는 다섯개의 bin들에 사물들을 포장하는 최적의 방법을 어떻게 찾는지를 보여준다.
Example
이전의 예제와 마찬가지로, 다양한 무게와 값들에 대한 사물의 집합으로 시작한다. 이 문제에서는 사물들을 부분집합으로 5개의 bin들에 포장하는 문제이며, 이들 각각의 최대 용량은 100이고, 전체 포장된 값은 최대여야한다.
따르는 섹션에서는 이 문제를 푸는 프로그램을 보여준다.
MIP Solution
from ortools.linear_solver import pywraplp
def MultipleKnapsacks():
#create the data
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']) # 0에서 해당 값 사이의 값들을 리스트로
data['bin_capacities'] = [100, 100, 100, 100, 100]
data['num_bins'] = len(data['bin_capacities'])
data['all_bins'] = range(data['num_bins'])
#declare the MIP solver
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}')
#사물 i가 bin j에 위치해있으면 x[i, j]는 1이며, 그렇지 않으면 0이다.
#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]
)
#define the objective
#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()
# x[i, j] * data['values'][i]가 bin j에 들어있다면, 사물 i의 값을 objective에 더하는 것이다.
#만약 i가 어떠한 bin에도 들어있지 않다면, 그것의 값은 objective에 기여할 수 없다.
#invoke the solver
status = solver.Solve()
if status == pywraplp.Solver.OPTIMAL:
print(f'Total packed value: {objective.Value()}')
total_weight = 0
for b in data['all_bins']:
print(f'Bin {b}')
bin_weight = 0
bin_value = 0
for i in data['all_items']:
if x[i, b].solution_value() > 0:
print(f"Item {i} weight : {data['weights'][i]} value: {data['values'][i]}")
bin_weight += data['weights'][i]
bin_value += data['values'][i]
print(f'Packed bin weight: {bin_weight}')
print(f'Packed bin value: {bin_value}\n')
total_weight += bin_weight
print(f'Total packed weight: {total_weight}')
else:
print('The problem does not have an optimal solution.')
MultipleKnapsacks()
CP SAT solution
from ortools.sat.python import cp_model
def CPSAT():
model = cp_model.CpModel()
#create the data
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'])
#create the variables
#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] = model.NewBoolVar(f'x_{i}_{b}')
#each item is assigned to at most one bin
for i in data['all_items']:
model.AddAtMostOne(x[i, b] for b in data['all_bins'])
#the amount packed in each bin cannot exceed its capacity
for b in data['all_bins']:
model.Add(
sum(x[i, b] * data['weights'][i]
for i in data['all_items']) <= data['bin_capacities'][b]
)
#create the objective function
#maximize total value of packed items
objective = []
for i in data['all_items']:
for b in data['all_bins']:
objective.append(
cp_model.LinearExpr.Term(x[i, b], data['values'][i])
)
model.Maximize(cp_model.LinearExpr.Sum(objective))
#invoke the solver
solver = cp_model.CpSolver()
status = solver.Solve(model)
if status == cp_model.OPTIMAL:
print(f'Total packed value: {solver.ObjectiveValue()}')
total_weight = 0
for b in data['all_bins']:
print(f'Bin {b}')
bin_weight = 0
bin_value = 0
for i in data['all_items']:
if solver.Value(x[i, b]) > 0:
print(f"Item {i} weight: {data['weights'][i]} value : {data['values'][i]}")
bin_weight += data['weights'][i]
bin_value += data['values'][i]
print(f'Packed bin weight: {bin_weight}')
print(f'Packed bin value: {bin_value}\n')
total_weight += bin_weight
print(f'Total packed weight: {total_weight}')
else:
print('The problem does not have an optimal solution.')
CPSAT()
Reference:
https://developers.google.com/optimization/pack/multiple_knapsack
여러 여행 가방 문제 해결하기 | OR-Tools | Google Developers
이 페이지는 Cloud Translation API를 통해 번역되었습니다. Switch to English 의견 보내기 여러 여행 가방 문제 해결하기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세
developers.google.com
'M.S. > OR-Tools' 카테고리의 다른 글
[OR-Tools] Scheduling Overview (0) | 2023.02.24 |
---|---|
[OR-Tools 스터디] The Bin Packing Problem (0) | 2023.02.24 |
[OR-Tools 스터디] Packing (0) | 2023.02.23 |
[OR-Tools 스터디] Linear Sum Assignment Solver (0) | 2023.02.23 |
[OR-Tools 스터디] Assignment with Allowed Groups (0) | 2023.02.23 |
댓글