Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4961b3a

Browse files
Jiang15weijiangpre-commit-ci[bot]MaximSmolskiy
authored
Enhancement of the knapsack algorithm with memorization and generalisation (#9295)
* enhance knapsack problem * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * wei/refactor code * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update test_knapsack.py * Update knapsack.py * Update test_knapsack.py * Update knapsack.py * Update knapsack.py * Update knapsack.py * Update knapsack.py * Update knapsack.py * Update test_knapsack.py --------- Co-authored-by: weijiang <weijiang@weijiangs-MacBook-Pro.local> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maxim Smolskiy <mithridatus@mail.ru>
1 parent 44cf167 commit 4961b3a

File tree

3 files changed

+55
-24
lines changed

3 files changed

+55
-24
lines changed

‎knapsack/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# A naive recursive implementation of 0-1 Knapsack Problem
1+
# A recursive implementation of 0-N Knapsack Problem
22

33
This overview is taken from:
44

‎knapsack/knapsack.py

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
1-
"""A naive recursive implementation of 0-1 Knapsack Problem
1+
"""A recursive implementation of 0-N Knapsack Problem
22
https://en.wikipedia.org/wiki/Knapsack_problem
33
"""
44

55
from __future__ import annotations
66

7+
from functools import lru_cache
78

8-
def knapsack(capacity: int, weights: list[int], values: list[int], counter: int) -> int:
9+
10+
def knapsack(
11+
capacity: int,
12+
weights: list[int],
13+
values: list[int],
14+
counter: int,
15+
allow_repetition=False,
16+
) -> int:
917
"""
1018
Returns the maximum value that can be put in a knapsack of a capacity cap,
11-
whereby each weight w has a specific value val.
19+
whereby each weight w has a specific value val
20+
with option to allow repetitive selection of items
1221
1322
>>> cap = 50
1423
>>> val = [60, 100, 120]
@@ -17,28 +26,40 @@ def knapsack(capacity: int, weights: list[int], values: list[int], counter: int)
1726
>>> knapsack(cap, w, val, c)
1827
220
1928
20-
The result is 220 cause the values of 100 and 120 got the weight of 50
29+
Given the repetition is NOT allowed,
30+
the result is 220 cause the values of 100 and 120 got the weight of 50
2131
which is the limit of the capacity.
32+
>>> knapsack(cap, w, val, c, True)
33+
300
34+
35+
Given the repetition is allowed,
36+
the result is 300 cause the values of 60*5 (pick 5 times)
37+
got the weight of 10*5 which is the limit of the capacity.
2238
"""
2339

24-
# Base Case
25-
if counter == 0 or capacity == 0:
26-
return 0
27-
28-
# If weight of the nth item is more than Knapsack of capacity,
29-
# then this item cannot be included in the optimal solution,
30-
# else return the maximum of two cases:
31-
# (1) nth item included
32-
# (2) not included
33-
if weights[counter - 1] > capacity:
34-
return knapsack(capacity, weights, values, counter - 1)
35-
else:
36-
left_capacity = capacity - weights[counter - 1]
37-
new_value_included = values[counter - 1] + knapsack(
38-
left_capacity, weights, values, counter - 1
39-
)
40-
without_new_value = knapsack(capacity, weights, values, counter - 1)
41-
return max(new_value_included, without_new_value)
40+
@lru_cache
41+
def knapsack_recur(capacity: int, counter: int) -> int:
42+
# Base Case
43+
if counter == 0 or capacity == 0:
44+
return 0
45+
46+
# If weight of the nth item is more than Knapsack of capacity,
47+
# then this item cannot be included in the optimal solution,
48+
# else return the maximum of two cases:
49+
# (1) nth item included only once (0-1), if allow_repetition is False
50+
# nth item included one or more times (0-N), if allow_repetition is True
51+
# (2) not included
52+
if weights[counter - 1] > capacity:
53+
return knapsack_recur(capacity, counter - 1)
54+
else:
55+
left_capacity = capacity - weights[counter - 1]
56+
new_value_included = values[counter - 1] + knapsack_recur(
57+
left_capacity, counter - 1 if not allow_repetition else counter
58+
)
59+
without_new_value = knapsack_recur(capacity, counter - 1)
60+
return max(new_value_included, without_new_value)
61+
62+
return knapsack_recur(capacity, counter)
4263

4364

4465
if __name__ == "__main__":

‎knapsack/tests/test_knapsack.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def test_base_case(self):
3030

3131
def test_easy_case(self):
3232
"""
33-
test for the base case
33+
test for the easy case
3434
"""
3535
cap = 3
3636
val = [1, 2, 3]
@@ -48,6 +48,16 @@ def test_knapsack(self):
4848
c = len(val)
4949
assert k.knapsack(cap, w, val, c) == 220
5050

51+
def test_knapsack_repetition(self):
52+
"""
53+
test for the knapsack repetition
54+
"""
55+
cap = 50
56+
val = [60, 100, 120]
57+
w = [10, 20, 30]
58+
c = len(val)
59+
assert k.knapsack(cap, w, val, c, True) == 300
60+
5161

5262
if __name__ == "__main__":
5363
unittest.main()

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /