19
19
#include < functional>
20
20
#include < utility>
21
21
22
+ #include " absl/base/log_severity.h"
22
23
#include " absl/functional/function_ref.h"
23
24
#include " absl/log/check.h"
24
25
#include " absl/numeric/int128.h"
25
26
#include " absl/types/span.h"
26
27
#include " ortools/base/logging.h"
27
28
28
29
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
+ //
30
34
// EXAMPLE:
31
35
// // Finds the value x in [0,Pi/2] such that cos(x)=2sin(x):
32
36
// BinarySearch<double>(/*x_true=*/0.0, /*x_false=*/M_PI/2,
33
37
// [](double x) { return cos(x) >= 2*sin(x); });
34
38
//
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.
36
41
//
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 .
42
47
//
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.
45
53
//
46
54
// Also note that 'Point' may be floating-point types: the function will still
47
55
// converge when the midpoint can't be distinguished from one of the limits,
@@ -68,7 +76,7 @@ namespace operations_research {
68
76
// Note also that even if f() is non-deterministic, i.e. f(X) can sometimes
69
77
// return true and sometimes false for the same X, then the binary search will
70
78
// 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 >
72
80
Point BinarySearch (Point x_true, Point x_false, std::function<bool (Point )> f);
73
81
74
82
// Used by BinarySearch(). This is just (x+y)/2, with some DCHECKs to catch
@@ -207,10 +215,12 @@ Point BinarySearchMidpoint(Point x, Point y) {
207
215
return midpoint;
208
216
}
209
217
210
- template <class Point >
218
+ template <class Point , bool check_bounds >
211
219
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
+ }
214
224
int num_iterations = 0 ;
215
225
constexpr int kMaxNumIterations = 1000000 ;
216
226
while (true ) {
0 commit comments