17#ifndef __math_quadratic_line_search_h__
18#define __math_quadratic_line_search_h__
71 template <
typename ValueType>
79 enum return_t {SUCCESS, EXECUTING, OUTSIDE_BOUNDS, NONCONVEX, NONCONVERGING};
82 init_lower (lower_bound),
83 init_mid (0.5 * (lower_bound + upper_bound)),
84 init_upper (upper_bound),
85 value_tolerance (0.001 * (upper_bound - lower_bound)),
86 function_tolerance (0.0),
87 exit_outside_bounds (
true),
92 void set_lower_bound (
const ValueType i) { init_lower = i; }
93 void set_init_estimate (
const ValueType i) { init_mid = i; }
94 void set_upper_bound (
const ValueType i) { init_upper = i; }
95 void set_value_tolerance (
const ValueType i) { value_tolerance = i; }
96 void set_function_tolerance (
const ValueType i) { function_tolerance = i; }
97 void set_exit_if_outside_bounds (
const bool i) { exit_outside_bounds = i; }
98 void set_max_iterations (
const size_t i) { max_iters = i; }
99 void set_message (
const std::string& i) { message = i; }
101 return_t get_status()
const {
return status; }
104 template <
class Functor>
105 ValueType operator() (Functor&
functor)
const
110 std::unique_ptr<ProgressBar> progress (message.size() ?
new ProgressBar (message) :
nullptr);
112 ValueType l = init_lower, m = init_mid, u = init_upper;
117 while (iters++ < max_iters) {
124 if (fm > (fl + ((fu-fl)*(m-l)/(u-l)))) {
125 if ((std::min(m-l, u-m) < value_tolerance) || (
abs((fu-fl)/(0.5*(fu+fl))) < function_tolerance)) {
133 const ValueType sl = (fm-fl) / (m-l);
134 const ValueType su = (fu-fm) / (u-m);
136 const ValueType n = (0.5*(l+m)) - ((sl*(u-l)) / (2.0*(su-sl)));
138 const ValueType fn =
functor (n);
139 if (!std::isfinite(fn))
143 if (exit_outside_bounds) {
144 status = OUTSIDE_BOUNDS;
167 if (exit_outside_bounds) {
168 status = OUTSIDE_BOUNDS;
179 if ((u-l) < value_tolerance) {
186 status = NONCONVERGING;
193 template <
class Functor>
194 ValueType verbose (Functor&
functor)
const
199 ValueType l = init_lower, m = init_mid, u = init_upper;
201 std::cerr <<
"Initialising quadratic line search\n";
202 std::cerr <<
" Lower Mid Upper\n";
203 std::cerr <<
"Pos " <<
str (l) <<
" " <<
str(m) <<
" " <<
str(u) <<
"\n";
204 std::cerr <<
"Value " <<
str (fl) <<
" " <<
str(fm) <<
" " <<
str(fu) <<
"\n";
207 while (iters++ < max_iters) {
209 if (fm > (fl + ((fu-fl)*(m-l)/(u-l)))) {
210 if (std::min(m-l, u-m) < value_tolerance) {
211 std::cerr <<
"Returning due to nonconvexity, through successfully\n";
216 std::cerr <<
"Returning due to nonconvexity, unsuccessfully\n";
220 const ValueType sl = (fm-fl) / (m-l);
221 const ValueType su = (fu-fm) / (u-m);
223 const ValueType n = (0.5*(l+m)) - ((sl*(u-l)) / (2.0*(su-sl)));
225 const ValueType fn =
functor (n);
227 std::cerr <<
" New point " <<
str(n) <<
", value " <<
str(fn) <<
"\n";
230 if (exit_outside_bounds) {
231 status = OUTSIDE_BOUNDS;
254 if (exit_outside_bounds) {
255 status = OUTSIDE_BOUNDS;
264 std::cerr <<
"Pos " <<
str (l) <<
" " <<
str(m) <<
" " <<
str(u) <<
"\n";
265 std::cerr <<
"Value " <<
str (fl) <<
" " <<
str(fm) <<
" " <<
str(fu) <<
"\n";
267 if ((u-l) < value_tolerance) {
269 std::cerr <<
"Returning successfully\n";
275 status = NONCONVERGING;
276 std::cerr <<
"Returning due to too many iterations\n";
283 ValueType init_lower, init_mid, init_upper, value_tolerance, function_tolerance;
284 bool exit_outside_bounds;
288 mutable return_t status;
Computes the minimum of a 1D function using a quadratic line search.
implements a progress meter to provide feedback to the user
constexpr std::enable_if< std::is_arithmetic< X >::value &&std::is_unsigned< X >::value, X >::type abs(X x)
std::string str(const T &value, int precision=0)
constexpr default_type NaN
std::remove_reference< Functor >::type & functor