Nlopt优化函数库,用法举例
/* * main.c * * Created on: Oct 9, 2018 * Author: lgh */ #include <stdio.h> #include <math.h> #include "nlopt.h" #define INF (1.0/0.0) int i=0; //目标函数; double utility(unsigned n, const double *x, double *grad, void *data) { if(grad){ grad[0]=2*x[0]; grad[1]=2*x[1]; } printf("迭代次数 i= %d, x[0]=%f, x[1]= %f,f(x1,x2)=%f\n",i++,x[0],x[1],x[0]*x[0]+x[1]*x[1]+8); return ( x[0]*x[0]+x[1]*x[1]+8 ); } //等式限制条件; double constraint(unsigned n, const double *x, double *grad, void *data) { if(grad){ grad[0]= -1.0; grad[1]= -2*x[1]; } return (-x[0]-x[1]*x[1]+2); } //不等式限制条件; double inconstraint(unsigned n, const double *x, double *grad, void *data) { if(grad){ grad[0]= -2*x[0]; grad[1]= 1.0; } return (-x[0]*x[0]+x[1]); } int main(int argc, char const *argv[]) { double tol=1e-8; double lb[2]={0,0}; //x1、x2的下边界; double ub[2]={INF,INF}; double x[2]={1, 1}; //给x1、x2赋予初始值; double f_max; nlopt_opt opter=nlopt_create( NLOPT_LD_SLSQP, 2); //设置自变量下限; nlopt_set_lower_bounds(opter, lb); // 目标函数; nlopt_set_min_objective(opter, utility, NULL); // 不等式约束; nlopt_add_inequality_constraint(opter, inconstraint, NULL, tol); // 等式约束; nlopt_add_equality_constraint(opter, constraint, NULL, tol); // 停止时需要的条件; nlopt_set_xtol_rel(opter, tol); // 开始优化; nlopt_result result=nlopt_optimize(opter, x, &f_max); if (result) { printf("目标函数最大值=%g, x=(%g,%g)\n", f_max, x[0], x[1]); } //free nlopt_destroy(opter); return 0; }
结果:
迭代次数 i= 0, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 1, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 2, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 3, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 4, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 5, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 6, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 7, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 8, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 9, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 10, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 11, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 12, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 13, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 14, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 15, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 16, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 17, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 18, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 19, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 20, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 21, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 22, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 23, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 迭代次数 i= 24, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=10.000000 目标函数最大值=10, x=(1,1)
/* * main.c * * Created on: Oct 9, 2018 * Author: lgh */ #include <stdio.h> #include <math.h> #include "nlopt.h" #define INF (1.0/0.0) int i=0; //目标函数; double utility(unsigned n, const double *x, double *grad, void *data) { if(grad){ grad[0]=-1.0+x[0]; grad[1]=-2.0+x[2]; } printf("迭代次数 i= %d, x[0]=%f, x[1]= %f,f(x1,x2)=%f\n", i++,x[0],x[1],-x[0]-2*x[1]+0.5*x[0]*x[0]+0.5*x[1]*x[1]); return (-x[0]-2*x[1]+0.5*x[0]*x[0]+0.5*x[1]*x[1]); } //不等式限制条件; double inconstraint_1(unsigned n, const double *x, double *grad, void *data) { if(grad){ grad[0]= 2.0; grad[1]= 3.0; } return (2*x[0]+3*x[1]-6); } //不等式限制条件; double inconstraint_2(unsigned n, const double *x, double *grad, void *data) { if(grad){ grad[0]= 1.0; grad[1]= 4.0; } return (x[0]+4*x[1]-5); } //不等式限制条件; double inconstraint_3(unsigned n, const double *x, double *grad, void *data) { if(grad){ grad[0]= 2.0; grad[1]= 6.0*x[1]; } return (2*x[0]+3*x[1]*x[1]-6); } int main(int argc, char const *argv[]) { double tol=1e-4; double lb[2]={0,0}; //x1、x2的下边界; double ub[2]={INF,INF}; double x[2]={1, 1}; //给x1、x2赋予初始值; double f_min; nlopt_opt opter=nlopt_create( NLOPT_LD_SLSQP, 2); //设置自变量下限; nlopt_set_lower_bounds(opter, lb); // 目标函数; nlopt_set_min_objective(opter, utility, NULL); // 不等式约束; nlopt_add_inequality_constraint(opter, inconstraint_1, NULL, tol); nlopt_add_inequality_constraint(opter, inconstraint_2, NULL, tol); nlopt_add_inequality_constraint(opter, inconstraint_3, NULL, tol); // 停止时需要的条件; nlopt_set_xtol_rel(opter, tol); // 开始优化; nlopt_result result=nlopt_optimize(opter, x, &f_min); if (result) { printf("极小值=%g, x=(%g,%g)\n", f_min, x[0], x[1]); } //free nlopt_destroy(opter); return 0; }
结果为:
迭代次数 i= 0, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=-2.000000 迭代次数 i= 1, x[0]=0.764706, x[1]= 1.058824,f(x1,x2)=-2.029412 迭代次数 i= 2, x[0]=0.750000, x[1]= 1.062500,f(x1,x2)=-2.029297 迭代次数 i= 3, x[0]=0.759904, x[1]= 1.060024,f(x1,x2)=-2.029400 迭代次数 i= 4, x[0]=0.762660, x[1]= 1.059335,f(x1,x2)=-2.029410 迭代次数 i= 5, x[0]=0.763753, x[1]= 1.059062,f(x1,x2)=-2.029411 迭代次数 i= 6, x[0]=0.764245, x[1]= 1.058939,f(x1,x2)=-2.029412 迭代次数 i= 7, x[0]=0.764479, x[1]= 1.058880,f(x1,x2)=-2.029412 迭代次数 i= 8, x[0]=0.764594, x[1]= 1.058852,f(x1,x2)=-2.029412 迭代次数 i= 9, x[0]=0.764650, x[1]= 1.058838,f(x1,x2)=-2.029412 迭代次数 i= 10, x[0]=0.764678, x[1]= 1.058831,f(x1,x2)=-2.029412 迭代次数 i= 11, x[0]=0.764692, x[1]= 1.058827,f(x1,x2)=-2.029412 迭代次数 i= 12, x[0]=0.764699, x[1]= 1.058825,f(x1,x2)=-2.029412 迭代次数 i= 13, x[0]=0.764699, x[1]= 1.058825,f(x1,x2)=-2.029412 极小值=-2.02941, x=(0.764706,1.05882)
对于例子二这种有多个非线性约束的情况,也可以采用多非线性函数:
/* * main.c * * Created on: Oct 9, 2018 * Author: lgh */ /************************************************************************* * 函数: * nlopt_result nlopt_add_inequality_mconstraint( nlopt_opt opt, unsigned m, * nlopt_mfunc c, void* c_data, const double *tol ); **************************************************************************/ #include <stdio.h> #include <math.h> #include "nlopt.h" #define INF (1.0/0.0) int i=0; //目标函数; double objective_fun(unsigned n, const double *x, double *grad, void *data) { if(grad){ grad[0]=-1.0+x[0]; grad[1]=-2.0+x[2]; } printf("迭代次数 i= %d, x[0]=%f, x[1]= %f,f(x1,x2)=%f\n", i++,x[0],x[1],-x[0]-2*x[1]+0.5*x[0]*x[0]+0.5*x[1]*x[1]); return (-x[0]-2*x[1]+0.5*x[0]*x[0]+0.5*x[1]*x[1]); } //不等式限制条件; void c(unsigned m, double *result, unsigned n, const double *x, double *grad, void *data) { if(grad){ grad[0]= 2.0; grad[1]= 3.0; grad[2]= 1.0; grad[3]= 4.0; grad[4]= 2.0; grad[5]= 6*x[1]; } result[0] = 2*x[0] + 2*x[1]-6; result[1] = x[0] + 4*x[1] - 5; result[2] = 2*x[1] + 3*x[1]*x[1]-6; } int main(int argc, char const *argv[]) { double tol=1e-4; double lb[2]={0,0}; //x1、x2的下边界; double x[2]={1, 1}; //给x1、x2赋予初始值; double f_min; nlopt_opt opter=nlopt_create( NLOPT_LN_COBYLA, 2); //设置自变量下限; nlopt_set_lower_bounds(opter, lb); // 目标函数; nlopt_set_min_objective(opter, objective_fun, NULL); // 多个不等式约束; nlopt_add_inequality_mconstraint(opter, 3, c, NULL, NULL); // 停止时需要的条件; nlopt_set_xtol_rel(opter, tol); // 开始优化; nlopt_result result=nlopt_optimize(opter, x, &f_min); if (result) { printf("极小值=%g, x=(%g,%g)\n", f_min, x[0], x[1]); } //free nlopt_destroy(opter); return 0; }
/* * main.c * * Created on: Oct 9, 2018 * Author: lgh */ #include <stdio.h> #include <math.h> #include "nlopt.h" #define INF (1.0/0.0) int i=0; //目标函数; double utility(unsigned n, const double *x, double *grad, void *data) { if(grad){ grad[0]=1.0/x[0]; grad[1]=1.0/x[1]; } printf("迭代次数 i= %d, x[0]=%f, x[1]= %f,f(x1,x2)=%f\n", i++,x[0],x[1],log(x[0])+log(x[1])); return (log(x[0])+log(x[1])); } //等式限制条件; double constraint(unsigned n, const double *x, double *grad, void *data) { if(grad){ grad[0]= 1.0; grad[1]= 2.0; } return (x[0]+2*x[1]-5); } //不等式限制条件; double inconstraint(unsigned n, const double *x, double *grad, void *data) { if(grad){ grad[0]= 1.0; grad[1]= -1.0; } return (x[0]-x[1]); } int main(int argc, char const *argv[]) { double tol=1e-4; double lb[2]={0,0}; //x1、x2的下边界; double ub[2]={INF,INF}; double x[2]={1, 1}; //给x1、x2赋予初始值; double f_min; nlopt_opt opter=nlopt_create( NLOPT_LD_SLSQP, 2); //设置自变量下限; nlopt_set_lower_bounds(opter, lb); // 目标函数; nlopt_set_max_objective(opter, utility, NULL); // 不等式约束; nlopt_add_inequality_constraint(opter, inconstraint, NULL, tol); //添加等式约束; nlopt_add_equality_constraint(opter, constraint, NULL, tol); // 停止时需要的条件; nlopt_set_xtol_rel(opter, tol); // 开始优化; nlopt_result result=nlopt_optimize(opter, x, &f_min); if (result) { printf("极小值=%g, x=(%g,%g)\n", f_min, x[0], x[1]); } //free nlopt_destroy(opter); return 0; }
结果为:
迭代次数 i= 0, x[0]=1.000000, x[1]= 1.000000,f(x1,x2)=0.000000 迭代次数 i= 1, x[0]=1.666667, x[1]= 1.666667,f(x1,x2)=1.021651 极小值=1.02165, x=(1.66667,1.66667)
/* * main.c * * Created on: Oct 9, 2018 * Author: lgh */ #include <stdio.h> #include <math.h> #include "nlopt.h" #define INF (1.0/0.0) typedef struct{ double a, b; }my_constraint_data; int i=0; //不等式约束; double myconstraint(unsigned n, const double *x, double *grad, void *data) { //将所需要的参数传递给不等式约束的参数; my_constraint_data *d = (my_constraint_data*)data; double a =d->a, b =d->b; if(grad){ grad[0] = 3*a*(a*x[0]+b)*(a*x[0]+b); grad[1] = -1.0; } return ( (a*x[0]+b)*(a*x[0]+b)*(a*x[0]+b)-x[1] ); } //设置目标函数,n为目标函数的个数,由nlopt_create函数的第2个参数设置; //double *x存放自变量数组,初始值在nlopt_optimize函数中第2个参数进行设置; // grad如果不为空,则grad[0]到grad[n-1]分别存放各个自变量x的偏倒数; double myfunc(unsigned n, const double *x, double *grad, void *my_func_data) { if(grad){ grad[0] = 0.0; grad[1] = 0.5/sqrt(x[1]); } i++; printf("迭代寻优的次数为: i=%d\n",i); return sqrt(x[1]); } int main() { //设置自变量{x0,x1}的下限; double lb[2] = {-INF,0}; nlopt_opt opt = nlopt_create(NLOPT_LD_MMA,2); nlopt_set_lower_bounds(opt,lb); nlopt_set_min_objective(opt,myfunc,NULL); //为两个不等式的系数; my_constraint_data data[2] = {{2,0},{-1,1}}; //添加不等式约束,data[0]是给a、b进行赋值; nlopt_add_inequality_constraint(opt,myconstraint,&data[0],1e-8); nlopt_add_inequality_constraint(opt,myconstraint,&data[1],1e-8); //当前后差值小于 1e-4时就跳出迭代循环; nlopt_set_xtol_rel(opt,1e-4); //设置最大迭代寻优次数; nlopt_set_maxeval(opt,5000); //设置初始值; double x[2] = {1.234, 5.678}; double minf; if(nlopt_optimize(opt,x,&minf)<0){ printf("nlopt 搜索失败.\n"); } else{ printf("找到最小值 f(%g,%g) = %0.10g\n",x[0],x[1],minf); } nlopt_destroy(opt); return 0; }
结果为:
迭代寻优的次数为: i=1 迭代寻优的次数为: i=2 迭代寻优的次数为: i=3 迭代寻优的次数为: i=4 迭代寻优的次数为: i=5 迭代寻优的次数为: i=6 迭代寻优的次数为: i=7 迭代寻优的次数为: i=8 迭代寻优的次数为: i=9 迭代寻优的次数为: i=10 迭代寻优的次数为: i=11 找到最小值 f(0.333333,0.296296) = 0.5443310474