assertion error
This commit is contained in:
1 parent
5a8c8cf0b0
commit
f36985221b
1 file changed
+112
-3
+112
-3
@@ -1,6 +1,13 @@
|
|||||||
"""Matrix multiplication with explicit dimension checks."""
|
"""Matrix multiplication with explicit dimension checks.
|
||||||
|
|
||||||
#ergänzter kommentar
|
This module provides a pure‑Python implementation that
|
||||||
|
- validates input dimensions and structure
|
||||||
|
- performs generic matrix multiplication without external libs
|
||||||
|
- raises informative ``ValueError`` when inputs are inconsistent.
|
||||||
|
|
||||||
|
The implementation is small but fully typed so it can be
|
||||||
|
imported into other projects or used as a teaching example.
|
||||||
|
"""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -23,23 +30,33 @@ def matmul(left: Matrix, right: Matrix) -> list[list[float]]:
|
|||||||
ValueError: If either input is empty, ragged, or if
|
ValueError: If either input is empty, ragged, or if
|
||||||
cols_left != rows_right.
|
cols_left != rows_right.
|
||||||
"""
|
"""
|
||||||
|
# Validate first matrix (rows and columns), raise if invalid.
|
||||||
_validate(left, "left")
|
_validate(left, "left")
|
||||||
|
# Validate second matrix for similar conditions.
|
||||||
_validate(right, "right")
|
_validate(right, "right")
|
||||||
|
|
||||||
|
# Number of columns in left matrix.
|
||||||
cols_left = len(left[0])
|
cols_left = len(left[0])
|
||||||
|
# Number of rows in right matrix.
|
||||||
rows_right = len(right)
|
rows_right = len(right)
|
||||||
|
# Ensure the inner dimensions are compatible.
|
||||||
if cols_left != rows_right:
|
if cols_left != rows_right:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"dimension mismatch: left has {cols_left} columns, "
|
f"dimension mismatch: left has {cols_left} columns, "
|
||||||
f"right has {rows_right} rows"
|
f"right has {rows_right} rows"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Number of columns in right matrix.
|
||||||
cols_right = len(right[0])
|
cols_right = len(right[0])
|
||||||
|
# Prepare result container: rows of left × columns of right.
|
||||||
result: list[list[float]] = []
|
result: list[list[float]] = []
|
||||||
|
# Iterate over rows of left matrix.
|
||||||
for i in range(len(left)):
|
for i in range(len(left)):
|
||||||
row: list[float] = []
|
row: list[float] = []
|
||||||
|
# Iterate over columns of right matrix.
|
||||||
for j in range(cols_right):
|
for j in range(cols_right):
|
||||||
total = 0.0
|
total = 0.0
|
||||||
|
# Accumulate dot product of row i of left and column j of right.
|
||||||
for k in range(cols_left):
|
for k in range(cols_left):
|
||||||
total += left[i][k] * right[k][j]
|
total += left[i][k] * right[k][j]
|
||||||
row.append(total)
|
row.append(total)
|
||||||
@@ -47,8 +64,20 @@ def matmul(left: Matrix, right: Matrix) -> list[list[float]]:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Helper to validate a matrix is non‑empty and rectangular.
|
||||||
def _validate(matrix: Matrix, name: str) -> None:
|
def _validate(matrix: Matrix, name: str) -> None:
|
||||||
"""Check that *matrix* is a non-empty, rectangular 2D sequence."""
|
"""Check that *matrix* is a non‑empty, rectangular 2D sequence.
|
||||||
|
|
||||||
|
Validation rules:
|
||||||
|
* The outer sequence must contain at least one row.
|
||||||
|
* Every row must have the same number of columns.
|
||||||
|
* No empty rows are allowed.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the matrix is empty, has zero columns, or is ragged.
|
||||||
|
"""
|
||||||
if len(matrix) == 0:
|
if len(matrix) == 0:
|
||||||
raise ValueError(f"{name} matrix is empty")
|
raise ValueError(f"{name} matrix is empty")
|
||||||
width = len(matrix[0])
|
width = len(matrix[0])
|
||||||
@@ -61,6 +90,36 @@ def _validate(matrix: Matrix, name: str) -> None:
|
|||||||
f"row {index} has {len(row)}"
|
f"row {index} has {len(row)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def transpose(matrix: Matrix) -> list[list[float]]:
|
||||||
|
"""Transponiere die gegebene Matrix.
|
||||||
|
|
||||||
|
Alle Zeilen werden zu Spalten und alle Spalten zu Zeilen.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
matrix
|
||||||
|
Matrix in Form ``Sequence[Sequence[float]]``.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
list[list[float]]
|
||||||
|
Die transponierte Matrix.
|
||||||
|
|
||||||
|
Raises
|
||||||
|
------
|
||||||
|
ValueError
|
||||||
|
Wenn ``matrix`` leer ist oder nicht gleichmäßig viele Spalten
|
||||||
|
in den Zeilen hat.
|
||||||
|
"""
|
||||||
|
_validate(matrix, "matrix")
|
||||||
|
rows = len(matrix)
|
||||||
|
cols = len(matrix[0])
|
||||||
|
transposed: list[list[float]] = []
|
||||||
|
for c in range(cols):
|
||||||
|
new_row: list[float] = []
|
||||||
|
for r in range(rows):
|
||||||
|
new_row.append(matrix[r][c])
|
||||||
|
transposed.append(new_row)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Example 1: standard 2x3 * 3x2 multiplication.
|
# Example 1: standard 2x3 * 3x2 multiplication.
|
||||||
@@ -101,3 +160,53 @@ if __name__ == "__main__":
|
|||||||
print("example 3 passed:", error)
|
print("example 3 passed:", error)
|
||||||
else:
|
else:
|
||||||
raise AssertionError("example 3 failed: no ValueError raised")
|
raise AssertionError("example 3 failed: no ValueError raised")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# Example 1: standard 2x3 * 3x2 multiplication.
|
||||||
|
a = [
|
||||||
|
[1, 2, 3],
|
||||||
|
[4, 5, 6],
|
||||||
|
]
|
||||||
|
b = [
|
||||||
|
[7, 8],
|
||||||
|
[9, 10],
|
||||||
|
[11, 12],
|
||||||
|
]
|
||||||
|
expected = [
|
||||||
|
[58, 64],
|
||||||
|
[139, 154],
|
||||||
|
]
|
||||||
|
assert matmul(a, b) == expected, f"example 1 failed: {matmul(a, b)}"
|
||||||
|
print("example 1 passed:", matmul(a, b))
|
||||||
|
|
||||||
|
# Example 2: multiplication with the identity matrix changes nothing.
|
||||||
|
identity = [
|
||||||
|
[1, 0, 0],
|
||||||
|
[0, 1, 0],
|
||||||
|
[0, 0, 1],
|
||||||
|
]
|
||||||
|
c = [
|
||||||
|
[2, -1, 0],
|
||||||
|
[0, 3, 4],
|
||||||
|
[5, 6, -2],
|
||||||
|
]
|
||||||
|
assert matmul(c, identity) == c, "example 2 failed"
|
||||||
|
print("example 2 passed:", matmul(c, identity))
|
||||||
|
|
||||||
|
# Example 3: mismatched dimensions must raise ValueError.
|
||||||
|
try:
|
||||||
|
matmul([[1, 2, 3]], [[1, 2]])
|
||||||
|
except ValueError as error:
|
||||||
|
print("example 3 passed:", error)
|
||||||
|
else:
|
||||||
|
raise AssertionError("example 3 failed: no ValueError raised")
|
||||||
|
|
||||||
|
# Example 4: Demonstration of the transpose function.
|
||||||
|
example_matrix = [[1, 2, 3], [4, 5, 6]]
|
||||||
|
transposed = transpose(example_matrix)
|
||||||
|
print("Example 4: transpose([[1,2,3],[4,5,6]]) =", transposed)
|
||||||
|
assert transposed == [[1, 4], [2, 5], [3, 6]], "Example 4 failed"
|
||||||
|
print("example 4 passed")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in new issue
Block a user