原文:Eigen官網-Inplace matrix decompositions
從Eigen3.3開始,LU
、Cholesky
和QR分解
可以就地操作,即直接在給定的輸入矩陣內操作。當處理大型矩陣或可用內存非常有限(嵌入式系統)時,此功能特別有用。
爲此,必須使用Ref<>
矩陣類型實例化相應的分解類,並且必須使用輸入矩陣作爲參數構造分解對象。作爲一個例子,讓我們考慮一個局部旋轉的就地LU分解
。
#include <iostream>
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;
int main()
{
MatrixXd A(2,2);
A << 2, -1, 1, 3;
cout << "Here is the input matrix A before decomposition:\n" << A << endl;
//聲明inplace LU 對象 lu,並輸出此時矩陣A中的內容
//這裏,對象lu 計算L和U因子並將其存儲在由矩陣A所在的內存中。因此,A的係數在因子分解期間被破壞,並被L和U因子替換,因爲可以驗證:
PartialPivLU<Ref<MatrixXd> > lu(A);
cout << "Here is the input matrix A after decomposition:\n" << A << endl;
//輸出lu對象的L和U因子,可以發現,結果和矩陣A的結果一樣
cout << "Here is the matrix storing the L and U factors:\n" << lu.matrixLU() << endl;
//然後,可以像往常一樣使用lu對象,例如解決Ax=b問題:
//由於原始矩陣A的內容已經丟失,我們不得不聲明一個新的矩陣A0來驗證結果。
MatrixXd A0(2,2); A0 << 2, -1, 1, 3;
VectorXd b(2); b << 1, 2;
VectorXd x = lu.solve(b);
cout << "Residual: " << (A0 * x - b).norm() << endl;
// 輸出結果:Residual: 0
//由於內存在A和lu之間共享,修改矩陣A將使lu無效。通過修改A的內容並再次嘗試解決初始問題,可以很容易地驗證這一點:
A << 3, 4, -2, 1;
x = lu.solve(b);
cout << "Residual: " << (A0 * x - b).norm() << endl;
// 輸出結果:Residual: 15.8114
//如果要用修改後的A更新因子分解,必須像往常一樣調用compute方法:
A0 = A; // save A
lu.compute(A);
x = lu.solve(b);
cout << "Residual: " << (A0 * x - b).norm() << endl;
// 輸出結果:Residual: 0
//請注意,調用compute不會更改lu對象引用的內存。因此,如果使用與A不同的另一個矩陣A1調用計算方法,則不會修改A1的內容。這仍然是用於存儲矩陣A1的L和U因子的A的內容。這一點很容易驗證如下:
MatrixXd A1(2,2);
A1 << 5,-2,3,4;
lu.compute(A1);
cout << "Here is the input matrix A1 after decomposition:\n" << A1 << endl;
// 輸出結果: Here is the input matrix A1 after decomposition:
// 5 -2
// 3 4
//The matrix A1 is unchanged, and one can thus solve A1*x=b, and directly check the residual without any copy of A1:
x = lu.solve(b);
cout << "Residual: " << (A1 * x - b).norm() << endl;
// 輸出結果: Residual: 2.48253e-16
結果如下:
Here is the input matrix A before decomposition:
2 -1
1 3
Here is the input matrix A after decomposition:
2 -1
0.5 3.5
Here is the matrix storing the L and U factors:
2 -1
0.5 3.5
如下是支持inplace機制的矩陣分解:
- class LLT
- class LDLT
- class PartialPivLU
- class FullPivLU
- class HouseholderQR
- class ColPivHouseholderQR
- class FullPivHouseholderQR
- class CompleteOrthogonalDecomposition