0

我的问题涉及数字食谱。我正在尝试使用共轭梯度求解器“frprmn.cpp”来最小化取决于数据和一堆其他参数的问题的负对数似然函数。为了让所有相关参数和数据可用于评估对数似然,我编写了一个类,对数似然函数和梯度函数都是该类的成员函数。当我使用这些函数作为参数调用 frprmn 时,我收到错误消息

'DP (kalman_yield_only::)(Vec_I_DP&) {aka double (kalman_yield_only::)(const NRVec&)}' 类型的参数不匹配 'DP (*)(Vec_I_DP&){aka double (*)(const NRVec&)}'

目标对数似然函数和梯度函数在名为 kalman_yield_only.cpp 的文件中定义如下,该文件还定义了名称为 kalman_yield_only 的类。

DP kalman_yield_only::llh(Vec_I_DP& theta)
{
    ...code...;
    DP L_num=...;
    return L_num;
}

梯度函数为:

void kalman_yield_only::llh_grad(Vec_I_DP& theta, Vec_O_DP& grad)
{
    ...code...;
}

同一个文件还有一个调用求解器的成员函数:

void kalman_yield_only::optimizer(Vec_IO_DP& theta)
{   
    const double ftol = 1e-6;
    double fret;
    int iter;
    NR::frprmn(theta,ftol,iter,fret,kalman_yield_only::llh,kalman_yield_only::llh_grad);
}

然后整个事情被 main 调用

int main(int arg, char* pszArgs[])
{
    ...code for data and parameters...;
    kalman_yield_only ks(...data and parameters...);
    ...code for theta...;
    ks.optimizer(theta);
    ...code for doing stuff with theta...;
    return 0;
}

在 kalman_yield_only.h 中,我有线条

class kalman_yield_only
{
 public:
  kalman_yield_only(Mat_IO_DP& , Mat_IO_DP& , Vec_IO_DP& , Vec_IO_DP& , Mat_IO_DP& ,   Mat_IO_DP& , DP& , DP& , DP& , DP& , DP&, Vec_IO_DP& );

// All sorts of data and parameter object declarations...

  // Member functions
  DP llh(Vec_I_DP &);
  void llh_grad(Vec_I_DP & , Vec_O_DP & );
  void optimizer(Vec_IO_DP& );
};

kalman_yield_only.cpp 中对应的构造函数如下:

kalman_yield_only::kalman_yield_only(Mat_IO_DP& Y_in, Mat_IO_DP& Z_in, Vec_IO_DP& vH_in, Vec_IO_DP& c_in, Mat_IO_DP& mT_in, Mat_IO_DP& Q_in, DP& maxZ_in, DP& maxT_in, DP& maxQ_in, DP& maxc_in, DP& tol_in, Vec_IO_DP& Maturities_in )
{
    … code...;
}

我想我尝试了在函数调用中添加和删除 NR:: 和 kalman_yield_only:: 前缀的所有排列,但无济于事。当我使用相同的编译器和 make-file 基础结构从数值配方编译示例文件“xfrprmn.cpp”时,它可以毫无问题地编译和运行。除了我的目标和渐变例程是类的成员函数之外,我看不出我自己的代码有什么不同,所以我想知道这是否是让我感到困惑的原因。非常感谢任何帮助。

4

2 回答 2

0

'DP (kalman_yield_only::)(Vec_I_DP&) {aka double (kalman_yield_only::)(const NRVec&)}' 类型的参数不匹配 'DP (*)(Vec_I_DP&){aka double (*)(const NRVec&)}'

这意味着您正在尝试在需要函数的地方使用方法(需要隐藏的 this 指针)。C++ 中的数值配方并不是真正的 C++,因为它希望您使用全局/静态变量!!!!

我想我会编辑数值配方,以便您传递的函数是一个模板参数 - 意味着在使用位置它没有定义,除了它需要一个向量参数并返回一个双精度:

    template<typename FUNCTION>
    frprmn(..., const FUNCTION &_rF, ....)
    {
            ...
    }

像这样编写 frprmn 仍然可以让您传递一个普通的函数指针。

然后将函数定义为包含所有信息的类的 operator() :

    struct YourClass
    {
            double operator()(const NRVec&) const;
    };
于 2013-11-03T21:34:52.057 回答
0

我找到了一种解决方法,我调整了 Numerical Recipes 例程,以便将指向我的类对象的指针作为参数,而不是指向目标函数和梯度函数的指针。在例程中,我更改了代码,以便它们调用所传递的类对象的成员函数。如果有更优雅的解决方案,仍然会感兴趣。

于 2013-06-17T14:56:21.543 回答