-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathKnapSack.py
91 lines (71 loc) · 3.28 KB
/
KnapSack.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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
from Strategy import Strategy
from Strategy import MaxValueStrategy
from Bag import Bag
class KnapSack():
def __init__(self, strategy: Strategy) -> None:
self._strategy = strategy
self.discarder = 0
self.criterion_function = None
self.message = ""
self.bag = None
@property
def strategy(self) -> Strategy:
return self._strategy
def getStrategy(self, weight):
return self._strategy.knapSack(weight)
@strategy.setter
def strategy(self, strategy: Strategy) -> None:
self._strategy = strategy
def isMaxValueStrategy(self,strategy):
True if isinstance(strategy, MaxValueStrategy) else False
def printBagContent(self):
if self.bag is None:
print("Error: cannot print total values, try using execute() first")
return
self.bag.printBag()
def execute(self, knapsack_max_weight, items_weight, items_values) -> None:
def makeDummyArray(length):
return [0] * length
def makeCopy(array):
return list(array)
def discardValue(array, position, discarder=1):
array[position] = discarder
if len(items_weight) is not len(items_values):
print("Error: Discrepancy between items weight length and items values length, does not match.")
return
items_length = len(items_weight)
# Get variables from strategy
self.message, self.discarder, self.criterion_function = self.getStrategy(items_weight)
dummy_array = makeDummyArray(items_length)
items_weight_copy = makeCopy(items_weight)
if self.isMaxValueStrategy(self._strategy): # it needs to divide values per unit
items_weight_copy = self._strategy.divideValuesPerUnit(items_values,items_weight)
current_weight = 0
final_items_weight_values = list()
# [ KnapSack alorithm ]
while( current_weight < knapsack_max_weight ):
actual_value = self.criterion_function(items_weight_copy) # max/min
actual_value_position = items_weight_copy.index(actual_value)
# current weight + the next calculated weight
future_weight = current_weight + items_weight[actual_value_position]
# if future weight is still less than the KnapSack max weight:
if future_weight <= knapsack_max_weight:
current_weight = future_weight
discardValue(dummy_array, actual_value_position)
else:
break
# Add the value and discard it.
final_items_weight_values.append(actual_value)
discardValue(items_weight_copy, actual_value_position, self.discarder)
# Finished algorithm - Now printing results
total_value = 0
values_grabbed = list()
# Using dummy array to get data
for i in range(len(dummy_array)):
if dummy_array[i] != 0:
values_grabbed.append(items_values[i])
total_value += items_values[i]
# Setting data and printing.
self.bag = Bag(values_grabbed, final_items_weight_values, total_value, current_weight)
print("Algorithm: '", self.message ,"' has been used. printing now.")
self.printBagContent()