Solving Linear Systems with Iterative Methods#
Teng-Jui Lin
Content adapted from UW AMATH 301, Beginning Scientific Computing, in Spring 2020.
Solving linear systems with iteration methods
Jocabi method
Gauss-Seidel method
Convergence criteria of the methods
Finding eigenvalues by
np.linalg.eig()
ornp.linalg.eigvals()
Iteration methods are useful to solve for systems with large and sparse matrices.
Jacobi method#
Goal: solve for a linear system
We split the matrix
so that
for exact solutions. Adding subscripts for numerical iteration, we have
We can write this as
where
We calculate
Implementation#
Problem Statement. Use Jacobi method to solve the linear system
import numpy as np
def jacobi(A, b, x0, tolerance=1e-6, max_iter=50000):
'''
Solves linear system Ax=b using Jacobi iteration method
:param A: matrix of the system
:param b: column vector of the right hand side
:param x0: initial guess
:param tolerance: tolerance for stopping criteria
:param max_iter: maximum iterations allowed for calculation
:returns: final solution to Ax=b
'''
import numpy as np
import scipy
D = np.diag(np.diag(A))
T = A - D
M = -np.linalg.solve(D, T)
c = np.linalg.solve(D, b)
x_old = x0
i = 0 # iteration counter
change = tolerance * 2 # stopping criteria
# jacobi method logic
while change > tolerance and i < max_iter:
x_new = M@x_old + c
change = np.linalg.norm(x_new - x_old, np.inf)
x_old = x_new
i += 1
# maximum iteration warning
if i == max_iter:
import warnings
warnings.warn(f'Maximum iteration reached. Current stopping criteria is {change}', UserWarning)
return x_new
A = np.array([[7, 1, 1, 1], [0, 15, 2, 9], [3, 3, 20, 0], [1, -1, -2, -12]])
b = np.array([1, -3, 12, 2])
x0 = np.array([0, 0, 0, 0])
jacobi(A, b, x0)
array([ 0.11085635, -0.1322629 , 0.60321108, -0.24694186])
# compare with numpy solve
np.linalg.solve(A, b)
array([ 0.11085627, -0.132263 , 0.60321101, -0.2469419 ])
Gauss-Seidel method#
Goal: solve for a linear system
We split the matrix
so that
for exact solutions. Adding subscripts for numerical iteration, we have
We can write this as
where
We calculate
Implementation#
Problem Statement. Use Gauss-Seidel method to solve the linear system
def gauss_seidel(A, b, x0, tolerance=1e-6, max_iter=50000):
'''
Solves linear system Ax=b using Gauss-Seidel iteration method
:param A: matrix of the system
:param b: column vector of the right hand side
:param x0: initial guess
:param tolerance: tolerance for stopping criteria
:param max_iter: maximum iterations allowed for calculation
:returns: final solution to Ax=b
'''
import numpy as np
import scipy
S = np.tril(A)
T = A - S
M = -np.linalg.solve(S, T)
c = np.linalg.solve(S, b)
x_old = x0
i = 0 # iteration counter
change = tolerance * 2 # stopping criteria
# gauss seidel method logic
while change > tolerance and i < max_iter:
x_new = M@x_old + c
change = np.linalg.norm(x_new - x_old, np.inf)
x_old = x_new
i += 1
# maximum iteration warning
if i == max_iter:
import warnings
warnings.warn(f'Maximum iteration reached. Current stopping criteria is {change}', UserWarning)
return x_new
A = np.array([[7, 1, 1, 1], [0, 15, 2, 9], [3, 3, 20, 0], [1, -1, -2, -12]])
b = np.array([1, -3, 12, 2])
x0 = np.array([0, 0, 0, 0])
gauss_seidel(A, b, x0)
array([ 0.11085636, -0.13226307, 0.60321101, -0.24694188])
# compare with numpy solve
np.linalg.solve(A, b)
array([ 0.11085627, -0.132263 , 0.60321101, -0.2469419 ])
Convergence of iteration methods#
Strict diagonal dominance (SDD)#
A matrix is strictly diagonal dominant when the absolute value of its diagonal element in each row is greater than the sum of the absolute values of the off-diagonal elements.
SDD is a weak convergence criteria. If the matrix
Eigenvalues of iteration matrix #
In iteration methods, we have
but for exact solution, we have
Subtract thee equations, we get that the error is related to the iteration matrix:
In general, the iteration matrix
Convergence criteria:
If all the eigenvalues of
satisfy , the method convergesIf any of the eigenvalues of
satisfy , the method does not convergeIf the eigenvalues of
are closer to 0, the method will converge faster
Usually, the eigenvalues of the iteration matrix for the Gauss-Seidel method are smaller than the eigenvalues of the iteration matrix for the Jacobi method (but not always).
Implementation#
Problem Statement. Determine if Jacobi and Gauss-Seidel method will converge for solving the linear system
Compare their speed of convergence.
# convergence of jacobi method
A = np.array([[7, 1, 1, 1], [0, 15, 2, 9], [3, 3, 20, 0], [1, -1, -2, -12]])
D = np.diag(np.diag(A))
T = A - D
M = -np.linalg.solve(D, T)
lambdas = np.linalg.eigvals(M)
max_lambda = max(abs(lambdas))
max_lambda
0.3520564053849318
# convergence of gauss-seidel method
A = np.array([[7, 1, 1, 1], [0, 15, 2, 9], [3, 3, 20, 0], [1, -1, -2, -12]])
S = np.tril(A)
T = A - S
M = -np.linalg.solve(S, T)
lambdas = np.linalg.eigvals(M)
max_lambda = max(abs(lambdas))
max_lambda
0.10591293846976324
In this case, both iterative methods converge. Gauss-Seidel method has smaller maximum eigenvalue, so it converges faster than Jacobi method.