Member 13922009 Ответов: 1

Как решить проблему "необработанное исключение было обнаружено во время обратного вызова пользователя" ?


Я пытаюсь реализовать NLOPT в классе в своей программе. Ошибки заключаются в следующем :
Warning	7	warning C4717: 'NonlinearOpt::nlopt_add_inequality_constraint' : recursive on all control paths, function will cause runtime stack overflow	d:\program\robotsimu190902_salah\robotsimu\nonlinearopt.cpp	142
Warning	6	warning C4717: 'NonlinearOpt::nlopt_create' : recursive on all control paths, function will cause runtime stack overflow	d:\program\robotsimu190902_salah\robotsimu\nonlinearopt.cpp	149
Warning	10	warning C4717: 'NonlinearOpt::nlopt_optimize' : recursive on all control paths, function will cause runtime stack overflow	d:\program\robotsimu190902_salah\robotsimu\nonlinearopt.cpp	169
Warning	9	warning C4717: 'NonlinearOpt::nlopt_set_lower_bounds' : recursive on all control paths, function will cause runtime stack overflow	d:\program\robotsimu190902_salah\robotsimu\nonlinearopt.cpp	156
Warning	5	warning C4717: 'NonlinearOpt::nlopt_set_min_objective' : recursive on all control paths, function will cause runtime stack overflow	d:\program\robotsimu190902_salah\robotsimu\nonlinearopt.cpp	177
Warning	8	warning C4717: 'NonlinearOpt::nlopt_set_xtol_rel' : recursive on all control paths, function will cause runtime stack overflow	d:\program\robotsimu190902_salah\robotsimu\nonlinearopt.cpp	161


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

Вот код, который я сошел с ума :
&ЛТ;nonlinearopt.ч&ГТ;
#ifndef __NONLINEAROPT_H__
#define __NONLINEAROPT__
#pragma once

#include "stdafx.h"

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <windows.h>
#include <iostream>

#include "nlopt.h"

#pragma comment(lib, "libnlopt-0.lib")

class NonlinearOpt
{
private:

public:
	double ankle_angle;		//ankle angle from GA
	double knee_angle;		//knee angle from GA
	double pelvis_angle;	//pelvis angle from GA

	double k1;
	double k2;
	double k3;
	
	double max_ankle;		//maximum ankle angle
	double max_knee;		//maximum knee angle
	double max_pelvis;		//maximum pelvis angle

	double min_ankle;		//minimum ankle angle
	double min_knee;		//minimum knee angle
	double min_pelvis;		//minimum pelvis angle

	double new_ankle_angle;
	double new_knee_angle;
	double new_pelvis_angle;

public:
	NonlinearOpt(void){

		//constant value
		k1 = 1.0;
		k2 = 1.0;
		k3 = 1.0;

	};

	~NonlinearOpt(void){

	};

	public:

/************************** Nonlinear Equations ********************************/

	//joint function (f)
	double myfunction(unsigned int n, const double *theta, double *grad);

	//constraint function (c) for solution 1
	double myconstraint1(unsigned int n, const double *x, double *grad);	//c1
	double myconstraint2(unsigned n, const double *x, double *grad);		//c2	
double myconstraint6(unsigned n, const double *x, double *grad);		//c6
	
	int main();

/****************** NLOPT Functions ****************************/
	//add inequality constraints
	nlopt_result nlopt_add_inequality_constraint(nlopt_opt opt, nlopt_func fc, void* fc_data, double tol);

	//add equality constraints
	nlopt_result nlopt_add_equality_constraint(nlopt_opt opt, nlopt_func h, void* h_data, double tol);

	//create the dimension of algorithm
	nlopt_opt nlopt_create(nlopt_algorithm algorithm, unsigned n);

	//add the lower bounds for minimalization
	nlopt_result nlopt_set_lower_bounds(nlopt_opt opt, const double* lb);

	//add the variable's tolarance
	nlopt_result nlopt_set_xtol_rel(nlopt_opt opt, double tol);

	//for minimal optimization
	nlopt_result nlopt_optimize(nlopt_opt opt, double *x, double *opt_f);
	nlopt_result nlopt_set_min_objective(nlopt_opt opt, nlopt_func f, void* f_data);

	//destroy optimization
	void nlopt_destroy(nlopt_opt opt);
};

#endif


&ЛТ;nonlinearopt.НПК&ГТ;
#include "stdafx.h"
#include "NonlinearOpt.h"

typedef UINT( __stdcall * ThreadFunc )( PVOID );


//solution 1
//f= k2(x2-a2)^2 + k3(x3-a3)^2 
double NonlinearOpt::myfunction(unsigned int n, const double *theta, double *grad) {
	if (grad) {
		grad[0] = 2*k1*(theta[0]-ankle_angle);
		grad[1] = 2*k2*(theta[1]-knee_angle);
		grad[2] = 2*k3*(theta[2]-pelvis_angle);
	}

	return (k1*(theta[0]-ankle_angle)*(theta[0]-ankle_angle) + k2*(theta[1]-knee_angle)*(theta[1]-knee_angle) + k3*(theta[2]-pelvis_angle)*(theta[2]-pelvis_angle));
}

//wrapper function of myfunction
double MyFunction( unsigned n, const double *theta, double *grad, void *pdata )
{
   NonlinearOpt * pnlo = (NonlinearOpt *)pdata;
   return pnlo->myfunction( n, theta, grad );
}

//nlopt constraints h(x)<=0 
//c1 = theta1_min - theta1
double NonlinearOpt::myconstraint1(unsigned n, const double *theta, double *grad){
	//++count;
	if (grad) {
		grad[0] = -1;		//grad[0] = d(c1)/dtheta1
		grad[1] = 0;		//grad[1] = d(c1)/dtheta2
		grad[2] = 0;		//grad[2] = d(c1)/dtheta3
	}
	return (min_ankle - theta[0]);
}

//wrapper function of myconstraint1
double MyConstraint1( unsigned n, const double *theta, double *grad, void *pdata )
{
   NonlinearOpt * pnlo = (NonlinearOpt *)pdata;
   return pnlo->myconstraint1( n, theta, grad );
}

//c2 = theta1 - theta1_max
double NonlinearOpt::myconstraint2(unsigned n, const double *theta, double *grad){
	//++count;
	if (grad) {
		grad[0] = 1;		//grad[0] = d(c2)/dtheta1
		grad[1] = 0;		//grad[1] = d(c2)/dtheta2
		grad[2] = 0;		//grad[2] = d(c2)/dtheta3
	}
	return (theta[0] - max_ankle);
}

//wrapper function of myconstraint2
double MyConstraint2( unsigned n, const double *theta, double *grad, void *pdata )
{
   NonlinearOpt * pnlo = (NonlinearOpt *)pdata;
   return pnlo->myconstraint2( n, theta, grad );
}



nlopt_result NonlinearOpt::nlopt_add_inequality_constraint(nlopt_opt opt, nlopt_func fc, void *fc_data, double tol){
	opt = opt;
	fc = fc;
	fc_data = fc_data;
	tol = tol;

	return nlopt_add_inequality_constraint(opt, fc, fc_data, tol);
}

nlopt_opt NonlinearOpt::nlopt_create(nlopt_algorithm algorithm, unsigned int n){
	algorithm = algorithm;
	n=n;

	return nlopt_create(algorithm, n);
}

nlopt_result NonlinearOpt::nlopt_set_lower_bounds(nlopt_opt opt, const double *lb){
	opt = opt;
	lb = lb;

	return nlopt_set_lower_bounds(opt, lb);
}

nlopt_result NonlinearOpt::nlopt_set_xtol_rel(nlopt_opt opt, double tol){

	return nlopt_set_xtol_rel(opt, tol);
}

nlopt_result NonlinearOpt::nlopt_optimize(nlopt_opt opt, double *x, double *opt_f){
	opt = opt;
	x = x;
	opt_f = opt_f;

	return nlopt_optimize(opt, x, opt_f);
}

nlopt_result NonlinearOpt::nlopt_set_min_objective(nlopt_opt opt, nlopt_func f, void *f_data){
	opt = opt;
	f = f;
	f_data = f_data;

	return nlopt_set_min_objective(opt, f, f_data);
}

void NonlinearOpt::nlopt_destroy(nlopt_opt opt){
	opt = opt;
}

int NonlinearOpt::main() {

	nlopt_opt opt;
	
	double lb[2] = { -HUGE_VAL, 0 }; // lower bounds 
	double theta[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_add_inequality_constraint(opt, MyConstraint2, NULL, 1e-8);

	nlopt_set_xtol_rel(opt, 1e-4);

	if (nlopt_optimize(opt, theta, &minf) < 0) {
		printf("nlopt failed!\n");
	}
	else {
		//printf("found minimum after %d evaluation\n", &CNonlinearOptimization::count);
		printf("found minimum at f(%0.10g,%0.10g,%0.10g) = %0.10g\n", theta[0], theta[1], theta[2], minf);
		new_ankle_angle  = theta[0];
		new_knee_angle   = theta[1];
		new_pelvis_angle = theta[2];
	}
	nlopt_destroy(opt);
	system("pause");
	
	return 0;
}


Когда я отлаживал свою программу, ошибка относилась к функции-оболочке ограничений (MyConstraint1, MyConstraint2 и т. д.). Знаете ли вы, как решить эту проблему ? специально для моей функции-оболочки для вызова NLOPT. Если вы так хорошо знаете о НЛОП, пожалуйста, дайте мне знать. Спасибо

Gerry Schmitz

Вы скопировали этот код, внесли в него изменения, и теперь (если вообще когда-либо) он не работает?

Member 13922009

да, вы знаете, как это решить ?

1 Ответов

Рейтинг:
0

Rick York

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

nlopt_result NonlinearOpt::nlopt_add_inequality_constraint( nlopt_opt opt, nlopt_func fc, void *fc_data, double tol )
{
    return ::nlopt_add_inequality_constraint( opt, fc, fc_data, tol );
}
Присвоение переменных самим себе ничего не делает, поэтому они не нужны. Двойные двоеточия (::) в этом случае являются операторами разрешения области видимости. Они говорят компилятору использовать функции в глобальном пространстве имен. Без них компилятор будет использовать версию в текущем пространстве имен, что приведет к появлению предупреждений о рекурсии, которые были помечены. Это необходимо сделать для каждого случая, когда было отмечено предупреждение о рекурсии.

Для этой библиотеки доступен интерфейс C++. Вы должны рассмотреть возможность его использования. Одна из вещей, которую он делает, заключается в том, что он удаляет префикс nlopt_ из тех функций, которые не являются необходимыми в методах класса-оболочки, поскольку вы знаете, на какой объект ссылаетесь. Возможно, Вам не понадобятся некоторые методы вашего класса-оболочки, поскольку он делает по существу то же самое. То есть, если вы не должны писать свой собственный класс-оболочку. В этом случае, одна вещь, вы должны сделать, это удалить nlopt_ префиксы от ваших методов. :)


Member 13922009

Я попробовал ваш совет, но получил те же ошибки :
Предупреждение 1 предупреждение C4717: 'NonlinearOpt::nlopt_add_inequality_constraint' : рекурсивная на всех путях управления функция вызовет переполнение стека времени выполнения d:\program\robotsimu190902\robotsimu\nonlinearopt.cpp 137
Предупреждение 4 предупреждение C4717: 'NonlinearOpt::nlopt_create' : рекурсивно на всех путях управления, функция вызовет переполнение стека времени выполнения d:\program\robotsimu190902\robotsimu\nonlinearopt.cpp 146
Предупреждение 2 предупреждение C4717: 'NonlinearOpt::nlopt_optimize' : рекурсивно на всех путях управления, функция вызовет переполнение стека времени выполнения d:\program\robotsimu190902\robotsimu\nonlinearopt.cpp 161
Предупреждение 5 предупреждение C4717: 'NonlinearOpt::nlopt_set_lower_bounds' : рекурсивная на всех путях управления функция вызовет переполнение стека времени выполнения d:\program\robotsimu190902\robotsimu\nonlinearopt.cpp 151
Предупреждение 3 предупреждение C4717: 'NonlinearOpt::nlopt_set_min_objective' : рекурсивная на всех путях управления функция вызовет переполнение стека времени выполнения d:\program\robotsimu190902\robotsimu\nonlinearopt.cpp 166
Предупреждение 6 предупреждение C4717: 'NonlinearOpt::nlopt_set_xtol_rel' : рекурсивно на всех путях управления, функция вызовет переполнение стека времени выполнения d:\program\robotsimu190902\robotsimu\nonlinearopt.cpp 156

те же сообщения. Это будет работать в одной программе, но когда я реализую в одном классе в моей программе, которая имеет несколько cpp и заголовочных файлов, эта ошибка всегда возникает

Rick York

Отредактируйте свой вопрос и поместите туда обновленный код, чтобы мы могли видеть, что вы это сделали.

У вас есть те же ошибки, смещенные на несколько строк. Похоже, что вы не сделали того, что я предложил, иначе эти ошибки исчезли бы. Какую часть из того, что я предложил, вы попробовали?

Member 13922009

Я удаляю префиксы nlopt_

Rick York

Вы удалили приставки из чего? Они были в нескольких местах. Вы должны быть очень внимательны., ОЧЕНЬ конкретика в ваших описаниях.

Я даже не буду пытаться угадать, в чем проблема, пока вы не обновите исходный вопрос своим текущим кодом.

Member 13922009

Спасибо, я только что разгадал это предупреждение. Я меняю nlopt на Win32 с платформы 64x с помощью cmake. Я сделал это потому, что в моей программе используется платформа win32. Я следую вашим советам относительно моей целевой функции "myfunction" и "myconstraint". Спасибо, что помог мне. :)