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

 

posted on 2018-11-16 10:07  忠诚的卫士  阅读(3590)  评论(0编辑  收藏  举报

导航