Я хочу использовать механизм автоматического дифференцирования, предоставляемый
CppAD внутри линейной алгебры. Пример типа
Эйген :: Матрица< CppAD :: AD, -1, -1>. Так как CppAD :: AD является пользовательским числовым типом
NumTrait для этого типа должны быть предоставлены. CppAD обеспечивает
те, в файле cppad / пример / 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, это сработает. Однако это
не является решением, потому что продвижение типа практически используется
везде в Эйгене.
Мне кажется, что 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> > >’
Кто-нибудь может указать мне правильное направление? Возможно, что NumTrait для старых собственных версий. Я использую 3.3.2 и CppAD из
текущая мастер ветка.
Если вы хотите умножить 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;
Других решений пока нет …