Eigen矩阵运算的混淆问题
1. 混淆产生的原因
在Eigen中,当变量同时出现在左值和右值,赋值操作可能会带来混淆问题。
例如
MatrixXi mat(3,3);
mat << 1, 2, 3, 4, 5, 6, 7, 8, 9;
cout << "Here is the matrix mat:\n" << mat << endl;// This assignment shows the aliasing problem
mat.bottomRightCorner(2,2) = mat.topLeftCorner(2,2);
cout << "After the assignment, mat = \n" << mat << endl;
输出
Here is the matrix mat:
1 2 3
4 5 6
7 8 9
After the assignment, mat =
1 2 3
4 1 2
7 4 1
出现混淆的代码是
mat.bottomRightCorner(2,2) = mat.topLeftCorner(2,2);
它等价于
mat(1,1) = mat(0,0);
mat(1,2) = mat(0,1);
mat(2,1) = mat(1,0);
mat(2,2) = mat(1,1);
混淆还会在缩小矩阵时出现,例如
vec = vec.head(n)mat = mat.block(i,j,r,c)。
一般来说,混淆在编译阶段很难被检测到。
2. 解决混淆问题
2.1. 使用eval()函数函数
Eigen需要把右值赋值为一个临时matrix/array,然后再将临时值赋值给左值,便可以解决混淆。eval()函数实现了这个功能。
例如
MatrixXi mat(3,3);
mat << 1, 2, 3, 4, 5, 6, 7, 8, 9;
cout << "Here is the matrix mat:\n" << mat << endl;
// The eval() solves the aliasing problem
mat.bottomRightCorner(2,2) = mat.topLeftCorner(2,2).eval();
cout << "After the assignment, mat = \n" << mat << endl;
输出
Here is the matrix mat:
1 2 3
4 5 6
7 8 9
After the assignment, mat =
1 2 3
4 1 2
7 4 5
2.2. 尽量使用带InPlace的函数
在调用矩阵的某个函数操作赋值给对象本身时,如果存在xxxInPlace函数,推荐使用这类函数,它们更加清晰地标明了你在做什么。
Origin | In-place |
---|---|
MatrixBase::adjoint() | MatrixBase::adjointInPlace() |
DenseBase::reverse() | DenseBase::reverseInPlace() |
LDLT::solve() | LDLT::solveInPlace() |
LLT::solve() | LLT::solveInPlace() |
TriangularView::solve() | TriangularView::solveInPlace() |
DenseBase::transpose() | DenseBase::transposeInPlace() |
3. 混淆和component级的操作
组件级是指整体的操作,比如matrix加法、scalar乘、array乘等,这类操作是安全的,不会出现混淆。
MatrixXf mat(2,2);
mat << 1, 2, 4, 7;
cout << "Here is the matrix mat:\n" << mat << endl << endl;
mat = 2 * mat;
cout << "After 'mat = 2 * mat', mat = \n" << mat << endl << endl;
mat = mat - MatrixXf::Identity(2,2);
cout << "After the subtraction, it becomes\n" << mat << endl << endl;
ArrayXXf arr = mat;
arr = arr.square();
cout << "After squaring, it becomes\n" << arr << endl << endl;
输出
Here is the matrix mat:
1 2
4 7
After 'mat = 2 * mat', mat =2 48 14
After the subtraction, it becomes1 48 13
After squaring, it becomes1 1664 169
4. 混淆和矩阵的乘法
在Eigen中,矩阵的乘法一般都会出现混淆。除非是方阵(实质是元素级的乘)。
MatrixXf matA(2,2);
matA << 2, 0, 0, 2;
matA = matA * matA;
cout << matA;
4 0
0 4
其他的操作,Eigen默认都是存在混淆的。所以Eigen对矩阵乘法自动引入了临时变量,对的matA=matA*matA
这是必须的,但是对matB=matA*matA
这样便是不必要的了。我们可以使用noalias()函数来声明这里没有混淆,matA*matA的结果可以直接赋值为matB。
matB.noalias() = matA * matA;
从Eigen3.3开始,如果目标矩阵resize且结果不直接赋值给目标矩阵,默认不存在混淆。
MatrixXf A(2,2), B(3,2);
B << 2, 0, 0, 3, 1, 1;
A << 2, 0, 0, -2;
A = (B * A).cwiseAbs();//cwiseAbs()不直接赋给目标
//A = (B * A).eval().cwiseAbs()
cout << A;
当然,对于任何混淆问题,都可以通过matA=(matB*matA).eval()
来解决。
参考文献
- https://www.bbsmax.com/A/KE5Q9yG05L/
Eigen矩阵运算的混淆问题相关推荐
- Eigen 矩阵运算库在实际项目中的使用
Eigen 矩阵运算库在实际项目中的使用情况如何? 心血来潮,试了试纯模板技术写的 Eigen 并作了简单的性能测试,三个 1000 阶的方阵连乘运算 Eigen 比 MATLAB 快了一倍,比 Op ...
- Eigen矩阵运算库快速上手
目录 1. 配置 2. 初始化 2.1 Array类 2.2 Vector类 2.3 Matrix类 2.4 Vector赋值 2.5 高级初始化 3. 矩阵计算 3.1 矩阵基本计算 3.2 线性求 ...
- eigen 编译_OpenCV+Eigen上位机程序移植(七十一)
1.给硬盘分区 现在小伙伴们对于给电脑硬盘分区想必比较头疼,给电脑硬盘分区分为两种情况,一是在安装系统之前给系统硬盘分区,二是在安装系统之后给硬盘分区,我们现在购买的品牌机和笔记本的用户比较多,而且笔 ...
- eigen库安装_OpenCV+Eigen上位机程序移植(七十一)
1.给硬盘分区 现在小伙伴们对于给电脑硬盘分区想必比较头疼,给电脑硬盘分区分为两种情况,一是在安装系统之前给系统硬盘分区,二是在安装系统之后给硬盘分区,我们现在购买的品牌机和笔记本的用户比较多,而且笔 ...
- [视觉Slam十四讲(2)踩坑记录]第3讲:Fatal error :Eigen/core没有那个文件或目录
[视觉Slam十四讲(2)踩坑记录]第3讲:Fatal error :Eigen/core没有那个文件或目录 问题描述: 在学习SlamBook2-ch3中对Eigen矩阵运算包内容时,编写好相关代码 ...
- Qt间接平差法进行直线拟合(Eigen运算、Qcustomplot绘图)
目录 间接平差法进行直线拟合,使用Qt.Qcustomplot.Eigen 间接平差法直线拟合原理 工具介绍 Qt Qcustomplot Eigen 准备工作 1.Qt读取文件存入矩阵 2.Eige ...
- 我所理解的卡尔曼滤波——公式推导与应用
我所理解的卡尔曼滤波--公式推导与应用 1.什么是卡尔曼滤波 2.卡尔曼滤波的数学推导 2.1 状态方程和测量方程 2.2 卡尔曼滤波过程 3 卡尔曼滤波应用 1.什么是卡尔曼滤波 先举个例子说一下什 ...
- opencv镜像_DX200操作要领—PAM与镜像平移变换(三十八)
6.4 PAM功能 6.4.1 PAM功能 再现中的位置修改功能 (PAM 功能:Position Adjustment Manual) ,可在查看机器人动作状况的同时,在不停止机器人的情况下,通过简 ...
- 星之卡比镜之迷宫机器人_机器人工程师入门(0)
前言:多年前看到一片知乎文章 YY硕:机器人工程师学习计划zhuanlan.zhihu.com 当时看到这个,只觉醍醐灌顶,能看到有如此详尽的关于机器人工程师的个人技术发展规划,又不禁觉得有些遗憾, ...
最新文章
- 3.	定义10个字节的键盘缓冲区,然后键盘输入字符填满该缓冲区,做如下工作: (1)分别将输入键盘缓冲区的字符按数字,小写字母,大写字母,其他字符进行计数; 分别将这些计数值显示出来。 (2)分别将这
- python笔记 print+‘\r‘ (打印新内容时删除打印的旧内容)
- Python中shuffle() 函数的作用及用法
- windows下redis安装,注册成系统服务
- poll()函数详解
- 信号与系统郑君里上册pdf_信号与系统(上册)
- HTML的块级元素和行级元素的标签列表
- 【数据湖存储】数据湖的终极奥秘,无招胜有招
- oracle写转帐的存储过程,Oracle存储过程及块编程基础经典案例
- 笔记本暗屏维修多少钱_电视机烧了维修多少钱?
- bzoj 1670: [Usaco2006 Oct]Building the Moat护城河的挖掘(凸包)
- File类和各种io类会不会自动创建文件
- [翻译]WPF控件库 MaterialDesignInXamlToolkit (2) Brush Names
- python 笔记 冒泡排序
- C/C++[codeup 2043]小白鼠排队
- 【预测模型-ELAMN预测】基于哈里斯鹰算法优化ELMAN神经网络实现数据回归预测matlab代码
- fv计算机公式,p=fv是什么公式
- 冰点还原无法修改计算机时间,设置冰点还原解冻期间方法
- 如何快速识别图片中的文字?建议使用者两种方法
- 揭秘摄像头黑产链:暴露在外的80端口