| 80 | |
| 81 | template <class FunctionType, class StateType> |
| 82 | struct Progress { |
| 83 | using ScalarType = typename FunctionType::ScalarType; |
| 84 | using VectorType = typename FunctionType::VectorType; |
| 85 | using MatrixType = typename FunctionType::MatrixType; |
| 86 | |
| 87 | size_t num_iterations = 0; // Maximum number of allowed iterations. |
| 88 | ScalarType x_delta = ScalarType{0}; // Minimum change in parameter vector. |
| 89 | int x_delta_violations = 0; // Number of violations in pareameter vector. |
| 90 | ScalarType f_delta = ScalarType{0}; // Minimum change in cost function. |
| 91 | int f_delta_violations = 0; // Number of violations in cost function. |
| 92 | // When true, `f_delta` is interpreted as `factr * epsmch` in Fortran |
| 93 | // L-BFGS-B 3.0's `|f_k - f_{k+1}| <= factr * epsmch * max(|f_k|, |
| 94 | // |f_{k+1}|, 1)` convergence test (i.e. a *relative* tolerance scaled |
| 95 | // by the current function magnitude). When false, `f_delta` is an |
| 96 | // absolute threshold. Default false; `Lbfgsb` sets it true in its own |
| 97 | // constructor to match Fortran's convergence test exactly. |
| 98 | bool f_delta_relative = false; |
| 99 | ScalarType gradient_norm = ScalarType{0}; // Minimum norm of gradient vector. |
| 100 | // When true, `gradient_norm` is interpreted as a relative tolerance against |
| 101 | // the current iterate: the solver stops when |
| 102 | // `|g|_inf < gradient_norm * max(1, |x|_inf)`. |
| 103 | // This matches the convergence tests used by Nocedal's Fortran L-BFGS |
| 104 | // (`gnorm/xnorm <= eps`) and libLBFGS (`||g|| < epsilon * max(1, ||x||)`) |
| 105 | // and handles badly-scaled problems where `|x|` is large but the residual |
| 106 | // is already at its floor (e.g. MGH-10 Meyer converges around |
| 107 | // |x| ~ 6e3, |g|_inf ~ 6e-2). When false, `gradient_norm` is an absolute |
| 108 | // threshold, matching LBFGSpp. |
| 109 | bool gradient_norm_relative = true; |
| 110 | ScalarType condition_hessian = |
| 111 | ScalarType{0}; // Maximum condition number of hessian_t. |
| 112 | ScalarType constraint_threshold = |
| 113 | ScalarType{0}; // Minimum norm of constraint violations. |
| 114 | // Outer-loop KKT-stationarity tolerance. The constrained solver |
| 115 | // (`AugmentedLagrangian`) reports `Status::Finished` only when |
| 116 | // primal feasibility AND Lagrangian-gradient stationarity both |
| 117 | // hold; `kkt_stationarity_threshold` is the threshold on the |
| 118 | // measured Lagrangian gradient sup-norm. A non-positive value |
| 119 | // disables the check and falls back to feasibility-only stopping. |
| 120 | // |
| 121 | // The default is deliberately looser than the inner-solver |
| 122 | // `gradient_norm` threshold: the outer-loop Lagrangian gradient |
| 123 | // accumulates roundoff from all constraint evaluations, so a |
| 124 | // Lagrangian gradient at the `1e-6` level is often unattainable |
| 125 | // even when every per-constraint residual is at machine epsilon. |
| 126 | ScalarType kkt_stationarity_threshold = ScalarType{1e-4}; |
| 127 | Status status = Status::NotStarted; // Status of state. |
| 128 | |
| 129 | // Past-delta stopping: stop when the function value has not decreased |
| 130 | // meaningfully over the last `past` iterations. The test fires when |
| 131 | // |f_{k-past} - f_k| / max(1, |f_k|) < past_delta. |
| 132 | // Set `past = 0` to disable (default for backward compatibility). |
| 133 | // LBFGS-Lite uses past=3, delta=1e-6 and this is a major contributor |
| 134 | // to its lower nfev count on well-behaved problems. |
| 135 | int past = 0; |
| 136 | ScalarType past_delta = ScalarType{1e-6}; |
| 137 | |
| 138 | // Ring buffer for the past-delta stopping test (internal state). |
| 139 | std::vector<ScalarType> past_f_ring_; |
nothing calls this directly
no outgoing calls
no test coverage detected