150 lines
4.1 KiB
Python
150 lines
4.1 KiB
Python
"""Modul zur Matrizenmultiplikation."""
|
||
from __future__ import annotations
|
||
import math
|
||
from tabulate import tabulate
|
||
#test
|
||
Matrix = list[list[float]]
|
||
|
||
|
||
def matmul(a: Matrix, b: Matrix) -> Matrix:
|
||
"""Multipliziert zwei Matrizen a * b.
|
||
|
||
Args:
|
||
a: Erste Matrix der Dimension (m x n).
|
||
b: Zweite Matrix der Dimension (n x p).
|
||
|
||
Returns:
|
||
Ergebnismatrix der Dimension (m x p).
|
||
|
||
Raises:
|
||
ValueError: Wenn die Matrizen leer sind, unregulär sind
|
||
(ungleiche Zeilenlängen) oder die Innen Dimensionen
|
||
nicht zusammenpassen (a.Zeilen != b.Spalten).
|
||
"""
|
||
if not a or not b:
|
||
raise ValueError("Matrizen duerfen nicht leer sein.")
|
||
|
||
rows_a = len(a)
|
||
cols_a = len(a[0])
|
||
rows_b = len(b)
|
||
cols_b = len(b[0])
|
||
|
||
for row in a:
|
||
if len(row) != cols_a:
|
||
raise ValueError("Matrix a ist nicht rechteckig.")
|
||
for row in b:
|
||
if len(row) != cols_b:
|
||
raise ValueError("Matrix b ist nicht rechteckig.")
|
||
|
||
if cols_a != rows_b:
|
||
raise ValueError(
|
||
f"Nicht passende Dimensionen: a ist {rows_a}x{cols_a}, "
|
||
f"b ist {rows_b}x{cols_b} (a.Spalten muss b.Zeilen sein)."
|
||
)
|
||
|
||
result: Matrix = []
|
||
for i in range(rows_a):
|
||
new_row: list[float] = []
|
||
for j in range(cols_b):
|
||
new_row.append(sum(a[i][k] * b[k][j] for k in range(cols_a)))
|
||
result.append(new_row)
|
||
return result
|
||
|
||
|
||
def transpose(m: Matrix) -> Matrix:
|
||
"""Transponiert die gegebene Matrix.
|
||
|
||
Args:
|
||
m: Matrix von Dimension (rows x cols).
|
||
Returns:
|
||
Eine neue Matrix mit umgekehrter Dimension (cols x rows).
|
||
"""
|
||
if not m:
|
||
raise ValueError("Matrix darf nicht leer sein.")
|
||
rows = len(m)
|
||
cols = len(m[0])
|
||
# überprüfen, ob die Matrix rechteckig ist
|
||
for row in m:
|
||
if len(row) != cols:
|
||
raise ValueError("Matrix ist nicht rechteckig.")
|
||
# Transponieren
|
||
return [[m[r][c] for r in range(rows)] for c in range(cols)]
|
||
|
||
def rot_2D(m: Matrix | float) -> Matrix:
|
||
"""Rotiert die Matrix um 90 Grad im Uhrzeigersinn.
|
||
|
||
Falls ``m`` ein Zahlenwert ist, wird die Rotationsmatrix
|
||
für den Winkel ``m`` (in Bogenmaß) zurückgegeben. Andernfalls
|
||
wird die Matrix um 90° gedreht.
|
||
|
||
Args:
|
||
m: Eingabe‑Matrix oder Winkel in Radiant.
|
||
Returns:
|
||
Rotierte Matrix bzw. 2×2‑Rotationsmatrix.
|
||
"""
|
||
if isinstance(m, (int, float)):
|
||
theta = float(m)
|
||
c = math.cos(theta)
|
||
s = math.sin(theta)
|
||
return [[c, -s], [s, c]]
|
||
# Ansonsten normal 90°‑Rotation (wie bisher)
|
||
if not m:
|
||
raise ValueError("Matrix darf nicht leer sein.")
|
||
rows = len(m)
|
||
cols = len(m[0])
|
||
for row in m:
|
||
if len(row) != cols:
|
||
raise ValueError("Matrix ist nicht rechteckig.")
|
||
return [[m[row][col] for row in reversed(range(rows))] for col in range(cols)]
|
||
|
||
|
||
|
||
|
||
|
||
|
||
if __name__ == "__main__":
|
||
# Beispiel 1: klassischer Fall 2x3 * 3x2 -> 2x2
|
||
print(tabulate(rot_2D(1.0)))
|
||
a1 = [[1, 2, 3],
|
||
[4, 5, 6]]
|
||
b1 = [[7, 8],
|
||
[9, 10],
|
||
[11, 12]]
|
||
expected1 = [[58, 64],
|
||
[139, 154]]
|
||
got1 = matmul(a1, b1)
|
||
assert got1 == expected1, f"Beispiel 1 fehlgeschlagen: {got1}"
|
||
print("Beispiel 1 ok:", got1)
|
||
|
||
# Beispiel 4: Transponieren einer 3x2 Matrix -> 2x3
|
||
m4 = [[1, 2],
|
||
[3, 4],
|
||
[5, 6]]
|
||
expected4 = [[1, 3, 5],
|
||
[2, 4, 6]]
|
||
got4 = transpose(m4)
|
||
assert got4 == expected4, f"Beispiel 4 fehlgeschlagen: {got4}"
|
||
print("Beispiel 4 ok:", got4)
|
||
|
||
# Beispiel 5: Transponieren einer Einheitsmatrix -> gleich
|
||
e5 = [[1, 0, 0],
|
||
[0, 1, 0],
|
||
[0, 0, 1]]
|
||
got5 = transpose(e5)
|
||
assert got5 == e5, f"Beispiel 5 fehlgeschlagen: {got5}"
|
||
print("Beispiel 5 ok:", got5)
|
||
|
||
# Beispiel 6: Fehlerfall – transponieren leerer Matrix
|
||
try:
|
||
transpose([])
|
||
except ValueError as err:
|
||
print("Beispiel 6 ok (Fehler erwartet):", err)
|
||
|
||
m7 = [[1, 2, 3],
|
||
[4, 5, 6]]
|
||
expected7 = [[4, 1],
|
||
[5, 2],
|
||
[6, 3]]
|
||
|
||
|