215 const Vector& xp,
const Vector& drt,
const Scalar& step_max,
216 Scalar& step, Scalar& fx, Vector& grad, Scalar& dg, Vector& x)
360 const Scalar step_min = param.min_step;
361 if (step <= Scalar(0))
362 throw std::invalid_argument(
"'step' must be positive");
364 throw std::invalid_argument(
"'step' is smaller than 'param.min_step'");
366 throw std::invalid_argument(
"'step' exceeds 'step_max'");
369 const Scalar fx_init = fx;
371 const Scalar dg_init = dg;
376 if (dg_init >= Scalar(0))
377 throw std::logic_error(
"the moving direction does not decrease the objective function value");
381 const Scalar test_decr = param.ftol * dg_init;
383 const Scalar test_curv = -param.wolfe * dg_init;
386 const Scalar Inf = std::numeric_limits<Scalar>::infinity();
387 Scalar I_lo = Scalar(0), I_hi = Inf;
388 Scalar fI_lo = Scalar(0), fI_hi = Inf;
389 Scalar gI_lo = (Scalar(1) - param.ftol) * dg_init, gI_hi = Inf;
390 Scalar psiI_lo = fI_lo;
393 Vector x_lo = xp, grad_lo = grad;
394 Scalar fx_lo = fx_init, dg_lo = dg_init;
397 bool bracketed =
false;
398 bool f_is_psi =
true;
399 bool use_step_min_safeguard = (step_min > Scalar(0));
400 Scalar I_width = Inf;
401 Scalar I_width_prev = Inf;
402 int I_shrink_fail_count = 0;
405 const Scalar delta_max = Scalar(1.1);
406 const Scalar delta_min = Scalar(7) / Scalar(12);
407 const Scalar shrink = Scalar(0.66);
409 for (iter = 0; iter < param.max_linesearch; iter++)
412 x.noalias() = xp + step * drt;
422 const Scalar psit = fx - fx_init - step * test_decr;
423 const Scalar dpsit = dg - test_decr;
428 if (psit <= Scalar(0) && abs(dg) <= test_curv)
436 if (step <= step_min && (psit > Scalar(0) || dpsit >= Scalar(0)))
442 if (step >= step_max && (psit <= Scalar(0) && dpsit < Scalar(0)))
461 const Scalar ft = f_is_psi ? psit : fx;
462 const Scalar gt = f_is_psi ? dpsit : dg;
468 if (use_step_min_safeguard && (psit <= Scalar(0) && dpsit < Scalar(0)))
470 use_step_min_safeguard =
false;
475 const bool in_case_2 = (psit <= psiI_lo) && (dpsit * (I_lo - step) > Scalar(0));
480 new_step = (std::min)(step_max, step + delta_max * (step - I_lo));
496 new_step = step_selection(I_lo, I_hi, step, fI_lo, fI_hi, ft, gI_lo, gI_hi, gt);
498 new_step = (std::max)(new_step, step_min);
499 new_step = (std::min)(new_step, step_max);
507 if (use_step_min_safeguard)
509 const Scalar lower = step_min;
510 const Scalar upper = (std::max)(step_min, delta_min * step);
511 new_step = (std::max)(new_step, lower);
512 new_step = (std::min)(new_step, upper);
564 if ((!bracketed) && (!in_case_2))
566 const Scalar I_left = (std::min)(I_lo, I_hi);
567 const Scalar I_right = (std::max)(I_lo, I_hi);
568 bracketed = (I_left >= step_min && I_right <= step_max);
574 I_width_prev = I_width;
575 I_width = abs(I_hi - I_lo);
577 if (I_width_prev < Inf && I_width > shrink * I_width_prev)
579 I_shrink_fail_count += 1;
583 I_shrink_fail_count = 0;
586 if (I_shrink_fail_count >= 2)
588 new_step = (I_lo + I_hi) / Scalar(2);
589 I_shrink_fail_count = 0;
602 if (iter >= param.max_linesearch)
604 std::cout <<
"** Maximum step size reached\n\n";