118 lines
3.1 KiB
Python
118 lines
3.1 KiB
Python
from __future__ import annotations
|
|
|
|
import math
|
|
|
|
|
|
def rot_2D(theta: float) -> list[list[float]]:
|
|
"""Erzeuge die 2D-Rotationsmatrix fuer eine Drehung um theta.
|
|
|
|
Args:
|
|
theta: Drehwinkel im Bogenmaß (Gegen den Uhrzeigersinn).
|
|
|
|
Returns:
|
|
Rotationsmatrix der Form 2 x 2:
|
|
[[cos(theta), -sin(theta)], [sin(theta), cos(theta)]].
|
|
"""
|
|
c = math.cos(theta)
|
|
s = math.sin(theta)
|
|
return [[c, -s], [s, c]]
|
|
|
|
|
|
def matmul(a: list[list[float]], b: list[list[float]]) -> list[list[float]]:
|
|
"""Multipliziere zwei Matrizen a (m x n) und b (n x p).
|
|
|
|
Args:
|
|
a: Matrix als Liste von Zeilen, Form m x n.
|
|
b: Matrix als Liste von Zeilen, Form n x p.
|
|
|
|
Returns:
|
|
Ergebnis c der Form m x p mit c[i][j] = sum(a[i][k] * b[k][j]).
|
|
|
|
Raises:
|
|
ValueError: wenn a oder b keine rechteckige Matrix ist, oder
|
|
wenn die Spaltenzahl von a ungleich der Zeilenzahl von b ist.
|
|
"""
|
|
if not a or not b:
|
|
raise ValueError("Matrizen duerfen nicht leer sein.")
|
|
|
|
n = len(a[0])
|
|
if any(len(row) != n for row in a):
|
|
raise ValueError("Matrix a ist nicht rechteckig.")
|
|
if any(len(row) != len(b[0]) for row in b):
|
|
raise ValueError("Matrix b ist nicht rechteckig.")
|
|
|
|
m = len(a)
|
|
k = len(b)
|
|
p = len(b[0])
|
|
|
|
if n != k:
|
|
raise ValueError(f"Dimensionen passen nicht: a ist {m}x{n}, b ist {k}x{p}.")
|
|
|
|
return [
|
|
[sum(a[i][t] * b[t][j] for t in range(n)) for j in range(p)] for i in range(m)
|
|
]
|
|
|
|
|
|
def transpose(a: list[list[float]]) -> list[list[float]]:
|
|
"""Transponiere eine Matrix a (m x n) zu a^T (n x m).
|
|
|
|
Args:
|
|
a: Matrix als Liste von Zeilen, Form m x n.
|
|
|
|
Returns:
|
|
Ergebnis a^T der Form n x m mit a^T[j][i] = a[i][j].
|
|
|
|
Raises:
|
|
ValueError: wenn a leer oder nicht rechteckig ist.
|
|
"""
|
|
if not a:
|
|
raise ValueError("Matrix darf nicht leer sein.")
|
|
|
|
n = len(a[0])
|
|
if any(len(row) != n for row in a):
|
|
raise ValueError("Matrix ist nicht rechteckig.")
|
|
|
|
return [list(col) for col in zip(*a)]
|
|
|
|
|
|
def rotate(a: list[list[float]]) -> list[list[float]]:
|
|
"""Rotiere eine Matrix a um 90 Grad im Uhrzeigersinn.
|
|
|
|
Args:
|
|
a: Matrix als Liste von Zeilen, Form m x n.
|
|
|
|
Returns:
|
|
Neue Matrix der Form n x m.
|
|
|
|
Raises:
|
|
ValueError: wenn a leer oder nicht rechteckig ist.
|
|
"""
|
|
return [list(reversed(row)) for row in transpose(a)]
|
|
|
|
|
|
if __name__ == "__main__":
|
|
a = [[1, 2, 3], [4, 5, 6]]
|
|
b = [[7, 8], [9, 10], [11, 12]]
|
|
|
|
product = matmul(a, b)
|
|
assert product == [[58, 64], [139, 154]]
|
|
print("matmul:", product)
|
|
|
|
transposed = transpose(a)
|
|
assert transposed == [[1, 4], [2, 5], [3, 6]]
|
|
print("transpose:", transposed)
|
|
assert transpose(transpose(a)) == a
|
|
|
|
rotated = rotate(a)
|
|
assert rotated == [[4, 1], [5, 2], [6, 3]]
|
|
print("rotate:", rotated)
|
|
assert rotate(rotate(rotate(rotate(a)))) == a
|
|
|
|
assert rot_2D(0) == [[1, 0], [0, 1]]
|
|
quarter = rot_2D(math.pi / 2)
|
|
point = transpose([[1.0, 0.0]])
|
|
result = matmul(quarter, point)
|
|
assert abs(result[0][0]) < 1e-9
|
|
assert abs(result[1][0] - 1.0) < 1e-9
|
|
print("rot_2D:", quarter)
|