線性代數——C語言實現(超長篇慎入)【封】


線性代數

鎮樓圖

Pixiv: csyday


僅作為學習線代的實驗,不會特別注重內存泄漏、bug等問題

目前不打算用寫稀疏矩陣,之后可能會轉C++



〇、准備工作(構建分數ADT)

點擊查看詳細內容

要知道網上很多在線計算最煩的一點是沒有分數全都是小數,這樣答案也寫不進作業中。

為了方便學習寫作業,這里特地寫一塊內容

typedef struct __fraction{
	int numerator;//分子
    int denominator;//分母
}fraction,*Fraction;
bool fraction_ifexist(Fraction a){
	//作用:判斷分數是否是有效的 
    //如果分母為0則返回0視為無效
    //如果分母不為0則返回1視為有效
	return (a->denominator == 0) ? false : true;
};
int fraction_ifproper(Fraction a){
	//作用:判斷分數是否為真分數 
	//如果分數是真分數則返回1否則返回0 
	if(!fraction_ifexist(a)){
		printf("錯誤:分母為0!!!");
		exit(-1);
	}
	return (a->denominator > a->numerator) ? true : false;
};
int gcd(int a,int b){
	//求最大公約數 
	b = abs(b);
	a = abs(a);
	if(b > a){
		int t = a;
		a = b;
		b = t;
	}
	return (b == 0) ? a : gcd(b,a%b);
}

void fraction_simplify(Fraction a){
	//作用:約分
	if(!fraction_ifexist(a)){
		printf("錯誤:分母為0!!!");
		exit(-1);
	}
	int GCD = gcd(a->numerator,a->denominator);
	a->numerator /= GCD;
	a->denominator /= GCD;
	if(a->denominator < 0){
		a->numerator *= -1;
		a->denominator *= -1;
	}
	return;
}
int lcm(int a,int b){
	//求最小公倍數 
	return abs(a)*abs(b)/gcd(a,b);
}

void fraction_complicated(Fraction a,Fraction b){
	//作用:通分
	if(!fraction_ifexist(a) || !fraction_ifexist(b)){
		printf("錯誤:分母為0!!!");
		exit(-1);
	}
	int LCM = lcm(a->denominator,b->denominator);
	a->numerator *= LCM/a->denominator;
	b->numerator *= LCM/b->denominator;
	a->denominator = b->denominator = LCM;
	return;
} 
Fraction fraction_add(Fraction a,Fraction b){
	//作用:加法 
	if(!fraction_ifexist(a) || !fraction_ifexist(b)){
		printf("錯誤:分母為0!!!");
		exit(-1);
	}
	Fraction r = (Fraction)malloc(sizeof(fraction));
	fraction_complicated(a,b);
	r->numerator = a->numerator + b->numerator;
	r->denominator = a->denominator;
	fraction_simplify(r);
	return r;
}

Fraction fraction_sub(Fraction a,Fraction b){
	//作用:減法 
	if(!fraction_ifexist(a) || !fraction_ifexist(b)){
		printf("錯誤:分母為0!!!");
		exit(-1);
	}
	Fraction r = (Fraction)malloc(sizeof(fraction));
	fraction_complicated(a,b);
	r->numerator = a->numerator - b->numerator;
	r->denominator = a->denominator;
	fraction_simplify(r);
	return r;
}
Fraction fraction_mul(Fraction a,Fraction b){
	//作用:乘法
	 if(!fraction_ifexist(a) || !fraction_ifexist(b)){
		printf("錯誤:分母為0!!!");
		exit(-1);
	}
	Fraction r = (Fraction)malloc(sizeof(fraction));
	r->numerator = a->numerator * b->numerator;
	r->denominator = a->denominator * b->denominator;
	fraction_simplify(r);
	return r;
}

Fraction fraction_div(Fraction a,Fraction b){
	//作用:除法 
	 if(!fraction_ifexist(a) || !fraction_ifexist(b)){
		printf("錯誤:分母為0!!!");
		exit(-1);
	}
	Fraction r = (Fraction)malloc(sizeof(fraction));
	r->numerator = a->numerator * b->denominator;
	r->denominator = a->denominator * b->numerator;
	fraction_simplify(r);
	return r;
}
void fraction_print(Fraction a){
	//作用:約分並輸出
	 if(!fraction_ifexist(a)){
		printf("錯誤:分母為0!!!");
		exit(-1);
	}
	fraction_simplify(a);
	if(a->denominator == 1 || a->numerator == 0){
		a->denominator = 1;
		printf("%d",a->numerator);
	}else printf("%d/%d",a->numerator,a->denominator); 
	return;
} 
fraction fraction_create(int a,int b){
	//生成一個以a為分子b為分母的分數
    fraction r;
    r.numerator = a;
    r.denominator = b;
    return r;
}

這樣就完成了准備工作

一、線性方程(組)

點擊查看詳細內容

線性方程

\(a_1x_1+a_2x_2...+a_nx_n=b\)

其中\(a_i\)為系數,\(x_i\)為變量,\(b\)為值

\(a_i\)\(b\)可以為實數或復數

得出的一組可行的變量值組合為解

解分為三種情況

無解
不存在組合使得線性方程(組)成立
有限解
只有有限個組合使得線性方程(組)成立
無窮解
有無數種組合使得線性方程(組)成立

解構成的集合稱為解集

有解的線性方程(組)稱為是相容

無解的線性方程(組)稱為是不相容

線性方程組

所謂線性方程組是一組線性方程構成的一組變量有關聯的方程組

比如

\(\begin{cases}&x&+&y&+&z=&50 \\ &5x&+&2y&+&z=&100 \end{cases}\)

增廣矩陣

可以將變量、運算符去掉,只保留系數、值

這樣由線性方程組用矩陣符號化后的矩陣稱為'增廣矩陣'

\(\begin{bmatrix}1&1&1&50 \\ 5&2&1&100 \end{bmatrix}\)

這個矩陣中\(\begin{bmatrix}1&1&1&50\end{bmatrix}\)稱為

這個矩陣中\(\begin{bmatrix}1 \\ 50\end{bmatrix}\)稱為

維數是指矩陣所包含的行數和列數

typedef struct __matrix{
	Fraction **base;//矩陣首元素
    int row;//矩陣行數
    int col;//矩陣列數
}matrix,*Matrix;
void matrix_null(Matrix a,int m,int n){
	//創建m×n的零矩陣
	a->base = (Fraction**)malloc(sizeof(Fraction*)*m);
	for(int i = 0;i < m;i++)
		a->base[i] = (Fraction*)malloc(sizeof(Fraction)*n);
    //二維數組賦予內存稍麻煩
	a->row = m;
	a->col = n;
	for(int i=0;i < a->row;i++)
		for(int j=0;j < a->col;j++)
			a->base[i][j] = fraction_create(0,1);
    return;
}
void matrix_edelete(matrix a,int i,int j){
    //釋放矩陣內a(i,j)的內存
    free(a.base[i][j]);
    return;
}
void matrix_set(matrix a,int i,int j,Fraction value){
	//將矩陣a的第i、j位置的元素修改為value 
	matrix_edelete(a,i,j);
	a.base[i][j] = value;
	return;	
}
void matrix_print(matrix a){
    //輸出矩陣
	for(int i = 0;i < a.row;i++){
		for(int j = 0;j < a.col;j++){
			fraction_print(a.base[i][j]);
			printf("\t");
		}
		printf("\n");
	}
}
void matrix_delete(matrix a){
	//刪除矩陣 
	for(int i = 0;i < a.row;i++){
		free(a.base[i]);
	}
	free(a.base);
	a.base = NULL;
	a.col = a.row = 0;
	return;
}
matrix matrix_rowcombine(matrix a,matrix b){
	//作用:按行合並矩陣a,b
	if(a.row != b.row){
		printf("錯誤:行數不一致");
		exit(-1);
	}
	matrix new;
	matrix_null(&new,a.row,a.col+b.col);
	for(int i = 0;i < a.row;i++){
		for(int j = 0;j < a.col;j++){
			matrix_set(new,i,j,a.base[i][j]);
		}
	}
	for(int i = 0;i < a.row;i++){
		for(int j = a.col;j < a.col+b.col;j++){
			matrix_set(new,i,j,b.base[i][j - a.col]);
		}
	}
	return new;
}

matrix matrix_colcombine(matrix a,matrix b){
	//作用:按列合並矩陣a,b
	if(a.col != b.col){
		printf("錯誤:列數不一致");
		exit(-1);
	}
	matrix new;
	matrix_null(&new,a.row+b.row,a.col);
	for(int i = 0;i < a.row;i++){
		for(int j = 0;j < a.col;j++){
			matrix_set(new,i,j,a.base[i][j]);
		}
	}
	for(int i = a.row;i < a.row+b.row;i++){
		for(int j = 0;j < a.col;j++){
			matrix_set(new,i,j,b.base[i - a.row][j]);
		}
	}
	return new;
}
void matrix_identity(Matrix a,int n){
    //生成n階的單位矩陣
    a->base = (Fraction**)malloc(sizeof(Fraction*)*n);
	for(int i = 0;i < n;i++)
		a->base[i] = (Fraction*)malloc(sizeof(Fraction)*n);
	a->row = n;
	a->col = n;
	for(int i=0;i < a->row;i++)
		for(int j=0;j < a->col;j++)
			if(i != j) a->base[i][j] = fraction_create(0,1);
			else a->base[i][j] = fraction_create(1,1);
	return;
}
void matrix_square(Matrix a,int n){
    //生成n階的單位矩陣
    a->base = (Fraction**)malloc(sizeof(Fraction*)*n);
	for(int i = 0;i < n;i++)
		a->base[i] = (Fraction*)malloc(sizeof(Fraction)*n);
	a->row = n;
	a->col = n;
	for(int i=0;i < a->row;i++)
		for(int j=0;j < a->col;j++)
			a->base[i][j] = fraction_create(0,1);
	return;
}

現在就能用幾行代碼來生成一個矩陣了,更加具體的操作我會隨着線代的學習來寫代碼

初等變換

增廣矩陣不過是符號化后的線性方程組,線性方程組該怎么求還就怎么求

根據原本對線性方程組的求解方法,在增廣矩陣里可以抽象為一種規律

使用下述規律后這個增廣矩陣依然等價

①倍加:可以將某一行/列加上另一行的某個倍數

②對換:可以任意交換兩行/列

③倍乘:某一行/列可以乘上某一不為0的倍數

初等變換也是可逆的

bool matrix_ifrow(matrix a,int i){
	//判斷第i行是否在a矩陣里合法 
	return (i >=0 && i < a.row) ? true : false;
}

①對換

void matrix_transfrom_rreplace(matrix a,int i1,int i2){
	//矩陣a進行初等行變換,i1行與i2行交換 
	if(!matrix_ifrow(a,i1) || !matrix_ifrow(a,i2)){
		printf("錯誤:所描述的行已超出行數");
		exit(-1);
	} 
	for(int j = 0;j < a.col;j++){
		Fraction t = a.base[i1][j];
		a.base[i1][j] = a.base[i2][j];
		a.base[i2][j] = t;
	}
	return;
}

②倍乘

void matrix_transfrom_rmul(matrix a,int i,Fraction c){
	//矩陣a進行初等行變換,i1行乘上某已分數 
	if(!matrix_ifrow(a,i)){
		printf("錯誤:所描述的行已超出行數");
		exit(-1);
	} 
	for(int j = 0;j < a.col;j++){
		a.base[i][j] = fraction_mul(a.base[i][j],c);
	}
	return;
}

③加法

void matrix_transfrom_radd(matrix a,int i1,int i2){
	//矩陣a進行初等行變換,i1行加i2行
	if(!matrix_ifrow(a,i1) || !matrix_ifrow(a,i2)){
		printf("錯誤:所描述的行已超出行數");
		exit(-1);
	} 
	for(int j = 0;j < a.col;j++){
		a.base[i1][j] = fraction_add(a.base[i1][j],a.base[i2][j]);
	}
	return;
}

④倍加

void matrix_transfrom_rcadd(matrix a,int i1,Fraction c,int i2){
	//矩陣a進行初等行變換,i1行加c的倍i2行
	if(!matrix_ifrow(a,i1) || !matrix_ifrow(a,i2)){
		printf("錯誤:所描述的行已超出行數");
		exit(-1);
	} 
	for(int j = 0;j < a.col;j++){
		a.base[i1][j] = fraction_add(a.base[i1][j],fraction_mul(a.base[i2][j],c));
	}
	return;
}

行階梯形矩陣

以下面這個矩陣為例

\(\begin{bmatrix}0&1&2&3&0&15 \\ 0&0&5&6&7&16 \\ 0&0&0&0&9&17 \\ 0&0&0&0&0&0 \end{bmatrix}\)

其中矩陣當中如果有某一行元素全部為0就稱這是零行

在非零行的最左側的元素稱為先導元素,這里是1,5,9

主元除了滿足先導元素條件以外,還要保證左側全是0

主元所在位置稱為主元位置,主元所在列稱為主元列

所謂主元就算在主元位置上的非零元素

為了符號化的表示,用表示先導元素,*表示由先導元素所形成的階梯內的元素,其他元素為0的則省略不寫

此例符號化表示為

\(\begin{bmatrix}&■&*&*&*&* \\ &&■&*&*&* \\ &&&&■&* \\ &&&&& \end{bmatrix}\)

行階梯形矩陣

只有滿足以下條件才能算得上是行階梯矩陣

①非零行要在零行上

②先導元素一定是從左到右依次排列好的

③先導元素所在列的下方元素都為0

簡化階梯形矩陣(U)

這是增廣矩陣的最簡形式,簡單到能一眼看出解,這是比其他行階梯形矩陣還要好算的形式

除了行階梯形矩陣的定義以外還要滿足以下條件

①先導元素為1

②先導元素是這一列唯一的非零元素

每個矩陣只有唯一的簡化階梯形矩陣(簡化階梯形的唯一性)

程序里常用rref或ref來表示(英文縮寫)

二、高斯消元法(行化簡算法)

點擊查看詳細內容

為了計算求解線性方程組需要求解增廣矩陣的階梯形矩陣或簡化階梯形矩陣

高斯消元算法正是匯編了一套方法來求解,而其原理也很簡單就是行初等變換

①構建框架

目前接觸到了\(row~<=~col\)的情況,\(row~>~col\)的情況干脆忽略了

void matrix_augmented_REF(matrix a){
    //求解矩陣等價的階梯形矩陣
	if(a.row > a.col){
		printf("無法處理:行數大於列數\n");
		exit(-1);
	}
	//
}

②選擇主元

在求解線性方程組一般情況會將主元優先選擇在\((0,0)\)的位置,但也有特殊情況

\((0,0)\)恰好是零元素

這種情況好解決,可以通過交換其他不是零元素的行,在程序里默認找絕對值的最大值

\((0,0)\)這一列都是零元素,交換了也沒用

這種情況的話,都是0,不存在所謂的主元,這一列都不用考慮了,需要移動到下1列找主元

//分數操作9
int fraction_abscmp(Fraction a,Fraction b){
	/*作用:比較分數a與b絕對值的大小
      若a < b返回-1
	  若a = b返回0
	  若a > b返回1*/
    fraction_complicated(a,b);
    if(fabs(a->numerator) < fabs(b->numerator))return -1;
    else if(fabs(a->numerator) == fabs(b->numerator))return 0;
    else return 1;
}
bool matrix_augmented_REF_select(matrix a,int* posx,int* posy){
     int maxx = *posx;
    //maxx為a.base[maxx][posy]的絕對值最大的橫坐標
	for(int i = *posx;i < a.row;i++){
		if(fraction_abscmp(a.base[maxx][*posy],a.base[i][*posy]) < 0)maxx = i;
	}
	//從posy列中索引,找到最大的一個來避免第一種特殊情況
    if(a.base[maxx][*posy]->numerator == 0){
        return false;
    }
    matrix_transfrom_rreplace(a,*posx,maxx);
    return true;
    //然后判斷第二種特殊情況,如果成立則換到下一列
    //不然就直接交換來完成第一步操作
    //返回true表示在(posx,posy)這一列成功找到主元
    //返回false表示未找到主元
}

②消元

根據第一步操作,如果未找到主元,則要修改主元位置來重新選擇主元,這里先考慮如果找到了主元的情況

//分數操作10
Fraction fraction_opposite(Fraction a){
	//求分數的相反數 
	fraction b;
	b.numerator = -1;
	b.denominator = 1;
	return fraction_mul(a,&b);
}
void matrix_augmented_REF_eliminate(matrix a,int* posx,int* posy){
	//消元
	for(int i = *posx+1;i < a.row;i++){
		matrix_transfrom_rcadd(a,i,fraction_div(a.base[i][*posy],fraction_opposite(a.base[*posx][*posy])),*posx);
    }
    return;
}

③迭代

根據前兩步的處理,判斷下一個主元位置在哪

■首先要根據第一步不同的返回值來操作

如果返回了true就代表當前列存在主元,位置\((posx,posy)\)將移動到\((posx+1,posy+1)\)

如果返回了false,位置\((posx,posy)\)將移動到\((posx,posy+1)\)

■同時需要設置什么時候退出迭代

根據這個算法可知只有要選擇主元的位置超出矩陣范圍時就不需要再執行了

bool matrix_augmented_REF_iterator(matrix a,bool ifsuccess,int* posx,int* posy){
    (ifsuccess == true) ? (*posx)++,(*posy)++ : (*posy)++ ;
    if(*posx >= a.row || *posy >= a.col-1)return false;
	else return true;
    //修改主元位置
}

④匯總

根據前三步已經描述出了這個算法的流程,接下來只要設置好即可

void matrix_augmented_REF(matrix a){
    //求解矩陣等價的階梯形矩陣
	if(a.row > a.col){
		printf("無法處理:行數大於列數\n");
		exit(-1);
	}
	int posx = 0,posy = 0;
    bool flag;
	do{
        bool issuccess = matrix_augmented_REF_select(a,&posx,&posy);
        if(issuccess)matrix_augmented_REF_eliminate(a,&posx,&posy);
        flag =  matrix_augmented_REF_iterator(a,issuccess,&posx,&posy);
    }while(flag);
    return;
}

⑤階梯形矩陣變簡化階梯形矩陣

這里只需要修改之前的一部分代碼即可,之前是求得了階梯形矩陣,只要在求得階梯形矩陣中加入一些操作就能變成簡化階梯形矩陣

■在消元后額外添加一步——當前主元變為1,並消除主元列中除主元以外其他的元素

void matrix_augmented_REFF_extra(matrix a,int* posx,int* posy){
    matrix_transfrom_rmul(a,*posx,fraction_create(a.base[*posx][*posy]->denominator,a.base[*posx][*posy]->numerator));
    for(int i = (*posx)-1;i >= 0;i--){
    	matrix_transfrom_rcadd(a,i,fraction_opposite(a.base[i][*posy]),*posx);
	}
}
void matrix_augmented_REFF(matrix a){
    //求解矩陣等價的簡化階梯形矩陣 
	if(a.row > a.col){
		printf("無法處理:行數大於列數\n");
		exit(-1);
	}
	int posx = 0,posy = 0;
    bool flag;
	do{
        bool issuccess = matrix_augmented_REF_select(a,&posx,&posy);
        if(issuccess){
			matrix_augmented_REF_eliminate(a,&posx,&posy);
			matrix_augmented_REFF_extra(a,&posx,&posy);
            //這是額外的一步
		}
        flag =  matrix_augmented_REF_iterator(a,issuccess,&posx,&posy);
    }while(flag);
    return;
}

至此完成了求解簡化階梯形矩陣的算法,簡化階梯形矩陣只是在求階梯形矩陣時多了一步而已

三、線性方程組的解

點擊查看詳細內容

以上面的例子為例,最終通過高斯消元算法求得了簡化階梯形矩陣,主元所對應的變量當作未知量,其余變量當作已知量得

\(\begin{cases} x_1=-24+2x_3-3x_4 \\ x_2=-7+2x_3-2x_4 \\x_5=4 \end{cases}\)

其中主元所對應的變量稱為基本變量,其他不是主元所對應的變量稱為自由變量

此例\(x_3\)\(x_4\)是自由變量,其他是基本變量

一般情況是以基本變量當作未知量,自由變量當作已知量

這樣求得的解稱為通解,而\(x_3\)\(x_4\)取什么是無所謂的

因為含有自由變量,所以有無數種解

存在與唯一性定理

若某一行不存在這種形式\(\begin{bmatrix}0& ... &0&b \end{bmatrix}~~~b≠0\),則增廣矩陣一定相容

增廣矩陣相容時,若增廣矩陣不存在自由變量則只有唯一解,若增廣矩陣存在自由變量則有無窮多解

之前用set函數來輸入代碼量實在多,下述代碼主要改善一下輸入功能

void matrix_input(matrix a,int* n,int* d){
	//n數組元素作為分子,d數組元素作為分母,按行輸入
    int count = 0;
    for(int i = 0;i < a.row;i++){
    	for(int j = 0;j < a.col;j++){
    		matrix_set(a,i,j,fraction_create(n[count],d[count]));
    		count++;
		}
	}
	return;
}
void matrix_inputint(matrix a,int* n){
	//n數組元素作為分子,分母為1,按行輸入 
    int count = 0;
    for(int i = 0;i < a.row;i++){
    	for(int j = 0;j < a.col;j++){
    		matrix_set(a,i,j,fraction_create(n[count],1));
    		count++;
		}
	}
	return;
}

四、線性變換

點擊查看詳細內容 這屬於線代在圖形學應用方面,但這個應用實在重要,直接在此說明了 注:這里僅考慮二維的線性變換

\(Ax=b\)

\(A\)代表的是一組基向量構建的新坐標系

\(x\)代表的是點的位置

\(b\)代表的是在原坐標系下於新坐標系的點的位置

但換個角度想,\(x\)如果是表示原坐標系和新坐標系的點

點會存在一個變換

如圖所示,E通過矩陣乘法變換到了其他位置

而如果是一個圖形,同樣會存在一個變換

你可以清楚地看到粉色圖形隨着A的變換而變換

標准矩陣

\(A\)也稱為標准矩陣,可以發現圖形進行線性變換最重要的是\(A\),因為\(A\)的不同導致了圖形不同的變換

因此研究標准矩陣是重要的一環

這里形式化定義一個函數\(T(x)=Ax\)

由於是線性變換滿足線性

\(T(cx)=c~T(x)\)

\(T(ax+by)=a~T(x)+b~T(y)\)

矩陣可以完成剛體變換、仿射變換、投影變換

①平移變換

嚴格來說平移不屬於線性變換,但可以通過增加一個維度(齊次坐標系)來完成平移

\(\begin{bmatrix}1&0&t_x \\ 0&1&t_y \\ 0&0&1 \end{bmatrix}\)

而此時點的位置為\(\begin{bmatrix}x\\y\\1 \end{bmatrix}\)

通過增加一維來完成\(\begin{cases}x'=x+t_x \\ y'=y+t_y \\ z=1 \end{cases}\)

②旋轉變換

這屬於線性變換

\(\begin{bmatrix}cos~x&-sin~x \\ sin~x&cos~x \end{bmatrix}\)

而x為按逆時針所要旋轉的角度

③對稱變換

(1)關於\(x\)軸變換

\(\begin{bmatrix}1&0 \\ 0&-1 \end{bmatrix}\)

(2)關於\(y\)軸變換

\(\begin{bmatrix}-1&0 \\ 0&1 \end{bmatrix}\)

(3)關於\(x=y\)對稱

\(\begin{bmatrix}0&1 \\ 1&0 \end{bmatrix}\)

(4)關於\(x=-y\)對稱

\(\begin{bmatrix}0&-1 \\ -1&0 \end{bmatrix}\)

(5)關於原點對稱

\(\begin{bmatrix}-1&0 \\ 0&-1 \end{bmatrix}\)

如何記住?

這里我推薦直接畫個基向量,然后根據對稱畫出對稱的基向量,然后就能得出了

④伸縮變換

(1)水平伸縮

\(\begin{bmatrix}k&0 \\ 0&1 \end{bmatrix}\)

(2)垂直伸縮

\(\begin{bmatrix}1&0 \\ 0&k \end{bmatrix}\)

(3)放縮

\(\begin{bmatrix}k&0 \\ 0&k \end{bmatrix}\)

⑤剪切變換

(1)水平剪切

\(\begin{bmatrix}1&k \\ 0&1 \end{bmatrix}\)

(2)垂直剪切

\(\begin{bmatrix}1&0 \\ k&1 \end{bmatrix}\)

⑥投影變換

(1)投影至x軸

\(\begin{bmatrix}1&0 \\ 0&0 \end{bmatrix}\)

(2)投影至y軸

\(\begin{bmatrix}0&0 \\ 0&1 \end{bmatrix}\)

由於投影至一條線,因此無法看到,這里不做演示。但如果是3維投影到2維情況就不一樣了,可以將一個立體物體變成二維,而如果這時候將投影后的圖像塗黑,就變成了影子

五、矩陣運算性質

點擊查看詳細內容

注:這一塊內容僅說明運算性質

基本術語

零空間用\(0_{m×n}\)表示

矩陣元素用\(a_{ij}\)表示,\(i\)為行,\(j\)為列(當然按照計算機傳統,默認從0開始)

列向量用\(a_i\)表示,一般一個矩陣會用\(\begin{bmatrix}a_1&a_2& ...&a_n \end{bmatrix}\)表示

行向量也用\(a_i\)表示,一般一個矩陣會用\(\begin{bmatrix}a_1 \\ a_2 \\ \vdots \\ a_n \end{bmatrix}\)表示

單位矩陣用\(E\)\(I_m\)表示

標量乘法、加法

\(A+B=B+A\)(交換律)

\((A+B)+C=A+(B+C)\)(結合律)

\((r+s)A=rA+sA\)(分配律)

\(r(A+B)=rA+rB\)(分配律)

\(r(sA)=(rs)A\)(結合律)

matrix matrix_add(matrix a,matrix b){
	//作用:矩陣加法a+b
	if(a.col != b.col || a.row != b.row){
		printf("錯誤:維數不匹配");
		exit(-1);
	}
	matrix r;
	matrix_null(&r,a.row,a.col);
	for(int i = 0;i < a.row;i++){
		for(int j = 0;j < a.col;j++){
			r.base[i][j] = fraction_add(a.base[i][j],b.base[i][j]);
		}
	}
	return r;
}

matrix matrix_sub(matrix a,matrix b){
	//作用:矩陣減法a-b
	if(a.col != b.col || a.row != b.row){
		printf("錯誤:維數不匹配");
		exit(-1);
	}
	matrix r;
	matrix_null(&r,a.row,a.col);
	for(int i = 0;i < a.row;i++){
		for(int j = 0;j < a.col;j++){
			r.base[i][j] = fraction_sub(a.base[i][j],b.base[i][j]);
		}
	}
	return r;
}

matrix matrix_cmul(matrix a,Fraction C){
	//作用:標量乘法C*a
	matrix r;
	matrix_null(&r,a.row,a.col);
	for(int i = 0;i < a.row;i++){
		for(int j = 0;j < a.col;j++){
			r.base[i][j] = fraction_mul(a.base[i][j],C);
		}
	}
	return r;
}

matrix matrix_linear(Fraction C1,matrix a,Fraction C2,matrix b){
	//作用:矩陣線性組合C1*a+C2*b
	if(a.col != b.col || a.row != b.row){
		printf("錯誤:維數不匹配");
		exit(-1);
	}
	matrix r;
	matrix_null(&r,a.row,a.col);
	for(int i = 0;i < a.row;i++){
		for(int j = 0;j < a.col;j++){
			r.base[i][j] = fraction_add(fraction_mul(a.base[i][j],C1),fraction_mul(b.base[i][j],C2));
		}
	}
	return r;
}

矩陣乘法

\(AB\)\(A\)的各列乘上\(B\)所對應的權

從單個元素來看得出重要公式

\((AB)_{ij}=∑_{k=0}^{n}a_{ik}b_{kj}\)

然后根據這個重要公式編寫代碼

matrix matrix_mul(matrix a,matrix b){
	//作用:矩陣乘法A*B
	if(a.col != b.row){
		printf("錯誤:維數不匹配");
		exit(-1);
	}
	matrix r;
	matrix_null(&r,a.row,b.col);
	for(int i = 0;i < r.row;i++){
		for(int j = 0;j < r.col;j++){
			for(int k = 0;k < a.col;k++)
			r.base[i][j] = fraction_add(r.base[i][j],fraction_mul(a.base[i][k],b.base[k][j]));
		}
	}
	return r;
}

\(AB≠BA\)一般情況不滿足交換律!!!

因為不滿足交換律,\(B\)乘上\(A\)就分為了兩種方式

一個是左乘\(AB\),一個是右乘\(BA\)

\(A(BC)=(AB)C\)(結合律)

\(B(A+C)=BA+BC\)(左分配律)

\((A+C)B=AB+CB\)(右分配律)

\(A(rB)=r(AB)\)

\(I_mA=AI_m=A\)

⑦不滿足消去律,不能由\(AB=AC\)推出\(B=C\)

乘冪

\(A^k=A.A...A\)

\(A^0=I_m\)

matrix matrix_pow(matrix a,int k){
	//作用:矩陣乘冪A^k
	if(a.row != a.col){
		printf("錯誤:維數無法匹配");
		exit(-1);
	}
	matrix r;
	matrix_identity(&r,a.row);
	while(k--){
		r = matrix_mul(r,a);
	}
	return r;
}

轉置

行向量是指\(\begin{bmatrix}a_1&a_2&...&a_n \end{bmatrix}\)的向量

行向量本質上是和列向量一樣的,只是表達上有所區別

比如從行向量看待的\(\begin{bmatrix}1&2 \end{bmatrix}\)和從列向量看待的\(\begin{bmatrix}1 \\ 2 \end{bmatrix}\)是一樣的

中間經過一個叫轉置的運算,記作\(A^T\)

轉置是將原本從列/行向量看待的矩陣變成從行/列向量看待的矩陣

從單個元素來看就是\(a_{ij}=a_{ji}\)

矩陣乘法從不同角度所做的運算是不同的,但結果相似的
列向量看待矩陣乘法是Ax把右側看作未知量,為左乘
行向量看待矩陣乘法時就是xA把左側看作未知量,為右乘

比如\(\begin{bmatrix}1&2 \\ 3&4 \end{bmatrix}\begin{bmatrix}1\\2\end{bmatrix}=1\begin{bmatrix} 1 \\ 3\end{bmatrix}+2\begin{bmatrix} 2 \\ 4\end{bmatrix}=\begin{bmatrix}5 \\ 11\end{bmatrix}\)

從行向量看待,就需要將這個式子中的矩陣進行轉置並且把左乘改成右乘

從行向量看待的乘法就要從行來看待\(\begin{bmatrix}1&2 \end{bmatrix}\begin{bmatrix}1&3 \\ 2&4 \end{bmatrix}=1\begin{bmatrix}1&3 \end{bmatrix}+2\begin{bmatrix}2&4 \end{bmatrix}=\begin{bmatrix}5&11 \end{bmatrix}\)

但可以發現的是結果之間進行轉置就能相互得到

\((AB)^T=B^TA^T\)(列向量轉行向量,左乘變右乘)

\((A^T)^T=A\)

\((A+B)^T=A^T+B^T\)(分配律)

matrix matrix_transf(matrix a){
	//作用:矩陣轉置A^T
	matrix r;
	matrix_null(&r,a.col,a.row);
	for(int i = 0;i < r.row;i++){
		for(int j = 0;j < r.col;j++){
			r.base[i][j] = a.base[j][i];
		}
	}
	return r;
}

行向量與列向量

如果是以行向量的角度來看,矩陣乘法要為左乘

如果是以列向量的角度來看,矩陣乘法要為右乘

bool matrix_ifcol(matrix a,int j){
	//作用:判斷a矩陣是否有第j列 
	return (i >= 0 && i < a.col) ? true : false;
}

void matrix_cadd(matrix a,int j1,int j2){
	//作用:j1列加j2列
	if(!matrix_ifcol(a,j1) || !matrix_ifrow(a,j2)){
		printf("錯誤:超出列數");
		exit(-1);
	} 
	for(int i = 0;i < a.row;i++){
		a.base[i][j1] = fraction_add(a.base[i][j1],a.base[i][j2]);
	}
	return;
}

void matrix_creplace(matrix a,int j1,int j2){
	//作用:交換j1列、j2列
	if(!matrix_ifcol(a,j1) || !matrix_ifcol(a,j2)){
		printf("錯誤:超出列數");
		exit(-1);
	} 
	for(int i = 0;i < a.row;i++){
		Fraction t = a.base[i][j1];
		a.base[i][j1] = a.base[i][j2];
		a.base[i][j2] = t;
	}
	return;
}

void matrix_ccmul(matrix a,int j,Fraction C){
	//作用:j列乘上分數C
	if(!matrix_ifcol(a,j)){
		printf("錯誤:超出列數");
		exit(-1);
	} 
	for(int i = 0;i < a.row;i++){
		a.base[i][j] = fraction_mul(a.base[i][j],C);
	}
	return;
}

void matrix_ccadd(matrix a,int j1,Fraction C,int j2){
	//作用:j1列加C倍的j2列
	if(!matrix_ifcol(a,j1) || !matrix_ifcol(a,j2)){
		printf("錯誤:超出列數");
		exit(-1);
	} 
	for(int i = 0;i < a.row;i++){
		a.base[i][j1] = fraction_add(a.base[i][j1],fraction_mul(a.base[i][j2],C));
	}
	return;
}

對稱矩陣

\(A^T=A\)則稱矩陣\(A\)為對稱矩陣

\(AA^T\)一定也為對稱矩陣

逆矩陣

類似倒數概念,若\(AA^{-1}=I\)

那么\(A^{-1}\)就叫\(A\)的"逆矩陣"(或\(A\)\(A^{-1}\)的"逆矩陣")

形式上若\(A\)\(m×n\),那么\(A^{-1}\)\(n×m\)的,這樣才能得到單位矩陣

但為了更簡單地討論,在逆矩陣的定義中\(A\)\(A^{-1}\)必須是方陣

\(A\)不是方陣,那么\(A\)的逆被稱為廣義逆

從線性變換角度上相當於撤銷操作。比如用放縮矩陣進行了放縮,如果要將這個操作還原就要用到逆矩陣

奇異矩陣

(0沒有倒數,自然矩陣中也存在沒有逆的情況)

如果矩陣\(A\)是可逆的(有其逆矩陣),那么就稱\(A\)是非奇異矩陣(可逆矩陣)

如果矩陣\(A\)是不可逆的(沒有其逆矩陣),那么就稱\(A\)是奇異矩陣(不可逆矩陣)

逆矩陣性質

\(AA^{-1}=I_m\)

\((A^{-1})^{-1}=A\)

\((AB)^{-1}=B^{-1}A^{-1}\)

\((A^T)^{-1}=(A^{-1})^T\)

如果\(A\)是可逆矩陣,則滿足

\(A\)\(n\)個主元

\(Ax=0\)僅有平凡解

\(A\)的各個列向量是線性無關的

\(b∈R^n\),則矩陣方程\(Ax=b\)至少有一個解

\(A\)的各個列向量生成了空間\(R^n\)

\(A^T\)也是可逆的

⑦逆矩陣行/列等價於單位矩陣

⑧逆矩陣可以看成是原矩陣的逆向線性變換

求解逆矩陣

\(A^{-1}\)看作未知數,相當於求矩陣方程\(\begin{bmatrix} A&I \end{bmatrix}\)

然后左乘\(A^{-1}\),矩陣方程行等價於\(\begin{bmatrix}I&A^{-1} \end{bmatrix}\)

根據方程只需要將\(A\)通過行初等變換得到\(I\),同時\(I\)進行相同的變換就能得到逆矩陣

如果是用行向量的角度來看就是求解\(\begin{bmatrix}A \\ I \end{bmatrix}\)

現在來寫代碼求解

這里對之前的高斯消元法進行擴展,使得也能求得逆矩陣

#define all 0
#define left 1
#define right 2

typedef int mode;

void matrix_mode(matrix* r,int col,mode code){
	if(code == all){
		return;
	}else if(code == left){
		r->col -= col;
		return;
	}else if(code == right){
		matrix new;
		matrix_null(&new,r->row,r->col-col);
		for(int i = 0;i < new.row;i++){
			for(int j = 0;j < new.col;j++){
				new.base[i][j] = r->base[i][j+col];
			}
		}
		*r = new;
		return;
	}else{
		printf("錯誤:無效模式碼");
		exit(-1);
	}
}

bool matrix_REF_select(matrix a,int* posx,int* posy){
    //作用:REF算法的第一步——選擇主元
	int maxx = *posx;
	for(int i = *posx;i < a.row;i++){
		if(fraction_abscmp(a.base[maxx][*posy],a.base[i][*posy]) < 0)maxx = i;
	}
    if(a.base[maxx][*posy]->numerator == 0){
        return false;
    }
    matrix_rreplace(a,*posx,maxx);
    return true;
}

void matrix_REF_eliminate(matrix a,int* posx,int* posy){
	//作用:REF算法中的第二步——主元列除主元以外其他變為0
	for(int i = *posx+1;i < a.row;i++){
		matrix_rcadd(a,i,fraction_div(a.base[i][*posy],fraction_opposite(a.base[*posx][*posy])),*posx);
    }
    return;
}

bool matrix_REF_iterator(matrix a,bool ifsuccess,int* posx,int* posy){
    //作用:REF算法的最后一步——迭代,移動當前位置
	(ifsuccess == true) ? (*posx)++,(*posy)++ : (*posy)++ ;
    if(*posx >= a.row || *posy >= a.col-1)return false;
	else return true;
}

matrix matrix_REF(matrix a,matrix b,mode code){
    //作用:求增廣矩陣的階梯形矩陣
	matrix r = matrix_rowcombine(a,b);
	int posx = 0,posy = 0;
    bool flag;
	do{
        bool issuccess = matrix_REF_select(r,&posx,&posy);
        if(issuccess)matrix_REF_eliminate(r,&posx,&posy);
        flag =  matrix_REF_iterator(r,issuccess,&posx,&posy);
    }while(flag);
	matrix_mode(&r,a.col,code);
    return r;
}

void matrix_REFF_extra(matrix a,int* posx,int* posy){
	//REF算法額外的一步——當前主元變為1主元列其余元素化為0
    matrix_rmul(a,*posx,fraction_create(a.base[*posx][*posy]->denominator,a.base[*posx][*posy]->numerator));
    for(int i = (*posx)-1;i >= 0;i--){
    	matrix_rcadd(a,i,fraction_opposite(a.base[i][*posy]),*posx);
	}
}

matrix matrix_REFF(matrix a,matrix b,mode code){
    //作用:求增廣矩陣的簡化階梯形
	matrix r = matrix_rowcombine(a,b);
	int posx = 0,posy = 0;
    bool flag;
	do{
        bool issuccess = matrix_REF_select(r,&posx,&posy);
        if(issuccess){
			matrix_REF_eliminate(r,&posx,&posy);
			matrix_REFF_extra(r,&posx,&posy);
		}
        flag =  matrix_REF_iterator(r,issuccess,&posx,&posy);
    }while(flag);
	matrix_mode(&r,a.col,code);
    return r;
}
matrix matrix_inverse(matrix a){
	if(a.col != a.row){
		printf("錯誤:行列不匹配");
		exit(-1);
	}
	matrix i;
	matrix_identity(&i,a.row);
	return matrix_REFF(a,i,right);
}

初等矩陣E

初等矩陣是對單位矩陣進行一次初等變換的矩陣

初等矩陣用\(E\)表示

初等矩陣本身是初等變換得到的,但初等矩陣乘上某一矩陣\(A\)\(A\)也具有同樣的初等變換效果

比如\(E=\begin{bmatrix}1&0&0 \\ 0&1&0 \\ -4 &0&1 \end{bmatrix}\)\(EA\)則是\(A\)將第一行倍加至第三行,如果是\(AE\)則是將第三列倍加至第一列

這樣就有了對矩陣進行初等行/列變換的方法

①左乘\(E\)為初等行變換,右乘\(E\)為初等列變換

②初等矩陣或可逆矩陣進行有限次乘積也必然是非奇異矩陣

③任何一個非奇異矩陣可以拆解成有限次初等矩陣的乘積

\(A=E_pE_{p-1}...E_1\)

④初等矩陣的逆矩陣是一個同類型的初等矩陣

LU分解

LU分解常常用在稀疏矩陣中求解矩陣方程

LU分解是上面第三條的觀點

假設存在一個\(m×n\)的矩陣\(A\),那么存在等式

\((∏_iE_i)A=U\)\(U\)\(A\)行等價的階梯形)

\(E_i\)只能通過倍加變換得到的

那么\(A=(∏_iE_i)^{-1}U\)

其中\((∏_iE_i)^{-1}\)被稱為置換下三角矩陣,記作\(L\)

這種僅用倍加變換處理得到的\(LU\)就稱為LU分解

性質

\(A=LU\)

\(L\)\(min(m,n)×min(m,n)\)的方陣

\(L\)表明了一種行/列變換的一種過程

比如\(L=\begin{bmatrix}1&& \\ -2&1& \\ 1&-3&1 \end{bmatrix}\)從行變換角度來說可以將\(A\)依次進行變換\(row_2+2row_1 \\ row_3-row_1 \\ row_3+3row_2\)(之所以要加負號是因為\(U=L^{-1}A\)

滿足此\(L\)的矩陣有\(\begin{bmatrix}2&4&-1&5 \\ -4&-5&3&-8 \\ 2&-5&-4&1 \end{bmatrix}\)

依次進行變換后得到\(\begin{bmatrix}2&4&-1&5 \\ 0&3&1&2 \\ 0&0&0&2 \end{bmatrix}\)

可以發現正是一個階梯形\(U\)

病態矩陣

計算機計算時常常會出現微小誤差,如果一個矩陣因為微小誤差結果就出現了重大變化,就稱這類矩陣為病態矩陣。比如奇異矩陣可能因為誤差得到的是非奇異矩陣的結果,而一個非常接近奇異矩陣的非奇異矩陣可能因為誤差得到的是奇異矩陣的結果

分塊矩陣

之前一直是將實數看成矩陣的元素,當然矩陣也可以看成是一個元素

\(\left[\begin{array}{c|c|c} \begin{matrix}3&0&-1 \\ -5&2&4 \\ -8&-6&3 \end{matrix}& \begin{matrix}5&9 \\ 0&-3 \end{matrix} & \begin{matrix}-2 \\ 1 \end{matrix} \\ \hline \begin{matrix}-8&-6&3 \end{matrix} & \begin{matrix}1&7 \end{matrix} &-4 \end{array} \right]\)

抽象后為

\(\begin{bmatrix}A_{11}&A_{12}&A_{13} \\ A_{21}&A_{22}&A_{23} \end{bmatrix}\)

分塊矩陣的引入是為了更加系統地描述某一模型

比如可以分割稱\(2×3\)的系統,每一系統都有一定的參數

這常常用來將一些高階矩陣化為低階矩陣,然后解決

分塊矩陣運算

①加法、標量乘法

這和原來的一樣,只要保證\(A\)\(B\)維數一樣且分塊方式一樣,則可以進行加法、標量乘法。然后再分塊逐個計算

②矩陣乘法AB

除了保證A的列數與B的行數一致以外,還要保證分塊后A的列數和B的行數一致

\(A\)是列數為5,\(B\)的行數為5

則按照某種分塊方式

\(A\)分成了2列3列,那么\(B\)也要分成2行3行

\(A=\begin{bmatrix}A_{11}&A_{12} \\ A_{21}&A_{22} \end{bmatrix}\)\(B=\begin{bmatrix}B_1 \\ B_2 \end{bmatrix}\)

\(AB=\begin{bmatrix}A_{11}B_1+A_{12}B_2 \\ A_{21}B1+A_{22}B_2 \end{bmatrix}\)

依據分塊矩陣可以這樣定義矩陣乘法

\(row_i(A)\)\(A\)的第\(i\)行的分塊,\(col_i(A)\)為A的第\(i\)列的分塊

\(AB=\begin{bmatrix}col_1(A)&col_2(A)&...&col_n(A) \end{bmatrix} \begin{bmatrix}row_1(B) \\ row_2(B) \\ \vdots \\row_n(B) \end{bmatrix} =∑_i~col_i(A)row_i(B)\)

③轉置

分塊矩陣的逆運算,出了矩陣元素要轉置以外,本身的矩陣也要轉置

\(\begin{bmatrix}A_{11}&A_{12} \\ A_{21}&A_{22} \end{bmatrix}^T=\begin{bmatrix}(A_{11})^T&(A_{21})^T \\ (A_{12})^T&(A_{22})^T \end{bmatrix}\)

六、行列式

點擊查看詳細內容

意義(口胡)

行列式是一個多項式函數,用來描述當前維度的空間大小

\(det~~A\)\(|A|\)表示,其中\(A\)是當前空間的矩陣

當前空間大小如何度量?

顯然空間是無窮大的,但空間又是有大有小的(比如放縮矩陣)

於是用基向量平行后所圍成的圖像來度量空間大小

比如\(\begin{bmatrix}1&0 \\ 0&1 \end{bmatrix}\)其基向量是\(\begin{bmatrix}1 \\ 0 \end{bmatrix}\)\(\begin{bmatrix}0 \\ 1 \end{bmatrix}\)

在二維情況下是基向量平行后是平行四邊形,也就說平行四邊形的面積來描述當前空間的大小

\(det~\begin{bmatrix}1&0 \\0&1 \end{bmatrix}=1\)

在二維下行列式的公式比較簡單

\(det~\begin{bmatrix}a&b \\ c&d \end{bmatrix}=ad-bc\)

\(det~\begin{bmatrix}2&4 \\0&3 \end{bmatrix}=底×高=2×3=6\)

還有一種說法是行列式表示的是當前空間和原空間大小的比值。但原空間大小是1,當前空間大小和線性變換后的空間大小當然是一樣的,因此也行列式\(det\)也可以看成是一個空間進行線性變換后與原空間大小的比值

如果\(n\)階方陣\(A\)是非奇異矩陣,對於\(R^n\)內的\(∀b\),方程\(Ax=b\)只有唯一解

同時左乘\(A^{-1}\)

\(AA^{-1}x=A^{-1}b→x=A^{-1}b\)

當然如果一個矩陣方程是右乘\(xA=b\)

那么\(x=bA^{-1}\)

雖然能用逆矩陣求解方程組,但一般情況是直接用高斯消元法或分解

三階以下的行列式

\(det~[a] = a\)

\(det~\begin{bmatrix}a&b \\c&d \end{bmatrix}=ad-bc\)

\(det~\begin{bmatrix}a_{11}&a_{12}&a_{13} \\ a_{21}&a_{22}&a_{23} \\a_{31}&a_{32}&a_{33} \end{bmatrix}=a_{11}a_{22}a_{33}+a_{12}a_{23}a_{31}+a_{13}a_{21}a_{32}-a_{11}a_{23}a_{32}-a_{12}a_{21}a_{33}-a_{13}a_{22}a_{21}\)

可以將三階行列式化簡

$a_{11}a_{22}a_{33}+a_{12}a_{23}a_{31}+a_{13}a_{21}a_{32}-a_{11}a_{23}a_{32}-a_{12}a_{21}a_{33}-a_{13}a_{22}a_{21} \ $$=a_{11}(a_{22}a_{33}-a_{23}a_{32})-a_{12}(a_{21}a_{33})+a_{13}(a_{21}a_{32}-a_{22}a_{31})$

\(=a_{11}det~~\begin{bmatrix}a_{22}&a_{23} \\a_{32}&a_{33} \end{bmatrix}-a_{12}det~~\begin{bmatrix}a_{21}&a_{23} \\a_{31}&a_{33} \end{bmatrix}+a_{13}det~~\begin{bmatrix}a_{21}&a_{22} \\a_{31}&a_{32} \end{bmatrix}\)

進行抽象

\(=a_{11}det~~A_{11}-a_{12}det~~A_{12}+a_{13}det~~A_{13}\)

其中\(A_{ij}\)的行標列標和\(a_{ij}\)是一致的

而矩陣\(A_{ij}\)是划去\(i\)\(j\)列所剩下的矩陣

n階行列式

形式上將\(n\)階矩陣變成\((n-1)\)階矩陣

這是一個遞歸定義

\(det~~A=a_{11}det~~A_{11}-a_{12}det~~A_{12}+...+(-1)^{1+n}a_{1n}det~~A_{1n}\)

\(=∑_{j=1}^n(-1)^{1+j}a_{1j}det~~A_{1j}\)

\(A_{1j}\)也可以再次通過定義降一階,直到三階、二階這種熟悉地行列式時就能得到答案

用不太標准的程序算法就是

det(matrix A){
	//判斷基准情況
    int sum = 0;
    for(int i = 1;i <= n;i++){
        sum += (-1)^(1+i)a[1][i]det(A[1][i]);
    }
    return sum;
}
//不過這個算法實現

其中\(A_{ij}\)被稱為\(a_{ij}\)的余子式

其中\(C_{ij}=(-1)^{i+j}A_{ij}\)被稱為\(a_{ij}\)的代數余子式

行列式的展開有兩種,按行展開或按列展開

可以在任意列任意行展開

\(det~~A=∑_{j=1}^na_{ij}C_{ij}\)

\(det~~A=∑_{i=1}^na_{ij}C_{ij}\)

至於行列式某一項的正負號有兩種方法確定

①定義

②棋盤模式

代數余子式的正負取決於\(a_ij\)的位置,可以用一個棋盤來表示當前代數余子式的正負

\(\begin{bmatrix}+&-&+&... \\ -&+&-&\\ +&-&+& \\ \vdots&&& \ddots \end{bmatrix}\)

逆序數下行列式的定義

一組n個元素組成的有序數組被稱為n級排列

而在n級排列中如果一個數大於之后的一個數就稱為這兩個數構成逆序

逆序數是指一個n級排列中擬序的總數,用\(τ(i_1,i_2...i_n)\)表示

逆序數為奇數的排列稱為奇排列,逆序數為偶數的排列稱為偶排列

行列式的定義還可以寫成

\(det~~A=∑_{j_{1}...j_{n}}(-1)^{τ(j_{1}...j_{n})a_{1j_{1}}}a_{1j_{2}}...a_{1j_{n}}\)

逆序數還揭示了一點:n階行列式展開后項數有\(n!\)

這種定義雖然用到了逆序數,但在程序實現上要簡單不少,但實現上依然復雜,不采用這種定義實現

性質

①如果A是三角矩陣,那么\(det~~A\)為主對角線各個元素之積

②初等變換對\(det~~A\)的影響

倍加:\(det~~A_{倍加}=det~~A\)

倍乘:\(det~~A_{倍乘k}=k~det~~A\)

交換:\(det~~A_{某兩行/列交換}=-det~~A\)

③依據初等變換倍加、交換可以得到

\(det~~A=(-1)^rU\)

其中\(r\)為交換次數,\(U\)為階梯形

而一個階梯形又是上三角矩陣可以通過乘上對角線元素來求得

Fraction matrix_det(matrix a){
	//作用:求矩陣a的行列式
	if(a.col != a.row){
		printf("錯誤:行列不匹配");
		exit(-1);
	}
	int count = 0;
	int posx = 0,posy = 0;
	bool flag = true;
	while(flag){
		bool issuccess;
		{
			int maxx = posx;
			for(int i = posx;i < a.row;i++){
				if(fraction_abscmp(a.base[maxx][posy],a.base[i][posy]) < 0)maxx = i;
			}
			if(a.base[maxx][posy]->numerator == 0){
				issuccess = false;
			}else{
				issuccess = true;
			}
			if(maxx != posx){
				matrix_rreplace(a,posx,maxx);
				count++;
			}
		}
		if(issuccess){
			matrix_REF_eliminate(a,&posx,&posy);
		}
		flag =  matrix_REF_poschange(a,issuccess,&posx,&posy);
	}
	Fraction r;
	r = (count%2) ? fraction_create(-1,1) : fraction_create(1,1);
	for(int i = 0;i < a.row;i++){
		r  = fraction_mul(r,a.base[i][i]);
	}
	return r;
}

④若\(det~~A≠0\),則方陣\(A\)是非奇異矩陣矩陣

\(det~~A=0\),則方陣\(A\)是奇異矩陣

//求逆矩陣算法中可以增加這一條件
if(matrix_det(a) == 0){
		printf("錯誤:奇異矩陣");
		exit(-1);
}

\(det~~A^T=det~~A\)

\(det~~AB=det~~A.det~~B\)

(一般情況\(det~~(A+B)≠det~~A+det~~B\)

⑦線性性質

分為兩種,從列向量觀點來看,假設\(A\)中某一列為\(x\)

則存在函數\(T(x)=\begin{bmatrix}a_1&...&x&a_n \end{bmatrix}\)

滿足\(T(cx)=c~T(x)\)\(T(x+y)=T(x)+T(y)\)

對於行向量也是如此

⑧初等矩陣行列式性質

\(det~~E=\begin{cases}~~~1,E_{倍加} \\ -1,E_{交換} \\ ~~~k,E_{倍乘k} \end{cases}\)

\(det^{-1}~~A=det~~A^{-1}\)(可以從\(det~~I=det~~AA^{-1}\)得到)

\(det~~A^{k}=det^{k}~~A\)(包括\(k<0\)的情況)

\(det~~kA=k^ndet~~A\)

⑫若某一行/列元素相同,則\(det~~A=0\)

⑬若某一行/列與另一行/列成比例,則\(det~~A=0\)

范德蒙行列式(略)

形如\(det~~\begin{bmatrix}1&1&...&1 \\ x_1&x_2&...&x_n \\ \vdots & \vdots && \vdots \\ x_1^{n-1}&x_2^{n-1}&...&x_n^{n-1} \end{bmatrix}\)稱為n階范德蒙行列式

這里不做證明,結果為\(∏_{1≤j≤i≤n}(x_i-x_j)\)

余子式與代數余子式的性質(略)

因為\(C_{ij}=(-1)^{i+j}A_{ij}\),所以代數余子式和余子式之間可以相互轉換,最多差個負號

如果求某一矩陣的余子式相加或代數余子式相加,可以轉換成行列式

比如求\(A_{11}+2A_{12}+4A_{14}\)可以將矩陣\(A\)\(a_{11}\)\(a_{12}\)\(a_{14}\)元素改成1、2、4然后這個新矩陣的行列式就是\(A_{11}+2A_{12}+4A_{14}\)的結果

根據范德蒙行列式,還可以知道

\(a_{1i}A_{1j}+a_{2i}A_{2j}...+a_{ni}A_{nj}=0(i≠j)\)

\(a_{i1}A_{j1}+a_{i2}A_{j2}...+a_{ni}A_{nj}=0(i≠j)\)

克拉默法則

假設\(A=\begin{bmatrix}a_1&a_2&...&a_n \end{bmatrix}\)

那么定義

\(A_i(b)=A.I_i(x)=\begin{bmatrix}Ae_1&...&Ax&...Ae_n \end{bmatrix}\)

\(=\begin{bmatrix}a_1&a_2&...&b(位於i列)&...&a_n \end{bmatrix}\)

\(A_i(b)\)是將矩陣\(A\)\(i\)列替換為\(b\)

如果\(A\)是可逆的\(n\)階矩陣,那么矩陣方程\(Ax=b\)的解可以表示為

\(det~~A.det~~I_i(x)=det~~A_i(b)\)

\(I_i(x)=x_i=\frac{det~~A_i(b)}{det~~A}\)\(i=1,2...n\)

利用克拉默法則不考慮算法復雜度的情況下,邏輯上是要比高斯消元法還要簡單的一種求解線性方程組的方法

逆矩陣的公式

如果已知\(n\)階矩陣\(A\),求其逆矩陣本質上是解矩陣方程\(Ax=I_n\)

根據克拉默法則

可以求\(Ax=e_j\)\(j\)為單位矩陣第\(j\)

\(x_{ij}=\frac{det~~A_i(e_j)}{det~~A}\)求解的是第\(i\)行第\(j\)列的逆矩陣的元素

綜上\(A^{-1}=\begin{bmatrix}\frac{det~~A_1(e_1)}{det~~A}&\frac{det~~A_1(e_2)}{det~~A}&...&\frac{det~~A_1(e_n)}{det~~A} \\ \frac{det~~A_2(e_1)}{det~~A}&\frac{det~~A_2(e_2)}{det~~A}&...&\frac{det~~A_2(e_n)}{det~~A} \\ \vdots& \vdots&& \vdots \\ \frac{det~~A_n(e_1)}{det~~A}&\frac{det~~A_n(e_2)}{det~~A}&...&\frac{det~~A_n(e_n)}{det~~A} \end{bmatrix}\)

提取\(\frac{1}{det~~A}\)

\(A^{-1}=\frac{1}{det~~A} \begin{bmatrix}det~~A_1(e_1)&det~~A_1(e_2)&...&det~~A_1(e_n) \\ det~~A_2(e_1)&det~~A_2(e_2)&...&det~~A_2(e_n) \\ \vdots& \vdots&& \vdots \\ det~~A_n(e_1)&det~~A_n(e_2)&...&det~~A_n(e_n)\end{bmatrix}\)

現在處理\(det~~A_i(e_j)\),首先這個矩陣表示在第\(i\)列被\(e_j\)替換,而要知道\(e_j\)中只有第\(j\)個元素是1,其余是0。

因此矩陣在第\(i\)列中,除了\((j,i)\)為1以外,都為0

\(det~~A_i(e_j)=(-1)^{i+j}det~~A_{ji}=C_{ji}\)

因此\(A^{-1}=\frac{1}{det~~A}\begin{bmatrix}C_{11}&C_{21}&...&C_{n1} \\ C_{12}&C_{22}&...&C_{n2} \\ \vdots& \vdots && \vdots \\ C_{1n} & C_{2n} &...&C_{nn} \end{bmatrix}\)

而其中右邊的余因子矩陣的轉置被稱為\(A\)的伴隨矩陣,記作\(adj~~A\)

\(A^{-1}=\frac{1}{det~~A}adj~~A\)

這個公式儼然不適合計算,但作為理論揭示了一些內容(比如空間大小上,逆矩陣的行列式和矩陣的行列式成反比)

也說明判斷矩陣是否可逆關鍵看\(det~~A\)是否為0

【注:部分術語可能與其他材料不同,\(M_{ij}\)表示余子式,\(A_{ij}\)表示代數余子式,\(A^*\)表示伴隨矩陣】

反對角線行列式公式(口胡)

做題時發現的一個問題,除了課本中的公式,鄙人自行推出了另一個公式,程序中測試了1~5000階來驗證公式,未發現錯誤

有證明,但不嚴謹,這里就不說明了

大概思路:生成序列\(\{0,1,1,0,0,1,1,0,0,...\}\)

\(原公式:D=(-1)^{\frac{n(n-1)}{2}}∏_i λ_i\)

新公式:\(D=(-1)^{1-⌈\frac{n+1}{2}⌉ \% 2 }∏_i λ_i\)

等價公式1\(D=(-1)^{1-⌈\frac{n+1}{2}⌉ + (n+1)//2 }∏_i λ_i\)\(//\)表示整除)

和群友討論時,有人說\(\frac{n+1}{2}\)在計算機計算時會出現浮點數,有缺點,於是我稍微變換了一下

等價公式2:\(D=(-1)^{1-((n+1)//2+(n+1) \%2) \% 2 }∏_i λ_i\)

新公式最大的問題是形式復雜

但等價公式2解決了新公式的浮點數問題以及原公式的溢出問題

七、向量空間

點擊查看詳細內容 在線代中有一個相當重要的問題,那就是在空間上具有什么含義

行/列向量

\(n×1\)的矩陣來代表一個列向量,其中\(n\)表示這個列向量在空間的維數

比如\(\begin{bmatrix}1 \\ 2 \\ 3 \end{bmatrix}\)是表示在三維空間中\((1,2,3)\)的向量,當然默認始點在原點,那么這個列向量也可以代表是三維空間的一個點

從另外一個觀點來看,也可以用一個\(1×n\)的矩陣表示一個行向量

基於列向量的運算

①標量乘法

\(\vec u=\begin{bmatrix}u_1 \\... \\ u_n \end{bmatrix}\)

\(c\vec u=\begin{bmatrix}c.u_1 \\... \\ c.u_n \end{bmatrix}\)

②加法

\(\vec u=\begin{bmatrix}u_1 \\... \\ u_n \end{bmatrix}\)\(\vec v=\begin{bmatrix}v_1 \\... \\ v_n \end{bmatrix}\)

\(\vec u~ +~ \vec v = \begin{bmatrix}u_1+v_1 \\... \\ u_n+v_n \end{bmatrix}\)

③兩個向量的線性組合

\(\vec u=\begin{bmatrix}u_1 \\... \\ u_n \end{bmatrix}\)\(\vec v=\begin{bmatrix}v_1 \\... \\ v_n \end{bmatrix}\)

\(c_1.\vec u~ +~c_2. \vec v = \begin{bmatrix}c_1.u_1+c_2.v_1 \\... \\ c_1.u_n+c_2.v_n \end{bmatrix}\)

行向量也同理

線性組合與向量方程

通過線性組合得到的向量設為\(\vec y\)

這樣得到的一個方程稱為向量方程

\(c_1 \vec {v_1}+c_2 \vec {v_2}...+c_n \vec {v_n} = \vec y\)

其中\(c_i\)稱為權,\(\vec{v_i}\)為列向量,\(\vec y\)是通過線性組合后得到的新向量

其中這一組向量組成一個集合,記作\(β\),稱為向量集

\(R^n\)空間(略)

線代中的空間滿足三個性質

假設\(H⊆R^n\)

(1) \(0∈H\)

(2) \(u+v∈H\)

(3) \(Cu∈H\)

矩陣\(A\)各個列向量構成的空間稱為列空間,記作\(Col~~A={b~|~~b=Ax,x∈R^n}\)

矩陣\(A\)各個行向量構成的空間稱為行空間,記作\(Row~~A={b~|~~b=xA,x∈R^n}\)

\(Ax=0\)所有解的集合稱為\(A\)的零空間,記作\(Nul~~A={x~|~~Ax=0,x∈R^n}\)

假設向量集\(β\)線性無關,就稱\(β\)是線性無關集

向量集\(β\)生成的空間記作\(Span(β)\),稱為張成空間或生成空間

不同形式下的方程

這是線性方程組

\(\begin{cases}v_{00}c_1+v_{01}c_2...+v_{0n}c_n=y_0 \\ v_{10}c_1+v_{11}c_2...+v_{1n}c_n=y_1 \\... \\v_{n0}c_1+v_{n1}c_2...+v_{nn}c_n=y_n \end{cases}\)

這是增廣矩陣

\(\begin{bmatrix}v_{00}&v_{01}&...&v_{0n}&y_0 \\v_{10}&v_{11}&...&v_{1n}&y_1\\...&...&...&...&...\\v_{n0}&v_{n1}&...&v_{nn}&y_n \end{bmatrix}\)

這是向量方程

\(c_0 \vec {v_0}+c_1 \vec {v_1}...+c_n \vec {v_n}=∑_0^n c_i.\vec {v_i} = \vec y\)

這是矩陣方程

\(Ax=b\)

結論:線性方程組、增廣矩陣、向量方程、矩陣方程可以隨意轉換,這個結論是顯然的,是從不同角度或抽象而來的

齊次線性方程組

矩陣方程\(Ax=b\)中若\(b=\mathbf 0\)則稱這是齊次的,否則為非齊次的

(注:這里的\(\mathbf 0\)是表示一個零矩陣)

其中如果計算出來的解\(x=\mathbf 0\)則稱這個解是平凡解

結論

①若齊次線性方程組\(Ax=\mathbf 0\)有非平凡解,則這個方程至少有1個自由變量,即有無數解

②設矩陣\(A\)\(m×n\)的矩陣,則下列命題要么全滿足要么全不滿足

​ ■\(∀b\)\(R^m\)空間內的任意點,\(Ax=b\)一定相容

​ ■\(b\)可以看成是\(A\)各列向量的線性組合

​ ■由\(A\)各個列向量生成的\(R^m\)空間一定是\(n\)維空間

​ ■\(A\)每一行都有一個主元

③齊次線性方程組和非齊次線性方程組的關系:

設方程為\(Ax=b\),那么\(Ax=\mathbf 0\)的解僅僅是忽略了\(Ax=b\)解的常數項

(注:若Ax=b只有唯一解,則解都是常數項,則Ax=0的解忽略常數項后就是0)

③若\(v_1...v_p\)在空間\(V\)中,則\(Span(v_1...v_p)⊆V\)

線性相關性

假設存在向量集\(β\),若向量方程\(β_1x_1+β_2x_2...+β_nx_n=0\)存在非平凡解,則稱向量集\(β\)具有線性相關性

反之,若向量方程僅存在非平凡解,則稱向量集\(β\)具有線性無關性且稱\(β\)是線性無關集

而某一矩陣\(A\)從列/行向量角度來看就是向量集

①具有線性相關性的向量集存在\(v\)是其他向量的線性組合

②線性無關集\(β\)的張成空間\(H=Span(β)\)\(H\)恰好是\(|β|\)維的空間

③生成集定理

具有線性相關性的向量集\(α\)中如果去掉可以線性組合得到的向量,那么剩下的向量也就構成了線性無關集\(β\),張成空間\(H\)恰好是\(|β|\)維的。

那么去除的向量對於張成空間不做任何貢獻,可以認為是冗余的

\(H=Span(α)=Span(β)\)\(β⊆α\)

④從空間角度來說,某一空間\(H\)的一組基向量就是某一線性無關集

Nul A和Col A的性質

假設有一\(m×n\)的矩陣\(A\)

\(Nul~~A⊆R^n\)

\(Col~~A⊆R^m\)

\(|Nul~A|\)\(A\)自由變量個數

④若\(Nul~A={0}\)的充要條件是\(Ax=0\)僅有平凡解

⑤若\(Col~A=R^m\)的充要條件是\(Ax=b\)僅有唯一解

⑥對矩陣初等變換不影響矩陣的線性關系

假如存在一個\(m×n\)的矩陣\(A\),那么可以將\(A\)通過高斯消元變為\(U\)

然后根據\(U\)的自由變量數,即非主元的個數來得到$ |Nul~A|$

根據\(U\)的綁定變量數,即主元的個數來得到\(|Col~A|\)

同時\(U\)中非主元列全部去除即可得到\(A\)張成空間的基向量

⑦線性無關集\(β\)從生成空間角度來看,是一個"不大不小"的向量集。如果加入一個新向量很可能會使得\(β\)具有線性相關性或者使得空間新增一維,如果減少一個向量則會讓空間失去一維,無法得到原本空間

坐標系(略)

如果某空間\(H\)可以通過基\(β\)生成得到,那么這一基\(β\)各個向量也稱為坐標系的基向量

基是指線性無關集

①唯一表示定理:若有空間\(H\)的基\(β={b_1...b_n}\),則\(∀x∈H\)\(x=c_1b_1+...+c_nb_n\)(這個等式唯一)

其中\(\begin{bmatrix}c_1 \\ \vdots \\ c_n \end{bmatrix}\)記作\([x]_β\)稱為\(x\)\(β-\)坐標向量

\(x=[x]_β.β\)

維數(略)

維數的概念是從線性相關性、線性無關性推導得出的,一般情況在判斷維數時需要先判斷是否線性相關

在空間中維數表示相互獨立即線性無關的一組向量,顯然線性基\(β\)生成空間的維數為\(|β|\)

若空間\(H\)是由有限線性無關集生成的,則維數為有限維,記作\(dim~~H\)

若空間\(H\)是由無限線性無關集生成,則維數為無窮維

維數為\(n\)的空間被稱為\(n\)維空間

①若有\(n\)維空間\(H\)是由向量集\(β\)生成的,則滿足\(n≤|β|\)

推論:若\(|β|>n\),則\(β\)一定是線性相關的

\(n\)維空間所有可能的基的元素數也為\(n\)

③基定理:若有\(n\)維空間\(H\),則具有\(n\)個元素數的線性無關集一定是\(H\)的基

\(dim~~R^n=n\)

④若有限維空間\(H⊆V\),則\(dim~~H≤dim~~V\)

\(dim~~Nul~~A\)\(A\)中自由變量的個數

\(dim~~Col~~A\)\(A\)中主元列的個數

\(dim~~Row~~A\)\(A\)中非零行的個數

這里闡述了行空間、列空間、零空間的維數定義,而在下面秩的概念中將表明行空間、列空間、零空間維數之間的關系

\(m×n\)的矩陣\(A\)中從行空間和列空間兩種不同角度去考慮

\(A\)化簡為某一階梯形\(U\)

假設這個階梯形\(U\)形式上是這樣的\(\begin{bmatrix}■&※&※&※&※ \\ &■&※&※&※ \\ &&&■&※ \\ & \end{bmatrix}\)

那么這里列空間維數就是主元列個數(即主元個數)為3

行空間的基為\(\{\begin{bmatrix}■&※&※&※&※ \end{bmatrix},\begin{bmatrix}0&■&※&※&※ \end{bmatrix},\begin{bmatrix}0&0&0&■&※ \end{bmatrix}\}\)

行空間維數就是非零行個數(即主元個數)為3

列空間的基為\(\{\begin{bmatrix}■ \\ 0 \\ 0 \\ 0 \end{bmatrix},\begin{bmatrix}※ \\ ■ \\ 0 \\ 0 \end{bmatrix},\begin{bmatrix}※ \\ ※ \\ ■ \\ 0 \end{bmatrix}\}\)

可見列空間維數和行空間維數都取決於主元,因為主元所在列為主元列,主元所在行為非零行,所以能得出\(dim~~Col~~A=dim~~Row~~A\)

而這個主元數就稱之為秩數,用\(rank~~A\)表示

從定義上得出以下結論

\(rank~~A=dim~~Col~~A=dim~~Row~~A\)

\(dim~~Col~~A\)\(A\)主元個數即綁定變量個數

\(dim~~Row~~A\)\(A\)主元個數即綁定變量個數

④秩定理:\(dim~~Nul~~A+rank~~A=n\)

⑤秩定理推論:秩數就是矩陣的綁定變量數,零空間維數就是矩陣的自由變量數

秩的概念揭示了行空間、列空間、零空間之間維數的關系,這種關系我認為也是刻畫了矩陣方程\(Ax=b\)\(xA=b\)以及\(Ax=0\)的關系

int matrix_dim(matrix a,space code){
	/*code若為col,計算矩陣a列空間維數
	  code若為row,計算矩陣a行空間維數
	  code若為nul,計算矩陣a零空間維數
	  code若為rank,計算矩陣a秩數*/
	//bug:使用dim函數后a會變成階梯形
	int bind = 0;
	matrix r = a;

	int posx = 0,posy = 0;
    bool flag = true;
	while(flag){
        bool issuccess = matrix_REF_select(r,&posx,&posy);
        if(issuccess)matrix_REF_eliminate(r,&posx,&posy);
        (issuccess) ? posx++,posy++,bind++ : posy++;
    	if(posx >= r.row || posy > r.col-1)flag = false;
		else flag = true;
    }
	return (code == space_nul) ? r.col-bind : bind;
}

基本原理也是高斯消元,bind變量用來計數綁定變量數,然后利用秩定理可以求得零空間維數

但秩數同樣受到行數和列數限制,比如一個\(6×9\)的矩陣是不可能有2維零空間。

如果具有2維零空間,那么秩數就為7,但\(dim~~Row~~A\)因為行數限制是不可能超過6的,因此不具有2維零空間

注:一般情況而言,會將\(A\)的主元列作為\(Col~~A\)的基,會將\(U\)的非零行作為\(Row~~A\)的基

注:n維度不代表空間\(R^n\)

秩和逆矩陣

\(A\)\(n\)階逆矩陣,則滿足以下充要條件

\(Col~~A=R^n\)

\(rank~~A=n\)

\(dim~~Nul~~A=0\)

(部分和轉置相關定理由於課本並未給出,這里不會詳細說明)

\(rank~~A=rank~~A^T\)

\(Row~~A=Col~~A^T\)

\(rank~~A+dim~~Nul~~A^T=m\)

課本中對於秩的定義

課本中采用行列式進行定義

\(m×n\)的矩陣中任取\(k\)\(k\)列然后取出做\(det\)運算,這個就稱為\(A\)\(k\)階子式

存在\(A\)\(n\)階子式不為0,而所有\(n+1\)階子式為0,那么這個\(n\)就是\(A\)的秩數

形象點說就是在\(A\)\(k\)維下如果有不為0的,就代表A的列/行空間在當前\(k\)維里是能度量的,如果在\(k+1\)維下所有行列式都為0,那么就代表列/行空間在\(k+1\)維下是無法度量的(比如空間是一維的線,在二維里問線的面積是多少)那么這個\(k\)就是秩數了

從這個定義看,秩數是\(A\)能度量的最大維度

①若\(A\)的秩數為\(r\),那么\(r\)階子式就稱為\(A\)的最高階非零子式(不唯一)

\(m×n\)的矩陣\(A\),其行空間維數、列空間維數受行數、列數制約

\(\begin{cases}dim~~Col~~A ≤ m~~~∧~~~dim~~Col~~A ≤ n \\ dim~~Row~~A ≤ m~~~∧~~~dim~~Row~~A ≤ n \\ rank~~A ≤ m~~~∧~~~rank~~A ≤ n \end{cases}\)

\(m×n\)的矩陣\(A\)

\(rank~~A=m\),則\(A\)稱為行滿秩矩陣

\(rank~~A=n\),則\(A\)稱為列滿秩矩陣

若同時滿足上面兩點,即\(A\)為方陣且\(rank~~A=n\),則\(A\)稱為滿秩矩陣

\(A\)為方陣但\(rank~~A≠n\),則\(A\)稱為降秩矩陣

④根據逆矩陣和秩的定理,滿秩矩陣為非奇異矩陣,降秩矩陣為奇異矩陣

相關結論

①若\(A\)為非奇異矩陣,則\(det~~A≠0\),即\(rank~~A=n\)

②若\(A\)為奇異矩陣,則\(det~~A=0\),即\(rank~~A<n\)

\(rank~~cA=rank~~A\)

\(rank~~A=rank~~A^T\)

\(rank~~A+B≤rank~~A+rank~~B\)

\(max(rank~~A,rank~~B)≤rank~~[A,B]≤rank~~A+rank~~B\)

\(rank~~A+rank~~B-n≤rank~~AB≤min(rank~~A,rank~~B)\)

⑧存在矩陣方程\(Ax=b\)

\(rank~~A<rank~~[A,B]\),則矩陣方程不相容

\(rank~~A=rank=rank~~[A,B]\),則矩陣方程相容

\(rank~~A=rank~~[A,B]=n\),則矩陣方程有唯一解

\(rank~~A=rank~~[A,B]<n\),則矩陣方程有無數解

\(rank~~adj~~A=\begin{cases}n,rank~~A=n \\ 1,rank~~A=n-1 \\ 0,rank~~A<n-1 \end{cases}\)

向量與秩(略)

不管是列向量集還是行向量集都能組成一個矩陣,從而能得出向量和秩的關系

\(m\)\(n\)維向量,若\(m>n\),則向量集線性相關

②若向量集\(\{a_1,...a_m\}\)可由向量集\(\{b_1...b_n\}\)線性表出(線性組合)且\(m>n\)

則向量集\(\{a_1,...a_m\}\)線性相關

③若向量集\(\{a_1,...a_m\}\)可由向量集\(\{b_1...b_n\}\)線性表出且\(\{a_1,...a_m\}\)線性相關

​ 則\(m≤n\)

④極大無關組\(β\)\(β\)為向量組\(α\)的一部分且\(α\)可由\(β\)線性表出,則\(β\)稱為極大無關組

⑤極大無關組與原本向量組等價\(Span(α)=Span(β)\)

⑥同一向量組的極大無關組等價

⑦等價的極大無關組秩數一樣

⑧行秩即為行空間的維數,列秩即為列空間的維數。行秩等於列秩

齊次線性方程組的基礎解系(略)

將方程\(Ax=0\)化成向量集Ω,這個向量集就稱為是\(Ax=0\)的基礎解系

基變換

基變換也就是線性變換的原理

假設基\(β\),那么在\(β\)為基的情況\([x]_β\)\(β-\)坐標向量,滿足等式\(x=β[x]_β\)

假若現在要線性變換,將基從\(β\)變為\(c\),那么就要將\([x]_β\)變為\([x]_c\)

\([x]_c=[β[x]_β]_c=[[b_1]_c~[b_2]_c~...[b_n]_c][x]_β\)

其中\([[b_1]_c~[b_2]_c~...[b_n]_c]\)記為\(P_{c←β}\)

\([x]_c=P_{c←β}[x]_β\)

\((P_{c←β})^{-1}[x]_c=[x]_β\)\((P_{c←β})^{-1}=P_{β←c}\)

只要求出\(P_{c←β}\)就能得出\([x]_c\)

根據定義得出方程組\(\begin{cases}b_1=c[b_1]_c \\ b_2=c[b_2]_c \\ \dots \\ b_n=c[b_n]_c \end{cases}\)

這里以\(\{~[b_1]_c~~~...~~~[b_n]_c~\}\)為變量\(x\)\(cx=β\)\(x=c^{-1}β\)

\(P_{c←β}=x=c^{-1}β\)

因此\([x]_c=c^{-1}β[x]_β\)

比如某向量\(x\)通過左乘\(A\),得到\(Ax\)

這在基變換中相當於\(x\)左乘\(β^{-1}\),得到\([x]_β=β^{-1}x\)

如果要從\(Ax\)左乘B,得到\(BAx\)

這在基變換中相當於\(β^{-1}x\)左乘\(c^{-1}\),得到\([x]_c=c^{-1}[x]_β=c^{-1}β^{-1}x\)

在此例中\(A=β^{-1}\)\(B=c^{-1}\)

八、特征值、特征向量

點擊查看詳細內容 在之前線性變換描述了$x$和$Ax$之間的區別,從行列式描述大小區別,伴隨矩陣描述“方向”區別,空間描述基、坐標系的區別 #### 特征值、特征向量

若存在\(λ\)使\(Ax=λx\)\(A\)為方陣,\(x≠0\))成立

則稱\(λ\)\(A\)的特征值

\(x\)\(A\)對應於\(λ\)的特征向量

經變換可得\((A-λI)x=0\)

其中\(x\)解集為\(A-λI\)的零空間,這個空間也稱為\(A\)對應於\(λ\)的特征空間

(1)若特征方程成立,則方程存在非平凡解,即\(r(A-λI)<n\)\(det~~(A-λI)=0\)

(2)若\(A\)為三角矩陣,則\(λ\)為主對角線元素

(3)若\(A\)存在零特征值,則該矩陣為奇異矩陣,否則為非奇異矩陣

(4)矩陣的一組特征值構成的集合稱為譜,若譜中不同的特征值對應了任意一個特征向量,則這些特征向量構成的向量集\(V\)具有線性無關性

(5)\(A^kx=λ^kx\)

特征方程

\(det~~(A-λI)=0\)稱為特征方程

特征方程展開后稱為特征多項式,即\(det~~(A-λI)=∏(λ_i-λ)\)

根據特征方程求出的根也稱為特征根

特征根若存在\(x\)個相同的值,則稱為該特征值重數為\(x\),該特征根也稱為重根

若考慮重根、復數根,則\(n\)階矩陣有且僅有\(n\)個特征值

若已知某一特征根\(λ\),則求\((A-λI)x=0\)的基礎解系后便能求得特征向量

特征向量表明伸縮變換后方向固定的向量

(1)\(det~~(A-λI)=∏(λ_i-λ)\)

(2)\(det~~A=∏λ_i\)

(3)\(A^{-1}\)的特征值為\(λ^{-1}\),即\(A^{-1}x=λ^{-1}x\)

(4)\(A^T\)的特征值為\(λ\),即\(A^Tx=λx\)

(5)\(A^{k}\)的特征值為\(λ^{k}\),即\(A^{k}x=λ^{k}x\)

(6)\(λ_i\)所對應的特征空間維數小於等於其重數\(x\)

矩陣相似

若滿足\(A=PBP^{-1}\)\(P\)可逆),則稱\(A\)\(B\)相似

若矩陣相似滿足以下關系

(1)具有相同特征方程

(2)具有相同特征多項式

(3)具有相同行列式

(4)具有相同跡

(5)若\(A\),\(B\)相似,則\(kA\),\(kB\)相似

(6)若\(A\),\(B\)相似,則\(A^{-1}\),\(B^{-1}\)相似

對角化(譜分解)

若存在\(A=PDP^{-1}\)\(D\)為對角矩陣)

則稱\(A\)可對角化,從\(A\)\(PDP^{-1}\)的過程稱為對角化或譜分解

(1)對角化定理:\(n\)階矩陣\(A\)可對角化的充要條件是:\(A\)存在着一組具有線性無關性的\(n\)個特征向量

可推得其他充要條件:⇔所有相異特征值\(λ_i\)所對應特征空間的維數之和為\(n\)\(∑dim(A-λ_iI)=n\)

​ ⇔所有相異特征值\(λ_i\)特征空間的維數等於其重數\(x\)\(dim(A-λ_iI)=x\)

(2)\(A^k=PD^kP^{-1}\)

(3)具有\(n\)個不同特征值的\(n\)階矩陣一定可對角化

(4)\(n\)階對稱矩陣一定可對角化

對角化(譜分解)步驟

1.求出\(A\)的譜\(λ\)

2.根據不同特征值\(λ_i\)求出對應的線性無關的特征向量\(v_i\)

3.得出\(P=\begin{bmatrix}v_1&v_2&...&v_n \end{bmatrix}\)\(D=\begin{bmatrix}λ_1&& \\ &\ddots & \\ && λ_n \end{bmatrix}\)

其中\(v_i\)\(λ_i\)對應

九、正交性

點擊查看詳細內容 #### 范數(長度)

范數表明一個向量的大小

\(||u||\)表示

范數為1的向量稱為單位向量常用\(e\)表示

單位化是指將某個向量\(u\)經過運算得到單位向量,\(e_u=\frac{u}{||u||}\)

距離

表示兩向量之間的范數

\(dist(u,v)=||u-v||=\sqrt{||u-v||^2}=\sqrt{∑(u_i-v_i)^2}\)

內積

內積是向量與向量之間的一種運算,在原本向量空間中加上內積運算,這個空間九稱為內積空間

內積運算有這些寫法\(u.v\)\(<u,v>\)\([u,v]\)

滿足以下性質

(1)\(<u,v>=<v,u>\)

(2)\(<u+v,w>=<u,w>+<v,w>\)

(3)\(<cu,v>=c<u,v>\)

(4)\(<u,u>≥0\)\(<u,u>=0⇔u=0\)

(5)Cauchy–Schwarz不等式:\(|<u,v>|≤||u||+||v||\)

范數相關性質

(6)\(||u||=\sqrt{<u,u>}\)

(7)\(||u||^2=<u,u>\)

(8)\(||cu||=|c|.||u||\)

距離相關性質

(9)三角不等式:\(||u+v||≤||u||+||v||\)

(10)\(||u-v||=||u||.||v||.cos~~α\)\(cos~~α\)為兩向量的夾角)

向量的正交性

通俗來講,正交就是垂直

若滿足\(||u+v||=||u-v||\),即\(<u,v>=0\)那么就稱\(u\)\(v\)是相互正交的正交向量

記作\(u⊥ v\)

(1)零向量與任意向量正交

(2)勾股定理:\(||u+v||^2=||u||^2+||v||^2\)

空間的正交性

假設有空間W和空間V

其中在空間V的任意向量\(v_i\)若與空間W的任意向量\(w_j\)正交

那么就稱這兩個空間是正交的,其中的某一向量也與另一空間正交

空間與空間的正交記作\(V=W^⊥\)\(W=V^⊥\)\(V⊥W\)

向量與空間的正交性記作\(v_i⊥W\)

(1)\(Nul~~A=(Row~~A)^⊥\)

(2)\(Nul~~A^T=(Col~~A)^⊥\)

正交集

若集合\(V=\{v_1,v_2...v_n\}\)其中任意向量之間正交,則稱這個集合為正交集

(1)若\(V\)正交集,則\(V\)是線性無關集

(2)在正交集構成空間中的某一向量滿足

\(y=∑c_iy_i\)

那么可以求得\(c_i=\frac{<y,v_i>}{<v_i,v_i>}\),這個系數是\(V\)構成向量的一個權值,在后續也會用到

(3)假設\(y=αu+z\),其中\(u∈L\)\(z⊥L\)

\(⇒z=y-αu\)

\(∵z⊥u\)

\(∴<y-αu,u>=0\)

\(⇒α=\frac{<y,u>}{<u,u>}\)

其中\(αu\)記作\(Proj_L~y\)表示\(y\)在空間\(L\)上的正交投影

(值得注意的是正交投影只存在於空間\(L\)

那么可得\(Proj_L~y = \frac{<y,u>}{<u,u>} u\)

正交分解定理

和上述第三點性質類似,但推廣到了更抽象的空間

\(y=z_1+z_2\)\(z_1∈W\)\(z2⊥W\)

其中\(z2\)所在空間恰好是\(W^⊥\)

可以得知\(y\)存在於\(W\)空間和\(W^⊥\)空間

可以將\(y\)分解為\(z1∈W\)\(z2∈W^⊥\)

\(W\)\(W^⊥\)的設置是任意的

\(z1\)就稱為\(y\)\(W\)的投影

\(z1=∑ \frac{<y,u_i>}{<u_i,u_i>}u_i\)

\(∴y=Proj_W~y+z_2\)\(Proj_W~y⊥z_2\)

最佳逼近定理

\(||y-Proj_W~y||~<~||y-v||\)\(v∈W\)\(v≠Proj_W~y\)

最佳逼近定理表明已知空間\(W\),那么距離\(y\)最近的向量是\(Proj_W~y\)

(單位)正交基

單位化的正交基稱為單位正交基

滿足性質\(U^TU=I\)

\(\begin{bmatrix}u_1^T \\ \vdots \\ u_n^T \end{bmatrix} \begin{bmatrix}u_1&...&u_n \end{bmatrix}=\begin{bmatrix}u_1^Tu_1&...&u_1^Tu_n \\ \vdots & \ddots & \vdots \\ u_n^Tu_1 & ... &u_n^Tu_n \end{bmatrix}=I\)

\(u_i^Tu_j= \begin{cases}1,i=j \\ 0,i≠j \end{cases}\)

單位正交基在線性映射下依然保持范數、正交性

(1)\(||Ux||=||x||\)

(2)\(<Ux,Uy>=<x,y>\)

(3)\(<x,y>=0~~⇔~~<Ux,Uy>=0\)

(4)\(||U||=\sqrt{U^TU}=1\)

(5)正交矩陣\(U\)若為方陣,則行列均是正交的

(6)在正交基下,\(Proj_W~y=∑(<y,u_i>)u_i=UU^Ty\)

Gram-Schmidt正交化算法

已知線性無關集\(X=\{x_1,x_2...x_n\}\)是子空間\(W\)的基

可以通過以下步驟構造正交基\(V=\{v_1,v_2...v_n\}\)

(1)\(v_1=x_1\)\(W_1=Span(v_1)\)

(2)\(v_i=x_i-∑ \frac{<x_i,v_i>}{v_i,v_i}v_i\)\(W_i=Span(v_1...v_n)\)

可看作\(v_i=x_i-Proj_{W_{i-1}}~~x_i\)

\(x_i\)剔除\(W_{i-1}\)的空間分量

即可求出正交基

若需要單位正交基

還需要進行一步單位化

\(e_{v_i}=\frac{v_i}{||v_i||}\)

QR分解

\(A=QR\)\(A\)\(m×n\)矩陣)

\(Q\)是由\(Col~~A\)標准正交基形成的\(m×n\)矩陣

\(R\)\(n×n\)上三角可逆矩陣,主對角線元素均為正數

\(x_i=r_iv_i\)

\(r_i=\begin{bmatrix}r_{1i} \\ \vdots \\ r_{ii} \\ 0 \\ \vdots \\ 0 \end{bmatrix}\)

QR分解步驟

(1)求出正交矩陣\(Q\)

(2)\(R=Q^{-1}A=Q^TA\)求出\(R\)

十、二次型

點擊查看詳細內容

對稱矩陣

\(A\)為對稱矩陣,則不同特征空間之間的任意特征向量均是具有正交性

\(v_i⊥v-j\)\(v_i∈V_i\)\(v_j∈V_j\)

矩陣關系

相等關系:\(A=B\),不僅形式一樣,元素也要相同

等價關系:\(A=PBQ\),即通過任意次初等變換可得到則稱為等價

相似關系:\(A=P^{-1}BP\),即矩陣可逆

合同關系:\(A=C^TBC\),即實矩陣對稱

(1)具有合同關系的矩陣一定也具有相似關系、等價關系

(2)具有相似關系的矩陣一定也具有等價關系

(3)\(A\)可正交對角化的充要條件是:\(A\)是對稱矩陣

譜定理

\(A\)\(n\)階對稱矩陣,則

(1)\(A\)具有\(n\)個實特征值且一定重復

(2)每一特征空間維數等於其重數,即\(dim~~(A-λI)=x\)

(3)特征空間之間相互正交,即\(V_i⊥V_j\)

(4)可正交對角化

二次型矩陣

\(Q(x)=x^TAx\)\(A\)為對稱矩陣)稱為二次型

對稱矩陣\(A\)的元素\(a_ij\)表示二次型某一項為\(a_{ij}x_ix_j\)

若二次型展開中\(i≠j\),那么對應於對稱矩陣的\(a_{ij}\)也需要折半

主軸定理

主軸定理核心原理是變量代換

\(x=Py\)

\(x^TAx=y^T(P^{-1}AP)y\)

如果能將\(x^TAx\)變換為\(y^TDy\)就稱為二次型標准化

其中\(P\)稱為主軸

主軸的作用是將二次型原本非標准位置轉變為標准位置,即改變基向量將基向量變為\(I\)

二次型標准化步驟

(1)求解\(A\)的特征向量集\(P\)(線性無關且可逆)

(2)令\(x=Py\)求解\(y\)

(3)求得\(x^TAx=y^T(P^TAP)y=y^TDy\)\(D\)\(P\)相對應)

二次型類型

正定二次型:\(x≠0\)\(∀x~~~Q(x)>0\)

半正定二次型:\(∀x~~~Q(x)≥0\)

負定二次型:\(x≠0\)\(∀x~~~Q(x)>0\)

半負定二次型:\(∀x~~~Q(x)≤0\)

不定二次型:\(∃x~~~Q(x)>0~~~∨~~~Q(x)<0\)

判定定理:

\(A\)為對稱矩陣

\(Q(x)\)正定的充要條件是:\(A\)的特征值均為正數

\(Q(x)\)負定的充要條件是:\(A\)的特征值均為負數

\(Q(x)\)不定的充要條件是:\(A\)的特征值有正數也有負數

Last、實際應用

點擊查看詳細內容

①列向量標量乘法

假設列向量為要生產的一個商品\(\vec u=\begin{bmatrix}材料成本=0.8 \\ 人力成本=1.2 \\ 管理成本=0.5\end{bmatrix}\)

那么生產一百個商品成本為\(100\vec u=\begin{bmatrix}80\\120\\50 \end{bmatrix}\)

注:列向量可以設置不同參數表示某一個具象或抽象的東西,而標量乘法代表多個東西下的總參數

②構造線性模型:求解線性方程組

這個應用極其廣泛,大部分學科都需要求解線性方程組,這里就簡單列舉化學方程式配平

配平化學式\(KMnO_4+HCl→KCl+MnCl_2+Cl_2+H_2O\)

根據化學式的要求,首先系數必須是整數,要保證左右相等

用一列表示某一分子含有的元素數

\(\begin{bmatrix}K \\ Mn \\ O \\ H \\ Cl \end{bmatrix}\)

這個方程即為\(x_1 \begin{bmatrix}1\\1\\4\\0\\0 \end{bmatrix}+x_2 \begin{bmatrix}0\\0\\0\\1\\1 \end{bmatrix}=x_3 \begin{bmatrix}1\\0\\0\\0\\1 \end{bmatrix}+x_4 \begin{bmatrix}0\\1\\0\\0\\2 \end{bmatrix}+x_5 \begin{bmatrix}0\\0\\0\\0\\2 \end{bmatrix}+x_6 \begin{bmatrix}0\\0\\1\\2\\0 \end{bmatrix}\)

即為\(\begin{bmatrix}1&0&-1&0&0&0\\1&0&0&-1&0&0 \\ 4&0&0&0&0&-1 \\0&1&0&0&0&-2 \\ 0&1&-1&-2&-2&0 \end{bmatrix}\begin{bmatrix}x_1 \\x_2 \\x_3 \\x_4 \\ x_5 \\ x_6 \end{bmatrix} = \begin{bmatrix}0 \\ 0 \\ 0 \\ 0 \\ 0 \end{bmatrix}\)

然后求解增廣矩陣\(\begin{bmatrix}1&0&-1&0&0&0&0\\1&0&0&-1&0&0&0 \\ 4&0&0&0&0&-1&0 \\0&1&0&0&0&-2&0 \\ 0&1&-1&-2&-2&0&0 \end{bmatrix}\)即可

求出來為\(\begin{bmatrix}1&0&0&0&0&-\frac{1}{4}&0 \\ 0&1&0&0&0&-2&0 \\ 0&0&1&0&0&-\frac{1}{4}&0 \\0&0&0&1&0&-\frac{1}{4}&0 \\ 0&0&0&0&1&-\frac{5}{8}&0 \end{bmatrix}\)

\(\begin{cases}x_1 = -1/4 \\ x_2=-2 \\ x_3 = -1/4 \\ x_4 = -1/4 \\ x_5 = -5/8 \end{cases}\)

然后去掉分母和負數就能求得\(\begin{cases}x_1 = 2 \\ x_2=16 \\ x_3 = 2 \\ x_4 = 2 \\ x_5 = 5 \end{cases}\)

因此這個化學式配平后為\(2KMnO_4+16HCl→2KCl2MnCl_2+2Cl_2+5H_2O\)

在中學階段是憑感覺配平,現在可以很快速地用線性代數來配平

除了化學方程式配平以外,只要你能意識到當前所做的運算是在求解線性方程組就能用線性代數求解

在實際應用過程中需要注意以下特點

①需要注意每一行每一列所代表的實際含義,比如這里每一行代表不同元素數,每一列代表當前分子

②需要注意解的取值范圍,需要對結果進行適當變換,比如化學式配平只能取正整數

注:比較特殊的線性方程組是差分方程

③圖像學中的應用(略)

見第六節,三維很多變換我省略了,這些在網上是能找到的,這篇blog不側重圖像學的應用,因此省略了

④列昂惕夫投入產出模型(略)

假設經濟體系分為3個部門,x為產出,d為需求

消耗\部門 A B C
A 0.5 0.4 0.2
B 0.2 0.3 0.1
C 0.1 0.1 0.3

此表格為不同部門生產需要消耗其他部門資源的數量

這個表格用矩陣表示為C,稱為消耗矩陣

那么滿足等式\(x=Cx+d\)



參考教程

Geogebra:matrix 3D
Geogebra:Geometry of 2x2 Matrix Multiplication with Intro Questions

參考書籍

《線性代數及其應用(第三版)》,David C.Lay/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM