Module 5 · Lesson 3

Solving Linear Systems

To solve Ax = b for x, use np.linalg.solve(A, b). It is faster and numerically more stable than computing np.linalg.inv(A) @ b — computing a full inverse does unnecessary extra work and amplifies floating-point error. Prefer solve over inv whenever you just need x.

np.linalg.det(A) computes the determinant. A matrix with det(A) == 0 is singular — it has no unique inverse, and np.linalg.solve will raise a LinAlgError for it.

That said, not every LAPACK build raises reliably for a singular matrix — some just hand back nan/inf values instead of erroring. np.isfinite(x) is the elementwise check for exactly this: it returns False wherever a value is nan or inf, and True everywhere else, so np.all(np.isfinite(x)) tells you in one line whether an entire array/result is “clean” (no nan/inf anywhere).

A = np.array([[3.0, 1.0], [1.0, 2.0]])
b = np.array([9.0, 8.0])

x = np.linalg.solve(A, b)
print("solution x:", x)
print("check A @ x == b:", np.allclose(A @ x, b))
print("det(A):", np.linalg.det(A))

singular = np.array([[1.0, 2.0], [2.0, 4.0]])   # second row = 2 * first row
print("det(singular):", np.linalg.det(singular))
try:
    np.linalg.solve(singular, np.array([1.0, 2.0]))
except np.linalg.LinAlgError as e:
    print("LinAlgError:", e)

Output:

solution x: [2. 3.]
check A @ x == b: True
det(A): 5.000000000000001
det(singular): 0.0
LinAlgError: Singular matrix
3.1

Solve or report singular

Write solve_or_none(A, b) that returns the solution vector x to Ax = b using np.linalg.solve, or returns None if A is singular. Catch LinAlgError — but also treat a result containing nan/inf as singular: depending on the exact LAPACK build, np.linalg.solve doesn't always raise for a singular matrix, it sometimes just returns garbage values instead, so a robust solution checks both.

💡 Hint

Wrap np.linalg.solve(A, b) in a try/except np.linalg.LinAlgError and return None in the except branch — then also check np.all(np.isfinite(x)) on whatever it returns, since a singular matrix doesn't always raise.

✅ Solution
def solve_or_none(A, b):
    try:
        x = np.linalg.solve(A, b)
    except np.linalg.LinAlgError:
        return None
    return x if np.all(np.isfinite(x)) else None
3.2

Is it singular?

Write is_singular(A, tol=1e-10) that returns True if the square matrix A is singular (its determinant is within tol of zero), False otherwise.

💡 Hint

Compute np.linalg.det(A) and compare abs(det) against tol.

✅ Solution
def is_singular(A, tol=1e-10):
    return abs(np.linalg.det(A)) < tol