Сочетание Eigen и CppAD

Я хочу использовать механизм автоматического дифференцирования, предоставляемый CppAD, внутри линейной алгебры Eigen. Примером типа является Eigen::Matrix‹ 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.

Мне кажется, что NumTraits, предоставленные CppAD, недостаточны для этого случая. Это подтверждается последующим сообщением об ошибке:

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 относятся к старым собственным версиям. Я использую 3.3.2 и CppAD из текущей основной ветки.


person theoreticallyapplied    schedule 20.07.2017    source источник
comment
Почему вы не хотите, чтобы m имел тип Eigen::Matrix<AD,Eigen::Dynamic,Eigen::Dynamic>?   -  person Alex    schedule 20.07.2017


Ответы (1)


Если вы хотите умножить 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;
person chtz    schedule 20.07.2017