Gurobi优化器使用(一)搭建并求解一个优化模型的过程【C++环境】

Gurobi优化器使用(一)搭建并求解一个优化模型的过程 【C++环境】

  • Gurobi可以解决的问题
  • 文档
  • 实例——通过系数矩阵建模并求解
    • 解释
  • 实例——直接建模并求解
  • 求解结果
  • 如何读取一个已保存的模型

Gurobi可以解决的问题

Gurobi优化器使用(一)搭建并求解一个优化模型的过程【C++环境】_第1张图片

文档

官方文档
8.1版本C++接口的官方文档

实例——通过系数矩阵建模并求解

当系数已存入到外部的模型文件中需要读取时可以采用该方法建模,否则不推荐这种方式.
待解决的问题如下:
Gurobi优化器使用(一)搭建并求解一个优化模型的过程【C++环境】_第2张图片

/* 该例子解决下面的凸二次规划问题:
	minimize x + y + x^2 + x*y + y^2 + y*z + z^2
	subject to x + 2 y + 3 z >= 4
	x + y >= 1
	x, y, z 非负

使用预定义的参数矩阵A和Q进行求解(一般在参数已存入外部数据时使用),否则不推荐使用稠密
矩阵的方法。
*/

#include "gurobi_c++.h"
using namespace std;

static bool dense_optimize(GRBEnv* env,
	int rows,
	int cols,
	double* c, /* 目标函数的线性系数项 */
	double* Q, /* 目标函数的二次项 */
	double* A, /* 约束矩阵 */
	char* sense, /* 约束不等关系(大于,小于) */
	double* rhs, /* 右端项向量 */
	double* lb, /* 变量下界 */
	double* ub, /* 变量上界 */
	char* vtype, /* 变量类型 ( continuous , binary , etc .) */
	double* solution,
	double* objvalP)
{
	GRBModel model = GRBModel(*env);
	int i, j;
	bool success = false;
	/* Add variables to the model */
	GRBVar* vars = model.addVars(lb, ub, NULL, vtype, NULL, cols);
	/* Populate A matrix */
	for (i = 0; i < rows; i++) {
		GRBLinExpr lhs = 0;
		for (j = 0; j < cols; j++)
			if (A[i * cols + j] != 0)
				lhs += A[i * cols + j] * vars[j];
		model.addConstr(lhs, sense[i], rhs[i]);
	}
	GRBQuadExpr obj = 0;
	for (j = 0; j < cols; j++)
		obj += c[j] * vars[j];
	for (i = 0; i < cols; i++)
		for (j = 0; j < cols; j++)
			if (Q[i * cols + j] != 0)
				obj += Q[i * cols + j] * vars[i] * vars[j];
	model.setObjective(obj);
	model.optimize();
	model.write(" dense.lp");
	if (model.get(GRB_IntAttr_Status) == GRB_OPTIMAL) {
		*objvalP = model.get(GRB_DoubleAttr_ObjVal);
		for (i = 0; i < cols; i++)
			solution[i] = vars[i].get(GRB_DoubleAttr_X);
		success = true;
	}
	delete[] vars;
	return success;
}
int main(int argc,char* argv[])
{
	GRBEnv* env = 0;
	try {
		env = new GRBEnv();
		double c[] = { 1, 1, 0 };
		double Q[3][3] = { {1 , 1, 0}, {0, 1, 1}, {0, 0, 1} };
		double A[2][3] = { {1 , 2, 3}, {1, 1, 0} };
		char sense[] = { '>', '>' };
		double rhs[] = { 4, 1 };
		double lb[] = { 0, 0, 0 };
		bool success;
		double objval, sol[3];
		success = dense_optimize(env, 2, 3, c, &Q[0][0], &A[0][0], sense, rhs,
			lb, NULL, NULL, sol, &objval);
		cout << "x: " << sol[0] << " y: " << sol[1] << " z: " << sol[2] << endl;
	}
	catch (GRBException e) {
		cout << " Error code = " << e.getErrorCode() << endl;
		cout << e.getMessage() << endl;
	}
	catch (...) {
		cout << " Exception during optimization " << endl;
	}
	delete env;
	return 0;
}
}

解释

  1. 构建Gurobi环境

    GRBEnv* env = 0;
    env = new GRBEnv();
    
  2. 建立模型的实例

    GRBModel model = GRBModel(*env);
    
  3. 添加优化变量

    GRBVar* vars = model.addVars(lb, ub, NULL, vtype, NULL, cols);
    
    GRBVar* addVars(const double* lb, const double* ub,
                        const double* obj, const char* type,
                        const std::string* name, int len);
    

    注意: 传入的是指针

  4. 添加约束

    model.addConstr(const GRBLinExpr& expr, char sense, double rhs,
                            std::string name="");
    GRBLinExpr lhs = 0;
    

    ① GRBLinExpr是线性表示类,源代码通过运算符重载,使它可以表示为GRBVar* vars的线性组合.
    ② sense是char类型,指约束的不等关系,‘>’
    ③ rhs是不等式右边的项
    ④ 一次只能添加一个约束,可以放到循环里面

  5. 设置目标函数

    GRBQuadExpr obj = 0;
    

    目标函数是二次型,与GRBLinExpr一样的方式,不过obj可以表示为二次。

  6. 添加目标函数,并进行优化

    model.setObjective(obj);
    model.optimize();
    
  7. 保存优化好的模型

    model.write(" dense.lp");
    

    模型文件格式说明

  8. 打印优化结果

    if (model.get(GRB_IntAttr_Status) == GRB_OPTIMAL) {
     	*objvalP = model.get(GRB_DoubleAttr_ObjVal);
     	for (i = 0; i < cols; i++)
     		solution[i] = vars[i].get(GRB_DoubleAttr_X);
    

    打印最优目标值和最优解

  9. 释放空间
    一般定义了指针的话需要手动释放变量和环境

    delete[] vars;
    delete env;
    

实例——直接建模并求解

这种建模方式直接了当.

/* 该例子解决下面的凸二次规划问题:
	minimize x + y + x^2 + x*y + y^2 + y*z + z^2
	subject to x + 2 y + 3 z >= 4
	x + y >= 1
	x, y, z 非负

直接求解
*/

#include "gurobi_c++.h"
using namespace std;

int main(int argc, char* argv[])
{
	GRBEnv* env = 0;
	try {
		env = new GRBEnv();
		GRBModel model = GRBModel(* env);

		// Create Variables
		GRBVar x = model.addVar(0, GRB_INFINITY, 1.0, GRB_CONTINUOUS, "x");
		GRBVar y = model.addVar(0, GRB_INFINITY, 1.0, GRB_CONTINUOUS, "y");
		GRBVar z = model.addVar(0, GRB_INFINITY, 1.0, GRB_CONTINUOUS, "z");

		model.setObjective(x + y + x * x + x * y + y * y + y * z + z * z, GRB_MINIMIZE);
		
		model.addConstr(x + 2 * y + 3 * z >= 4, "c0");
		model.addConstr(x +  y >= 1, "c1");

		// Optimize model
		model.optimize();
		cout << x.get(GRB_StringAttr_VarName) << " "
			<< x.get(GRB_DoubleAttr_X) << endl;
		cout << y.get(GRB_StringAttr_VarName) << " "
			<< y.get(GRB_DoubleAttr_X) << endl;
		cout << z.get(GRB_StringAttr_VarName) << " "
			<< z.get(GRB_DoubleAttr_X) << endl;
		cout << "Obj: " << model.get(GRB_DoubleAttr_ObjVal) << endl;

	}
	catch (GRBException e) {
		cout << " Error code = " << e.getErrorCode() << endl;
		cout << e.getMessage() << endl;
	}
	catch (...) {
		cout << " Exception during optimization " << endl;
	}
	delete env;
	return 0;
}

求解结果

Gurobi优化器使用(一)搭建并求解一个优化模型的过程【C++环境】_第3张图片

两种方法求解结果是一样的

如何读取一个已保存的模型

以.lp模型为例。

GRBModel model = GRBModel(*env, "dense.lp");

GRBVar x = model.getVar(0);
GRBVar y = model.getVar(1);
GRBVar z = model.getVar(2);

model.optimize();

cout << x.get(GRB_StringAttr_VarName) << " "
	<< x.get(GRB_DoubleAttr_X) << endl;
cout << y.get(GRB_StringAttr_VarName) << " "
	<< y.get(GRB_DoubleAttr_X) << endl;
cout << z.get(GRB_StringAttr_VarName) << " "
	<< z.get(GRB_DoubleAttr_X) << endl;
cout << "Obj: " << model.get(GRB_DoubleAttr_ObjVal) << endl;

大部分内容跟上面是类似的,只不过在model构造函数的时候,从filename中读取模型。然后再获得变量值,进行模型优化。值得注意的是,lp文件指保留了模型的信息,并没有保存上一次优化后的结果。因此需要重新优化一下方可显示结果。

你可能感兴趣的:(优化问题及算法,c++,算法,visual,studio)