1.Nlopt优化包介绍
NLopt是一个用于非线性优化的免费/开源库,提供了多种局部优化、全局优化算法的原始实现及通用接口,类似于MATLAB中的 fmincon ,其简单粗暴,方便好用,支持C++,但是其安装配置稍显麻烦。现有的帖子中多多少少不够全面或者有些许问题,因此特作此文作为总结,So,废话少说,进入正题。
2.下载Nlopt优化包
Nlopt下载地址:https://nlopt.readthedocs.io/en/latest/NLopt_on_Windows
选择多少位取决于编译器的设置,若用win32平台编译则下载32-bit版本,用X64平台编译则下载64-bit版本。本文以32-bit版本为例。
Nlopt下载网页截图
下载后解压,能看见libnlopt-0.def文件,最关键的步骤就是用.def文件生成.lib库文件,有这个文件后就能在VS中配置环境然后直接调用了。
Nlopt压缩包解压截图
3..def生成.lib静态链接库
根据以往的帖子有两种方法
方法一参照博客:
http://blog.csdn.net/qq_37043191/article/details/78473386
但是根据实验,发现会报错:
方法一报错截图
方法二:
- 先找到lib.exe:E:\Microsoft Visual Studio 14.0\VC\bin
- 运行>cmd;并切换到lib.exe所在的目录下:
在CMD中切换至lib.exe所在的目录
- 输入命令:lib /out:G:\nlopt-2.4.2-dll32\libnlopt-0.lib /MACHINE:IX86 /DEF:G:\nlopt-2.4.2-dll32\libnlopt-0.def
/out:是.lib文件生成的位置,/MACHINE:IX86:表示机器类型,32位机器,/DEF:表示的是.def存放的位置。
运行完后就会在G:\nlopt-2.4.2-dll32目录下生成对应的.lib文件和.exp文件:
在CMD中输入命令
生成.lib和.exp文件
- 将libnlopt-0.dll文件复制到vs2015的的目录下,找到vc文件夹下的bin文件夹:
将libnlopt-0.dll复制到VS的安装目录下
4.在VS2015进行配置环境并优化案例
- 有了以上步骤,就得到了如下图所示的所有文件:G:\NonlinearOptimization\nlopt-2.4.2-dll32
生成.lib后的所有文件截图
- 打开vs2015,新建一个空项目,然后对其项目属性进行配置
VC++目录设置
链接器输入设置
- 包含头文件nlopt.h和nlopt.hpp,并添加nonlinearoptimization.cpp文件(数学模型及代码附在本文后面)
头文件及代码截图
- 数学模型:
数学模型
上述中有一个等式约束和一个不等式约束。使用Sequential Least-Squares Quadratic Programming (SLSQP) 算法来求解这个优化问题。
- C++代码(nonlinearoptimization.cpp文件中的代码):
#include <stdio.h>
#include <math.h>
#include "nlopt.h"
#define INF (1000000)
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;
}
- 程序非常快速的收敛到了正确的结果:
优化结果
5.总结
关于nlopt的入门应用,上述内容已经非常的详细。还有一些稍微高深的用法需要读者自己根据实际情况变通。
比如实际应用中,可能会需要更进一步的用C++语法的继承、派生等写出基于此文叙述基础上的代码框架,可以将等式约束,不等式约束,目标函数集中在一个函数中形成类似于MATLAB中fmincon函数类似的形式。
还有关于步骤【 将libnlopt-0.dll文件复制到vs2015的的目录下 】在实际项目研发中并不适用,可移植性很差,进一步涉及到dll文件调用方法,这部分的帖子将会陆续发布。
参考链接:
https://zhuanlan.zhihu.com/econcode/24350637
http://nlopt.readthedocs.io/en/latest/NLopt_on_Windows