NLopt在windows下的安装以及vs下的include可以参考其他博客,本文主要记录nlopt示例程序的c++使用。
数学模型如下:
目标函数求最大值,约束函数为后两行;
#include"nlopt.hpp" using namespace nlopt;
使用c++接口首先包含.hpp文件,相应的接口名均在nlopt命名空间里。
/**************************************************************************************************/
opt opter(algorithm, unsigned n);
opt opter(LD_SLSQP, 2); //定义一个优化器,使用SLSQP算法,两个优化维度
首先创建一个opt对象,algorithm为NLopt算法支持参数,n为所求问题维度。
目标函数
void nlopt::opt::set_max_objective(nlopt::vfunc f, void* f_data);
opter.set_max_objective(myfunc, NULL);
指定目标函数f,f_data为可选传入数据若无则为NULL。
double f(const std::vector<double> &x, std::vector<double> &grad, void* f_data);
double myfunc(const vector<double>&x, vector<double>&grad, void *my_func_data) { grad[0] = 1 / x[0]; grad[1] = 1 / x[1]; return log(x[0]) + log(x[1]); }
函数f的形式如上,返回值为在一个x向量下的目标函数的值,grad返回为此时最优化参数的梯度,并非所有优化算法(如下)都使用梯度信息:对于列为“无衍生”的算法,grad参数将始终为空,且不需要计算。(但对于使用渐变信息的算法,grad对于某些调用可能仍为空。)
边界约束
void nlopt::opt::set_lower_bounds(const std::vector<double> &lb); void nlopt::opt::set_upper_bounds(const std::vector<double> &ub);
vector<double> lb{ 0,0 }; vector<double> rb{ 10000,10000 }; opter.set_lower_bounds(lb); opter.set_upper_bounds(rb);
设定要检索的最大最小值;
非线性约束
void nlopt::opt::add_inequality_constraint(nlopt::vfunc fc, void *fc_data, double tol=0); //不等式约束 void nlopt::opt::add_equality_constraint(nlopt::vfunc h, void *h_data, double tol=0); //等式约束
double myconstraint(const vector<double>&x, vector<double>&grad, void *my_data) { double *p = (double *)my_data; grad[0] = p[0]; grad[1] = p[1]; return x[0] * p[0] + x[1] * p[1] - 5; } double myinconstraint(const vector<double>&x, vector<double>&grad, void *my_data) { grad[0] = 1; grad[1] = -1; return x[0] - x[1]; }
fc与h函数与上面目标函数一个格式,tol为容差
优化收敛opter.set_xtol_rel(tol); opter.set_force_stop(tol);获取结果
double f_max = -10000; result res = opter.optimize(x,f_max);
最大值储存在f_max内,对应的向量储存在x内;
代码如下:
#include<iostream> #include<vector> #include<cmath> #include"nlopt.hpp" using namespace std; using namespace nlopt; double myfunc(const vector<double>&x, vector<double>&grad, void *my_func_data) { grad[0] = 1 / x[0]; grad[1] = 1 / x[1]; return log(x[0]) + log(x[1]); } double myconstraint(const vector<double>&x, vector<double>&grad, void *my_data) { double *p = (double *)my_data; grad[0] = p[0]; grad[1] = p[1]; return x[0] * p[0] + x[1] * p[1] - 5; } double myinconstraint(const vector<double>&x, vector<double>&grad, void *my_data) { grad[0] = 1; grad[1] = -1; return x[0] - x[1]; } int main() { double f_max = -10000; double tol = 1e-8; double p[2] = { 1,2 }; vector<double> x{ 1,1 }; opt opter(LD_SLSQP, 2); //定义一个优化器,使用SLSQP算法,两个优化维度 opter.set_max_objective(myfunc, NULL); vector<double> lb{ 0,0 }; vector<double> rb{ 10000,10000 }; opter.set_lower_bounds(lb); opter.set_upper_bounds(rb); opter.add_equality_constraint(myconstraint, p,tol); opter.add_inequality_constraint(myinconstraint, NULL,tol); opter.set_xtol_rel(tol); opter.set_force_stop(tol); result res = opter.optimize(x,f_max); cout << x[0] << ends << x[1] << ends << f_max << endl; system("pause"); }
参考文章:
https://blog.csdn.net/u014571489/article/details/79344676