-
Notifications
You must be signed in to change notification settings - Fork 1
/
knapsack_bnb_pq.py
48 lines (42 loc) · 1.52 KB
/
knapsack_bnb_pq.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 0-1 Knapsack Branch and Bound with Heapq
# By James Lao.
from heapq import *
import time
import sys
def knapsack(vw, limit):
def bound(v, w, j):
if j >= len(vw) or w > limit:
return -1
else:
while j < len(vw) and w + vw[j][1] <= limit:
v, w, j = v + vw[j][0], w + vw[j][1], j + 1
if j < len(vw):
v += (limit - w) * vw[j][0] / (vw[j][1] * 1.0)
return v
maxValue = 0
PQ = [[-bound(0, 0, 0), 0, 0, 0]] # -bound to keep maxheap
counter = 0
while PQ:
counter += 1
b, v, w, j = heappop(PQ)
if b <= -maxValue: # promising w/ j
if w + vw[j][1] <= limit:
maxValue = max(maxValue, v + vw[j][0])
heappush(PQ, [-bound(v + vw[j][0], w + vw[j][1],
j + 1), v + vw[j][0], w + vw[j][1], j + 1])
if j < len(vw) - 1:
heappush(PQ, [-bound(v, w, j + 1), v, w, j + 1])
print("Total nodes:", counter)
return maxValue
if __name__ == "__main__":
with open(sys.argv[1] if len(sys.argv) > 1 else sys.exit(1)) as f:
limit, n = map(int, f.readline().split())
vw = [] # value, weight, value density
for ln in f.readlines():
vl, wl = tuple(map(int, ln.split()))
vw.append([vl, wl, vl / (wl * 1.0)])
start = time.time()
A = knapsack(sorted(vw, key=lambda x: x[2], reverse=True), limit)
end = time.time()
print(A)
print(end - start)