c++ SCIP求解整数规划模型

SCIP是一款开源的求解整数规划求解器,跟cplex、gurobi一样。

到SCIP官网下载软件 https://scipopt.org/#download ,下载10.0.1版本的.exe程序,点击安装。我的路径G:\software\SCIPOptSuite1001,而且G:\software\SCIPOptSuite1001\bin要添加到系统环境变量中。

CMakeLists.txt内容如下:

cpp 复制代码
cmake_minimum_required(VERSION 3.25)
project(P_median_problem)

set(CMAKE_CXX_STANDARD 20)

# 设置 SCIP 根目录(根据你的实际路径修改)
set(SCIP_DIR "G:/software/SCIPOptSuite1001")

# 包含头文件目录
include_directories(${SCIP_DIR}/include)

# 添加库目录(以便 find_library 或直接链接)
link_directories(${SCIP_DIR}/lib)

# 添加可执行文件
add_executable(my_scip_app ../improved_Lagrangian_relaxation/main1_SCIP_MIP.cpp)

# 查找 SCIP 核心库和 SoPlex 库
find_library(SCIP_CORE_LIBRARY NAMES libscip PATHS ${SCIP_DIR}/lib NO_DEFAULT_PATH)
find_library(SOPLEX_LIBRARY NAMES libsoplex libsoplexshared PATHS ${SCIP_DIR}/lib NO_DEFAULT_PATH)

if(NOT SCIP_CORE_LIBRARY)
    message(FATAL_ERROR "SCIP core library not found")
endif()
if(NOT SOPLEX_LIBRARY)
    message(FATAL_ERROR "SoPlex library not found")
endif()

target_link_libraries(my_scip_app ${SCIP_CORE_LIBRARY} ${SOPLEX_LIBRARY} ws2_32 winmm)

# 复制 SCIP bin 目录下所有 DLL 到输出目录
add_custom_command(TARGET my_scip_app POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_directory
        "${SCIP_DIR}/bin"
        $<TARGET_FILE_DIR:my_scip_app>
        COMMENT "Copying SCIP DLLs to output directory"
)

main1_SCIP_MIP.cpp内容如下:

cpp 复制代码
#include <iostream>
#include "scip/scip.h"
#include "scip/scipdefplugins.h"

using namespace std;

int main() {
    // 1. 创建 SCIP 实例并加载默认插件
    SCIP* scip = nullptr;
    SCIP_CALL( SCIPcreate(&scip) );
    SCIP_CALL( SCIPincludeDefaultPlugins(scip) );

    // 2. 创建问题
    SCIP_CALL( SCIPcreateProbBasic(scip, "simple_integer_program") );
    SCIPsetObjsense(scip, SCIP_OBJSENSE_MAXIMIZE);

    // 3. 创建变量
    SCIP_VAR* x1 = nullptr;
    SCIP_VAR* x2 = nullptr;

    SCIP_CALL( SCIPcreateVar(scip, &x1, "x1", 0.0, SCIPinfinity(scip), 3.0,
                              SCIP_VARTYPE_INTEGER, true, false,
                              nullptr, nullptr, nullptr, nullptr, nullptr) );
    SCIP_CALL( SCIPcreateVar(scip, &x2, "x2", 0.0, SCIPinfinity(scip), 5.0,
                              SCIP_VARTYPE_INTEGER, true, false,
                              nullptr, nullptr, nullptr, nullptr, nullptr) );

    SCIP_CALL( SCIPaddVar(scip, x1) );
    SCIP_CALL( SCIPaddVar(scip, x2) );

    // 4. 创建约束(使用简化版本 SCIPcreateConsBasicLinear)
    SCIP_CONS* cons1 = nullptr;
    SCIP_CONS* cons2 = nullptr;

    // 约束 1: 2x1 + 4x2 <= 100
    {
        SCIP_VAR* vars[2] = { x1, x2 };
        double coeffs[2] = { 2.0, 4.0 };
        SCIP_CALL( SCIPcreateConsBasicLinear(scip, &cons1, "resource1",
                                              2, vars, coeffs,
                                              -SCIPinfinity(scip), 100.0) );
        SCIP_CALL( SCIPaddCons(scip, cons1) );
    }

    // 约束 2: 3x1 + 2x2 <= 90
    {
        SCIP_VAR* vars[2] = { x1, x2 };
        double coeffs[2] = { 3.0, 2.0 };
        SCIP_CALL( SCIPcreateConsBasicLinear(scip, &cons2, "resource2",
                                              2, vars, coeffs,
                                              -SCIPinfinity(scip), 90.0) );
        SCIP_CALL( SCIPaddCons(scip, cons2) );
    }

    // 释放约束(已添加到问题,可以释放)
    SCIP_CALL( SCIPreleaseCons(scip, &cons1) );
    SCIP_CALL( SCIPreleaseCons(scip, &cons2) );

    // 5. 设置求解器参数
    SCIP_CALL( SCIPsetRealParam(scip, "limits/time", 60.0) );   // 限制求解时间 60 秒
    SCIP_CALL( SCIPsetIntParam(scip, "display/verblevel", 5) ); // 输出详细日志

    // 6. 求解
    cout << "Starting optimization..." << endl;
    SCIP_CALL( SCIPsolve(scip) );

    // 7. 获取解
    SCIP_SOL* sol = SCIPgetBestSol(scip);
    if ( sol ) {
        double objval = SCIPgetSolOrigObj(scip, sol);
        double x1_val = SCIPgetSolVal(scip, sol, x1);
        double x2_val = SCIPgetSolVal(scip, sol, x2);

        cout << "\nOptimal solution found!" << endl;
        cout << "Objective value = " << objval << endl;
        cout << "x1 = " << x1_val << endl;
        cout << "x2 = " << x2_val << endl;
    } else {
        cout << "No solution found." << endl;
    }

    // 8. 清理
    SCIP_CALL( SCIPreleaseVar(scip, &x1) );
    SCIP_CALL( SCIPreleaseVar(scip, &x2) );
    SCIP_CALL( SCIPfree(&scip) );

    return 0;
}

运行结果如下:

cpp 复制代码
Starting optimization...
LP Solver <SoPlex 8.0.1>: barrier convergence tolerance cannot be set -- tolerance of SCIP and LP solver may differ
LP Solver <SoPlex 8.0.1>: fastmip setting not available -- SCIP parameter has no effect
LP Solver <SoPlex 8.0.1>: number of threads settings not available -- SCIP parameter has no effect
transformed problem has 2 variables (0 bin, 2 int, 0 cont) and 2 constraints
      2 constraints of type <linear>

original problem has 4 active (100%) nonzeros and 4 (100%) check nonzeros

feasible solution found by trivial heuristic after 0.0 seconds, objective value 0.000000e+00
presolving:
(round 1, fast)       0 del vars, 0 del conss, 0 add conss, 3 chg bounds, 0 chg sides, 0 chg coeffs, 0 upgd conss, 0 impls, 0 clqs, 0 implints
   (0.0s) running MILP presolver
   (0.0s) MILP presolver found nothing
(round 2, exhaustive) 0 del vars, 0 del conss, 0 add conss, 3 chg bounds, 0 chg sides, 0 chg coeffs, 2 upgd conss, 0 impls, 0 clqs, 0 implints
   (0.0s) symmetry computation started: requiring (bin +, int +, cont +), (fixed: bin -, int -, cont -)
   (0.0s) no symmetry present (symcode time: 0.00)
clique table cleanup detected 0 bound changes

presolved problem has 4 active (100%) nonzeros and 4 (100%) check nonzeros

presolving (3 rounds: 3 fast, 2 medium, 2 exhaustive):
 0 deleted vars, 0 deleted constraints, 0 added constraints, 3 tightened bounds, 0 added holes, 0 changed sides, 0 changed coefficients
 0 implications, 0 cliques, 0 implied integral variables (0 bin, 0 int, 0 cont)
presolved problem has 2 variables (0 bin, 2 int, 0 cont) and 2 constraints
      2 constraints of type <varbound>
transformed objective value is always integral (scale: 1)
Presolving Time: 0.00
transformed 1/1 original solutions to the transformed problem space

 time | node  | left  |LP iter|LP it/n|mem/heur|mdpt |vars |cons |rows |cuts |sepa|confs|strbr|  dualbound   | primalbound  |  gap   | compl. 
p 0.0s|     1 |     0 |     0 |     - | vbounds|   0 |   2 |   2 |   2 |   0 |  0 |   0 |   0 | 2.150000e+02 | 9.000000e+01 | 138.89%| unknown
p 0.0s|     1 |     0 |     0 |     - | vbounds|   0 |   2 |   2 |   2 |   0 |  0 |   1 |   0 | 2.150000e+02 | 1.250000e+02 |  72.00%| unknown
* 0.0s|     1 |     0 |     2 |     - |    LP  |   0 |   2 |   2 |   2 |   0 |  0 |   3 |   0 | 1.350000e+02 | 1.350000e+02 |   0.00%| unknown
  0.0s|     1 |     0 |     2 |     - |   843k |   0 |   2 |   2 |   2 |   0 |  0 |   3 |   0 | 1.350000e+02 | 1.350000e+02 |   0.00%| unknown

SCIP Status        : problem is solved [optimal solution found]
Solving Time (sec) : 0.00
Solving Nodes      : 1
Primal Bound       : +1.35000000000000e+02 (4 solutions)
Dual Bound         : +1.35000000000000e+02
Gap                : 0.00 %

Optimal solution found!
Objective value = 135
x1 = 20
x2 = 15

Process finished with exit code 0
相关推荐
echome8882 小时前
Python 装饰器详解:从入门到实战
开发语言·python
奇树谦2 小时前
QMap 全面解析(Qt5 vs Qt6)
开发语言·qt
sqyno1sky2 小时前
代码动态生成技术
开发语言·c++·算法
中科三方2 小时前
域名管理常见问题:添加域名解析多久生效?为什么不能马上生效?
开发语言·php
廖圣平2 小时前
Drogon 现代化C ++高性能框架
android·c语言·开发语言
2401_853576502 小时前
C++中的策略模式变体
开发语言·c++·算法
lj850862 小时前
性能测试总结
java·开发语言·spring
学嵌入式的小杨同学2 小时前
STM32 进阶封神之路(十四):语音交互实战 ——SU03T 语音识别模块从固件制作到 STM32 控制(串口通信 + 命令响应)
c++·stm32·单片机·嵌入式硬件·架构·硬件架构·ux
阿蒙Amon2 小时前
C#常用类库-详解Ecng.Collections
开发语言·c#·ar