一、前言
虽然C++编程大部分人都会选择使用VS,但是作为 IDEA 的长期用户,我还是比较习惯 JetBrains 风格的编译器,所以就选择使用 CLion 进行 C++ 的编程。
关于 CLion 中如何引入 Gurobi,网上的资料很少,并且大部分都是针对 Linux/Mac 系统的,我也是踩了很多坑才尝试成功。在此特地记录一下。
本博客的实验环境是:Windows 11、CLion 2023.2.1、Gurobi 10.0.1;并且已经安装了 VS 2022 和 VS 2013。
二、具体操作
2.1 创建项目
使用 CLion 的小伙伴,创建项目的步骤就不用我解释了吧。如下图所示,我们创建一个测试项目,取名为 test3,并使用 C++17 标准。
项目创建成功后,如下图所示:
2.2 修改编译工具
这里就是我踩坑最久的地方,默认应该都是 MinGW 编译,但是 Gurobi 不支持 MinGW 编译,因此需要换成 VS 编译。
这里需要注意一下版本对应,高版本的 Gurobi 一般也需要高版本的 VS 才能编译成功,之前我是用的 VS 2013,编译没成功,后来换了 VS 2022 才成功的。
2.3 修改 CMakeLists.txt
修改后的 CMakeLists.txt 内容如下(注意,你的电脑中关于 Gurobi 的环境变量 GUROBI_HOME
需要配置好才可使用下面的代码):
cmake_minimum_required(VERSION 3.26)
project(test3)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXE_LINKER_FLAGS "-static")
add_executable(${PROJECT_NAME} main.cpp)
#################################################### Gurobi ####################################################
set(GUROBI_LIB_DIR "$ENV{GUROBI_HOME}\\lib")
set(GUROBI_INCLUDE_DIR "$ENV{GUROBI_HOME}\\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}\\gurobi100.lib" "${GUROBI_LIB_DIR}\\gurobi_c++mdd2017.lib")
2.4 修改 main.cpp
/* Copyright 2022, 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;
void testGurobi() {
try {
// Create an environment
GRBEnv env = GRBEnv("ENV");
// 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;
}
}
int main(int argc, char *argv[]) {
testGurobi();
return 0;
}
2.5 运行测试
Gurobi Optimizer version 10.0.1 build v10.0.1rc0 (win64)
CPU model: 12th Gen Intel(R) Core(TM) i9-12900H, instruction set [SSE2|AVX|AVX2]
Thread count: 14 physical cores, 20 logical processors, using up to 20 threads
Optimize a model with 2 rows, 3 columns and 5 nonzeros
Model fingerprint: 0x98886187
Variable types: 0 continuous, 3 integer (3 binary)
Coefficient statistics:
Matrix range [1e+00, 3e+00]
Objective range [1e+00, 2e+00]
Bounds range [1e+00, 1e+00]
RHS range [1e+00, 4e+00]
Found heuristic solution: objective 2.0000000
Presolve removed 2 rows and 3 columns
Presolve time: 0.00s
Presolve: All rows and columns removed
Explored 0 nodes (0 simplex iterations) in 0.00 seconds (0.00 work units)
Thread count was 1 (of 20 available processors)
Solution count 2: 3 2
Optimal solution found (tolerance 1.00e-04)
Best objective 3.000000000000e+00, best bound 3.000000000000e+00, gap 0.0000%
x 1
y 0
z 1
Obj: 3