Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 背包分枝定界错误结果_Python_Algorithm_Knapsack Problem - Fatal编程技术网

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

我已经将上给出的代码转换为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 = 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)