|
7 | 7 | #include "linear_algebra/LAPACK.hpp" |
8 | 8 | #include "linear_algebra/SymmetricMatrix.hpp" |
9 | 9 | #include "optimization/Iterate.hpp" |
| 10 | +#include "optimization/OptimizationProblem.hpp" |
10 | 11 | #include "symbolic/Expression.hpp" |
11 | 12 | #include "symbolic/Range.hpp" |
12 | 13 | #include "tools/Statistics.hpp" |
13 | 14 |
|
14 | 15 | namespace uno { |
15 | | - LBFGSHessian::LBFGSHessian(std::optional<double> fixed_objective_multiplier, const Options& options): |
| 16 | + LBFGSHessian::LBFGSHessian(double objective_multiplier, const Options& options): |
16 | 17 | HessianModel(), |
17 | | - fixed_objective_multiplier(fixed_objective_multiplier), |
| 18 | + objective_multiplier(objective_multiplier), |
18 | 19 | memory_size(options.get_unsigned_int("quasi_newton_memory_size")) { |
19 | | - if (fixed_objective_multiplier.has_value()) { |
20 | | - DEBUG << "L-BFGS Hessian model was declared with a fixed objective multiplier of " << *fixed_objective_multiplier << '\n'; |
21 | | - } |
22 | 20 | } |
23 | 21 |
|
24 | 22 | bool LBFGSHessian::has_implicit_representation() const { |
@@ -67,8 +65,11 @@ namespace uno { |
67 | 65 |
|
68 | 66 | // Hessian-vector product where the Hessian approximation is Bk = B0 - U U^T + V V^T and B0 = delta I |
69 | 67 | // Bk v = (B0 - U U^T + V V^T) v = delta v - U U^T x + V V^T x |
70 | | - void LBFGSHessian::compute_hessian_vector_product(const Model& model, const double* vector, double /*objective_multiplier*/, |
| 68 | + void LBFGSHessian::compute_hessian_vector_product(const Model& model, const double* vector, double objective_multiplier, |
71 | 69 | const Vector<double>& /*constraint_multipliers*/, double* result) { |
| 70 | + assert(objective_multiplier == this->objective_multiplier && |
| 71 | + "The L-BFGS Hessian model was initialized with a different objective multiplier"); |
| 72 | + |
72 | 73 | if (this->hessian_recomputation_required) { |
73 | 74 | this->recompute_hessian_representation(); |
74 | 75 | this->hessian_recomputation_required = false; |
@@ -136,23 +137,21 @@ namespace uno { |
136 | 137 | // fill the Y matrix: y = \nabla L(x_k, y_k, z_k) - \nabla L(x_{k-1}, y_k, z_k) |
137 | 138 | void LBFGSHessian::update_Y_matrix(const Model& model, Iterate& current_iterate, Iterate& trial_iterate) { |
138 | 139 | // evaluate Lagrangian gradients at the current and trial iterates, both with the trial multipliers |
139 | | - // TODO objective multiplier is hardcoded for the moment |
140 | | - if (this->fixed_objective_multiplier.has_value()) { |
141 | | - current_iterate.evaluate_objective_gradient(model); |
142 | | - current_iterate.evaluate_constraint_jacobian(model); |
143 | | - trial_iterate.evaluate_objective_gradient(model); |
144 | | - trial_iterate.evaluate_constraint_jacobian(model); |
145 | | - // TODO preallocate |
146 | | - Vector<double> current_lagrangian_gradient(this->dimension); |
147 | | - Vector<double> trial_lagrangian_gradient(this->dimension); |
148 | | - const double objective_multiplier = *this->fixed_objective_multiplier; |
149 | | - model.evaluate_lagrangian_gradient(current_lagrangian_gradient, current_iterate, trial_iterate.multipliers, objective_multiplier); |
150 | | - model.evaluate_lagrangian_gradient(trial_lagrangian_gradient, trial_iterate, trial_iterate.multipliers, objective_multiplier); |
151 | | - this->Y_matrix.column(this->current_memory_slot) = trial_lagrangian_gradient - current_lagrangian_gradient; |
152 | | - } |
153 | | - else { |
154 | | - throw std::runtime_error("LBFGSHessian::update_Y_matrix: the objective multiplier varies. This is not implemented yet"); |
155 | | - } |
| 140 | + current_iterate.evaluate_objective_gradient(model); |
| 141 | + current_iterate.evaluate_constraint_jacobian(model); |
| 142 | + trial_iterate.evaluate_objective_gradient(model); |
| 143 | + trial_iterate.evaluate_constraint_jacobian(model); |
| 144 | + // TODO preallocate |
| 145 | + LagrangianGradient<double> current_split_lagrangian_gradient(this->dimension); |
| 146 | + LagrangianGradient<double> trial_split_lagrangian_gradient(this->dimension); |
| 147 | + const OptimizationProblem problem{model}; |
| 148 | + problem.evaluate_lagrangian_gradient(current_split_lagrangian_gradient, current_iterate, trial_iterate.multipliers); |
| 149 | + problem.evaluate_lagrangian_gradient(trial_split_lagrangian_gradient, trial_iterate, trial_iterate.multipliers); |
| 150 | + const auto current_lagrangian_gradient = this->objective_multiplier * current_split_lagrangian_gradient.objective_contribution |
| 151 | + + current_split_lagrangian_gradient.constraints_contribution; |
| 152 | + const auto trial_lagrangian_gradient = this->objective_multiplier * trial_split_lagrangian_gradient.objective_contribution |
| 153 | + + trial_split_lagrangian_gradient.constraints_contribution; |
| 154 | + this->Y_matrix.column(this->current_memory_slot) = trial_lagrangian_gradient - current_lagrangian_gradient; |
156 | 155 | } |
157 | 156 |
|
158 | 157 | void LBFGSHessian::update_D_matrix() { |
|
0 commit comments