Числовые рецепты: функции-члены класса в качестве аргументов

Мой вопрос касается числовых рецептов. Я пытаюсь использовать решатель сопряженных градиентов «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);
}

Затем все это вызывается в основном с помощью

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:: в вызове функции, но безрезультатно. Когда я компилирую пример файла «xfrprmn.cpp» из числовых рецептов, используя тот же компилятор и инфраструктуру make-файла, он компилируется и запускается без проблем. Я не вижу большой разницы с моим собственным кодом, за исключением того, что мои целевые и градиентные подпрограммы являются функциями-членами класса, поэтому мне интересно, не это ли меня сбивает с толку. Любая помощь очень ценится.


person Eric    schedule 14.06.2013    source источник
comment
Какой компилятор? Между прочим, Clang обычно имеет гораздо лучшие сообщения об ошибках, чем gcc/g++ .   -  person denis    schedule 26.07.2013


Ответы (2)


Я нашел обходной путь, с помощью которого я адаптирую подпрограммы Numerical Recipes, чтобы принимать в качестве аргументов указатели на мой объект класса вместо указателей на объективные и градиентные функции. Внутри подпрограмм я изменил код таким образом, чтобы они вызывали функции-члены переданного им объекта класса. Все равно было бы интересно, есть ли более элегантное решение.

person Eric    schedule 17.06.2013

аргумент типа 'DP (kalman_yield_only::)(Vec_I_DP&) {aka double (kalman_yield_only::)(const NRVec&)}' не соответствует 'DP (*)(Vec_I_DP&){aka double (*)(const NRVec&)}'

Это означает, что вы пытаетесь использовать метод (который нуждается в скрытом указателе this), где ожидается функция. Numerical Recipes в C++ на самом деле не C++, так как он предполагает, что вы будете использовать глобальные/статические переменные!!!!

Я думаю, что я бы отредактировал числовые рецепты, чтобы функция, которую вы передаете, была аргументом шаблона - означает, что в месте использования она не определена, кроме того, что ей нужен векторный аргумент и она возвращает двойной:

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

Написание frprmn таким образом по-прежнему позволяет передавать обычный указатель на функцию.

Затем определите функцию как operator() вашего класса, содержащую всю информацию:

    struct YourClass
    {
            double operator()(const NRVec&) const;
    };
person Community    schedule 03.11.2013