以官方给的例程,重新梳理,以供理解NLopt的使用。
问题被定义为:
min
x
∈
R
2
x
2
s
u
b
j
e
c
t
t
o
x
2
≥
0
,
x
2
≥
(
a
1
x
1
+
b
1
)
3
,
a
n
d
x
2
≥
(
a
2
x
1
+
b
2
)
3
f
o
r
p
a
r
a
m
e
t
e
r
s
a
1
=
2
,
b
1
=
0
,
a
2
=
−
1
,
b
2
=
1.
\begin{gathered} \min_{\mathbf{x}\in\mathbb{R}^2}\sqrt{x_2} \\ \mathrm{subject~to~}x_2\geq0,x_2\geq(a_1x_1+b_1)^3,\mathrm{and~}x_2\geq(a_2x_1+b_2)^3 \\ \mathrm{for~parameters~a_{1}=2,~b_{1}=0,~a_{2}=-1,~b_{2}=1.} \end{gathered}
x∈R2minx2subject to x2≥0,x2≥(a1x1+b1)3,and x2≥(a2x1+b2)3for parameters a1=2, b1=0, a2=−1, b2=1.
使用步骤如下:
- 创建nlopt对象
- 设置上下边界
- 设置不等式约束
- 设置优化目标
- 设置迭代停止条件,参考传送门
- 设置算法起始点
- 执行优化函数
#include <stdio.h>
#include <math.h>
#include "nlopt.h"
#include <stdlib.h>
#define INF (1.0/0.0)
typedef struct {
double a, b;
} my_constraint_data; // 约束参数
// 目标函数
int item_count = 0;
double myfunc(unsigned n, const double *x, double *grad, void *my_func_data)
{
++item_count;
if (grad) {
grad[0] = 0.0;
grad[1] = 0.5 / sqrt(x[1]);
}
return sqrt(x[1]);
}
// 约束函数
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]);
}
int main()
{
// 创建nlopt对象
nlopt_opt opt;
opt = nlopt_create(NLOPT_LD_MMA, 2); /* algorithm and dimensionality */
// 设置上下边界
double lb[2] = {-HUGE_VAL, 0 }; /* lower bounds */
double ub[2] = {INF, INF};
nlopt_set_lower_bounds(opt, lb);
nlopt_set_upper_bounds(opt, ub);
// 设置优化目标
nlopt_set_min_objective(opt, myfunc, NULL);
// 添加不等式约束
my_constraint_data data[2] = { {2,0}, {-1,1} }; // a1=2,b1=0 a2=-1,b2=1
nlopt_add_inequality_constraint(opt, myconstraint, &data[0], 1e-8); // 1e-8是约束的可选容差
nlopt_add_inequality_constraint(opt, myconstraint, &data[1], 1e-8);
// 优化参数x的相对容差
nlopt_set_xtol_rel(opt, 1e-4);
double x[2] = { 1.234, 5.678 }; /* `*`some` `initial` `guess`*` */
double minf; /* `*`the` `minimum` `objective` `value,` `upon` `return`*` */
// 执行优化
if (nlopt_optimize(opt, x, &minf) < 0)
{
printf("nlopt failed!\n");
}
else
{
printf("found minimum at f(%g,%g) = %0.10g\n", x[0], x[1], minf);
}
printf("found minimum after %d evaluations\n", item_count);
// 销毁对象
nlopt_destroy(opt);
return 0;
}
案例2:
#include<iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <nlopt.hpp>
#include <stdio.h>
#include <math.h>
using namespace std;
using namespace nlopt;
/*
* main.c
*
* Created on: Oct 9, 2018
* Author: lgh
*/
#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];
grad[2]=1.0;
grad[3]=2*x[3];
}
printf("迭代次数 i= %d, x[0]=%f, x[1]= %f,x[2]= %f,x[3]= %f,f(x1,x2,x3,x4)=%f\n",i++,x[0],x[1],x[2],x[3],x[0]*x[0]+x[1]*x[1]+x[2]+x[3]*x[3]+10);
return ( x[0]*x[0]+x[1]*x[1]+x[2]+x[3]*x[3]+10 );
}
//等式限制条件;
double constraint(unsigned n, const double *x, double *grad, void *data)
{
if(grad){
grad[0]= 1.0;
grad[1]= 1.0;
grad[2]= 1.0;
grad[3]= 1.0;
}
return (x[0]+x[1]+x[2]+x[3]);
}
//不等式限制条件;
double inconstraint(unsigned n, const double *x, double *grad, void *data)
{
if(grad){
grad[0]= -2*x[0];
grad[1]= -2*x[1];
}
return (-x[0]*x[0]-x[1]*x[1]-100);
}
int main(int argc, char const *argv[])
{
double tol=1e-8;
double lb[4]={-INF,-INF,-INF,-INF}; //x1、x2的下边界;
double ub[4]={INF,INF,INF,INF};
double x[4]={1, 1, 1, 1}; //给x1、x2赋予初始值;
double f_max;
nlopt_opt opter=nlopt_create( NLOPT_LD_SLSQP, 4);
//设置自变量下限;
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], x[2], x[3]);
}
//free
nlopt_destroy(opter);
return 0;
}
参考链接:https://www.cnblogs.com/derek-dhb/p/17497953.html