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); //初始化3X3的随机动态矩阵
cout << "Random Matrix:" << endl << m << endl;
m = MatrixXd::Constant(3, 3, 1.2); //3X3的矩阵,每个值都是1.2
cout << "Constant Matrix:" << endl << m << endl;
VectorXd v(3); //创建矩阵v
v << 1, 2, 3; //设置v的值
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个元素 |