17 if (not std::isfinite(yᵀs))
28 bool cbfgs_cond = a_yᵀs >= sᵀs * ϵ * std::pow(pᵀp, α / 2);
38 real_t pₙₑₓₜᵀpₙₑₓₜ,
bool forced) {
42 real_t sᵀs = s.squaredNorm();
43 if (not update_valid(params, yᵀs, sᵀs, pₙₑₓₜᵀpₙₑₓₜ))
61 return update_sy_impl(s, y, pₙₑₓₜᵀpₙₑₓₜ, forced);
66 Sign sign,
bool forced) {
67 const auto s = xₙₑₓₜ - xₖ;
68 const auto y = (sign == Sign::Positive) ? pₙₑₓₜ - pₖ : pₖ - pₙₑₓₜ;
69 real_t pₙₑₓₜᵀpₙₑₓₜ = params.cbfgs ? pₙₑₓₜ.squaredNorm() : 0;
70 return update_sy_impl(s, y, pₙₑₓₜᵀpₙₑₓₜ, forced);
76 if (idx == 0 && not full)
81 auto new_idx = pred(idx);
82 real_t yᵀy = y(new_idx).squaredNorm();
83 γ = 1 / (ρ(new_idx) * yᵀy);
87 α(i) = ρ(i) * s(i).dot(q);
95 real_t β = ρ(i) * y(i).dot(q);
96 q -= (β - α(i)) * s(i);
102template <Config Conf>
105 if (idx == 0 && not full)
107 const bool fullJ = q.size() ==
static_cast<index_t>(J.size());
114 throw std::invalid_argument(
"CBFGS check not supported when using "
115 "masked version of LBFGS::apply_masked()");
125 const auto dotJ = [&J, fullJ](
const auto &a,
const auto &b) {
136 const auto axmyJ = [&J, fullJ](
real_t a,
const auto &x,
auto &y) {
145 const auto scalJ = [&J, fullJ](
real_t a,
auto &x) {
159 real_t sᵀs = dotJ(s(i), s(i));
162 if (not update_valid(params, yᵀs, sᵀs, 0)) {
163 ρ(i) = NaN<config_t>;
167 α(i) = ρ(i) * dotJ(s(i), q);
168 axmyJ(α(i), y(i), q);
172 real_t yᵀy = dotJ(y(i), y(i));
173 γ = 1 / (ρ(i) * yᵀy);
185 if (std::isnan(ρ(i)))
188 real_t β = ρ(i) * dotJ(y(i), q);
189 axmyJ(β - α(i), s(i), q);
195template <Config Conf>
197 return apply_masked_impl(q, γ, J);
200template <Config Conf>
202 const std::vector<index_t> &J)
const {
203 return apply_masked_impl(q, γ, J);
206template <Config Conf>
212template <Config Conf>
214 if (params.memory < 1)
215 throw std::invalid_argument(
"LBFGS::Params::memory must be >= 1");
216 sto.resize(n, params.memory);
220template <Config Conf>
222 sto.resize(n + 1, history * 2);
225template <Config Conf>
228 for (
index_t i = 0; i < history(); ++i) {
233 for (
index_t i = 0; i < idx; ++i) {
bool apply_masked(rvec q, real_t γ, crindexvec J) const
Apply the inverse Hessian approximation to the given vector q, applying only the columns and rows of ...
bool update_sy(crvec s, crvec y, real_t pₙₑₓₜᵀpₙₑₓₜ, bool forced=false)
Update the inverse Hessian approximation using the new vectors sₖ = xₙₑₓₜ - xₖ and yₖ = pₙₑₓₜ - pₖ.
static bool update_valid(const Params ¶ms, real_t yᵀs, real_t sᵀs, real_t pᵀp)
Check if the new vectors s and y allow for a valid BFGS update that preserves the positive definitene...
bool apply_masked_impl(rvec q, real_t γ, const auto &J) const
Apply the inverse Hessian approximation to the given vector q, applying only the columns and rows of ...
void resize(length_t n)
Re-allocate storage for a problem with a different size.
void reset()
Throw away the approximation and all previous vectors s and y.
bool update_sy_impl(const auto &s, const auto &y, real_t pₙₑₓₜᵀpₙₑₓₜ, bool forced=false)
Sign
The sign of the vectors passed to the update method.
bool apply(rvec q, real_t γ=-1) const
Apply the inverse Hessian approximation to the given vector q.
void scale_y(real_t factor)
Scale the stored y vectors by the given factor.
bool update(crvec xₖ, crvec xₙₑₓₜ, crvec pₖ, crvec pₙₑₓₜ, Sign sign=Sign::Positive, bool forced=false)
Update the inverse Hessian approximation using the new vectors xₙₑₓₜ and pₙₑₓₜ.
real_t min_abs_s
Reject update if .
CBFGSParams< config_t > cbfgs
Parameters in the cautious BFGS update condition.
bool force_pos_def
If set to true, the inverse Hessian estimate should remain definite, i.e.
typename Conf::real_t real_t
typename Conf::index_t index_t
typename Conf::length_t length_t
typename Conf::crvec crvec
real_t min_div_fac
Reject update if .
@ BasedOnCurvature
Initial inverse Hessian approximation is set to .
typename Conf::crindexvec crindexvec
real_t ϵ
Set to zero to disable CBFGS check.
void resize(length_t n, length_t history)
Re-allocate storage for a problem with a different size.