Description
matrix/inverse_of_matrix.py::inverse_of_matrix returns the transpose of the true inverse for 3×3 matrices. It builds the adjoint (transpose of the cofactor matrix) into adjoint_matrix, then never uses it — the inverse is computed from the un-transposed cofactor_matrix instead:
# Transpose the cofactor matrix (Adjoint matrix)
adjoint_matrix = array(cofactor_matrix)
for i in range(3):
for j in range(3):
adjoint_matrix[i][j] = cofactor_matrix[j][i] # adjoint computed correctly...
# Inverse of the matrix using the formula (1/determinant) * adjoint matrix
inverse_matrix = array(cofactor_matrix) # BUG: uses cofactor_matrix, not adjoint_matrix
for i in range(3):
for j in range(3):
inverse_matrix[i][j] /= d(determinant)
The correct formula is inverse = (1/det) * adjoint = (1/det) * transpose(cofactor). Because inverse_matrix is seeded from cofactor_matrix (line 148) and adjoint_matrix is discarded, the result is (1/det) * cofactor — the transpose of the real inverse. For any non-symmetric 3×3 matrix the returned matrix is wrong (it does not satisfy M @ M⁻¹ == I). The 2×2 branch is correct.
The existing 3×3 doctest enshrines the wrong (transposed) value, so the test suite does not catch it.
Steps to reproduce
import numpy as np
from matrix.inverse_of_matrix import inverse_of_matrix
M = [[2, 5, 7], [2, 0, 1], [1, 2, 3]] # the repo's own doctest input
got = inverse_of_matrix(M)
print(got) # [[2.0, 5.0, -4.0], [1.0, 1.0, -1.0], [-5.0, -12.0, 10.0]]
print(np.linalg.inv(np.array(M, float)).tolist())
# correct inverse: [[2, 1, -5], [5, 1, -12], [-4, -1, 10]] (the transpose of `got`)
print((np.array(M, float) @ np.array(got, float)))
# M @ got = [[-26, -69, 57], [-1, -2, 2], [-11, -29, 24]] -- NOT the identity
Expected behavior
inverse_of_matrix(M) returns M⁻¹ such that M @ M⁻¹ == I. For the example above that is [[2, 1, -5], [5, 1, -12], [-4, -1, 10]].
Actual behavior
It returns [[2, 5, -4], [1, 1, -1], [-5, -12, 10]] — the transpose of M⁻¹. M @ result is not the identity matrix, so the result is not an inverse.
Suggested fix
Use the adjoint when seeding the inverse (and correct the 3×3 doctests, which currently assert the transposed values):
inverse_matrix = array(adjoint_matrix) # was: array(cofactor_matrix)
for i in range(3):
for j in range(3):
inverse_matrix[i][j] /= d(determinant)
After the fix, verify with numpy.allclose(M @ inverse_of_matrix(M), numpy.eye(3)) for several non-symmetric matrices.
Description
matrix/inverse_of_matrix.py::inverse_of_matrixreturns the transpose of the true inverse for 3×3 matrices. It builds the adjoint (transpose of the cofactor matrix) intoadjoint_matrix, then never uses it — the inverse is computed from the un-transposedcofactor_matrixinstead:The correct formula is
inverse = (1/det) * adjoint = (1/det) * transpose(cofactor). Becauseinverse_matrixis seeded fromcofactor_matrix(line 148) andadjoint_matrixis discarded, the result is(1/det) * cofactor— the transpose of the real inverse. For any non-symmetric 3×3 matrix the returned matrix is wrong (it does not satisfyM @ M⁻¹ == I). The 2×2 branch is correct.The existing 3×3 doctest enshrines the wrong (transposed) value, so the test suite does not catch it.
Steps to reproduce
Expected behavior
inverse_of_matrix(M)returnsM⁻¹such thatM @ M⁻¹ == I. For the example above that is[[2, 1, -5], [5, 1, -12], [-4, -1, 10]].Actual behavior
It returns
[[2, 5, -4], [1, 1, -1], [-5, -12, 10]]— the transpose ofM⁻¹.M @ resultis not the identity matrix, so the result is not an inverse.Suggested fix
Use the adjoint when seeding the inverse (and correct the 3×3 doctests, which currently assert the transposed values):
After the fix, verify with
numpy.allclose(M @ inverse_of_matrix(M), numpy.eye(3))for several non-symmetric matrices.