Skip to content

Commit b000f15

Browse files
authored
Define Item property ratio
1 parent 503c3bd commit b000f15

File tree

1 file changed

+42
-36
lines changed

1 file changed

+42
-36
lines changed

Diff for: greedy_methods/fractional_cover_problem.py

+42-36
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,93 @@
1-
# Explanation:- https://en.wikipedia.org/wiki/Set_cover_problem
1+
# https://en.wikipedia.org/wiki/Set_cover_problem
22

33
from dataclasses import dataclass
4+
from operator import attrgetter
45

56

67
@dataclass
78
class Item:
89
weight: int
910
value: int
1011

12+
@property
13+
def ratio(self) -> float:
14+
"""
15+
Return the value-to-weight ratio for the item.
16+
17+
Returns:
18+
float: The value-to-weight ratio for the item.
19+
20+
Examples:
21+
>>> Item(10, 65).ratio
22+
6.5
23+
24+
>>> Item(20, 100).ratio
25+
5.0
26+
27+
>>> Item(30, 120).ratio
28+
4.0
29+
"""
30+
return self.value / self.weight
31+
1132

1233
def fractional_cover(items: list[Item], capacity: int) -> float:
1334
"""
1435
Solve the Fractional Cover Problem.
1536
1637
Args:
17-
items (List[Item]): A list of items, where each item is represented as an
18-
Item object with weight and value attributes.
19-
capacity (int): The maximum weight capacity of the knapsack.
38+
items: A list of items, where each item has weight and value attributes.
39+
capacity: The maximum weight capacity of the knapsack.
2040
2141
Returns:
22-
float: The maximum value that can be obtained by selecting fractions of items to
23-
cover the knapsack's capacity.
42+
The maximum value that can be obtained by selecting fractions of items to cover
43+
the knapsack's capacity.
2444
2545
Raises:
26-
ValueError: If the `capacity` is negative.
46+
ValueError: If capacity is negative.
2747
2848
Examples:
29-
>>> items = [Item(10, 60), Item(20, 100), Item(30, 120)]
30-
>>> fractional_cover(items, 50)
49+
>>> fractional_cover((Item(10, 60), Item(20, 100), Item(30, 120)), capacity=50)
3150
240.0
3251
33-
>>> items = [Item(20, 100), Item(30, 120), Item(10, 60)]
34-
>>> fractional_cover(items, 25)
52+
>>> fractional_cover([Item(20, 100), Item(30, 120), Item(10, 60)], capacity=25)
3553
135.0
3654
37-
>>> items = [Item(10, 60), Item(20, 100), Item(30, 120)]
38-
>>> fractional_cover(items, 60)
55+
>>> fractional_cover([Item(10, 60), Item(20, 100), Item(30, 120)], capacity=60)
3956
280.0
4057
41-
>>> items = [Item(5, 30), Item(10, 60), Item(15, 90)]
42-
>>> fractional_cover(items, 30)
58+
>>> fractional_cover(items=[Item(5, 30), Item(10, 60), Item(15, 90)], capacity=30)
4359
180.0
4460
45-
>>> items = []
46-
>>> fractional_cover(items, 50)
61+
>>> fractional_cover(items=[], capacity=50)
4762
0.0
4863
49-
>>> items = [Item(10, 60)]
50-
>>> fractional_cover(items, 5)
64+
>>> fractional_cover(items=[Item(10, 60)], capacity=5)
5165
30.0
5266
53-
>>> items = [Item(10, 60)]
54-
>>> fractional_cover(items, 1)
67+
>>> fractional_cover(items=[Item(10, 60)], capacity=1)
5568
6.0
5669
57-
>>> items = [Item(1, 1)]
58-
>>> fractional_cover(items, 0)
70+
>>> fractional_cover(items=[Item(10, 60)], capacity=0)
5971
0.0
6072
61-
>>> items = [Item(10, 60)]
62-
>>> fractional_cover(items, -1)
73+
>>> fractional_cover(items=[Item(10, 60)], capacity=-1)
6374
Traceback (most recent call last):
6475
...
6576
ValueError: Capacity cannot be negative
6677
"""
6778
if capacity < 0:
6879
raise ValueError("Capacity cannot be negative")
69-
# Calculate the value-to-weight ratios for each item
70-
ratios = [(item.value / item.weight, item) for item in items]
71-
72-
# Sort the items by their value-to-weight ratio in descending order
73-
ratios.sort(key=lambda item_ratio: item_ratio[0], reverse=True)
7480

7581
total_value = 0.0
7682
remaining_capacity = capacity
7783

78-
for ratio, item in ratios:
84+
# Sort the items by their value-to-weight ratio in descending order
85+
for item in sorted(items, key=attrgetter("ratio"), reverse=True):
7986
if remaining_capacity == 0:
8087
break
8188

8289
weight_taken = min(item.weight, remaining_capacity)
83-
total_value += weight_taken * ratio
90+
total_value += weight_taken * item.ratio
8491
remaining_capacity -= weight_taken
8592

8693
return total_value
@@ -89,8 +96,7 @@ def fractional_cover(items: list[Item], capacity: int) -> float:
8996
if __name__ == "__main__":
9097
import doctest
9198

92-
result = doctest.testmod().failed
93-
if result == 0:
94-
print("All tests passed")
95-
else:
99+
if result := doctest.testmod().failed:
96100
print(f"{result} test(s) failed")
101+
else:
102+
print("All tests passed")

0 commit comments

Comments
 (0)