我正在尝试将 CppAD 标量类型与 Eigen 一起使用。
以下无法编译:

#include <Eigen/Dense>
#include <cppad/cppad.hpp>
#include <cppad/example/cppad_eigen.hpp>

int main()
{
    using Scalar = CppAD::AD<double>;
    //using Scalar = double;

    Eigen::Matrix<Scalar, 1,4> row;
    Eigen::Matrix<Scalar, 4,1> col;
    Scalar scalar = 5;

    Scalar res2 = row * col + scalar; //fails

    return 0;
}
错误基本上是它不能向乘法的结果添加标量。但是,乘法的结果本身就是一个标量,所以应该没有问题。事实上,当使用 double 作为 Scalar 类型时,没有问题。
这是编译器错误:
cppad-eigen-problem.cpp:14:29: error: no match for ‘operator+’ (operand types are ‘const Eigen::Product<Eigen::Matrix<CppAD::AD<double>, 1, 4>, Eigen::Matrix<CppAD::AD<double>, 4, 1, 0, 4, 1>, 0>’ and ‘Scalar’ {aka ‘CppAD::AD<double>’})
   14 |     Scalar res2 = row * col + scalar; //fails
      |                   ~~~~~~~~~ ^ ~~~~~~
      |                       |       |
      |                       |       Scalar {aka CppAD::AD<double>}
      |                       const Eigen::Product<Eigen::Matrix<CppAD::AD<double>, 1, 4>, Eigen::Matrix<CppAD::AD<double>, 4, 1, 0, 4, 1>, 0>

有一个 issue on the CppAD project ,但我不确定问题出在哪里:
  • 如果我使用另一个微不足道的自定义标量,则无法重现该错误...
  • 另一方面,标量类型的 CppAD Eigen traits 对我来说看起来不错。

  • 版本:Eigen 3.3.7,最新的 CppAD 大师,g++ 9.3.0
    有什么线索吗?
    谢谢

    最佳答案

    虽然 (1x1) 矩阵是标量在数学上是正确的,但 C++ 是一个不同的故事:operator*row * col 的返回类型不是标量,也不是 (1x1) 矩阵,而是乘积表达式。此乘积表达式可隐式转换为其操作数的标量类型,在本例中为 CppAD::AD<double>
    您看到的错误的原因是 CppAD::AD<double> 是一个模板,因此它的运算符是函数模板,例如就像是

    template<typename T>
    CppAD::AD<T> operator+(const CppAD::AD<T>& lhs, const CppAD::AD<T>& rhs);
    
    现在的问题是无法调用上述模板化的 operator+ ,因为模板参数中没有隐式转换,而正是将乘积表达式转换为 CppAD::AD<double> 需要这样做。
    这也是避免产品起作用的原因(例如,通过使用 Eigen 的 .dot 函数)。
    不过你可以通过例如解决这个问题定义适当的 operator+ ,例如(未测试)
    template<typename Derived>
    CppAD::AD<double>  operator+(const MatrixBase<Derived>& lhs, const CppAD::AD<double> & rhs) {
      return lhs.derived().coeff(0, 0) + rhs;
                         //^^^^^^^^^^^ No need for an implicit conversion
    }
    
    或者您可以使用 Eigen's plugin mechanism 并向 MatrixBase 添加一个运算符。

    关于c++ - 行时间列不是标量,具有自定义标量类型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/65019299/

    10-12 19:06