Skip to content

Commit

Permalink
add plot iterations in PADM
Browse files Browse the repository at this point in the history
  • Loading branch information
hlefebvr committed Oct 23, 2024
1 parent c32efb0 commit 781b6be
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "idol/optimizers/Algorithm.h"
#include "idol/optimizers/mixed-integer-optimization/padm/SubProblem.h"
#include "idol/optimizers/mixed-integer-optimization/callbacks/watchers/PlotManager.h"
#include "Formulation.h"
#include "PenaltyUpdates.h"

Expand All @@ -21,7 +22,8 @@ class idol::Optimizers::PADM : public Algorithm {
std::vector<idol::ADM::SubProblem>&& t_sub_problem_specs,
PenaltyUpdate* t_penalty_update,
SolutionStatus t_feasible_solution_status,
double t_initial_penalty_parameter);
double t_initial_penalty_parameter,
Plots::Manager* t_plot_manager);

std::string name() const override { return "PADM"; }

Expand All @@ -43,6 +45,7 @@ class idol::Optimizers::PADM : public Algorithm {

unsigned int get_inner_loop_iteration_count() const;

class IterationPlot;
protected:
void add(const Var &t_var) override;

Expand Down Expand Up @@ -115,6 +118,7 @@ class idol::Optimizers::PADM : public Algorithm {
const unsigned int m_max_inner_loop_iterations = std::numeric_limits<unsigned int>::max();
const SolutionStatus m_feasible_solution_status;
const unsigned int m_max_iterations_without_feasibility_change = 1000;
std::unique_ptr<IterationPlot> m_history_plotter;

std::optional<unsigned int> m_last_iteration_with_no_feasibility_change;
std::optional<double> m_last_objective_value_when_rescaled;
Expand All @@ -138,5 +142,27 @@ class idol::Optimizers::PADM : public Algorithm {
std::list<IterationLog> m_history;
};

class TPad;
class TGraph;
class TLine;

class idol::Optimizers::PADM::IterationPlot {
Plots::Manager& m_manager;

TCanvas* m_canvas = nullptr;
std::vector<TPad*> m_pads;
std::vector<TGraph*> m_graphs;
std::vector<std::list<TLine*>> m_lines;
unsigned int m_last_outer_iteration = 0;

void initialize(unsigned int t_n_sub_problems);
public:
explicit IterationPlot(Plots::Manager& t_manager);

void update(unsigned int t_outer_loop_iteration,
unsigned int t_inner_loop_iteration,
const std::vector<double>& t_objective_values,
const std::vector<double>& t_infeasibilities);
};

#endif //IDOL_OPTIMIZERS_PADM_H
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "SubProblem.h"
#include "Formulation.h"
#include "PenaltyUpdates.h"
#include "idol/optimizers/mixed-integer-optimization/callbacks/watchers/PlotManager.h"
#include <optional>

namespace idol {
Expand All @@ -26,7 +27,7 @@ class idol::PADM : public OptimizerFactoryWithDefaultParameters<PADM> {
PADM(const PADM& t_src);
PADM(PADM&&) = default;

PADM& operator=(const PADM&) = default;
PADM& operator=(const PADM&) = delete;
PADM& operator=(PADM&&) = default;

PADM& with_default_sub_problem_spec(ADM::SubProblem t_sub_problem);
Expand All @@ -43,10 +44,11 @@ class idol::PADM : public OptimizerFactoryWithDefaultParameters<PADM> {

PADM& with_initial_penalty_parameter(double t_value);

PADM& with_iteration_plot(Plots::Manager& t_manager);

Optimizer *operator()(const Model &t_model) const override;

OptimizerFactory *clone() const override;

private:
Annotation<Var, unsigned int> m_decomposition;
std::optional<Annotation<Ctr, bool>> m_penalized_constraints;
Expand All @@ -57,6 +59,7 @@ class idol::PADM : public OptimizerFactoryWithDefaultParameters<PADM> {
std::optional<bool> m_independent_penalty_update;
std::optional<SolutionStatus> m_feasible_solution_status;
std::optional<double> m_initial_penalty_parameter;
std::optional<Plots::Manager*> m_plot_manager;

std::vector<ADM::SubProblem> create_sub_problem_specs(const Model& t_model, const ADM::Formulation& t_formulation) const;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,6 @@ CoinPackedMatrix idol::impl::MibSFromAPI::parse_matrix() {
vector.sortIncrIndex();

result.appendCol(vector);

}

return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ idol::Optimizers::PADM::PADM(const Model& t_model,
std::vector<idol::ADM::SubProblem>&& t_sub_problem_specs,
PenaltyUpdate* t_penalty_update,
SolutionStatus t_feasible_solution_status,
double t_initial_penalty_parameter)
double t_initial_penalty_parameter,
Plots::Manager* t_plot_manager)
: Algorithm(t_model),
m_formulation(std::move(t_formulation)),
m_sub_problem_specs(std::move(t_sub_problem_specs)),
m_penalty_update(t_penalty_update),
m_feasible_solution_status(t_feasible_solution_status),
m_initial_penalty_parameter(t_initial_penalty_parameter) {
m_initial_penalty_parameter(t_initial_penalty_parameter),
m_history_plotter(t_plot_manager ? new IterationPlot(*t_plot_manager) : nullptr) {

}

Expand Down Expand Up @@ -549,6 +551,14 @@ void idol::Optimizers::PADM::make_history() {
objective_values.emplace_back(m_formulation.sub_problem(i).get_best_obj());
infeasibility_values.emplace_back(infeasibility_l1(i, m_last_solutions[i]));
}

if (m_history_plotter) {
m_history_plotter->update(m_outer_loop_iteration,
m_inner_loop_iterations,
objective_values,
infeasibility_values);
}

m_history.emplace_back(m_outer_loop_iteration,
m_inner_loop_iterations,
std::move(objective_values),
Expand Down Expand Up @@ -628,3 +638,86 @@ void idol::Optimizers::PADM::restart() {

++m_n_restart;
}

idol::Optimizers::PADM::IterationPlot::IterationPlot(idol::Plots::Manager &t_manager) : m_manager(t_manager) {

}

#ifdef IDOL_USE_ROOT
#include <TGraph.h>
#include <TLine.h>
#include <TAxis.h>
#endif

void idol::Optimizers::PADM::IterationPlot::initialize(unsigned int t_n_sub_problems) {
#ifdef IDOL_USE_ROOT
// Create the canvas
m_canvas = m_manager.create<TCanvas>("canvas", "Sub-problems Objective Progress", 800, 600);

// Create the pads for each sub-problem and TGraphs
m_pads.resize(t_n_sub_problems);
m_graphs.resize(t_n_sub_problems);
m_lines.resize(t_n_sub_problems);

for (unsigned int i = 0; i < t_n_sub_problems; ++i) {
// Divide the canvas into vertical pads for each graph
m_pads[i] = m_manager.create<TPad>(Form("pad%d", i), Form("Sub-problem %d", i), 0.0, 1.0 - (i + 1) * (1.0 / t_n_sub_problems), 1.0, 1.0 - i * (1.0 / t_n_sub_problems));
m_pads[i]->Draw();
m_pads[i]->cd();

// Create a TGraph for each sub-problem
m_graphs[i] = m_manager.create<TGraph>();
m_graphs[i]->SetTitle(Form("Sub-problem %d; Inner Loop Iteration; Objective Value", i));

m_graphs[i]->Draw("APL");

m_canvas->cd();
}
#else
throw Exception("idol was not compiled with ROOT.");
#endif
}

void
idol::Optimizers::PADM::IterationPlot::update(unsigned int t_outer_loop_iteration,
unsigned int t_inner_loop_iteration,
const std::vector<double> &t_objective_values,
const std::vector<double> &t_infeasibilities) {

if (!m_canvas) {
initialize(t_objective_values.size());
}

#ifdef IDOL_USE_ROOT
const unsigned int n_sub_problems = t_objective_values.size();
const bool outer_loop_changed = m_last_outer_iteration != t_outer_loop_iteration;

for (unsigned int i = 0; i < n_sub_problems; ++i) {
m_graphs[i]->SetPoint(m_graphs[i]->GetN(), t_inner_loop_iteration, t_objective_values[i]);

m_pads[i]->cd();
m_graphs[i]->Draw("AL");

if (outer_loop_changed) {
auto* vertical_line = m_manager.create<TLine>(t_inner_loop_iteration,
m_graphs[i]->GetYaxis()->GetXmin(),
t_inner_loop_iteration,
m_graphs[i]->GetYaxis()->GetXmax());
vertical_line->SetLineColor(kRed);
vertical_line->SetLineStyle(2); // Dashed line
m_lines[i].emplace_back(vertical_line);
m_last_outer_iteration = t_outer_loop_iteration;
}

for (auto* line : m_lines[i]) {
line->SetY1(m_graphs[i]->GetYaxis()->GetXmin());
line->SetY2(m_graphs[i]->GetYaxis()->GetXmax());
line->Draw("SAME");
}

}

m_canvas->cd();
m_canvas->Update();
#endif
}
15 changes: 14 additions & 1 deletion lib/src/optimizers/mixed-integer-optimization/padm/PADM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ idol::Optimizer *idol::PADM::operator()(const idol::Model &t_model) const {
std::move(sub_problem_specs),
penalty_update,
m_feasible_solution_status ? *m_feasible_solution_status : Feasible,
m_initial_penalty_parameter ? *m_initial_penalty_parameter : 1e-1
m_initial_penalty_parameter ? *m_initial_penalty_parameter : 1e-1,
m_plot_manager ? *m_plot_manager : nullptr
);

handle_default_parameters(result);
Expand Down Expand Up @@ -174,3 +175,15 @@ idol::PADM &idol::PADM::with_sub_problem_spec(unsigned int t_id, idol::ADM::SubP

return *this;
}

idol::PADM &idol::PADM::with_iteration_plot(Plots::Manager &t_manager) {

if (m_plot_manager) {
throw Exception("The plot manager has already been set.");
}

m_plot_manager = &t_manager;

return *this;

}
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ idol::Optimizers::PADM *idol::PenaltyMethod::operator()(const idol::Model &t_mod
{ ADM::SubProblem().with_optimizer(*m_optimizer) },
penalty_update,
m_feasible_solution_status ? *m_feasible_solution_status : Feasible,
m_initial_penalty_parameter ? *m_initial_penalty_parameter : 1e2
m_initial_penalty_parameter ? *m_initial_penalty_parameter : 1e2,
nullptr
);

handle_default_parameters(result);
Expand Down

0 comments on commit 781b6be

Please sign in to comment.