LU分解求逆

文章转自:

https://www.cnblogs.com/bigmonkey/p/9555710.html

https://blog.csdn.net/xx_123_1_rj/article/details/39553809

什么是LU分解

在线性代数中, LU分解是矩阵分解的一种,可以将一个矩阵分解为一个单位下三角矩阵和一个上三角矩阵的乘积(有时是它们和一个置换矩阵的乘积)

如果有一个矩阵A,将A表示成下三角矩阵L和上三角矩阵U的乘积,称为A的LU分解。

 

  更进一步,我们希望下三角矩阵的对角元素都为1:

LU分解的步骤

  上一章讲到,对于满秩矩阵A来说,通过左乘一个消元矩阵,可以得到一个上三角矩阵U。

  可以看到,L实际上就是消元矩阵的逆。容易知道二阶矩阵的逆:

 

  现在假设A是一个3×3矩阵,在不考虑行交换的情况下,通过消元得到上三角矩阵的过程是:

 

 

LU 分解的前提

  并非所有矩阵都能进行LU分解,能够LU分解的矩阵需要满足以下三个条件:

  1. 矩阵是方阵(LU分解主要是针对方阵);
  2. 矩阵是可逆的,也就是该矩阵是满秩矩阵,每一行都是独立向量;
  3. 消元过程中没有0主元出现,也就是消元过程中不能出现行交换的初等变换

 示例

  

  如果A存在LU分解存,a,b满足什么条件?

  使用消元法逐一消去主元:

  由于E31 中出现了 –b/a,所以a ≠ 0

 

  b可以是任意常数。

 

具体的算法流程可以是:

 

1)进行LU分解;

2)对分解后的L阵(下三角矩阵)和U阵(上三角矩阵)进行求逆;

3)L阵的逆矩阵和U阵的逆矩阵相乘,即可求得原来矩阵的逆。即:

程序实现如下:

 

  1 #include<stdio.h>
  2 #include <string.h>
  3 #define N 4
  4 void main()
  5 { 
  6     float a[N][N];
  7     float L[N][N],U[N][N],out[N][N], out1[N][N];
  8     float r[N][N],u[N][N];
  9     memset( a , 0 , sizeof(a));  //初始化
 10     memset( L , 0 , sizeof(L));
 11     memset( U , 0 , sizeof(U));
 12     memset( r , 0 , sizeof(r));
 13     memset( u , 0 , sizeof(u));
 14     int n=N;
 15     int k,i,j;
 16     int flag=1;
 17     float s,t;
 18     ////////////////////input a matrix////
 19     printf("input A=\n");
 20     for(i=0;i<n;i++)
 21         for(j=0;j<n;j++)
 22             scanf("%f",&a[i][j]);
 23         //////////////////figure the input matrix//////////////////////////
 24         printf("输入矩阵:\n");
 25         for(i=0;i<n;i++)
 26         {
 27             for (j = 0; j < n; j++)
 28             {
 29                 printf("%lf ", a[i][j]);
 30             }
 31             printf("\n");
 32         }
 33         for(j=0;j<n;j++)
 34             a[0][j]=a[0][j];  //计算U矩阵的第一行
 35         
 36         for(i=1;i<n;i++)
 37             a[i][0]=a[i][0]/a[0][0];   //计算L矩阵的第1列
 38         for(k=1;k<n;k++)
 39         {
 40             for(j=k;j<n;j++)
 41             {
 42                 s=0;
 43                 for (i=0;i<k;i++)
 44                     s=s+a[k][i]*a[i][j];   //累加
 45                 a[k][j]=a[k][j]-s; //计算U矩阵的其他元素
 46             }
 47             for(i=k+1;i<n;i++)
 48             {
 49                 t=0;
 50                 for(j=0;j<k;j++)
 51                     t=t+a[i][j]*a[j][k];   //累加
 52                 a[i][k]=(a[i][k]-t)/a[k][k];    //计算L矩阵的其他元素
 53             }
 54         }
 55         for(i=0;i<n;i++)
 56             for(j=0;j<n;j++)
 57             { 
 58                 if(i>j)
 59                 { 
 60                     L[i][j]=a[i][j]; 
 61                     U[i][j]=0;
 62                 }//如果i>j,说明行大于列,计算矩阵的下三角部分,得出L的值,U的//为0
 63                 else
 64                 {
 65                     U[i][j]=a[i][j];
 66                     if(i==j) 
 67                         L[i][j]=1;  //否则如果i<j,说明行小于列,计算矩阵的上三角部分,得出U的//值,L的为0
 68                     else 
 69                         L[i][j]=0;
 70                 }
 71             }  
 72             if(U[1][1]*U[2][2]*U[3][3]*U[4][4]==0)
 73             {
 74                 flag=0;
 75                 printf("\n逆矩阵不存在");}
 76             if(flag==1)
 77             {
 78                 /////////////////////求L和U矩阵的逆
 79                 for (i=0;i<n;i++) /*求矩阵U的逆 */
 80                 {
 81                     u[i][i]=1/U[i][i];//对角元素的值,直接取倒数
 82                     for (k=i-1;k>=0;k--)
 83                     {
 84                         s=0;
 85                         for (j=k+1;j<=i;j++)
 86                             s=s+U[k][j]*u[j][i];
 87                         u[k][i]=-s/U[k][k];//迭代计算,按列倒序依次得到每一个值,
 88                     }
 89                 }
 90                 for (i=0;i<n;i++) //求矩阵L的逆 
 91                 {
 92                     r[i][i]=1; //对角元素的值,直接取倒数,这里为1
 93                     for (k=i+1;k<n;k++)
 94                     {
 95                         for (j=i;j<=k-1;j++)
 96                             r[k][i]=r[k][i]-L[k][j]*r[j][i];   //迭代计算,按列顺序依次得到每一个值
 97                     }
 98                 }
 99                 /////////////////绘制矩阵LU分解后的L和U矩阵///////////////////////
100                 printf("\nLU分解后L矩阵:");
101                 for(i=0;i<n;i++)
102                 { 
103                     printf("\n");
104                     for(j=0;j<n;j++)
105                         printf(" %lf",L[i][j]);
106                 }
107                 printf("\nLU分解后U矩阵:");
108                 for(i=0;i<n;i++)
109                 { 
110                     printf("\n");
111                     for(j=0;j<n;j++)
112                         printf(" %lf",U[i][j]);
113                 }
114                 printf("\n");
115                 ////////绘制L和U矩阵的逆矩阵
116                 printf("\nL矩阵的逆矩阵:");
117                 for(i=0;i<n;i++)
118                 { 
119                     printf("\n");
120                     for(j=0;j<n;j++)
121                         printf(" %lf",r[i][j]);
122                 }
123                 printf("\nU矩阵的逆矩阵:");
124                 for(i=0;i<n;i++)
125                 { 
126                     printf("\n");
127                     for(j=0;j<n;j++)
128                         printf(" %lf",u[i][j]);
129                 }
130                 printf("\n");
131                 //验证将L和U相乘,得到原矩阵
132                 printf("\nL矩阵和U矩阵乘积\n");
133                 for(i=0;i<n;i++)
134                 {
135                     for(j=0;j<n;j++)
136                     {
137                         out[i][j]=0;
138                     }
139                 }
140                 for(i=0;i<n;i++)
141                 {
142                     for(j=0;j<n;j++)
143                     {
144                         for(k=0;k<n;k++)
145                         {
146                             out[i][j]+=L[i][k]*U[k][j];
147                         }
148                     }  
149                 }
150                 for(i=0;i<n;i++)
151                 {
152                     for(j=0;j<n;j++)
153                     {
154                         printf("%lf\t",out[i][j]);
155                     }
156                     printf("\r\n");
157                 }
158                 //////////将r和u相乘,得到逆矩阵
159                 printf("\n原矩阵的逆矩阵:\n");
160                 for(i=0;i<n;i++)
161                 {
162                     for(j=0;j<n;j++)
163                     {out1[i][j]=0;}
164                 }
165                 for(i=0;i<n;i++)
166                 {
167                     for(j=0;j<n;j++)
168                     {
169                         for(k=0;k<n;k++)            
170                         {
171                             out1[i][j]+=u[i][k]*r[k][j];
172                         }
173                     }  
174                 }
175                 for(i=0;i<n;i++)
176                 {
177                     for(j=0;j<n;j++)
178                     {
179                         printf("%lf\t",out1[i][j]);
180                     }
181                     printf("\r\n");
182                 }
183             }
184  }

 

 

posted @ 2019-11-02 17:47  ywangji  阅读(11843)  评论(0编辑  收藏  举报