c++ - Eigen::AutoDiff 的 Eigen::Spline 的错误模板参数

标签 c++ c++11 eigen splines autodiff

来自 EDIT 的解决方案现在作为答案发布。

老问题

我想将 Eigen::Spline 的样条插值包含到一个更大的公式中,并想在 Eigen::AutoDiff 的帮助下确定该公式的导数。

我尝试了以下代码:

#include <iostream>
#include <Eigen/Eigen>
#include <unsupported/Eigen/AutoDiff>
#include <unsupported/Eigen/Splines>

double array[] = {
    1.0, 2.0,
    3.0, 4.0,
    5.0, 1.0,
    6.0, 2.0
};

constexpr size_t nCols=2;
constexpr size_t rowSize=sizeof(array)/sizeof(double)/nCols;
constexpr size_t derOrder=1;

typedef Eigen::Map<Eigen::Matrix<double,1,rowSize>,Eigen::Unaligned,Eigen::InnerStride<nCols> > Map;

typedef const Eigen::Spline<double,nCols-1> Spline;

constexpr size_t interpolOrder=3;
constexpr double& xStop=array[nCols*(rowSize-1)];

Spline spline=Eigen::SplineFitting<Spline>::Interpolate(Map(array+1),interpolOrder,Map(static_cast<double*>(array))/xStop);

typedef Eigen::AutoDiffScalar<Eigen::Matrix<double,1,2> > DerType;

DerType f(const DerType& x){
    DerType ret;
    auto y = spline.derivatives<1>(x.value()/xStop);
//*** Compilation is okay if previous line is substituted with:
// Eigen::Array<double,1,2> y; y << 1.0, 2.0;
    ret.value() = y(0,0);
    ret.derivatives() = x.derivatives()*y(0,0);
    return ret;
}


int main() {
    DerType x(1.0,DerType::DerType(1.0,1.0));

    auto y = f(x);

    std::cout << "\nValue=" << y.value() << "\nDer=" << y.derivatives() << '\n';

    return 0;
}


/*
    Local Variables:
    compile-command: "g++ -g -std=c++11 -I/usr/local/include/eigen3 eigenInterpolAD.cc -o a.exe && (echo \"Running\"; ./a.exe);"
    End:
*/

遗憾的是,代码编译报错如下:

g++ -g -std=c++11 -I/usr/local/include/eigen3 eigenInterpolAD.cc -o a.exe && (echo "Running"; ./a.exe);
In file included from /usr/local/include/eigen3/Eigen/Core:254:0,
                 from /usr/local/include/eigen3/Eigen/Dense:1,
                 from /usr/local/include/eigen3/Eigen/Eigen:1,
                 from eigenInterpolAD.cc:5:
/usr/local/include/eigen3/Eigen/src/Core/PlainObjectBase.h: In instantiation of ‘static void Eigen::PlainObjectBase<Derived>::_check_template_params() [with Derived = Eigen::Array<double, 1, -1, 0, 1, 2>]’:
/usr/local/include/eigen3/Eigen/src/Core/Array.h:195:36:   required from ‘Eigen::Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::Array(const Eigen::Array<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>&) [with _Scalar = double; int _Rows = 1; int _Cols = -1; int _Options = 0; int _MaxRows = 1; int _MaxCols = 2]’
eigenInterpolAD.cc:33:48:   required from here
/usr/local/include/eigen3/Eigen/src/Core/util/StaticAssert.h:32:40: error: static assertion failed: INVALID_MATRIX_TEMPLATE_PARAMETERS
     #define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG);
                                        ^
/usr/local/include/eigen3/Eigen/src/Core/PlainObjectBase.h:657:7: note: in expansion of macro ‘EIGEN_STATIC_ASSERT’
       EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor)
       ^

如何避免错误?在此先感谢您提供任何有用的提示。

Eigen 版本为 3.2.1。对于 Eigen 3.1 和 3.0 版,编译也失败。

编译器版本为:

gcc 版本 4.8.1 (Ubuntu/Linaro 4.8.1-10ubuntu9)

最佳答案

作为用户 Anycorn指出“老问题”部分的源代码在 Bitbucket 上使用最新版本的 Eigen 编译和运行:

$hg showconfig
bundle.mainreporoot=/usr/local/eigen
paths.default=https://bitbucket.org/eigen/eigen
/usr/local/eigen
$hg identify
fabd880592ac tip
/usr/local/eigen

我用下面的代码测试了这个原理:

/**
     Spline interpolation with AD.
 */
#include <iostream>
#include <fstream>
#include <Eigen/Eigen>
#include <unsupported/Eigen/AutoDiff>
#include <unsupported/Eigen/Splines>

constexpr const double array[] = {
    1.0, 2.0,
    3.0, 4.0,
    5.0, 1.0,
    6.0, 2.0
};

constexpr size_t nCols=2;
constexpr size_t rowSize=sizeof(array)/sizeof(double)/nCols;
constexpr size_t derOrder=1;

typedef Eigen::Map<Eigen::Matrix<double,1,rowSize>,Eigen::Unaligned,Eigen::InnerStride<nCols> > Map;

typedef Eigen::Spline<double,nCols-1> Spline;

constexpr size_t interpolOrder=3;
constexpr double xStart=array[0];
constexpr double xStop=array[nCols*(rowSize-1)];
constexpr double xDelta=xStop-xStart;

const Spline spline=Eigen::SplineFitting<Spline>::Interpolate(Map(
        const_cast<double*>(array)+1),
    interpolOrder,
    (Map(const_cast<double*>(array)).array()-xStart)/xDelta);

typedef Eigen::AutoDiffScalar<Eigen::Matrix<double,1,2> > DerType;

DerType f(const DerType& x){
    DerType ret;
    auto y = spline.derivatives<1>((x.value()-xStart)/xDelta);
    ret.value() = y(0,0);
    ret.derivatives() = x.derivatives()*y(0,1)/xDelta;
    return ret;
}


int main() {
    std::ofstream of("/temp/test.dat");

    constexpr size_t n=101;
    const double xStart=0.0;
    const double xStop=6.0;
    const double dx=(xStop-xStart)/(n-1);

    double x=xStart;

    for(size_t i=0; i!=n; i++, x+=dx) {
        DerType xAD(x,DerType::DerType(1.0,1.0));
        auto yAD = f(xAD);

        of << x << ' ' << yAD.value() << ' ' << yAD.derivatives()[0] << '\n';
    }

    of.close();

    return 0;
}


/*
    Local Variables:
    compile-command: "g++ -g -std=c++11 -I/usr/local/include/eigen3 eigenInterpolAD.cc -o a.exe && (echo \"Running\"; ./a.exe);"
    End:
*/

下面生成的数据图表明代码现在可以在 hg 版本的 Eigen 上正常工作。红色曲线是插值样条曲线,绿色曲线是它的导数。

enter image description here

关于c++ - Eigen::AutoDiff 的 Eigen::Spline 的错误模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22851258/

相关文章:

C++ XInput 和 XBOX 360 Controller 从不连接

c++ - 如何在 C++11 中创建我自己的 initializer_list 类?

c++ - Eigen 程序中的性能瓶颈

eigen - 在 Eigen 中混合标量类型

c++ - 为什么有些东西在 C++ 中留下未定义的行为?如果其中一些在标准中预先定义不是更好吗?

c++ - 有没有一种方法可以将一 block 无符号字符移动到 STL vector 中,而不是一次移动 1 个无符号字符

c++ - 如何在 Gui win32 编程中使用静态标签和按钮

c++ - C++11 中的默认构造函数、POD 的初始化和隐式类型转换

c++ - 在不知道确切名称的情况下读取文件夹中的图像

c++ - 从一个稀疏矩阵中提取一个 block 作为另一个稀疏矩阵