backport main/

This commit is contained in:
Corentin Le Molgat
2024-10-14 15:28:45 +02:00
parent 960d970dd3
commit 8a996d7e68
36 changed files with 1026 additions and 738 deletions

View File

@@ -15,6 +15,9 @@
cmake_minimum_required(VERSION 3.20)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# Enable output of compile commands during generation.
option(CMAKE_EXPORT_COMPILE_COMMANDS "Export compile command" ON)
include(utils)
set_version(VERSION)

View File

@@ -75,7 +75,7 @@ git_repository(
git_repository(
name = "rules_python",
tag = "0.34.0",
tag = "0.36.0",
remote = "https://github.com/bazelbuild/rules_python.git",
)
@@ -105,6 +105,43 @@ git_repository(
repo_mapping = {"@abseil-cpp": "@com_google_absl"},
)
## Python
load("@rules_python//python:repositories.bzl", "py_repositories")
py_repositories()
load("@rules_python//python:repositories.bzl", "python_register_toolchains")
DEFAULT_PYTHON = "3.11"
python_register_toolchains(
name = "python3_11",
python_version = DEFAULT_PYTHON,
ignore_root_user_error=True,
)
load("@python3_11//:defs.bzl", "interpreter")
# Create a central external repo, @pip_deps, that contains Bazel targets for all the
# third-party packages specified in the bazel/requirements.txt file.
load("@rules_python//python:pip.bzl", "pip_parse")
pip_parse(
name = "pip_deps",
python_interpreter_target = interpreter,
requirements_lock = "//bazel:ortools_requirements.txt",
)
load("@pip_deps//:requirements.bzl",
install_pip_deps="install_deps")
install_pip_deps()
# Add a second repo @ortools_notebook_deps for jupyter notebooks.
pip_parse(
name = "ortools_notebook_deps",
python_interpreter_target = interpreter,
requirements_lock = "//bazel:notebook_requirements.txt",
)
load("@ortools_notebook_deps//:requirements.bzl",
install_notebook_deps="install_deps")
install_notebook_deps()
## Protobuf
# proto_library, cc_proto_library, and java_proto_library rules implicitly
# depend on @com_google_protobuf for protoc and proto runtimes.
@@ -205,40 +242,6 @@ new_git_repository(
remote = "https://github.com/swig/swig.git",
)
## Python
load("@rules_python//python:repositories.bzl", "py_repositories")
py_repositories()
load("@rules_python//python:repositories.bzl", "python_register_toolchains")
DEFAULT_PYTHON = "3.12"
python_register_toolchains(
name = "python3_12",
python_version = DEFAULT_PYTHON,
ignore_root_user_error=True,
)
# Create a central external repo, @pip_deps, that contains Bazel targets for all the
# third-party packages specified in the bazel/requirements.txt file.
load("@rules_python//python:pip.bzl", "pip_parse")
pip_parse(
name = "pip_deps",
requirements_lock = "//bazel:ortools_requirements.txt",
)
load("@pip_deps//:requirements.bzl",
install_pip_deps="install_deps")
install_pip_deps()
# Add a second repo @ortools_notebook_deps for jupyter notebooks.
pip_parse(
name = "ortools_notebook_deps",
requirements_lock = "//bazel:notebook_requirements.txt",
)
load("@ortools_notebook_deps//:requirements.bzl",
install_notebook_deps="install_deps")
install_notebook_deps()
# Protobuf
load("@com_google_protobuf//bazel:system_python.bzl", "system_python")
system_python(
@@ -283,7 +286,7 @@ new_git_repository(
new_git_repository(
name = "pybind11_protobuf",
commit = "84653a591aea5df482dc2bde42c19efafbd53a57", # 2024/06/28
commit = "ed430af1814a97e4017f2f808d3ba28cc10802f1", # 2024/10/02
remote = "https://github.com/pybind/pybind11_protobuf.git",
)

View File

@@ -632,7 +632,7 @@ TOOLCHAIN_STAGES := env devel toolchain build test
define toolchain-stage-target =
#$$(info STAGE: $1)
#$$(info Create targets: toolchain_$1 $(addprefix toolchain_, $(addsuffix _$1, $(TOOLCHAIN_TARGETS))).)
targets_toolchain_$1 = $(addprefix toolchain_, $(addsuffix _$1, $(TOOLCHAIN_TARGETS)))
targets_toolchain_$1 := $(addprefix toolchain_, $(addsuffix _$1, $(TOOLCHAIN_TARGETS)))
.PHONY: toolchain_$1 $$(targets_toolchain_$1)
toolchain_$1: $$(targets_toolchain_$1)
$$(targets_toolchain_$1): toolchain_%_$1: docker/toolchain/Dockerfile
@@ -645,7 +645,7 @@ $$(targets_toolchain_$1): toolchain_%_$1: docker/toolchain/Dockerfile
..
#$$(info Create targets: save_toolchain_$1 $(addprefix save_toolchain_, $(addsuffix _$1, $(TOOLCHAIN_TARGETS))) (debug).)
save_targets_toolchain_$1 = $(addprefix save_toolchain_, $(addsuffix _$1, $(TOOLCHAIN_TARGETS)))
save_targets_toolchain_$1 := $(addprefix save_toolchain_, $(addsuffix _$1, $(TOOLCHAIN_TARGETS)))
.PHONY: save_toolchain_$1 $$(save_targets_toolchain_$1)
save_toolchain_$1: $$(save_targets_toolchain_$1)
$$(save_targets_toolchain_$1): save_toolchain_%_$1: cache/%/docker_$1.tar
@@ -727,7 +727,7 @@ VAGRANT_VMS := \
define make-vagrant-target =
#$$(info VMS: $1)
#$$(info Create target: $1_<LANG>.)
$1_targets = $(addprefix $1_, $(LANGUAGES))
$1_targets := $(addprefix $1_, $(LANGUAGES))
.PHONY: $1 $$($1_targets)
$1: $$($1_targets)
$$($1_targets): $1_%: vagrant/$1/%/Vagrantfile
@@ -736,14 +736,14 @@ $$($1_targets): $1_%: vagrant/$1/%/Vagrantfile
cd vagrant/$1/$$* && vagrant up
#$$(info Create targets: sh_$1_<lang> vagrant machine (debug).)
sh_$1_targets = $(addprefix sh_$1_, $(LANGUAGES))
sh_$1_targets := $(addprefix sh_$1_, $(LANGUAGES))
.PHONY: $$(sh_$1_targets)
$$(sh_$1_targets): sh_$1_%:
cd vagrant/$1/$$* && vagrant up
cd vagrant/$1/$$* && vagrant ssh
#$$(info Create targets: clean_$1)
clean_$1_targets = $(addprefix clean_$1_, $(LANGUAGES))
clean_$1_targets := $(addprefix clean_$1_, $(LANGUAGES))
.PHONY: clean_$1 $(clean_$1_targets)
clean_$1: $$(clean_$1_targets)
$$(clean_$1_targets): clean_$1_%:

View File

@@ -79,12 +79,36 @@ if(USE_COINOR)
set(COINOR_DEPS Coin::CbcSolver Coin::OsiCbc Coin::ClpSolver Coin::OsiClp)
endif()
if(USE_CPLEX)
if(NOT TARGET CPLEX::CPLEX)
message(FATAL_ERROR "Target CPLEX::CPLEX not available.")
endif()
set(CPLEX_DEPS CPLEX::CPLEX)
endif()
if(USE_GLPK)
if(NOT TARGET GLPK::GLPK)
message(FATAL_ERROR "Target GLPK::GLPK not available.")
endif()
set(GLPK_DEPS GLPK::GLPK)
endif()
if(USE_HIGHS)
if(NOT TARGET highs::highs)
message(FATAL_ERROR "Target highs::highs not available.")
endif()
set(HIGHS_DEPS highs::highs)
endif()
if(USE_PDLP AND BUILD_PDLP)
set(PDLP_DEPS Eigen3::Eigen)
endif()
if(USE_SCIP AND NOT TARGET libscip)
message(FATAL_ERROR "Target libscip not available.")
if(USE_SCIP)
if(NOT TARGET libscip)
message(FATAL_ERROR "Target libscip not available.")
endif()
set(SCIP_DEPS libscip)
endif()
# Check optional Dependencies

View File

@@ -147,70 +147,153 @@ endif()
# ortools_cxx_test()
# CMake function to generate and build C++ test.
# Parameters:
# FILE_NAME: the C++ filename
# COMPONENT_NAME: name of the ortools/ subdir where the test is located
# note: automatically determined if located in ortools/<component>/
# NAME: CMake target name
# SOURCES: List of source files
# [COMPILE_DEFINITIONS]: List of private compile definitions
# [COMPILE_OPTIONS]: List of private compile options
# [LINK_LIBRARIES]: List of private libraries to use when linking
# note: ortools::ortools is always linked to the target
# [LINK_OPTIONS]: List of private link options
# e.g.:
# ortools_cxx_test(
# FILE_NAME
# ${PROJECT_SOURCE_DIR}/ortools/foo/foo_test.cc
# COMPONENT_NAME
# foo
# DEPS
# NAME
# foo_bar_test
# SOURCES
# bar_test.cc
# ${PROJECT_SOURCE_DIR}/ortools/foo/bar_test.cc
# LINK_LIBRARIES
# GTest::gmock
# GTest::gtest_main
# )
function(ortools_cxx_test)
set(options "")
set(oneValueArgs "FILE_NAME;COMPONENT_NAME")
set(multiValueArgs "DEPS")
set(oneValueArgs "NAME")
set(multiValueArgs
"SOURCES;COMPILE_DEFINITIONS;COMPILE_OPTIONS;LINK_LIBRARIES;LINK_OPTIONS")
cmake_parse_arguments(TEST
"${options}"
"${oneValueArgs}"
"${multiValueArgs}"
${ARGN}
)
if(NOT TEST_FILE_NAME)
message(FATAL_ERROR "no FILE_NAME provided")
if(NOT TEST_NAME)
message(FATAL_ERROR "no NAME provided")
endif()
get_filename_component(TEST_NAME ${TEST_FILE_NAME} NAME_WE)
message(STATUS "Configuring test ${TEST_FILE_NAME} ...")
if(NOT TEST_COMPONENT_NAME)
# test is located in ortools/<component_name>/
get_filename_component(COMPONENT_DIR ${TEST_FILE_NAME} DIRECTORY)
get_filename_component(COMPONENT_NAME ${COMPONENT_DIR} NAME)
else()
set(COMPONENT_NAME ${TEST_COMPONENT_NAME})
if(NOT TEST_SOURCES)
message(FATAL_ERROR "no SOURCES provided")
endif()
message(STATUS "Configuring test ${TEST_NAME} ...")
add_executable(${TEST_NAME} ${TEST_FILE_NAME})
add_executable(${TEST_NAME} "")
target_sources(${TEST_NAME} PRIVATE ${TEST_SOURCES})
target_include_directories(${TEST_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(${TEST_NAME} PRIVATE ${TEST_COMPILE_DEFINITIONS})
target_compile_features(${TEST_NAME} PRIVATE cxx_std_17)
target_compile_options(${TEST_NAME} PRIVATE ${TEST_COMPILE_OPTIONS})
target_link_libraries(${TEST_NAME} PRIVATE
${PROJECT_NAMESPACE}::ortools
${TEST_DEPS}
${TEST_LINK_LIBRARIES}
)
target_link_options(${TEST_NAME} PRIVATE ${TEST_LINK_OPTIONS})
include(GNUInstallDirs)
if(APPLE)
set_target_properties(${TEST_NAME} PROPERTIES INSTALL_RPATH
"@loader_path/../${CMAKE_INSTALL_LIBDIR};@loader_path")
set_target_properties(${TEST_NAME} PROPERTIES
INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR};@loader_path")
elseif(UNIX)
cmake_path(RELATIVE_PATH CMAKE_INSTALL_FULL_LIBDIR
BASE_DIRECTORY ${CMAKE_INSTALL_FULL_BINDIR}
OUTPUT_VARIABLE libdir_relative_path)
set_target_properties(${TEST_NAME} PROPERTIES
INSTALL_RPATH "$ORIGIN/${libdir_relative_path}")
INSTALL_RPATH "$ORIGIN/${libdir_relative_path}:$ORIGIN")
endif()
if(BUILD_TESTING)
add_test(
NAME cxx_${COMPONENT_NAME}_${TEST_NAME}
COMMAND ${TEST_NAME})
NAME cxx_${TEST_NAME}
COMMAND ${TEST_NAME}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
)
endif()
message(STATUS "Configuring test ${TEST_FILE_NAME} ...DONE")
message(STATUS "Configuring test ${TEST_NAME} ...DONE")
endfunction()
###################
## C++ Library ##
###################
# ortools_cxx_library()
# CMake function to generate and build C++ library.
# Parameters:
# NAME: CMake target name
# SOURCES: List of source files
# [TYPE]: SHARED or STATIC
# [COMPILE_DEFINITIONS]: List of private compile definitions
# [COMPILE_OPTIONS]: List of private compile options
# [LINK_LIBRARIES]: List of **public** libraries to use when linking
# note: ortools::ortools is always linked to the target
# [LINK_OPTIONS]: List of private link options
# e.g.:
# ortools_cxx_library(
# NAME
# foo_bar_library
# SOURCES
# bar_library.cc
# ${PROJECT_SOURCE_DIR}/ortools/foo/bar_library.cc
# TYPE
# SHARED
# LINK_LIBRARIES
# GTest::gmock
# GTest::gtest_main
# TESTING
# )
function(ortools_cxx_library)
set(options "TESTING")
set(oneValueArgs "NAME;TYPE")
set(multiValueArgs
"SOURCES;COMPILE_DEFINITIONS;COMPILE_OPTIONS;LINK_LIBRARIES;LINK_OPTIONS")
cmake_parse_arguments(LIBRARY
"${options}"
"${oneValueArgs}"
"${multiValueArgs}"
${ARGN}
)
if(LIBRARY_TESTING AND NOT BUILD_TESTING)
return()
endif()
if(NOT LIBRARY_NAME)
message(FATAL_ERROR "no NAME provided")
endif()
if(NOT LIBRARY_SOURCES)
message(FATAL_ERROR "no SOURCES provided")
endif()
message(STATUS "Configuring library ${LIBRARY_NAME} ...")
add_library(${LIBRARY_NAME} ${LIBRARY_TYPE} "")
target_sources(${LIBRARY_NAME} PRIVATE ${LIBRARY_SOURCES})
target_include_directories(${LIBRARY_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(${LIBRARY_NAME} PRIVATE ${LIBRARY_COMPILE_DEFINITIONS})
target_compile_features(${LIBRARY_NAME} PRIVATE cxx_std_17)
target_compile_options(${LIBRARY_NAME} PRIVATE ${LIBRARY_COMPILE_OPTIONS})
target_link_libraries(${LIBRARY_NAME} PUBLIC
${PROJECT_NAMESPACE}::ortools
${LIBRARY_LINK_LIBRARIES}
)
target_link_options(${LIBRARY_NAME} PRIVATE ${LIBRARY_LINK_OPTIONS})
include(GNUInstallDirs)
if(APPLE)
set_target_properties(${LIBRARY_NAME} PROPERTIES
INSTALL_RPATH "@loader_path/../${CMAKE_INSTALL_LIBDIR};@loader_path")
elseif(UNIX)
cmake_path(RELATIVE_PATH CMAKE_INSTALL_FULL_LIBDIR
BASE_DIRECTORY ${CMAKE_INSTALL_FULL_BINDIR}
OUTPUT_VARIABLE libdir_relative_path)
set_target_properties(${LIBRARY_NAME} PROPERTIES
INSTALL_RPATH "$ORIGIN/${libdir_relative_path}:$ORIGIN")
endif()
add_library(${PROJECT_NAMESPACE}::${LIBRARY_NAME} ALIAS ${LIBRARY_NAME})
message(STATUS "Configuring library ${LIBRARY_NAME} ...DONE")
endfunction()
##################
@@ -460,11 +543,11 @@ target_link_libraries(${PROJECT_NAME} PUBLIC
protobuf::libprotobuf
${RE2_DEPS}
${COINOR_DEPS}
$<$<BOOL:${USE_CPLEX}>:CPLEX::CPLEX>
$<$<BOOL:${USE_GLPK}>:GLPK::GLPK>
$<$<BOOL:${USE_HIGHS}>:highs::highs>
${CPLEX_DEPS}
${GLPK_DEPS}
${HIGHS_DEPS}
${PDLP_DEPS}
$<$<BOOL:${USE_SCIP}>:libscip>
${SCIP_DEPS}
Threads::Threads)
if(WIN32)
target_link_libraries(${PROJECT_NAME} PUBLIC psapi.lib ws2_32.lib)

View File

@@ -129,7 +129,7 @@ if(BUILD_re2)
GIT_REPOSITORY "https://github.com/google/re2.git"
GIT_TAG "2024-04-01"
GIT_SHALLOW TRUE
#PATCH_COMMAND git apply --ignore-whitespace "${CMAKE_CURRENT_LIST_DIR}/../../patches/re2-2024-04-01.patch"
PATCH_COMMAND git apply --ignore-whitespace "${CMAKE_CURRENT_LIST_DIR}/../../patches/re2-2024-04-01.patch"
)
FetchContent_MakeAvailable(re2)
list(POP_BACK CMAKE_MESSAGE_INDENT)
@@ -300,7 +300,8 @@ if(BUILD_CoinUtils)
FetchContent_Declare(
CoinUtils
GIT_REPOSITORY "https://github.com/Mizux/CoinUtils.git"
GIT_TAG "cmake/2.11.6"
GIT_TAG "stable/2.11"
#GIT_TAG "cmake/2.11.6"
GIT_SHALLOW TRUE
PATCH_COMMAND git apply --ignore-whitespace
"${CMAKE_CURRENT_LIST_DIR}/../../patches/coinutils-2.11.patch")
@@ -318,7 +319,8 @@ if(BUILD_Osi)
FetchContent_Declare(
Osi
GIT_REPOSITORY "https://github.com/Mizux/Osi.git"
GIT_TAG "cmake/0.108.7"
GIT_TAG "stable/0.108"
#GIT_TAG "cmake/0.108.7"
GIT_SHALLOW TRUE
PATCH_COMMAND git apply --ignore-whitespace
"${CMAKE_CURRENT_LIST_DIR}/../../patches/osi-0.108.patch")
@@ -336,10 +338,11 @@ if(BUILD_Clp)
FetchContent_Declare(
Clp
GIT_REPOSITORY "https://github.com/Mizux/Clp.git"
GIT_TAG "cmake/1.17.7"
GIT_TAG "stable/1.17"
#GIT_TAG "cmake/1.17.7"
GIT_SHALLOW TRUE
PATCH_COMMAND git apply --ignore-whitespace
"${CMAKE_CURRENT_LIST_DIR}/../../patches/clp-1.17.4.patch")
"${CMAKE_CURRENT_LIST_DIR}/../../patches/clp-1.17.patch")
FetchContent_MakeAvailable(Clp)
list(POP_BACK CMAKE_MESSAGE_INDENT)
message(CHECK_PASS "fetched")
@@ -354,7 +357,8 @@ if(BUILD_Cgl)
FetchContent_Declare(
Cgl
GIT_REPOSITORY "https://github.com/Mizux/Cgl.git"
GIT_TAG "cmake/0.60.5"
GIT_TAG "stable/0.60"
#GIT_TAG "cmake/0.60.5"
GIT_SHALLOW TRUE
PATCH_COMMAND git apply --ignore-whitespace
"${CMAKE_CURRENT_LIST_DIR}/../../patches/cgl-0.60.patch")
@@ -372,7 +376,8 @@ if(BUILD_Cbc)
FetchContent_Declare(
Cbc
GIT_REPOSITORY "https://github.com/Mizux/Cbc.git"
GIT_TAG "cmake/2.10.7"
GIT_TAG "stable/2.10"
#GIT_TAG "cmake/2.10.7"
GIT_SHALLOW TRUE
PATCH_COMMAND git apply --ignore-whitespace
"${CMAKE_CURRENT_LIST_DIR}/../../patches/cbc-2.10.patch")
@@ -398,6 +403,8 @@ if(BUILD_googletest)
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG v1.15.2
GIT_SHALLOW TRUE
PATCH_COMMAND git apply --ignore-whitespace
"${CMAKE_CURRENT_LIST_DIR}/../../patches/googletest-v1.15.2.patch"
#PATCH_COMMAND git apply --ignore-whitespace ""
)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)

View File

@@ -463,9 +463,11 @@ add_custom_command(
$<TARGET_FILE:pywraplp> ${PYTHON_PROJECT}/linear_solver
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:model_builder_helper_pybind11> ${PYTHON_PROJECT}/linear_solver/python
COMMAND ${CMAKE_COMMAND} -E copy
COMMAND ${CMAKE_COMMAND} -E
$<IF:$<BOOL:${BUILD_MATH_OPT}>,copy,true>
$<TARGET_FILE:math_opt_pybind11> ${PYTHON_PROJECT}/math_opt/core/python
COMMAND ${CMAKE_COMMAND} -E copy
COMMAND ${CMAKE_COMMAND} -E
$<IF:$<BOOL:${BUILD_MATH_OPT}>,copy,true>
$<TARGET_FILE:status_py_extension_stub> ${PYTHON_PROJECT}/../pybind11_abseil
COMMAND ${CMAKE_COMMAND} -E
$<IF:$<TARGET_EXISTS:pdlp_pybind11>,copy,true>

View File

@@ -17,8 +17,15 @@ endif()
if(BUILD_CXX_EXAMPLES)
file(GLOB CXX_SRCS "*.cc")
foreach(FILE_NAME IN LISTS CXX_SRCS)
ortools_cxx_test(FILE_NAME ${FILE_NAME})
foreach(_FULL_FILE_NAME IN LISTS CXX_SRCS)
get_filename_component(_NAME ${_FULL_FILE_NAME} NAME_WE)
get_filename_component(_FILE_NAME ${_FULL_FILE_NAME} NAME)
ortools_cxx_test(
NAME
tests_${_NAME}
SOURCES
${_FULL_FILE_NAME}
)
endforeach()
endif()

View File

@@ -385,6 +385,15 @@ cc_library(
],
)
cc_test(
name = "dense_doubly_linked_list_test",
srcs = ["dense_doubly_linked_list_test.cc"],
deps = [
":dense_doubly_linked_list",
"//ortools/base:gmock_main",
],
)
cc_library(
name = "dynamic_partition",
srcs = ["dynamic_partition.cc"],

View File

@@ -12,7 +12,7 @@
# limitations under the License.
file(GLOB _SRCS "*.h" "*.cc")
list(FILTER _SRCS EXCLUDE REGEX "/[^/]*_test\\.cc$")
list(FILTER _SRCS EXCLUDE REGEX ".*/.*_test.cc")
set(NAME ${PROJECT_NAME}_algorithms)
@@ -31,3 +31,23 @@ target_link_libraries(${NAME} PRIVATE
protobuf::libprotobuf
${PROJECT_NAMESPACE}::ortools_proto)
#add_library(${PROJECT_NAMESPACE}::algorithms ALIAS ${NAME})
if(BUILD_TESTING)
file(GLOB _TEST_SRCS "*_test.cc")
list(FILTER _TEST_SRCS EXCLUDE REGEX ".*_stress_test.cc")
list(FILTER _TEST_SRCS EXCLUDE REGEX "set_cover_test.cc")
foreach(_FULL_FILE_NAME IN LISTS _TEST_SRCS)
get_filename_component(_NAME ${_FULL_FILE_NAME} NAME_WE)
get_filename_component(_FILE_NAME ${_FULL_FILE_NAME} NAME)
ortools_cxx_test(
NAME
algorithms_${_NAME}
SOURCES
${_FILE_NAME}
LINK_LIBRARIES
benchmark::benchmark
GTest::gmock
GTest::gtest_main
)
endforeach()
endif()

View File

@@ -1,184 +0,0 @@
// Copyright 2010-2024 Google LLC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "ortools/algorithms/duplicate_remover.h"
#include <random>
#include <vector>
#include "benchmark/benchmark.h"
#include "gtest/gtest.h"
#include "ortools/base/gmock.h"
#include "ortools/base/linked_hash_set.h"
#include "ortools/util/random_engine.h"
#include "util/tuple/dump_vars.h"
namespace operations_research {
namespace {
using ::testing::ElementsAre;
using ::testing::ElementsAreArray;
using ::testing::IsEmpty;
TEST(DenseIntDuplicateRemoverTest, RemoveDuplicatesEmpty) {
std::vector<int> v;
DenseIntDuplicateRemover deduper(10);
deduper.RemoveDuplicates(&v);
EXPECT_THAT(v, IsEmpty());
}
TEST(DenseIntDuplicateRemoverTest, RemoveDuplicatesNZeroAndEmpty) {
std::vector<int> v;
DenseIntDuplicateRemover deduper(0);
deduper.RemoveDuplicates(&v);
EXPECT_THAT(v, IsEmpty());
}
TEST(DenseIntDuplicateRemoverTest, RemoveDuplicatesSimpleCaseWithDuplicates) {
std::vector<int> v = {1, 8, 2, 2, 8, 4, 1, 2, 7, 0, 2};
DenseIntDuplicateRemover deduper(9);
deduper.RemoveDuplicates(&v);
EXPECT_THAT(v, ElementsAre(1, 8, 2, 4, 7, 0));
}
TEST(DenseIntDuplicateRemoverTest, RemoveDuplicatesSimpleCaseWithNoDuplicates) {
std::vector<int> v = {3, 2, 0, 5, 4, 1};
const std::vector<int> v_copy = v;
DenseIntDuplicateRemover deduper(6);
deduper.RemoveDuplicates(&v);
EXPECT_THAT(v, ElementsAreArray(v_copy));
}
TEST(DenseIntDuplicateRemoverTest, RemoveDuplicatesWithRepeatedField) {
const std::vector<int> v = {1, 0, 1, 2, 1};
google::protobuf::RepeatedField<int> r(v.begin(), v.end());
DenseIntDuplicateRemover deduper(3);
deduper.RemoveDuplicates(&r);
EXPECT_THAT(r, ElementsAre(1, 0, 2));
}
std::vector<int> UniqueValues(absl::Span<const int> span) {
absl::flat_hash_set<int> set;
std::vector<int> out;
for (int x : span)
if (set.insert(x).second) out.push_back(x);
return out;
}
TEST(DenseIntDuplicateRemoverTest, RemoveDuplicatesRandomizedStressTest) {
constexpr int kNumValues = 1003;
DenseIntDuplicateRemover deduper(kNumValues);
constexpr int kNumTests = 1'000'000;
absl::BitGen random;
for (int t = 0; t < kNumTests; ++t) {
const int size = absl::LogUniform(random, 0, 16);
const int domain_size =
absl::Uniform(absl::IntervalClosed, random, 1, kNumValues);
std::vector<int> v(size);
for (int& x : v) x = absl::Uniform(random, 0, domain_size);
const std::vector<int> v_initial = v;
const std::vector<int> unique_values = UniqueValues(v);
deduper.RemoveDuplicates(&v);
ASSERT_THAT(v, ElementsAreArray(unique_values)) << DUMP_VARS(t, v_initial);
}
}
TEST(DenseIntDuplicateRemoverTest,
AppendAndLazilyRemoveDuplicatesRandomizedStressTest) {
constexpr int kNumValues = 103;
constexpr int kNumTests = 1'000;
std::mt19937 random;
gtl::linked_hash_set<int> reference;
std::vector<int> v;
int64_t num_extra_elements = 0;
int64_t num_unique_elements = 0;
for (int t = 0; t < kNumTests; ++t) {
const int num_inserts = absl::LogUniform(random, 2, 1 << 16);
const int domain_size =
absl::Uniform(absl::IntervalClosed, random, 1, kNumValues);
v.clear();
reference.clear();
DenseIntDuplicateRemover deduper(domain_size);
for (int i = 0; i < num_inserts; ++i) {
const int x = absl::Uniform(random, 0, domain_size);
deduper.AppendAndLazilyRemoveDuplicates(x, &v);
reference.insert(x);
}
ASSERT_LE(v.size(), domain_size * 2 + 15);
const int old_size = v.size();
deduper.RemoveDuplicates(&v);
num_unique_elements += v.size();
num_extra_elements += old_size - v.size();
ASSERT_THAT(v, ElementsAreArray(reference))
<< DUMP_VARS(t, num_inserts, domain_size, old_size, v.size());
}
EXPECT_LE(static_cast<double>(num_extra_elements) / num_unique_elements, 0.5);
}
template <bool use_flat_hash_set>
void BM_AppendAndLazilyRemoveDuplicates(benchmark::State& state) {
const int num_inserts = state.range(0);
const int domain_size = state.range(1);
std::vector<int> to_insert(num_inserts);
random_engine_t random;
for (int& x : to_insert) x = absl::Uniform(random, 0, domain_size);
DenseIntDuplicateRemover deduper(domain_size);
std::vector<int> v;
absl::flat_hash_set<int> set;
for (auto _ : state) {
v.clear();
set.clear();
for (int x : to_insert) {
if (use_flat_hash_set) {
set.insert(x);
} else {
deduper.AppendAndLazilyRemoveDuplicates(x, &v);
}
}
if (!use_flat_hash_set) deduper.RemoveDuplicates(&v);
benchmark::DoNotOptimize(v);
benchmark::DoNotOptimize(set);
}
state.SetItemsProcessed(state.iterations() * num_inserts);
}
BENCHMARK(BM_AppendAndLazilyRemoveDuplicates<true>)
->ArgPair(1, 10)
->ArgPair(10, 2)
->ArgPair(10, 10)
->ArgPair(100, 100)
->ArgPair(100, 10)
->ArgPair(10'000, 10'000)
->ArgPair(10'000, 1'000)
->ArgPair(10'000, 100)
->ArgPair(10'000, 10)
->ArgPair(1'000'000, 1'000'000)
->ArgPair(1'000'000, 10'000)
->ArgPair(1'000'000, 100);
BENCHMARK(BM_AppendAndLazilyRemoveDuplicates<false>)
->ArgPair(1, 10)
->ArgPair(10, 2)
->ArgPair(10, 10)
->ArgPair(100, 100)
->ArgPair(100, 10)
->ArgPair(10'000, 10'000)
->ArgPair(10'000, 1'000)
->ArgPair(10'000, 100)
->ArgPair(10'000, 10)
->ArgPair(1'000'000, 1'000'000)
->ArgPair(1'000'000, 10'000)
->ArgPair(1'000'000, 100);
} // namespace
} // namespace operations_research

View File

@@ -1,428 +0,0 @@
// Copyright 2010-2024 Google LLC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <algorithm>
#include <string>
#include <vector>
#include "absl/log/check.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/time/time.h"
#include "gtest/gtest.h"
#include "ortools/algorithms/set_cover_heuristics.h"
#include "ortools/algorithms/set_cover_invariant.h"
#include "ortools/algorithms/set_cover_lagrangian.h"
#include "ortools/algorithms/set_cover_mip.h"
#include "ortools/algorithms/set_cover_model.h"
#include "ortools/algorithms/set_cover_reader.h"
#include "ortools/base/logging.h"
#include "ortools/base/path.h"
#include "ortools/base/timer.h"
namespace operations_research {
void LogStats(std::string name, SetCoverModel* model) {
LOG(INFO) << ", " << name << ", num_elements, " << model->num_elements()
<< ", num_subsets, " << model->num_subsets();
LOG(INFO) << ", " << name << ", num_nonzeros, " << model->num_nonzeros()
<< ", fill rate, " << model->FillRate();
LOG(INFO) << ", " << name << ", cost, "
<< model->ComputeCostStats().DebugString();
LOG(INFO) << ", " << name << ", num_rows, " << model->num_elements()
<< ", rows sizes, " << model->ComputeRowStats().DebugString();
LOG(INFO) << ", " << name << ", row size deciles, "
<< absl::StrJoin(model->ComputeRowDeciles(), ", ");
LOG(INFO) << ", " << name << ", num_columns, " << model->num_subsets()
<< ", columns sizes, " << model->ComputeColumnStats().DebugString();
LOG(INFO) << ", " << name << ", column size deciles, "
<< absl::StrJoin(model->ComputeColumnDeciles(), ", ");
SetCoverInvariant inv(model);
Preprocessor preprocessor(&inv);
preprocessor.NextSolution();
LOG(INFO) << ", " << name << ", num_columns_fixed_by_singleton_row, "
<< preprocessor.num_columns_fixed_by_singleton_row();
}
void LogCostAndTiming(std::string name, std::string algo, double cost,
absl::Duration duration) {
LOG(INFO) << ", " << name << ", " << algo << "_cost, " << cost << ", "
<< absl::ToInt64Microseconds(duration) << "e-6, s";
}
SetCoverInvariant RunChvatalAndSteepest(std::string name,
SetCoverModel* model) {
SetCoverInvariant inv(model);
GreedySolutionGenerator greedy(&inv);
WallTimer timer;
timer.Start();
CHECK(greedy.NextSolution());
DCHECK(inv.CheckConsistency());
LogCostAndTiming(name, "GreedySolutionGenerator", inv.cost(),
timer.GetDuration());
SteepestSearch steepest(&inv);
steepest.NextSolution(100000);
LogCostAndTiming(name, "GreedySteepestSearch", inv.cost(),
timer.GetDuration());
DCHECK(inv.CheckConsistency());
return inv;
}
SetCoverInvariant RunChvatalAndGLS(std::string name, SetCoverModel* model) {
SetCoverInvariant inv(model);
GreedySolutionGenerator greedy(&inv);
WallTimer timer;
timer.Start();
CHECK(greedy.NextSolution());
DCHECK(inv.CheckConsistency());
LogCostAndTiming(name, "GreedySolutionGenerator", inv.cost(),
timer.GetDuration());
GuidedLocalSearch gls(&inv);
gls.NextSolution(100'000);
LogCostAndTiming(name, "GLS", inv.cost(), timer.GetDuration());
DCHECK(inv.CheckConsistency());
return inv;
}
SetCoverInvariant RunElementDegreeGreedyAndSteepest(std::string name,
SetCoverModel* model) {
SetCoverInvariant inv(model);
ElementDegreeSolutionGenerator element_degree(&inv);
WallTimer timer;
timer.Start();
CHECK(element_degree.NextSolution());
DCHECK(inv.CheckConsistency());
LogCostAndTiming(name, "ElementDegreeSolutionGenerator", inv.cost(),
timer.GetDuration());
SteepestSearch steepest(&inv);
steepest.NextSolution(100000);
LogCostAndTiming(name, "ElementDegreeSteepestSearch", inv.cost(),
timer.GetDuration());
DCHECK(inv.CheckConsistency());
return inv;
}
void IterateClearAndMip(std::string name, SetCoverInvariant* inv) {
WallTimer timer;
timer.Start();
std::vector<SubsetIndex> focus = inv->model()->all_subsets();
double best_cost = inv->cost();
SubsetBoolVector best_choices = inv->is_selected();
for (int i = 0; i < 10; ++i) {
std::vector<SubsetIndex> range =
ClearMostCoveredElements(std::min(100UL, focus.size()), inv);
SetCoverMip mip(inv);
mip.NextSolution(range, true, 0.02);
DCHECK(inv->CheckConsistency());
if (inv->cost() < best_cost) {
best_cost = inv->cost();
best_choices = inv->is_selected();
}
}
timer.Stop();
LogCostAndTiming(name, "IterateClearAndMip", best_cost, timer.GetDuration());
}
SetCoverInvariant ComputeLPLowerBound(std::string name, SetCoverModel* model) {
SetCoverInvariant inv(model);
WallTimer timer;
timer.Start();
SetCoverMip mip(&inv, SetCoverMipSolver::SCIP); // Use Gurobi for large pbs.
mip.NextSolution(false, .3); // Use 300s or more for large problems.
LogCostAndTiming(name, "LPLowerBound", mip.lower_bound(),
timer.GetDuration());
return inv;
}
void ComputeLagrangianLowerBound(std::string name, SetCoverInvariant* inv) {
const SetCoverModel* model = inv->model();
WallTimer timer;
timer.Start();
SetCoverLagrangian lagrangian(inv, /*num_threads=*/8);
const auto [lower_bound, reduced_costs, multipliers] =
lagrangian.ComputeLowerBound(model->subset_costs(), inv->cost());
LogCostAndTiming(name, "LagrangianLowerBound", lower_bound,
timer.GetDuration());
}
SetCoverInvariant RunMip(std::string name, SetCoverModel* model) {
SetCoverInvariant inv(model);
WallTimer timer;
timer.Start();
SetCoverMip mip(&inv, SetCoverMipSolver::SCIP); // Use Gurobi for large pbs.
mip.NextSolution(true, .5); // Use 300s or more for large problems.
timer.Stop();
LogCostAndTiming(name, "MIP", inv.cost(), timer.GetDuration());
return inv;
}
void IterateClearElementDegreeAndSteepest(std::string name,
SetCoverInvariant* inv) {
WallTimer timer;
timer.Start();
double best_cost = inv->cost();
SubsetBoolVector best_choices = inv->is_selected();
ElementDegreeSolutionGenerator element_degree(inv);
SteepestSearch steepest(inv);
for (int i = 0; i < 1000; ++i) {
std::vector<SubsetIndex> range =
ClearRandomSubsets(0.1 * inv->trace().size(), inv);
CHECK(element_degree.NextSolution());
steepest.NextSolution(range, 100000);
DCHECK(inv->CheckConsistency());
if (inv->cost() < best_cost) {
best_cost = inv->cost();
best_choices = inv->is_selected();
}
}
timer.Stop();
LogCostAndTiming(name, "IterateClearElementDegreeAndSteepest", best_cost,
timer.GetDuration());
}
double RunSolver(std::string name, SetCoverModel* model) {
LogStats(name, model);
WallTimer global_timer;
global_timer.Start();
RunChvatalAndSteepest(name, model);
// SetCoverInvariant inv = ComputeLPLowerBound(name, model);
// RunMip(name, model);
RunChvatalAndGLS(name, model);
SetCoverInvariant inv = RunElementDegreeGreedyAndSteepest(name, model);
ComputeLagrangianLowerBound(name, &inv);
// IterateClearAndMip(name, inv);
IterateClearElementDegreeAndSteepest(name, &inv);
return inv.cost();
}
// We break down the ORLIB set covering problems by their expected runtime with
// our solver (as of July 2023).
enum ProblemSize {
SUBMILLI, // < 1ms
FEWMILLIS, // < 3ms
SUBHUNDREDTH, // < 10ms
FEWHUNDREDTHS, // < 30ms
SUBTENTH, // < 100ms
FEWTENTHS, // < 300ms
SUBSECOND, // < 1s
FEWSECONDS, // < 3s
MANYSECONDS, // >= 3s
UNKNOWN = 999, // Not known (i.e. not benchmarked).
};
// These two macros provide indirection which allows the __LINE__ macro
// to be pasted, giving the tests useful names.
#define APPEND(x, y) x##y
#define APPEND_AND_EVAL(x, y) APPEND(x, y)
const char data_dir[] =
"operations_research_data/operations_research_data/"
"SET_COVERING";
// In the following, the lower bounds are taken from:
// [1] Caprara, Alberto, Matteo Fischetti, and Paolo Toth. 1999. “A Heuristic
// Method for the Set Covering Problem.” Operations Research 47 (5): 73043.
// https://www.jstor.org/stable/223097 , and
// [2] Yagiura, Mutsunori, Masahiro Kishida, and Toshihide Ibaraki. 2006.
// “A 3-Flip Neighborhood Local Search for the Set Covering Problem.” European
// Journal of Operational Research 172 (2): 47299.
// https://www.sciencedirect.com/science/article/pii/S0377221704008264
// This macro makes it possible to declare each test below with a one-liner.
// 'best_objective' denotes the best objective costs found in literature.
// These are the proven optimal values. This can be achieved with MIP.
// For the rail instances, they are the best solution found in the literature
// [1] and [2]. They are not achievable though local search or MIP or a
// combination of the two.
// 'expected_objective' are the costs currently reached by the solver.
// TODO(user): find and add values for the unit cost (aka unicost) case.
#define ORLIB_TEST(name, best_objective, expected_objective, size, function) \
TEST(OrlibTest, APPEND_AND_EVAL(TestOnLine, __LINE__)) { \
auto filespec = \
file::JoinPathRespectAbsolute(::testing::SrcDir(), data_dir, name); \
LOG(INFO) << "Reading " << name; \
operations_research::SetCoverModel model = function(filespec); \
double cost = RunSolver(name, &model); \
(void)cost; \
}
#define ORLIB_UNICOST_TEST(name, best_objective, expected_objective, size, \
function) \
TEST(OrlibUnicostTest, APPEND_AND_EVAL(TestOnLine, __LINE__)) { \
auto filespec = \
file::JoinPathRespectAbsolute(::testing::SrcDir(), data_dir, name); \
LOG(INFO) << "Reading " << name; \
operations_research::SetCoverModel model = function(filespec); \
for (SubsetIndex i : model.SubsetRange()) { \
model.SetSubsetCost(i, 1.0); \
} \
double cost = RunSolver(absl::StrCat(name, "_unicost"), &model); \
(void)cost; \
}
#define SCP_TEST(name, best_objective, expected_objective, size) \
ORLIB_TEST(name, best_objective, expected_objective, size, \
operations_research::ReadBeasleySetCoverProblem) \
ORLIB_UNICOST_TEST(name, best_objective, expected_objective, size, \
operations_research::ReadBeasleySetCoverProblem)
#define RAIL_TEST(name, best_objective, expected_objective, size) \
ORLIB_TEST(name, best_objective, expected_objective, size, \
operations_research::ReadRailSetCoverProblem) \
ORLIB_UNICOST_TEST(name, best_objective, expected_objective, size, \
operations_research::ReadRailSetCoverProblem)
#define BASIC_SCP
#define EXTRA_SCP
#define RAIL
#ifdef BASIC_SCP
SCP_TEST("scp41.txt", 429, 442, FEWMILLIS);
SCP_TEST("scp42.txt", 512, 555, FEWMILLIS);
SCP_TEST("scp43.txt", 516, 557, FEWMILLIS);
SCP_TEST("scp44.txt", 494, 516, FEWMILLIS);
SCP_TEST("scp45.txt", 512, 530, FEWMILLIS);
SCP_TEST("scp46.txt", 560, 594, FEWMILLIS);
SCP_TEST("scp47.txt", 430, 451, FEWMILLIS);
SCP_TEST("scp48.txt", 492, 502, FEWMILLIS);
SCP_TEST("scp49.txt", 641, 693, FEWMILLIS);
SCP_TEST("scp410.txt", 514, 525, FEWMILLIS);
SCP_TEST("scp51.txt", 253, 274, FEWMILLIS);
SCP_TEST("scp52.txt", 302, 329, FEWMILLIS);
SCP_TEST("scp53.txt", 226, 233, FEWMILLIS);
SCP_TEST("scp54.txt", 242, 255, FEWMILLIS);
SCP_TEST("scp55.txt", 211, 222, FEWMILLIS);
SCP_TEST("scp56.txt", 213, 234, FEWMILLIS);
SCP_TEST("scp57.txt", 293, 313, FEWMILLIS);
SCP_TEST("scp58.txt", 288, 309, FEWMILLIS);
SCP_TEST("scp59.txt", 279, 292, FEWMILLIS);
SCP_TEST("scp510.txt", 265, 276, FEWMILLIS);
SCP_TEST("scp61.txt", 138, 151, FEWMILLIS);
SCP_TEST("scp62.txt", 146, 173, FEWMILLIS);
SCP_TEST("scp63.txt", 145, 154, FEWMILLIS);
SCP_TEST("scp64.txt", 131, 137, FEWMILLIS);
SCP_TEST("scp65.txt", 161, 181, FEWMILLIS);
SCP_TEST("scpa1.txt", 253, 275, FEWHUNDREDTHS);
SCP_TEST("scpa2.txt", 252, 268, FEWHUNDREDTHS);
SCP_TEST("scpa3.txt", 232, 244, FEWHUNDREDTHS);
SCP_TEST("scpa4.txt", 234, 253, FEWHUNDREDTHS);
SCP_TEST("scpa5.txt", 236, 249, FEWHUNDREDTHS);
SCP_TEST("scpb1.txt", 69, 74, FEWTENTHS);
SCP_TEST("scpb2.txt", 76, 78, FEWTENTHS);
SCP_TEST("scpb3.txt", 80, 85, FEWTENTHS);
SCP_TEST("scpb4.txt", 79, 85, FEWTENTHS);
SCP_TEST("scpb5.txt", 72, 77, FEWTENTHS);
SCP_TEST("scpc1.txt", 227, 251, FEWHUNDREDTHS);
SCP_TEST("scpc2.txt", 219, 238, FEWHUNDREDTHS);
SCP_TEST("scpc3.txt", 243, 259, FEWHUNDREDTHS);
SCP_TEST("scpc4.txt", 219, 246, FEWHUNDREDTHS);
SCP_TEST("scpc5.txt", 214, 228, FEWHUNDREDTHS);
SCP_TEST("scpd1.txt", 60, 68, FEWHUNDREDTHS);
SCP_TEST("scpd2.txt", 66, 70, FEWHUNDREDTHS);
SCP_TEST("scpd3.txt", 72, 78, FEWHUNDREDTHS);
SCP_TEST("scpd4.txt", 62, 67, FEWHUNDREDTHS);
SCP_TEST("scpd5.txt", 61, 72, FEWHUNDREDTHS);
SCP_TEST("scpe1.txt", 5, 5, FEWMILLIS);
SCP_TEST("scpe2.txt", 5, 6, FEWMILLIS);
SCP_TEST("scpe3.txt", 5, 5, FEWMILLIS);
SCP_TEST("scpe4.txt", 5, 6, FEWMILLIS);
SCP_TEST("scpe5.txt", 5, 5, FEWMILLIS);
SCP_TEST("scpnre1.txt", 29, 31, SUBTENTH);
SCP_TEST("scpnre2.txt", 30, 34, SUBTENTH);
SCP_TEST("scpnre3.txt", 27, 32, SUBTENTH);
SCP_TEST("scpnre4.txt", 28, 32, SUBTENTH);
SCP_TEST("scpnre5.txt", 28, 31, SUBTENTH);
SCP_TEST("scpnrf1.txt", 14, 17, SUBTENTH);
SCP_TEST("scpnrf2.txt", 15, 16, SUBTENTH);
SCP_TEST("scpnrf3.txt", 14, 16, SUBTENTH);
SCP_TEST("scpnrf4.txt", 14, 15, SUBTENTH);
SCP_TEST("scpnrf5.txt", 13, 15, SUBTENTH);
SCP_TEST("scpnrg1.txt", 176, 196, SUBTENTH);
SCP_TEST("scpnrg2.txt", 154, 171, SUBTENTH);
SCP_TEST("scpnrg3.txt", 166, 182, SUBTENTH);
SCP_TEST("scpnrg4.txt", 168, 187, SUBTENTH);
SCP_TEST("scpnrg5.txt", 168, 183, SUBTENTH);
SCP_TEST("scpnrh1.txt", 63, 71, FEWTENTHS);
SCP_TEST("scpnrh2.txt", 63, 70, FEWTENTHS);
SCP_TEST("scpnrh3.txt", 59, 65, FEWTENTHS);
SCP_TEST("scpnrh4.txt", 58, 66, FEWTENTHS);
SCP_TEST("scpnrh5.txt", 55, 62, FEWTENTHS);
#endif
#ifdef EXTRA_SCP
SCP_TEST("scpclr10.txt", 0, 32, FEWMILLIS);
SCP_TEST("scpclr11.txt", 0, 30, FEWMILLIS);
SCP_TEST("scpclr12.txt", 0, 31, FEWMILLIS);
SCP_TEST("scpclr13.txt", 0, 33, FEWMILLIS);
SCP_TEST("scpcyc06.txt", 0, 60, FEWMILLIS);
SCP_TEST("scpcyc07.txt", 0, 144, FEWMILLIS);
SCP_TEST("scpcyc08.txt", 0, 360, FEWMILLIS);
SCP_TEST("scpcyc09.txt", 0, 816, SUBHUNDREDTH);
SCP_TEST("scpcyc10.txt", 0, 1920, FEWHUNDREDTHS);
SCP_TEST("scpcyc11.txt", 0, 4284, SUBTENTH);
#endif
#ifdef RAIL
RAIL_TEST("rail507.txt", 174, 218, FEWTENTHS);
RAIL_TEST("rail516.txt", 182, 204, FEWTENTHS);
RAIL_TEST("rail582.txt", 211, 250, FEWTENTHS);
RAIL_TEST("rail2536.txt", 691, 889, MANYSECONDS);
RAIL_TEST("rail2586.txt", 952, 1139, MANYSECONDS);
RAIL_TEST("rail4284.txt", 1065, 1362, MANYSECONDS);
RAIL_TEST("rail4872.txt", 1527, 1861, MANYSECONDS); // [2]
#endif
#undef BASIC_SCP
#undef EXTRA_SCP
#undef RAIL
#undef ORLIB_TEST
#undef ORLIB_UNICOST_TEST
#undef APPEND
#undef APPEND_AND_EVAL
#undef SCP_TEST
#undef RAIL_TEST
TEST(SetCoverHugeTest, GenerateProblem) {
SetCoverModel seed_model =
ReadRailSetCoverProblem(file::JoinPathRespectAbsolute(
::testing::SrcDir(), data_dir, "rail4284.txt"));
seed_model.CreateSparseRowView();
const BaseInt num_wanted_subsets(100'000'000);
const BaseInt num_wanted_elements(40'000);
const double row_scale = 1.1;
const double column_scale = 1.1;
const double cost_scale = 10.0;
SetCoverModel model = SetCoverModel::GenerateRandomModelFrom(
seed_model, num_wanted_elements, num_wanted_subsets, row_scale,
column_scale, cost_scale);
SetCoverInvariant inv =
RunElementDegreeGreedyAndSteepest("rail4284_huge.txt", &model);
LOG(INFO) << "Cost: " << inv.cost();
}
} // namespace operations_research

View File

@@ -187,6 +187,10 @@ class RevisedSimplex {
double DeterministicTime() const;
bool objective_limit_reached() const { return objective_limit_reached_; }
DenseColumn::ConstView GetDualSquaredNorms() {
return dual_edge_norms_.GetEdgeSquaredNorms();
}
const DenseBitRow& GetNotBasicBitRow() const {
return variables_info_.GetNotBasicBitRow();
}

View File

@@ -39,3 +39,34 @@ target_link_libraries(${NAME} PRIVATE
${PROJECT_NAMESPACE}::ortools_proto
$<$<BOOL:${USE_COINOR}>:Coin::Cbc>)
#add_library(${PROJECT_NAMESPACE}::graph ALIAS ${NAME})
if(BUILD_TESTING)
file(GLOB _TEST_SRCS "*_test.cc")
list(FILTER _TEST_SRCS EXCLUDE REGEX "max_flow_test.cc")
foreach(_FULL_FILE_NAME IN LISTS _TEST_SRCS)
get_filename_component(_NAME ${_FULL_FILE_NAME} NAME_WE)
get_filename_component(_FILE_NAME ${_FULL_FILE_NAME} NAME)
ortools_cxx_test(
NAME
graph_${_NAME}
SOURCES
${_FILE_NAME}
LINK_LIBRARIES
benchmark::benchmark
GTest::gmock
GTest::gtest_main
)
endforeach()
ortools_cxx_test(
NAME
graph_max_flow_test
SOURCES
"max_flow_test.cc"
LINK_LIBRARIES
benchmark::benchmark
GTest::gmock
GTest::gtest_main
COMPILE_DEFINITIONS
-DROOT_DIR="../../"
)
endif()

View File

@@ -36,7 +36,9 @@
#include "ortools/linear_solver/linear_solver.h"
#include "ortools/util/file_util.h"
#if not defined(ROOT_DIR)
#define ROOT_DIR "com_google_ortools/"
#endif
namespace operations_research {
namespace {

View File

@@ -402,7 +402,7 @@ PROTO2_RETURN(
%rename (suppressOutput) operations_research::MPSolver::SuppressOutput; // no test
%rename (lookupConstraintOrNull) operations_research::MPSolver::LookupConstraintOrNull; // no test
%rename (lookupVariableOrNull) operations_research::MPSolver::LookupVariableOrNull; // no test
%rename (write) operations_research::MPSolver::Write;
%rename (write) operations_research::MPSolver::Write; // no test
// Expose very advanced parts of the MPSolver API. For expert users only.
%rename (computeConstraintActivities) operations_research::MPSolver::ComputeConstraintActivities;

View File

@@ -20,6 +20,7 @@ add_subdirectory(constraints)
add_subdirectory(cpp)
add_subdirectory(io)
add_subdirectory(labs)
add_subdirectory(solver_tests)
add_subdirectory(solvers)
add_subdirectory(storage)
add_subdirectory(validators)

View File

@@ -26,3 +26,21 @@ target_link_libraries(${NAME} PRIVATE
absl::strings
${PROJECT_NAMESPACE}::math_opt_proto)
#install(TARGETS ${NAME} EXPORT ${PROJECT_NAME}Targets)
if(BUILD_TESTING)
file(GLOB _TEST_SRCS "*_test.cc")
foreach(_FULL_FILE_NAME IN LISTS _TEST_SRCS)
get_filename_component(_NAME ${_FULL_FILE_NAME} NAME_WE)
get_filename_component(_FILE_NAME ${_FULL_FILE_NAME} NAME)
ortools_cxx_test(
NAME
math_opt_constraints_indicator_${_NAME}
SOURCES
${_FILE_NAME}
LINK_LIBRARIES
#benchmark::benchmark
GTest::gmock
GTest::gtest_main
)
endforeach()
endif()

View File

@@ -25,3 +25,21 @@ target_include_directories(${NAME} PUBLIC
target_link_libraries(${NAME} PRIVATE
absl::strings
${PROJECT_NAMESPACE}::math_opt_proto)
if(BUILD_TESTING)
file(GLOB _TEST_SRCS "*_test.cc")
foreach(_FULL_FILE_NAME IN LISTS _TEST_SRCS)
get_filename_component(_NAME ${_FULL_FILE_NAME} NAME_WE)
get_filename_component(_FILE_NAME ${_FULL_FILE_NAME} NAME)
ortools_cxx_test(
NAME
math_opt_constraints_quadratic_${_NAME}
SOURCES
${_FILE_NAME}
LINK_LIBRARIES
#benchmark::benchmark
GTest::gmock
GTest::gtest_main
)
endforeach()
endif()

View File

@@ -25,3 +25,21 @@ target_include_directories(${NAME} PUBLIC
target_link_libraries(${NAME} PRIVATE
absl::strings
${PROJECT_NAMESPACE}::math_opt_proto)
if(BUILD_TESTING)
file(GLOB _TEST_SRCS "*_test.cc")
foreach(_FULL_FILE_NAME IN LISTS _TEST_SRCS)
get_filename_component(_NAME ${_FULL_FILE_NAME} NAME_WE)
get_filename_component(_FILE_NAME ${_FULL_FILE_NAME} NAME)
ortools_cxx_test(
NAME
math_opt_constraints_second_order_cone_${_NAME}
SOURCES
${_FILE_NAME}
LINK_LIBRARIES
#benchmark::benchmark
GTest::gmock
GTest::gtest_main
)
endforeach()
endif()

View File

@@ -25,3 +25,21 @@ target_include_directories(${NAME} PUBLIC
target_link_libraries(${NAME} PRIVATE
absl::strings
${PROJECT_NAMESPACE}::math_opt_proto)
if(BUILD_TESTING)
file(GLOB _TEST_SRCS "*_test.cc")
foreach(_FULL_FILE_NAME IN LISTS _TEST_SRCS)
get_filename_component(_NAME ${_FULL_FILE_NAME} NAME_WE)
get_filename_component(_FILE_NAME ${_FULL_FILE_NAME} NAME)
ortools_cxx_test(
NAME
math_opt_constraints_sos_${_NAME}
SOURCES
${_FILE_NAME}
LINK_LIBRARIES
#benchmark::benchmark
GTest::gmock
GTest::gtest_main
)
endforeach()
endif()

View File

@@ -25,3 +25,21 @@ target_include_directories(${NAME} PUBLIC
target_link_libraries(${NAME} PRIVATE
absl::strings
${PROJECT_NAMESPACE}::math_opt_proto)
if(BUILD_TESTING)
file(GLOB _TEST_SRCS "*_test.cc")
foreach(_FULL_FILE_NAME IN LISTS _TEST_SRCS)
get_filename_component(_NAME ${_FULL_FILE_NAME} NAME_WE)
get_filename_component(_FILE_NAME ${_FULL_FILE_NAME} NAME)
ortools_cxx_test(
NAME
math_opt_constraints_util_${_NAME}
SOURCES
${_FILE_NAME}
LINK_LIBRARIES
#benchmark::benchmark
GTest::gmock
GTest::gtest_main
)
endforeach()
endif()

View File

@@ -25,3 +25,19 @@ target_include_directories(${NAME} PUBLIC
target_link_libraries(${NAME} PRIVATE
absl::strings
${PROJECT_NAMESPACE}::math_opt_proto)
ortools_cxx_library(
NAME
math_opt_matchers
SOURCES
"matchers.cc"
"matchers.h"
TYPE
SHARED
LINK_LIBRARIES
absl::log
absl::status
absl::strings
GTest::gmock
TESTING
)

View File

@@ -11,8 +11,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
package(default_visibility = ["//ortools/math_opt:__subpackages__"])
cc_binary(
name = "basic_example",
srcs = ["basic_example.cc"],

View File

@@ -0,0 +1,372 @@
# Copyright 2010-2024 Google LLC
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set(_PREFIX math_opt)
ortools_cxx_library(
NAME
${_PREFIX}_base_solver_test
SOURCES
"base_solver_test.cc"
"base_solver_test.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_callback_tests
SOURCES
"callback_tests.cc"
"callback_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
absl::status
absl::strings
ortools::math_opt_matchers
ortools::math_opt_base_solver_test
ortools::math_opt_test_models
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_status_tests
SOURCES
"status_tests.cc"
"status_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
ortools::math_opt_matchers
ortools::math_opt_test_models
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_lp_tests
SOURCES
"lp_tests.cc"
"lp_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
ortools::math_opt_matchers
ortools::math_opt_base_solver_test
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_lp_incomplete_solve_tests
SOURCES
"lp_incomplete_solve_tests.cc"
"lp_incomplete_solve_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
ortools::math_opt_matchers
ortools::math_opt_test_models
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_invalid_input_tests
SOURCES
"invalid_input_tests.cc"
"invalid_input_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
ortools::math_opt_base_solver_test
TESTING
)
# In CMake or-tools is linked with all enable solvers so this test won't work.
#ortools_cxx_test(
# NAME
# ${_PREFIX}_unregistered_solver_test
# SOURCES
# "unregistered_solver_test.cc"
# LINK_LIBRARIES
# GTest::gmock
# GTest::gmock_main
#)
ortools_cxx_library(
NAME
${_PREFIX}_mip_tests
SOURCES
"mip_tests.cc"
"mip_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
absl::status
ortools::math_opt_matchers
ortools::math_opt_base_solver_test
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_ip_model_solve_parameters_tests
SOURCES
"ip_model_solve_parameters_tests.cc"
"ip_model_solve_parameters_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
ortools::math_opt_matchers
ortools::math_opt_base_solver_test
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_ip_multiple_solutions_tests
SOURCES
"ip_multiple_solutions_tests.cc"
"ip_multiple_solutions_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::strings
ortools::math_opt_matchers
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_lp_model_solve_parameters_tests
SOURCES
"lp_model_solve_parameters_tests.cc"
"lp_model_solve_parameters_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
ortools::math_opt_matchers
ortools::math_opt_base_solver_test
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_lp_parameter_tests
SOURCES
"lp_parameter_tests.cc"
"lp_parameter_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
absl::status
absl::strings
ortools::math_opt_matchers
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_lp_initial_basis_tests
SOURCES
"lp_initial_basis_tests.cc"
"lp_initial_basis_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
absl::status
ortools::math_opt_base_solver_test
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_ip_parameter_tests
SOURCES
"ip_parameter_tests.cc"
"ip_parameter_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
ortools::math_opt_matchers
ortools::math_opt_test_models
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_multi_objective_tests
SOURCES
"multi_objective_tests.cc"
"multi_objective_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
ortools::math_opt_matchers
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_qp_tests
SOURCES
"qp_tests.cc"
"qp_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
ortools::math_opt_matchers
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_qc_tests
SOURCES
"qc_tests.cc"
"qc_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
ortools::math_opt_matchers
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_second_order_cone_tests
SOURCES
"second_order_cone_tests.cc"
"second_order_cone_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
ortools::math_opt_matchers
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_logical_constraint_tests
SOURCES
"logical_constraint_tests.cc"
"logical_constraint_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
ortools::math_opt_matchers
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_test_models
SOURCES
"test_models.cc"
"test_models.h"
TYPE
STATIC
LINK_LIBRARIES
absl::log
absl::strings
TESTING
)
ortools_cxx_test(
NAME
${_PREFIX}_test_models_test
SOURCES
"test_models_test.cc"
LINK_LIBRARIES
GTest::gmock
GTest::gmock_main
ortools::math_opt_test_models
ortools::math_opt_matchers
#ortools::math_opt_glop_solver
#ortools::math_opt_gscipt_solver
)
ortools_cxx_library(
NAME
${_PREFIX}_generic_tests
SOURCES
"generic_tests.cc"
"generic_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
ortools::math_opt_matchers
ortools::math_opt_test_models
TESTING
)
ortools_cxx_library(
NAME
${_PREFIX}_infeasible_subsystem_tests
SOURCES
"infeasible_subsystem_tests.cc"
"infeasible_subsystem_tests.h"
TYPE
STATIC
LINK_LIBRARIES
GTest::gmock
absl::log
absl::status
absl::strings
absl::time
ortools::math_opt_matchers
TESTING
)

View File

@@ -618,6 +618,7 @@ cc_test(
"//ortools/math_opt/solver_tests:lp_parameter_tests",
"//ortools/math_opt/solver_tests:lp_tests",
"//ortools/math_opt/solver_tests:mip_tests",
"//ortools/math_opt/solver_tests:multi_objective_tests",
"//ortools/math_opt/solver_tests:status_tests",
"//ortools/math_opt/testing:param_name",
"@com_google_absl//absl/status",

View File

@@ -52,3 +52,183 @@ target_link_libraries(${NAME} PRIVATE
$<$<BOOL:${USE_PDLP}>:Eigen3::Eigen>
$<$<BOOL:${USE_SCIP}>:libscip>
${PROJECT_NAMESPACE}::math_opt_proto)
if(USE_SCIP)
ortools_cxx_test(
NAME
math_opt_solvers_gscip_solver_test
SOURCES
"gscip_solver_test.cc"
LINK_LIBRARIES
GTest::gmock
GTest::gmock_main
absl::status
ortools::math_opt_matchers
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_callback_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_generic_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_infeasible_subsystem_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_invalid_input_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_ip_model_solve_parameters_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_ip_multiple_solutions_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_ip_parameter_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_logical_constraint_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_mip_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_multi_objective_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_qc_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_qp_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_second_order_cone_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_status_tests>"
)
endif()
if(USE_GLOP)
ortools_cxx_test(
NAME
math_opt_solvers_glop_solver_test
SOURCES
"glop_solver_test.cc"
LINK_LIBRARIES
GTest::gmock
GTest::gmock_main
absl::status
ortools::math_opt_matchers
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_callback_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_generic_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_infeasible_subsystem_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_invalid_input_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_logical_constraint_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_parameter_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_incomplete_solve_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_initial_basis_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_model_solve_parameters_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_multi_objective_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_qc_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_qp_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_second_order_cone_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_status_tests>"
)
endif()
ortools_cxx_test(
NAME
math_opt_solvers_cp_sat_solver_test
SOURCES
"cp_sat_solver_test.cc"
LINK_LIBRARIES
GTest::gmock
GTest::gmock_main
absl::status
ortools::math_opt_matchers
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_callback_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_generic_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_infeasible_subsystem_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_invalid_input_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_ip_model_solve_parameters_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_ip_multiple_solutions_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_ip_parameter_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_logical_constraint_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_mip_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_multi_objective_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_qc_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_qp_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_second_order_cone_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_status_tests>"
)
ortools_cxx_test(
NAME
math_opt_solvers_message_callback_data_test
SOURCES
"message_callback_data_test.cc"
LINK_LIBRARIES
GTest::gmock_main
absl::cleanup
absl::synchronization
)
if(USE_PDLP)
ortools_cxx_test(
NAME
math_opt_solvers_pdlp_solver_test
SOURCES
"pdlp_solver_test.cc"
LINK_LIBRARIES
GTest::gmock
GTest::gmock_main
absl::status
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_callback_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_generic_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_infeasible_subsystem_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_invalid_input_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_logical_constraint_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_incomplete_solve_tests>"
#"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_initial_basis_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_model_solve_parameters_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_parameter_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_multi_objective_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_qc_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_qp_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_second_order_cone_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_status_tests>"
)
endif()
if(USE_GLPK)
ortools_cxx_test(
NAME
math_opt_solvers_glpk_solver_test
SOURCES
"glpk_solver_test.cc"
LINK_LIBRARIES
GTest::gmock
GTest::gmock_main
absl::status
absl::time
ortools::math_opt_matchers
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_callback_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_generic_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_infeasible_subsystem_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_invalid_input_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_ip_model_solve_parameters_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_ip_parameter_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_logical_constraint_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_incomplete_solve_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_model_solve_parameters_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_parameter_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_mip_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_multi_objective_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_qc_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_qp_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_second_order_cone_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_status_tests>"
)
endif()
if(USE_HIGHS)
ortools_cxx_test(
NAME
math_opt_solvers_highs_solver_test
SOURCES
"highs_solver_test.cc"
LINK_LIBRARIES
GTest::gmock
GTest::gmock_main
absl::status
ortools::math_opt_matchers
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_callback_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_generic_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_infeasible_subsystem_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_ip_model_solve_parameters_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_ip_parameter_tests>"
#"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_logical_constraint_tests>"
#"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_incomplete_solve_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_model_solve_parameters_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_parameter_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_lp_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_mip_tests>"
"$<LINK_LIBRARY:WHOLE_ARCHIVE,ortools::math_opt_status_tests>"
)
endif()

View File

@@ -42,11 +42,15 @@ target_link_libraries(${NAME} PRIVATE
if(BUILD_TESTING)
file(GLOB _TEST_SRCS "*_test.cc")
foreach(FILE_NAME IN LISTS _TEST_SRCS)
foreach(_FULL_FILE_NAME IN LISTS _TEST_SRCS)
get_filename_component(_NAME ${_FULL_FILE_NAME} NAME_WE)
get_filename_component(_FILE_NAME ${_FULL_FILE_NAME} NAME)
ortools_cxx_test(
FILE_NAME
${FILE_NAME}
DEPS
NAME
sat_${_NAME}
SOURCES
${_FILE_NAME}
LINK_LIBRARIES
benchmark::benchmark
GTest::gmock
GTest::gtest_main

View File

@@ -1,12 +1,12 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 22b7a17f..0a5a18dd 100644
index be94fca..1529011 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,6 +51,7 @@ if(APPLE)
@@ -88,6 +88,7 @@ if(APPLE)
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Wno-inconsistent-missing-override -Wno-unused-command-line-argument -Wno-unused-result -Wno-exceptions"
)
+ add_compile_options(-O1)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version")
endif(APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
endif()

View File

@@ -1,12 +1,12 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4a70789..d19c2a9 100644
index 8c51561..f223f08 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,6 +51,7 @@ if(APPLE)
@@ -88,6 +88,7 @@ if(APPLE)
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Wno-inconsistent-missing-override -Wno-unused-command-line-argument -Wno-unused-result -Wno-exceptions"
)
+ add_compile_options(-O1)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version")
endif(APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
endif()

View File

@@ -1,12 +1,12 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e1d43115..6b2a17ad 100644
index bb95c63..7fde473 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,6 +51,7 @@ if(APPLE)
@@ -88,6 +88,7 @@ if(APPLE)
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Wno-inconsistent-missing-override -Wno-unused-command-line-argument -Wno-unused-result -Wno-exceptions"
)
+ add_compile_options(-O1)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version")
endif(APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
endif()

View File

@@ -1,12 +1,12 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fcfa658..267ddd9 100644
index 3fc9cff..b2423fe 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,6 +51,7 @@ if(APPLE)
@@ -88,6 +88,7 @@ if(APPLE)
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Wno-inconsistent-missing-override -Wno-unused-command-line-argument -Wno-unused-result -Wno-exceptions"
)
+ add_compile_options(-O1)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version")
endif(APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
endif()

View File

@@ -0,0 +1,18 @@
diff --git a/googletest/cmake/internal_utils.cmake b/googletest/cmake/internal_utils.cmake
index 580ac1c..c6cc44c 100644
--- a/googletest/cmake/internal_utils.cmake
+++ b/googletest/cmake/internal_utils.cmake
@@ -190,6 +190,13 @@ function(cxx_library_with_type name type cxx_flags)
COMPILE_DEFINITIONS "GTEST_CREATE_SHARED_LIBRARY=1")
target_compile_definitions(${name} INTERFACE
$<INSTALL_INTERFACE:GTEST_LINKED_AS_SHARED_LIBRARY=1>)
+ if(APPLE)
+ set_target_properties(${name} PROPERTIES
+ INSTALL_RPATH "@loader_path")
+ elseif(UNIX)
+ set_target_properties(${name} PROPERTIES
+ INSTALL_RPATH "$ORIGIN")
+ endif()
endif()
if (DEFINED GTEST_HAS_PTHREAD)
target_link_libraries(${name} PUBLIC Threads::Threads)

View File

@@ -1,12 +1,12 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7b3cee2..2ac9c9d 100644
index bc22fbd..1c2a604 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,6 +51,7 @@ if(APPLE)
@@ -88,6 +88,7 @@ if(APPLE)
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Wno-inconsistent-missing-override -Wno-unused-command-line-argument -Wno-unused-result -Wno-exceptions"
)
+ add_compile_options(-O1)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X deployment version")
endif(APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
endif()

View File

@@ -55,7 +55,7 @@ index ceb65a8..e142837 100644
include_directories(${TOP_LEVEL_DIR} ${pybind11_INCLUDE_DIRS})
diff --git a/cmake/dependencies/CMakeLists.txt b/cmake/dependencies/CMakeLists.txt
new file mode 100644
index 0000000..b67d564
index 0000000..cb13e7e
--- /dev/null
+++ b/cmake/dependencies/CMakeLists.txt
@@ -0,0 +1,19 @@
@@ -158,7 +158,7 @@ index 791c245..33e614a 100644
)
diff --git a/pybind11_abseil/CMakeLists.txt b/pybind11_abseil/CMakeLists.txt
index d1b7483..ce7fd72 100644
index d1b7483..74e3443 100644
--- a/pybind11_abseil/CMakeLists.txt
+++ b/pybind11_abseil/CMakeLists.txt
@@ -42,14 +42,19 @@ target_link_libraries(ok_status_singleton_pyinit_google3
@@ -184,7 +184,7 @@ index d1b7483..ce7fd72 100644
target_link_libraries(ok_status_singleton
PUBLIC ok_status_singleton_pyinit_google3)
@@ -150,14 +155,23 @@ target_link_libraries(status_pyinit_google3 PUBLIC register_status_bindings)
@@ -150,14 +155,30 @@ target_link_libraries(status_pyinit_google3 PUBLIC register_status_bindings)
# status ====================================================================
@@ -195,25 +195,32 @@ index d1b7483..ce7fd72 100644
+set_target_properties(status_py_extension_stub PROPERTIES LIBRARY_OUTPUT_NAME "status")
+# note: macOS is APPLE and also UNIX !
+if(APPLE)
+ set_target_properties(status_py_extension_stub PROPERTIES SUFFIX ".so")
+ set_target_properties(status_py_extension_stub PROPERTIES
+ SUFFIX ".so"
+ INSTALL_RPATH "@loader_path;@loader_path/../ortools/.libs"
+ )
+ set_property(TARGET status_py_extension_stub APPEND PROPERTY
+ LINK_FLAGS "-flat_namespace -undefined suppress")
+elseif(UNIX)
+ set_target_properties(status_py_extension_stub PROPERTIES
+ INSTALL_RPATH "$ORIGIN:$ORIGIN/../ortools/.libs"
+ )
+endif()
+
+add_library(pybind11_abseil::status ALIAS status_py_extension_stub)
-target_include_directories(status INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
+target_include_directories(status_py_extension_stub INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
+add_library(pybind11_abseil::status ALIAS status_py_extension_stub)
-set_target_properties(status PROPERTIES PREFIX "")
+set_target_properties(status_py_extension_stub PROPERTIES PREFIX "")
+target_include_directories(status_py_extension_stub INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
-target_link_libraries(status PUBLIC status_pyinit_google3 absl::status)
+set_target_properties(status_py_extension_stub PROPERTIES PREFIX "")
+
+target_link_libraries(status_py_extension_stub PUBLIC status_pyinit_google3 absl::status)
# import_status_module =========================================================
@@ -167,7 +181,7 @@ add_library(pybind11_abseil::import_status_module ALIAS import_status_module)
@@ -167,7 +188,7 @@ add_library(pybind11_abseil::import_status_module ALIAS import_status_module)
target_include_directories(import_status_module
INTERFACE $<BUILD_INTERFACE:${TOP_LEVEL_DIR}>)
@@ -222,7 +229,7 @@ index d1b7483..ce7fd72 100644
# status_casters ===============================================================
@@ -175,25 +189,27 @@ add_library(status_casters INTERFACE)
@@ -175,25 +196,27 @@ add_library(status_casters INTERFACE)
add_library(pybind11_abseil::status_casters ALIAS status_casters)
target_include_directories(status_casters

View File

@@ -0,0 +1,18 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bdac5af..cedaf6e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -131,6 +131,13 @@ set(RE2_HEADERS
add_library(re2 ${RE2_SOURCES})
target_compile_features(re2 PUBLIC cxx_std_14)
+if(APPLE)
+ set_target_properties(re2 PROPERTIES
+ INSTALL_RPATH "@loader_path")
+elseif(UNIX)
+ set_target_properties(re2 PROPERTIES
+ INSTALL_RPATH "$ORIGIN")
+endif()
target_include_directories(re2 PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
# CMake gives "set_target_properties called with incorrect number of arguments."
# errors if we don't quote ${RE2_HEADERS}, so quote it despite prevailing style.