{"record":{"id":"e4334817edd12f7e","repo":"TheAlgorithms/Python","slug":"matrix-is-singular","errorCode":null,"errorMessage":"Matrix is singular","messagePattern":"Matrix is singular","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"linear_algebra/src/gaussian_elimination_pivoting.py","lineNumber":51,"sourceCode":"    ValueError: Matrix is singular\n    \"\"\"\n    ab = np.copy(matrix)\n    num_of_rows = ab.shape[0]\n    num_of_columns = ab.shape[1] - 1\n    x_lst: list[float] = []\n\n    if num_of_rows != num_of_columns:\n        raise ValueError(\"Matrix is not square\")\n\n    for column_num in range(num_of_rows):\n        # Lead element search\n        for i in range(column_num, num_of_columns):\n            if abs(ab[i][column_num]) > abs(ab[column_num][column_num]):\n                ab[[column_num, i]] = ab[[i, column_num]]\n\n        # Upper triangular matrix\n        if abs(ab[column_num, column_num]) < 1e-8:\n            raise ValueError(\"Matrix is singular\")\n\n        if column_num != 0:\n            for i in range(column_num, num_of_rows):\n                ab[i, :] -= (\n                    ab[i, column_num - 1]\n                    / ab[column_num - 1, column_num - 1]\n                    * ab[column_num - 1, :]\n                )\n\n    # Find x vector (Back Substitution)\n    for column_num in range(num_of_rows - 1, -1, -1):\n        x = ab[column_num, -1] / ab[column_num, column_num]\n        x_lst.insert(0, x)\n        for i in range(column_num - 1, -1, -1):\n            ab[i, -1] -= ab[i, column_num] * x\n\n    # Return the solution vector\n    return np.asarray(x_lst)","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/TheAlgorithms/Python/blob/f5988cc09713315817df6a7e327e258013a94440/linear_algebra/src/gaussian_elimination_pivoting.py#L33-L69","documentation":"Raised by solve_linear_system() in linear_algebra/src/gaussian_elimination_pivoting.py:51 during forward elimination when, after the pivot search, abs(ab[column_num][column_num]) < 1e-8. This means no usable pivot exists in that column — the matrix is (numerically) singular or ill-conditioned enough that the fixed 1e-8 tolerance rejects it, so back substitution would divide by zero.","triggerScenarios":"Calling solve_linear_system() with duplicate/linearly dependent rows, e.g. np.array([[1, 2, 3], [2, 4, 6]], dtype=float) (row2 = 2*row1), or np.zeros((2, 3)). Also triggered by very small-magnitude entries: a matrix scaled by 1e-9 can be rejected even if mathematically non-singular, because of the absolute tolerance.","commonSituations":"Rank-deficient data (repeated measurements, collinear features), zero matrices from empty input, or poorly scaled systems where legitimate pivots fall below 1e-8. Users moving from np.linalg.solve are surprised that near-singular matrices are rejected by tolerance rather than producing garbage.","solutions":["Check np.linalg.matrix_rank(A) == n or abs(np.linalg.det(A)) is not tiny before calling.","Rescale rows/columns so matrix entries are of order 1 (row equilibration) — the 1e-8 tolerance is absolute, not relative.","Remove linearly dependent equations or use np.linalg.lstsq for rank-deficient least-squares solutions.","Catch ValueError and surface a 'singular system' message to the caller."],"exampleFix":"// before\nx = solve_linear_system(np.array([[1, 2, 3], [2, 4, 6]], dtype=float))  # ValueError: singular\n\n// after\nA = np.array([[1, 2], [2, 4]])\nif np.linalg.matrix_rank(A) < A.shape[0]:\n    x, *_ = np.linalg.lstsq(A, np.array([3, 6]), rcond=None)\nelse:\n    ab = np.column_stack((A, np.array([3, 6]))).astype(float)\n    x = solve_linear_system(ab)","handlingStrategy":"try-catch","validationCode":"import numpy as np\n\nA = ab[:, :-1]\n# rank check + scale check: the solver's 1e-8 pivot tolerance is absolute\nnonsingular = np.linalg.matrix_rank(A) == A.shape[0]\nwell_scaled = np.max(np.abs(A)) > 1e-6  # avoids rejecting legitimately small entries\nif not (nonsingular and well_scaled):\n    raise ValueError(\"system is singular or too small in magnitude for the 1e-8 pivot tolerance\")","typeGuard":null,"tryCatchPattern":"try:\n    x = solve_linear_system(ab)\nexcept ValueError as e:\n    if \"singular\" in str(e):\n        x, *_ = np.linalg.lstsq(ab[:, :-1], ab[:, -1], rcond=None)  # least-squares fallback\n    else:\n        raise","preventionTips":["Screen with np.linalg.matrix_rank(A) == n before solving; rank deficiency guarantees this error.","Scale equations so coefficients are order 1 — the 1e-8 pivot cutoff is absolute, so uniformly tiny systems (entries ~1e-9) get falsely rejected.","Deduplicate or drop linearly dependent rows before assembling the system.","Distinguish the two ValueErrors this function raises ('not square' vs 'singular') by message when handling both."],"tags":["linear-algebra","gaussian-elimination","singular-matrix","numerical-tolerance"],"backgroundTag":null,"analyzedSha":"f5988cc09713315817df6a7e327e258013a94440","analyzedAt":"2026-08-14T17:30:07.041Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}