50 template <
typename NumberType>
51 std::optional<NumberType>
53 const NumberType f_low,
54 const NumberType g_low,
55 const NumberType x_hi,
56 const NumberType f_hi);
67 template <
typename NumberType>
68 std::optional<NumberType>
70 const NumberType f_low,
71 const NumberType g_low,
72 const NumberType x_hi,
73 const NumberType f_hi,
74 const NumberType g_hi);
83 template <
typename NumberType>
84 std::optional<NumberType>
86 const NumberType f_low,
87 const NumberType g_low,
88 const NumberType x_hi,
89 const NumberType f_hi,
90 const NumberType x_rec,
91 const NumberType f_rec);
104 template <
typename NumberType>
107 const NumberType f_low,
108 const NumberType g_low,
109 const NumberType x_hi,
110 const NumberType f_hi,
111 const NumberType g_hi,
115 const std::pair<NumberType, NumberType> bounds);
121 template <
typename NumberType>
124 const NumberType f_low,
125 const NumberType g_low,
126 const NumberType x_hi,
127 const NumberType f_hi,
128 const NumberType g_hi,
132 const std::pair<NumberType, NumberType> bounds);
302 template <
typename NumberType>
303 std::pair<NumberType, unsigned int>
305 const std::function<std::pair<NumberType, NumberType>(
const NumberType x)>
310 NumberType(
const NumberType x_low,
311 const NumberType f_low,
312 const NumberType g_low,
313 const NumberType x_hi,
314 const NumberType f_hi,
315 const NumberType g_hi,
319 const std::pair<NumberType, NumberType> bounds)> &interpolate,
321 const NumberType eta = 0.9,
322 const NumberType mu = 0.01,
323 const NumberType a_max = std::numeric_limits<NumberType>::max(),
324 const unsigned int max_evaluations = 20,
325 const bool debug_output =
false);
334 template <
typename NumberType>
335 std::optional<NumberType>
343 const NumberType denom = (2. * g1 * x2 - 2. * g1 * x1 - 2. * f2 + 2. * f1);
347 return (g1 * (x2 * x2 - x1 * x1) + 2. * (f1 - f2) * x1) / denom;
352 template <
typename NumberType>
353 std::optional<NumberType>
362 const NumberType beta1 = g1 + g2 - 3. * (f1 - f2) / (x1 - x2);
363 const NumberType s = beta1 * beta1 - g1 * g2;
368 const NumberType denom =
369 x1 < x2 ? g2 - g1 + 2. * beta2 : g1 - g2 + 2. * beta2;
373 return x1 < x2 ? x2 - (x2 - x1) * (g2 + beta2 - beta1) / denom :
374 x1 - (x1 - x2) * (g1 + beta2 - beta1) / denom;
379 template <
typename NumberType>
380 std::optional<NumberType>
398 const NumberType x2_shift = x2 - x1;
399 const NumberType x3_shift = x3 - x1;
400 const NumberType r1 = f2 - f1 - g1 * x2_shift;
401 const NumberType r2 = f3 - f1 - g1 * x3_shift;
402 const NumberType denom =
403 Utilities::fixed_power<2>(x2_shift * x3_shift) * (x2_shift - x3_shift);
407 const NumberType A = (r1 * Utilities::fixed_power<2>(x3_shift) -
408 r2 * Utilities::fixed_power<2>(x2_shift)) /
410 const NumberType B = (r2 * Utilities::fixed_power<3>(x2_shift) -
411 r1 * Utilities::fixed_power<3>(x3_shift)) /
413 const NumberType &
C = g1;
416 const NumberType radical = B * B - A *
C * 3;
420 return x1 + (-B +
std::sqrt(radical)) / (A * 3);
425 template <
typename NumberType>
436 const std::pair<NumberType, NumberType> bounds)
445 std::optional<NumberType> res =
cubic_fit(x1, f1, g1, x2, f2, g2);
446 if (res && *res >= bounds.first && *res <= bounds.second)
451 if (res && *res >= bounds.first && *res <= bounds.second)
456 return (bounds.first + bounds.second) * 0.5;
461 template <
typename NumberType>
472 const std::pair<NumberType, NumberType> bounds)
481 std::optional<NumberType> res =
484 std::optional<NumberType>{};
485 if (res && *res >= bounds.first && *res <= bounds.second)
490 if (res && *res >= bounds.first && *res <= bounds.second)
495 return (bounds.first + bounds.second) * 0.5;
500 template <
typename NumberType>
501 std::pair<NumberType, unsigned int>
503 const std::function<std::pair<NumberType, NumberType>(
const NumberType x)>
508 NumberType(
const NumberType x_low,
509 const NumberType f_low,
510 const NumberType g_low,
511 const NumberType x_hi,
512 const NumberType f_hi,
513 const NumberType g_hi,
517 const std::pair<NumberType, NumberType> bounds)> &choose,
519 const NumberType eta,
521 const NumberType a_max,
522 const unsigned int max_evaluations,
523 const bool debug_output)
534 const NumberType tau1 = 9.;
539 const NumberType tau2 = 0.1;
540 const NumberType tau3 = 0.5;
542 const NumberType g0_abs =
std::abs(g0);
543 const NumberType f_min = f0 + a_max * mu * g0;
547 const auto w1 = [&](
const NumberType a,
const NumberType f) {
548 return f <= f0 + a * mu * g0;
553 const auto w2 = [&](
const NumberType g) {
560 const NumberType x = std::numeric_limits<NumberType>::signaling_NaN();
561 NumberType a_lo = x, f_lo = x, g_lo = x;
562 NumberType a_hi = x, f_hi = x, g_hi = x;
563 NumberType ai = x, fi = x, gi = x;
568 NumberType f_prev, g_prev, a_prev;
574 while (i < max_evaluations)
576 const auto fgi = func(ai);
582 deallog <<
"Bracketing phase: " << i << std::endl
583 << ai <<
' ' << fi <<
' ' << gi <<
' ' << w1(ai, fi) <<
' '
584 << w2(gi) <<
' ' << f_min << std::endl;
587 if (fi <= f_min || ai == a_max)
590 deallog <<
"Reached the maximum step size." << std::endl;
591 return std::make_pair(ai, i);
595 (fi >= f_prev && i > 1))
610 deallog <<
"Satisfied both Wolfe conditions during Bracketing."
614 return std::make_pair(ai, i);
631 std::make_pair(2. * ai - a_prev,
632 std::min(a_max, ai + tau1 * (ai - a_prev)));
649 "Could not find the initial bracket within the given number of iterations."));
666 if (
std::abs(a_lo) > std::numeric_limits<NumberType>::epsilon() &&
667 std::abs(a_hi) > std::numeric_limits<NumberType>::epsilon())
675 while (i < max_evaluations)
677 const NumberType a_lo_safe = a_lo + tau2 * (a_hi - a_lo);
678 const NumberType a_hi_safe = a_hi - tau3 * (a_hi - a_lo);
679 const auto bounds = std::minmax(a_lo_safe, a_hi_safe);
682 a_lo, f_lo, g_lo, a_hi, f_hi, g_hi, a_rec, f_rec, g_rec, bounds);
684 const std::pair<NumberType, NumberType> fgi = func(ai);
690 deallog <<
"Sectioning phase: " << i << std::endl
691 << a_lo <<
' ' << f_lo <<
' ' << g_lo <<
' ' << w1(a_lo, f_lo)
692 <<
' ' << w2(g_lo) << std::endl
693 << a_hi <<
' ' << f_hi <<
' ' << g_hi <<
' ' << w1(a_hi, f_hi)
694 <<
' ' << w2(g_hi) << std::endl
695 << ai <<
' ' << fi <<
' ' << gi <<
' ' << w1(ai, fi) <<
' '
696 << w2(gi) << std::endl;
698 if (!w1(ai, fi) || fi >= f_lo)
714 deallog <<
"Satisfied both Wolfe conditions." << std::endl;
716 return std::make_pair(ai, i);
719 if (gi * (a_hi - a_lo) >= 0)
748 "Could not could complete the sectioning phase within the given number of iterations."));
749 return std::make_pair(std::numeric_limits<NumberType>::signaling_NaN(), i);
std::pair< NumberType, unsigned int > line_search(const std::function< std::pair< NumberType, NumberType >(const NumberType x)> &func, const NumberType f0, const NumberType g0, const std::function< NumberType(const NumberType x_low, const NumberType f_low, const NumberType g_low, const NumberType x_hi, const NumberType f_hi, const NumberType g_hi, const FiniteSizeHistory< NumberType > &x_rec, const FiniteSizeHistory< NumberType > &f_rec, const FiniteSizeHistory< NumberType > &g_rec, const std::pair< NumberType, NumberType > bounds)> &interpolate, const NumberType a1, const NumberType eta=0.9, const NumberType mu=0.01, const NumberType a_max=std::numeric_limits< NumberType >::max(), const unsigned int max_evaluations=20, const bool debug_output=false)