Skip to content

Determinant and Inverse

Compute matrix determinants and inverses using np.linalg.

np.linalg.det

1. Basic Usage

import numpy as np

def main():
    A = np.array([[1, 2],
                  [3, 4]])

    det = np.linalg.det(A)

    print("A =")
    print(A)
    print(f"det(A) = {det}")

if __name__ == "__main__":
    main()

Output:

A =
[[1 2]
 [3 4]]
det(A) = -2.0

2. Mathematical Form

For 2×2 matrix:

\[\det\begin{pmatrix} a & b \\ c & d \end{pmatrix} = ad - bc\]
import numpy as np

def main():
    a, b, c, d = 1, 2, 3, 4
    A = np.array([[a, b],
                  [c, d]])

    det_numpy = np.linalg.det(A)
    det_manual = a * d - b * c

    print(f"NumPy det:  {det_numpy}")
    print(f"Manual det: {det_manual}")

if __name__ == "__main__":
    main()

3. Larger Matrices

import numpy as np

def main():
    A = np.array([[1, 2, 3],
                  [4, 5, 6],
                  [7, 8, 10]])

    det = np.linalg.det(A)

    print("A =")
    print(A)
    print(f"det(A) = {det:.4f}")

if __name__ == "__main__":
    main()

Singular Matrices

1. Zero Determinant

import numpy as np

def main():
    # Singular matrix (rows are linearly dependent)
    A = np.array([[1, 2, 3],
                  [4, 5, 6],
                  [7, 8, 9]])

    det = np.linalg.det(A)

    print("A =")
    print(A)
    print(f"det(A) = {det:.2e}")  # Essentially zero

if __name__ == "__main__":
    main()

2. Numerical Precision

import numpy as np

def main():
    A = np.array([[1, 2, 3],
                  [4, 5, 6],
                  [7, 8, 9]])

    det = np.linalg.det(A)

    # Check if "essentially zero"
    is_singular = np.abs(det) < 1e-10

    print(f"det(A) = {det:.2e}")
    print(f"Is singular: {is_singular}")

if __name__ == "__main__":
    main()

3. Condition Number

Better way to check near-singularity.

import numpy as np

def main():
    A = np.array([[1, 2, 3],
                  [4, 5, 6],
                  [7, 8, 9.0001]])  # Nearly singular

    cond = np.linalg.cond(A)

    print(f"Condition number: {cond:.2e}")
    print("High condition number indicates near-singularity")

if __name__ == "__main__":
    main()

np.linalg.inv

1. Basic Usage

import numpy as np

def main():
    A = np.array([[1, 2],
                  [3, 4]])

    A_inv = np.linalg.inv(A)

    print("A =")
    print(A)
    print()
    print("A^(-1) =")
    print(A_inv)

if __name__ == "__main__":
    main()

2. Verify Inverse

import numpy as np

def main():
    A = np.array([[1, 2],
                  [3, 4]])

    A_inv = np.linalg.inv(A)

    # A @ A^(-1) should be identity
    product = A @ A_inv

    print("A @ A^(-1) =")
    print(product)
    print()
    print("Close to identity:", np.allclose(product, np.eye(2)))

if __name__ == "__main__":
    main()

3. Singular Matrix Error

import numpy as np

def main():
    A = np.array([[1, 2],
                  [2, 4]])  # Singular (row 2 = 2 * row 1)

    try:
        A_inv = np.linalg.inv(A)
    except np.linalg.LinAlgError as e:
        print(f"Error: {e}")

if __name__ == "__main__":
    main()

np.linalg.pinv

1. Pseudo-Inverse

Moore-Penrose pseudo-inverse for non-square or singular matrices.

import numpy as np

def main():
    # Non-square matrix
    A = np.array([[1, 2],
                  [3, 4],
                  [5, 6]])

    A_pinv = np.linalg.pinv(A)

    print(f"A shape: {A.shape}")
    print(f"A+ shape: {A_pinv.shape}")
    print()
    print("A+ =")
    print(A_pinv)

if __name__ == "__main__":
    main()

2. Least Squares

Pseudo-inverse gives least squares solution.

import numpy as np

def main():
    # Overdetermined system
    A = np.array([[1, 1],
                  [1, 2],
                  [1, 3]])
    b = np.array([1, 2, 2])

    # Least squares via pinv
    x = np.linalg.pinv(A) @ b

    print(f"x = {x}")
    print(f"Residual: {np.linalg.norm(A @ x - b):.4f}")

if __name__ == "__main__":
    main()

3. Singular Matrix

import numpy as np

def main():
    # Singular matrix
    A = np.array([[1, 2],
                  [2, 4]])

    # inv fails, pinv works
    A_pinv = np.linalg.pinv(A)

    print("A (singular) =")
    print(A)
    print()
    print("A+ =")
    print(A_pinv)

if __name__ == "__main__":
    main()

Applications

1. Linear Transformation

import numpy as np

def main():
    # Transform points
    A = np.array([[2, 0],
                  [0, 3]])

    points = np.array([[1, 0],
                       [0, 1],
                       [1, 1]])

    # Forward transform
    transformed = (A @ points.T).T

    # Inverse transform
    A_inv = np.linalg.inv(A)
    recovered = (A_inv @ transformed.T).T

    print("Original points:")
    print(points)
    print()
    print("Transformed:")
    print(transformed)
    print()
    print("Recovered:")
    print(recovered)

if __name__ == "__main__":
    main()

2. Covariance Inverse

import numpy as np

def main():
    # Sample covariance matrix
    np.random.seed(42)
    X = np.random.randn(100, 3)
    cov = np.cov(X.T)

    # Precision matrix (inverse covariance)
    precision = np.linalg.inv(cov)

    print("Covariance:")
    print(cov.round(3))
    print()
    print("Precision:")
    print(precision.round(3))

if __name__ == "__main__":
    main()

3. Matrix Equation

Solve \(AXB = C\) for \(X\).

import numpy as np

def main():
    A = np.array([[1, 2],
                  [3, 4]])
    B = np.array([[5, 6],
                  [7, 8]])
    C = np.array([[10, 20],
                  [30, 40]])

    # X = A^(-1) @ C @ B^(-1)
    X = np.linalg.inv(A) @ C @ np.linalg.inv(B)

    # Verify
    print("X =")
    print(X)
    print()
    print("A @ X @ B =")
    print(A @ X @ B)

if __name__ == "__main__":
    main()

Best Practices

1. Avoid Inverse

Prefer np.linalg.solve over computing inverse explicitly.

import numpy as np

def main():
    A = np.random.randn(100, 100)
    b = np.random.randn(100)

    # Bad: compute inverse
    x_bad = np.linalg.inv(A) @ b

    # Good: solve directly
    x_good = np.linalg.solve(A, b)

    print(f"Results close: {np.allclose(x_bad, x_good)}")

if __name__ == "__main__":
    main()

2. Check Condition

Always check condition number for numerical stability.

3. Use pinv for Robustness

When matrix may be singular or non-square, use pinv.