commit e2ba1fd13cbea24c22d7c7ef820162a157dc93ec Author: somakui Date: Thu Oct 15 16:45:46 2026 +0200 Erster Stand: compute.py diff --git a/compute.py b/compute.py new file mode 100644 index 0000000..d686c28 --- /dev/null +++ b/compute.py @@ -0,0 +1,172 @@ +"""Mathematische Hilfsfunktionen für Matrixoperationen.""" + +import math + + +def matmul(matrix_a: list[list[float]], matrix_b: list[list[float]]) -> list[list[float]]: + """Berechnet das Matrixprodukt zweier Matrizen (matrix_a @ matrix_b). + + :param matrix_a: Die linke Matrix. + :param matrix_b: Die rechte Matrix. + :return: Die Ergebnismatrix der Multiplikation. + :raises ValueError: Wenn eine Matrix leer ist, Zeilen ungleich lang sind + oder die Spaltenanzahl von matrix_a nicht der Zeilenanzahl + von matrix_b entspricht. + """ + if not matrix_a or not matrix_b or not matrix_a[0] or not matrix_b[0]: + raise ValueError("Beide Matrizen müssen nicht-leer sein.") + + rows_a, cols_a = len(matrix_a), len(matrix_a[0]) + rows_b, cols_b = len(matrix_b), len(matrix_b[0]) + + if any(len(row) != cols_a for row in matrix_a) or any(len(row) != cols_b for row in matrix_b): + raise ValueError("Alle Zeilen einer Matrix müssen dieselbe Länge besitzen.") + + if cols_a != rows_b: + raise ValueError("Matrixdimensionen stimmen für die Multiplikation nicht überein.") + + result: list[list[float]] = [] + for i in range(rows_a): + result_row: list[float] = [] + for j in range(cols_b): + dot_product = sum(matrix_a[i][k] * matrix_b[k][j] for k in range(cols_a)) + result_row.append(dot_product) + result.append(result_row) + return result + + +def transpose(matrix: list[list[float]]) -> list[list[float]]: + """Transponiert eine Matrix, sodass alle Zeilen zu Spalten und Spalten zu Zeilen werden. + + :param matrix: Die zu transponierende Matrix. + :return: Die transponierte Matrix. + :raises ValueError: Wenn die Matrix leer ist oder die Zeilen ungleichmäßig + viele Spalten besitzen. + """ + if not matrix or not matrix[0]: + raise ValueError("Die Matrix darf nicht leer sein.") + + num_cols = len(matrix[0]) + if any(len(row) != num_cols for row in matrix): + raise ValueError("Alle Zeilen müssen dieselbe Länge besitzen.") + + num_rows = len(matrix) + return [ + [matrix[row_idx][col_idx] for row_idx in range(num_rows)] + for col_idx in range(num_cols) + ] + + +def rot_2d(angle: float) -> list[list[float]]: + """Berechnet die 2D-Rotationsmatrix für einen gegebenen Drehwinkel. + + Die Rotationsmatrix R(theta) lautet: + [[cos(theta), -sin(theta)], + [sin(theta), cos(theta)]] + + :param angle: Der Rotationswinkel im Bogenmaß (Radiant). + :return: Die 2x2-Rotationsmatrix als verschachtelte Liste. + """ + cos_theta = math.cos(angle) + sin_theta = math.sin(angle) + return [ + [cos_theta, -sin_theta], + [sin_theta, cos_theta], + ] + +if __name__ == "__main__": + a1 = [ + [3, 4, -1, 4], + [-2, 2, 5, 1], + ] + b1 = [ + [1, 3, -2], + [2, 5, 1], + [-1, 4, -4], + [2, 3, 6], + ] + expected_c1 = [ + [20, 37, 26], + [-1, 27, -8], + ] + c1 = matmul(a1, b1) + assert c1 == expected_c1, f"Fehler in Beispiel 1: Erwartet {expected_c1}, erhalten {c1}" + print("Test 1 (Skript-Beispiel) erfolgreich bestanden!") + + a2 = [ + [1, 2], + [3, 4], + ] + identity = [ + [1, 0], + [0, 1], + ] + c2 = matmul(a2, identity) + assert c2 == a2, f"Fehler in Beispiel 2: Erwartet {a2}, erhalten {c2}" + print("Test 2 (Einheitsmatrix) erfolgreich bestanden!") + + incompatible_b = [ + [1, 2], + [3, 4], + ] + try: + matmul(a1, incompatible_b) + raise AssertionError("Fehlerfall wurde nicht abgefangen!") + except ValueError: + print("Test 3 (Fehlerfall inkompatible Dimensionen) erfolgreich abgefangen!") + + # Tests für Transpose + example_matrix = [ + [1, 2, 3], + [4, 5, 6], + ] + expected_transposed = [ + [1, 4], + [2, 5], + [3, 6], + ] + assert transpose(example_matrix) == expected_transposed, ( + f"Erwartet: {expected_transposed}, Erhalten: {transpose(example_matrix)}" + ) + print("Test 4 (transpose) erfolgreich bestanden!") + + # Test transpose: Leere Matrix + try: + transpose([]) + raise AssertionError("Leere Matrix wurde nicht abgefangen!") + except ValueError: + print("Test 5 (transpose leere Matrix) erfolgreich abgefangen!") + + # Test transpose: Ungleichmäßige Zeilenlänge + uneven_matrix = [ + [1, 2, 3], + [4, 5], + ] + try: + transpose(uneven_matrix) + raise AssertionError("Ungleichmäßige Matrix wurde nicht abgefangen!") + except ValueError: + print("Test 6 (transpose ungleichmäßige Matrix) erfolgreich abgefangen!") + + # Test 7: Rotation um 0 Radianten (entspricht der Einheitsmatrix) + rot_0 = rot_2d(0.0) + assert math.isclose(rot_0[0][0], 1.0, abs_tol=1e-9) + assert math.isclose(rot_0[0][1], 0.0, abs_tol=1e-9) + assert math.isclose(rot_0[1][0], 0.0, abs_tol=1e-9) + assert math.isclose(rot_0[1][1], 1.0, abs_tol=1e-9) + print("Test rot_2D (0 Radiant) erfolgreich bestanden!") + + # Test 8: Rotation um 90 Grad (pi / 2) -> [[0, -1], [1, 0]] + rot_90 = rot_2d(math.pi / 2) + assert math.isclose(rot_90[0][0], 0.0, abs_tol=1e-9) + assert math.isclose(rot_90[0][1], -1.0, abs_tol=1e-9) + assert math.isclose(rot_90[1][0], 1.0, abs_tol=1e-9) + assert math.isclose(rot_90[1][1], 0.0, abs_tol=1e-9) + print("Test rot_2D (pi / 2 Radiant) erfolgreich bestanden!") + + # Test 9: Drehung des Vektors (1, 0) um 90 Grad ergibt (0, 1) via matmul + point = [[1.0], [0.0]] + rotated_point = matmul(rot_90, point) + assert math.isclose(rotated_point[0][0], 0.0, abs_tol=1e-9) + assert math.isclose(rotated_point[1][0], 1.0, abs_tol=1e-9) + print("Test rot_2D (Vektordrehung mit matmul) erfolgreich bestanden!") \ No newline at end of file