Skip to content

Commit 8068658

Browse files
committed
backport from main
1 parent c96c824 commit 8068658

30 files changed

+149
-130
lines changed

ortools/algorithms/binary_search.h

+23-13
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,37 @@
1919
#include <functional>
2020
#include <utility>
2121

22+
#include "absl/base/log_severity.h"
2223
#include "absl/functional/function_ref.h"
2324
#include "absl/log/check.h"
2425
#include "absl/numeric/int128.h"
2526
#include "absl/types/span.h"
2627
#include "ortools/base/logging.h"
2728

2829
namespace operations_research {
29-
30+
// Finds a point in [x_true, x_false) where f changes from true to false.
31+
// If check_bounds is true, it will CHECK that f(x_true) = true and
32+
// f(x_false) = false.
33+
//
3034
// EXAMPLE:
3135
// // Finds the value x in [0,Pi/2] such that cos(x)=2sin(x):
3236
// BinarySearch<double>(/*x_true=*/0.0, /*x_false=*/M_PI/2,
3337
// [](double x) { return cos(x) >= 2*sin(x); });
3438
//
35-
// Note that x_true > x_false is supported: it works either way.
39+
// MONOTONIC FUNCTIONS: Suppose f is a monotonic boolean function. See below for
40+
// the NON-MONOTONIC case.
3641
//
37-
// Ideally, f is a monotonic boolean function, such that:
38-
// - f(x_true) = true
39-
// - f(x_false) = false
40-
// - there exists X such that f(x)=true for all x between x_true and X, and
41-
// f(x)=false for all x between X and x_false.
42+
// If x_true < x_false, this returns X such that:
43+
// - x_true < X < x_false,
44+
// - f((x_true, X]) = true (i.e. for all x in (x_true, X], f(x) = true),
45+
// - f((X, x_false)) = false (i.e. for all x in (X, x_false), f(x) = false)
46+
// or this returns x_true if such an X does not exist.
4247
//
43-
// In those conditions, this returns that value X (note that f(X) is true).
44-
// See below for the NON-MONOTONIC case.
48+
// If x_true > x_false, this function returns X such that:
49+
// - x_false < X < x_true
50+
// - f((x_false, X)) = false
51+
// - f([X, x_true)) = true
52+
// or this return x_true if such an X does not exist.
4553
//
4654
// Also note that 'Point' may be floating-point types: the function will still
4755
// converge when the midpoint can't be distinguished from one of the limits,
@@ -68,7 +76,7 @@ namespace operations_research {
6876
// Note also that even if f() is non-deterministic, i.e. f(X) can sometimes
6977
// return true and sometimes false for the same X, then the binary search will
7078
// still finish, but it's hard to say anything about the returned X.
71-
template <class Point>
79+
template <class Point, bool check_bounds = DEBUG_MODE>
7280
Point BinarySearch(Point x_true, Point x_false, std::function<bool(Point)> f);
7381

7482
// Used by BinarySearch(). This is just (x+y)/2, with some DCHECKs to catch
@@ -207,10 +215,12 @@ Point BinarySearchMidpoint(Point x, Point y) {
207215
return midpoint;
208216
}
209217

210-
template <class Point>
218+
template <class Point, bool check_bounds>
211219
Point BinarySearch(Point x_true, Point x_false, std::function<bool(Point)> f) {
212-
DCHECK(f(x_true)) << x_true;
213-
DCHECK(!f(x_false)) << x_false;
220+
if constexpr (check_bounds) {
221+
CHECK(f(x_true)) << x_true;
222+
CHECK(!f(x_false)) << x_false;
223+
}
214224
int num_iterations = 0;
215225
constexpr int kMaxNumIterations = 1000000;
216226
while (true) {

ortools/algorithms/binary_search_test.cc

+47
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,53 @@ TEST(BinarySearchDeathTest, DiesIfEitherBoundaryConditionViolatedInFastbuild) {
175175
"");
176176
}
177177

178+
TEST(BinarySearchDeathTest, DiesIfBoundCheckIsEnabledAndABoundIsViolated) {
179+
// EXPECT_DEATH does not work with 2-parameter templates.
180+
auto bs = [](int x_true, int x_false, auto f) {
181+
return BinarySearch<int, true>(x_true, x_false, f);
182+
};
183+
EXPECT_DEATH(bs(/*x_true=*/0, /*x_false=*/42, [](int x) { return x < 999; }),
184+
"");
185+
EXPECT_DEATH(bs(/*x_true=*/0, /*x_false=*/42, [](int x) { return x < 0; }),
186+
"");
187+
EXPECT_DEATH(bs(/*x_true=*/0, /*x_false=*/42, [](int x) { return x > 20; }),
188+
"");
189+
}
190+
191+
TEST(BinarySearchTest, NoDeathIfBoundCheckIsDisabled) {
192+
// EXPECT_EQ does not work with 2-parameter templates.
193+
auto bs = [](int x_true, int x_false, auto f) {
194+
return BinarySearch<int, false>(x_true, x_false, f);
195+
};
196+
197+
// f is true on the whole interval ]0, 42[: return last value 41.
198+
EXPECT_EQ(bs(/*x_true=*/0, /*x_false=*/42, [](int x) { return x < 999; }),
199+
41);
200+
// f is true on reversed interval ]42, 0[: return last value 1.
201+
EXPECT_EQ(bs(/*x_true=*/42, /*x_false=*/0, [](int x) { return x < 999; }), 1);
202+
// f is false on the whole interval ]0, 42[: return x_true bound 0.
203+
EXPECT_EQ(bs(/*x_true=*/0, /*x_false=*/42, [](int x) { return x < 0; }), 0);
204+
// f is false on reversed interval ]42, 0[: return x_true bound 42.
205+
EXPECT_EQ(bs(/*x_true=*/0, /*x_false=*/42, [](int x) { return x < 0; }), 0);
206+
// f is false on x_true, true on x_false.
207+
// No DCHECK trigger, instead return a transition point of the function
208+
// f': x_true -> true, x_false -> false, x_true < x < x_false -> f(x).
209+
// The transitions are: 0 (true) -> 1 (false) and 41 (true) -> 42 (false).
210+
{
211+
const int x_transition =
212+
bs(/*x_true=*/0, /*x_false=*/42, [](int x) { return x > 20; });
213+
EXPECT_TRUE(x_transition == 0 || x_transition == 41);
214+
}
215+
// f is false on x_true, true on x_false, with a reversed interval.
216+
// No DCHECK trigger, return one of the transition points.
217+
// The transitions are: 42 (true) -> 41 (false) and 1 (true) -> 0 (false).
218+
{
219+
const int x_transition =
220+
bs(/*x_true=*/42, /*x_false=*/0, [](int x) { return x < 20; });
221+
EXPECT_TRUE(x_transition == 42 || x_transition == 1);
222+
}
223+
}
224+
178225
} // namespace
179226

180227
// Examples of cases where one needs to override BinarySearchMidpoint() to get

ortools/algorithms/dynamic_partition_test.cc

+2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
#include <random>
2020
#include <vector>
2121

22+
#include "absl/base/log_severity.h"
2223
#include "absl/random/bit_gen_ref.h"
2324
#include "absl/random/random.h"
25+
#include "absl/types/span.h"
2426
#include "gtest/gtest.h"
2527
#include "ortools/base/gmock.h"
2628
#include "ortools/base/stl_util.h"

ortools/algorithms/hungarian_test.cc

+19-20
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,12 @@
2020
#include <random>
2121
#include <vector>
2222

23+
#include "absl/base/macros.h"
2324
#include "absl/container/flat_hash_map.h"
2425
#include "absl/random/distributions.h"
2526
#include "absl/types/span.h"
2627
#include "gtest/gtest.h"
27-
#include "ortools/base/macros.h"
2828
#include "ortools/base/map_util.h"
29-
#include "ortools/base/types.h"
3029

3130
namespace operations_research {
3231

@@ -94,24 +93,24 @@ TEST(LinearAssignmentTest, InvalidMatrix) {
9493
TestMinimization(cost_nan, 0, expected_agents, expected_tasks);
9594
}
9695

97-
#define MATRIX_TEST \
98-
{ \
99-
std::vector<std::vector<double>> cost(kMatrixHeight); \
100-
for (int row = 0; row < kMatrixHeight; ++row) { \
101-
cost[row].resize(kMatrixWidth); \
102-
for (int col = 0; col < kMatrixWidth; ++col) { \
103-
cost[row][col] = kCost[row][col]; \
104-
} \
105-
} \
106-
EXPECT_EQ(arraysize(expected_agents_for_min), \
107-
arraysize(expected_tasks_for_min)); \
108-
EXPECT_EQ(arraysize(expected_agents_for_max), \
109-
arraysize(expected_tasks_for_max)); \
110-
const int assignment_size = arraysize(expected_agents_for_max); \
111-
TestMinimization(cost, assignment_size, expected_agents_for_min, \
112-
expected_tasks_for_min); \
113-
TestMaximization(cost, assignment_size, expected_agents_for_max, \
114-
expected_tasks_for_max); \
96+
#define MATRIX_TEST \
97+
{ \
98+
std::vector<std::vector<double>> cost(kMatrixHeight); \
99+
for (int row = 0; row < kMatrixHeight; ++row) { \
100+
cost[row].resize(kMatrixWidth); \
101+
for (int col = 0; col < kMatrixWidth; ++col) { \
102+
cost[row][col] = kCost[row][col]; \
103+
} \
104+
} \
105+
EXPECT_EQ(ABSL_ARRAYSIZE(expected_agents_for_min), \
106+
ABSL_ARRAYSIZE(expected_tasks_for_min)); \
107+
EXPECT_EQ(ABSL_ARRAYSIZE(expected_agents_for_max), \
108+
ABSL_ARRAYSIZE(expected_tasks_for_max)); \
109+
const int assignment_size = ABSL_ARRAYSIZE(expected_agents_for_max); \
110+
TestMinimization(cost, assignment_size, expected_agents_for_min, \
111+
expected_tasks_for_min); \
112+
TestMaximization(cost, assignment_size, expected_agents_for_max, \
113+
expected_tasks_for_max); \
115114
}
116115

117116
// Test on a 1x1 matrix

ortools/algorithms/knapsack_solver_test.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
#include <limits>
1818
#include <vector>
1919

20+
#include "absl/base/macros.h"
2021
#include "gtest/gtest.h"
21-
#include "ortools/base/macros.h"
2222
#include "ortools/util/time_limit.h"
2323

2424
namespace operations_research {

ortools/base/BUILD.bazel

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ cc_library(
4444
hdrs = [
4545
"commandlineflags.h",
4646
"init_google.h",
47-
"logging.h",
4847
"stl_logging.h",
4948
"types.h",
5049
"version.h",
@@ -63,7 +62,6 @@ cc_library(
6362
deps = [
6463
":commandlineflags",
6564
":logging",
66-
":macros",
6765
":types",
6866
"@com_google_absl//absl/base",
6967
"@com_google_absl//absl/container:flat_hash_map",
@@ -73,7 +71,10 @@ cc_library(
7371
"@com_google_absl//absl/flags:flag",
7472
"@com_google_absl//absl/flags:parse",
7573
"@com_google_absl//absl/flags:usage",
74+
"@com_google_absl//absl/log",
75+
"@com_google_absl//absl/log:check",
7676
"@com_google_absl//absl/log:die_if_null",
77+
"@com_google_absl//absl/log:globals",
7778
"@com_google_absl//absl/log:initialize",
7879
"@com_google_absl//absl/strings",
7980
"@com_google_absl//absl/synchronization",
@@ -617,7 +618,6 @@ cc_library(
617618
srcs = ["timer.cc"],
618619
hdrs = ["timer.h"],
619620
deps = [
620-
":macros",
621621
"@com_google_absl//absl/log:check",
622622
"@com_google_absl//absl/time",
623623
],

ortools/base/adjustable_priority_queue-inl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@
1414
#ifndef OR_TOOLS_BASE_ADJUSTABLE_PRIORITY_QUEUE_INL_H_
1515
#define OR_TOOLS_BASE_ADJUSTABLE_PRIORITY_QUEUE_INL_H_
1616

17-
#include "ortools/base/adjustable_priority_queue.h"
17+
#include "ortools/base/adjustable_priority_queue.h" // IWYU pragma: export
1818

1919
#endif // OR_TOOLS_BASE_ADJUSTABLE_PRIORITY_QUEUE_INL_H_

ortools/base/adjustable_priority_queue.h

-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
#include <list>
2121
#include <vector>
2222

23-
#include "ortools/base/macros.h"
24-
2523
template <typename T, typename Comparator>
2624
class LowerPriorityThan {
2725
public:

ortools/base/constant_divisor_test.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ TEST(ConstantDivisorTemplateTest, Simple) {
6868
}
6969

7070
TEST(ConstantDivisorUint64Test, Bugs) {
71-
// If forumula (27) from p231 is ever implemented, these divisors will break
71+
// If formula (27) from p231 is ever implemented, these divisors will break
7272
// if a >= is accidentally used instead of >.
7373
EXPECT_EQ(uint64_t{828560257293048160},
7474
ConstantDivisor<uint64_t>(21).div(uint64_t{17399765403154011380u}));

ortools/base/gzipfile.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ enum class AppendedStreams {
2828
kIgnoreAppendedData,
2929
};
3030

31-
// Return a readonly file that contains a uncompressed version of
31+
// Return a read-only file that contains a uncompressed version of
3232
// another File.
3333
//
3434
// If "ownership == TAKE_OWNERSHIP", the file takes ownership of

ortools/base/int_type.h

+7-14
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,12 @@
147147

148148
#include <stddef.h>
149149

150-
#include <functional>
151150
#include <iosfwd>
152151
#include <ostream> // NOLINT
153152
#include <type_traits>
154153

155-
#include "absl/base/port.h"
154+
#include "absl/base/attributes.h"
156155
#include "absl/strings/string_view.h"
157-
#include "ortools/base/macros.h"
158156

159157
namespace gtl {
160158

@@ -198,8 +196,13 @@ class IntType {
198196
}
199197
};
200198

199+
template <typename H>
200+
friend H AbslHashValue(H h, const IntType& i) {
201+
return H::combine(std::move(h), i.value());
202+
}
203+
201204
public:
202-
// Default c'tor initializing value_ to 0.
205+
// Default constructor initializing value_ to 0.
203206
constexpr IntType() : value_(0) {}
204207
// C'tor explicitly initializing from a ValueType.
205208
constexpr explicit IntType(ValueType value) : value_(value) {}
@@ -273,9 +276,6 @@ class IntType {
273276
private:
274277
// The integer value of type ValueType.
275278
ValueType value_;
276-
277-
COMPILE_ASSERT(std::is_integral<ValueType>::value,
278-
invalid_integer_type_for_id_type_);
279279
} ABSL_ATTRIBUTE_PACKED;
280280

281281
// -- NON-MEMBER STREAM OPERATORS ----------------------------------------------
@@ -357,11 +357,4 @@ INT_TYPE_COMPARISON_OP(>=); // NOLINT
357357

358358
} // namespace gtl
359359

360-
// Allows it to be used as a key to hashable containers.
361-
namespace std {
362-
template <typename IntTypeName, typename ValueType>
363-
struct hash<gtl::IntType<IntTypeName, ValueType> >
364-
: gtl::IntType<IntTypeName, ValueType>::Hasher {};
365-
} // namespace std
366-
367360
#endif // OR_TOOLS_BASE_INT_TYPE_H_

ortools/base/logging.cc

-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
#include <mutex> // for std::call_once and std::once_flag. // NOLINT
1717

18-
#include "absl/flags/flag.h"
1918
#include "absl/flags/usage.h"
2019
#include "absl/log/globals.h"
2120
#include "absl/log/initialize.h"
@@ -34,6 +33,4 @@ void FixFlagsAndEnvironmentForSwig() {
3433
absl::EnableLogPrefix(false);
3534
}
3635

37-
void KeepAbslSymbols() { absl::SetFlag(&FLAGS_stderrthreshold, 0); }
38-
3936
} // namespace operations_research

ortools/base/macros.h

+1-17
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@
1414
#ifndef OR_TOOLS_BASE_MACROS_H_
1515
#define OR_TOOLS_BASE_MACROS_H_
1616

17-
#include <cstdlib> // for size_t.
18-
19-
#include "ortools/base/base_export.h" // for OR_DLL
17+
#include "ortools/base/base_export.h" // IWYU pragma: export
2018

2119
#define COMPILE_ASSERT(x, msg)
2220

@@ -26,18 +24,4 @@ const bool DEBUG_MODE = false;
2624
const bool DEBUG_MODE = true;
2725
#endif // NDEBUG
2826

29-
// DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions.
30-
// It goes in the private: declarations in a class.
31-
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
32-
TypeName(const TypeName&) = delete; \
33-
TypeName& operator=(const TypeName&) = delete
34-
35-
template <typename T, size_t N>
36-
char (&ArraySizeHelper(T (&array)[N]))[N];
37-
#ifndef COMPILER_MSVC
38-
template <typename T, size_t N>
39-
char (&ArraySizeHelper(const T (&array)[N]))[N];
40-
#endif
41-
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
42-
4327
#endif // OR_TOOLS_BASE_MACROS_H_

ortools/base/mathutil.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
// See the License for the specific language governing permissions and
1212
// limitations under the License.
1313

14+
#include "absl/log/check.h"
1415
#if defined(_MSC_VER)
1516
#define _USE_MATH_DEFINES
1617
#include <cmath>
1718
#endif
1819

19-
#include "ortools/base/logging.h"
2020
#include "ortools/base/mathutil.h"
2121

2222
namespace operations_research {

0 commit comments

Comments
 (0)