14 throw std::invalid_argument(
15 "Structured L-BFGS requires eval_inactive_indices_res_lna()");
16 if (direction_params.hessian_vec_factor != 0 &&
17 !direction_params.hessian_vec_finite_differences &&
18 !direction_params.full_augmented_hessian &&
20 throw std::invalid_argument(
21 "Structured L-BFGS requires eval_hess_L_prod(). Alternatively, set "
22 "hessian_vec_factor = 0 or hessian_vec_finite_differences = true.");
23 if (direction_params.hessian_vec_factor != 0 &&
24 !direction_params.hessian_vec_finite_differences &&
25 direction_params.full_augmented_hessian &&
28 throw std::invalid_argument(
29 "Structured L-BFGS requires _eval_hess_ψ_prod() or "
30 "eval_hess_L_prod(). Alternatively, set "
31 "hessian_vec_factor = 0 or hessian_vec_finite_differences = true.");
32 if (direction_params.hessian_vec_factor != 0 &&
33 !direction_params.hessian_vec_finite_differences &&
34 direction_params.full_augmented_hessian &&
37 throw std::invalid_argument(
38 "Structured L-BFGS requires either eval_hess_ψ_prod() or "
39 "get_box_D() and eval_grad_gi(). Alternatively, set "
40 "hessian_vec_factor = 0, hessian_vec_finite_differences = true, or "
41 "full_augmented_hessian = false.");
43 this->problem = &problem;
47 const auto n = problem.
get_n();
48 const auto m = problem.
get_m();
52 if (direction_params.hessian_vec_finite_differences) {
56 }
else if (direction_params.full_augmented_hessian) {
66 const auto n = problem->get_n();
69 auto nJ = problem->eval_inactive_indices_res_lna(
γₖ,
xₖ,
grad_ψxₖ, J_sto);
70 auto J = J_sto.topRows(nJ);
81 return lbfgs.apply(
qₖ,
γₖ);
85 if (direction_params.hessian_vec_factor != 0) {
90 direction_params.hessian_vec_factor * HqK(
J);
96 bool success = lbfgs.apply_masked(
qₖ,
γₖ,
J);
104 switch (direction_params.failure_policy) {
105 case DirectionParams::FallbackToProjectedGradient:
return success;
106 case DirectionParams::UseScaledLBFGSInput:
112 default:
return false;
116template <Config Conf>
119 const auto m = problem->get_m();
121 if (direction_params.hessian_vec_finite_differences) {
122 Helpers::calc_augmented_lagrangian_hessian_prod_fd(
123 *problem,
xₖ, *y, *Σ,
grad_ψxₖ,
qₖ, HqK, work_n, work_n2, work_m);
127 if (!direction_params.full_augmented_hessian) {
129 problem->eval_hess_L_prod(
xₖ, *y, 1,
qₖ, HqK);
131 if (problem->provides_eval_hess_ψ_prod()) {
134 problem->eval_hess_ψ_prod(
xₖ, *y, *Σ, 1,
qₖ, HqK);
137 problem->eval_hess_L_prod(
xₖ, *y, 1,
qₖ, HqK);
140 if (direction_params.full_augmented_hessian) {
141 assert(m == 0 || problem->provides_eval_grad_gi());
142 const auto &D = problem->get_box_D();
144 problem->eval_g(
xₖ, g);
145 for (
index_t i = 0; i < m; ++i) {
146 real_t ζ = g(i) + (*y)(i) / (*Σ)(i);
148 D.lowerbound(i) <
ζ &&
ζ < D.upperbound(i);
150 problem->eval_grad_gi(
xₖ, i, work_n);
151 auto t = (*Σ)(i)*work_n.dot(
qₖ);
155 HqK(
j) += work_n(
j) * t;
bool provides_eval_hess_ψ_prod() const
Returns true if the problem provides an implementation of eval_hess_ψ_prod.
length_t get_n() const
[Required] Number of decision variables.
length_t get_m() const
[Required] Number of constraints.
bool provides_eval_inactive_indices_res_lna() const
Returns true if the problem provides an implementation of eval_inactive_indices_res_lna.
bool provides_eval_hess_L_prod() const
Returns true if the problem provides an implementation of eval_hess_L_prod.
bool provides_eval_grad_gi() const
Returns true if the problem provides an implementation of eval_grad_gi.
bool provides_get_box_D() const
Returns true if the problem provides an implementation of get_box_D.
typename Conf::real_t real_t
typename Conf::index_t index_t
typename Conf::crvec crvec
typename Conf::crindexvec crindexvec
void initialize(const Problem &problem, crvec y, crvec Σ, real_t γ_0, crvec x_0, crvec x̂_0, crvec p_0, crvec grad_ψx_0)
void approximate_hessian_vec_term(crvec xₖ, crvec grad_ψxₖ, rvec qₖ, crindexvec J) const
bool apply(real_t γₖ, crvec xₖ, crvec x̂ₖ, crvec pₖ, crvec grad_ψxₖ, rvec qₖ) const