From cf4cef772603b0f4768ca9c5dc252aa60cb8aaad Mon Sep 17 00:00:00 2001 From: Felix Martin Date: Wed, 4 Dec 2019 12:50:14 -0500 Subject: [PATCH] Started to implement Knapsack. --- discrete_optimization.sublime-project | 9 ++++ knapsack/knapsack.py | 63 +++++++++++++++++++++++++-- knapsack/solver.py | 1 - 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/discrete_optimization.sublime-project b/discrete_optimization.sublime-project index 24db303..9452cc4 100644 --- a/discrete_optimization.sublime-project +++ b/discrete_optimization.sublime-project @@ -1,4 +1,13 @@ { + "build_systems": + [ + { + "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)", + "name": "Anaconda Python Builder", + "selector": "source.python", + "shell_cmd": "\"python\" -u \"$file\"" + } + ], "folders": [ { diff --git a/knapsack/knapsack.py b/knapsack/knapsack.py index 8b525b9..dab6d8d 100644 --- a/knapsack/knapsack.py +++ b/knapsack/knapsack.py @@ -62,8 +62,58 @@ def solve_knapsack_dynamic(knapsack): def solve_knapsack_depth_first_search(knapsack): - objective = 0 - pass + knapsack.items.sort(key=lambda item: item.value / item.weight, + reverse=True) + num_items = len(knapsack.items) + result = {"objective": 0, + "path": []} + + def get_max_value(from_index, capacity): + value = 0 + for item in knapsack.items[from_index:]: + if item.weight <= capacity: + value += item.value + capacity -= item.weight + else: + value += int((item.weight / capacity) * item.value) + 1 + return value + return value + + return sum([i.value for i in knapsack.items[from_index:]]) + + def search(index, capacity, value, path, result): + + if capacity < 0: + return + + if value > result["objective"]: + result["objective"] = value + result["path"] = path + + # Take current item. + if value + get_max_value(index, capacity) > result["objective"]: + item = knapsack.items[index] + new_index = index + 1 + new_path = path + [1] + new_capacity = capacity - item.weight + new_value = value + item.value + search(new_index, new_capacity, new_value, new_path, result) + + # Do not take current item. + new_index = index + 1 + if value + get_max_value(new_index, capacity) > result["objective"]: + new_path = path + [0] + search(new_index, capacity, value, new_path, result) + + def correct_path(path): + path = path + [0] * (num_items - len(path)) + values = zip(path, knapsack.items) + path = [v[0] for v in sorted(values, key=lambda value: value[1].index)] + return path + + search(0, knapsack.capacity, 0, [], result) + + return Result(result["objective"], 1, correct_path(result["path"])) def input_data_to_knapsack(input_data): @@ -74,7 +124,7 @@ def input_data_to_knapsack(input_data): for i in range(1, item_count + 1): line = lines[i] value, weight = map(int, line.split()) - items.append(Item(i-1, value, weight)) + items.append(Item(i - 1, value, weight)) k = Knapsack(item_count, capacity, items) return k @@ -87,3 +137,10 @@ def result_to_output_data(result): return output_data +if __name__ == '__main__': + file_location = "./data/ks_60_0" + with open(file_location, 'r') as input_data_file: + input_data = input_data_file.read() + k = input_data_to_knapsack(input_data) + print(result_to_output_data(solve_knapsack_dynamic(k))) + print(result_to_output_data(solve_knapsack_depth_first_search(k))) diff --git a/knapsack/solver.py b/knapsack/solver.py index 5ff74ba..2c638ae 100755 --- a/knapsack/solver.py +++ b/knapsack/solver.py @@ -25,4 +25,3 @@ if __name__ == '__main__': print("This test requires an input file. " "Please select one from the data directory. " "(i.e. python solver.py ./data/ks_4_0)") -