线性方程组数值解法及R语言实现

文章目录

  • LU分解
  • Gauss-Seidel迭代
  • Jacobi迭代

LU分解

对矩阵进行LU分解,可将其分解为一个上三角矩阵和下三角矩阵,这样对于求解线性方程组时可简化许多计算量。
线性方程组数值解法及R语言实现_第1张图片
最终可得 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=LU
Ly=b
Ux=y
下面是R语言实现
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)

Gauss-Seidel迭代

设线性方程组为Ax=b,将A拆分为一个对角阵,下三角矩阵L和上三角矩阵U,即A=D-L-U
线性方程组数值解法及R语言实现_第2张图片
则方程变为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)=(DL)1Ux(k)+(DL)1b
若记 B = ( D − L ) − 1 U , f = ( D − L ) − 1 b B=(D-L)^{-1}U,f=(D-L)^{-1}b B=(DL)1U,f=(DL)1b,则原式即 x ( k + 1 ) = B x ( k ) + f x^{(k+1)}=Bx^{(k)}+f x(k+1)=Bx(k)+f
可以看到要对矩阵(D-L)求逆,因此由此可以得到Gauss-Seidel迭代的收敛条件:

  1. A不可逆
  2. 矩阵B的谱半径小于1,即B矩阵最大特征值小于1

下面是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)

Jacobi迭代

设线性方程组为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)=D1Nx+D1b
M = D − 1 N , f = D − 1 b M=D^{-1}N,f=D^{-1}b M=D1N,f=D1b,则原式即 x ( k + 1 ) = M x ( k ) + f x^{(k+1)}=Mx^{(k)}+f x(k+1)=Mx(k)+f
由此可写出收敛条件:

  1. A不可逆
  2. M谱半径小于1,即M的最大特征值小于1
    下面是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

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)

你可能感兴趣的:(多元统计)