C++ Eigen 矩阵运算

1 Eigen的安装与CMakeLists.txt的编写

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

1.1、Eigen的安装

eigen3在linux下的安装可以直接用命令安装:

sudo apt-get install libeigen3-dev

1.2、Eigen的CMakeLists.txt编写

eigen库采用模板编程技术,仅由一些头文件组成,运行速度快。用cmake管理项目的时候,只需要在CMakeLists.txt里面头文件的路径即可:

find_package(Eigen3 REQUIRED)
include_directories(${EIGEN3_INCLUDE_DIR})

1.3、版本查看

tac /usr/include/eigen3/Eigen/src/Core/util/Macros.h    # tac表示从文本的后面往前输出

在这里插入图片描述

2、Eigen的头文件

Eigen所有的头文件及头文件里面的类的作用见下表
在这里插入图片描述
一般为了省事,可以直接导入#include <Eigen/Dense> 或者#include <Eigen/Eigen>

3、Eigen的基础

  • 先来一个最简单的eigen程序体验下

在这里插入图片描述
在这里插入图片描述

  • 一个简单的Matrixvector程序
  • 在这里插入图片描述

在这里插入图片描述
输出
在这里插入图片描述

3.1 Eigen初始化

Eigen提供了一种逗号初始化器语法,该语法使用户可以轻松设置矩阵,向量或数组的所有系数。只需列出系数,从左上角开始,从左到右,从上到下移动。需要预先指定对象的大小。如果列出的系数太少或太多,编译器就会报错。

此外,初始化列表的元素本身可以是向量或矩阵。通常的用途是将向量或矩阵连接在一起。例如,这是如何将两个行向量连接在一起。请记住,必须先设置大小,然后才能使用逗号初始化程序。

在这里插入图片描述
输出
在这里插入图片描述

3.1.1 一些常用的初始化方法

初始化为0,初始化为1,初始化为单位矩阵

在这里插入图片描述
输出
在这里插入图片描述

3.2 矩阵大小

矩阵的当前大小可以通过rows()cols()和size()检索。这些方法分别返回行数,列数和系数数。调整动态大小矩阵的大小是通过resize()方法完成的。
动态矩阵可以随意调整矩阵大小,固定尺寸`的矩阵无法调整大小
在这里插入图片描述
在这里插入图片描述

什么时候应该使用固定尺寸(例如Matrix4f),什么时候应该使用动态尺寸(例如MatrixXf)?简单的答案是:在可能的地方使用固定尺寸来显示非常小的尺寸,在需要的地方使用动态尺寸来显示较大的尺寸。

对于小尺寸,尤其是对于小于(大约)16的尺寸,使用固定尺寸对性能有极大的好处,因为它使Eigen避免了动态内存分配并展开了循环。在内部,固定大小的本征矩阵只是一个简单的数组,即

Matrix4f mymatrix;
等同于: 
float mymatrix[16];

因此,这确实具有零运行时间成本。相比之下,动态大小矩阵的数组始终分配在堆上,因此

MatrixXf mymatrix(rows,columns);
等同于: 
float mymatrix = new float[rows*columns];

矩阵分别有 .rows()、.cols()、.size() 函数来分别获取矩阵的行数、列数以及元素个数;
使用 .resize() 函数可以改变矩阵的大小
在这里插入图片描述
在这里插入图片描述

3.3 Eigen矩阵类

Matrix的3个必需模板参数是:

Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>
  • Scalar 是标量类型,即系数的类型。也就是说,如果要使用浮点数矩阵,此处选择float。有关所有受支持的标量类型的列表以及如何将支持扩展到新类型的信息,请参见标量类型。
  • RowsAtCompileTime和ColsAtCompileTime是在编译时已知的矩阵的行数和列数。
    这里提供了许多方便的typedef来覆盖通常的情况。例如,Matrix4f是一个4x4的浮点矩阵。这是Eigen定义的:
typedef Matrix <float44> Matrix4f;

Eigen里面用到了很多的typedef简化名称长度,例如下面:

typedef Matrix<float, 3, 1>                               Vector3f;
typedef Matrix<int, 1, 2>                                 RowVector2i;
typedef Matrix<double, Dynamic, Dynamic> MatrixXd;
typedef Matrix<int, Dynamic, 1>                           VectorXi;
typedef Array<float,Dynamic,Dynamic>                      ArrayXXf
typedef Array<double,Dynamic,1>                           ArrayXd
typedef Array<int,1,Dynamic>                              RowArrayXi
typedef Array<float,3,3>                                  Array33f
typedef Array<float,4,1>                                  Array4f
......

在Eigen中可以使用 () 来获取矩阵中的元素,可以直接对矩阵中的元素进行赋值
如:m(4,7)就表示获取4行7列的元素
.data()函数用于返回一个指向矩阵或向量的首地址的指针
在这里插入图片描述
在这里插入图片描述

3.4 Eigen矩阵的创建

一般而言,创建一个矩阵需要调用 Matrix<> 构造,其共包含6个参数,前3个为必须参数,后3个为可选参数,有默认值。3个必须参数如下:
在这里插入图片描述

  • 向量的矩阵,例是列数恒为 1, 如
    在这里插入图片描述
    Eigen 库中预先定义了一些固定大小的矩阵和向量类型,如下所示:
    在这里插入图片描述
    可以指定矩阵的行数或者列数为 Dynamic ,创建动态大小的矩阵,如下所示:
    在这里插入图片描述

4 Eigen的Array类

Eigen 不仅提供了MatrixVector结构,还提供了Array结构。

区别如下,Matrix和Vector就是线性代数中定义的矩阵和向量,所有的数学运算都和数学上一致。但是存在一个问题是数学上的定义并不一定能完全满足现实需求。比如,数学上并没有定义一个矩阵和一个标量的加法运算。但是如果想给一个矩阵的每个元素都加上同一个数,那么这个操作就需要自己去实现,这显然并不方便。

Array 提供了一个Array类,也提供了大量的矩阵未定义的操作,且Array和Matrix之间很容易相互转换 ,所以相当于给矩阵提供更多的方法。也为使用者的不同需求提供了更多的选择。

  • Array类和Matrix有相同的参数。
Array<typename Scalar, int RowsAtCompileTime , int ColsAtCompileTime >

上面参数的意义和Matrix中参数的意义是相同的。
Array也对常用的情况作了一些类型定义。

typedef Array<float ,Dynamic,1> ArrayXf;
typedef Array<float,3,1> Array3f;
typedef Array<double,Dynamic ,Dynamic > ArrayXXd;
typedef Array<double ,3,3 > Array33d;

4.1 Array的初始化

Eigen::Array类重载了+、-、*、/ 运算符,可以直接用这些运算符对Array对象进行操作。相乘操作是对应的数字相乘,相除是对应的元素相除
在这里插入图片描述

4.2 Array的其他操作

Array 还定义了 绝对值 abs() ,开平方根sqrt() , 以及找对应元素最小值操作min()
在这里插入图片描述

4. 3、Array与Matrix之间的互相转换

Matrix类和Array类之间可以相互转换,必须显式转换,才能对他们进行加减乘除运算。

  • Array 有 .matrix( ) 方法。
  • Matrix 有 .array( )方法。

在这里插入图片描述

5 矩阵运算

5.1 Matrix的转置和共轭

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

在这里插入图片描述

在这里插入图片描述
a = a.transpose();无法运行,这称为别名问题,在debug模式下当assertions没有禁止时,这种问题会被自动检测到。要避免错误,可以使用in-place转置。类似的还有adjointInPlace()。
所以正确的操作见下面程序:

    // a = a.transpose(); //   不要这样写代码,无法运行
    a.transposeInPlace();

5.2 向量的点积和叉积

对于点积和叉积,直接使用dot()cross()方法。
在这里插入图片描述

在这里插入图片描述
注意:记住叉积仅仅用于尺寸为3的向量!点积可以用于任意尺寸的向量,当使用复数时,Eigen的点积操作是第一个变量为共轭线性的,第二个为线性的。

5.3 矩阵的基础的算术(求和,平均值等)

Eigen提供了一些对于矩阵或向量的规约操作,如sum(),prod(),maxCoeff()minCoeff()
在这里插入图片描述
在这里插入图片描述

trace为矩阵的迹,也可以由a.diagonal().sum()得到。
minCoeffmaxCoeff函数也可以返回相应的元素的位置信息

5.4矩阵的块操作

块指的是矩阵或数组中的一个矩形区域,块表达式可以用于左值或者右值,同样不会耗费运行时间,由编译器优化。
Eigen中最常用的块操作是block()方法,共有两个版本。
在这里插入图片描述
在这里插入图片描述

上述例子中的块操作方法作为表达式的右值,意味着是只读形式的,然而,块操作也可以作为左值使用,意味着你可以给他赋值。下面的例子说明了这一点,当然对于矩阵的操作是一样的。

在这里插入图片描述
在这里插入图片描述
尽管block()方法可用于任何形式的块操作,还是有特殊的方法API用于特殊情况的,主要是为了更好的性能。
说到性能,最重要的是在编译阶段给Eigen尽可能多的信息。

比如,如果你的块是一个矩阵中的一列,那么使用col()方法会更好。本节其余的介绍都是关于这些特殊的方法的。

5.5 矩阵的行列操作

行和列是一中特殊的块。Eigen提供了特殊的方法:col() 列 row() 行。
在这里插入图片描述

5.6 矩阵边角相关的操作

Eigen同样提供了对于挨着矩阵或数组的边、角的特殊操作方法,比如topLeftCorner()方法可用于操作矩阵左上角的区域。总结如下:

在这里插入图片描述

5.7 向量的块操作

Eigen也提供了一些针对向量和一维数组的块操作方法:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5.8 范数计算

向量的平方范数由squaredNorm()获得,等价于向量对自身做点积,也等同于所有元素额平方和。Eigen也提供了norm()范数,返回的是squaredNorm()的根。这些操作也适用于矩阵。

如果想使用其他元素级的范数,使用lpNorm()方法,当求无穷范数时,模板参数p可以取特殊值Infinity,得到的是所有元素的最大绝对值。
在这里插入图片描述

在这里插入图片描述

参考链接:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@BangBang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值