NLopt优化库在c++下的使用

  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

猜你喜欢

转载自blog.csdn.net/potxxx/article/details/80743146