From 878470fe738492b3806e479d4713d739b6709cbe Mon Sep 17 00:00:00 2001 From: Piotr Kozak Date: Sat, 14 Jun 2025 12:15:20 +0200 Subject: [PATCH] Backpack corrections and updates for file validation --- Lab3/graph.py | 48 +++++++++++++++++++++++++++++++++++++++++++++++- Lab3/hamilton.py | 34 ++++++++++++++++++++++++++++++++++ Lab4/backpack.py | 34 ++++++++++++++++++---------------- 3 files changed, 99 insertions(+), 17 deletions(-) diff --git a/Lab3/graph.py b/Lab3/graph.py index ae578fc..7926502 100644 --- a/Lab3/graph.py +++ b/Lab3/graph.py @@ -1,6 +1,8 @@ import random import time import matplotlib.pyplot as plt +import sys +from typing import List def generateGraph(n: int, saturation: int): edges = (n * (n - 1)) // 2 @@ -49,7 +51,16 @@ def generateGraph(n: int, saturation: int): return graph -def findEulerianCycle(graph_adj_sets): +def graphFromMatrix(matrix: List[List[int]]): + n = len(matrix) + graph = {i: [] for i in range(n)} + for i in range(n): + for j in range(n): + if matrix[i][j] == 1: + graph[i].append(j) + return graph + +def findEulerianCycle(graph_adj_sets) -> List[int] | None: current_graph = {v: set(neighbors) for v, neighbors in graph_adj_sets.items()} if not current_graph: @@ -113,6 +124,41 @@ def findHamiltonianCycle(graph): return None 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: + 0 0 1 1 1 1 + 0 0 1 1 0 0 + 1 1 0 0 1 1 + 1 1 0 0 1 1 + 1 0 1 1 0 1 + 1 0 1 1 1 0 + """ + with open(file, 'r') as f: + lines = f.readlines() + matrix = [list(map(int, line.strip().split())) for line in lines] + graph = graphFromMatrix(matrix) + + euler = findEulerianCycle(graph) + hamilton = findHamiltonianCycle(graph) + + if euler is None: + print("Eulerian cycle not found.") + exit(1) + if hamilton is None: + print("Hamiltonian cycle not found.") + exit(1) + + # We were asked to print the cycles starting from 1. Add the first node to the end of the list to make it a cycle + # Expected: 1 6 5 4 6 3 5 1 4 2 3 1 | Actual: 1 3 2 4 1 5 3 6 4 5 6 1 + print("Eulerian Cycle:", [v + 1 for v in euler ]) + # 1 3 2 4 5 6 1 | Real: 1 3 2 4 5 6 1 + print("Hamiltonian Cycle", [v + 1 for v in hamilton] + [hamilton[0] + 1]) + + exit(0) + n_values = range(10, 26) # Number of nodes to test saturations = [30, 70] # Saturation levels to test results = {} diff --git a/Lab3/hamilton.py b/Lab3/hamilton.py index 91faafe..dc4573d 100644 --- a/Lab3/hamilton.py +++ b/Lab3/hamilton.py @@ -1,6 +1,8 @@ import random import time import matplotlib.pyplot as plt +import sys +from typing import List def generate_hamiltonian_graph(n, saturation_percent): max_possible_edges = n * (n - 1) // 2 @@ -34,6 +36,16 @@ def generate_hamiltonian_graph(n, saturation_percent): return {k: list(v) for k, v in graph.items()} +def graphFromMatrix(matrix: List[List[int]]): + n = len(matrix) + graph = {i: [] for i in range(n)} + for i in range(n): + for j in range(n): + if matrix[i][j] == 1: + graph[i].append(j) + return graph + + def find_all_hamiltonian_cycles(graph): n = len(graph) cycles = set() @@ -65,6 +77,28 @@ def find_all_hamiltonian_cycles(graph): return list(cycles) if __name__ == "__main__": + if len(sys.argv) > 1: + file = sys.argv[1] + """ + Format we are expecting: + 0 0 1 1 1 1 + 0 0 1 1 0 0 + 1 1 0 0 1 1 + 1 1 0 0 1 1 + 1 0 1 1 0 1 + 1 0 1 1 1 0 + """ + with open(file, 'r') as f: + lines = f.readlines() + matrix = [list(map(int, line.strip().split())) for line in lines] + graph = graphFromMatrix(matrix) + + cycles = find_all_hamiltonian_cycles(graph) + + for cycle in cycles: + print(cycle) + exit(0) + n_values = range(5, 15) saturation = 50 diff --git a/Lab4/backpack.py b/Lab4/backpack.py index 9bc5f1b..a046865 100644 --- a/Lab4/backpack.py +++ b/Lab4/backpack.py @@ -4,18 +4,16 @@ 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]) + pairs = list(zip(value, weight)) + pairs.sort(reverse=True, key=lambda x: x[0] / x[1]) - current_weight = 0 current_value = 0 - items_taken = [] + currentCapacity = capacity - 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))) + for i in range(n): + if pairs[i][1] <= currentCapacity: + current_value += pairs[i][0] + currentCapacity -= pairs[i][1] return current_value @@ -61,6 +59,7 @@ def benchmark_containers(container_list, capacity): greedy_values.append(gr) dynamic_values.append(dyn) + print(f"greedy: {gr}, dynamic: {dyn}, rel_error: {(dyn - gr) / dyn * 100 if dyn != 0 else 0:.2f}%") rel_errors.append((dyn - gr) / dyn * 100 if dyn != 0 else 0) return greedy_times, dynamic_times, rel_errors @@ -75,7 +74,7 @@ def benchmark_capacity(capacity_list, containers): # 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)] + values = [random.randint(2, 20) for _ in range(containers)] # Dynamic start = time.time() @@ -91,8 +90,9 @@ def benchmark_capacity(capacity_list, containers): dynamic_times.append(dyn_time) greedy_values.append(gr) dynamic_values.append(dyn) + print(f"greedy: {gr}, dynamic: {dyn}, rel_error: {(dyn - gr) / dyn * 100 if dyn != 0 else 0:.2f}%") - rel_errors.append(abs((dyn - gr) / dyn) * 100 if dyn != 0 else 0) + rel_errors.append((dyn - gr) / dyn * 100 if dyn != 0 else 0) return greedy_times, dynamic_times, rel_errors @@ -115,20 +115,22 @@ if __name__ == "__main__": capacity = int(lines[3].strip()) dynamic(n, weights, values, capacity, print_table=True) + print(greedy(n, weights, values, capacity)) exit(0) # First test case - constant capacity, variable number of containers - containers_list = list(range(5, 101, 5)) + containers_list = list(range(1, 51, 2)) # 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.plot(containers_list, greedy_times, label='Zachłanny', ) + plt.plot(containers_list, dynamic_times, label='Dynamiczny', ) plt.xlabel('Liczba kontenerów') plt.ylabel('Czas [ms]') + # plt.yscale('log', base=2) plt.title('Czas działania dla zmiennej liczby kontenerów (B=20)') plt.legend() @@ -149,8 +151,8 @@ if __name__ == "__main__": 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.plot(capacity_list, greedy_times, label='Zachłanny' ) + plt.plot(capacity_list, dynamic_times, label='Dynamiczny') plt.xlabel('Pojemność') plt.ylabel('Czas [ms]') plt.title('Czas działania dla zmiennej pojemności (n=50)')