博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c++矩阵运算库Eigen简介
阅读量:5976 次
发布时间:2019-06-20

本文共 8244 字,大约阅读时间需要 27 分钟。

C++矩阵运算库Eigen介绍

C++中的矩阵运算库常用的有Armadillo,Eigen,OpenCV,ViennaCL,PETSc等。我自己在网上搜了一下不同运算库的特点,最后选择了Eigen。主要原因是Eigen体积较小,不用安装也不用编译,库是以头文件的形式给出,直接将它扔到我们自己的工程文件中即可,移植起来也无压力。我们可以在下载源文件。

Eigen的HelloWorld

我这里使用的Eigen的版本为Eigen 3.3.3,源文件目录如下:

Eigen文件目录

可以直接用记事本打开INSTALL文件,里面有编译和不编译时分别怎么使用。我这里使用的方法是不对文件进行编译。

  1. 找个地方新建一个工程目录,这里我在桌面上新建一个MatrixTest文件夹。
  2. 将Eigen目录中的Eigen文件夹拷贝到我们的MatrixTest目录中。
  3. 在MatrixTest中再建立一个main.cpp文件写入如下代码:
#include 
#include "Eigen\Core"//import most common Eigen typesusing namespace Eigen;int main(int,char*[]){ Matrix3f m3; m3<<1,2,3,4,5,6,7,8,9; Matrix4f m4 = Matrix4f::Identity(); Vector4i v4(1,2,3,4); std::cout<<"m3\n"<
<<"\nm4:\n" <
<<"\nv4:\n"<
<
  1. 在MatrixTest目录的地址栏中输入cmd,然后用g++ main.cpp对文件进行编译,再运行命令a。可以看到我们已经输出了我们的矩阵了。

HelloMatrix

Eigen常规矩阵定义

Eigen的使用在官网上有详细的介绍,这里对我学习过程中用到的基本操作进行介绍。首先是矩阵的定义。

在矩阵类的模板参数共有6个。一般情况下我们只需要关注前三个参数即可。前三个模板参数如下所示:

Matrix
  1. Scalar参数为矩阵元素的类型,该参数可以是int,float,double等。
  2. RowsAtCompileTime和ColsAtCompileTime是矩阵的行数和列数。

Matrix<float,4,4> M44是定义一个4×4的矩阵,矩阵元素以float类型存储。直接使用矩阵模板定义一个矩阵往往会觉得麻烦,Eigen提供了一些基本矩阵的别名定义,如typedef Matrix<float,4,4> Matrix4f.下面是一些内置的别名定义.来源于:

typedef Matrix< std::complex
, 2 , 2 > Matrix2cdtypedef Matrix< std::complex
, 2 , 2 > Matrix2cftypedef Matrix< double , 2 , 2 > Matrix2dtypedef Matrix< float , 2 , 2 > Matrix2ftypedef Matrix< int , 2 , 2 > Matrix2itypedef Matrix< std::complex
, 3 , 3 > Matrix3cdtypedef Matrix< std::complex
, 3 , 3 > Matrix3cftypedef Matrix< double , 3 , 3 > Matrix3dtypedef Matrix< float , 3 , 3 > Matrix3ftypedef Matrix< int , 3 , 3 > Matrix3itypedef Matrix< std::complex
, 4 , 4 > Matrix4cdtypedef Matrix< std::complex
, 4 , 4 > Matrix4cftypedef Matrix< double , 4 , 4 > Matrix4dtypedef Matrix< float , 4 , 4 > Matrix4ftypedef Matrix< int , 4 , 4 > Matrix4itypedef Matrix< std::complex
, Dynamic , Dynamic > MatrixXcdtypedef Matrix< std::complex
, Dynamic , Dynamic > MatrixXcftypedef Matrix< double , Dynamic , Dynamic > MatrixXdtypedef Matrix< float , Dynamic , Dynamic > MatrixXftypedef Matrix< int , Dynamic , Dynamic > MatrixXitypedef Matrix< std::complex
, 1, 2 > RowVector2cdtypedef Matrix< std::complex
, 1, 2 > RowVector2cftypedef Matrix< double , 1, 2 > RowVector2dtypedef Matrix< float , 1, 2 > RowVector2ftypedef Matrix< int , 1, 2 > RowVector2itypedef Matrix< std::complex
, 1, 3 > RowVector3cdtypedef Matrix< std::complex
, 1, 3 > RowVector3cftypedef Matrix< double , 1, 3 > RowVector3dtypedef Matrix< float , 1, 3 > RowVector3ftypedef Matrix< int , 1, 3 > RowVector3itypedef Matrix< std::complex
, 1, 4 > RowVector4cdtypedef Matrix< std::complex
, 1, 4 > RowVector4cftypedef Matrix< double , 1, 4 > RowVector4dtypedef Matrix< float , 1, 4 > RowVector4ftypedef Matrix< int , 1, 4 > RowVector4itypedef Matrix< std::complex
, 1, Dynamic > RowVectorXcdtypedef Matrix< std::complex
, 1, Dynamic > RowVectorXcftypedef Matrix< double , 1, Dynamic > RowVectorXdtypedef Matrix< float , 1, Dynamic > RowVectorXftypedef Matrix< int , 1, Dynamic > RowVectorXitypedef Matrix< std::complex
, 2 , 1> Vector2cdtypedef Matrix< std::complex
, 2 , 1> Vector2cftypedef Matrix< double , 2 , 1> Vector2dtypedef Matrix< float , 2 , 1> Vector2ftypedef Matrix< int , 2 , 1> Vector2itypedef Matrix< std::complex
, 3 , 1> Vector3cdtypedef Matrix< std::complex
, 3 , 1> Vector3cftypedef Matrix< double , 3 , 1> Vector3dtypedef Matrix< float , 3 , 1> Vector3ftypedef Matrix< int , 3 , 1> Vector3itypedef Matrix< std::complex
, 4 , 1> Vector4cdtypedef Matrix< std::complex
, 4 , 1> Vector4cftypedef Matrix< double , 4 , 1> Vector4dtypedef Matrix< float , 4 , 1> Vector4ftypedef Matrix< int , 4 , 1> Vector4itypedef Matrix< std::complex
, Dynamic , 1> VectorXcdtypedef Matrix< std::complex
, Dynamic , 1> VectorXcftypedef Matrix< double , Dynamic , 1> VectorXdtypedef Matrix< float , Dynamic , 1> VectorXftypedef Matrix< int , Dynamic , 1> VectorXi

2 向量

向量被作为一种特殊的矩阵进行处理,即要么行为一要么列为一。除非显式的说明为行向量,否则这里将向量默认为列向量。请看下面两个别名定义:

typedef Matrix
Vector3f;typedef Matrix
RowVector2i;

3 矩阵的动态空间分配

很多时候在程序的编译阶段也许我们并不知道矩阵具体的行列数,这时候使用动态控件分配就显得很必要了。当我们给矩阵模板中参数RowsAtCompileTime或者ColsAtCompileTime参数指定为Dynamic时,表示该矩阵对应行或列为一个动态分配的值。下面是两个动态矩阵的别名定义:

typedef Matrix
MatrixXd;typedef Matrix
VectorXi;

4 矩阵的构建

经过上面的介绍以后,我们应该能定义一些基本的矩阵了。如:

Matrix3f a;   //定义一个float类型3×3固定矩阵aMatrixXf b;   //定义一个float类型动态矩阵b(0×0)Matrix
b; //定义一个int类型动态矩阵(0×3)

对应动态矩阵,我们也可以在构造的时候给出矩阵所占用的空间,比如:

MatrixXf a(10,15);  //定义float类型10×15动态矩阵VectorXf b(30); //定义float类型30×1动态矩阵(列向量)

为了保持一致性,我们也可以使用上面构造函数的形式定义一个固定的矩阵,即Matrix3f a(3,3)也是允许的。

上面矩阵在构造的过程中并没有初始化,Eigen还为一些小的(列)向量提供了可以初始化的构造函数。如:

Vector2d a(5.0,6.0);Vector3d b(5.0,6.0,7.0);Vector4d c(5.0,6.0,7.0,8.0);

5 矩阵元素的访问

Eigen提供了矩阵元素的访问形式和matlab中矩阵的访问形式非常相似,最大的不同是matlab中元素从1开始,而Eigen的矩阵中元素是从0开始访问。对于矩阵,第一个参数为行索引,第二个参数为列索引。而对于向量只需要给出一个索引即可。

#include 
#include "Eigen\Core"//import most common Eigen typesusing namespace Eigen;int main(){ MatrixXd m(2,2); m(0,0) = 3; m(1,0) = 2.5; m(0,1) = -1; m(1,1) = m(1,0) + m(0,1); std::cout<<"Hear is the matrix m:\n"<
<

输出结果如下:

Hear is the matrix m:  3  -12.5 1.5Here is the vector v:43

m(index)这种访问形式并不仅限于向量之中,对于矩阵也可以这样访问。这一点和matlab相同,我们知道在matlab中定义一个矩阵a(3,4),如果我访问a(5)相当于访问a(2,2),这是因为在matlab中矩阵是按列存储的。这里比较灵活,默认矩阵元素也是按列存储的,但是我们也可以通过矩阵模板构造参数Options=RowMajor改变存储方式(这个参数是我们还没有提到的矩阵构造参数的第4个参数)。

6 一般初始化方法

对于矩阵的初始化,我们可以采用下面的方法方便且直观的进行:

Matrix3f m;m<<1,2,3,   4,5,6,   7,8,9;std:cout<

7 矩阵的大小

Eigen提供了rows(),cols(),size()方法来获取矩阵的大小,同时也同了resize()方法从新改变动态数组的大小。

#include 
#include "Eigen\Core"using namespace Eigen;int main(){ MatrixXd m(2,5); m<<1,2,3,4,5, 6,7,8,9,10; m.resize(4,3); std::cout<<"The matrix m is:\n"<
<

输出结果如下:

The matrix m is:           1            3            5           6            8           10           2            4 9.58787e-315           7            9 1.17493e-309The matrix m is of size 4x3It has 12 coefficientsThe vector v is:           1           21.17477e-309 7.0868e-304           0The vector v is of size 5As a matrix,v is of size 5x1

可以看到我们可以把矩阵任意的resize,但是resize后矩阵的元素会改变,如果resize后的矩阵比之前的大会出现一些未初始化的元素。如果被resize的矩阵按列存储(默认),那么resize命令和matlab中的reshape执行结果相同,只是matlab要求reshape的矩阵前后元素必须相同,也就是不允许resize后不能出现未初始化的元素。

对于固定大小的矩阵虽然也支持resize命令,但是resize后的大小只能是它本身的大小,否则就会报错。因为resize前后如果矩阵大小一样,就不会执行resize。如果我们不想在resize后改变矩阵的对应元素,那么可以使用conservativeResize()方法。对应上面程序中的m矩阵我们调用m.conservativeResize(4,3)后得到结果如下。其中因为行数增加了,增加的行会以未初始化的形式出现。

The matrix m is:           1            2            3           6            7            89.58787e-315   2.122e-314 1.52909e+249           0            0 2.47039e+249

8 赋值和大小变换

在Eigen中使用=可以直接将一个矩阵复制给另外一个矩阵,如果被复制的和赋值矩阵大小不一致,会自动对被复制矩阵执行resize函数。当然如果被复制的矩阵为固定矩阵当然就不会执行resize函数。当然也可以通过一些设置取消这个自动resize的过程。

using namespace Eigen;int main(){    MatrixXf a(2,2);    MatrixXf b(3,3);    b<<1,2,3,       4,5,6,       7,8,9;    a = b;    std::cout<<

输出结果:

1 2 34 5 67 8 9

9 固定矩阵和动态矩阵

什么时候使用固定矩阵什么时候使用动态矩阵呢?简单的说:当矩阵尺寸比较小时使用固定矩阵(一般小于16),当矩阵尺寸较大时使用动态矩阵(一般大于32)。使用固定矩阵有更好的表现,它可以避免重复的动态内存分配,固定矩阵实际上是一个array。即Matrix4f mymatrix;事实上是float mymatrix[16];。所以这个是真的不花费任何运行时间。相反动态矩阵的建立需要在

heap中分配空间。即MatrixXf mymatrix(rows,colums);实际上是float *mymatrix = new float[rows*colums];.此外动态矩阵还要保存行和列的值。
当然固定矩阵也存在着显而易见的弊端。当数组的大小过大时,固定数组的速度优势就不那么明显了,相反过大的固定数组有可能造成stack的溢出。这时候动态矩阵的灵活性就显得十分重要了。

10 其他模板参数

最开始我们已经提到了建立一个矩阵一共有6个模板参数,其中有3个我们还没有提到(其实第三个参数已经提到过了)。

Matrix
  1. Options:这个参数决定了矩阵在存储过程中实际是按行还是按列存储。这个存储方式在前面我们提到的矩阵变换时必须要注意。默认是按列存储,我们可以显示的使用Options=RowMajor让矩阵实际按行存储。如Matrix<float,2,3,RowMajor> a;.
  2. MaxRowsAtCompileTime和MaxColsAtCompileTime:这两个值是设定动态矩阵在分配空间时最大的行数和列数。如Matrix<float,Dynamic,Dynamic,0,3,4>;.

11 常规的矩阵typedef

我们前面给出了一些常用的矩阵typedef.其实可以总结如下:

  1. MatrixNt对应的是Matrix<type,N,N>.比如MatrixXi对应的是Matrix<int,Dynamic,Dynamic>.
  2. VectorNt对应的是Matrix<type,N,1>.比如Vector2f对应的是Matrix<float,2,1>.
  3. RowVectorNt对应的是Matrix<type,1,N>.比如RowVector3d对应的是Matrix<double,1,3>.

其中:

  1. N可以是2,3,4或者X(表示Dynamic).
  2. t可以是i(int),f(float),d(double),cf(complex),cd(complex).只定义了这些类型的typedef并不表示只支持这些数据类型的运算。比如所有的整形类型的运算都支持(长的,短的,有符号的,无符号的)。

转载于:https://www.cnblogs.com/yabin/p/6435901.html

你可能感兴趣的文章
zabbix企业应用之监控mysql 5.6版本
查看>>
BGP选路原则与专有命令的研究
查看>>
关于java的引用、C++的指针、引用的深入分析
查看>>
CMD 修改Host文件 BAT
查看>>
linux用户管理的命令及手动添加用户
查看>>
Windows 7 家庭版如何启用Administrator账户
查看>>
我的友情链接
查看>>
mfs权威指南
查看>>
只是你没那么重要罢了
查看>>
javabean的初步认识学习
查看>>
GTK 安装步骤
查看>>
js 生成随机13位国际条码 支持获取校验位
查看>>
java根据开始时间和结束时间,计算中间天数,并打印
查看>>
Android apk的安装、卸载、更新升级(通过Eclipse实现静默安装)
查看>>
android幻灯片效果实现-Gallery
查看>>
node中exports与module.exports的区别
查看>>
PHP学习笔记2:文件
查看>>
jsrender简单使用
查看>>
window mysql-bin 转化为可读模式
查看>>
redis 安装及php扩展编译安装
查看>>