对矩阵进行LU分解,可将其分解为一个上三角矩阵和下三角矩阵,这样对于求解线性方程组时可简化许多计算量。
最终可得 A = L U A=LU A=LU,其中L是一个下三角矩阵,U是一个上三角矩阵。
此时求解线性方程组 A x = b Ax=b Ax=b变为求解 L U x = b LUx=b LUx=b,若记 U x = y Ux=y Ux=y,则原式即求解 L y = b Ly=b Ly=b,而由于L是下三角矩阵,因此可以轻松地求出y,此时再求解 U x = y Ux=y Ux=y,而由于U是一个上三角矩阵,因此可轻松地求出x。因此步骤如下:
A <- matrix(c(4,2,3,5,-8,1,4,7,-9),nrow=3,byrow=T)
b <- matrix(c(1,4,0))
lusolution <- function(A,b){
##LU decompose
##Doolittle
t1 = Sys.time()
U = A
n = ncol(A)
L = diag(n)
for(k in 1:(n-1)){
for(j in (k+1):n){
L[j,k] = U[j,k]/U[k,k]
U[j,k:n] = U[j,k:n] - L[j,k]*U[k,k:n]
}
}
##solute Ly = b
y = matrix(rep(0,n))
y[1] = L[1,1]
for(i in 2:n){
s = b[i]
for(j in 1:(i-1)){
s = s - L[i,j]*y[j]
}
y[i] = s/L[i,i]
}
##solute UX = y
x = matrix(rep(0,n))
x[n] = U[n,n]
for(i in (n-1):1){
s = y[i]
for(j in i:(n-1)){
s = s - U[i,j]*x[j]
}
x[i] = s/U[i,i]
}
print(Sys.time()-t1)
return(x)
}
lusolution(A,b)
设线性方程组为Ax=b,将A拆分为一个对角阵,下三角矩阵L和上三角矩阵U,即A=D-L-U
则方程变为Lx = b-Ux,由此建立迭代公式
x ( k + 1 ) = ( D − L ) − 1 U x ( k ) + ( D − L ) − 1 b x^{(k+1)}=(D-L)^{-1}Ux^{(k)}+(D-L)^{-1}b x(k+1)=(D−L)−1Ux(k)+(D−L)−1b
若记 B = ( D − L ) − 1 U , f = ( D − L ) − 1 b B=(D-L)^{-1}U,f=(D-L)^{-1}b B=(D−L)−1U,f=(D−L)−1b,则原式即 x ( k + 1 ) = B x ( k ) + f x^{(k+1)}=Bx^{(k)}+f x(k+1)=Bx(k)+f
可以看到要对矩阵(D-L)求逆,因此由此可以得到Gauss-Seidel迭代的收敛条件:
下面是R语言实现
A1 = matrix(c(3,1,1,0,1,5,-1,2,1,0,3,1,0,1,1,4),nrow=4,byrow=T)
A2 = matrix(c(2.5,1,1,0,1,4.1,-1,2,1,0,2.1,1,0,1,1,2.1),nrow=4,byrow=T)
A3 = matrix(c(2,1,1,0,1,3.5,-1,2,1,0,2.1,1,0,1,1,2.1),nrow=4,byrow=T)
b1 = matrix(c(1,4,-2,1))
b2 = b1;b3 = b1
gauss.seidel <- function(A,b,x,iter=200,tol=1e-8){
if(det(A)==0){
return(c('A can not inverse!'))
}
m = nrow(A)
n = ncol(A)
D = diag(n)
L = matrix(0,nrow=m,ncol=n)
for(i in 1:n){
D[i,i] = A[i,i]
}
for(i in 2:n){
for(j in 1:(i-1)){
L[i,j] = -A[i,j]
}
}
U = D-L-A
B = solve(D-L)%*%U
f = solve(D-L)%*%b
rho <- max(eigen(B)$values)
if(rho>=1){
return(c('Warning:it will not converge!'))
}
outstats = as.data.frame(matrix(rep(0,(2+n)*iter),nrow=iter))
x <- t(as.matrix(outstats[1,3:(n+2)]))
for(i in 1:iter){
x0 = B%*%x + f
outstats[i,] <- matrix(c(i,norm(x-x0)/norm(x0),t(x0)),nrow=1)
if(norm(x-x0) < tol*norm(x0)){
result <- list('x'=x0,'outstats'=outstats[1:i,],'iter'=i,'rho'=rho)
return(result)
break
}
x <- x0
}
result <- list('x'=x,'outstats'=outstats,'iter'=i,'rho'=rho)
return(result)
}
x <- c(0,0,0,0)
Y1 = gauss.seidel(A1,b1,x)
print(Y1)
Y2 = gauss.seidel(A2,b2,x)
print(Y2)
gauss.seidel(A3,b3,x)
设线性方程组为Ax=b,将A矩阵拆分为对角元素与其余元素的差,即A=D-N
则可写出迭代式
x ( k + 1 ) = D − 1 N x + D − 1 b x^{(k+1)}=D^{-1}Nx+D^{-1}b x(k+1)=D−1Nx+D−1b
记 M = D − 1 N , f = D − 1 b M=D^{-1}N,f=D^{-1}b M=D−1N,f=D−1b,则原式即 x ( k + 1 ) = M x ( k ) + f x^{(k+1)}=Mx^{(k)}+f x(k+1)=Mx(k)+f
由此可写出收敛条件:
A1 = matrix(c(3,1,1,0,1,5,-1,2,1,0,3,1,0,1,1,4),nrow=4,byrow=T)
A2 = matrix(c(2.5,1,1,0,1,4.1,-1,2,1,0,2.1,1,0,1,1,2.1),nrow=4,byrow=T)
A3 = matrix(c(2,1,1,0,1,3.5,-1,2,1,0,2.1,1,0,1,1,2.1),nrow=4,byrow=T)
b1 = matrix(c(1,4,-2,1))
b2 = b1;b3 = b1
jacobi.iter <- function(A,b,iter=1000){
if(det(A)==0){
return(c('A can not inverse!'))
}
m = nrow(A)
n = ncol(A)
D = diag(n)
for(i in 1:n){
D[i,i] = A[i,i]
}
N = D-A
x = matrix(rep(0,n))
M = solve(D)%*%N
f = solve(D)%*%b
#谱半径>1则发散
if(max(eigen(M)$values)>=1){
return(c('Warning:it will not converge!'))
}
for(i in 1:iter){
x0 = M%*%x + f
if(sum(abs(x0-x))<.00001){
return(x0)
}
x = x0
}
return(x)
}
x1 = jacobi.iter(A1,b3)
A1%*%x1
x2 = jacobi.iter(A2,b2)
A2%*%x2
jacobi.iter(A3,b3)