Eigen笔记(一)基本简介

C++线性代数库——Eigen

简介

Eigen是一款开源的C++线性代数库。Eigen可以编译,也可以开箱即用。Eigen是一个高层次的C ++库,有效支持线性代数,矩阵和矢量运算,数值分析及其相关的算法。Eigen是一个开源库,从3.1.1版本开始遵从MPL2许可。

数据类型一

在Eigen中所有的矩阵和向量都源于一个模板类Matrix,向量仅仅是一个矩阵的特例,他是一个一行一列的矩阵。

Matrix类有六个模板参数,这里我们先去讨论它的前三个模板参数。后面三个模板都会有默认值,而且一般情况下我们接触不到。

Matrix<typename Scalar,int RowsAtCompileTime,int ColsAtComplieTme>

其中第一个参数指定了我们矩阵的数据的数据类型,如果你想要你的矩阵中存储的数据为float类型,那么你需要指定Scalar为float。后面的两个参数,根据其定变量的字面意思我们可以得知,他们决定了矩阵的形状。第二个指定矩阵的行数,第二个指定矩阵的列数。尤其,使用这种方法去指定矩阵的形状,那么根据泛型编程的特点,矩阵的形状将会在编译阶段(compile time)确定下来。

同时呢Eigen为了方便我们使用矩阵,Eigen对于一些常用的矩阵做了重命名。

例如:

typedef Matrix<float,4,4> Matrix4f;

Eigen在对这些矩阵进行命名时,会有一定的规则,如果是矩阵,他们会以Matrix开头,之后会带上Matrix的形状,这里应该注意,这样定义的矩阵为方阵。最后一个字母代表了矩阵中存储数据的数据类型。

向量的定义可以看作是矩阵的特例。一般行向量定义为Matrix<T,1,x>列向量定义为Matrix<T,x,1>

构造函数

在Eigen中有一个默认的构造函数可供使用,这个构造函数不会去动态的申请内存空间,也不会初始化一些系数矩阵。

Matrix3d A;//得到一个3阶方阵,方阵存储的数据类型为double
Vector2d B;//得到一个大小为2的列向量,向量中存储的数据类型为double
/*
*在Eigen中向量优先为列向量存储
*/

如果创建矩阵

MatrixXf a(10,15); //创建一个10行15列的矩阵,矩阵存储的数据类型为float
VectorXf b(30); //创建一个大小为30的列向量,向量中存储的数据类型为float

为了在固定大小和动态大小的矩阵之间提供统一的API,在固定大小的矩阵上使用这些构造函数是合法的,即使在这种情况下传递大小是无用的。所以这是合法的。

Matrix3f a(3,3);//虽然创建矩阵的时候已经确定了矩阵的大小,但是我们也可以在构造函数中传入参数
//这也是合法的

但是,如果我们实现定义出来的矩阵大小,与构造函数中传入的参数大小不匹配。这个时候并不会去触发编译的错误,但是在运行时会触发运行时错误。

Matrix3f a(3,4);
//编译会通过,但是会触发运行时的内存分配错误。

成员访问

在Eigen中主要的成员访问方式是通过()去访问,Eigen对括号运算符做了重载。利用括号运算符,你可以去获取/更改矩阵中的特定元素。对于矩阵而言,()中的第一个参数为行数,第二个参数为列数。对于向量,我们只需要传递数据的索引值即可。

#include <iostream>
#include <Eigen/Dense>
using 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 << "Here is the matrix m:\n" << m << std::endl;
  VectorXd v(2);
  v(0) = 4;
  v(1) = v(0) - 1;
  std::cout << "Here is the vector v:\n" << v << std::endl;
}

程序输出

Here is the matrix m:
  3  -1
2.5 1.5
Here is the vector v:
4
3

Resizing

Eigen中Matrix类提供了一些成员函数来获取矩阵目前的一些信息,例如:你可以通过rows()来获取矩阵的行数;通过cols()来获取矩阵的列数。通过size()获取矩阵的大小。同时你也可以通过resize()函数来动态的修改矩阵的大小。*注:resize()只适用于未通过类模板定义的矩阵大小的矩阵,只适用于通过构造函数动态创建的矩阵。

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
  MatrixXd m(2,5);
  m.resize(4,3);
  std::cout << "The matrix m is of size "
            << m.rows() << "x" << m.cols() << std::endl;
  std::cout << "It has " << m.size() << " coefficients" << std::endl;
  VectorXd v(2);
  v.resize(5);
  std::cout << "The vector v is of size " << v.size() << std::endl;
  std::cout << "As a matrix, v is of size "
            << v.rows() << "x" << v.cols() << std::endl;
}

程序输出:

The matrix m is of size 4x3
It has 12 coefficients
The vector v is of size 5
As a matrix, v is of size 5x1

Assignment and resizing

我们同样可以利用赋值的方法去调整矩阵的大小。在Eigen中赋值是一个左值运算符,他会把赋值=好右边的矩阵内容copy到左边的矩阵中,这样也可以完成矩阵大小的重整。*注:这种赋值重整大小的方法同样也是仅适用于动态大小的矩阵,而不适用于固定大小的矩阵

MatrixXf a(2,2);
std::cout << "a is of size " << a.rows() << "x" << a.cols() << std::endl;
MatrixXf b(3,3);
a = b;
std::cout << "a is now of size " << a.rows() << "x" << a.cols() << std::endl;

程序输出:

a is of size 2x2
a is now of size 3x3

Fixed vs Dynamic size

什么时候应该使用固定大小(例如Matrix4f),什么时候应该选择动态大小(例如MatrixXf)?简单的答案是:在可能的情况下,对非常小的尺寸使用固定大小,对于较大的尺寸或必须使用动态大小。对于较小的大小,特别是小于(大约)16的大小,使用固定大小对性能非常有利,因为它允许Eigen避免动态内存分配和展开循环。在内部,一个固定大小的特征矩阵只是一个普通的数组

dynamic sizes for larger sizes or where you have to. For small sizes, especially for sizes smaller than (roughly) 16, using fixed sizes is hugely beneficial to performance, as it allows Eigen to avoid dynamic memory allocation and to unroll loops. Internally, a fixed-size Eigen matrix is just a plain array, i.e. doing

可选的模板参数

我们在这一页的开头提到矩阵类接受六个模板参数,但是到目前为止我们只讨论了前三个。其余三个参数是可选的。以下是模板参数的完整列表

Matrix<typename Scalar,
       int RowsAtCompileTime,
       int ColsAtCompileTime,
       int Options = 0,
       int MaxRowsAtCompileTime = RowsAtCompileTime,
       int MaxColsAtCompileTime = ColsAtCompileTime>
  • Options Options将会指定我们矩阵在数据存储过程中的优先级,一般默认为行优先。
  • MaxRowsAtCompileTimeMaxColsAtCompileTime在您需要指定的时候非常有用,即使在编译时不知道矩阵的确切大小,但是在编译时知道一个固定的上限。您这样做的最大原因可能是为了避免动态内存分配。例如,下面的矩阵类型使用12个浮点数的普通数组,没有动态内存分配:

一个动态和固定的问题

我们知道,在Eigen中所有的数据类型都来源于模板类Matrix。那么既然他们同源,所以动态和固定之间也是有着联系的。

我们知道我们用Matrix3f去创建一个固定大小为9的3x3的矩阵,那么这个矩阵我们称之为固定大小矩阵。在底层他是通过Matrix<float,3,3>这几组模板参数限制了矩阵的大小。换句话说,指定了模板参数的大小,也就相当于我们在编译阶段确定了矩阵应该分配的内存空间。

那么动态的矩阵MatrixXf其实现原理也应该是设置了模板参数。经过测试我发现,当把模板参数中的行数和列数统统设置为**-1**时,这个矩阵就变成动态的矩阵,他的大小我们可以通过构造函数(constructor)去定义。

同样,一旦矩阵的大小动态了,我们必须通过构造函数去给他一个初始大小不然程序会在运行时抛出异常。

也就是说我们可以Matrix3d test但是不可以MatrixXd test

猜你喜欢

转载自blog.csdn.net/hbn13343302533/article/details/95509802