2017-07-20 4 views
3

Je veux utiliser le mécanisme de différenciation automatique fourni par CppAD à l'intérieur de l'algèbre linéaire Eigen. Un exemple de type est Eigen :: Matrix < CppAD :: AD, -1, -1>. Comme CppAD :: AD est un type numérique personnalisé les NumTraits pour ce type doivent être fournis. CppAD fournit ceux dans le fichier cppad/example/cppad_eigen.hpp. Cela rend le suivants compilent exemple minimal:Combinaison Eigen et CppAD

#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); 
} 

Dès une expression plus complexe est utilisé, par exemple la dessus

y = m * x; 

le code ne parvient pas à compiler:

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... 

Si je jette manuellement la double matrice de AD, il fonctionne. Cependant cette n'est pas une solution car la promotion de type est pratiquement utilisée partout dans Eigen.

Il me semble que les NumTraits fournis par CppAD ne sont pas suffisants pour ce cas. Ceci est soutenu par un message d'erreur suivi:

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) 
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

D'autres cas d'utilisation conduisent à des messages d'erreur comme:

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> > >’ 

Quelqu'un peut-il me diriger dans la bonne direction? Il est possible que les NumTraits soient pour les anciennes versions Eigen. J'utilise 3.3.2 et CppAD de la branche maître actuelle .

+0

Pourquoi vous ne voulez pas 'm' pour avoir taper' Eigen :: matrice '? – Alex

Répondre

3

Si vous souhaitez multiplier un Matrix<CppAD::AD<double>, ...> par un Matrix<double, ...> vous devez également se spécialiser correspondant 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 

Cela exige que CppAD::AD<X>() * X() est mis en œuvre.

Sinon, vous devez jeter votre matrice m-AD:

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