From b78271d271c8688e32479f0764bb2e23b12882fd Mon Sep 17 00:00:00 2001 From: Charlie Vanaret Date: Tue, 12 Nov 2024 11:59:04 +0100 Subject: [PATCH] Passed warmstart object around to properly handle the warmstart information --- .../ConstraintRelaxationStrategy.hpp | 2 +- .../FeasibilityRestoration.cpp | 19 +++++++------ .../FeasibilityRestoration.hpp | 2 +- .../l1Relaxation.cpp | 3 +- .../l1Relaxation.hpp | 2 +- .../BacktrackingLineSearch.cpp | 11 ++++---- .../BacktrackingLineSearch.hpp | 3 +- .../GlobalizationMechanism.hpp | 4 ++- .../TrustRegionStrategy.cpp | 14 ++++------ .../TrustRegionStrategy.hpp | 3 +- uno/optimization/WarmstartInformation.cpp | 28 +++++++------------ uno/optimization/WarmstartInformation.hpp | 7 ++--- 12 files changed, 47 insertions(+), 51 deletions(-) diff --git a/uno/ingredients/constraint_relaxation_strategies/ConstraintRelaxationStrategy.hpp b/uno/ingredients/constraint_relaxation_strategies/ConstraintRelaxationStrategy.hpp index 41c5a1ad..3c2d1eb5 100644 --- a/uno/ingredients/constraint_relaxation_strategies/ConstraintRelaxationStrategy.hpp +++ b/uno/ingredients/constraint_relaxation_strategies/ConstraintRelaxationStrategy.hpp @@ -46,7 +46,7 @@ namespace uno { void compute_feasible_direction(Statistics& statistics, Iterate& current_iterate, Direction& direction, const Vector& initial_point, WarmstartInformation& warmstart_information); [[nodiscard]] virtual bool solving_feasibility_problem() const = 0; - virtual void switch_to_feasibility_problem(Statistics& statistics, Iterate& current_iterate) = 0; + virtual void switch_to_feasibility_problem(Statistics& statistics, Iterate& current_iterate, WarmstartInformation& warmstart_information) = 0; // trial iterate acceptance [[nodiscard]] virtual bool is_iterate_acceptable(Statistics& statistics, Iterate& current_iterate, Iterate& trial_iterate, const Direction& direction, diff --git a/uno/ingredients/constraint_relaxation_strategies/FeasibilityRestoration.cpp b/uno/ingredients/constraint_relaxation_strategies/FeasibilityRestoration.cpp index 7633dcfc..01bd0529 100644 --- a/uno/ingredients/constraint_relaxation_strategies/FeasibilityRestoration.cpp +++ b/uno/ingredients/constraint_relaxation_strategies/FeasibilityRestoration.cpp @@ -71,17 +71,16 @@ namespace uno { // switch to the feasibility problem, starting from the current direction statistics.set("status", "infeas. subproblem"); DEBUG << "/!\\ The subproblem is infeasible\n"; - this->switch_to_feasibility_problem(statistics, current_iterate); - warmstart_information.set_cold_start(); + this->switch_to_feasibility_problem(statistics, current_iterate, warmstart_information); this->subproblem->set_initial_point(direction.primals); } else { + warmstart_information.no_changes(); return; } } catch (const UnstableRegularization&) { - this->switch_to_feasibility_problem(statistics, current_iterate); - warmstart_information.set_cold_start(); + this->switch_to_feasibility_problem(statistics, current_iterate, warmstart_information); } } @@ -99,7 +98,8 @@ namespace uno { } // precondition: this->current_phase == Phase::OPTIMALITY - void FeasibilityRestoration::switch_to_feasibility_problem(Statistics& statistics, Iterate& current_iterate) { + void FeasibilityRestoration::switch_to_feasibility_problem(Statistics& statistics, Iterate& current_iterate, + WarmstartInformation& warmstart_information) { DEBUG << "Switching from optimality to restoration phase\n"; this->current_phase = Phase::FEASIBILITY_RESTORATION; this->globalization_strategy->notify_switch_to_feasibility(current_iterate.progress); @@ -114,6 +114,7 @@ namespace uno { DEBUG2 << "Current iterate:\n" << current_iterate << '\n'; if (Logger::level == INFO) statistics.print_current_line(); + warmstart_information.whole_problem_changed(); } void FeasibilityRestoration::solve_subproblem(Statistics& statistics, const OptimizationProblem& problem, Iterate& current_iterate, @@ -142,7 +143,7 @@ namespace uno { this->subproblem->exit_feasibility_problem(this->optimality_problem, trial_iterate); // set a cold start in the subproblem solver - warmstart_information.set_cold_start(); + warmstart_information.whole_problem_changed(); } bool FeasibilityRestoration::is_iterate_acceptable(Statistics& statistics, Iterate& current_iterate, Iterate& trial_iterate, const Direction& direction, @@ -156,6 +157,9 @@ namespace uno { if (this->current_phase == Phase::FEASIBILITY_RESTORATION && this->can_switch_to_optimality_phase(current_iterate, trial_iterate, direction, step_length)) { this->switch_to_optimality_phase(current_iterate, trial_iterate, warmstart_information); } + else { + warmstart_information.no_changes(); + } bool accept_iterate = false; if (direction.norm == 0.) { @@ -170,9 +174,6 @@ namespace uno { accept_iterate = this->globalization_strategy->is_iterate_acceptable(statistics, current_iterate.progress, trial_iterate.progress, predicted_reduction, this->current_problem().get_objective_multiplier()); } - if (accept_iterate) { - // this->set_dual_residuals_statistics(statistics, trial_iterate); - } ConstraintRelaxationStrategy::set_progress_statistics(statistics, trial_iterate); return accept_iterate; } diff --git a/uno/ingredients/constraint_relaxation_strategies/FeasibilityRestoration.hpp b/uno/ingredients/constraint_relaxation_strategies/FeasibilityRestoration.hpp index 7cc2dc94..1a4381b7 100644 --- a/uno/ingredients/constraint_relaxation_strategies/FeasibilityRestoration.hpp +++ b/uno/ingredients/constraint_relaxation_strategies/FeasibilityRestoration.hpp @@ -25,7 +25,7 @@ namespace uno { // direction computation void compute_feasible_direction(Statistics& statistics, Iterate& current_iterate, Direction& direction, WarmstartInformation& warmstart_information) override; [[nodiscard]] bool solving_feasibility_problem() const override; - void switch_to_feasibility_problem(Statistics& statistics, Iterate& current_iterate) override; + void switch_to_feasibility_problem(Statistics& statistics, Iterate& current_iterate, WarmstartInformation& warmstart_information) override; // trial iterate acceptance [[nodiscard]] bool is_iterate_acceptable(Statistics& statistics, Iterate& current_iterate, Iterate& trial_iterate, const Direction& direction, diff --git a/uno/ingredients/constraint_relaxation_strategies/l1Relaxation.cpp b/uno/ingredients/constraint_relaxation_strategies/l1Relaxation.cpp index 6ac3c6b2..4bf09bed 100644 --- a/uno/ingredients/constraint_relaxation_strategies/l1Relaxation.cpp +++ b/uno/ingredients/constraint_relaxation_strategies/l1Relaxation.cpp @@ -79,7 +79,8 @@ namespace uno { return (this->penalty_parameter == 0.); } - void l1Relaxation::switch_to_feasibility_problem(Statistics& /*statistics*/, Iterate& /*current_iterate*/) { + void l1Relaxation::switch_to_feasibility_problem(Statistics& /*statistics*/, Iterate& /*current_iterate*/, + WarmstartInformation& /*warmstart_information*/) { throw std::runtime_error("l1Relaxation::switch_to_feasibility_problem is not implemented"); } diff --git a/uno/ingredients/constraint_relaxation_strategies/l1Relaxation.hpp b/uno/ingredients/constraint_relaxation_strategies/l1Relaxation.hpp index 0057001e..805a6bbc 100644 --- a/uno/ingredients/constraint_relaxation_strategies/l1Relaxation.hpp +++ b/uno/ingredients/constraint_relaxation_strategies/l1Relaxation.hpp @@ -32,7 +32,7 @@ namespace uno { void compute_feasible_direction(Statistics& statistics, Iterate& current_iterate, Direction& direction, WarmstartInformation& warmstart_information) override; [[nodiscard]] bool solving_feasibility_problem() const override; - void switch_to_feasibility_problem(Statistics& statistics, Iterate& current_iterate) override; + void switch_to_feasibility_problem(Statistics& statistics, Iterate& current_iterate, WarmstartInformation& warmstart_information) override; // trial iterate acceptance [[nodiscard]] bool is_iterate_acceptable(Statistics& statistics, Iterate& current_iterate, Iterate& trial_iterate, const Direction& direction, diff --git a/uno/ingredients/globalization_mechanisms/BacktrackingLineSearch.cpp b/uno/ingredients/globalization_mechanisms/BacktrackingLineSearch.cpp index 971fecb4..15d358f4 100644 --- a/uno/ingredients/globalization_mechanisms/BacktrackingLineSearch.cpp +++ b/uno/ingredients/globalization_mechanisms/BacktrackingLineSearch.cpp @@ -30,9 +30,8 @@ namespace uno { this->constraint_relaxation_strategy.initialize(statistics, initial_iterate, options); } - void BacktrackingLineSearch::compute_next_iterate(Statistics& statistics, const Model& model, Iterate& current_iterate, Iterate& trial_iterate) { - WarmstartInformation warmstart_information{}; - warmstart_information.set_hot_start(); + void BacktrackingLineSearch::compute_next_iterate(Statistics& statistics, const Model& model, Iterate& current_iterate, Iterate& trial_iterate, + WarmstartInformation& warmstart_information) { DEBUG2 << "Current iterate\n" << current_iterate << '\n'; this->constraint_relaxation_strategy.compute_feasible_direction(statistics, current_iterate, this->direction, warmstart_information); @@ -59,6 +58,9 @@ namespace uno { // scale or not the constraint dual direction with the LS step length this->scale_duals_with_step_length ? step_length : 1.); + // let the constraint relaxation strategy determine which quantities change + warmstart_information.no_changes(); + is_acceptable = this->constraint_relaxation_strategy.is_iterate_acceptable(statistics, current_iterate, trial_iterate, this->direction, step_length, warmstart_information); this->set_statistics(statistics, trial_iterate, this->direction, step_length, number_iterations); @@ -89,8 +91,7 @@ namespace uno { } // switch to solving the feasibility problem statistics.set("status", "small LS step length"); - this->constraint_relaxation_strategy.switch_to_feasibility_problem(statistics, current_iterate); - warmstart_information.set_cold_start(); + this->constraint_relaxation_strategy.switch_to_feasibility_problem(statistics, current_iterate, warmstart_information); this->constraint_relaxation_strategy.compute_feasible_direction(statistics, current_iterate, this->direction, this->direction.primals, warmstart_information); BacktrackingLineSearch::check_unboundedness(this->direction); diff --git a/uno/ingredients/globalization_mechanisms/BacktrackingLineSearch.hpp b/uno/ingredients/globalization_mechanisms/BacktrackingLineSearch.hpp index 4fa4865c..21884c02 100644 --- a/uno/ingredients/globalization_mechanisms/BacktrackingLineSearch.hpp +++ b/uno/ingredients/globalization_mechanisms/BacktrackingLineSearch.hpp @@ -15,7 +15,8 @@ namespace uno { BacktrackingLineSearch(ConstraintRelaxationStrategy& constraint_relaxation_strategy, const Options& options); void initialize(Statistics& statistics, Iterate& initial_iterate, const Options& options) override; - void compute_next_iterate(Statistics& statistics, const Model& model, Iterate& current_iterate, Iterate& trial_iterate) override; + void compute_next_iterate(Statistics& statistics, const Model& model, Iterate& current_iterate, Iterate& trial_iterate, + WarmstartInformation& warmstart_information) override; private: const double backtracking_ratio; diff --git a/uno/ingredients/globalization_mechanisms/GlobalizationMechanism.hpp b/uno/ingredients/globalization_mechanisms/GlobalizationMechanism.hpp index 0fb8af8e..538045c0 100644 --- a/uno/ingredients/globalization_mechanisms/GlobalizationMechanism.hpp +++ b/uno/ingredients/globalization_mechanisms/GlobalizationMechanism.hpp @@ -13,6 +13,7 @@ namespace uno { class Model; class Options; class Statistics; + class WarmstartInformation; class GlobalizationMechanism { public: @@ -20,7 +21,8 @@ namespace uno { virtual ~GlobalizationMechanism() = default; virtual void initialize(Statistics& statistics, Iterate& initial_iterate, const Options& options) = 0; - virtual void compute_next_iterate(Statistics& statistics, const Model& model, Iterate& current_iterate, Iterate& trial_iterate) = 0; + virtual void compute_next_iterate(Statistics& statistics, const Model& model, Iterate& current_iterate, Iterate& trial_iterate, + WarmstartInformation& warmstart_information) = 0; [[nodiscard]] size_t get_hessian_evaluation_count() const; [[nodiscard]] size_t get_number_subproblems_solved() const; diff --git a/uno/ingredients/globalization_mechanisms/TrustRegionStrategy.cpp b/uno/ingredients/globalization_mechanisms/TrustRegionStrategy.cpp index 01b7285e..b584cb76 100644 --- a/uno/ingredients/globalization_mechanisms/TrustRegionStrategy.cpp +++ b/uno/ingredients/globalization_mechanisms/TrustRegionStrategy.cpp @@ -38,9 +38,8 @@ namespace uno { this->constraint_relaxation_strategy.initialize(statistics, initial_iterate, options); } - void TrustRegionStrategy::compute_next_iterate(Statistics& statistics, const Model& model, Iterate& current_iterate, Iterate& trial_iterate) { - WarmstartInformation warmstart_information{}; - warmstart_information.set_hot_start(); + void TrustRegionStrategy::compute_next_iterate(Statistics& statistics, const Model& model, Iterate& current_iterate, Iterate& trial_iterate, + WarmstartInformation& warmstart_information) { DEBUG2 << "Current iterate\n" << current_iterate << '\n'; size_t number_iterations = 0; @@ -64,14 +63,14 @@ namespace uno { statistics.set("status", "unbounded subproblem"); if (Logger::level == INFO) statistics.print_current_line(); this->decrease_radius_aggressively(); - warmstart_information.set_cold_start(); + warmstart_information.whole_problem_changed(); } else if (this->direction.status == SubproblemStatus::ERROR) { this->set_statistics(statistics, this->direction); statistics.set("status", "solver error"); if (Logger::level == INFO) statistics.print_current_line(); this->decrease_radius(); - warmstart_information.set_cold_start(); + warmstart_information.whole_problem_changed(); } else { // take full primal-dual step @@ -79,7 +78,7 @@ namespace uno { this->reset_active_trust_region_multipliers(model, this->direction, trial_iterate); // let the constraint relaxation strategy and the radius update rule determine which quantities change - warmstart_information.reset(); + warmstart_information.no_changes(); is_acceptable = this->is_iterate_acceptable(statistics, current_iterate, trial_iterate, this->direction, warmstart_information); if (is_acceptable) { @@ -99,7 +98,7 @@ namespace uno { statistics.set("status", "eval. error"); if (Logger::level == INFO) statistics.print_current_line(); this->decrease_radius(); - warmstart_information.set_cold_start(); + warmstart_information.whole_problem_changed(); } if (not is_acceptable && this->radius < this->minimum_radius) { throw std::runtime_error("Small trust-region radius"); @@ -127,7 +126,6 @@ namespace uno { // the trial iterate is accepted by the constraint relaxation strategy or if the step is small and we cannot switch to solving the feasibility problem bool TrustRegionStrategy::is_iterate_acceptable(Statistics& statistics, Iterate& current_iterate, Iterate& trial_iterate, const Direction& direction, WarmstartInformation& warmstart_information) { - // direction.primal_dual_step_length is usually 1, can be lower if reduced by fraction-to-boundary rule bool accept_iterate = this->constraint_relaxation_strategy.is_iterate_acceptable(statistics, current_iterate, trial_iterate, direction, 1., warmstart_information); this->set_statistics(statistics, trial_iterate, direction); diff --git a/uno/ingredients/globalization_mechanisms/TrustRegionStrategy.hpp b/uno/ingredients/globalization_mechanisms/TrustRegionStrategy.hpp index 76c0a3c1..378408be 100644 --- a/uno/ingredients/globalization_mechanisms/TrustRegionStrategy.hpp +++ b/uno/ingredients/globalization_mechanisms/TrustRegionStrategy.hpp @@ -12,7 +12,8 @@ namespace uno { TrustRegionStrategy(ConstraintRelaxationStrategy& constraint_relaxation_strategy, const Options& options); void initialize(Statistics& statistics, Iterate& initial_iterate, const Options& options) override; - void compute_next_iterate(Statistics& statistics, const Model& model, Iterate& current_iterate, Iterate& trial_iterate) override; + void compute_next_iterate(Statistics& statistics, const Model& model, Iterate& current_iterate, Iterate& trial_iterate, + WarmstartInformation& warmstart_information) override; private: double radius; /*!< Current trust region radius */ diff --git a/uno/optimization/WarmstartInformation.cpp b/uno/optimization/WarmstartInformation.cpp index 44957d1f..c5e7bd52 100644 --- a/uno/optimization/WarmstartInformation.cpp +++ b/uno/optimization/WarmstartInformation.cpp @@ -13,28 +13,28 @@ namespace uno { std::cout << "Problem: " << std::boolalpha << this->problem_changed << '\n'; } - void WarmstartInformation::reset() { - this->objective_changed = true; - this->constraints_changed = true; - this->constraint_bounds_changed = true; - this->variable_bounds_changed = true; - this->problem_changed = true; + void WarmstartInformation::no_changes() { + this->objective_changed = false; + this->constraints_changed = false; + this->constraint_bounds_changed = false; + this->variable_bounds_changed = false; + this->problem_changed = false; } - void WarmstartInformation::set_cold_start() { + void WarmstartInformation::iterate_changed() { this->objective_changed = true; this->constraints_changed = true; this->constraint_bounds_changed = true; this->variable_bounds_changed = true; - this->problem_changed = true; + this->problem_changed = false; } - void WarmstartInformation::set_hot_start() { + void WarmstartInformation::whole_problem_changed() { this->objective_changed = true; this->constraints_changed = true; this->constraint_bounds_changed = true; this->variable_bounds_changed = true; - this->problem_changed = false; + this->problem_changed = true; } void WarmstartInformation::only_objective_changed() { @@ -44,12 +44,4 @@ namespace uno { this->variable_bounds_changed = false; this->problem_changed = false; } - - void WarmstartInformation::only_variable_bounds_changed() { - this->objective_changed = false; - this->constraints_changed = false; - this->constraint_bounds_changed = false; - this->variable_bounds_changed = true; - this->problem_changed = false; - } } // namespace \ No newline at end of file diff --git a/uno/optimization/WarmstartInformation.hpp b/uno/optimization/WarmstartInformation.hpp index f7e3b128..c7d474e4 100644 --- a/uno/optimization/WarmstartInformation.hpp +++ b/uno/optimization/WarmstartInformation.hpp @@ -13,11 +13,10 @@ namespace uno { bool problem_changed{false}; void display() const; - void reset(); - void set_cold_start(); - void set_hot_start(); + void no_changes(); + void iterate_changed(); + void whole_problem_changed(); void only_objective_changed(); - void only_variable_bounds_changed(); }; } // namespace