Files

145 lines
3.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Matrix multiplication for nested list matrices.
This module contains the :func:`matmul` function, which multiplies two
matrices represented as nested Python lists. The matrices are
expected to be rectangular (each sub‑list has the same length). A
:class:`ValueError` is raised if the inner dimensions do not match.
Example
-------
>>> a = [[1, 2], [3, 4]]
>>> b = [[5, 6], [7, 8]]
>>> matmul(a, b)
[[19.0, 22.0], [43.0, 50.0]]
The function is intentionally simple and performs no type checking
of the inner elements; it simply forwards the arithmetic operations to
Python's built‑in integer and float handling.
"""
import math
from tabulate import tabulate
def rot_2D(theta: float) -> list[list[float]]:
"""Return the 2‑D rotation matrix for a given angle.
Parameters
----------
theta : float
Angle in radians to rotate counter‑clockwise around the origin.
Returns
-------
list[list[float]]
2x2 rotation matrix
Examples
--------
>>> rot_2D(0) # identity
[[1.0, -0.0], [0.0, 1.0]]
"""
c = math.cos(theta)
s = math.sin(theta)
return [[c, -s], [s, c]]
def matmul(a: list[list[float | int]], b: list[list[float | int]]) -> list[list[float]]:
"""Return the matrix product of *a* and *b*.
Parameters
----------
a : list[list[float | int]]
First matrix, shape ``(m, n)``.
b : list[list[float | int]]
Second matrix, shape ``(n, p)``.
Returns
-------
list[list[float]]
The result matrix of shape ``(m, p)``.
Raises
------
ValueError
If the number of columns of ``a`` does not equal the number of
rows of ``b``.
"""
n_cols_a = len(a[0]) if a else 0
n_rows_b = len(b)
if n_cols_a != n_rows_b:
raise ValueError(
f"inner dimensions must match: {n_cols_a} (a columns) != {n_rows_b} (b rows)"
)
m = len(a)
p = len(b[0]) if b else 0
# Pre‑allocate result matrix
result: list[list[float]] = [[0.0 for _ in range(p)] for _ in range(m)]
for i in range(m):
for k in range(n_cols_a): # using k as column index of a, row of b
a_val = a[i][k]
for j in range(p):
result[i][j] += a_val * b[k][j]
return result
def transpose(matrix: list[list[float | int]]) -> list[list[float | int]]:
"""Return the transpose of the given matrix.
Parameters
----------
matrix : list[list[float | int]]
Matrix to transpose. All rows must have the same length.
Returns
-------
list[list[float | int]]
Transposed matrix.
Raises
------
ValueError
If ``matrix`` is empty or rows have differing lengths.
Examples
--------
>>> mat = [[1, 2, 3], [4, 5, 6]]
>>> transpose(mat)
[[1, 4], [2, 5], [3, 6]]
"""
if not matrix:
raise ValueError("Matrix must not be empty")
row_length = len(matrix[0])
if any(len(row) != row_length for row in matrix):
raise ValueError("All rows must have the same number of columns")
return [list(col) for col in zip(*matrix)]
if __name__ == "__main__":
matrix_a = [
[3, 4, -1, 4],
[-2, 2, 5, 1],
]
matrix_b = [
[1, 3, -2],
[2, 5, 1],
[-1, 4, -4],
[2, 3, 6],
]
matrix = [
[1, 2, 3],
[4, 5, 6],
]
print("Transposed Matrix:\n", transpose(matrix))
print("\nMatrix multiplication result:\n")
matrix_c = matmul(matrix_a, matrix_b)
for row in matrix_c:
print(row)
print("\nRotation matrix 90°:\n", rot_2D(math.pi / 2))
print(tabulate(rot_2D(1.0)))