工作中经常遇到优化的问题,比如多数的统计方法最终都可以归结为一个优化问题。一般的统计和数值计算软件都会包含最优化算法的函数,比如Matlab中的fminsearch等,不过对于C等其他语言,很多时候可以选择的并不多。
之前工作中经常用到的是GSL中的优化算法,不过由于最近更经常使用MKL,所以希望能摆脱对GSL的依赖。这个时候找到了NLopt这个包。
NLopt使用起来非常简单,且支持非常多的语言,常见的语言比如C/ C++/ Julia/ Python/ R/ Fortran/ Lua/ OCaml/ Octave等都支持,所以算是一个“一招鲜,吃遍天”的包。除此之外,NLopt还有很多其他优点,比如:
- 可以方便的在不更改代码的情况下更改算法进行尝试,
- 支持一些常见的全局最优算法
- 支持一些高维的问题
- 支持常见的需要导数和不需要导数的多种算法
- 支持等式、不等式、有界等不同的约束极值问题
总之,很好用!
NLopt的安装也非常简单,与一般的源码安装过程一样,从官网NLopt - AbInitio 下载源码,然后:
./configure
make
sudo make install
就可以了,默认安装在/usr/local/lib/下。windows下可以用MinGW。
NLopt支持的算法可以从NLopt Algorithms 查询,包括:
下面是如下问题的一个实例代码:
注意其中有一个等式约束和一个不等式约束。我们使用Sequential Least-Squares Quadratic Programming (SLSQP) 算法来求解这个优化问题。
代码:
#include <stdio.h>
#include <math.h>
#include "nlopt.h"
#define INF (1.0/0.0)
double utility(unsigned n, const double *x, double *grad, void *data){
grad[0]=1.0/x[0];
grad[1]=1.0/x[1];
printf("%f, %f, %f ", 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){
double *p=(double *)data;
grad[0]=*p;
grad[1]=*(p+1);
printf("Constraint: %f\n", x[0]*(*p)+x[1]*(*(p+1))-5);
return x[0]*(*p)+x[1]*(*(p+1))-5;
}
double inconstraint(unsigned n, const double *x, double *grad, void *data){
grad[0]=1;
grad[1]=-1;
return x[0]-x[1];
}
int main(int argc, char const *argv[]) {
double p[2]={1,2};
double tol=1e-8;
double lb[2]={0,0};
double ub[2]={INF,INF};
double x[2]={1,1};
double f_max=-INF;
// set up optimizer
nlopt_opt opter=nlopt_create(NLOPT_LD_SLSQP, 2);
// lower and upper bound
nlopt_set_lower_bounds(opter, lb);
nlopt_set_upper_bounds(opter, ub);
// objective function
nlopt_set_max_objective(opter, utility, NULL);
// equality constraint
nlopt_add_equality_constraint(opter, constraint, p, tol);
// inequality constraint
nlopt_add_inequality_constraint(opter, inconstraint, NULL, tol);
// stopping criterion
nlopt_set_xtol_rel(opter, tol);
nlopt_set_ftol_abs(opter, tol);
nlopt_set_force_stop(opter, tol);
// optimize
nlopt_result result=nlopt_optimize(opter, x, &f_max);
if (result)
printf("Maximum utility=%f, x=(%f,%f)\n", f_max, x[0], x[1]);
// free
nlopt_destroy(opter);
return 0;
}
编译:
gcc main.c -lnlopt -lm -Wall -O3 -o main
可以得到结果:
1.000000, 1.000000, 0.000000 Constraint: -2.000000
1.666667, 1.666667, 1.021651 Constraint: 0.000000
Maximum utility=1.021651, x=(1.666667,1.666667)
程序非常快速的收敛到了正确的结果。
过段时间再试试Julia的NLopt。
康格鹿1 年前
数值优化的程序包或者软件很多,往往不需要自己造车轮,只要能适当调用,往往能事半功倍。
3回复踩举报
张亮1 年前
您好,请问这里有能代替matlab中fmincon函数,用于求解非线性约束优化问题函数吗?
赞回复踩举报
当然可以,如果是在matlab里面用,我是没用过,不过官网上有matlab里面怎么使用nlopt的,你可以看看
1查看对话回复踩举报
猫酱1 年前
谢谢。我知道身边一些组是用这个package的,不知道nlopt可不可以做quadratic/conic programming,他和其他一些商业软件比如mosek比有什么优势劣势呢?
我也准备趁十二月假期多好好研究一下。
1回复踩举报
zhong z1 年前
用了julia的jump你就知道c里面调用方式是多浪费人生了
赞回复踩举报
用过啊~
赞查看对话回复踩举报
我一般会先用julia写一个大概,然后把计算密集型的部分用C写,用了MKL、Openmp、TBB之后的C程序仍然不是Julia能相比的
赞查看对话回复踩举报
谢谢!我是用C/C++实现MATLAB里这个函数的功能,之前也只是简单了解过NLOPT这个库,当时看的很浅显,并没有实现相应的功能,我还是回头再仔细学习一下吧
赞查看对话回复踩举报
某财1 年前
第一次见这个优化程序,我注意到您举例的优化问题是线性的,想请教下:1 非线性的优化问题能求解吗? 2 得出的结果保证是最优的吗?
赞回复踩举报
我的问题哪里是线性的。。。。
赞查看对话回复踩举报
1尴尬了,没仔细看目标函数....不好意思!那第二个问题,结果是最优的吗?
赞查看对话回复踩举报
包里面包含了全局最优的算法,不过是不是全局最优,谁知道呢。
1查看对话回复踩举报
多谢指教!
赞查看对话回复踩举报
如果是凸优化的话也许可以用CVX
1查看对话回复踩举报
matlab里面的?
赞查看对话回复踩举报
陈辉辉1 年前
本人是新手,不知道用minGW怎么安装nlopt啊?有没有大神救救我
赞回复踩举报
configure-make-make install
赞查看对话回复踩举报
云设那般10 个月前
请问三个方程式解六元 在做约束该怎么写呢?也就是*p*x[0]+..+ .*(p+5) * x[5] = 13,*d*x[0]+..+ .*(d+5) * x[5] = 21,....
赞回复踩举报
酸荔枝1 个月前
您好,请教一下,就是在utility()、constraint()等中有grad求导一项,这应该是一个全局变量,但是并没有包含在函数返回中,请问这个是由什么用呢?