文内程序旨在实现求逆运算核心思想。n方程组是怎么求解的也。xn称为方程组的败。

矩阵求逆运算有多算法:

数学是电脑技术之底蕴,线性代数是机器上与深上之基础,了解多少知识最好的措施本身以为是亮概念,数学不单单是读时用来考查的,也是干活受到必要的基础知识,实际上有为数不少好玩之数学类在学堂里套不交,有许多拓展类的数据能叫咱发散思维,但控制最核心的数学知识是前提,本文就因线性代数的各种词条来开一下预热,不明了的记百度转眼。

本节咱们讨论哪边用LUP分解法求解线性方程组,对于富含n个未知变量x1,x2,x3,…,xn的线性方程组:

  1. 随同矩阵的想想,分别算有该伴随矩阵和行列式,再算有逆矩阵;
  2. LU分解法(若选主元即为LUP分解法: Ax = b ==> PAx = Pb ==>LUx = Pb ==> Ly = Pb ==> Ux = y
    ,每步重新选择主元),它有少栽不同之兑现;

    • A-1=(LU)-1=U-1L-1,将A分解为LU后,对L和U分别求逆,再相乘;
    • 由此解线程方程组Ax=b的计求逆矩阵。b分别获得单位阵的各个列向量,所获的解向量x就是逆矩阵的逐条列向量,拼成逆矩阵即可。

矩阵与方程组

710官方网站 1

脚是这半种植艺术的c++代码实现,所有代码都采用常规数量集验证过。

还记得n*n方程组是怎么求解的为?这个术语叫“回代法”,即改成三角形方程组再相继代入求解

以满足方程组中持有方程的一个数值集:x1,x2,…,xn称为方程组的消除。

文内程序旨在实现求逆运算核心思想,某些老检测的功效就未兑现(如矩阵维数检测、矩阵奇异等)。

直白未懂得“代数”这个“代”是什么意思,现在竟知道了,代,英文是substitution,含义是代,从初中及现行直以为“代数”就是“代入”

以方程组改写成矩阵向量等式:

小心:文中A阵均为方阵。

系数矩阵,英文称coefficient
matrix,怪不得读开源代码里面经常碰到变量名叫做coe,原来是自这来之

710官方网站 2

陪伴矩阵法C++程序:

“导数”、“可导”还记吗?不知道“导”是啊意思的起麻痹有?英文derivative(含义是派生的、衍生的),看起不是疏导的意,而是音译过来的

记为:

  1 #include <iostream>
  2 #include <ctime>    //用于产生随机数据的种子
  3 
  4 #define N 3    //测试矩阵维数定义
  5 
  6 //按第一行展开计算|A|
  7 double getA(double arcs[N][N],int n)
  8 {
  9     if(n==1)
 10     {
 11         return arcs[0][0];
 12     }
 13     double ans = 0;
 14     double temp[N][N]={0.0};
 15     int i,j,k;
 16     for(i=0;i<n;i++)
 17     {
 18         for(j=0;j<n-1;j++)
 19         {
 20             for(k=0;k<n-1;k++)
 21             {
 22                 temp[j][k] = arcs[j+1][(k>=i)?k+1:k];
 23                 
 24             }
 25         }
 26         double t = getA(temp,n-1);
 27         if(i%2==0)
 28         {
 29             ans += arcs[0][i]*t;
 30         }
 31         else
 32         {
 33             ans -=  arcs[0][i]*t;
 34         }
 35     }
 36     return ans;
 37 }
 38 
 39 //计算每一行每一列的每个元素所对应的余子式,组成A*
 40 void  getAStart(double arcs[N][N],int n,double ans[N][N])
 41 {
 42     if(n==1)
 43     {
 44         ans[0][0] = 1;
 45         return;
 46     }
 47     int i,j,k,t;
 48     double temp[N][N];
 49     for(i=0;i<n;i++)
 50     {
 51         for(j=0;j<n;j++)
 52         {
 53             for(k=0;k<n-1;k++)
 54             {
 55                 for(t=0;t<n-1;t++)
 56                 {
 57                     temp[k][t] = arcs[k>=i?k+1:k][t>=j?t+1:t];
 58                 }
 59             }
 60             
 61             
 62             ans[j][i]  =  getA(temp,n-1);  //此处顺便进行了转置
 63             if((i+j)%2 == 1)
 64             {
 65                 ans[j][i] = - ans[j][i];
 66             }
 67         }
 68     }
 69 }
 70 
 71 //得到给定矩阵src的逆矩阵保存到des中。
 72 bool GetMatrixInverse(double src[N][N],int n,double des[N][N])
 73 {
 74     double flag=getA(src,n);
 75     double t[N][N];
 76     if(0==flag)
 77     {
 78         cout<< "原矩阵行列式为0,无法求逆。请重新运行" <<endl;
 79         return false;//如果算出矩阵的行列式为0,则不往下进行
 80     }
 81     else
 82     {
 83         getAStart(src,n,t);
 84         for(int i=0;i<n;i++)
 85         {
 86             for(int j=0;j<n;j++)
 87             {
 88                 des[i][j]=t[i][j]/flag;
 89             }
 90             
 91         }
 92     }
 93     
 94     return true;
 95 }
 96 
 97 int main()
 98 {
 99     bool flag;//标志位,如果行列式为0,则结束程序
100     int row =N;
101     int col=N;
102     double matrix_before[N][N]{};//{1,2,3,4,5,6,7,8,9};
103     
104     //随机数据,可替换
105     srand((unsigned)time(0));
106     for(int i=0; i<N ;i++)
107     {
108         for(int j=0; j<N;j++)
109         {
110             matrix_before[i][j]=rand()%100 *0.01;
111         }
112     }
113     
114     cout<<"原矩阵:"<<endl;
115     
116     for(int i=0; i<N ;i++)
117     {
118         for(int j=0; j<N;j++)
119         {
120             //cout << matrix_before[i][j] <<" ";
121             cout << *(*(matrix_before+i)+j)<<" ";
122         }
123         cout<<endl;
124     }
125     
126     
127     double matrix_after[N][N]{};
128     flag=GetMatrixInverse(matrix_before,N,matrix_after);
129     if(false==flag)
130         return 0;
131     
132     
133     cout<<"逆矩阵:"<<endl;
134     
135     for(int i=0; i<row ;i++)
136     {
137         for(int j=0; j<col;j++)
138         {
139             cout <<matrix_after[i][j] <<" ";
140             //cout << *(*(matrix_after+i)+j)<<" ";
141         }
142         cout<<endl;
143     }
144     
145     GetMatrixInverse(matrix_after,N,matrix_before);
146     
147     cout<<"反算的原矩阵:"<<endl;//为了验证程序的精度
148     
149     for(int i=0; i<N ;i++)
150     {
151         for(int j=0; j<N;j++)
152         {
153             //cout << matrix_before[i][j] <<" ";
154             cout << *(*(matrix_before+i)+j)<<" ";
155         }
156         cout<<endl;
157     }
158     
159     
160     return 0;
161 }

矩阵就是矩形的数字阵列,这重简单不了了

Ax=b

 

n*n的矩阵叫方阵,傻子都清楚了

假定A为非奇异矩阵,那么A存在逆矩阵,亦即方程组有解。

LU分解法C++程序:

系数矩阵加同列右端起的矩阵叫增广矩阵,英文叫做augmented
matrix,记作:(A|B),科学家等凭想个东西从个名字即为我们收获在书本啃,我管A后面放少个B,叫做“增广矩阵二”行呢

LUP分解的思是寻觅来三只n*n的矩阵,L、U和P,满足

  1 #include <iostream>
  2 #include <cmath>
  3 #include <ctime>
  4 
  5 #define N 300
  6 
  7 //矩阵乘法
  8 double * mul(double A[N*N],double B[N*N])
  9 {
 10     double *C=new double[N*N]{};
 11     for(int i=0;i<N;i++)
 12     {
 13         for(int j=0;j<N;j++)
 14         {
 15             for(int k=0;k<N;k++)
 16             {
 17                 C[i*N+j] += A[i*N+k]*B[k*N+j];
 18             }
 19         }
 20     }
 21 
 22     //若绝对值小于10^-10,则置为0(这是我自己定的)
 23     for(int i=0;i<N*N;i++)
 24     {
 25         if(abs(C[i])<pow(10,-10))
 26         {
 27             C[i]=0;
 28         }
 29     }
 30 
 31     return C;
 32 }
 33 
 34 //LUP分解
 35 void LUP_Descomposition(double A[N*N],double L[N*N],double U[N*N],int P[N])
 36 {
 37     int row=0;
 38     for(int i=0;i<N;i++)
 39     {
 40         P[i]=i;
 41     }
 42     for(int i=0;i<N-1;i++)
 43     {
 44         double p=0.0d;
 45         for(int j=i;j<N;j++)
 46         {
 47             if(abs(A[j*N+i])>p)
 48             {
 49                 p=abs(A[j*N+i]);
 50                 row=j;
 51             }
 52         }
 53         if(0==p)
 54         {
 55             cout<< "矩阵奇异,无法计算逆" <<endl;
 56             return ;
 57         }
 58 
 59         //交换P[i]和P[row]
 60         int tmp=P[i];
 61         P[i]=P[row];
 62         P[row]=tmp;
 63 
 64         double tmp2=0.0d;
 65         for(int j=0;j<N;j++)
 66         {
 67             //交换A[i][j]和 A[row][j]
 68             tmp2=A[i*N+j];
 69             A[i*N+j]=A[row*N+j];
 70             A[row*N+j]=tmp2;
 71         }
 72 
 73         //以下同LU分解
 74         double u=A[i*N+i],l=0.0d;
 75         for(int j=i+1;j<N;j++)
 76         {
 77             l=A[j*N+i]/u;
 78             A[j*N+i]=l;
 79             for(int k=i+1;k<N;k++)
 80             {
 81                 A[j*N+k]=A[j*N+k]-A[i*N+k]*l;
 82             }
 83         }
 84 
 85     }
 86 
 87     //构造L和U
 88     for(int i=0;i<N;i++)
 89     {
 90         for(int j=0;j<=i;j++)
 91         {
 92             if(i!=j)
 93             {
 94                 L[i*N+j]=A[i*N+j];
 95             }
 96             else
 97             {
 98                 L[i*N+j]=1;
 99             }
100         }
101         for(int k=i;k<N;k++)
102         {
103             U[i*N+k]=A[i*N+k];
104         }
105     }
106 
107 }
108 
109 //LUP求解方程
110 double * LUP_Solve(double L[N*N],double U[N*N],int P[N],double b[N])
111 {
112     double *x=new double[N]();
113     double *y=new double[N]();
114 
115     //正向替换
116     for(int i = 0;i < N;i++)
117     {
118         y[i] = b[P[i]];
119         for(int j = 0;j < i;j++)
120         {
121             y[i] = y[i] - L[i*N+j]*y[j];
122         }
123     }
124     //反向替换
125     for(int i = N-1;i >= 0; i--)
126     {
127         x[i]=y[i];
128         for(int j = N-1;j > i;j--)
129         {
130             x[i] = x[i] - U[i*N+j]*x[j];
131         }
132         x[i] /= U[i*N+i];
133     }
134     return x;
135 }
136 
137 /*****************矩阵原地转置BEGIN********************/
138 
139 /* 后继 */
140 int getNext(int i, int m, int n)
141 {
142   return (i%n)*m + i/n;
143 }
144 
145 /* 前驱 */
146 int getPre(int i, int m, int n)
147 {
148   return (i%m)*n + i/m;
149 }
150 
151 /* 处理以下标i为起点的环 */
152 void movedata(double *mtx, int i, int m, int n)
153 {
154   double temp = mtx[i]; // 暂存
155   int cur = i;    // 当前下标
156   int pre = getPre(cur, m, n);
157   while(pre != i)
158   {
159     mtx[cur] = mtx[pre];
160     cur = pre;
161     pre = getPre(cur, m, n);
162   }
163   mtx[cur] = temp;
164 }
165 
166 /* 转置,即循环处理所有环 */
167 void transpose(double *mtx, int m, int n)
168 {
169   for(int i=0; i<m*n; ++i)
170   {
171     int next = getNext(i, m, n);
172     while(next > i) // 若存在后继小于i说明重复,就不进行下去了(只有不重复时进入while循环)
173       next = getNext(next, m, n);
174     if(next == i)  // 处理当前环
175       movedata(mtx, i, m, n);
176   }
177 }
178 /*****************矩阵原地转置END********************/
179 
180 //LUP求逆(将每列b求出的各列x进行组装)
181 double * LUP_solve_inverse(double A[N*N])
182 {
183     //创建矩阵A的副本,注意不能直接用A计算,因为LUP分解算法已将其改变
184     double *A_mirror = new double[N*N]();
185     double *inv_A=new double[N*N]();//最终的逆矩阵(还需要转置)
186     double *inv_A_each=new double[N]();//矩阵逆的各列
187     //double *B    =new double[N*N]();
188     double *b    =new double[N]();//b阵为B阵的列矩阵分量
189 
190     for(int i=0;i<N;i++)
191     {
192         double *L=new double[N*N]();
193         double *U=new double[N*N]();
194         int *P=new int[N]();
195 
196         //构造单位阵的每一列
197         for(int i=0;i<N;i++)
198         {
199             b[i]=0;
200         }
201         b[i]=1;
202 
203         //每次都需要重新将A复制一份
204         for(int i=0;i<N*N;i++)
205         {
206             A_mirror[i]=A[i];
207         }
208 
209         LUP_Descomposition(A_mirror,L,U,P);
210 
211         inv_A_each=LUP_Solve (L,U,P,b);
212         memcpy(inv_A+i*N,inv_A_each,N*sizeof(double));//将各列拼接起来
213     }
214     transpose(inv_A,N,N);//由于现在根据每列b算出的x按行存储,因此需转置
215 
216     return inv_A;
217 }
218 
219 int main()
220 {
221     double *A = new double[N*N]();
222 
223     srand((unsigned)time(0));
224     for(int i=0; i<N ;i++)
225     {
226         for(int j=0; j<N;j++)
227         {
228             A[i*N+j]=rand()%100 *0.01;
229         }
230     }
231 
232 
233     double *E_test = new double[N*N]();
234     double *invOfA = new double[N*N]();
235     invOfA=LUP_solve_inverse(A);
236 
237     E_test=mul(A,invOfA);    //验证精确度
238 
239     cout<< "矩阵A:" <<endl;
240     for(int i=0;i<N;i++)
241     {
242         for(int j=0;j<N;j++)
243         {
244             cout<< A[i*N+j]<< " " ;
245         }
246         cout<<endl;
247     }
248 
249     cout<< "inv_A:" <<endl;
250     for(int i=0;i<N;i++)
251     {
252         for(int j=0;j<N;j++)
253         {
254             cout<< invOfA[i*N+j]<< " " ;
255         }
256         cout<<endl;
257     }
258 
259     cout<< "E_test:" <<endl;    
260     for(int i=0;i<N;i++)
261     {
262         for(int j=0;j<N;j++)
263         {
264             cout<< E_test[i*N+j]<< " " ;
265         }
266         cout<<endl;
267     }
268 
269     return 0;
270 }

行阶梯型矩阵,这回有硌难度了,它便是这么的:非零一行于同实行少,第一独因素是1,数字靠右

PA=LU

 

高斯消元法:把增广矩阵化为行阶梯型矩阵

里面,L是一个单位下三角矩阵,U是一个齐三角矩阵,P是一个交换矩阵。则称满足上述等式的L、U和P为矩阵A的LUP分解

 

超定方程组:方程个数较未知量个数多

等式Ax=b两限与乘以P,变形也PAx=Pb,亦即:

些微种方式运行时测试样例(运行环境不同或许会见出不同结果,我之主频是2.6GHz,内存8g。时间单位:毫秒ms)

实行最简形:行阶梯形,每行第一单非零元是该列唯一的非零元

LUx=Pb

710官方网站 3

高斯-若尔当消元法:将矩阵化为无限简形的计

设y=Ux,其中x就是咱们渴求的为量解。我们率先通过正于替换求解下三角系统:

私认为LU分解法的个别只1ms其实凡不准确之(实际应多低于1ms,有趣味可以试试看)。

齐次方程组(homogeneous):右端项都否零星。齐次方程组总是有解的

Ly=Pb

老三种植艺术的复杂度分析:

平凡解,就是零解(0,0,0,…..0),能不能够生成这么平庸的叫….

博未知变量y。然后,通过正朝着替换求解上三角系统:

  1. 随同矩阵法:此法的时空复杂度主要来源于计算行列式,由于计算行列式的函数为递归形式,其复杂度为O(n2)[参见这里],而整机算法需要计算每个元素的代数余子式,时间复杂度直接扩大n2倍,变为O(n4)。而递归算法本身是用占用栈空间的,因此待注意:当矩阵的维数较充分时,随着递归深度的加大,临时占的空间将会晤愈加多,甚至可能会见出现栈不足够用之景况(当然本次实现无赶上,因为这的时间支付实在让人难以忍受)!
  2. LU分解法:此法主要是说明过程耗时,求解三角矩阵的光阴复杂度是O(n2),分解过程是O(n3),总体来说和高斯消元法差不多,但是避免了高斯消元法的主元素为0的经过。
    为了省空间,A=LU分解的素存放在A的矩阵中(因为当用过了a[i][j]要素后,便不再用了,所以可以占据原矩阵A的长空)。但是福利就产生弊端,考虑而是上千独元素的矩阵,引用传参,这样虽变更原来矩阵了,因此次中使用A_mintor作为副本进行应用。另外,可以看到,当矩阵维数超过某值时,内存空间便不敷用了(具体是聊并未考)。还索要小心的某些是:程序中不对矩阵是否奇异进行检查,如果矩阵奇异,就无应允重展开下去了。
  3. LU分解法被,还可优先分别求出U和L的迎接,再相乘,此法其实和常规LU分解法差不多。

非平凡解:零解以外的排除

Ux=y

其他:

x上面加水平箭头表示水平数组(行向量),不加则表示列向量,不一致的书写里记法不顶相同,姑且这么记吧

得到未知变量x。

文章被因故到了矩阵的原地转置算法,具体要参考第4篇文献,这种艺术降低了上空复杂度。

对如矩阵的特性:转置等于他自己

鉴于置换矩阵P是可逆的,等式PA=LU两止与乘以P-1,得:

 

若A=(1),则An=(2n-1)

A=P-1LU

=P-1Ly

=P-1Pb

=b

内需专注的问题:

假使AB=BA=I,则称A是可逆的,或A是非奇异的(nonsingular),B叫做A的逆元,记作A-1

于是x就是Ax=b的解。

正文介绍的方法new了一部分指针,未释放,会油然而生内存泄漏,使用前要释放掉。

矩阵没有乘法逆元,那么叫做奇异的(singlular)

调用方法:

 

(AB)-1=B-1A-1

    linear::CLinearEqualtion l(3);
    l.init_A("A.txt");
    l.init_b("b.txt");
    l.lu_decomposition();
    l.lup_solve();
    l.show_y();
    l.show_x();
    l.save_solution();

正文参考了以下几首文章:

(AB)T=BTAT

C++实现:

  • http://www.cnblogs.com/tianya2543/p/3999118.html 
  • http://blog.csdn.net/cumtwyc/article/details/49980063 
  • http://blog.csdn.net/xx_123_1_rj/article/details/39553809
  • http://www.jb51.net/article/53715.htm

希冀的邻接矩阵(相连为1否则为0)是对如之

#include <iostream>
#include <vector>
#include <cassert>
#include <fstream>

using namespace std;

namespace linear
{
#define array_1(__type) std::vector<__type>
#define array_2(__type) std::vector<array_1(__type)>

    class CLinearEqualtion
    {
        /*
        使用方法:
        1. 定义计算方程组的类对象,并初始化其系数矩阵的大小
        linear::CLinearEqualtion l(3);

        2. 读取系数阵 A
        l.init_A("A.txt");

        3. 读取 b
        l.init_b("b.txt");

        4. 对系数矩阵进行lu分解
        l.lu_decomposition();

        5. 求解方程组
        l.lup_solve();

        6. 显示反向替换的解
        l.show_y();

        7. 显示正向替换的解
        l.show_x();

        8. 保存方程的解
        l.save_solution();

        A.txt
        1    5    4
        2    0    3
        5    8    2

        b.txt
        12
        9
        5

        x[0] = -0.157895
        x[1] = -0.0526316
        x[2] = 3.10526
        */
    private:
        array_2(double) A;
        array_2(double) L;
        array_2(double) U;

        array_1(double) b;
        array_1(int) p;

        array_1(double) x;
        array_1(double) y;

    public:
        CLinearEqualtion(int n)
        {
            assert(n>1);

            A = array_2(double)(n);
            L = array_2(double)(n);
            U = array_2(double)(n);
            for (int i= 0; i < n;i++)
            {
                A[i] = array_1(double)(n);
                L[i] = array_1(double)(n);
                U[i] = array_1(double)(n);
            }
            b = array_1(double)(n);
            x = array_1(double)(n);
            y = array_1(double)(n);
            p = array_1(int)(n);
        } // !CLinearEqualtion(int n)
        virtual ~CLinearEqualtion(){} // !virtual ~CLinearEqualtion()

    public:
        void init_A(array_2(double) _A)
        {
            for (int i = 0; i < _A.size(); i++)
                A[i].assign(_A[i].begin(), _A[i].end());
        } // !void init_A(array_2(double) _A)

        void init_A(std::string _fileName)
        {
            std::ifstream in(_fileName.c_str());
            int i = 0;
            int j = 0;
            while(!in.eof())
            {
                double e = 0;
                in>>e;
                std::cout<<e<<std::endl;
                A[i][j] = e;
                if (j==A.size() - 1)
                {
                    i++;
                    j = 0;
                }
                else
                {
                    j++;
                }
            }
        } // !void init_A(std::string _fileName)

        void init_b(std::string _fileName)
        {
            std::ifstream in(_fileName.c_str());
            int i = 0;
            while(!in.eof())
            {
                double e = 0;
                in>>e;
                std::cout<<e<<std::endl;
                b[i++] = e;
            }
        } // !void init_b(std::string _fileName)

        void lu_decomposition()
        {
            int n = A.size(); // get array size
            for (int i = 0; i < n; i++)
                p[i] = i;
            for (int k = 0; k < n; k++)
            {
                int max = 0;
                int k_ = k;
                // get max e in col k.
                for (int i = k; i < n; i++)
                {
                    if (fabs(A[i][k]) > max)
                    {
                        max = fabs(A[i][k]);
                        k_ = i;
                    }
                }
                // make sure not all is zero.
                if (max == 0)
                    assert("singular matrix");

                // swap cur row,max row.
                if (k != k_)
                {
                    swap(p[k], p[k_]);
                    for (int i = 0; i < n; i++)
                        swap(A[k][i], A[k_][i]);                    
                }

                for (int i = k + 1; i < n; i++)
                {
                    // gen v
                    A[i][k] /= A[k][k];
                    for (int j = k + 1; j < n; j++)
                    {
                        A[i][j] -= A[i][k] * A[k][j];
                    }
                }
            }

            init_LU();
        } // !void lu_decomposition()

        void init_LU()
        {
            int n = A.size(); // get array size

            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    if (i > j)
                    {
                        L[i][j] = A[i][j];
                    } 
                    else
                    {
                        U[i][j] = A[i][j];
                        if (i == j)
                            L[i][i] = 1;
                    }
                }
            }

        } // !void init_LU()

        void lup_solve()
        {
            int n = A.size();
            int i = 0, j = 0;
            for (i = 0; i < n; i++)
            {
                x[i] = 0;
                y[i] = 0;
            }

            for (i = 0; i < n; i++)
            {
                y[i] = b[p[i]];
                for (j = 0; j < i; j++)
                    y[i] -= L[i][j] * y[j];
            }
            for (i = n - 1; i >= 0; i--)
            {
                double delt = y[i];
                for (j = n - 1; j > i; j--)
                    delt -= U[i][j] * x[j];
                x[i] = delt / U[i][j];
            }
        } // !void lup_solve()

        void show_y()
        {
            int n = A.size();
            std::cout << "###" << std::endl;
            for (int i = 0; i < n; i++)
            {
                std::cout << "y[" << i << "]=" << y[i] << std::endl;
            }
        } // !void show_y()

        void show_x()
        {
            int n = A.size();
            std::cout << "###" << std::endl;
            for (int i = 0; i < n; i++)
                std::cout << "x[" << i << "]=" << x[i] << std::endl;
        } // !void show_x()


        void save_solution()
        {
            int n = A.size();
            ofstream out("result.txt", ios::out);
            out << "-------------------------------------" << std::endl;
            std::cout << "-------------------------------------" << std::endl;
            for (int i = 0; i < n; i++)
            {                
                out << "x[" << i << "] = " << x[i]<< std::endl;
                std::cout << "x[" << i << "] = " << x[i]<< std::endl;
            }
            out << "-------------------------------------" << std::endl;
            std::cout << "-------------------------------------" << std::endl;
            out.close();
        }
    };
}

 

初等矩阵:乘到方程两端取行阶梯形,初等矩阵是非奇异之,即有逆

链接:http://pan.baidu.com/s/1hqJes4k 密码:elwz

如若B=多个初等矩阵连乘A,那么说A与B是行等价的

倘若A与I行等价,那么Ax=0只来平凡解0,而且A有逆矩阵A-1,也尽管是A是非奇异的,此时Ax=b有唯一排

求逆的章程:对增广矩阵A|I做行变换,把A变成I,则I变成了A-1

本着竞赛矩阵:对角线以外的元素还是0

若A可以只使用行运算化简为严格上三角形,则A有一LU讲,L是单位下三角矩阵,矩阵值就是移使得的系数,这被LU分解

矩阵分块后满足矩阵乘法规则

内积也为标量积:行向量和列向量乘积,得出一个反复

外积:列向量和行向量乘积,得出一个矩阵

外积展开:两个矩阵分别就此为量计表示,其乘积可以表示也外积展开

行列式

行列式:两漫长竖线间包括的阵列

每个方形矩阵可以和外的行列式对应,行列式数值说明方阵是否是惊叹的

行列式算法:展开某同履,每个数随着以客的余子式并加和

若是行列式非0,则方形矩阵为非奇异

det(A)可代表为A的其它履行还是列的余子式展开

三角形形矩阵的行列式等于对角元素乘积

交换矩阵两实践,行列式变成原来的负数,即det(EA)=-det(A)

矩阵某行乘以a,行列式变成原来的a倍,即det(EA)=adet(A)

矩阵某行乘以a加到其他一样推行,行列式不变换

若果有行外一行的翻番,则矩阵行列式为零星

det(AB)=det(A)det(B)

adj A:矩阵的陪伴(adjoint),将元素用余子式替换并转置

求逆方法:A-1=(1/det(A)) adj A,推导:A(adj A)=det(A)I所以A(((1/det(A))
adj A) = I

克拉黙法则:Ax=b的唯一破是xi=det(Ai)/det(A),这是线性方程组用行列式求解的有利方法

消息加密方法:找到行列式为正负1的平头矩阵A,A-1=+-adj
A易求,乘A加密,乘A-1解密,A的构造方法:单位矩阵做初等变换

向量积也是一个向量

微积分中x看做行向量,线性代数中x看做列向量

假设x和y是行向量,则x*y=(x2y3-y2x3)i-(x1y3-y1x3)j+(x1y2-y1x2)k,其中i,j,k是单位矩阵的行向量

向量积可用于定义副法线方向

xT(x*y)=yT(x*y)=0,说明为量积与向量夹角为0

向量空间

向量空间:这个集中满足加法和标量乘法运算,标量通常指实数

子空间:向量空间S的子集本身吗是单向量空间,这个子集叫做子空间

而外{0}和向量空间本身他,其他子空间叫做真子空间,类似于真子集的定义,{0}叫做零子空间

Ax=0的解空间N(A)称为A的零空间,也就是说Ax=0线性方程组的解空间构成一个向量空间

向量空间V中多只向量的线性组合构成的聚合成为这些向量的张成(span),记作span(v1,v2,…,vn)

span(e1,e2)为R3的一个子空间,从几何上象征也保有x1x2面内3维空间的向量

span(e1,e2,e3)=R3

若果span(v1,v2,v3)=R3,那么说为量v1,v2,v3张成R3,{v1,v2,v3}是V的一个张集

尽小张集是说里面没剩余的向量

极端小张集的判定方式是:这些向量线性组合=0只是来0解,这种情况吧尽管是这些向量是线性无关的,如果生免零解那么尽管算得线性相关的

于几乎哪里上看二各项向量线性相关等价于平,三维向量线性相关等价于在与一个平面内

向量构成矩阵的行列式det(A)=0,则线性相关,否则线性无关

线性无关向量唯一地线性组合来表示任意向量

最好小张集构成向量空间的基,{e1,e2…en}叫做标准基,基向量数目就是向量空间的维数

易矩阵:把坐标从同组基到另一样组基的转移矩阵

由A的行向量张成的R1*n子空间改为A的行空间,由A的列向量张成的Rm子空间改为A的排列空间

A的行空间的维数成为A的秩(rank),求A的秩方法:把A化为行阶梯形,非零行个数就是秩

矩阵的零空间的维数成为矩阵的零度,一般秩和零度的与齐矩阵的列数

m*n矩阵行空间维数等于列空间的维数

线性变换

线性变换:L(av1+bv2)=aL(v1)+bL(v2)

线性算子:一个向量空间及那个本身的线性变换

首屈一指线性算子距离:ax(伸长或压缩a倍),x1e1(到x1幅的影),(x1,-x2)T(关于x1轴作对称),(-x2,x1)T逆时针旋转90过

看清是无是线性变换,就看这种转移能无克转化成为一个m*n矩阵

线性变换L的核记为ker(L),表示线性变换后的向量空间被之0向量

子空间S的象记为L(S),表示子空间S上向量做L变换的价

满向量空间的象L(V)成为L的值域

ker(L)为V的一个子空间,L(S)为W的一个子上空,其中L是V到W的线性变换,S是V的子空间

打为E为来序基的向量空间V到为F为出序基的向量空间W的线性变换的矩阵A叫做表示矩阵

B为L相应于[u1,u2]的意味矩阵,A为L相应于[e1,e2]的表示矩阵,U为自[u1,u2]到[e1,e2]的更换矩阵,则B=U-1AU

如果B=S-1AS,则称B相似于A

而A和B为同一线性算子L的意味矩阵,则A和B是一般的

正交性

有限个向量的标量积为零,则称他们正交(orthogonal)

R2或R3中的向量x和y之间的相距是:||x-y||

xTy=||x|| ||y|| cos θ,即cos θ=xTy / (||x|| ||y||)

设方向向量u=(1/||x||)x,v=(1/||y||)y,则cos
θ=uTv,即夹角余弦等单位向量的标量积

柯西-施瓦茨不等式:|xTy| <= ||x|| 
||y||,当且仅当有0奔量或变成倍数关系常等号成立

标量投影:向量投影的长度,α=xTy/||y||

向量投影:p=(xTy/||y||)y=(xTy/yTy)y

对R3:||x*y|| = ||x|| ||y|| sinθ

当x和y正交时, ||x+y||2= ||x||2+ ||y||2,叫毕达哥拉斯定律

c2=a2+b2于毕达哥拉斯定理,其实就是招股弦定理

余弦应用叫判断一般程度

U为向量组成的矩阵,C=UTU对诺每一行向量的标量积值,这个矩阵表示有关程度,即相关矩阵(correlation
matrix),值为刚不怕是刚相关,值也倚就是因连带,值为0就是勿相干

协方差:x1和x2为寡单集聚相对平均值的错误向量,协方差cov(X1,X2)=(x1Tx2)/(n-1)

协方差矩阵S=1/(n-1)
XTX,矩阵的对角线元素为老三只成绩集合的方差,非对角线元素呢协方差

无独有偶交子空间:向量空间的有限只支行空间各取出一个向量都正交,则分空间正交。比如z轴子空间以及xy平颜空间是正交的

支行空间Y的正交补:是这么一个聚集,集合中每个向量都跟Y正交

正巧交补一定为是一个子空中

A的列空间R(A)就是A的值域,即Rn中之x向量,列空间受到之b=Ax

R(AT)的正交空间是零空间N(A),也就是说A的排空间和A的零空间正交

S为Rn的一个子空间,则S的维数+S正交空间的维数=n

S为Rn的一个子空中,则S的正交空间的正交空间是外自

最小二趁(least squares)用来拟合平面及之点集

极小二乘机解为p=Ax最接近b的为量,向量p为b在R(A)上之影子

极端小二趁解x的残差r(x)一定属于R(A)的正交空间

残差:r(x) = b – Ax

ATAx = ATb叫做正规方程组,它发出唯一解x =
(ATA)-1ATb,这虽是绝小二乘解,投影向量p=A(ATA)-1ATb为R(A)中的因素

插值多项式:不超越n次的几近项式通过平面上n+1个点

一个定义了内积的向量空间改为内积空间

标量内积是Rn中的正统内积,加权求和也是千篇一律种内积

内积表示为,内积需满足: >= 0; =; =a+b

a=/||v||为u到v的标量投影

p=(/) v为u到v的向量投影

柯西-施瓦茨不等式:|| <= ||u|| ||v||

范数(norm):定义跟向量相关联的实数||v||,满足||v||>=0; ||av||=|a|
||v||; ||v+w|| <= ||v|| + ||w||

||v|| = ()^-1为一个范数

||x||=sigma|xi|为一个范数

||x||=max|xi|为一个范数

诚如地,范数给闹了相同种植方法来度量两只向量的距离

v1,v2,…,vn如果相互之间=0,则{v1,v2,…,vn}成为向量的正交集

正巧交集中的向量都是线性无关的

正式正交的向量集合是单位向量的正交集,规范正交集中=1,里面的向量叫做规范正交基

恰交矩阵:列向量构成规范正交基

矩阵Q是正交矩阵重要原则是QTQ=I,即Q-1=QT

趁以一个正交矩阵,内积保持无转移,即=

就以一个正交矩阵,仍维持向量长度,即||Qx||=||x||

交换矩阵:将单位矩阵的各列重新排列

假设A的列向量构成规范正夹,则最为小二趁问题解为x=ATb

非零子空间S中为量b到S的阴影p=UUTb,其中U为S的均等组正式正交基,其中UUT为到S上的投影矩阵

应用非越n次的大半项式对连函数进行逼近,可以就此最好小二就逼近。

某取值范围外线性函数的子空间,内积形式是取值范围外对个别个函数乘积做积分

由此将FN乘以向量z来算离散傅里叶系数d的法门称为DFT算法(离散傅里叶变换)

FFT(快速傅里叶变换),利用矩阵分块,比离散傅里叶变换快8w多倍增

格拉姆-施密特正交化过程:u1=(1/||x1||)x1, u2=(1/||x2-p1||) (x2-p1),
…..直接伸手来同样组正式正交基

格拉姆-施密特QR分解:m*n矩阵A如果秩为n,则A可以解释为QR,Q为列向量正交的矩阵,R为达三角矩阵,而且对角元素都也刚刚,具体算法:

r11=||a1||,其中r11是针对比赛矩阵第一排列第一独要素,a1凡A的列向量,

rkk=||ak-p(k-1)||, rik=qiTak, a1=r11q1

Ax=b的卓绝小二乘机解为x=R-1QTb,其中QR为因式分解矩阵,解x可用回代法求解Rx=QTb得到

运用多项式进行多少拟合和逼近连续函数可透过选择逼近函数的一致组正交基进行简化

大抵项式序列p0(x),p1(x),…下标就是高次数,如果=0,则{pn(x)}成为正交多项式序列,如果=1,则于规范正交多项式序列

经正交多项式:勒让德行多项式、切比雪夫多项式、雅克于多项式、艾尔米特多项式、拉盖尔多项式

逼让德行多项式:在内积=-1到1之积分p(x)q(x)dx意义下正交,(n+1)P(n+1)(x)=(2n+1)xPn(x)-nP(n-1)(x)

切比雪夫多项式:在内积=-1到1底积分p(x)q(x)(1-x2)-1/2dx意义下正交,T1(x)=xT0(x),
T(n+1)(x)=2xTn(x)-T(n-1)(x)

拉格朗日插值公式:P(x)=sigma f(xi) Li(x)

拉格朗日函数Li(x)=(x-xj)连乘积 / (xi-xj)连乘积

f(x)w(x)在a到b的积分可以简化为sigma Li(x)w(x)在a到b的积分 f(xi)

特征值

经过矩阵变换后向量保持不更换,稳定后底向量叫做该过程的稳态向量

是非零的x使得Ax=λx,则称λ为特点值,x为属于λ的特征向量。特征值就是一个缩放因子,表示线性变换这个算子的当然频率

旁空间N(A-λI)称为对应特征值λ的特征空间

det(A-λI)=0称为矩阵A的特征方程,求解特征方程可以算是出λ

λ1λ2…λn=det(A),即有特征值的连乘积等于矩阵A的行列式的价

sigma λi= sigma aii,所有特征值的跟当矩阵对角线元素之和

A的对角线元素的以及称为A的划痕(trace),记否tr(A)

相似矩阵:B=S-1AS

相似矩阵具有同样之风味多项式,和同样的特征值

线性微分方程解法可以据此特征值特征向量,形如Y’=AY,
Y(0)=Y0的解是ae(λt)x,其中x是向量,这样的题目称为初值问题,如果起差不多单特色值,则败可以是差不多只ae(λt)x的线性组合

随机高阶微分方程都可转正成为一号微分方程,一流微分方程可以据此特征值特征向量求解

矩阵A的不等特征值的特征向量线性无关

倘若存在X使得X-1AX=D,D是对角矩阵,则说A是可针对角化的,称X将A对角化,X叫做对角化矩阵

假定A有n个线性无关的特征向量,则A可对角化

本着角化矩阵X的列向量就是A的特征向量,D的对角元素就是是A的特征值,X和D都非是唯一的,乘以只标量,或重新排列,都是一个新的

An=XDnX-1,所以按A=XDX-1因式分解后,容易计算幂次

苟A有些许n个线性无关的特征向量,则称A为落后的(defective),退化矩阵不可对角化

特征值和特征向量的几哪里理解:矩阵A有特点值2,特征空间由e3摆成,看成几何重数(geometric
multiplicity)是1

矩阵B有特色值2,特征向量有有限单x=(2,1,0)和e3,看成几哪里重数(geometric
multiplicity)是2

轻易过程:一个试验队,每一样步输出都在于概率

马尔可夫过程:可能的出口集合或状态是鲜的;下同样步输出仅靠前无异步输出,概率相对于日是常数

万一1也换矩阵A的住特征值,则马尔可夫链将不复存在到稳态向量

一个换矩阵为A的马尔可夫过程,若A的某某幂次的因素都呢正之,则称该为正则的(regular)

PageRank算法可以看做浏览网页是马尔可夫过程,求稳态向量就得到每个网页的pagerank值

A的奇异值(singlular
value)分解:把A分解为一个乘积UΣVT,其中U、V都是正交矩阵,Σ矩阵的对准角线下拥有因素呢0,对角线元素逐个减,对角线上的值叫奇异值

A的秩等于非零奇异值的个数

A的奇异值等于特征向量的开方

若A=UΣVT,那么点ATuj=σjvj,下面ATuj=0,其中vj叫做A的右奇异向量,uj叫做左奇异向量

缩减形式的奇异值分解:U1=(u1,u2,…,ur), V1=(v1,v2,…,vr),A=U1Σ1V1T

奇异值分解解题过程:先算ATA的性状值,从而算出奇异值,同时算出特征向量,由特征向量得出正交矩阵V,求N(AT)的同等组基并化成规范正交基,组成U,最终得出A=UΣVT

数值秩是在有限位精度计算着之秩,不是标准之秩,一般假要一个挺粗之epsilon值,如果奇异值小于它则觉得是0,这样来算数值秩

因此来储存图像的矩阵做奇异值分解后失去丢较小的奇异值得到更小秩的矩阵,实现减少存储

消息寻找中失去丢小奇异值得到的近乎矩阵可以大大提高检索效率,减多少误差

二次型:每一个次浅方程关联的朝量函数f(x)=xTAx,即第二破方程中ax2+2bxy+cy2部分

ax2+2bxy+cy2+dx+ey+f=0图是一个圆锥曲线,如果没解则称虚圆锥曲线,如果只是来一个碰、直线、两长长的直线,则号称退化的圆锥曲线,非退化的圆锥曲线为宏观、椭圆、抛物线、双曲线

一个有关x、y的亚蹩脚方程可以形容为xTAx+Bx+f=0,其中A为2*2对称,B为1*2矩阵,如果A是非奇异的,利用旋转和平换坐标轴,则可化简为λ1(x’)2+λ2(y’)2+f’=0,其中λ1和λ2为A的特征值。如果A是怪的,且只有发一个特征值为零星,则化简为λ1(x’)2+e’y’+f’=0或λ2(x’)2+d’x’+f’=0

二次型f(x)=xTAx对于所有x都是一个号,则称定的(definite),若符号为正,则让正定的(positive
definite),相对应叫负定的(negative
definite),如果符号来异则吃不定的(indefinite),如果可能=0,则于半正定的(positive
semidefinite),和半负定的(negative semidefinite)

如二次型正定则称A为正定的

一阶偏导存在且为0的点称为驻点,驻点是极致小值点还是巨大值点还是鞍点取决于A是正定负定还是不肯定

一个针对如矩阵是正定的,当且仅当其有特征值均为正的

r阶前主矩阵:将n-r行和列删去获取的矩阵

假使A是一个对称正定矩阵,则A可讲为LDLT,其中L为产三交锋的,对角线上元素呢1,D为对角矩阵,其针对性角元素均为刚刚的

如A是一个对称正定矩阵,则A可讲为LLT,其中L为产三竞的,其对角线元素都为正

本着如矩阵如下结论等价:A是正定的;前主人矩阵均为正定的;A可就用行运算化为直达三比的,且主元全否刚刚;A有一个楚列斯基分解LLT(其中L为下三角矩阵,其针对性角元素为刚的);A可以解释为一个乘积BTB,其中B为某非奇异矩阵

非负矩阵:所有因素都大于等于0

一个非负矩阵A,若然则将生标集{1,2,…,n}划分为非空不交集合I1和I2,使得当i属于I1而j属于I2中常,aij=0,则变为其也可约的,否则也不可约的

数值线性代数

舍入误差(round off error):四放弃五适合后底浮点数x’和原始数x之间的异

绝对误差:x’-x

相对误差:(x’-x)/x,通常用符号δ表示,|δ|可以为此一个正常数ε限制,称为机器精度(machine
epsilon)

高斯消元法涉及最少之算术运算,因此于看是无与伦比快速的计量方式

求解Ax=b步骤:将A乘以n个初等矩阵得到上三角矩阵U,把初等矩阵求逆相乘得到L,那么A=LU,其中L为下三角矩阵,一旦A化简为三角形式,LU分解就规定了,那么解方程如下:LUx=b,令y=Ux,则Ly=b,所以可以透过求下三角方程求得y,y求得后又求解Ux=y,即可求得x

矩阵的弗罗贝尼乌斯范数记作||·||F,求其持有因素平方和的平方根

若A的奇异值分解A=UΣVT,则||A||2=σ1(最可怜之奇异值)

矩阵范数可用来估计线性方程组对系数矩阵的薄变化的敏感性

将x’代转原方程组观察b’=Ax’和b的类成都来查看精度,r=b-b’=b-Ax’叫做残差(residual),||r||/||b||叫做相对残差

奇异值为一个矩阵接近奇异程度的气量,矩阵越接近奇异就更病态

豪斯霍尔德变换(householder
transformation)矩阵H可由为量v和标量β求得,因此存储v和β更省空中

主特征值是因710官方网站太可怜之特征值

请主特征值的道:幂法。

求特征值方法:QR算法。将A分解为就积Q1R1,其中Q1为正交的,R1为达三交锋的,A2=Q1TAQ1=R1Q1,将A2说为Q2R2,定义A3=Q2TA2Q2=R2Q2,继续这样,得到相似矩阵序列Ak=QkRk,最终将熄灭到近似上三角矩阵,对角上是1*1或2*2底针对角块,对角块的特征值就是A的特征值

最后之下结论

奇异值分解幸亏针对这种线性变换的一个析构,A=,和是简单组正交单位向量,是对准角阵,表示奇异值,它表示A矩阵的打算是用一个向量从立组正交基向量的长空旋转交及时组正交基向量空间,并针对每个方向拓展了自然之缩放,缩放因子就是各个奇异值。如果维度比大,则代表尚进行了投影。可以说奇异值分解描述了一个矩阵完整的功能/特性。

特征值分解实在就描述了矩阵的部分职能。特征值,特征向量由Ax=x得到,它象征要一个为量v处于A的特征向量方向,那么Av对v的线性变换作用就是一个缩放。也就是说,求特征向量和特征值的历程,我们找到了如此局部势头,在这些方向直达矩阵A对向量的旋转、缩放改换(由于特征值只对方阵,所以没有投影转换)在得水准及抵消了,变成了存粹的缩放(这个缩放比例与奇异值分解受到之缩放比例或无一样)。

包一下,特征值分解不过报告我们于特征向量的不胜样子及,矩阵的线性变化作用相当于是简单的缩放,其他方向达成虽未掌握,所以我说她只是代表矩阵的有特性。而奇异值分解虽以原本隐含在矩阵中之转、缩放、投影三种意义清楚地剖析出,表示出来了,它是指向矩阵的一个整特征剖析。

参考文献

线性代数(原题第9本),史蒂文 J.利昂 (Steven J.Leon)(作者)

相关文章