Eigen —— 參考指南

機器人的運動規劃過程中會涉及大量的矩陣計算,而 EIGEN 庫對於矩陣計算而言,其意義不言而喻。所以最近學習了一下 EIGEN 庫的使用。並在此過程中記錄自己的感悟和理解。本篇通過Eigen庫的Quick reference guide來了解整個庫。

新學的知識,總喜歡自己動手整理一下,不知道是不是強迫症。整理完才發現,太長了,頭疼。

1. Eigen模塊和頭文件(Modules and Header files)

EIGEN庫其由核心模塊和若干附屬模塊構成,每一模塊都有對應的頭文件供編程引用。其文件組織結構列表如下:

模組 頭文件 說明
Core #include <Eigen/Core> 矩陣(Matrix)和數據(Array)類,並涉及基本的線性代數和數組操作
Geometry #include <Eigen/Geometry> 涉及變換、平移、縮放、2D和3D旋轉、四元數、角軸(AngleAxis)
LU #include <Eigen/LU> 逆運算、行列式、LU分解器 (FullPivLU, PartialPivLU)
Cholesky #include <Eigen/Cholesky> LLT and LDLT Cholesky 因式分解器
Householder #include <Eigen/Householder> Householder變換,也被其它線性代數模組所引用
SVD #include <Eigen/SVD> 基於最小二乘解算的SVD分解(JacobiSVD, BDCSVD)
QR #include <Eigen/QR> QR分解器 (HouseholderQR, ColPivHouseholderQR, FullPivHouseholderQR)
Eigenvalues #include <Eigen/Eigenvalues> 特徵值特徵向量分解(EigenSolver, SelfAdjointEigenSolver, ComplexEigenSolver)
Sparse #include <Eigen/Sparse> 稀疏矩陣存儲和相關基礎線性代數(SparseMatrix, SparseVector)
#include <Eigen/Dense> Includes Core, Geometry, LU, Cholesky, SVD, QR, and Eigenvalues header files
#include <Eigen/Eigen> Includes Dense and Sparse header files (整個EIGEN庫)

對於不涉及稀疏矩陣運算的,頭文件使用#include <Eigen/Dense>就可以滿足要求,或者直接包含整個EIGEN庫#include <Eigen/Eigen>,全面!任性!

2. 數組、矩陣和向量類型(Array, matrix and vector types)

Eigen庫提供了矩陣和向量兩種對象,都是由模版類進行表示的,矩陣用Matrix進行表示,而1維和2維數組則由模版類Array表示。Eigen庫提供的模版類形式如下:

typedef Matrix< Scalar, RowsAtCompileTime, ColsAtCompileTime, Options > MyMatrixType;
typedef Array< Scalar, RowsAtCompileTime, ColsAtCompileTime, Options >  MyArrayType;
  • Scalar :是數據結構中標量元素的類型,例如 float, double, bool, int 等,即在模版類定義自定義數據類型時,其內部的元素只能是標量。
  • RowsAtCompileTime:指定編譯時矩陣的行數,或用 Dynamic 參數,在運行時確定行數。
  • ColsAtCompileTime:指定矩陣的列數,或用 Dynamic 參數,在運行時確定行數。
  • Options:其值可以是 ColMajorRowMajor ,默認爲 ColMajor

以下組合方式都是有效的:爲了註釋明顯用%表示註釋。

Matrix<double, 6, Dynamic>                  % Dynamic number of columns (heap allocation)
Matrix<double, Dynamic, 2>                  % Dynamic number of rows (heap allocation)
Matrix<double, Dynamic, Dynamic, RowMajor>  % Fully dynamic, row major (heap allocation)
Matrix<double, 13, 3>                       % Fully fixed (usually allocated on stack)

以上代碼定義中,第一行定義的矩陣其行數是固定的,而列數是動態的,同理第二行定義。第三行則行列都是動態確定,最後一行則是指定了矩陣的固定行列數。這種方式,真是學到了。

而Eigen庫爲了使用上的方便,對常用的矩陣和數組類型進行了定義,如果不是個性化所需的數據類型,使用常用的已定義類型更加方便。矩陣類型中,已定義的有以下類型:

Matrix<float,Dynamic,Dynamic>   <=>   MatrixXf
Matrix<double,Dynamic,1>        <=>   VectorXd
Matrix<int,1,Dynamic>           <=>   RowVectorXi
Matrix<float,3,3>               <=>   Matrix3f
Matrix<float,4,1>               <=>   Vector4f

數組類型有以下已定義類型:

Array<float,Dynamic,Dynamic>    <=>   ArrayXXf
Array<double,Dynamic,1>         <=>   ArrayXd
Array<int,1,Dynamic>            <=>   RowArrayXi
Array<float,3,3>                <=>   Array33f
Array<float,4,1>                <=>   Array4f

<=> 後面表示定義的數據類型,就像double,float,int等一樣,可以在包含頭文件的代碼中直接使用。例如:

using namespace Eigen;
MatrixXf variable_1;
VectorXd variable_2;
Matrix3f variable_3;
Vector4f variable_4;
ArrayXXf variable_5;

Eigen::Array33f variable_6;

在使用時要加命名空間,如果不想直接使用命名空間,則需要在數據類型之前加上作用域說明,如以上代碼中的最後一行。同時矩陣和數組類型之間也有內在的轉換機制。如下示例代碼:

Array44f a1, a2;                  % 4 X 4 的二維數組
Matrix4f m1, m2;				  % 4 X 4 的矩陣
m1 = a1 * a2;                     % coeffwise product, 從數組到矩陣的隱式轉換
a1 = m1 * m2;                     % matrix product, 從矩陣到數組的隱式轉換
a2 = a1 + m1.array();             % 禁止混合數組和矩陣
m2 = a1.matrix() + m1;            % 如果需要混合運算,則需要顯式轉換
ArrayWrapper<Matrix4f> m1a(m1);   // m1a is an alias for m1.array(), they share the same coefficients
MatrixWrapper<Array44f> a1m(a1);

在以下的說明中,將使用*來強調特定對象的應用範圍和領域:
* linear algebra matrix and vector only
* array objects only

2.1 基本矩陣運算(Basic matrix manipulation)

2.1.1 構造函數

對象定義可以用以下方式,類會自動調用構造函數,構造類對象。

Vector4d  v1;
Array3i   v2(x, y, z);        % 以x,y,z爲元素構造類對象
Vector4d  v3(x, y, z, w);
Matrix4f  m1;
MatrixXf  m2;                 % 構造一個空對象

2.1.2 初始化

Eigen重載了<<運算符,可以直觀的用數據爲變量賦值,如下所示:

Vector3f  v1;     
v1 << x, y, z;                 % 將x,y,z按順利賦值給對應的位置

ArrayXf   v2(4);  
v2 << 1, 2, 3, 4;

Matrix3f  m1;   
m1 << 1, 2, 3,                 % 按行賦值給矩陣
	  4, 5, 6,
	  7, 8, 9;
	  
int rows=5, cols=5;
MatrixXf m(rows,cols);
m << (Matrix3f() << 1, 2, 3, 4, 5, 6, 7, 8, 9).finished(),       % 以塊的形式爲矩陣賦值
     MatrixXf::Zero(3,cols-3),
     MatrixXf::Zero(rows-3,3),
     MatrixXf::Identity(rows-3,cols-3);
cout << m;

輸出爲:
		1 2 3 0 0
		4 5 6 0 0
		7 8 9 0 0
		0 0 0 1 0
		0 0 0 0 1

2.1.3 運行時可獲取信息

使用類的優勢之一就是提供了大量的成員函數,可以獲取對象的信息,而Eigen中爲矩陣類對象提供了豐富的接口:

vector.size();             % 獲取向量的大小,即元素個數
vector.innerStride();      % 沿數據存儲的方向移動一個位置,內存中需要移動的位置數
vector.data();             % 獲取向量的數據

matrix.rows();             % 獲取矩陣的行數
matrix.cols();		       % 獲取矩陣的列數
matrix.innerSize();        % 按列存儲的矩陣返回其行數,接行存儲的矩陣返回其列數
matrix.outerSize();        % 按列存儲的矩陣返回其列數,按行存儲的矩陣返回其行數
matrix.innerStride();      % 返回內部實際存儲時相鄰元素之間的指針增量
matrix.outerStride();      % 返回按邏輯順序存儲時的指針增量
matrix.data();             % 獲取矩陣的數據指針

2.1.4 編譯時對象類型信息

ObjectType::Scalar              
ObjectType::RowsAtCompileTime
ObjectType::RealScalar          
ObjectType::ColsAtCompileTime
ObjectType::Index               
ObjectType::SizeAtCompileTime

2.1.5 調整大小

vector.resize(size);                         % 調整具有動態尺寸的向量大小
vector.resizeLike(other_vector);             % 按other_vector的尺寸調整具有動態尺寸的向量大小
vector.conservativeResize(size);
matrix.resize(nb_rows, nb_cols);             % 調整成具有指定行列數的矩陣
matrix.resize(Eigen::NoChange, nb_cols);	 % 只調整列
matrix.resize(nb_rows, Eigen::NoChange);	 % 只調整行
matrix.resizeLike(other_matrix);			 % 按other_matrix的大小調整矩陣
matrix.conservativeResize(nb_rows, nb_cols);

使用有風險,應用需要謹慎。

2.1.6 數據獲取

帶有範圍檢查的數據獲取方式如下:

vector(i)     vector.x()
vector[i]     vector.y()
              vector.z()
              vector.w()
matrix(i,j)

不帶有數據範圍檢查的獲取方式:

vector.coeff(i)
vector.coeffRef(i)
matrix.coeff(i,j)
matrix.coeffRef(i,j)

2.1.7 賦值/Copy

object = expression;
object_of_float = expression_of_double.cast<float>();

如果可能,左側爲動態矩陣時,會被自動調整爲與右側相同的維數形式。

2.2 預定義矩陣(Predefined Matrices)

2.2.1 固定維數的矩陣和向量

typedef {Matrix3f|Array33f} FixedXD;
FixedXD x;

x = FixedXD::Identity();				   % 構造一個單位陣臨時對象,並賦值給x
x = FixedXD::Zero();                       % 構造一個元素全是0的臨時對象,並賦值給x
x = FixedXD::Ones();					   % 構造一個元素全是1的臨時對象,並賦值給x
x = FixedXD::Constant(value);			   % 構造一個元素全是value的臨時對象,並賦值給x
x = FixedXD::Random();					   % 構造一個元素是隨機值的臨時對象,並賦值給x
x = FixedXD::LinSpaced(size, low, high);   % 構造一個元素數值在[low,high]區間的臨時對象,並賦值給x
 
x.setIdentity();						   % 設置對象爲單位陣
x.setZero();							   % 設置對象的元素值全爲0
x.setOnes();							   % 設置對象的元素值全爲1
x.setConstant(value);					   % 設置對象的元素值全爲 value
x.setRandom();						       % 設置對象的元素值爲隨機值
x.setLinSpaced(size, low, high);	       % 設置對象的元素數值在範圍區間內

Vector3f::UnitX() // 1 0 0
Vector3f::UnitY() // 0 1 0
Vector3f::UnitZ() // 0 0 1

2.2.2 動態維數的矩陣

與上面一部分類似:

typedef {MatrixXf|ArrayXXf} Dynamic2D;
Dynamic2D x;

x = Dynamic2D::Zero(rows, cols);
x = Dynamic2D::Ones(rows, cols);
x = Dynamic2D::Constant(rows, cols, value);
x = Dynamic2D::Random(rows, cols);
 
x.setZero(rows, cols);
x.setOnes(rows, cols);
x.setConstant(rows, cols, value);
x.setRandom(rows, cols);

x = Dynamic2D::Identity(rows, cols);
x.setIdentity(rows, cols);

2.2.3 動態維數的向量

與以上相比,多了個尺寸參數:

typedef {VectorXf|ArrayXf} Dynamic1D;
Dynamic1D x;
 
x = Dynamic1D::Zero(size);
x = Dynamic1D::Ones(size);
x = Dynamic1D::Constant(size, value);
x = Dynamic1D::Random(size);
x = Dynamic1D::LinSpaced(size, low, high);
 
x.setZero(size);
x.setOnes(size);
x.setConstant(size, value);
x.setRandom(size);
x.setLinSpaced(size, low, high);

VectorXf::Unit(size,i)
VectorXf::Unit(4,1) == Vector4f(0,1,0,0)
                    == Vector4f::UnitY()

2.3 映射外部數組(Mapping external arrays)

以下兩部分看官方給的例子,自己平時用得少。Map就是將數據以矩陣形式重新組織的過程。

2.3.1 連續存儲

float data[] = {1,2,3,4};
Map<Vector3f> v1(data);       // uses v1 as a Vector3f object
Map<ArrayXf>  v2(data,3);     // uses v2 as a ArrayXf object
Map<Array22f> m1(data);       // uses m1 as a Array22f object
Map<MatrixXf> m2(data,2,2);   // uses m2 as a MatrixXf object

2.3.2 strides的經典用法

float data[] = {1,2,3,4,5,6,7,8,9};
Map<VectorXf,0,InnerStride<2> >  v1(data,3);                      // = [1,3,5]
Map<VectorXf,0,InnerStride<> >   v2(data,3,InnerStride<>(3));     // = [1,4,7]
Map<MatrixXf,0,OuterStride<3> >  m2(data,2,3);                    // both lines     |1,4,7|
Map<MatrixXf,0,OuterStride<> >   m1(data,2,3,OuterStride<>(3));   // are equal to:  |2,5,8|

3. 算法運算符(Arithmetic Operators)

mat3 = mat1 + mat2;           mat3 += mat1;                              % 加
mat3 = mat1 - mat2;           mat3 -= mat1;                              % 減
mat3 = mat1 * s1;             mat3 *= s1;           mat3 = s1 * mat1;    % 數乘 scalar product
mat3 = mat1 / s1;             mat3 /= s1;
col2 = mat1 * col1;                                                      % 乘 matrix/vector products *
row2 = row1 * mat1;           row1 *= mat1;
mat3 = mat1 * mat2;           mat3 *= mat1; 

mat1 = mat2.transpose();      mat1.transposeInPlace();                   % 轉置   原地轉置
mat1.conjugate();														 % 共軛
mat1 = mat2.adjoint();        mat1.adjointInPlace();                     % 共軛轉置  原地共軛轉置
scalar = vec1.dot(vec2);                                                 % 點乘
scalar = col1.adjoint() * col2;
scalar = (col1.adjoint() * col2).value();                                % inner product *	
mat = col1 * col2.transpose();                                           % outer product *
scalar = vec1.norm();         scalar = vec1.squaredNorm();               % norm 
vec2 = vec1.normalized();     vec1.normalize(); // inplace               % normalization *
vec3 = vec1.cross(vec2);                                                 % 叉乘 *

mat1.sum();                                                              % 所有元素求和
mat1.prod();                                                             % 所有元素乘積
mat1.mean();                                                             % 所有元素求平均
mat1.trace();                                                            % 跡,對角元素的和

4. 係數、數組運算符(Coefficient-wise & Array operators)

除了以上提到的運算,Eigen庫還提供大量係數性運算和函數。大部分在數組相關的計算中都有其存在意義。以下算子在數組類對象之間可以使用,或通過 .array() 將向量和矩陣轉換爲數組類對象使用:

4.1 算法運算符(Arithmetic operators)

array1 * array2     array1 / array2     array1 *= array2    array1 /= array2
array1 + scalar     array1 - scalar     array1 += scalar    array1 -= scalar

4.2 比較運算符(Comparisons)

array1 < array2     array1 > array2     array1 < scalar     array1 > scalar
array1 <= array2    array1 >= array2    array1 <= scalar    array1 >= scalar
array1 == array2    array1 != array2    array1 == scalar    array1 != scalar
array1.min(array2)  array1.max(array2)  array1.min(scalar)  array1.max(scalar)

4.3 相關函數(Trigo, power, and misc functions and the STL-like variants)

array1.abs2()
array1.abs()                  abs(array1)
array1.sqrt()                 sqrt(array1)
array1.log()                  log(array1)
array1.log10()                log10(array1)
array1.exp()                  exp(array1)
array1.pow(array2)            pow(array1,array2)
array1.pow(scalar)            pow(array1,scalar)
                              pow(scalar,array2)
array1.square()
array1.cube()
array1.inverse()
 
array1.sin()                  sin(array1)
array1.cos()                  cos(array1)
array1.tan()                  tan(array1)
array1.asin()                 asin(array1)
array1.acos()                 acos(array1)
array1.atan()                 atan(array1)
array1.sinh()                 sinh(array1)
array1.cosh()                 cosh(array1)
array1.tanh()                 tanh(array1)
array1.arg()                  arg(array1)
 
array1.floor()                floor(array1)
array1.ceil()                 ceil(array1)
array1.round()                round(aray1)
 
array1.isFinite()             isfinite(array1)
array1.isInf()                isinf(array1)
array1.isNaN()                isnan(array1)

以下係數方面的函數對於所有的數據形式都適用 (matrices, vectors, and arrays), 對複數也有效:

Eigen's API	            STL-like APIs*	         Comments
mat1.real()             real(array1)             // read-write, no-op for real expressions
mat1.imag()             imag(array1)             // read-only for real, read-write for complexes
mat1.conjugate()        conj(array1)             // no-op for real expressions

通過cwise* 的方法一些運算可以方便的應用於矩陣和向量:

=============Matrix API * ==============

mat1.cwiseMin(mat2)         mat1.cwiseMin(scalar)
mat1.cwiseMax(mat2)         mat1.cwiseMax(scalar)
mat1.cwiseAbs2()
mat1.cwiseAbs()
mat1.cwiseSqrt()
mat1.cwiseInverse()
mat1.cwiseProduct(mat2)
mat1.cwiseQuotient(mat2)
mat1.cwiseEqual(mat2)       mat1.cwiseEqual(scalar)
mat1.cwiseNotEqual(mat2)

=============Via Array conversions=============
mat1.array().min(mat2.array())    mat1.array().min(scalar)
mat1.array().max(mat2.array())    mat1.array().max(scalar)
mat1.array().abs2()
mat1.array().abs()
mat1.array().sqrt()
mat1.array().inverse()
mat1.array() * mat2.array()
mat1.array() / mat2.array()
mat1.array() == mat2.array()      mat1.array() == scalar
mat1.array() != mat2.array()

以上兩種API的不同之處在於,矩陣類型的API返回矩陣類型的表達,而數組類型的API,返回的是數組結構的結果。 .array() 只是改變了可用的API和對數據的解釋,所以並沒有額外的消耗。

應用用戶自定義的程序通過使用 DenseBase::unaryExpr 和 std::ptr_fun (c++03), std::ref (c++11), or lambdas (c++11)來完成:

mat1.unaryExpr(std::ptr_fun(foo));
mat1.unaryExpr(std::ref(foo));
mat1.unaryExpr([](double x) { return foo(x); });

5. 簡化函數(Reductions)

Eigen 提供了若干簡化函數,例如: minCoeff() , maxCoeff() , sum() , prod() , trace() *, norm() *, squaredNorm() *, all() , and any() 。所有的函數操作都可以按照矩陣形式(matrix-wise), 列行式(column-wise) 或 行行式(row-wise)操作,例子如下:

      5 3 1
mat = 2 7 8
      9 4 6 
mat.minCoeff();             輸出: 1          % 求矩陣的最小元素

mat.colwise().minCoeff();   輸出: 2 3 1      % 求每列的最小元素,所以輸出爲行

mat.rowwise().minCoeff();   輸出:  1         % 求每行的最小元素,所以輸出爲列
                                   2
                                   4

特殊形式的minCoeff and maxCoeff ,也可以說是特殊應用形式

int i, j;
s = vector.minCoeff(&i);        // s == vector[i]
s = matrix.maxCoeff(&i, &j);    // s == matrix(i,j)

all()和any()函數的經典用法:

if((array1 > 0).all()) ...      // if all coefficients of array1 are greater than 0 ...
if((array1 < array2).any()) ... // if there exist a pair i,j such that array1(i,j) < array2(i,j) ...

6. 子矩陣(Sub-matrices)

矩陣或數組的行列讀寫訪問:

mat1.row(i) = mat2.col(j);
mat1.col(j1).swap(mat1.col(j2));

子向量的讀寫訪問:

|===========================|================================|=================================================|
|		 默認形式	        |     編譯時已知維數的優化形式      |                 Description                     |
|===========================|================================|=================================================|
|      vec1.head(n)         |       vec1.head<n>()           | the first n coeffs                              |
|      vec1.tail(n)         |       vec1.tail<n>()           | the last n coeffs                               |
|      vec1.segment(pos,n)  |       vec1.segment<n>(pos)     | the n coeffs in the range [pos : pos + n - 1]   |
|===========================|================================|=================================================|

子矩陣的讀寫訪問:

|===================================|=====================================|===========================================|
|		       默認形式	            |         編譯時已知維數的優化形式       |              Description                  |
|===================================|=====================================|===========================================|
| mat1.block(i,j,rows,cols)         | mat1.block<rows,cols>(i,j)          |(i,j)作爲起始位置的rows行和cols列的子矩陣  |
| mat1.topLeftCorner(rows,cols)     | mat1.topLeftCorner<rows,cols>()     | 以左上角爲起始位置的由rows和cols定義的子矩陣  |
| mat1.topRightCorner(rows,cols)    | mat1.topRightCorner<rows,cols>()    | 以右上角爲起始位置的由rows和cols定義的子矩陣  |
| mat1.bottomLeftCorner(rows,cols)  | mat1.bottomLeftCorner<rows,cols>()  | 以左下角爲起始位置的由rows和cols定義的子矩陣  |
| mat1.bottomRightCorner(rows,cols) | mat1.bottomRightCorner<rows,cols>() | 以右下角爲起始位置的由rows和cols定義的子矩陣  |
| mat1.topRows(rows)                | mat1.topRows<rows>()                | 由矩陣的前幾行構成的子矩陣                   |
| mat1.bottomRows(rows)             | mat1.bottomRows<rows>()             | 由矩陣的後幾行構成的子矩陣                   |
| mat1.leftCols(cols)               | mat1.leftCols<cols>()               | 由矩陣的前幾列構成的子矩陣                   |
| mat1.rightCols(cols)              | mat1.rightCols<cols>()              | 由矩陣的後幾列構成的子矩陣                   |
|===================================|=====================================|===========================================|

7. 其它操作(Miscellaneous operations)

7.1 倒置(Reverse)

向量或矩陣的行和列都可以進行倒置,如果說矩陣轉置是按左對角線進行的,那麼倒置則是沿右對角線進行(see DenseBase::reverse(), DenseBase::reverseInPlace(), VectorwiseOp::reverse())。

vec.reverse()           
mat.colwise().reverse()   
mat.rowwise().reverse()
vec.reverseInPlace()

7.2 複製(Replicate)

向量或矩陣的行和列可以在任意方向上進行復制:

vec.replicate(times)                                          vec.replicate<Times>
mat.replicate(vertical_times, horizontal_times)               mat.replicate<VerticalTimes, HorizontalTimes>()
mat.colwise().replicate(vertical_times, horizontal_times)     mat.colwise().replicate<VerticalTimes, HorizontalTimes>()
mat.rowwise().replicate(vertical_times, horizontal_times)     mat.rowwise().replicate<VerticalTimes, HorizontalTimes>()

8. 對角矩陣、三角矩陣和伴隨矩陣(Diagonal, Triangular, and Self-adjoint matrices)

本部分的操作和運算只適用於矩陣:

8.1 對角矩陣(Diagonal matrices)

8.1.1 將向量作爲對角矩陣顯示

mat1 = vec1.asDiagonal();

返回一個以向量元素作爲對角矩陣對角元素的僞對角矩陣。這個操作只適用於向量,行向量或列向量都可以。例如通過以下代碼可明白其使用方式:

cout << Matrix3i(Vector3i(2,5,6).asDiagonal()) << endl;

輸出爲:   
      2 0 0
	  0 5 0
	  0 0 6

8.1.2 聲明一個對象矩陣

DiagonalMatrix<Scalar,SizeAtCompileTime> diag1(size);
diag1.diagonal() = vector;

8.1.3 以向量形式讀寫對角元素

vec1 = mat1.diagonal();        mat1.diagonal() = vec1;      // main diagonal
vec1 = mat1.diagonal(+n);      mat1.diagonal(+n) = vec1;    // n-th super diagonal
vec1 = mat1.diagonal(-n);      mat1.diagonal(-n) = vec1;    // n-th sub diagonal
vec1 = mat1.diagonal<1>();     mat1.diagonal<1>() = vec1;   // first super diagonal
vec1 = mat1.diagonal<-2>();    mat1.diagonal<-2>() = vec1;  // second sub diagonal

8.1.4 優化的乘積和倒數

mat3  = scalar * diag1 * mat1;
mat3 += scalar * mat1 * vec1.asDiagonal();
mat3 = vec1.asDiagonal().inverse() * mat1
mat3 = mat1 * diag1.inverse()

8.2 三角形視圖(Triangular views)

Triangular views給出了矩陣的三角形視圖,並且允許執行優化的操作,而另一三角部分將不會被訪問,可以用來存儲其它數據。詳細信息需要參考The template and typename keywords in C++

8.2.1 帶參引用

m.triangularView<Xxx>()

Xxx參數可以是以下幾種:
Xxx = Upper, Lower, StrictlyUpper, StrictlyLower, UnitUpper, UnitLower

8.2.2 向三角部分寫數據

m1.triangularView<Eigen::Lower>() = m2 + m3 

轉換成矩陣,並將另一部分設置爲0:

m2 = m1.triangularView<Eigen::UnitUpper>()

8.2.3 乘法

m3 += s1 * m1.adjoint().triangularView<Eigen::UnitUpper>() * m2
m3 -= s1 * m2.conjugate() * m1.adjoint().triangularView<Eigen::Lower>()

8.2.4 解方程

分別對應以下方程:
M2:=L11M2M_2 := L_1^{-1} M_2
M3:=L11M3M_3 := {L_1^*}^{-1} M_3
M4:=M4U11M_4 := M_4 U_1^{-1}

L1.triangularView<Eigen::UnitLower>().solveInPlace(M2)
L1.triangularView<Eigen::Lower>().adjoint().solveInPlace(M3)
U1.triangularView<Eigen::Upper>().solveInPlace<OnTheRight>(M4)

8.3 對稱/伴隨矩陣(Symmetric/selfadjoint views)

就像三角矩陣一樣,可以引用方矩陣的任何三角形部分以將其視爲自伴矩陣並執行特殊的優化操作。 同樣,相對的三角形部分不會引用,可用於存儲其他信息。

Conversion to a dense matrix:
m2 = m.selfadjointView<Eigen::Lower>();       
                                
Product with another general matrix or vector:
m3  = s1 * m1.conjugate().selfadjointView<Eigen::Upper>() * m3;    
m3 -= s1 * m3.adjoint() * m1.selfadjointView<Eigen::Lower>();

Rank 1 and rank K update:
upper(M1)+=s1M2M2upper(M_1) \mathrel{{+}{=}} s_1 M_2 M_2^*
lower(M1)=M2M2lower(M_1) \mathbin{{-}{=}} M_2^* M_2

M1.selfadjointView<Eigen::Upper>().rankUpdate(M2,s1);  
M1.selfadjointView<Eigen::Lower>().rankUpdate(M2.adjoint(),-1); 

Rank 2 update: M+=suv+svuM \mathrel{{+}{=}} s u v^* + s v u^*

M.selfadjointView<Eigen::Upper>().rankUpdate(u,v,s);  

解線性方程: M2:=M11M2M_2 := M_1^{-1} M_2

// via a standard Cholesky factorization
m2 = m1.selfadjointView<Eigen::Upper>().llt().solve(m2);
// via a Cholesky factorization with pivoting
m2 = m1.selfadjointView<Eigen::Lower>().ldlt().solve(m2);

9. 參考資料

[1] Eigen Quick reference guide
[2] Eigen: C++開源矩陣計算工具——Eigen的簡單用法
[3] Eigen矩陣庫使用說明
[4] Eigen矩陣運算開源庫使用完全指南
[5] Eigen介紹及簡單使用
[6] C++矩陣庫 Eigen 簡介
[7] Eigen庫使用指南

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章