import numpy as np
import matplotlib.pyplot as plt
from sympy import Matrix, symbols, pprint
try:
import executable_engineering as exe
except ImportError:
%pip install -q executable_engineering
import executable_engineering as exeThe Intuition - solution by elimination.¶
Gaussian elimination is a formal algorithm for the most familiar and intuitive algebraic solution technique: substitution and elimination.
Let’s start with a classic problem:
You are organizing a fundraising event and need to buy chairs and tables. Chairs cost $20 each and tables cost $50 each. You have a budget of $700 and need a total of 20 pieces of furniture. How many chairs and tables should you buy?
Symbolic Manipulation¶
Let and be the number of chairs and tables respectively. We can define our two equations:
(1)
(2)
Solve (2) for :
Substitute into (1):
Substitute back into (2) to find . This works easily because our first step carries the unknown symbol .
The Numerical Approach¶
Computers don’t like carrying symbols. Let’s solve it numerically using only the coefficients.
(1)
(2)
Multiply (2) by 20:
Subtract from (1):
We eliminated from the second equation! It is now trivial to solve for , and then use back-substitution to find .
Transformation to Matrix Form¶
Notice how the linear system was fundamentally changed (without altering the final answer). In matrix form, we transformed it into:
The coefficient matrix is now upper triangular! This is the core goal of Gaussian Elimination.
Upper Triangular Matrices¶
An upper triangular matrix is a matrix whose elements below the main diagonal are exactly zero:
This is incredibly useful because the system can be solved from the bottom-up in time via back-substitution.
The Gaussian Elimination Algorithm¶
Gaussian Elimination transforms into .
We build an augmented matrix . To eliminate variables, we make a sequence of passes row-by-row, choosing a pivot row to eliminate elements in the equations below it.
We are allowed the following fundamental row operations:
| Operation | Effect on solution | Effect on |
|---|---|---|
| Exchange 2 rows | None | Flips sign |
| Multiply a row by scalar | None | Multiplied by |
| Subtract 2 rows | None | Unchanged |
(Note: While the solution remains identical, the determinant, norm, and condition number of the matrix are actively changing during elimination!)
Example: Guassian elimination¶
Let’s use the algorithm to solve:
In the following, note the definition of coefficients - they will be reference when we talk about LU decomposition.
Step 1: Get the augmented matrix
First Elimination Pass¶
Step 2: Eliminate from Row 2 Choose Row 1 as the pivot. Multiply Row 1 by and subtract it from Row 2:
Step 3: Eliminate from Row 3 Multiply Row 1 by and subtract it from Row 3:
Second Pass & Substitution¶
Step 4: Eliminate from Row 3 Now Row 2 is the pivot. Multiply Row 2 by and subtract it from Row 3: $$
$$
is now upper triangular!
Step 5: Back-substitution
Bottom row:
Middle row:
Top row:
Computational Complexity¶
If we analyze the two phases of standard Gaussian Elimination separately, we find:
Elimination Phase (Forward): Requires operations, meaning it scales as .
Back Substitution: Requires operations, meaning it scales as .
For massive systems (e.g., ), the elimination phase completely dominates the computational time.
Gauss-Jordan Elimination¶
An obvious extension is to conduct the elimination passes both downwards and upwards, normalizing the pivot rows to 1. This creates the reduced row echelon form (rref):
Since the coefficient matrix is now the Identity matrix , the answer is simply the right-hand vector!
Is Gauss-Jordan Faster? No.¶
Because Gauss-Jordan eliminates the need for back-substitution, one might think it is more efficient. Unfortunately, it is not:
The full up-and-down elimination phase requires operations.
Standard Gaussian Elimination requires operations.
Therefore, standard Gaussian Elimination is mathematically preferred for solving large systems.
Package Implementations¶
Because Gaussian Elimination has largely been surpassed by matrix decompositions (like LU decomposition), you will rarely use raw GE in numerical packages like numpy.
However, it is still incredibly useful for symbolic manipulation, and you will find it natively in sympy under rref():
# Define the coefficient matrix and the right-hand side vector
A = Matrix([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
b = Matrix([2, 5, -3])
# Combine into an augmented matrix
Ab = A.row_join(b)
# Calculate the reduced row echelon form (rref)
Ab_rref = Ab.rref()
print("Augmented matrix in rref:")
pprint(Ab_rref[0])
# Calculate the echelon form of the coefficient matrix
Ab_echelon = Ab.echelon_form()
print("\nCoefficient matrix in echelon form:")
pprint(Ab_echelon)