Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,23 @@ option(SETCOVERINGSOLVER_USE_CLP "Use Clp" OFF)
option(SETCOVERINGSOLVER_USE_CBC "Use Cbc" OFF)
option(SETCOVERINGSOLVER_USE_HIGHS "Use HiGHS" OFF)
option(SETCOVERINGSOLVER_USE_XPRESS "Use FICO Xpress" OFF)
option(SETCOVERINGSOLVER_USE_ORTOOLS "Use OR-Tools" OFF)

# Avoid FetchContent warning.
cmake_policy(SET CMP0135 NEW)

# Require C++14.
set(CMAKE_CXX_STANDARD 14)
# Require C++17.
set(CMAKE_CXX_STANDARD 17)

# Enable output of compile commands during generation.
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# Set MSVC_RUNTIME_LIBRARY.
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

# Update RPATH.
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")

# Add sub-directories.
add_subdirectory(extern)
add_subdirectory(src)
Expand Down
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Some parts of the code have been contributed by [Guillaume Verger](https://githu

- Mixed-integer linear program `--algorithm milp --solver highs`

- CP-SAT solved with OR-Tools `--algorithm cp-sat-ortools`

- Row weighting local search (unicost only) `--algorithm local-search-row-weighting`

- Large neighborhood search `--algorithm large-neighborhood-search --maximum-number-of-iterations 100000 --maximum-number-of-iterations-without-improvement 10000`
Expand All @@ -32,6 +34,23 @@ cmake --build build --config Release --parallel
cmake --install build --config Release --prefix install
```

To use OR-Tools
* Download and extract OR-Tools distribution binaries from the official website: https://developers.google.com/optimization/install/cpp
* Define an `ORTOOLSDIR` environment variable as the path to the extracted folder:
```shell
export ORTOOLSDIR="/home/$USER/or-tools_x86_64_Ubuntu-24.04_cpp_v9.10.4067"
```
* Compile this project with option `-DSETCOVERINGSOLVER_USE_ORTOOLS=ON`:
```shell
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DSETCOVERINGSOLVER_USE_ORTOOLS=ON
cmake --build build --config Release --parallel
cmake --install build --config Release --prefix install
```
* Update the `LD_LIBRARY_PATH` environment variable:
```shell
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$ORTOOLSDIR/lib"
```

Download data:
```shell
python3 scripts/download_data.py
Expand Down
18 changes: 18 additions & 0 deletions include/setcoveringsolver/algorithms/cp_sat_ortools.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include "setcoveringsolver/algorithm.hpp"

namespace setcoveringsolver
{

struct CpSatOrtoolsParameters: Parameters
{
/** Initial solution. */
const Solution* initial_solution = NULL;
};

const Output cp_sat_ortools(
const Instance& instance,
const CpSatOrtoolsParameters& parameters = {});

}
5 changes: 5 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ target_link_libraries(SetCoveringSolver_set_covering PUBLIC
OptimizationTools::graph
Threads::Threads)
add_library(SetCoveringSolver::set_covering ALIAS SetCoveringSolver_set_covering)
install(TARGETS SetCoveringSolver_set_covering)

add_subdirectory(algorithms)

Expand All @@ -31,6 +32,10 @@ if(SETCOVERINGSOLVER_BUILD_MAIN)
SetCoveringSolver_trivial_bound
SetCoveringSolver_clique_cover_bound
Boost::program_options)
if(SETCOVERINGSOLVER_USE_ORTOOLS)
target_link_libraries(SetCoveringSolver_main PUBLIC
SetCoveringSolver_cp_sat_ortools)
endif()
set_target_properties(SetCoveringSolver_main PROPERTIES OUTPUT_NAME "setcoveringsolver")
install(TARGETS SetCoveringSolver_main)
endif()
16 changes: 16 additions & 0 deletions src/algorithms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,22 @@ target_link_libraries(SetCoveringSolver_milp PUBLIC
MathOptSolversCMake::milp)
add_library(SetCoveringSolver::milp ALIAS SetCoveringSolver_milp)

if(SETCOVERINGSOLVER_USE_ORTOOLS)
list(APPEND CMAKE_PREFIX_PATH "$ENV{ORTOOLSDIR}")
find_package(ortools CONFIG REQUIRED)
add_library(SetCoveringSolver_cp_sat_ortools)
target_sources(SetCoveringSolver_cp_sat_ortools PRIVATE
cp_sat_ortools.cpp)
target_include_directories(SetCoveringSolver_cp_sat_ortools PUBLIC
${PROJECT_SOURCE_DIR}/include)
target_compile_definitions(SetCoveringSolver_cp_sat_ortools PUBLIC
ORTOOLS_FOUND=1)
target_link_libraries(SetCoveringSolver_cp_sat_ortools PUBLIC
SetCoveringSolver_set_covering
ortools::ortools)
add_library(SetCoveringSolver::cp_sat_ortools ALIAS SetCoveringSolver_cp_sat_ortools)
endif()

add_library(SetCoveringSolver_local_search_row_weighting)
target_sources(SetCoveringSolver_local_search_row_weighting PRIVATE
local_search_row_weighting.cpp)
Expand Down
74 changes: 74 additions & 0 deletions src/algorithms/cp_sat_ortools.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include "setcoveringsolver/algorithms/cp_sat_ortools.hpp"

#include "setcoveringsolver/algorithm_formatter.hpp"

#include "ortools/sat/cp_model.h"

using namespace setcoveringsolver;

const Output setcoveringsolver::cp_sat_ortools(
const Instance& instance,
const CpSatOrtoolsParameters& parameters)
{
Output output(instance);
AlgorithmFormatter algorithm_formatter(parameters, output);
algorithm_formatter.start("CP-SAT (OR-Tools)");

// Reduction.
if (parameters.reduction_parameters.reduce)
return solve_reduced_instance(cp_sat_ortools, instance, parameters, algorithm_formatter, output);

algorithm_formatter.print_header();

operations_research::sat::CpModelBuilder cp;

// Variables.
std::vector<operations_research::sat::BoolVar> x;
x.reserve(instance.number_of_sets());
for (SetId set_id = 0; set_id < instance.number_of_sets(); ++set_id)
x.push_back(cp.NewBoolVar());

// Objective: minimize total weight
operations_research::sat::LinearExpr objective;
for (SetId set_id = 0; set_id < instance.number_of_sets(); ++set_id) {
const Set& set = instance.set(set_id);
objective += set.cost * x[set_id];
}
cp.Minimize(objective);

// Constraints: each element must be covered.
for (ElementId element_id = 0;
element_id < instance.number_of_elements();
++element_id) {
const Element& element = instance.element(element_id);
operations_research::sat::LinearExpr expr;
for (SetId set_id: element.sets)
expr += x[set_id];
cp.AddGreaterOrEqual(expr, 1);
}

operations_research::sat::SatParameters cp_parameters;

// Write solver output to file.
// TODO
//cp_parameters.set_log_search_progress(true);

// Set time limit.
cp_parameters.set_max_time_in_seconds(parameters.timer.remaining_time());

// Solve
operations_research::sat::CpSolverResponse resp = operations_research::sat::SolveWithParameters(cp.Build(), cp_parameters);
if (resp.status() == operations_research::sat::CpSolverStatus::OPTIMAL
|| resp.status() == operations_research::sat::CpSolverStatus::FEASIBLE) {
Solution solution(instance);
for (SetId set_id = 0; set_id < instance.number_of_sets(); ++set_id)
if (SolutionIntegerValue(resp, x[set_id]) > 0)
solution.add(set_id);
algorithm_formatter.update_solution(solution, "");
if (resp.status() == operations_research::sat::CpSolverStatus::OPTIMAL)
algorithm_formatter.update_bound(solution.cost(), "");
}

algorithm_formatter.end();
return output;
}
9 changes: 9 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
#include "setcoveringsolver/solution.hpp"
#include "setcoveringsolver/algorithms/greedy.hpp"
#include "setcoveringsolver/algorithms/milp.hpp"
#if ORTOOLS_FOUND
#include "setcoveringsolver/algorithms/cp_sat_ortools.hpp"
#endif
#include "setcoveringsolver/algorithms/local_search_row_weighting.hpp"
#include "setcoveringsolver/algorithms/large_neighborhood_search.hpp"
#include "setcoveringsolver/algorithms/trivial_bound.hpp"
Expand Down Expand Up @@ -129,6 +132,12 @@ Output run(
XPRSfree();
#endif
return output;
#if ORTOOLS_FOUND
} else if (algorithm == "cp-sat-ortools") {
CpSatOrtoolsParameters parameters;
read_args(parameters, vm);
return cp_sat_ortools(instance, parameters);
#endif
} else if (algorithm == "local-search-row-weighting") {
LocalSearchRowWeightingParameters parameters;
read_args(parameters, vm);
Expand Down
Loading