使用Eigen求解線性方程組
一. 矩陣分解:
矩陣分解 (decomposition, factorization)是將矩陣拆解為數個矩陣的乘積,可分為三角分解、滿秩分解、QR分解、Jordan分解和SVD(奇異值)分解等,常見的有三種:1)三角分解法 (Triangular Factorization),2)QR 分解法 (QR Factorization),3)奇異值分解法 (Singular Value Decompostion)。
1. LU三角分解:
三角分解法是將原正方 (square) 矩陣分解成一個上三角形矩陣 或是排列(permuted) 的上三角形矩陣和一個 下三角形矩陣,這樣的分解法又稱為LU分解法。它的用途主要在簡化一個大矩陣的行列式值的計算過程,求 反矩陣,和求解聯立方程組。不過要注意這種分解法所得到的上下三角形矩陣並非唯一,還可找到數個不同 的一對上下三角形矩陣,此兩三角形矩陣相乘也會得到原矩陣。
MATLAB以lu函數來執行lu分解法, 其語法為[L,U]=lu(A)。
2. QR分解:
QR分解法是將矩陣分解成一個正規正交矩陣與上三角形矩陣,所以稱為QR分解法,與此正規正交矩陣的通用符號Q有關。
MATLAB以qr函數來執行QR分解法, 其語法為[Q,R]=qr(A)。
3. 奇異值分解:
奇異值分解 (singular value decomposition,SVD) 是另一種正交矩陣分解法;SVD是最可靠的分解法,但是它比QR 分解法要花上近十倍的計算時間。[U,S,V]=svd(A),其中U和V分別代表兩個正交矩陣,而S代表一對角矩陣。 和QR分解法相同, 原矩陣A不必為正方矩陣。使用SVD分解法的用途是解最小平方誤差法和數據壓縮。
MATLAB以svd函數來執行svd分解法, 其語法為[S,V,D]=svd(A)。
4. LLT分解:
A=LL^T
Cholesky 分解是把一個對稱正定的矩陣表示成一個下三角矩陣L和其轉置的乘積的分解。它要求矩陣的所有特征值必須大於零,故分解的下三角的對角元也是大於零的(LU三角分解法的變形)。
5. LDLT分解法:
若A為一對稱矩陣且其任意一k階主子陣均不為零,則A有如下惟一的分解形式:
A=LDL^T
其中L為一下三角形單位矩陣(即主對角線元素皆為1),D為一對角矩陣(只在主對角線上有元素,其余皆為零),L^T為L的轉置矩陣。
LDLT分解法實際上是Cholesky分解法的改進,因為Cholesky分解法雖然不需要選主元,但其運算過程中涉及到開方問題,而LDLT分解法則避免了這一問題,可用於求解線性方程組。
二. 代碼使用:
1 <span style="font-size:18px;">#include <iostream> 2 #include <Eigen/Dense> 3 4 using namespace std; 5 using namespace Eigen; 6 7 int main() 8 { 9 //線性方程求解 Ax =B; 10 Matrix4d A; 11 A << 2,-1,-1,1, 12 1,1,-2,1, 13 4,-6,2,-2, 14 3,6,-9,7; 15 Vector4d B(2,4,4,9); 16 Vector4d x = A.colPivHouseholderQr().solve(B); 17 Vector4d x2 = A.llt().solve(B); 18 Vector4d x3 = A.ldlt().solve(B); 19 std::cout << "The solution is:\n" << x <<"\n\n"<<x2<<"\n\n"<<x3 <<std::endl; 20 }</span>
除了colPivHouseholderQr、LLT、LDLT,還有以下的函數可以求解線性方程組,請注意精度和速度:解小矩陣(4*4)基本沒有速度差別
1 // Solve Ax = b. Result stored in x. Matlab: x = A \ b. 2 x = A.ldlt().solve(b)); // A sym. p.s.d. #include <Eigen/Cholesky> 3 x = A.llt().solve(b)); // A sym. p.d. #include <Eigen/Cholesky> 4 x = A.lu().solve(b)); // Stable and fast. #include <Eigen/LU> 5 x = A.qr().solve(b)); // No pivoting. #include <Eigen/QR> 6 x = A.svd().solve(b)); // Stable, slowest. #include <Eigen/SVD> 7 // .ldlt() -> .matrixL() and .matrixD() 8 // .llt() -> .matrixL() 9 // .lu() -> .matrixL() and .matrixU() 10 // .qr() -> .matrixQ() and .matrixR() 11 // .svd() -> .matrixU(), .singularValues(), and .matrixV()