122
社区成员
发帖
与我相关
我的任务
分享| 这个作业属于哪个课程 | 2302软件工程社区 |
|---|---|
| 这个作业要求在哪里 | 软件工程实践总结&个人技术博客 |
| 这个作业的目标 | 个人技术总结 |
| 其他参考文献 | CSDN、Gurobi官方文档 |
Gurobi是由美国 Gurobi Optimization 公司开发新一代大规模优化器,能对连续和混合整数线性问题、凸目标或约束连续和混合整数二次问题、非凸目标或约束连续和混合整数二次问题、含有对数指数三角函数高阶多项式目标或约束、以及任何形式的分段约束的非线性问题、含有绝对值最大值最小值逻辑与或非目标或约束的非线性问题等进行优化和求解。在开学初的规划中,我制定了贯穿一学期的科研任务,论文的实验也接近了尾声,于是我挑了实验中使用的比较多的ILP求解器来进行分享。
相信线性规划大家都不陌生,我们来看看高中学的线性规划是什么样的:

线性规划(LP)问题在许多科研学术上用处相当广泛,很多运筹学中的实际问题都可以用线性规划来表述。线性规划的某些特殊情况,例如网络流、多商品流量等问题,都被认为非常重要,并有大量对其算法的专门研究。很多其他种类的最优化问题算法都可以分拆成线性规划子问题,然后求得解。不过本文的重点不在此,本文主要介绍使用Gurobi解决线性规划问题(LP)的一个子分类:整数线性规划问题(ILP)。整数线性规划即线性规划问题中的所有变量约束为整数。由于整数约束条件的存在,ILP问题通常比线性规划问题更难。因此,在最坏情况下,ILP问题是NP难问题。也是由于整数约束的存在,离散化的变量也使得这类问题非常适用于使用计算机求解。
像下面两个ILP的例子就出自于两篇计算机的顶刊论文中:


还有下面的是清华大学的某专利中出现的ILP:

这些例子也体现出ILP求解不仅在计算机学术科研上有很多时候会用到,在民用技术里也会有所涉及,而求解ILP问题常常会使用求解器,现在有很多商用和免费的求解器可供使用,这里介绍其中比较优秀的一款商用求解器:Gurobi,Gurobi在今年四月份已全面支持国产芯片,与华为、阿里等国内大厂均有合作:


Gurobi激活过程有两种方式:
一种是IP激活,需要连接高校的内网,本人是福州某大学的在校生,本校校园网不能使用该方法激活(这里要吐槽一下了,我校的校园网真实又贵又难用,还限设备,这几天还出Bug了,动不动就拉黑名单,麻烦做校园网检测软件的程序员做好测试再上线吧,一看就没有按照标准的软件开发流程进行开发);
另一种是可以使用这里的方法进行申请,填写资料使用学校邮箱发邮件进行申请,一般不超过一天(我是几分钟就收到了)就会收到激活码邮件:

按邮件上的操作激活后就可以愉快的使用Gurobi了
在C++中使用Gurobi求解器大致分为五步:
一、创建模型
首先模型的建立需要根据具体情境进行建模,然后通过下面两句代码
GRBEnv env = GRBEnv();
GRBModel model = GRBModel(env);
创建model对象。
二、添加变量
通过model对象的addVar方法可以创建ILP所需要的变量,其中Gurobi宏定义了GRB_BINARY(二元变量)GRB_CONTINUOUS(连续变量)GRB_INTEGER(整数变量)GRB_BINARY(混合整数变量)和GRB_SEMICONT&GRB_SEMIINT(单双根恰好问题变量)各种变量对应的addVar方法的参数不太一样,可以按照需求查阅官方文档。
三、设置目标函数
通过model对象的setObjective()方法可以设置目标函数,如求解某几个变量的和最大化:
先声明GRBLinExpr对象:
GRBLinExpr obj;
然后将二中添加的某几个变量(假设是x,y,z)赋值给obj对象
obj+=x+y+z;
最后通过setObjective()方法添加目标函数
model.setObjective(obj, GRB_MAXIMIZE);
四、设置约束
通过调用model对象的addConstr方法可以添加约束,具体的项目按照具体的约束进行添加
model.addConstr(flow_in == 0);
model.addConstr(flow_out == 1);
上面这个只是我做项目时的一个例子,目的是约束图中该点出度为1,入度为0。
五、求解
最后通过调用model对象的optimize()开始求解器的求解
model.optimize();
具体的项目问题由于项目还没有公开这里不方便公开讲述,但这里可以讲讲我是如何放弃使用Visual Studio转而使用由Oracle开发、界面简单易用的C++ide:CLion的。
由于Gurobi和微软那不得不说的二三事,Gurobi求解器高度依赖Visual Studio的编译器,但长期使用idea和CLion进行开发的我实在不习惯Visual Studio生硬的界面和难用的代码提示,于是便花了些功夫将Gurobi配置在了CLion中:
首先是编译器的选择,CLion默认是使用MinGW进行编译,我们首先要将编译器修改为Visual Studio
如下图:

然后就是CLion是通过Cmake构建项目的,熟悉java的同学能想象maven在java中的作用吗?Cmake的作用差不多,所以在CLion中导入外部包和在idea中通过maven导入包一样简单,通过添加下面的Cmake配置:(注意下面路径中的Gurobi修改为你自己下载Gurobi的路径,如你下载在C盘就把下面的Gurobi\win64\lib改为C\win64\lib)
#################################################### Gurobi ####################################################
set(GUROBI_LIB_DIR "Gurobi\\win64\\lib")
set(GUROBI_INCLUDE_DIR "Gurobi\\win64\\include")
message(STATUS "GUROBI_LIB_DIR: ${GUROBI_LIB_DIR}")
message(STATUS "GUROBI_INCLUDE_DIR: ${GUROBI_INCLUDE_DIR}")
link_directories(${GUROBI_LIB_DIR})
include_directories(${GUROBI_INCLUDE_DIR})
target_link_libraries(${PROJECT_NAME} "${GUROBI_LIB_DIR}\\gurobi110.lib" "${GUROBI_LIB_DIR}\\gurobi_c++mdd2017.lib")
最后在项目中就可以直接导入使用了:
#include "gurobi_c++.h"
除了ILP,类似的LP、QP、QCP、MIQP、NLP等都可以通过Gurobi进行优化求解,在物流、生产制造、金融、交通运输、资源管理、集成电路设计、环境保护、电力管理等等领域都有涉及。
即使在工科的科研项目中不使用ILP,做对比实验复现时ILP方法也是常常用来对比的实验,而Gurobi求解器在我使用的过程来看已经是比较好入手的求解器了。有需要的话建议首先考虑。