Cbc(Coin或branch and cut)是一个开源的混合整数线性规划求解器,用C++编写。它可以用作可调用库或使用独立的可执行文件。它可以通过各种建模系统、包等以多种方式使用。Clp(Coin或线性规划)是一个开源线性规划求解器。它主要是用来作为一个可调用的库,但也有一个基本的、独立的可执行版本。本文将介绍如何用CLion(CMake)构建工程并能debug源码。
相关教程
相关文献
CMake工程构建(能访问GitHub方法)
博主的环境是Ubuntu 20.04 LTS。 首先打开CLion创建新工程: 修改CMakeLists.txt:
cmake_minimum_required(VERSION 3.21)
project(CbcProject)
set(PROJECT_ROOT_PATH "${PROJECT_SOURCE_DIR}")
set(LIBRARY_OUTPUT_PATH "${PROJECT_ROOT_PATH}/${OUTDIRS}/lib/")
set(EXECUTABLE_OUTPUT_PATH "${PROJECT_ROOT_PATH}/${OUTDIRS}/bin/")
set(BUILD_DEPS ON)
if (BUILD_DEPS)
set(BUILD_CoinUtils ON)
set(BUILD_Osi ON)
set(BUILD_Clp ON)
set(BUILD_Cgl ON)
set(BUILD_Cbc ON)
endif ()
include(FetchContent)
set(FETCHCONTENT_QUIET OFF)
get_filename_component(_deps "../_deps" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
set(FETCHCONTENT_BASE_DIR ${_deps})
set(CMAKE_CXX_STANDARD 11)
if (BUILD_CoinUtils)
message(CHECK_START "Fetching CoinUtils")
list(APPEND CMAKE_MESSAGE_INDENT " ")
FetchContent_Declare(
CoinUtils
GIT_REPOSITORY "https://github.com/Mizux/CoinUtils.git"
GIT_TAG "cmake/2.11.6"
)
FetchContent_MakeAvailable(CoinUtils)
list(POP_BACK CMAKE_MESSAGE_INDENT)
message(CHECK_PASS "fetched")
endif ()
if (BUILD_Osi)
message(CHECK_START "Fetching Osi")
list(APPEND CMAKE_MESSAGE_INDENT " ")
FetchContent_Declare(
Osi
GIT_REPOSITORY "https://github.com/Mizux/Osi.git"
GIT_TAG "cmake/0.108.7"
)
FetchContent_MakeAvailable(Osi)
list(POP_BACK CMAKE_MESSAGE_INDENT)
message(CHECK_PASS "fetched")
endif ()
if (BUILD_Clp)
message(CHECK_START "Fetching Clp")
list(APPEND CMAKE_MESSAGE_INDENT " ")
FetchContent_Declare(
Clp
GIT_REPOSITORY "https://github.com/Mizux/Clp.git"
GIT_TAG "cmake/1.17.7"
)
FetchContent_MakeAvailable(Clp)
list(POP_BACK CMAKE_MESSAGE_INDENT)
message(CHECK_PASS "fetched")
endif ()
if (BUILD_Cgl)
message(CHECK_START "Fetching Cgl")
list(APPEND CMAKE_MESSAGE_INDENT " ")
FetchContent_Declare(
Cgl
GIT_REPOSITORY "https://github.com/Mizux/Cgl.git"
GIT_TAG "cmake/0.60.5"
)
FetchContent_MakeAvailable(Cgl)
list(POP_BACK CMAKE_MESSAGE_INDENT)
message(CHECK_PASS "fetched")
endif ()
if (BUILD_Cbc)
message(CHECK_START "Fetching Cbc")
list(APPEND CMAKE_MESSAGE_INDENT " ")
FetchContent_Declare(
Cbc
GIT_REPOSITORY "https://github.com/Mizux/Cbc.git"
GIT_TAG "cmake/2.10.7"
)
FetchContent_MakeAvailable(Cbc)
list(POP_BACK CMAKE_MESSAGE_INDENT)
message(CHECK_PASS "fetched")
endif ()
add_executable(${PROJECT_NAME} main.cpp)
if (BUILD_DEPS)
set(COINOR_DEPS Coin::CbcSolver Coin::OsiCbc Coin::ClpSolver Coin::OsiClp)
target_link_libraries(${PROJECT_NAME} PUBLIC ${COINOR_DEPS})
endif ()
然后你会看到:
CMake工程构建(不能访问GitHub方法)
博主的环境是Ubuntu 20.04 LTS。 首先打开CLion创建新工程: 下载:coin-or/CoinUtils-cmake-2.11.6 Osi-cmake-0.108.7 Clp-cmake-1.17.7 Cgl-cmake-0.60.5 Cbc-cmake-2.10.7源码 解压到: 修改CMakeLists.txt:
cmake_minimum_required(VERSION 3.21)
project(CbcProject)
set(PROJECT_ROOT_PATH "${PROJECT_SOURCE_DIR}")
set(LIBRARY_OUTPUT_PATH "${PROJECT_ROOT_PATH}/${OUTDIRS}/lib/")
set(EXECUTABLE_OUTPUT_PATH "${PROJECT_ROOT_PATH}/${OUTDIRS}/bin/")
set(BUILD_DEPS ON)
if (BUILD_DEPS)
set(BUILD_CoinUtils ON)
set(BUILD_Osi ON)
set(BUILD_Clp ON)
set(BUILD_Cgl ON)
set(BUILD_Cbc ON)
endif ()
include(FetchContent)
set(FETCHCONTENT_QUIET OFF)
get_filename_component(_deps "../_deps" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
set(FETCHCONTENT_BASE_DIR ${_deps})
set(CMAKE_CXX_STANDARD 11)
if (BUILD_CoinUtils)
message(CHECK_START "Fetching CoinUtils")
list(APPEND CMAKE_MESSAGE_INDENT " ")
FetchContent_Declare(
CoinUtils
URL "${PROJECT_SOURCE_DIR}/deps/CoinUtils-cmake-2.11.6.zip"
)
FetchContent_MakeAvailable(CoinUtils)
list(POP_BACK CMAKE_MESSAGE_INDENT)
message(CHECK_PASS "fetched")
endif ()
if (BUILD_Osi)
message(CHECK_START "Fetching Osi")
list(APPEND CMAKE_MESSAGE_INDENT " ")
FetchContent_Declare(
Osi
URL "${PROJECT_SOURCE_DIR}/deps/Osi-cmake-0.108.7.zip"
)
FetchContent_MakeAvailable(Osi)
list(POP_BACK CMAKE_MESSAGE_INDENT)
message(CHECK_PASS "fetched")
endif ()
if (BUILD_Clp)
message(CHECK_START "Fetching Clp")
list(APPEND CMAKE_MESSAGE_INDENT " ")
FetchContent_Declare(
Clp
URL "${PROJECT_SOURCE_DIR}/deps/Clp-cmake-1.17.7.zip"
)
FetchContent_MakeAvailable(Clp)
list(POP_BACK CMAKE_MESSAGE_INDENT)
message(CHECK_PASS "fetched")
endif ()
if (BUILD_Cgl)
message(CHECK_START "Fetching Cgl")
list(APPEND CMAKE_MESSAGE_INDENT " ")
FetchContent_Declare(
Cgl
URL "${PROJECT_SOURCE_DIR}/deps/Cgl-cmake-0.60.5.zip"
)
FetchContent_MakeAvailable(Cgl)
list(POP_BACK CMAKE_MESSAGE_INDENT)
message(CHECK_PASS "fetched")
endif ()
if (BUILD_Cbc)
message(CHECK_START "Fetching Cbc")
list(APPEND CMAKE_MESSAGE_INDENT " ")
FetchContent_Declare(
Cbc
URL "${PROJECT_SOURCE_DIR}/deps/Cbc-cmake-2.10.7.zip"
)
FetchContent_MakeAvailable(Cbc)
list(POP_BACK CMAKE_MESSAGE_INDENT)
message(CHECK_PASS "fetched")
endif ()
add_executable(${PROJECT_NAME} main.cpp)
if (BUILD_DEPS)
set(COINOR_DEPS Coin::CbcSolver Coin::OsiCbc Coin::ClpSolver Coin::OsiClp)
target_link_libraries(${PROJECT_NAME} PUBLIC ${COINOR_DEPS})
endif ()
CLion debug源码
main.cpp:
#include <iostream>
#include "ClpSimplex.hpp"
#include "CoinBuild.hpp"
#include "CoinHelperFunctions.hpp"
#include "CoinModel.hpp"
#include "CoinTime.hpp"
#include <iomanip>
int main() {
ClpSimplex model;
int objIndex[] = {0, 2};
double objValue[] = {1.0, 4.0};
double upper[] = {2.0, COIN_DBL_MAX, 4.0};
model.resize(0, 3);
int i;
for (i = 0; i < 2; i++)
model.setObjectiveCoefficient(objIndex[i], objValue[i]);
for (i = 0; i < 3; i++) {
model.setColumnLower(i, 0.0);
model.setColumnUpper(i, upper[i]);
}
int row1Index[] = {0, 2};
double row1Value[] = {1.0, 1.0};
model.addRow(2, row1Index, row1Value,
2.0, COIN_DBL_MAX);
int row2Index[] = {0, 1, 2};
double row2Value[] = {1.0, -5.0, 1.0};
model.addRow(3, row2Index, row2Value,
1.0, 1.0);
model.dual();
model.allSlackBasis();
ClpSimplex modelSave = model;
double time1 = CoinCpuTime();
int k;
for (k = 0; k < 10000; k++) {
int row2Index[] = {0, 1, 2};
double row2Value[] = {1.0, -5.0, 1.0};
model.addRow(3, row2Index, row2Value,
1.0, 1.0);
}
printf("Time for 10000 addRow is %g\n", CoinCpuTime() - time1);
model.dual();
model = modelSave;
CoinBuild buildObject;
time1 = CoinCpuTime();
for (k = 0; k < 10000; k++) {
int row2Index[] = {0, 1, 2};
double row2Value[] = {1.0, -5.0, 1.0};
buildObject.addRow(3, row2Index, row2Value,
1.0, 1.0);
}
model.addRows(buildObject);
printf("Time for 10000 addRow using CoinBuild is %g\n", CoinCpuTime() - time1);
model.dual();
model = modelSave;
int del[] = {0, 1, 2};
model.deleteRows(2, del);
CoinBuild buildObject2;
time1 = CoinCpuTime();
for (k = 0; k < 10000; k++) {
int row2Index[] = {0, 1, 2};
double row2Value[] = {1.0, -1.0, 1.0};
buildObject2.addRow(3, row2Index, row2Value,
1.0, 1.0);
}
model.addRows(buildObject2, true);
printf("Time for 10000 addRow using CoinBuild+-1 is %g\n", CoinCpuTime() - time1);
model.dual();
model = modelSave;
model.deleteRows(2, del);
CoinModel modelObject2;
time1 = CoinCpuTime();
for (k = 0; k < 10000; k++) {
int row2Index[] = {0, 1, 2};
double row2Value[] = {1.0, -1.0, 1.0};
modelObject2.addRow(3, row2Index, row2Value,
1.0, 1.0);
}
model.addRows(modelObject2, true);
printf("Time for 10000 addRow using CoinModel+-1 is %g\n", CoinCpuTime() - time1);
model.dual();
model = ClpSimplex();
CoinModel modelObject3;
time1 = CoinCpuTime();
for (k = 0; k < 10000; k++) {
int row2Index[] = {0, 1, 2};
double row2Value[] = {1.0, -1.0, 1.0};
modelObject3.addRow(3, row2Index, row2Value,
1.0, 1.0);
}
model.loadProblem(modelObject3, true);
printf("Time for 10000 addRow using CoinModel load +-1 is %g\n", CoinCpuTime() - time1);
model.writeMps("xx.mps");
model.dual();
model = modelSave;
CoinModel modelObject;
time1 = CoinCpuTime();
for (k = 0; k < 10000; k++) {
int row2Index[] = {0, 1, 2};
double row2Value[] = {1.0, -5.0, 1.0};
modelObject.addRow(3, row2Index, row2Value,
1.0, 1.0);
}
model.addRows(modelObject);
printf("Time for 10000 addRow using CoinModel is %g\n", CoinCpuTime() - time1);
model.dual();
model.writeMps("b.mps");
time1 = CoinCpuTime();
ClpSimplex model2;
{
int numberRows = 10000;
int numberColumns = 3;
int numberElements = numberRows * numberColumns;
model2.resize(numberRows, numberColumns);
double *elements = new double[numberElements];
CoinBigIndex *starts = new CoinBigIndex[numberColumns + 1];
int *rows = new int[numberElements];;
int *lengths = new int[numberColumns];
double *columnUpper = model2.columnUpper();
double *objective = model2.objective();
double *rowLower = model2.rowLower();
double *rowUpper = model2.rowUpper();
for (k = 0; k < 2; k++) {
int iColumn = objIndex[k];
objective[iColumn] = objValue[k];
}
for (k = 0; k < numberColumns; k++)
columnUpper[k] = upper[k];
for (k = 0; k < numberRows; k++) {
rowLower[k] = 1.0;
rowUpper[k] = 1.0;
}
double row2Value[] = {1.0, -5.0, 1.0};
CoinBigIndex put = 0;
for (k = 0; k < numberColumns; k++) {
starts[k] = put;
lengths[k] = numberRows;
double value = row2Value[k];
for (int i = 0; i < numberRows; i++) {
rows[put] = i;
elements[put] = value;
put++;
}
}
starts[numberColumns] = put;
CoinPackedMatrix *matrix = new CoinPackedMatrix(true, 0.0, 0.0);
matrix->assignMatrix(true, numberRows, numberColumns, numberElements,
elements, rows, starts, lengths);
ClpPackedMatrix *clpMatrix = new ClpPackedMatrix(matrix);
model2.replaceMatrix(clpMatrix, true);
printf("Time for 10000 addRow using hand written code is %g\n", CoinCpuTime() - time1);
}
model2.dual();
model2.writeMps("a.mps");
int numberColumns = model.numberColumns();
double *columnPrimal = model.primalColumnSolution();
double *columnDual = model.dualColumnSolution();
double *columnLower = model.columnLower();
double *columnUpper = model.columnUpper();
double *columnObjective = model.objective();
int iColumn;
std::cout << " Primal Dual Lower Upper Cost"
<< std::endl;
for (iColumn = 0; iColumn < numberColumns; iColumn++) {
double value;
std::cout << std::setw(6) << iColumn << " ";
value = columnPrimal[iColumn];
if (fabs(value) < 1.0e5)
std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
else
std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value;
value = columnDual[iColumn];
if (fabs(value) < 1.0e5)
std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
else
std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value;
value = columnLower[iColumn];
if (fabs(value) < 1.0e5)
std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
else
std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value;
value = columnUpper[iColumn];
if (fabs(value) < 1.0e5)
std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
else
std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value;
value = columnObjective[iColumn];
if (fabs(value) < 1.0e5)
std::cout << std::setiosflags(std::ios::fixed | std::ios::showpoint) << std::setw(14) << value;
else
std::cout << std::setiosflags(std::ios::scientific) << std::setw(14) << value;
std::cout << std::endl;
}
std::cout << "--------------------------------------" << std::endl;
return 0;
}
最后尽情地开始Debug吧!!!(上一张成果图):
CMake打包Cbc.so:
其实通过上述步骤编译后你就会发现多了一个lib目录:
|