Подсчет предметов, входящих в ветку и связанный рюкзак
Используя алгоритм ветвей и границ, я оценил оптимальную прибыль от данного набора предметов, но теперь я хочу выяснить, какие предметы включены в это оптимальное решение. Я оцениваю значение прибыли оптимального ранца следующим образом (адаптировано отсюда):
import Queue
class Node:
def __init__(self, level, profit, weight):
self.level = level # The level within the tree (depth)
self.profit = profit # The total profit
self.weight = weight # The total weight
def solveKnapsack(weights, profits, knapsackSize):
numItems = len(weights)
queue = Queue.Queue()
root = Node(-1, 0, 0)
queue.put(root)
maxProfit = 0
bound = 0
while not queue.empty():
v = queue.get() # Get the next item on the queue
uLevel = v.level + 1
u = Node(uLevel, v.profit + e[uLevel][1], v.weight + e[uLevel][0])
bound = getBound(u, numItems, knapsackSize, weights, profits)
if u.weight <= knapsackSize and u.profit > maxProfit:
maxProfit = uProfit
if bound > maxProfit:
queue.put(u)
u = Node(uLevel, v.profit, v.weight)
bound = getBound(u, numItems, knapsackSize, weights, profits)
if (bound > maxProfit):
queue.put(u)
return maxProfit
# This is essentially the brute force solution to the fractional knapsack
def getBound(u, numItems, knapsackSize, weight, profit):
if u.weight >= knapsackSize: return 0
else:
upperBound = u.profit
totalWeight = u.weight
j = u.level + 1
while j < numItems and totalWeight + weight[j] <= C:
upperBound += profit[j]
totalWeight += weights[j]
j += 1
if j < numItems:
result += (C - totalWeight) * profit[j]/weight[j]
return upperBound
Итак, как я могу получить предметы, которые формируют оптимальное решение, а не только прибыль?
2 ответа
Я получил это с помощью вашего кода в качестве отправной точки. Я определил мой Node
Класс как:
class Node:
def __init__(self, level, profit, weight, bound, contains):
self.level = level # current level of our node
self.profit = profit
self.weight = weight
self.bound = bound # max (optimistic) value our node can take
self.contains = contains # list of items our node contains
Затем я запустил свой рюкзак Solver аналогичным образом, но инициализировал root = Node(0, 0, 0, 0.0, [])
, Значение root.bound
может быть поплавком, поэтому я инициализировал его 0.0
в то время как другие значения (по крайней мере, в моей проблеме) являются целыми числами. Узел пока ничего не содержит, поэтому я начал его с пустого списка. Я следовал схеме, аналогичной вашему коду, за исключением того, что сохранил границу в каждом узле (не уверен, что это необходимо) и обновил contains
список с использованием:
u.contains = v.contains[:] # copies the items in the list, not the list location
# Initialize u as Node(uLevel, uProfit, uWeight, 0.0, uContains)
u.contains.append(uLevel) # add the current item index to the list
Обратите внимание, что я только обновил contains
список в узле "Взятие предмета". Это первая инициализация в вашем основном цикле, предшествующая первой if bound > maxProfit:
заявление. Я обновил contains
список в if:
заявление прямо перед этим, когда вы обновляете значение maxProfit
:
if u.weight <= knapsackSize and u.value > maxProfit:
maxProfit = u.profit
bestList = u.contains
Здесь хранятся индексы предметов, которые вы принимаете bestList
, Я также добавил условие if v.bound > maxProfit and v.level < items-1
в основной цикл сразу после v = queue.get()
так что я не продолжаю идти после того, как достигну последнего пункта, и я не перебираю ветки, которые не стоит изучать.
Также, если вы хотите получить вывод в двоичном списке, показывающий, какие элементы выбраны по индексу, вы можете использовать:
taken = [0]*numItems
for item in bestList:
taken[item] = 1
print str(taken)
У меня были некоторые другие отличия в моем коде, но это должно позволить вам получить список выбранных вами предметов.
Я думал об этом в течение некоторого времени. Очевидно, вам нужно добавить несколько методов в ваш класс Node, которые будут назначать путь_узла и добавлять к нему текущий уровень. Вы вызываете ваши методы внутри вашего цикла и назначаете path_list для вашего optim_item_list, когда ваш node_weight меньше емкости, а его значение больше, чем max_profit, то есть где вы назначаете maxProfit. Вы можете найти реализацию Java здесь