I tried the implementation given here for knapsack problem using Branch and Bound.
The solution seems fine but it doesn't give the final selected items to reach the optimal value. Is there a way to get this by changing the following code minimally?
import sys
def bound(vw, v, w, idx):
if idx >= len(vw) or w > limit:
return -1
else:
while idx < len(vw) and w + vw[idx][1] <= limit:
v, w, idx = v + vw[idx][0], w + vw[idx][1], idx + 1
if idx < len(vw):
v += (limit - w) * vw[idx][0] / (vw[idx][1] * 1.0)
return v
def knapsack(vw, limit, curValue, curWeight, curIndex):
global maxValue
if bound(vw, curValue, curWeight, curIndex) >= maxValue:
if curWeight + vw[curIndex][1] <= limit:
maxValue = max(maxValue, curValue + vw[curIndex][0])
knapsack(vw, limit, curValue + vw[curIndex][0], curWeight + vw[curIndex][1], curIndex + 1)
if curIndex < len(vw) - 1:
knapsack(vw, limit, curValue, curWeight, curIndex + 1)
return maxValue
maxValue = 0
if __name__ == '__main__':
with open(sys.argv[1] if len(sys.argv) > 1 else sys.exit(1)) as f:
n, limit = map(int, f.readline().split())
vw = []
taken = n * [0]
for ln in f.readlines():
vl, wl = map(int, ln.split())
vw.append([vl, wl, vl / (wl * 1.0)])
print(knapsack(sorted(vw, key=lambda x: x[2], reverse=True), limit, 0, 0, 0))
print(taken)
Lets say we have an input file with following contents
4 11
8 4
15 8
4 3
10 5
I am expecting a result like the following
19
0 1 1 0
I wrote my own implementation which gives the above desired output but it's taking too long for large problems like this one