From 888114ce7d5e1d208ed8865dc836e4b94017e6a8 Mon Sep 17 00:00:00 2001 From: Charlie Vanaret Date: Wed, 5 Jun 2024 16:55:56 +0200 Subject: [PATCH] TR: if termination with small step, compute primal-dual residuals. Small changes to Vector and Iterate --- .../ConstraintRelaxationStrategy.hpp | 3 +++ .../FeasibilityRestoration.cpp | 8 ++++++-- .../FeasibilityRestoration.hpp | 3 +++ .../constraint_relaxation_strategy/l1Relaxation.cpp | 8 ++++++-- .../constraint_relaxation_strategy/l1Relaxation.hpp | 3 +++ .../globalization_mechanism/TrustRegionStrategy.cpp | 2 ++ uno/linear_algebra/Vector.hpp | 5 ++--- uno/optimization/Iterate.cpp | 5 +++-- 8 files changed, 28 insertions(+), 9 deletions(-) diff --git a/uno/ingredients/constraint_relaxation_strategy/ConstraintRelaxationStrategy.hpp b/uno/ingredients/constraint_relaxation_strategy/ConstraintRelaxationStrategy.hpp index dcb0dfe1..9899b31e 100644 --- a/uno/ingredients/constraint_relaxation_strategy/ConstraintRelaxationStrategy.hpp +++ b/uno/ingredients/constraint_relaxation_strategy/ConstraintRelaxationStrategy.hpp @@ -45,6 +45,9 @@ class ConstraintRelaxationStrategy { [[nodiscard]] virtual bool is_iterate_acceptable(Statistics& statistics, Iterate& current_iterate, Iterate& trial_iterate, const Direction& direction, double step_length) = 0; + // primal-dual residuals + virtual void compute_primal_dual_residuals(Iterate& iterate) = 0; + [[nodiscard]] virtual size_t get_hessian_evaluation_count() const = 0; [[nodiscard]] virtual size_t get_number_subproblems_solved() const = 0; diff --git a/uno/ingredients/constraint_relaxation_strategy/FeasibilityRestoration.cpp b/uno/ingredients/constraint_relaxation_strategy/FeasibilityRestoration.cpp index 34d00e4b..05f34f8c 100644 --- a/uno/ingredients/constraint_relaxation_strategy/FeasibilityRestoration.cpp +++ b/uno/ingredients/constraint_relaxation_strategy/FeasibilityRestoration.cpp @@ -42,7 +42,7 @@ void FeasibilityRestoration::initialize(Statistics& statistics, Iterate& initial // initial iterate const bool is_linearly_feasible = this->subproblem->generate_initial_iterate(this->optimality_problem, initial_iterate); this->evaluate_progress_measures(initial_iterate); - this->compute_primal_dual_residuals(this->optimality_problem, this->feasibility_problem, initial_iterate); + this->compute_primal_dual_residuals(initial_iterate); this->set_statistics(statistics, initial_iterate); if (not is_linearly_feasible) { this->switch_to_feasibility_problem(statistics, initial_iterate); @@ -200,13 +200,17 @@ bool FeasibilityRestoration::is_iterate_acceptable(Statistics& statistics, Itera this->globalization_strategy->is_infeasibility_sufficiently_reduced(current_iterate.progress, trial_iterate.progress)) { this->switch_to_optimality_phase(current_iterate, trial_iterate); } - this->compute_primal_dual_residuals(this->optimality_problem, this->feasibility_problem, trial_iterate); + this->compute_primal_dual_residuals(trial_iterate); this->set_dual_residuals_statistics(statistics, trial_iterate); } ConstraintRelaxationStrategy::set_progress_statistics(statistics, trial_iterate); return accept_iterate; } +void FeasibilityRestoration::compute_primal_dual_residuals(Iterate& iterate) { + ConstraintRelaxationStrategy::compute_primal_dual_residuals(this->optimality_problem, this->feasibility_problem, iterate); +} + const OptimizationProblem& FeasibilityRestoration::current_problem() const { if (this->current_phase == Phase::OPTIMALITY) { return this->optimality_problem; diff --git a/uno/ingredients/constraint_relaxation_strategy/FeasibilityRestoration.hpp b/uno/ingredients/constraint_relaxation_strategy/FeasibilityRestoration.hpp index 9545424a..26de001e 100644 --- a/uno/ingredients/constraint_relaxation_strategy/FeasibilityRestoration.hpp +++ b/uno/ingredients/constraint_relaxation_strategy/FeasibilityRestoration.hpp @@ -35,6 +35,9 @@ class FeasibilityRestoration : public ConstraintRelaxationStrategy { [[nodiscard]] bool is_iterate_acceptable(Statistics& statistics, Iterate& current_iterate, Iterate& trial_iterate, const Direction& direction, double step_length) override; + // primal-dual residuals + void compute_primal_dual_residuals(Iterate& iterate) override; + [[nodiscard]] size_t get_hessian_evaluation_count() const override; [[nodiscard]] size_t get_number_subproblems_solved() const override; diff --git a/uno/ingredients/constraint_relaxation_strategy/l1Relaxation.cpp b/uno/ingredients/constraint_relaxation_strategy/l1Relaxation.cpp index cd4c15da..6c13a73e 100644 --- a/uno/ingredients/constraint_relaxation_strategy/l1Relaxation.cpp +++ b/uno/ingredients/constraint_relaxation_strategy/l1Relaxation.cpp @@ -51,7 +51,7 @@ void l1Relaxation::initialize(Statistics& statistics, Iterate& initial_iterate, this->subproblem->set_elastic_variable_values(this->l1_relaxed_problem, initial_iterate); const bool is_linearly_feasible = this->subproblem->generate_initial_iterate(this->l1_relaxed_problem, initial_iterate); this->evaluate_progress_measures(initial_iterate); - this->compute_primal_dual_residuals(this->l1_relaxed_problem, this->feasibility_problem, initial_iterate); + this->compute_primal_dual_residuals(initial_iterate); this->set_statistics(statistics, initial_iterate); if (not is_linearly_feasible) { this->switch_to_feasibility_problem(statistics, initial_iterate); @@ -261,13 +261,17 @@ bool l1Relaxation::is_iterate_acceptable(Statistics& statistics, Iterate& curren } if (accept_iterate) { this->check_exact_relaxation(trial_iterate); - this->compute_primal_dual_residuals(this->l1_relaxed_problem, this->feasibility_problem, trial_iterate); + this->compute_primal_dual_residuals(trial_iterate); this->set_dual_residuals_statistics(statistics, trial_iterate); } this->set_progress_statistics(statistics, trial_iterate); return accept_iterate; } +void l1Relaxation::compute_primal_dual_residuals(Iterate& iterate) { + ConstraintRelaxationStrategy::compute_primal_dual_residuals(this->l1_relaxed_problem, this->feasibility_problem, iterate); +} + void l1Relaxation::evaluate_progress_measures(Iterate& iterate) const { this->set_infeasibility_measure(iterate); this->set_objective_measure(iterate); diff --git a/uno/ingredients/constraint_relaxation_strategy/l1Relaxation.hpp b/uno/ingredients/constraint_relaxation_strategy/l1Relaxation.hpp index 406a5bb8..702c6587 100644 --- a/uno/ingredients/constraint_relaxation_strategy/l1Relaxation.hpp +++ b/uno/ingredients/constraint_relaxation_strategy/l1Relaxation.hpp @@ -41,6 +41,9 @@ class l1Relaxation : public ConstraintRelaxationStrategy { [[nodiscard]] bool is_iterate_acceptable(Statistics& statistics, Iterate& current_iterate, Iterate& trial_iterate, const Direction& direction, double step_length) override; + // primal-dual residuals + void compute_primal_dual_residuals(Iterate& iterate) override; + [[nodiscard]] size_t get_hessian_evaluation_count() const override; [[nodiscard]] size_t get_number_subproblems_solved() const override; diff --git a/uno/ingredients/globalization_mechanism/TrustRegionStrategy.cpp b/uno/ingredients/globalization_mechanism/TrustRegionStrategy.cpp index 01c59e37..d03c89b5 100644 --- a/uno/ingredients/globalization_mechanism/TrustRegionStrategy.cpp +++ b/uno/ingredients/globalization_mechanism/TrustRegionStrategy.cpp @@ -169,10 +169,12 @@ bool TrustRegionStrategy::check_termination_with_small_step(const Model& /*model // terminate with a feasible point if (trial_iterate.progress.infeasibility <= this->tight_tolerance) { trial_iterate.status = TerminationStatus::FEASIBLE_SMALL_STEP; + this->constraint_relaxation_strategy.compute_primal_dual_residuals(trial_iterate); return true; } else if (this->constraint_relaxation_strategy.solving_feasibility_problem()) { // terminate with an infeasible point trial_iterate.status = TerminationStatus::INFEASIBLE_SMALL_STEP; + this->constraint_relaxation_strategy.compute_primal_dual_residuals(trial_iterate); return true; } else { // do not terminate, infeasible non stationary diff --git a/uno/linear_algebra/Vector.hpp b/uno/linear_algebra/Vector.hpp index 2b1c89c3..a7595ff9 100644 --- a/uno/linear_algebra/Vector.hpp +++ b/uno/linear_algebra/Vector.hpp @@ -36,10 +36,9 @@ class Vector { // move assignment operator Vector& operator=(std::vector&& other) { - if (&other == this) { - return *this; + if (&other != this) { + this->vector = std::move(other.vector); } - this->vector = std::move(other.vector); return *this; } diff --git a/uno/optimization/Iterate.cpp b/uno/optimization/Iterate.cpp index 333cf79a..5e6ca446 100644 --- a/uno/optimization/Iterate.cpp +++ b/uno/optimization/Iterate.cpp @@ -92,8 +92,9 @@ std::ostream& operator<<(std::ostream& stream, const Iterate& iterate) { stream << "Objective value: " << iterate.evaluations.objective << '\n'; stream << " ┌ Stationarity: " << iterate.residuals.KKT_stationarity << '\n'; - stream << " │ Feasibility stationarity: " << iterate.residuals.feasibility_stationarity << '\n'; - stream << "Residuals │ Constraint violation: " << iterate.residuals.infeasibility << '\n'; + stream << " │ FJ stationarity: " << iterate.residuals.FJ_stationarity << '\n'; + stream << "Residuals │ Feasibility stationarity: " << iterate.residuals.feasibility_stationarity << '\n'; + stream << " │ Constraint violation: " << iterate.residuals.infeasibility << '\n'; stream << " │ Complementarity: " << iterate.residuals.complementarity << '\n'; stream << " └ Feasibility complementarity: " << iterate.residuals.feasibility_complementarity << '\n';