Eigen 学习笔记(一)

2 篇文章 0 订阅

最近由于工作原因,所以需要学习使用 Eigen E i g e n ,顺便写一下学习笔记,方便你我他。

简介

简单的说, Eigen E i g e n 就是一个线性代数的 C++ C + + 库,它对矩阵( Matrix M a t r i x )和向量( Vector V e c t o r )等相关线性代数的运算操作进行了比较系统的实现。

注意:后文的示例代码中使用的变量名之间并无上下文关系,只是为了做一下简单的区分。

矩阵( Matrix M a t r i x

定义

矩阵模板函数中一共包含六个模板参数,前三个是比较常用的,分别表示矩阵元素的类型、行数、列数。在矩阵定义的时候可以使用 Dynamic D y n a m i c 来表示行或者列数未知。
ex: e x :

template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
class Eigen::Matrix< _Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols >

Eigen::Matrix<int, 3, 4> mat1;              //  3x4 的 int 类型的矩阵 mat1
Eigen::Matrix<double, 3, Dynamic> mat2;     //  3x? 的 double 类型的矩阵 mat2
Eigen::Matrix<float, Dynamic, 4> mat3;      //  ?x4 的 float 类型的矩阵 mat3
Eigen::Matrix<long, Dynamic, Dynamic> mat4; //  ?x? 的 long 类型的矩阵 mat4

类型

Eigen E i g e n typedef t y p e d e f 了很多矩阵的类型,通常命名为 Matrix M a t r i x 前缀加一个长度为 14 1 ∼ 4 的字符串 S S 的命名——MatrixS。其中 S S 可以用来判断该矩阵类型,数字 n 表示 n  n n   ∗   n n n 的范围是 24,字母 dfic d 、 f 、 i 、 c 表示 doublefloatintcomplex d o u b l e 、 f l o a t 、 i n t 、 c o m p l e x ,另外 X X 表示行或者列数未知的矩阵。
ex:

typedef Matrix<std::complex<double>, 2, 2> Eigen::Matrix2cd;            //  2x2 的 cd 类型的矩阵
typedef Matrix<double, 2, 2> Eigen::Matrix2d;                           //  2x2 的 d 类型的矩阵
typedef Matrix<std::complex<double>, 2, Dynamic> Eigen::Matrix2Xcd;     //  2x? 的 cd 类型的矩阵
typedef Matrix<std::complex<float>, Dynamic, 2> Eigen::MatrixX2cf;      //  ?x2 的 cf 类型的矩阵
typedef Matrix<std::complex<double>, Dynamic, Dynamic> Eigen::MatrixXcd;//  ?x? 的 cd 类型的矩阵
typedef Matrix<int, Dynamic, Dynamic> Eigen::MatrixXi;                  //  ?x? 的 i 类型的矩阵

存储

Eigen E i g e n 中矩阵默认均是列主序( Column Major C o l u m n   M a j o r ),如果想要改变 Eigen E i g e n 中矩阵的主序,就需要动用上述六个模板参数中的第四个参数(默认是 ColMajor C o l M a j o r )。
ex: e x :

Matrix<int, 5, 6, RowMajor> matRow; //  行主序的 5x6 的 int 类型矩阵

默认列主序是因为对于 Eigen E i g e n 来说这样运算会更快一些,但是对我们使用中并不需要特别在意存储的方式。

Ps. C++ C + + 中的二维数组默认的则是行主序( Row Major R o w   M a j o r )。

动态矩阵与静态矩阵

Eigen E i g e n 中可以用 Dynamic D y n a m i c 表示行或者列数未知,所以在定义一个矩阵时并不能确定矩阵的大小,只有在运行时才可以确定大小,然后进行动态分配,而静态矩阵则是在定义时便明确给定了行数以及列数,在编译时就可以分配好内存。

访问与赋值

C++ C + + 数组的操作不同的是, Eigen::Matrix E i g e n :: M a t r i x 是不能通过 [] [ ] 来访问赋值数据的,而是需要通过 () ( ) 。矩阵之间也可以通过 = = 来进行赋值(拷贝)。
ex:

x = mat(a, b);  //  获取到矩阵 mat 的 a 行 b 列的元素并赋值给 x
mat(b, a) = x;  //  将 x 赋值给矩阵 mat 的 b 行 a 列
mat1 = mat2;    //  将矩阵 mat2 赋值(拷贝)给矩阵 mat1

Ps. 通过 = = 进行矩阵之间的拷贝时,如果左右两侧矩阵尺寸不一样并且左侧矩阵为动态矩阵,那么会将左侧矩阵的尺寸修改为与右侧一致。

Eigen 中还重载了 << << <script type="math/tex" id="MathJax-Element-42"><<</script> 可以用来赋值矩阵,也可以用来 cout c o u t 输出矩阵。
ex: e x :

MatrixXf m(4, 4);   //  定义一个 4x4 的 float 类型的动态矩阵
m << 1, 2, 3, 4,
     5, 6, 7, 8,
     9, 10, 11, 12,
     13, 14, 15, 16;//  赋值
std::cout << m;     //  输出 m

Eigen E i g e n 矩阵还可以进行分块操作,通过成员函数 block() b l o c k ( ) 获取某一部分矩阵。
ex: e x :

mat = mat1.block(i, j, p, q);   //  从矩阵 mat1 的 i 行 j 列开始获取一个 p 行 q 列的子矩阵
mat = mat1.block<p, q>(i, j);   //  从矩阵 mat1 的 i 行 j 列开始获取一个 p 行 q 列的子矩阵(动态矩阵)

Eigen E i g e n 矩阵可以使用成员函数 row()col() r o w ( ) 、 c o l ( ) 来获取某一行或者某一列。
ex: e x :

mat = mat1.row(i);  //  获取 mat1 的第 i 行
mat = mat1.col(j);  //  获取 mat1 的第 j 列  

Eigen E i g e n 还提供了从边角开始提取子矩阵的方法。
ex: e x :

描述动态矩阵静态矩阵
左上角 pxq p x q mat.topLeftCorner(p,q) m a t . t o p L e f t C o r n e r ( p , q ) mat.topLeftCorner<p,q>() m a t . t o p L e f t C o r n e r < p , q > ( )
左下角 pxq p x q mat.bottomLeftCorner(p,q) m a t . b o t t o m L e f t C o r n e r ( p , q ) mat.bottomLeftCorner<p,q>() m a t . b o t t o m L e f t C o r n e r < p , q > ( )
右上角 pxq p x q mat.topRightCorner(p,q) m a t . t o p R i g h t C o r n e r ( p , q ) mat.topRightCorner<p,q>() m a t . t o p R i g h t C o r n e r < p , q > ( )
右下角 pxq p x q mat.bottomRightCorner(p,q) m a t . b o t t o m R i g h t C o r n e r ( p , q ) mat.bottomRightCorner<p,q>() m a t . b o t t o m R i g h t C o r n e r < p , q > ( )
p p mat.topRows(p) mat.topRows<p>() m a t . t o p R o w s < p > ( )
p p mat.bottomRows(p) mat.bottomRows<p>() m a t . b o t t o m R o w s < p > ( )
q q mat.leftCols(q) mat.leftCols<q>() m a t . l e f t C o l s < q > ( )
q q mat.rightCols(q) mat.rightCols<q>() m a t . r i g h t C o l s < q > ( )

Eigen E i g e n 矩阵其他分块操作还有 middleCols()middleRows() m i d d l e C o l s ( ) 、 m i d d l e R o w s ( ) 等可以了解一下。

Eigen E i g e n 矩阵还可以使用成员函数 fill() f i l l ( ) 进行统一赋值。
ex: e x :

mat.fill(n);    //  将 mat 的所有元素均赋值为 n

运算

Eigen E i g e n 重载了 +/+===/= + 、 − ( 减 ) 、 ∗ 、 / 、 − ( 负 ) 、 + = 、 − = 、 ∗ = 、 / =
ex: e x :

mat = mat1 + mat2;  //  +
mat = mat1 - mat2;  //  -(减)
mat = mat1 * mat2;  //  *
mat = mat1 * n;     //  *
mat = mat1 / n;     //  /
mat = -mat1;        //  -(负)
mat += mat1;        //  +=
mat -= mat1;        //  -=
mat *= mat1;        //  *=
mat *= n;           //  *=
mat /= n;           //  /=

对于 Matrix M a t r i x 的转置矩阵、共轭矩阵、伴随矩阵、对角矩阵可以通过成员函数 transpose()conjugate()adjoint()diagonal() t r a n s p o s e ( ) 、 c o n j u g a t e ( ) 、 a d j o i n t ( ) 、 d i a g o n a l ( ) 来获得,如果想要在原矩阵上进行转换,则需要通过成员函数 transposeInPlace()conjugateInPlace()adjointInPlace() t r a n s p o s e I n P l a c e ( ) 、 c o n j u g a t e I n P l a c e ( ) 、 a d j o i n t I n P l a c e ( )
ex: e x :

mat = mat1.transpose(); //  获取 mat1 的转置矩阵
mat = mat1.conjugate(); //  获取 mat1 的共轭矩阵
mat = mat1.adjoint();   //  获取 mat1 的伴随矩阵
mat = mat1.diagonal();  //  获取 mat1 的对角矩阵
mat1.transposeInPlace();//  mat1 转换为对应的转置矩阵
mat1.conjugateInPlace();//  mat1 转换为对应的共轭矩阵
mat1.adjointInPlace();  //  mat1 转换为对应的伴随矩阵
mat1.diagonalInPlace(); //  mat1 转换为对应的对角矩阵
mat1.transpose().colwise().reverse();   //  mat1 Rot90

特殊矩阵

Eigen E i g e n 提供了许多特殊矩阵的生成方法。
ex: e x :

mat = MatrixXd::Identity(rows, cols);   //  生成 rows x cols 的单位阵
mat.setIdentity(rows, cols);            //  将 mat 设置为 rows x cols 的单位阵
mat = MatrixXd::Zero(rows, cols);       //  生成 rows x cols 的零矩阵
mat.setZero(rows, cols);                //  将 mat 设置为 rows x cols 的零矩阵
mat = MatrixXd::Ones(rows, cols);       //  生成 rows x cols 的壹矩阵
mat.setOnes(rows, cols);                //  将 mat 设置为 rows x cols 的壹矩阵
mat = MatrixXd::Random(rows, cols);     //  生成 rows x cols 的随机矩阵
mat.setRandom(rows, cols);              //  将 mat 设置为 rows x cols 的随机矩阵

其他

当前矩阵的行数、列数、大小可以通过成员函数 rows()cols()size() r o w s ( ) 、 c o l s ( ) 、 s i z e ( ) 来获取。
ex: e x :

rows = mat.rows();  //  获取行数
cols = mat.cols();  //  获取列数
size = mat.size();  //  获取大小

动态矩阵可以通过成员函数 resize() r e s i z e ( ) 来进行修改大小,静态矩阵是不可以 resize() r e s i z e ( ) 的,并且动态矩阵 resize() r e s i z e ( ) 后元素不能保证不变。
ex: e x :

mat.resize(rows, cols); //  将动态矩阵 mat 大小尺寸修改为 rows x cols

向量( Vector V e c t o r

向量( Vector V e c t o r )本身就是一种特殊的矩阵,如果学会了 Matrix M a t r i x ,那么 Vector V e c t o r 的使用将会变得十分简单。

类型与存储

类似于矩阵的类型,不过前缀从 Matrix M a t r i x 改成 Vector V e c t o r
ex: e x :

typedef Matrix<std::complex<float>, 2, 1> Eigen::Vector2cf; //  cf 类型的 2 向量
typedef Matrix<int, 2, 1> Eigen::Vector2i;                  //  i 类型的 2 向量
typedef Matrix<double, 4, 1> Eigen::Vector4d;               //  d 类型的 4 向量
typedef Matrix<float, Dynamic, 1> Eigen::VectorXf;          //  f 类型的 ? 向量

上述的 Vector V e c t o r 默认的都是列向量,如果是行向量,在命名上则需要加上 Row R o w 前缀。
ex: e x :

typedef Matrix<float, 1, 2> Eigen::RowVector2f;                 //  f 类型的 2 向量(行向量)
typedef Matrix<std::complex<double>, 1, 4> Eigen::RowVector4cd; //  cd 类型的 4 向量(行向量)

动态向量与静态向量

这里类似于矩阵,动态的没有指定向量的尺寸,只有在运行时才会分配对应的内存,而静态的则一开始便定义好了大小,在编译时分配好内存。

访问与赋值

类似于 Matrix M a t r i x 的操作,不过向量也可以使用 [] [ ] ,另外向量对前四个元素的访问与赋值还可以通过成员函数 x()y()z()w() x ( ) 、 y ( ) 、 z ( ) 、 w ( ) 来操作。
ex: e x :

x = vec(n);     //  获取向量 vec 的第 n 个元素并赋值给 x
x = vec[n];
x = vec.x();    //  获取向量 vec 的第一个元素并赋值给 x
y = vec.y();    //  获取向量 vec 的第二个元素并赋值给 y
z = vec.z();    //  获取向量 vec 的第三个元素并赋值给 z
w = vec.w();    //  获取向量 vec 的第四个元素并赋值给 w
vec(n) = x;     //  将 x 赋值给 vec 的第 n 个元素

Eigen E i g e n 向量也提供了一些分块操作来获取子向量。
ex: e x :

描述静态向量动态向量
n n 个元素 vec.head(n) vec.head<n>() v e c . h e a d < n > ( )
n n 个元素 vec.tail(n) vec.tail<n>() v e c . t a i l < n > ( )
i i 开始取 n 个元素 vec.segment(i,n) v e c . s e g m e n t ( i , n ) vec.segment<n>(i) v e c . s e g m e n t < n > ( i )

运算

Eigen E i g e n 向量提供了 norm()squareNorm()dot()cross() n o r m ( ) 、 s q u a r e N o r m ( ) 、 d o t ( ) 、 c r o s s ( ) 等成员函数。
ex: e x :

x.norm()        //  norm(x)     Note that norm(R) doesn't work in Eigen.
x.squaredNorm()
x.dot(y)        //  dot(x, y)
x.cross(y)      //  cross(x, y) Requires #include <Eigen/Geometry>

其他

类似于 Matrix M a t r i x 的操作。
ex: e x :

size = vec.size();  //  获取 vec 的尺寸

参考

C++矩阵库 Eigen 快速入门
Eigen教程1-基础

  • 12
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值