Skip to content

Gauss-Jordan

To perform Gauss-Jordan elimination, the following steps should be considered:

We will have an equation of the form \(Ax = B\), where \(A\) is the coefficient matrix, \(x\) is the solution vector, and \(B\) is the results vector.

\[ \begin{bmatrix} a_{11} & \dots & a_{1n} \\ \vdots & & \vdots \\ a_{n1} & \dots & a_{nn} \end{bmatrix} \begin{bmatrix} x_{1} \\ \vdots \\ x_n \end{bmatrix} = \begin{bmatrix} b_{1} \\ \vdots \\ b_n \end{bmatrix} \]

Recall that the following operations can be performed:

  • Multiply (or divide) a row by a scalar.
  • Addition/subtraction between rows.
  • Swapping rows.

Implementation Details

  • Columns must be eliminated in order from left to right.
  • The number of row operations needed is always the number of elements below the main diagonal.
  • The pivot will always be the first row (or never changed).
  • Operations must be performed to eliminate first \(a_{21}, a_{31}, \dots, a_{n1}\).
    • In this case, the pivot will always be the first row to operate with.
    • The pivot is the row immediately above the diagonal.
  • The row swapping operation will always be performed when a zero can be moved down to satisfy the lower diagonal zeros.
  • The number of operations required by Gauss is at most \(\frac{2}{3}n^3 + \frac{5}{2}n^2 - \frac{7}{6}n\), which is \(O(n^3)\).
Python Code
import numpy as np

def determinant(A: list[list[float]]) -> float:
    matrix = np.array(A)
    return np.linalg.det(matrix)

def swap_rows(A: list[list[float]], k: int) -> bool:
    n = len(A)
    for i in range(k+1, n):
        if A[i][k] != 0.0:
            A[i], A[k] = A[k], A[i]
            return True
    return False

def solve_linear(A: list[list[float]], X: list[float]) -> int:
    n = len(A)
    ops_cnt = 0
    for k in range(n):
        if A[k][k] == 0.0:
            if not swap_rows(A, k):
                return 0
        for i in range(k+1, n):
            if A[i][k] == 0.0:
                continue
            factor = A[i][k]/A[k][k]
            for u in range(k, n):
                A[i][u] -= factor*A[k][u]
                ops_cnt += 2
    for i in range(n-1, -1, -1):
        s = A[i][n]
        for k in range(i+1, n):
            s -= X[k]*A[i][k]
        assert(A[i][i] != 0.0)
        X[i] = s/A[i][i]

    for i in range(n):
        s = 0
        for k in range(n):
            s += X[k]*A[i][k]
        assert(s == A[i][n])

def main():
    print("Number of rows:")
    n = int(input().strip())
    print("Coefficient Matrix")
    A = []
    for i in range(n):
        A.append(list(map(float, input().strip().split(" "))))
        assert(len(A[i]) == n)
    print("Solution Vector")
    B = list(map(float, input().strip().split(" ")))
    assert(len(B) == n)

    if determinant(A) == 0.0:
        print("No solution")
        return

    for i in range(n):
        A[i].append(B[i])
    X = [0.0] * n
    rank = solve_linear(A, X)

    if rank == 0.0:
        print("No solution")
        return
    print(X)

if __name__ == '__main__':
    main()