Python 背包分枝定界错误结果
我已经将上给出的代码转换为python版本。代码应计算重量Python 背包分枝定界错误结果,python,algorithm,knapsack-problem,Python,Algorithm,Knapsack Problem,我已经将上给出的代码转换为python版本。代码应计算重量W的背包中要填充的最大值的正确值。我已附上以下代码: #http://www.geeksforgeeks.org/branch-and-bound-set-2-implementation-of-01-knapsack/ from queue import Queue class Node: def __init__(self): self.level = None self.profit = N
W
的背包中要填充的最大值的正确值。我已附上以下代码:
#http://www.geeksforgeeks.org/branch-and-bound-set-2-implementation-of-01-knapsack/
from queue import Queue
class Node:
def __init__(self):
self.level = None
self.profit = None
self.bound = None
self.weight = None
def __str__(self):
return "Level: %s Profit: %s Bound: %s Weight: %s" % (self.level, self.profit, self.bound, self.weight)
def bound(node, n, W, items):
if(node.weight >= W):
return 0
profit_bound = int(node.profit)
j = node.level + 1
totweight = int(node.weight)
while ((j < n) and (totweight + items[j].weight) <= W):
totweight += items[j].weight
profit_bound += items[j].value
j += 1
if(j < n):
profit_bound += (W - totweight) * items[j].value / float(items[j].weight)
return profit_bound
Q = Queue()
def KnapSackBranchNBound(weight, items, total_items):
items = sorted(items, key=lambda x: x.value/float(x.weight), reverse=True)
u = Node()
v = Node()
u.level = -1
u.profit = 0
u.weight = 0
Q.put(u)
maxProfit = 0;
while not Q.empty():
u = Q.get()
if u.level == -1:
v.level = 0
if u.level == total_items - 1:
continue
v.level = u.level + 1
v.weight = u.weight + items[v.level].weight
v.profit = u.profit + items[v.level].value
if (v.weight <= weight and v.profit > maxProfit):
maxProfit = v.profit;
v.bound = bound(v, total_items, weight, items)
if (v.bound > maxProfit):
Q.put(v)
v.weight = u.weight
v.profit = u.profit
v.bound = bound(v, total_items, weight, items)
if (v.bound > maxProfit):
# print items[v.level]
Q.put(v)
return maxProfit
if __name__ == "__main__":
from collections import namedtuple
Item = namedtuple("Item", ['index', 'value', 'weight'])
input_data = open("test.data").read()
lines = input_data.split('\n')
firstLine = lines[0].split()
item_count = int(firstLine[0])
capacity = int(firstLine[1])
print "running from main"
items = []
for i in range(1, item_count+1):
line = lines[i]
parts = line.split()
items.append(Item(i-1, int(parts[0]), float(parts[1])))
kbb = KnapSackBranchNBound(capacity, items, item_count)
print kbb
第一行显示物品数量
和背包重量
。第一行下方的行显示这些项目的值
和重量
。项目使用名为双的创建,并根据值/重量进行排序。对于这个问题,我得到的是135而不是235。我做错了什么
编辑:
我已经解决了基于分支和边界查找正确项的问题。如果需要,可以检查它。问题是您正在队列中插入对同一节点()
对象的多个引用。修复方法是在while循环的每个迭代中初始化两个新的v
对象,如下所示:
while not Q.empty():
u = Q.get()
v = Node() # Added line
if u.level == -1:
v.level = 0
if u.level == total_items - 1:
continue
v.level = u.level + 1
v.weight = u.weight + items[v.level].weight
v.profit = u.profit + items[v.level].value
if (v.weight <= weight and v.profit > maxProfit):
maxProfit = v.profit;
v.bound = bound(v, total_items, weight, items)
if (v.bound > maxProfit):
Q.put(v)
v = Node() # Added line
v.level = u.level + 1 # Added line
v.weight = u.weight
v.profit = u.profit
v.bound = bound(v, total_items, weight, items)
if (v.bound > maxProfit):
# print(items[v.level])
Q.put(v)
而不是Q.empty():
u=Q.get()
v=节点()#添加了行
如果u.level==-1:
v、 级别=0
如果u.level==项目总数-1:
持续
v、 级别=u级+1
v、 重量=u.重量+项目[v.级别].重量
v、 利润=u.利润+项目[v.级别].价值
如果(v.重量最大利润):
最大利润=v.利润;
v、 绑定=绑定(v,项目总数,重量,项目)
如果(v.bound>maxProfit):
问题(五)
v=节点()#添加了行
v、 标高=u.标高+1#增加了一行
v、 重量=单位重量
v、 利润=美国利润
v、 绑定=绑定(v,项目总数,重量,项目)
如果(v.bound>maxProfit):
#打印(项目[级别])
问题(五)
如果没有这些重新初始化,您将修改已插入队列的v
对象。
这与C++中的不同,节点对象是隐式复制到队列中的值,以避免混淆问题,例如:< /P>你如何运行函数以获得135输出?在您的示例中,哪些项目的组合应该给出235?您是否有一个函数输出正确的较小示例?我已将代码修改为包含项的namedtuples。文件test.data
包含如上所述的信息。值为40、95和100的项目将给出此代码的值235。您可以通过设置input_data=“”{paste The file contents}”“”来运行它,并注释掉打开的(filename).read()。当然,如果使用Python2,队列模块是queue。我也将STR改为RPR,以便更好地使用调试器。是的,我看起来是在直接修改节点,而不必像C++版本那样复制它们。您知道现在有什么方法可以回溯此版本的解决方案吗?ThanksI也得到了同样的结果,不过如果定义节点(级别、权重、利润),看起来会更好。您还可以用一个简单的列表替换队列(用于同步线程)。@Pant这听起来像是一个新任务,您应该自己解决。你尝试了什么,你被困在哪里了?(提示:使用一个新属性扩展节点以跟踪已获取的项目。)我尝试累积哪些节点提供了超过maxProfit的值。然而,这会给出其中一个是最佳值的所有节点。我找不到一种方法来获取它们中的哪一个是最佳节点。@这里有另一个提示:尝试使用新属性v.selected扩展代码,使v.price==sum(items[I]。v.selected中I的值)和v.weight==sum(items[I]。v.selected中I的权重)。
while not Q.empty():
u = Q.get()
v = Node() # Added line
if u.level == -1:
v.level = 0
if u.level == total_items - 1:
continue
v.level = u.level + 1
v.weight = u.weight + items[v.level].weight
v.profit = u.profit + items[v.level].value
if (v.weight <= weight and v.profit > maxProfit):
maxProfit = v.profit;
v.bound = bound(v, total_items, weight, items)
if (v.bound > maxProfit):
Q.put(v)
v = Node() # Added line
v.level = u.level + 1 # Added line
v.weight = u.weight
v.profit = u.profit
v.bound = bound(v, total_items, weight, items)
if (v.bound > maxProfit):
# print(items[v.level])
Q.put(v)