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矩阵运算的混淆问题相关推荐

  1. Eigen 矩阵运算库在实际项目中的使用

    Eigen 矩阵运算库在实际项目中的使用情况如何? 心血来潮,试了试纯模板技术写的 Eigen 并作了简单的性能测试,三个 1000 阶的方阵连乘运算 Eigen 比 MATLAB 快了一倍,比 Op ...

  2. Eigen矩阵运算库快速上手

    目录 1. 配置 2. 初始化 2.1 Array类 2.2 Vector类 2.3 Matrix类 2.4 Vector赋值 2.5 高级初始化 3. 矩阵计算 3.1 矩阵基本计算 3.2 线性求 ...

  3. eigen 编译_OpenCV+Eigen上位机程序移植(七十一)

    1.给硬盘分区 现在小伙伴们对于给电脑硬盘分区想必比较头疼,给电脑硬盘分区分为两种情况,一是在安装系统之前给系统硬盘分区,二是在安装系统之后给硬盘分区,我们现在购买的品牌机和笔记本的用户比较多,而且笔 ...

  4. eigen库安装_OpenCV+Eigen上位机程序移植(七十一)

    1.给硬盘分区 现在小伙伴们对于给电脑硬盘分区想必比较头疼,给电脑硬盘分区分为两种情况,一是在安装系统之前给系统硬盘分区,二是在安装系统之后给硬盘分区,我们现在购买的品牌机和笔记本的用户比较多,而且笔 ...

  5. [视觉Slam十四讲(2)踩坑记录]第3讲:Fatal error :Eigen/core没有那个文件或目录

    [视觉Slam十四讲(2)踩坑记录]第3讲:Fatal error :Eigen/core没有那个文件或目录 问题描述: 在学习SlamBook2-ch3中对Eigen矩阵运算包内容时,编写好相关代码 ...

  6. Qt间接平差法进行直线拟合(Eigen运算、Qcustomplot绘图)

    目录 间接平差法进行直线拟合,使用Qt.Qcustomplot.Eigen 间接平差法直线拟合原理 工具介绍 Qt Qcustomplot Eigen 准备工作 1.Qt读取文件存入矩阵 2.Eige ...

  7. 我所理解的卡尔曼滤波——公式推导与应用

    我所理解的卡尔曼滤波--公式推导与应用 1.什么是卡尔曼滤波 2.卡尔曼滤波的数学推导 2.1 状态方程和测量方程 2.2 卡尔曼滤波过程 3 卡尔曼滤波应用 1.什么是卡尔曼滤波 先举个例子说一下什 ...

  8. opencv镜像_DX200操作要领—PAM与镜像平移变换(三十八)

    6.4 PAM功能 6.4.1 PAM功能 再现中的位置修改功能 (PAM 功能:Position Adjustment Manual) ,可在查看机器人动作状况的同时,在不停止机器人的情况下,通过简 ...

  9. 星之卡比镜之迷宫机器人_机器人工程师入门(0)

    前言:多年前看到一片知乎文章 YY硕:机器人工程师学习计划​zhuanlan.zhihu.com 当时看到这个,只觉醍醐灌顶,能看到有如此详尽的关于机器人工程师的个人技术发展规划,又不禁觉得有些遗憾, ...

最新文章

  1. 3. 定义10个字节的键盘缓冲区,然后键盘输入字符填满该缓冲区,做如下工作: (1)分别将输入键盘缓冲区的字符按数字,小写字母,大写字母,其他字符进行计数; 分别将这些计数值显示出来。 (2)分别将这
  2. python笔记 print+‘\r‘ (打印新内容时删除打印的旧内容)
  3. Python中shuffle() 函数的作用及用法
  4. windows下redis安装,注册成系统服务
  5. poll()函数详解
  6. 信号与系统郑君里上册pdf_信号与系统(上册)
  7. HTML的块级元素和行级元素的标签列表
  8. 【数据湖存储】数据湖的终极奥秘,无招胜有招
  9. oracle写转帐的存储过程,Oracle存储过程及块编程基础经典案例
  10. 笔记本暗屏维修多少钱_电视机烧了维修多少钱?
  11. bzoj 1670: [Usaco2006 Oct]Building the Moat护城河的挖掘(凸包)
  12. File类和各种io类会不会自动创建文件
  13. [翻译]WPF控件库 MaterialDesignInXamlToolkit (2) Brush Names
  14. python 笔记 冒泡排序
  15. C/C++[codeup 2043]小白鼠排队
  16. 【预测模型-ELAMN预测】基于哈里斯鹰算法优化ELMAN神经网络实现数据回归预测matlab代码
  17. fv计算机公式,p=fv是什么公式
  18. 冰点还原无法修改计算机时间,设置冰点还原解冻期间方法
  19. 如何快速识别图片中的文字?建议使用者两种方法
  20. 揭秘摄像头黑产链:暴露在外的80端口

热门文章

  1. 恶意软件每天至少30万个变种 杀毒软件捉襟见肘 来看4种恶意软件反查杀技术...
  2. 利用数据寿命增加基于闪存的存储类存储器的使用寿命
  3. 获取保存在沙盒中plist文件的用户的字典信息
  4. 学习C#要养成的好习惯
  5. oracle 分区表的建立方法
  6. 电脑中所有exe文件无法运行解决方案
  7. python中nlp的库_单词袋简介以及如何在Python for NLP中对其进行编码
  8. 如何一起破解图形化Python调试器
  9. 使用Fiddler进行HTTP流量分析
  10. 1015 Reversible Primes