diff --git a/EPR/ue07/main.py b/EPR/ue07/main.py index 88e49b1..ad0deb8 100644 --- a/EPR/ue07/main.py +++ b/EPR/ue07/main.py @@ -1,5 +1,5 @@ '''EPR Übung 7''' -__author__ = "7987847, Werner" +__author__ = "7987847, Werner, 8004356, Gill" import random @@ -141,10 +141,19 @@ if __name__ == "__main__": try: dimension = int(dimension) - except ValueError: + + # Check if the dimension is positive + if dimension <= 0: + raise ValueError("Dimension must be a positive number.") + + except (ValueError, TypeError) as e: print("Bitte geben Sie eine positive Zahl ein.") exit() + #Test 1 - Positive Number [3] as input --> generates Matrix successfully + #Test 2 - Negative Number [-1] as input --> Value Error + #Test 3 - String (Hello) as input --> Value Error + gened_matrix = gen_matrix(dimension) print("Matrix:") @@ -153,7 +162,8 @@ if __name__ == "__main__": optimal_path, optimal_cost= greedy_approach(gened_matrix) - + print("\nGreedy Ansatz") + print("------------------") print("Weg:", optimal_path) print("Kosten:", optimal_cost) diff --git a/EPR/ue07/main.py.old b/EPR/ue07/main.py.old new file mode 100644 index 0000000..ebfd1e0 --- /dev/null +++ b/EPR/ue07/main.py.old @@ -0,0 +1,166 @@ +'''EPR Übung 7''' +__author__ = "7987847, Werner" + +import random + +def gen_matrix(width_height: int) -> list[list[(int, int)]]: + '''Generiert eine nxn Matrix mit Zufallszahlen zwischen -9 und 9 + Args: + n (int): Dimension der Matrix + Returns: + list(list()): nxn Matrix mit Zufallszahlen zwischen -9 und 9 + ''' + return [[random.randint(-9, 9) for _ in range(width_height)] for _ in range(width_height)] + + +def greedy_approach(matrix) -> list((int, int)): + '''Greedy Ansatz für den Weg durch die Matrix + + Returns: + list((int, int)): Liste mit den Koordinaten des Weges + ''' + + width_height = len(matrix) + + # Testmatrix + #matrix = [[4, 0, 8], [-3, -4, -7], [-8, -1, 7]] + + # Startpunkt + path_list = [(0, 0)] + index = (0, 0) + + cost = matrix[0][0] + + # Solange der Endpunkt nicht erreicht ist + while index != (width_height-1, width_height-1): + # Aktuelle Position + index_x, index_y = index + + best_next_index = None + + # Bestimmen des bestmöglichen nächsten Schrittes + + # nach Rechts + if index_x+1 < width_height: + # check if best_next_index not in path_list + if (index_x+1, index_y) not in path_list: + best_next_index = (index_x+1, index_y) + best_next_value = matrix[index_y][index_x+1] + # nach Unten + if index_y+1 < width_height: + if matrix[index_y+1][index_x] < best_next_value \ + and (index_x, index_y+1) not in path_list: + best_next_index = (index_x, index_y+1) + best_next_value = matrix[index_y+1][index_x] + # nach Links + if index_x-1 >= 0: + if matrix[index_y][index_x-1] < best_next_value \ + and (index_x-1, index_y) not in path_list: + best_next_index = (index_x-1, index_y) + best_next_value = matrix[index_y][index_x-1] + # nach Oben + if index_y-1 >= 0: + if matrix[index_y-1][index_x] < best_next_value \ + and (index_x, index_y-1) not in path_list: + best_next_index = (index_x, index_y-1) + best_next_value = matrix[index_y-1][index_x] + # Wenn kein Schritt mehr möglich ist + if not best_next_index: + print("Sackgasse!") + break + + # Besten nächsten Schritt zum Weg hinzufügen + path_list.append(best_next_index) + index = best_next_index + + cost += best_next_value + + return path_list, cost + + +def recursive_optimal_path( + matrix, + current_position=(0, 0), + current_cost=0, + current_path=[] + ): + '''Rekursiver Ansatz für den Weg durch die Matrix + + Args: + matrix (list(list())): Matrix + current_position (tuple(int, int)): Aktuelle Position + current_cost (int): Aktuelle Kosten + current_path (list((int, int))): Aktueller Weg''' + rows = len(matrix) + end = (rows - 1, rows - 1) + + # Base case: reached the bottom right corner + if current_position == end: + return current_path + [end], current_cost + + row, col = current_position + neighbors = [] + + # Bestimmen des bestmöglichen nächsten Schrittes + if row > 0: + neighbors.append(((row - 1, col), matrix[row - 1][col])) + if row < rows - 1: + neighbors.append(((row + 1, col), matrix[row + 1][col])) + if col > 0: + neighbors.append(((row, col - 1), matrix[row][col - 1])) + if col < rows - 1: + neighbors.append(((row, col + 1), matrix[row][col + 1])) + + best_path = None + best_cost = 99 + + # Alle Nachbarn durchgehen + for next_position, cost in neighbors: + # Wenn der Nachbar nicht im Pfad ist, dann wird der Pfad rekursiv fortgesetzt + # sonst bedeutet es, dass dieses Feld bereits besucht wurde + if next_position not in current_path: + new_path, new_cost = recursive_optimal_path(matrix, next_position, + current_cost + cost, + current_path + [current_position]) + + # Wenn der neue Pfad besser ist, wird der alte überschrieben + if new_cost < best_cost: + best_path = new_path + best_cost = new_cost + + return best_path, best_cost + + + + +if __name__ == "__main__": + print("Greedy Ansatz") + print("-------------") + print("Je höher die Dimension der Matrix, desto länger dauert die Berechnung.") + dimension = input("Geben Sie die Dimension der Matrix ein (positive Zahl): ") + + try: + dimension = int(dimension) + except ValueError: + print("Bitte geben Sie eine positive Zahl ein.") + exit() + + gened_matrix = gen_matrix(dimension) + + print("Matrix:") + for i in gened_matrix: + print(i) + + + optimal_path, optimal_cost= greedy_approach(gened_matrix) + + print("Weg:", optimal_path) + print("Kosten:", optimal_cost) + + print("\nOptimierter Ansatz") + print("------------------") + + optimal_path, optimal_cost = recursive_optimal_path(gened_matrix) + + print("Weg:", optimal_path) + print("Kosten:", optimal_cost) diff --git a/EPR/ue07/timeing.py b/EPR/ue07/timeing.py index 5944d49..121c43c 100644 --- a/EPR/ue07/timeing.py +++ b/EPR/ue07/timeing.py @@ -1,5 +1,5 @@ '''EPRE Übung 7 Aufgabe 3''' -__author__ = "7987847, Werner" +__author__ = "7987847, Werner, 8004356, Gill" import concurrent.futures import timeit @@ -86,10 +86,7 @@ if __name__ == "__main__": for size, runtime in zip(matrix_sizes, recursive_runtimes): print(f"Size: {size}, Runtime: {runtime:.6f} seconds") - print("Recursive runtimes:") - for size, runtime in zip(matrix_sizes, recursive_runtimes): - print(f"Size: {size}, Runtime: {runtime:.6f} seconds") - print(f"Size: {size}, Runtime: {runtime:.6f} seconds") + try: import matplotlib.pyplot as plt @@ -98,3 +95,6 @@ if __name__ == "__main__": except ImportError: print("matplotlib not installed. Skipping plotting of results.") + + +# Tests are in Documentation \ No newline at end of file diff --git a/EPR/ue07/timeing.py.old b/EPR/ue07/timeing.py.old new file mode 100644 index 0000000..5f6a00d --- /dev/null +++ b/EPR/ue07/timeing.py.old @@ -0,0 +1,100 @@ +'''EPRE Übung 7 Aufgabe 3''' +__author__ = "7987847, Werner" + +import concurrent.futures +import timeit +from main import greedy_approach, recursive_optimal_path, gen_matrix + +def measure_runtime(function, matrix): + '''Misst die Laufzeit von function mit matrix als Argument + + Args: + function (function): Funktion, deren Laufzeit gemessen werden soll + matrix (list(list(int))): Matrix, die als Argument an function übergeben wird + + Returns: + float: Laufzeit von function mit matrix als Argument''' + runtime = timeit.timeit(lambda: function(matrix), number=100) + return runtime + +def compare_runtimes_parallel(sizes, max_workers=16): + '''Vergleicht die Laufzeiten von greedy_approach und recursive_optimal_path für + verschiedene Matrixgrößen + + Args: + sizes (list(int)): Liste mit Matrixgrößen + max_workers (int, optional): Maximale Anzahl an Threads. Defaults to 16. + + Returns: + list(float), list(float): Listen mit Laufzeiten von greedy_approach und + recursive_optimal_path + ''' + greedy_runtimes = [] + recursive_runtimes = [] + + with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor: + futures = [] + for size in sizes: + matrix = gen_matrix(size) + + # Greedy-Ansatz + greedy_future = executor.submit(measure_runtime, greedy_approach, matrix) + futures.append((greedy_future, "Greedy", size)) + + # Rekursiver optimaler Pfad + recursive_future = executor.submit(measure_runtime, recursive_optimal_path, matrix) + futures.append((recursive_future, "Recursive", size)) + + for future, label, size in futures: + runtime = future.result() + print(f"Size: {size}, {label} Runtime: {runtime:.6f} seconds") + if label == "Greedy": + greedy_runtimes.append(runtime) + else: + recursive_runtimes.append(runtime) + + return greedy_runtimes, recursive_runtimes + +def plot_results(sizes, greedy_runtimes, recursive_runtimes): + '''Plottet die Laufzeiten von greedy_approach und recursive_optimal_path für + verschiedene Matrixgrößen + + Args: + sizes (list(int)): Liste mit Matrixgrößen + greedy_runtimes (list(float)): Liste mit Laufzeiten von greedy_approach + recursive_runtimes (list(float)): Liste mit Laufzeiten von recursive_optimal_path + ''' + plt.plot(sizes, greedy_runtimes, label="Greedy Approach") + plt.plot(sizes, recursive_runtimes, label="Recursive Optimal Path") + plt.xlabel("Matrix Size") + plt.ylabel("Runtime (seconds)") + plt.title("Comparison of Runtimes") + plt.legend() + plt.xticks(range(min(sizes), max(sizes)+1)) + plt.show() + +if __name__ == "__main__": + matrix_sizes = list(range(1, 7)) + + greedy_runtimes, recursive_runtimes = compare_runtimes_parallel(matrix_sizes) + + print("Greedy runtimes:") + for size, runtime in zip(matrix_sizes, greedy_runtimes): + print(f"Size: {size}, Runtime: {runtime:.6f} seconds") + + print("Recursive runtimes:") + for size, runtime in zip(matrix_sizes, recursive_runtimes): + print(f"Size: {size}, Runtime: {runtime:.6f} seconds") + + print("Recursive runtimes:") + for size, runtime in zip(matrix_sizes, recursive_runtimes): + print(f"Size: {size}, Runtime: {runtime:.6f} seconds") + print(f"Size: {size}, Runtime: {runtime:.6f} seconds") + + try: + import matplotlib.pyplot as plt + + plot_results(matrix_sizes, greedy_runtimes, recursive_runtimes) + + except ImportError: + print("matplotlib not installed. Skipping plotting of results.")