Eigen的安装和基础使用
环境配置
Eigen是一个C++的数值计算库,包含矩阵、矢量、数值求解以及相关的算法。在下载页面,选择latest release candidate版本中的zip 格式进行下载。
下载之后解压,然后配置vs工程的附加包含目录。右键项目名称->属性(快捷键Shift +F4 ),选择C/C++ ->常规 ,然后将Eigen的解压路径添入其中。
然后就可以在工程中直接引用头文件了。
初步认识
Eigen所封装的模型以及头文件如下表
#include<Eigen/ | 内容 | 说明 |
---|
Core> | Matrix , Array | 矩阵和矢量类 | Geometry> | Transform , Translation , Scalling
Rotation2D , 3D rotations | 控件变换算法 | LU> | Inverse , FullPivLU , PartialPivLU | 求逆,LU分解 | Cholesky> | LLT , LDLT | Cholesky分解 | Householder> | | Householder变换 | SVD> | JacobiSVD , BDCSVD | SVD分解 | QR> | HouseholderQR , ColPivHouseholderQR
FullPivHouseholderQR | QR分解 | Eigenvalues> | EigenSolver , ComplexEigenSolver
SelfAdjointEigenSolver | | Sparse> | SparseMatrix , SparsVector | | Dense> | 除了Sparse 之外的头文件 | | Eigen> | 包括所有头文件 | |
Eigen中的动态矩阵和向量非常好用,创建新的矩阵和向量的方法如下:
#include <iostream>
#include <Eigen/core>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
int main()
{
MatrixXd m = MatrixXd::Random(3, 3);
cout << "Random Matrix:" << endl << m << endl;
m = MatrixXd::Constant(3, 3, 1.2);
cout << "Constant Matrix:" << endl << m << endl;
VectorXd v(3);
v << 1, 2, 3;
cout << "Vector:" << v << endl;
RowVectorXd h(3);
h << 4, 5, 6;
cout << "RoeVector:" << h << endl;
}
其输出为
Random Matrix:
-0.997497 0.617481 -0.299417
0.127171 0.170019 0.791925
-0.613392 -0.0402539 0.64568
Constant Matrix:
1.2 1.2 1.2
1.2 1.2 1.2
1.2 1.2 1.2
Vector:1
2
3
RoeVector:4 5 6
除了Random 和Constant 之外,Eigen还提供了其他创建特殊矩阵的方法
MatrixXd:: | |
---|
Zero(m,n) | m×n的全0矩阵 | Ones(m,n) | m×n的全1矩阵 | Identity(m,n) | m×n单位矩阵 |
常用函数
Eigen中对运算符的重载非常符合直觉,矩阵、向量的+ 、- 、* 、/ 操作无需赘述,代表元素之间的运算。需要注意的是,点乘和叉乘分别由.dot() 和.cross() 来实现。例如M.dot(N) ,表示
M
?
N
M\cdot N
M?N;M.cross(N) 表示
M
×
N
M\times N
M×N。
对于矩阵M的转置、共轭、与共轭转置分别由M.transpose() 、M.conjugate() 、M.adioint() 来实现。
然而M=M.transpose() 这种表达式却报错了,提示abort() has been called 。如果想实现类似的功能,可以使用M.transposeInPlace() 、M.adiointInPlace() 来实现。
对于矩阵M,向量V,其常用函数如下所示
表达式 | 备注 |
---|
M.cwiseAbs() | M中每个元素变为其绝对值 | M.sqrt() | M中每个元素变为其平方根 | M.minCoeff() | 返回M最小值 | M.maxCoeff() | 返回M最大值 | M.sum() | 返回M中元素的和 | M.prod() | 返回M中所有元素的乘积 | M.trace() | 返回矩阵的迹 | V.squareNorm() | 返回V的平方和 | V.norm() | 返回V的2范数,即平方根 |
对单个元素的索引非常符合直觉,M(i,j) 表示矩阵M中第i行第j列元素的值。但是如果想实现类似Matlab中M(a:b,c:d) 这样的操作,其表达式为M.block<a,b>(i,j) ,表示从(i,j)位置开始,截取尺寸为
a
×
b
a\times b
a×b的矩阵。(注意我们默认索引从0开始)
这种写法比较方便理解,但为了形式上的方便,也可以写为M.block(i,j,a,b) 。
同样,我们也可以通过这种块操作进行赋值。
int main()
{
MatrixXd M = MatrixXd::Random(3, 5);
cout << "原始矩阵:" << endl << M << endl;
M.block<2, 2>(1, 1) = MatrixXd::Constant(2, 2, 0);
cout << "新矩阵" << endl << M << endl;
}
输出结果为:
原始矩阵:
-0.997497 0.617481 -0.299417 0.49321 0.421003
0.127171 0.170019 0.791925 -0.651784 0.0270699
-0.613392 -0.0402539 0.64568 0.717887 -0.39201
新矩阵
-0.997497 0.617481 -0.299417 0.49321 0.421003
0.127171 0 0 -0.651784 0.0270699
-0.613392 0 0 0.717887 -0.39201
对于行或者列这种经常用到的块,Eigen提供了方便的方法,例如M.Row(i) 即返回第i行;M.Col(j) 即返回第j列。此外还提供了边角上的特殊块的操作,由于不常用,这里就不写了。
对向量V来说,Eigen提供了三种截取方式
表达式 | 说明 |
---|
V.head(n) | 从头截取n个元素 | V.tail(n) | 从末尾截取n个元素 | V.segment(i,n) | 从第i个元素开始截取n个元素 |
|