diff --git a/Lab4/backpack.py b/Lab4/backpack.py new file mode 100644 index 0000000..9bc5f1b --- /dev/null +++ b/Lab4/backpack.py @@ -0,0 +1,165 @@ +import random +import time +import matplotlib.pyplot as plt +import sys + +def greedy(n, weight, value, capacity ): + ratios = [(value[i] / weight[i], weight[i]) for i in range(n)] + ratios.sort(reverse=True, key=lambda x: x[0]) + + current_weight = 0 + current_value = 0 + items_taken = [] + + for ratio, weight in ratios: + if current_weight + weight <= capacity and current_value + value[ratios.index((ratio, weight))] <= capacity: + current_weight += weight + current_value += value[ratios.index((ratio, weight))] + items_taken.append(ratios.index((ratio, weight))) + + return current_value + +def dynamic(n, weight, value, capacity, print_table=False): + table = [[0 for _ in range(capacity + 1)] for _ in range(n + 1)] + + for i in range(1, n + 1): + for w in range(capacity + 1): + if weight[i - 1] <= w: + table[i][w] = max(table[i - 1][w], table[i - 1][w - weight[i - 1]] + value[i - 1]) + else: + table[i][w] = table[i - 1][w] + + + if print_table: + print("\n".join(["\t".join(map(str, row)) for row in table])) + return table[n][capacity] + +def benchmark_containers(container_list, capacity): + greedy_times = [] + dynamic_times = [] + greedy_values = [] + dynamic_values = [] + rel_errors = [] + + # For each container number or capacity + for containers in container_list: + weights = [random.randint(1, 10) for _ in range(containers)] + values = [random.randint(1, 20) for _ in range(containers)] + + # Dynamic + start = time.time() + dyn = dynamic(containers, weights, values, capacity) + dyn_time = (time.time() - start) * 1000 + + # Greedy + start = time.time() + gr = greedy(containers, weights, values, capacity) + gr_time = (time.time() - start) * 1000 + + greedy_times.append(gr_time) + dynamic_times.append(dyn_time) + greedy_values.append(gr) + dynamic_values.append(dyn) + + rel_errors.append((dyn - gr) / dyn * 100 if dyn != 0 else 0) + + return greedy_times, dynamic_times, rel_errors + +def benchmark_capacity(capacity_list, containers): + greedy_times = [] + dynamic_times = [] + greedy_values = [] + dynamic_values = [] + rel_errors = [] + + # For each container number or capacity + for capacity in capacity_list: + weights = [random.randint(1, 10) for _ in range(containers)] + values = [random.randint(1, 20) for _ in range(containers)] + + # Dynamic + start = time.time() + dyn = dynamic(containers, weights, values, capacity) + dyn_time = (time.time() - start) * 1000 + + # Greedy + start = time.time() + gr = greedy(containers, weights, values, capacity) + gr_time = (time.time() - start) * 1000 + + greedy_times.append(gr_time) + dynamic_times.append(dyn_time) + greedy_values.append(gr) + dynamic_values.append(dyn) + + rel_errors.append(abs((dyn - gr) / dyn) * 100 if dyn != 0 else 0) + + return greedy_times, dynamic_times, rel_errors + +if __name__ == "__main__": + # Check if there was given a second argument, if yes run a test instead of the benchmark + if len(sys.argv) > 1: + file = sys.argv[1] + """ + Format we are expecting: + 5 - liczba elementów + 3 2 4 3 1 - rozmiary + 5 3 4 4 2 - wartości + 8 - rozmiar plecaka + """ + with open(file, 'r') as f: + lines = f.readlines() + n = int(lines[0].strip()) + weights = list(map(int, lines[1].strip().split())) + values = list(map(int, lines[2].strip().split())) + capacity = int(lines[3].strip()) + + dynamic(n, weights, values, capacity, print_table=True) + exit(0) + + # First test case - constant capacity, variable number of containers + containers_list = list(range(5, 101, 5)) + + # Constant capacity of 20 + greedy_times, dynamic_times, rel_errors = benchmark_containers(containers_list, 20) + + plt.figure(figsize=(12,5)) + plt.subplot(1,2,1) + plt.plot(containers_list, greedy_times, label='Zachłanny', marker='o') + plt.plot(containers_list, dynamic_times, label='Dynamiczny', marker='o') + plt.xlabel('Liczba kontenerów') + plt.ylabel('Czas [ms]') + plt.title('Czas działania dla zmiennej liczby kontenerów (B=20)') + plt.legend() + + axis = plt.subplot(1,2,2) + plt.bar(containers_list, rel_errors) + plt.xlabel('Liczba kontenerów') + plt.ylabel('Błąd względny [%]') + axis.yaxis.set_major_formatter(lambda x, pos: f'{x}%'.replace('.0', '')) + plt.title('Błąd względny') + plt.savefig('benchmark_vary_n.png') + + + # Second test case - variable capacity, constant number of containers + capacity_list = list(range(5, 101, 5)) + + # Constant number of containers of 50 + greedy_times, dynamic_times, rel_errors = benchmark_capacity(capacity_list, 50) + + plt.figure(figsize=(12,5)) + plt.subplot(1,2,1) + plt.plot(capacity_list, greedy_times, label='Zachłanny', marker='o') + plt.plot(capacity_list, dynamic_times, label='Dynamiczny' , marker='o') + plt.xlabel('Pojemność') + plt.ylabel('Czas [ms]') + plt.title('Czas działania dla zmiennej pojemności (n=50)') + plt.legend() + + axis = plt.subplot(1,2,2) + plt.bar(capacity_list, rel_errors ) + plt.xlabel('Pojemność') + plt.ylabel('Błąd względny [%]') + axis.yaxis.set_major_formatter(lambda x, pos: f'{x}%'.replace('.0', '')) + plt.title('Błąd względny') + plt.savefig('benchmark_vary_capacity.png')