用C++调用Gurobi的基操教学(后续倾向求解VRP问题)
????????最近要用到Gurobi,而我自己不经常用python,但是在晚上几乎找不到除了操作手册之外的攻略,这对于我一个重度依赖CSDN的人来说简直是大灾难,所以在这里边学边记录,教学相长,欢迎评论区纠错
环境配置
? ? ? ? 首先开一个空项目
????????提前准备好gurobi的文件夹,最主要的是里面的两个文件夹的地址,vs2022与gurobi11.00是相对应的【据说版本对应不上是用不了的,但是我没有试过】gurobi11.0对应vs2017~vs2023
两个文件夹地址分别为
C:\gurobi1100\win64\include
C:\gurobi1100\win64\lib
配置C/C++外部包含目录
选择【属性】
【VC/C++】?→?【外部包含目录V】?→<编辑>
将地址C:\gurobi1100\win64\include添加进去
同时,需要确保【C/C++】的子菜单项【预编译头】设置为【不使用预编译头】。
配置链接器的附加库目录和附加依赖项
【链接器】?→?【常规】?→?【附加库目录】下,添加下文件路径:
C:\gurobi1100\win64\lib
????????接下来在gurobi文件夹中,进入C:\gurobi1100\win64\lib
? ? ? ? 具体如下图所示,选择红框中的两个文件,其名称分别是:
????????gurobi_c++mdd2017.lib
????????gurobi110.lib
? ? ? ? 应在【链接器】?→?【输入】?→?【附加依赖项】下添加这两个文件,注意,用英文分号;隔开。
? ? ? ? 最后点击确定,至此配置完成,接下来用官网公布的一段代码进行测试,如果运行成功就证明配置OK啦
函数测试
/* Copyright 2023, Gurobi Optimization, LLC */
/* This example formulates and solves the following simple MIP model:
maximize x + y + 2 z
subject to x + 2 y + 3 z <= 4
x + y >= 1
x, y, z binary
*/
#include "gurobi_c++.h"
using namespace std;
int
main(int argc,
char *argv[])
{
try {
// Create an environment
GRBEnv env = GRBEnv(true);
env.set("LogFile", "mip1.log");
env.start();
// Create an empty model
GRBModel model = GRBModel(env);
// Create variables
GRBVar x = model.addVar(0.0, 1.0, 0.0, GRB_BINARY, "x");
GRBVar y = model.addVar(0.0, 1.0, 0.0, GRB_BINARY, "y");
GRBVar z = model.addVar(0.0, 1.0, 0.0, GRB_BINARY, "z");
// Set objective: maximize x + y + 2 z
model.setObjective(x + y + 2 * z, GRB_MAXIMIZE);
// Add constraint: x + 2 y + 3 z <= 4
model.addConstr(x + 2 * y + 3 * z <= 4, "c0");
// Add constraint: x + y >= 1
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;
}
return 0;
}
运行结果如下图所示:
Gurobi介绍
????????直接跳过,因为我相信但凡来查找如何使用的朋友,一定都有自己的使用目的且在一定程度上了解gurobi
????????而我每次点开同类帖子大段的文字描写环境配置和介绍,一问到底怎么写,就说不出来了
导入头文件
????????环境配置之后,可以导入
#include<gurobi_c++.h>
错误报告
????????不知道为什么,所有代码都是在try里面写的,有固定格式的感觉,但是由于我c++学的也不好,没办法解释
int main()
{
try
{
// Formulate and solve model
}
catch(GRBException e)
{
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
} catch(...)
{
cout << "Exception during optimization" << endl;
}
}
????????主要书写内容都在try里面
创建环境
????????先展示一下官方代码
// Create an environment
GRBEnv env = GRBEnv(true);
env.set("LogFile", "mip1.log");
env.start();
????????但实际上,经过翻阅各类信息,合理利用gpt与实验,我发现只用写
// 创建Gurobi环境
GRBEnv env = GRBEnv();
就可以了。
????????我目前还是不知道是为什么的。(不知道评论区有没有大佬可以帮我解答一下)
创建模型
????????直接照抄模板,按顺序copy就可以了
GRBModel model = GRBModel(env);
向模型添加变量
先看示例
// Create variables
GRBVar x = model.addVar(0.0, 1.0, 0.0, GRB_BINARY, "x");
GRBVar y = model.addVar(0.0, 1.0, 0.0, GRB_BINARY, "y");
GRBVar z = model.addVar(0.0, 1.0, 0.0, GRB_BINARY, "z");
????????变量是通过模型对象上的 GRBModel::addVar 方法添加的。
GRBModel::addVar()
addVar() 一次增加一个变量
GRBVar addVar (double lb, double ub, double obj, char type, string name="" )
参数 | 详解 |
---|---|
lb | 新变量的下限。 |
ub | 新变量的上限。 |
obj | 新变量的客观系数。 |
type | 新变量的变量类型(GRB_CONTINUOUS、GRB_BINARY、GRB_INTEGER、GRB_SEMICONT 或 GRB_SEMIINT)。 |
names(可选) | 新变量的名称。 |
返回值 | 新的变量对象。 |
变量类型
变量类型 | 意义 | 用处 | 常规下限 | 上限 |
GRB_CONTINUOUS | 连续型 | 0 | INFINITY | |
GRB_BINARY | 二进制 | 0-1整数规划模型 | 0.0 | 1.0 |
GRB_INTEGER | 整数型 | |||
GRB_SEMICONT | 半连续性 | |||
GRB_SEMIINT | 半整数(?) |
? ? ? ? ?关于变量类型上下限的部分,暂时留白,因为我也没有看懂,只是翻阅了一下代码发现常规都是这样的,肯定还需要根据自己的问题切实修改。
GRBModel::addVars()
一次添加多个变量?
向模型添加约束
// Add constraint: x + 2 y + 3 z <= 4
model.addConstr(x + 2 * y + 3 * z <= 4, "c0");
GRBModel::addConstr()
种类很多……我暂时没发现除了参数不同之外还有什么区别,也不知道怎么区分去使用
?GRBConstr ?? ?addConstr(const GRBLinExpr& lhsExpr,
? ?? ??? ??? ? ??? ? ??? ? ?char sense,
? ?? ??? ??? ? ??? ? ??? ? ?const GRBLinExpr& rhsExpr,
? ?? ??? ??? ? ??? ? ??? ? ?string name="" )
参数 | 详解 |
---|---|
lhsExpr | 新线性约束的左侧表达式。 |
sense | 感知新的线性约束(GRB_LESS_EQUAL、GRB_EQUAL 或 GRB_GREATER_EQUAL)。 |
rhsExpr | 新线性约束的右侧表达式。 |
names(可选) | 新约束的名称。 |
返回值 | 新的约束对象。 |
设置优化目标
// Set objective: maximize x + y + 2 z
model.setObjective(x + y + 2 * z, GRB_MAXIMIZE);
????????还有第二种表达方法,应该是面对累加∑等情况,可以和循环搭配使用
GRBLinExpr obj = 0.0;
obj += x;
obj += y;
obj += 2*z;
model.setObjective(obj, GRB_MAXIMIZE);
优化模型
????????特别神奇的事情,只需要一行代码就可以搞定所有优化?
? ? ? ? ?这可能就是这个优化器的神奇之处吧
// 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;
????????我们还可以查询模型上的?ObjVal?属性,以获取当前解决方案的目标值:
cout << "Obj: " << model.get(GRB_DoubleAttr_ObjVal) << endl;
题目概述
????????经典VRP问题,多仓库多城市多车,找最短路径分配的VRP问题的代码。仓库开启需要花费100元,仓库关闭需要花费成本50元,持续运营在每一个回合需要耗费10元,车行驶一个单位长度需要花费10元,每辆车都必须从仓库出发,并且在完成配送任务后返回仓库,目标函数为最小花费。
现在已有参数以及目标函数及约束条件
1.在代码里添加所有参数作为变量?(doing)
2.定义集合?
感想随记
12.29夜晚开坑,在实验室里一时冲动就开了帖子,结果晚上快11点的时候被关门大爷赶了出去
12.30写着写着发现自己关于LP的知识全部还给老师了,今天去图书馆突击看一下……不然连符号都看不懂了,目前这个文章写得太草率了,主要是因为后续关于如何解决VRP问题,我遇到了比较多的问题正在解决,后续VRP问题会再开一个新帖子,这个帖子会根据后续我的学习再进行补充
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!