结合Eigen和CppAD

时间:2017-07-20 16:41:09

标签: c++ templates eigen automatic-differentiation

我想使用提供的自动差异化机制 特征线性代数中的CppAD。一个示例类型是 征::矩阵和LT; CppAD :: AD,-1,-1。由于CppAD :: AD是自定义数字类型 必须提供此类型的NumTraits。 CppAD提供 文件cppad/example/cppad_eigen.hpp中的那些文件。这使得 按照最小的例子编译:

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

int main() {
   typedef double Scalar;
   typedef CppAD::AD<Scalar> AD;

   // independent variable vector
   Eigen::Matrix<AD,Eigen::Dynamic,1> x(4);
   CppAD::Independent(x);

   // dependent variable vector 
   Eigen::Matrix<AD,Eigen::Dynamic,1> y(4);

   Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> m(4,4);
   m.setIdentity();

   y = 1. * x;
   // THIS DOES NOT WORK
   // y = m * x;

   CppAD::ADFun<Scalar> fun(x, y);
}

一旦使用一些更复杂的表达式,例如该 提到

y = m * x;

代码无法编译:

PATH/Eigen/latest/include/Eigen/src/Core/Product.h:29:116: error: 
      no type named 'ReturnType' in 'Eigen::ScalarBinaryOpTraits<double, CppAD::AD<double>,
      Eigen::internal::scalar_product_op<double, CppAD::AD<double> > >'
  ...typename ScalarBinaryOpTraits<typename traits<LhsCleaned>::Scalar, typename traits<RhsCleaned>::Scalar>::ReturnType...

如果我手动将双矩阵转换为AD,它可以正常工作。不过这个 不是解决方案,因为实际上使用了类型促销 在Eigen到处都是。

在我看来,CppAD提供的NumTraits不足以满足这种情况。后续错误消息支持此功能:

PATH/Eigen/latest/include/Eigen/src/Core/Product.h:155:5: error: 
      no type named 'CoeffReturnType' in
      'Eigen::internal::dense_product_base<Eigen::Matrix<double, -1, -1, 0, -1, -1>,
      Eigen::Matrix<CppAD::AD<double>, -1, 1, 0, -1, 1>, 0, 7>'
    EIGEN_DENSE_PUBLIC_INTERFACE(Derived)
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

其他用例会导致错误消息,如:

PATH/Eigen/src/Core/functors/Binary
Functors.h:78:92: error: no type named ‘ReturnType’ in ‘struct Eigen::ScalarBinaryOpTraits<dou
ble, CppAD::AD<double>, Eigen::internal::scalar_product_op<double, CppAD::AD<double> > >’

有人能指出我正确的方向吗? NumTraits可能适用于旧的Eigen版本。我使用的是3.3.2和CppAD 现任主分公司。<​​/ p>

1 个答案:

答案 0 :(得分:5)

如果您想将Matrix<CppAD::AD<double>, ...>乘以Matrix<double, ...>,您还需要专门化相应的ScalarBinaryOpTraits

namespace Eigen {
template<typename X, typename BinOp>
struct ScalarBinaryOpTraits<CppAD::AD<X>,X,BinOp>
{
  typedef CppAD::AD<X> ReturnType;
};

template<typename X, typename BinOp>
struct ScalarBinaryOpTraits<X,CppAD::AD<X>,BinOp>
{
  typedef CppAD::AD<X> ReturnType;
};
} // namespace Eigen

这要求CppAD::AD<X>() * X()已实施。

或者,您需要将矩阵m投射到AD

// should work:
y = m.cast<CppAD::AD<double> >() * x;