【问题标题】:Eigen gives wrong result when not storing intermediate resultEigen 在不存储中间结果时给出错误的结果
【发布时间】:2020-01-03 23:27:50
【问题描述】:

为牛顿方法编写一个实现雅可比矩阵的函数我注意到一个非常严重的错误。

调用函数

auto DF = [T](VectorXd y){
    return PhiAndW(y(0),y(1),T).second - MatrixXd::Identity(2,2);
 };

只返回PhiAndW(y(0),y(1),T).second 的值,省略MatrixXd::Identity(2,2) 的减法。但是如果我将代码更改为

auto DF = [T](VectorXd y){
    MatrixXd mat = PhiAndW(y(0),y(1),T).second - MatrixXd::Identity(2,2);
    return mat;
 };

一切都可以无缝运行。

我试图重现它,这不是完全相同的行为,但它的行为也不尽如人意:

考虑以下代码:

MatrixXd FF(MatrixXd y){
  return y;
}

int other(){

  auto DF = [](MatrixXd y){
    MatrixXd test = FF(y)  - MatrixXd::Identity(2,2);
    return test;
  };

  std::cout << DF(MatrixXd::Ones(2,2)) <<std::endl;
  std::cout << std::endl;
  std::cout << (MatrixXd::Ones(2,2) - MatrixXd::Identity(2,2))<< std::endl;

}

它会打印出来

>  1 0
>  0 1 
>
>  1 0 
>  0 1 

到控制台。

但是,如果我将功能 DF 更改为

  auto DF = [](MatrixXd y){
    return FF(y)  - MatrixXd::Identity(2,2);
  };

控制台将打印

>  2.22045e-15 1.63042e-322
>  2.37152e-322    -0.999998

对于第二个矩阵。 (这只是记忆中一些未初始化的垃圾)。

有人能解释一下我的代码和我的示例问题发生了什么吗?我真的不知道这里发生了什么。我特别感兴趣为什么将计算结果保存在临时变量中可以解决问题。

【问题讨论】:

  • 请阅读本页关于使用auto的部分:eigen.tuxfamily.org/dox-devel/TopicPitfalls.html
  • (在这种情况下,auto 隐含地是 lambda 的返回类型)
  • 你试过auto DF = []() -&gt; MatrixXd {...} 吗?这应该强制评估返回值。
  • 这是另一个很好的例子,auto 可能不像其他人(除了我)似乎相信的那样酷。 ;-) 我假设显式转换也可以修复第一个样本:auto DF = [](MatrixXd y){ return MatrixXd(FF(y) - MatrixXd::Identity(2,2)); };

标签: c++ eigen


【解决方案1】:

由于 cmets 几乎解决了我的问题(非常感谢),我想我会继续回答我的问题,以便其他人看到这个问题已经解决。

为什么会出现问题?

问题在于,例如,两个矩阵的特征乘法的结果类型不是特征矩阵,而是一些表示乘法并引用我们试图相乘的两个矩阵的内部对象。

因此,如果我们使用 auto 关键字,编译器很可能不会给出我们设置类型为 MatrixXd 的变量,而是给出某个内部对象的类型。

有关更多信息,请参阅Eigen documentation,其中明确指出:

简而言之:不要在 Eigen 表达式中使用 auto 关键字,除非您 100% 确定自己在做什么。特别是,不要使用 auto 关键字代替 Matrix 类型

如何防止它发生?

  • 不要使用auto 关键字,使用显式类型。
  • 对于 lambda 函数,始终指定返回类型:写入 auto DF = []() -&gt; MatrixXd {...} 而不是 auto DF = []() {...}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-19
    • 1970-01-01
    • 2011-11-15
    • 2019-02-06
    • 2014-01-30
    • 2018-08-01
    • 2016-08-30
    • 1970-01-01
    相关资源
    最近更新 更多