Eigen3第一期——Dense matrix and array manipulation/The Matrix class

C++是我这个行业的主要语言,所以还是需要认真的学习一下,Eigen3是C++生态中非常重要的第三方库,主要完成矩阵的计算,我找了一下没找到成熟的学习教程,和后面发现官网上有纯英文教程。所以现在决定跟着网上官方教程走一遍,即学习了c++还顺带学习了英语,岂不是double win?

所以本系列算是Eigen3教程也算是网页汉化。大部分为网页翻译,也会有部分个人批注。


本期:

第一章 稠密矩阵及数组操作

第一节 矩阵类

首先我们需要知道什么是稠密矩阵(Dense matrix)和稀疏矩阵
稠密矩阵:非0元素占比比较大的矩阵
稀疏矩阵:0元素占比比较大的矩阵

在Eigen中,所有的矩阵和向量都属矩阵类的对象,向量仅仅只是特殊情况下的矩阵,只有一行或是只有一列

矩阵类的前三个形参

矩阵类有6个形参,但学习前三个形参对现在来说已经足够,剩下的参数有默认值,现在我们不去改变他们,我们会在后面对其进行讨论。

前三个矩阵类强制的形参是:

Matrix<typename Scalar,int RowsAtCompileTime,int ColsAtCompileTime>

其中:

Scalar是精度类型,即数的类型,比如,如果你想创建一个浮点数矩阵,那么这里应该填float。

后面两个数是指在定义时已经知道的矩阵的行数和列数(如果定义时不知道矩阵的行数和列数见后文)。

我们提供很多便捷的类名来代替常用的矩阵,比如,Matrix4f,它代表4乘4的浮点型矩阵,它在Eigen中的定义如下:

typedef Matrix<float,4,4> Matrix4f

我们会在下文介绍这中快捷方法。

向量

如上所述,在Eigen中,向量只是一种特殊的情况下的矩阵(1行或1列),其中一列的情况最为普遍,这种向量我们称为列向量。其他情况,只有一行的向量我们成为行向量。

比如,3维浮点列向量的快捷类名是Vector3f,2维整型行向量的快捷类名是RowVector2i,其在Eigen种的定义如下:

typename Matrix<float,3,1> Vector3f
typename Martix<int,1,2> RowVector2i

特殊的动态值

当然,Eigen并不会限制定义矩阵时必须知道确切的维度。矩阵的行和列所对应的形参可以采用动态值,该值在定义的时候大小未知,因此必须当作变量来处理。在Eigen的术语中,这种维度被称为动态维度;而在定义时已知的维度被称为固定维度。例如:MatrixXd,意思是动态维度的矩阵。其定义为:

typename Matrix<double,Dynamic,Dynamic> MatrixXd;

类似的还有动态维度的向量定义方法:

typename Matrix<double,Dynamic,1> VectorXi

(注意:不能使用变量来对矩阵进行定义,有值的变量也不行,有值初始化的const int可以)

  //不允许的错误初始化
    int a;
    Eigen::Matrix<float,a,a> Mat_a;
  //不允许的错误初始化
    int c,b;
    const int a = b + c;
    Eigen::Matrix<float,a,a> Mat_a;
  //允许的正确初始化
    const int a = 5;
    Eigen::Matrix<float,a,a> Mat_a;

构造函数

默认构造函数总是可用的,不会执行任何的动态内存分配,并且从不初始化矩阵中的元素。你可以如下使用默认构造函数:

Matrix3f a;
MatrixXf b;

上述,a是一个未初始化的3乘3的浮点数矩阵。b是一个动态维度未初始化的矩阵(当前维度维0维)。

也可使用设置维度的构造函数。对于矩阵,总是先传递行数。对于向量,只需传递向量的大小。它们以给定的大小分配系数数组,但不初始化系数本身

MatrixXf a(10,15);        //10行15列的float矩阵
VectorXf b(30);           //长度为30的float的列向量

为了提供一致的API,对固定矩阵进行内存分配是合法的,如下语句是合法的

Matrix3f a(3,3)

矩阵和向量还可以使用列表进行初始化,在c++11以前,使用列表进行初始化有所限制,在c++11之后,可以使用列表初始化任意维度的矩阵和向量。如下:

Vector2i a(1, 2);           // 元素为{1, 2}的列向量
Matrix<int, 5, 1> b {1, 2, 3, 4, 5};   // 包含元素{1, 2, 3, 4, 5}的列向量
Matrix<int, 1, 5> c = {1, 2, 3, 4, 5}; // 包含元素{1, 2, 3, 4, 5}的行向量

对于固定维度大小的矩阵,使用列表进行初始化必须按行进行分组。如下:

MatrixXi a {      // 构造2x2矩阵
      {1, 2},     // 第一行
      {3, 4}      // 第二行
Matrix<double, 2, 3> b {
      {2, 3, 4},
      {5, 6, 7},
};

矩阵元素访问

对于矩阵及向量元素的访问见下例:

#include <iostream>
#include <Eigen/Dense>
 
int main()
{
  Eigen::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;
  Eigen::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

应注意,最好不要使用 [] 操作进行索引

逗号初始器

可以使用逗号来对矩阵数值进行初始化。如下例:

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

维度变化

矩阵可以通过 .rows() .cols() 来获取矩阵行和列,用 .resize() 来对动态维度进行改变,但是如果矩阵有确切的数值,可能会导致矩阵元素会进行破坏,如果想要使用稳妥一点的变换可以使用conservativeResize(),如下示例代码:

#include <iostream>
#include <Eigen/Dense>
 
int main()
{
  Eigen::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;
  Eigen::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

// ------------------------------ //

#include <iostream>
#include <Eigen/Dense>
 
int main()
{
  Eigen::Matrix4d m;
  m.resize(4,4); // no operation
  std::cout << "The matrix m is of size "
            << m.rows() << "x" << m.cols() << std::endl;
}
// 输出
The matrix m is of size 4x4

赋值和调整维度

赋值是将一个矩阵复制到另一个矩阵的操作,使用运算符 = ,Eigen会自动调整左侧矩阵的大小使其与右边大小相匹配,如下,当然,若左边是一个固定维度的矩阵,那么改变维度则是不被允许的。

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

固定维度 / 动态维度

固定维度矩阵是一个普通数组,而动态维度矩阵是一个动态数组,所以理论上固定维度数组更快。

可选形参

全部参数表如下:

Matrix<typename Scalar,
       int RowsAtCompileTime,
       int ColsAtCompileTime,
       int Options = 0,
       int MaxRowsAtCompileTime = RowsAtCompileTime,
       int MaxColsAtCompileTime = ColsAtCompileTime>

剩下三个介绍略。

方便的快捷类型

MatrixNt 表示 Matrix<type, N, N>.
   例:MatrixXi 表示 Matrix<int, Dynamic, Dynamic>.

MatrixXNt 表示 Matrix<type, Dynamic, N>. 
   例:MatrixX3i 表示 Matrix<int, Dynamic, 3>.

MatrixNXt 表示 Matrix<type, N, Dynamic>. 
   例:Matrix4Xd 表示 Matrix<double, 4, Dynamic>.

VectorNt 表示 Matrix<type, N, 1>. 
   例:Vector2f 表示 Matrix<float, 2, 1>.

RowVectorNt 表示 Matrix<type, 1, N>.
   例:RowVector3d 表示 Matrix<double, 1, 3>.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值