Member 13922009 Ответов: 1

Как вызвать функцию-член, когда мы применили nlopt в нашей программе ?


Я попытался реализовать библиотеку nlopt в своей программе с помощью класса CNonlinearOptimization. Проблема заключается в том, что при использовании указателя для вызова функции-члена "myfunction" я получил ошибки, потому что функция не совпадает с параметром типа "nlopt_func".

Вот функция-член:
double CNonlinearOptimization::myfunction(unsigned n, const double *x, double *grad, void *my_constraint_data) {
	if (grad) {
		grad[0] = 2*k1*(x[0]-1);
		grad[1] = 2*k2*(x[1]-3);
		grad[2] = 2*k3*(x[2]-5);
	}

	return (k1*(x[0]-1)*(x[0]-1)+k2*(x[1]-3)*(x[1]-3)+k3*(x[2]-5)*(x[2]-5));
}

double CNonlinearOptimization::myconstraint1(unsigned n, const double *x, double *grad, void *data){
	++count;
	if (grad) {
		grad[0] = -1;		//grad[0] = d(c1)/dx1
		grad[1] = 0;		//grad[1] = d(c1)/dx2
		grad[2] = 0;		//grad[2] = d(c1)/dx3
	}
	return (0.9-(x[0]-2));
}


А ошибка-это "myfunction" и "myconstraint1" в основной функции, как показано ниже
int CNonlinearOptimization::main() {

	CNonlinearOptimization nonlinopt;

	double lb[2] = { -HUGE_VAL, 0 }; // lower bounds 

	double x[3] = {0,0,1};  // `*`some` `initial` `guess`*` 
	double minf; // `*`the` `minimum` `objective` `value,` `upon` `return`*`

	opt = nlopt_create(NLOPT_LD_MMA, 3); // algorithm and dimensionality 
	nlopt_set_lower_bounds(opt, lb);

	nlopt_set_min_objective(opt,myfunction, NULL);

	nlopt_add_inequality_constraint(opt, myconstraint1, NULL, 1e-8);
	
	nlopt_set_xtol_rel(opt, 1e-4);

	if (nlopt_optimize(opt, x, &minf) < 0) {
		printf("nlopt failed!\n");
	}
	else {
		printf("found minimum after %d evaluation\n", nonlinopt.count);
		printf("found minimum at f(%0.10g,%0.10g,%0.10g) = %0.10g\n", x[0], x[1], x[2], minf);
	}

	nlopt_destroy(opt);
	system("pause");
	return 0;
}


Что я уже пробовал:

Я попытался сделать указатель
nonlinopt.myfunction
и еще один указатель, но он выглядит не очень хорошо. Как я могу ее решить ?

Richard MacCutchan

Каковы фактические сообщения об ошибках?

Member 13922009

Вот эта ошибка:


nonlinearoptimization.cpp(274): ошибка C3867: 'CNonlinearOptimization::myfunction в консоли': вызов функции отсутствует список аргументов; используйте '&амп;CNonlinearOptimization::myfunction в консоли для создания указателя на член


nonlinearoptimization.cpp(276): ошибка C3867: 'CNonlinearOptimization::myconstraint1': вызов функции отсутствует список аргументов; используйте '&CNonlinearOptimization::myconstraint1' для создания указателя на член


Richard MacCutchan

Ну, это кажется достаточно ясным.

Member 13922009

но когда я попробовал это сделать, все равно ошибка

Richard MacCutchan

Какая ошибка? Пожалуйста, не думайте, что мы можем видеть то, что отображается на вашем экране.

1 Ответов

Рейтинг:
0

Rick York

Что мне нравится делать, когда я имею дело с указателями на функции, так это создавать для них typedef. Вот один из них для функции, используемой с вызовом BeginThread в Windows :

typedef UINT( __stdcall * ThreadFunc )( PVOID );
Похоже, что в библиотеке тоже есть один файл под названием nlopt_func. В документации показано, что функция имеет прототип :
double f(unsigned n, const double* x, double* grad, void* f_data)
Проблема в том, что это не прототип для метода вашего класса. Это самостоятельная функция. Это означает, что вы должны передать указатель на свой объект через параметр f_data. Вы должны реализовать его следующим образом :
double MyFunction( unsigned n, const double *x, double *grad, void *pdata )
{
   CNonlinearOptimization * pnlo = (CNonlinearOptimization *)pdata;
   pnlo->myfunction( n, x, grad );
}
и вы должны удалить my_constraint_data в качестве аргумента вашего метода, как показано в этом фрагменте кода.

Эту же тактику следует использовать и с mycontstraint1.