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

it2025-03-01  21

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

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

Gurobi可以解决的问题

文档

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

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

当系数已存入到外部的模型文件中需要读取时可以采用该方法建模,否则不推荐这种方式. 待解决的问题如下:

/* 该例子解决下面的凸二次规划问题: 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; } }

解释

构建Gurobi环境

GRBEnv* env = 0; env = new GRBEnv();

建立模型的实例

GRBModel model = GRBModel(*env);

添加优化变量

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);

注意: 传入的是指针

添加约束

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

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

设置目标函数

GRBQuadExpr obj = 0;

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

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

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);

打印最优目标值和最优解

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

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; }

求解结果

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

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

以.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文件指保留了模型的信息,并没有保存上一次优化后的结果。因此需要重新优化一下方可显示结果。

最新回复(0)