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