LU分解原理解释及C语言实现

        本文为笔者在编写spice时,需利用LU求解线性方程组时所写。

1、杜尔里特算法:

        从下至上对矩阵A做初等行变换,将对角线左下方的元素编成零,即得到U矩阵。然后可以证明这些行变换的效果等同于左乘一系列单位下三角矩阵,这一系列单位下三角矩阵的乘积的逆就是L矩阵,它也是一个单位下三角矩阵。即杜尔特里算法证实了矩阵A可以唯一分解成为L和U矩阵。

2、LU分解原理概要:

        将方程组TX=B的系数矩阵T分解为两个三角矩阵的乘积,以四阶为例进行讨论,即

                        T=LU=\begin{bmatrix}1& 0& 0& 0\\ l_2_1&1& 0& 0\\ l_3_1& l_3_2&1 &0\\ l_4_2 &l_4_2&l_4_3&1 \end{bmatrix}\begin{bmatrix} u_1_1 & u_1_2 &u_1_3&u_1_4 \\ 0& u_2_2& u_2_3& u_2_4\\0 &0 & u_3_3& u_3_4\\0 & 0& 0&u_4_4 \end{bmatrix}

     TX=B可以改写为

                                                                    LUX=B

    引入中间变量y,

                                                                       Ly=B

                                                                       UX=y

    先由一式求出y,再带入二式求出X即可。

3、LU各矩阵求解图解:

         A、此处展示了求解LU的过程

       B、求解y

      

        C、求解X

 

4、算法到代码的思路讲解

                

5、C语言代码

5.1 主函数中进行LU分解

此所求解的方程组为:

TX=B

T=[1 3 2 5

      1 1  1 1

       2  1  3  4

       1   1   2  1];

B=[33,10,29,13];

解出X=[1,2,3,4]

#include <stdio.h>  
#include <stdlib.h>  
  
int main()  
{  
  int n=4;  
  int i,j,k,i_u,j_u;  
  double T[4][4]={1,3,2,5,1,1,1,1,2,1,3,4,1,1,2,1};  
  double B[4]={33,10,29,13};  
  double X[n],L[n][n],U[n][n],y[n];  
  //1、将L,U矩阵全部赋值为0  
  for(i=0;i<=n-1;i++)  
  {  
      for(j=0;j<=n-1;j++)  
      {  
          L[i][j]=0;  
          U[i][j]=0;  
      }  
  }  
  //2、进行最初的赋值  
  for(i=0;i<=n-1;i++)  
  {  
      U[0][i]=T[0][i];  
      L[i][i]=1;  
  }  
  //3、进行规律性赋值  
  for(j=0;j<=n-2;j++)  
  {  
      for(i=j+1;i<=n-1;i++)  
      {  
          //学会西格玛求和的编程方式  
          L[i][j]=T[i][j];  
          for(k=0;k<=j-1;k++)  
          {  
              L[i][j]=L[i][j]-L[i][k]*U[k][j];  
          }  
          L[i][j]=L[i][j]/U[j][j];  
      }  
      for(i=j+1;i<=n-1;i++)  
      {  
        i_u=j+1;  
        j_u=i;  
        U[i_u][j_u]=T[i_u][j_u];  
        for(k=0;k<=i_u-1;k++)  
        {  
            U[i_u][j_u]=U[i_u][j_u]-L[i_u][k]*U[k][j_u];  
        }  
      }  
  }  
  //4、求y  
  for(i=0;i<=n-1;i++)  
  {  
      y[i]=B[i];  
      for(k=0;k<=i-1;k++)  
      {  
          y[i]=y[i]-L[i][k]*y[k];  
      }  
  }  
  //5、求X  
  for(i=n-1;i>=0;i--)  
  {  
      X[i]=y[i];  
      for(k=i+1;k<=n-1;k++)  
      {  
          X[i]=X[i]-U[i][k]*X[k];  
      }  
      X[i]=X[i]/U[i][i];  
  }  
  return 0;  
}  

代码效果展示:

5.2 编写LU_decompositon子函数,通过调用函数的形式进行LU分解

#include <stdio.h>
#include <stdlib.h>

int main()
{
  int n=4;
  int i,j,k,i_u,j_u;
  double T[4][4]={1,3,2,5,1,1,1,1,2,1,3,4,1,1,2,1};
  double B[4]={33,10,29,13};
  double X[n],L[n][n],U[n][n],y[n];
  void LU_decomposition(int n,double(*T)[n],double *X,double *B);
  LU_decomposition(n,T,X,B);//调用LU分解函数进行LU分解求解方程组
  return 0;
}

void LU_decomposition(int n,double(*T)[n],double *X,double *B)
{
/*************************************************************
 函数名称:LU_decomposition
 函数功能描述:对TX=B进行LU分解求解
 形参说明:n:T方阵的阶数;T:混合系数矩阵;X:未知数矩阵;B:RHS
 作者:Mr.Liu @SDU
 创造时间:2021-08-27 21:44
**************************************************************/
  int i,j,k,i_u,j_u;
  double L[n][n],U[n][n],y[n];
  //1、将L,U矩阵全部赋值为0
  for(i=0;i<=n-1;i++)
  {
      for(j=0;j<=n-1;j++)
      {
          L[i][j]=0;
          U[i][j]=0;
      }
  }
  //2、进行最初的赋值
  for(i=0;i<=n-1;i++)
  {
      U[0][i]=*(*(T+0)+i);
      L[i][i]=1;
  }
  //3、进行规律性赋值
  for(j=0;j<=n-2;j++)
  {
      for(i=j+1;i<=n-1;i++)
      {
          //学会西格玛求和的编程方式
          L[i][j]=*(*(T+i)+j);
          for(k=0;k<=j-1;k++)
          {
              L[i][j]=L[i][j]-L[i][k]*U[k][j];
          }
          L[i][j]=L[i][j]/U[j][j];
      }
      for(i=j+1;i<=n-1;i++)
      {
        i_u=j+1;
        j_u=i;
        U[i_u][j_u]=*(*(T+i_u)+j_u);
        for(k=0;k<=i_u-1;k++)
        {
            U[i_u][j_u]=U[i_u][j_u]-L[i_u][k]*U[k][j_u];
        }
      }
  }
  //4、求y
  for(i=0;i<=n-1;i++)
  {
      y[i]=*(B+i);
      for(k=0;k<=i-1;k++)
      {
          y[i]=y[i]-L[i][k]*y[k];
      }
  }
  //5、求X
  for(i=n-1;i>=0;i--)
  {
      *(X+i)=y[i];
      for(k=i+1;k<=n-1;k++)
      {
          *(X+i)=*(X+i)-U[i][k]*(*(X+k));
      }
      *(X+i)=*(X+i)/U[i][i];
  }
  return 0;
}

代码效果展示:

 

 

  • 13
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
LU分解是一种求解矩阵逆的方法之一,下面是一个使用C语言实现LU分解求矩阵逆的示例代码: ```c #include <stdio.h> #include <stdlib.h> #define N 3 void LUdecomposition(double A[N][N], double L[N][N], double U[N][N]) { int i, j, k; double sum; // 初始化U矩阵为A矩阵 for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { U[i][j] = A[i][j]; } } // 初始化L矩阵为单位矩阵 for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { if (i == j) { L[i][j] = 1.0; } else { L[i][j] = 0.0; } } } // LU分解 for (k = 0; k < N - 1; k++) { for (i = k + 1; i < N; i++) { L[i][k] = U[i][k] / U[k][k]; for (j = k; j < N; j++) { U[i][j] -= L[i][k] * U[k][j]; } } } } void inverse(double A[N][N], double A_inv[N][N]) { int i, j, k; double L[N][N], U[N][N], y[N][N], sum; // LU分解 LUdecomposition(A, L, U); // 求解Ly=I for (k = 0; k < N; k++) { for (i = 0; i < N; i++) { sum = 0.0; for (j = 0; j < i; j++) { sum += L[i][j] * y[j][k]; } if (i == k) { y[i][k] = 1.0 - sum; } else { y[i][k] = -sum; } } } // 求解Ux=y for (k = 0; k < N; k++) { for (i = N - 1; i >= 0; i--) { sum = 0.0; for (j = i + 1; j < N; j++) { sum += U[i][j] * A_inv[j][k]; } A_inv[i][k] = (y[i][k] - sum) / U[i][i]; } } } int main() { double A[N][N] = {{2.0, -1.0, 0.0}, {-1.0, 2.0, -1.0}, {0.0, -1.0, 2.0}}; double A_inv[N][N]; int i, j; inverse(A, A_inv); printf("A_inv:\n"); for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { printf("%.2f\t", A_inv[i][j]); } printf("\n"); } return 0; } ``` 该代码中,`LUdecomposition()`函数实现LU分解,`inverse()`函数实现了矩阵逆的求解,`main()`函数中给出了一个示例矩阵A,调用`inverse()`函数求解其逆矩阵并输出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值