Eigen官网教程(1) Matrix相关

1. Eigen库与头文件

Eigen库被分为了一个Core模块和几个其他额外的模块,每个模块都有对应的头文件,使用时需要进行包含。其中通过Dense和Eigen头文件可以很方便的使用其他的模块,因此一般情况下使用这俩就够了。

2.Matrix

2.1

Matrix类共有6个模板参数,主要使用的是前三个参数,剩余的都有默认值,前三个参数分别是

Matrix <typename Scalar,int RowsAtCompileTime,int ColsAtCompileTime>

<变量类型 ,行 , 列>

2.2

在Eigen中,所有的矩阵和向量都是Matrix模板类的对象,向量只是特殊的矩阵而已,无论是行向量还是列向量。

2.3 参数Dynamic

RowsAtCompileTIme和ColsAtCompileTIme参数可以取特殊值Dynamic,这代表编译时不能确定矩阵的尺寸,必须在运行时确定。Eigen中称为动态尺寸,编译时确定尺寸的矩阵称为固定尺寸的矩阵

typedef Matrix <double,Dynamic,Dynamic> MatrixXd ;

typedef Matrix <int,Dynamic,1> VectorXi ;

2.3 构造函数

默认的构造函数不执行动态内存分配,也不初始化矩阵的元素。

Matrix3f a;  //a是3x3的矩阵,分配了float[9]的空间但是没有进行初始化

MatrixXf b; //b是个0x0的矩阵

对于构造函数指定尺寸也是可以的,对于矩阵首先传递的是行参数,对于向量则只传递尺寸就好,构造函数会分配相应的空间但是不进行初始化工作。

MatrixXf a(10,15); //a是10x15的矩阵,分配了空间没有进行初始化

VectorXf b(30); //b是个尺寸为30的向量同样没有初始化

尺寸小于4的向量可以直接在定义时初始化

Vector2d a(5.0,6.0);

Vector3d b(5.0,6.0,7.0);

Vector4d c(5.0,6.0,7.0,8.0);

2.4 元素获取

2.5 逗号初始化

更详细的初始化教程http://eigen.tuxfamily.org/dox/group__TutorialAdvancedInitialization.html

2.6 调整尺寸

矩阵的大小可以通过rows(), cols(), size()方法获取。对动态尺寸的矩阵调整尺寸时使用resize()方法

2.7 Assignment和resizing

Assignment是将一个矩阵赋值给另一个,如果尺寸不同时Eigen会将左边的矩阵的尺寸自动resize成和右边的矩阵相同的尺寸

2.8 固定尺寸VS动态尺寸

对于小的矩阵,尤其是小于16个元素的,使用固定尺寸有利于代码性能,因为会避免动态内存的分配,固定尺寸的矩阵实际上就是个数组,

比如Matrix4f mymatrix等价于float mymatrix[16],

动态尺寸的矩阵总是在堆上申请内存,

因此MatrixXf mymatrix[rows,cols]相当于float *mymatrix = new float[rows*cols],并且MatrixXf对象还会存储它的行和列作为成员变量。

使用固定尺寸的局限在于仅仅当你能提前确定矩阵的尺寸。对于较大的矩阵,如大于32,使用固定尺寸带来的性能效果就变得可以忽略了,更糟糕的是,当试图在函数内部创建一个很大的固定尺寸的矩阵时可能会导致栈溢出

2.8 可选的参数

Matrix完整参数:

Option是一个标志位,表明矩阵的存储方式,RowMajor表示按行存储。默认是按列存储的。例如:

Matrix<float, 3, 3, RowMajor>

MaxRowsAtCompileTimeMaxRowsAtCompileTime表示编译时矩阵尺寸的上限,主要是为了避免动态内存分配。

如下的定义使用的是长度为12的数组,没有使用动态内存分配

Matrix<float, Dynamic, Dynamic, 0, 3, 4>

3.矩阵与向量的运算

Eigen提供了一些矩阵和向量的数值运算,其中一些是通过通用的C++运算符重载实现,如+,-,*等,另一些通过特殊的方法实现,如dot(),cross()等方法。对于Matrix类,这些操作只支持线性代数运算,比如matrix1*matrix2代表矩阵的乘积,而向量+标量则是不允许的。

3.1  + -

运算符两侧必须有相同的行和列。而且还要有相同的数据类型,因为Eigen并不做自动类型转换,可用的操作符有:

  1. 二元运算+如a+b
  2. 二元运算-如a-b
  3. 一元运算-如-a
  4. 复合运算+=如a+=b
  5. 复合运算-=如a-=b

3.2  标量的乘除

  1. 二元运算符*         如matrix*scalar,scalar*matrix
  2. 二元运算符/          如matrix/scalar
  3. 复合运算符*=        如matrix*=scalar
  4. 复合运算符/=         如matrix/=scalar

3.3  表达式模板

不需要担心在Eigen中使用大的算法表达式。它仅仅是给了Eigen更多的优化机会

Eigen中数值运算符如+并不执行任何计算,而是返回一个表达式对象描述需要执行的计算。一般是当整个表达式被评估完之后(典型的比如遇到符号=)实际的计算才进行。这样做主要是为了优化提高效率,比如当你写

VectorXf a(50), b(50), c(50), d(50);

...

a = 3*b + 4*c + 5*d;

Eigen会把他们编译成一个循环以便数组们只需要访问一次,比如会编译成如下形式

for(int i = 0; i < 50; ++i)

  a[i] = 3*b[i] + 4*c[i] + 5*d[i];

3.4 转置和共轭

对矩阵的转置、共轭和共轭转置由成员函数transpose(),  conjugate(),  adjoint()实现

 

对于实数矩阵,conjugate()不做任何操作,所以adjoint()等同于transpose()。

基本的数值运算符、transpose()和adjoint()会简单的返回一个中间对象而不是对原对象做处理。

这称为别名问题,在debug模式下当assertions没有禁止时,这种问题会被自动检测到。要避免错误,可以使用in-place转置。类似的还有adjointInPlace()。

3.5 矩阵相乘,矩阵乘向量

矩阵相乘使用运算符*实现,由于向量也是一种特殊的矩阵,因此矩阵乘以向量和向量间的外积是一样的方法。所有这些情况都由两个运算符处理

  1. 二元运算符*如a*b
  2. 复合运算符*=如a*=b,等于a = a*b。

注:Eigen对矩阵相乘这种情况进行特殊处理,不用担心别名问题,比如m = m*m会被编译成tmp = m*m; m = tmp。

3.6 点积和叉积

对于点积和叉积,直接使用dot() 和  cross()方法

3.7 基础的算术规约操作

Eigen提供了一些对于矩阵或向量的规约操作,如sum(),prod(),maxCoeff()和minCoeff()

trace为矩阵的迹,也可以由a.diagonal().sum()得到。

minCoeff和maxCoeff函数也可以返回相应的元素的位置信息

3.8 操作的有效性

Eigen会检查你的操作的有效性,如果可能的话会在编译阶段产生,输出信息。这些信息可能比较长并且难看,不过重要的信息都用了大写的语句标出了,可以很容易找到。如

Matrix3f m;

Vector4f v;

v = m*v;      // Compile-time error: YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES

但是另一些情况下,比如对于动态尺寸的检查不能在编译阶段完成,那么Eigen会在运行期间检查,如果出错,那么程序会崩溃并输出一些信息。

MatrixXf m(3,3);

VectorXf v(4);

v = m * v; // Run-time assertion failure here: "invalid matrix product"

更多的报错信息参见:

http://eigen.tuxfamily.org/dox/TopicAssertions.html

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
eigen 中,sparse matrixmatrix 之间的转换可以通过 matrix 类的构造函数或者赋值运算符来实现。 假设我们有一个 sparse matrix `SparseMatrix<double>`,我们可以通过如下代码将其转换为 matrix `MatrixXd`: ```c++ #include <Eigen/Sparse> #include <Eigen/Dense> using namespace Eigen; int main() { // 创建一个稀疏矩阵 SparseMatrix<double> sp(3, 3); sp.insert(0, 0) = 1.0; sp.insert(1, 1) = 2.0; sp.insert(2, 2) = 3.0; // 将稀疏矩阵转换为 matrix MatrixXd m = MatrixXd(sp); // 输出结果 std::cout << "Sparse Matrix:\n" << sp << std::endl; std::cout << "Dense Matrix:\n" << m << std::endl; return 0; } ``` 在上述代码中,我们创建了一个 3x3 的稀疏矩阵 `sp`,并将其转换为 matrix `m`,然后输出结果。在转换时,我们直接将 `sp` 作为参数传递给 `MatrixXd` 的构造函数即可。 如果我们已经定义好了一个 matrix `MatrixXd`,我们也可以通过赋值运算符将其转换为 sparse matrix `SparseMatrix<double>`,示例如下: ```c++ #include <Eigen/Sparse> #include <Eigen/Dense> using namespace Eigen; int main() { // 创建一个 matrix MatrixXd m(3, 3); m << 1.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 3.0; // 将 matrix 转换为稀疏矩阵 SparseMatrix<double> sp = SparseMatrix<double>(m); // 输出结果 std::cout << "Dense Matrix:\n" << m << std::endl; std::cout << "Sparse Matrix:\n" << sp << std::endl; return 0; } ``` 在上述代码中,我们创建了一个 3x3 的 matrix `m`,并将其转换为 sparse matrix `sp`,然后输出结果。在转换时,我们将 `m` 作为参数传递给 `SparseMatrix<double>` 的构造函数即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值