SOPT
Sparse OPTimisation
bisection_method.h
Go to the documentation of this file.
1 #ifndef SOPT_BISECTION_METHOD_H
2 #define SOPT_BISECTION_METHOD_H
3 #include "sopt/config.h"
4 #include <functional>
5 #include <type_traits>
6 #include "sopt/exception.h"
7 #include "sopt/logging.h"
8 #include "sopt/types.h"
9 
10 namespace sopt {
12 template <typename K>
13 typename std::enable_if<std::is_same<t_real, K>::value, K>::type bisection_method(
14  const K &function_value, const std::function<K(K)> &func, const K &a, const K &b,
15  const t_real &rel_convergence = 1e-4);
16 
17 template <typename K>
18 typename std::enable_if<std::is_same<t_real, K>::value, K>::type bisection_method(
19  const K &function_value, const std::function<K(K)> &func, const K &a, const K &b,
20  const t_real &rel_convergence) {
21  t_real lower_eta = a;
22  t_real upper_eta = b;
23  t_real relative_difference = 1;
24  t_real eta = (a + b) * 0.5;
25  SOPT_LOW_LOG("Starting bisection method over x ∈ [{}, {}], to estimate f(x) = {}", a, b,
26  function_value);
27  const auto estimate = [&](const K &x) { return func(x) - function_value; };
28  const t_real eb = estimate(b);
29  const t_real ea = estimate(a);
30  if (eb == 0) return b;
31  if (ea == 0) return a;
32  if ((ea > 0 and eb > 0) or (ea < 0 and eb < 0))
33  SOPT_THROW("f(a) = " << ea << " and f(b) = " << eb
34  << " have the wrong sign."
35  "Where a = "
36  << a << " and b = " << b
37  << " Bisection Method not applicable for "
38  "this function.");
39  const auto sign = [&](const K &x) { return (x > 0) ? 1 : ((x < 0) ? -1 : 0); };
40  // SOPT_LOW_LOG("Convergence when: |f((a+b)/2) -f(x)| < {} or |a - b| < {}", rel_convergence,
41  // rel_convergence);
42  while (rel_convergence < relative_difference or
43  std::abs(upper_eta - lower_eta) > rel_convergence) {
44  if (upper_eta == lower_eta) SOPT_THROW("a == b, something is wrong.");
45  eta = (lower_eta + upper_eta) * 0.5;
46  auto const function_est = estimate(eta);
47  if (sign(estimate(lower_eta)) == sign(estimate(eta)))
48  lower_eta = eta;
49  else
50  upper_eta = eta;
51  relative_difference = std::abs(function_est);
52  assert(!(estimate(lower_eta) > 0 and estimate(upper_eta) > 0) and
53  !(estimate(lower_eta) < 0 and estimate(upper_eta) < 0));
54  // SOPT_LOW_LOG("|f(x_0) - f(x)| = {}, x = {}, [{}, {}]", relative_difference, eta, lower_eta,
55  // upper_eta);
56  }
57  return eta;
58 }
59 } // namespace sopt
60 #endif
constexpr Scalar b
constexpr Scalar a
#define SOPT_THROW(MSG)
Definition: exception.h:46
#define SOPT_LOW_LOG(...)
Low priority message.
Definition: logging.h:227
double t_real
Root of the type hierarchy for real numbers.
Definition: types.h:17
std::enable_if< std::is_same< t_real, K >::value, K >::type bisection_method(const K &function_value, const std::function< K(K)> &func, const K &a, const K &b, const t_real &rel_convergence=1e-4)
Find root to a function within an interval.