Skip to content

Commit

Permalink
Passed warmstart object around to properly handle the warmstart infor…
Browse files Browse the repository at this point in the history
…mation
  • Loading branch information
cvanaret committed Nov 12, 2024
1 parent d57ee9c commit b78271d
Show file tree
Hide file tree
Showing 12 changed files with 47 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ namespace uno {
void compute_feasible_direction(Statistics& statistics, Iterate& current_iterate, Direction& direction,
const Vector<double>& 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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand All @@ -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);
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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.) {
Expand All @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ namespace uno {
class Model;
class Options;
class Statistics;
class WarmstartInformation;

class GlobalizationMechanism {
public:
explicit GlobalizationMechanism(ConstraintRelaxationStrategy& constraint_relaxation_strategy);
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;
Expand Down
14 changes: 6 additions & 8 deletions uno/ingredients/globalization_mechanisms/TrustRegionStrategy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -64,22 +63,22 @@ 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
GlobalizationMechanism::assemble_trial_iterate(model, current_iterate, trial_iterate, this->direction, 1., 1.);
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) {
Expand All @@ -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");
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
28 changes: 10 additions & 18 deletions uno/optimization/WarmstartInformation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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
7 changes: 3 additions & 4 deletions uno/optimization/WarmstartInformation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit b78271d

Please sign in to comment.