Skip to content

Commit

Permalink
add Neame and Wentges static stabilization
Browse files Browse the repository at this point in the history
  • Loading branch information
hlefebvr committed Oct 31, 2023
1 parent 57c8a17 commit 4ae65ca
Show file tree
Hide file tree
Showing 12 changed files with 237 additions and 6 deletions.
7 changes: 5 additions & 2 deletions dev/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include "idol/optimizers/branch-and-bound/node-selection-rules/factories/WorstBound.h"
#include "idol/optimizers/dantzig-wolfe/DantzigWolfeDecomposition.h"
#include "idol/optimizers/dantzig-wolfe/infeasibility-strategies/FarkasPricing.h"
#include "idol/optimizers/dantzig-wolfe/stabilization/Neame.h"
#include "idol/optimizers/dantzig-wolfe/stabilization/Wentges.h"

using namespace idol;

Expand Down Expand Up @@ -53,15 +55,16 @@ int main(int t_argc, char** t_argv) {
model.use(BranchAndBound()
.with_node_optimizer(
DantzigWolfe::Decomposition(decomposition)
.with_master_optimizer(HiGHS::ContinuousRelaxation())
.with_master_optimizer(Gurobi::ContinuousRelaxation())
.with_default_sub_problem_spec(
DantzigWolfe::SubProblem()
.add_optimizer(HiGHS())
.add_optimizer(Gurobi())
.with_multiplicities(0, 1)
)
.with_infeasibility_strategy(DantzigWolfe::FarkasPricing())
.with_hard_branching(false)
.with_max_parallel_sub_problems(5)
.with_dual_price_smoothing_stabilization(DantzigWolfe::Wentges(.3))
.with_log_level(Info, Yellow)
)
.with_subtree_depth(0)
Expand Down
4 changes: 4 additions & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ add_library(idol STATIC
include/idol/optimizers/dantzig-wolfe/infeasibility-strategies/FarkasPricing.h
src/optimizers/column-generation/infeasibility-strategies/FarkasPricing.cpp
src/optimizers/column-generation/infeasibility-strategies/DantzigWolfeInfeasibilityStrategy.cpp
include/idol/optimizers/dantzig-wolfe/stabilization/DualPriceSmoothingStabilization.h
include/idol/optimizers/dantzig-wolfe/stabilization/Neame.h
include/idol/optimizers/dantzig-wolfe/stabilization/Wentges.h
include/idol/optimizers/dantzig-wolfe/stabilization/NoStabilization.h
)

find_package(OpenMP REQUIRED)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "idol/containers/Map.h"
#include "DantzigWolfeFormulation.h"
#include "idol/optimizers/dantzig-wolfe/infeasibility-strategies/DantzigWolfeInfeasibilityStrategy.h"
#include "idol/optimizers/dantzig-wolfe/stabilization/DualPriceSmoothingStabilization.h"

namespace idol::DantzigWolfe {
class Decomposition;
Expand All @@ -20,6 +21,7 @@ class idol::DantzigWolfe::Decomposition : public OptimizerFactoryWithDefaultPara
Annotation<Ctr, unsigned int> m_decomposition;
std::unique_ptr<OptimizerFactory> m_master_optimizer_factory;
std::unique_ptr<InfeasibilityStrategyFactory> m_infeasibility_strategy;
std::unique_ptr<DualPriceSmoothingStabilization> m_dual_price_smoothing_stabilization;
std::optional<unsigned int> m_max_parallel_sub_problems;
std::optional<bool> m_use_hard_branching;
std::optional<SubProblem> m_default_sub_problem_spec;
Expand Down Expand Up @@ -47,6 +49,8 @@ class idol::DantzigWolfe::Decomposition : public OptimizerFactoryWithDefaultPara

Decomposition& with_max_parallel_sub_problems(unsigned int t_n_sub_problems);

Decomposition& with_dual_price_smoothing_stabilization(const DualPriceSmoothingStabilization& t_stabilization);

const SubProblem& get_sub_problem_spec(unsigned int t_id) const;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "DantzigWolfeFormulation.h"
#include "DantzigWolfeSubProblem.h"
#include "idol/optimizers/dantzig-wolfe/infeasibility-strategies/DantzigWolfeInfeasibilityStrategy.h"
#include "idol/optimizers/dantzig-wolfe/stabilization/DualPriceSmoothingStabilization.h"

namespace idol::Optimizers {
class DantzigWolfeDecomposition;
Expand All @@ -18,13 +19,15 @@ class idol::Optimizers::DantzigWolfeDecomposition : public Algorithm {
idol::DantzigWolfe::Formulation m_formulation;
std::unique_ptr<OptimizerFactory> m_master_optimizer_factory;
std::unique_ptr<DantzigWolfe::InfeasibilityStrategyFactory::Strategy> m_strategy;
std::unique_ptr<DantzigWolfe::DualPriceSmoothingStabilization::Strategy> m_stabilization;
std::vector<DantzigWolfe::SubProblem> m_sub_problem_specifications;
unsigned int m_max_parallel_pricing;
bool m_use_hard_branching = false;
public:
DantzigWolfeDecomposition(const Model& t_model,
idol::DantzigWolfe::Formulation&& t_formulation,
const OptimizerFactory& t_master_optimizer_factory,
const DantzigWolfe::DualPriceSmoothingStabilization& t_stabilization,
unsigned int t_max_parallel_pricing,
bool t_use_hard_branching,
std::vector<DantzigWolfe::SubProblem>&& t_sub_problem_specifications,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class idol::Optimizers::DantzigWolfeDecomposition::ColumnGeneration {
SolutionReason m_reason = NotSpecified;
std::optional<Solution::Primal> m_master_primal_solution;
std::optional<Solution::Dual> m_last_master_solution;
std::optional<Solution::Dual> m_stability_center;
std::vector<DantzigWolfe::SubProblem::PhaseId> m_sub_problems_phases;
double m_best_obj = -Inf;
double m_best_bound = +Inf;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// Created by henri on 31.10.23.
//

#ifndef IDOL_DUALPRICESMOOTHINGSTABILIZATION_H
#define IDOL_DUALPRICESMOOTHINGSTABILIZATION_H

#include "idol/modeling/solutions/Solution.h"

namespace idol::DantzigWolfe {
class DualPriceSmoothingStabilization;
}

class idol::DantzigWolfe::DualPriceSmoothingStabilization {
public:
virtual ~DualPriceSmoothingStabilization() = default;

class Strategy {
public:
virtual ~Strategy() = default;

virtual void initialize() = 0;

virtual void update_stability_center(const Solution::Dual& t_master_dual) = 0;

virtual Solution::Dual compute_smoothed_dual_solution(const Solution::Dual& t_master_dual) = 0;
};

virtual Strategy* operator()() const = 0;

[[nodiscard]] virtual DualPriceSmoothingStabilization* clone() const = 0;
};

#endif //IDOL_DUALPRICESMOOTHINGSTABILIZATION_H
58 changes: 58 additions & 0 deletions lib/include/idol/optimizers/dantzig-wolfe/stabilization/Neame.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//
// Created by henri on 31.10.23.
//

#ifndef IDOL_NEAME_H
#define IDOL_NEAME_H

#include "DualPriceSmoothingStabilization.h"

namespace idol::DantzigWolfe {
class Neame;
}

class idol::DantzigWolfe::Neame : public DualPriceSmoothingStabilization {
double m_initial_factor;
public:
explicit Neame(double t_initial_factor) : m_initial_factor(t_initial_factor) {}

class Strategy : public DualPriceSmoothingStabilization::Strategy {
double m_factor;
std::optional<Solution::Dual> m_last_master_dual;
public:
explicit Strategy(double t_initial_factor) : m_factor(t_initial_factor) {}

void initialize() override {
m_last_master_dual.reset();
}

void update_stability_center(const Solution::Dual &t_master_dual) override {
// intentionally left blank
}

Solution::Dual compute_smoothed_dual_solution(const Solution::Dual &t_master_dual) override {

if (!m_last_master_dual.has_value() || m_factor <= 1e-4) {
m_last_master_dual = t_master_dual;
return t_master_dual;
}

auto result = m_factor * m_last_master_dual.value() + (1. - m_factor) * t_master_dual;

m_last_master_dual = t_master_dual;

return result;
}

};

DualPriceSmoothingStabilization::Strategy *operator()() const override {
return new Strategy(m_initial_factor);
}

DualPriceSmoothingStabilization *clone() const override {
return new Neame(*this);
}
};

#endif //IDOL_NEAME_H
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// Created by henri on 31.10.23.
//

#ifndef IDOL_NOSTABILIZATION_H
#define IDOL_NOSTABILIZATION_H

#include "DualPriceSmoothingStabilization.h"

namespace idol::DantzigWolfe {
class NoStabilization;
}

class idol::DantzigWolfe::NoStabilization : public DualPriceSmoothingStabilization {
public:
explicit NoStabilization() = default;

class Strategy : public DualPriceSmoothingStabilization::Strategy {
public:
explicit Strategy() = default;

void initialize() override {
// intentionally left blank
}

void update_stability_center(const Solution::Dual &t_master_dual) override {
// intentionally left blank
}

Solution::Dual compute_smoothed_dual_solution(const Solution::Dual &t_master_dual) override {
return t_master_dual;
}

};

DualPriceSmoothingStabilization::Strategy *operator()() const override {
return new Strategy();
}

DualPriceSmoothingStabilization *clone() const override {
return new NoStabilization(*this);
}
};

#endif //IDOL_NOSTABILIZATION_H
59 changes: 59 additions & 0 deletions lib/include/idol/optimizers/dantzig-wolfe/stabilization/Wentges.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// Created by henri on 31.10.23.
//

#ifndef IDOL_WENTGES_H
#define IDOL_WENTGES_H

#include <optional>
#include "DualPriceSmoothingStabilization.h"

namespace idol::DantzigWolfe {
class Wentges;
}

class idol::DantzigWolfe::Wentges : public DualPriceSmoothingStabilization {
double m_initial_factor;
public:
explicit Wentges(double t_initial_factor) : m_initial_factor(t_initial_factor) {}

class Strategy : public DualPriceSmoothingStabilization::Strategy {
double m_factor;
std::optional<Solution::Dual> m_stability_center;
public:
explicit Strategy(double t_initial_factor) : m_factor(t_initial_factor) {}

void initialize() override {
m_stability_center.reset();
}

void update_stability_center(const Solution::Dual &t_master_dual) override {
m_stability_center = t_master_dual;
}

Solution::Dual compute_smoothed_dual_solution(const Solution::Dual &t_master_dual) override {

if (!m_stability_center.has_value() || m_factor <= 1e-4) {
m_stability_center = t_master_dual;
return t_master_dual;
}

auto result = m_factor * m_stability_center.value() + (1. - m_factor) * t_master_dual;

m_stability_center = t_master_dual;

return result;
}

};

DualPriceSmoothingStabilization::Strategy *operator()() const override {
return new Strategy(m_initial_factor);
}

DualPriceSmoothingStabilization *clone() const override {
return new Wentges(*this);
}
};

#endif //IDOL_WENTGES_H
20 changes: 20 additions & 0 deletions lib/src/optimizers/column-generation/DantzigWolfeDecomposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "idol/optimizers/dantzig-wolfe/DantzigWolfeFormulation.h"
#include "idol/optimizers/dantzig-wolfe/Optimizers_DantzigWolfeDecomposition.h"
#include "idol/optimizers/dantzig-wolfe/infeasibility-strategies/FarkasPricing.h"
#include "idol/optimizers/dantzig-wolfe/stabilization/NoStabilization.h"

idol::OptimizerFactory *idol::DantzigWolfe::Decomposition::clone() const {
return new Decomposition(*this);
Expand All @@ -19,6 +20,7 @@ idol::DantzigWolfe::Decomposition::Decomposition(const Decomposition& t_src)
: OptimizerFactoryWithDefaultParameters<Decomposition>(t_src),
m_decomposition(t_src.m_decomposition),
m_master_optimizer_factory(t_src.m_master_optimizer_factory ? t_src.m_master_optimizer_factory->clone() : nullptr),
m_dual_price_smoothing_stabilization(t_src.m_dual_price_smoothing_stabilization ? t_src.m_dual_price_smoothing_stabilization->clone() : nullptr),
m_max_parallel_sub_problems(t_src.m_max_parallel_sub_problems),
m_use_hard_branching(t_src.m_use_hard_branching),
m_infeasibility_strategy(t_src.m_infeasibility_strategy ? t_src.m_infeasibility_strategy->clone() : nullptr),
Expand All @@ -43,9 +45,15 @@ idol::Optimizer *idol::DantzigWolfe::Decomposition::operator()(const Model &t_mo
default_strategy = std::make_unique<FarkasPricing>();
}

std::unique_ptr<DualPriceSmoothingStabilization> dual_price_smoothing;
if (!m_dual_price_smoothing_stabilization) {
dual_price_smoothing = std::make_unique<NoStabilization>();
}

return new Optimizers::DantzigWolfeDecomposition(t_model,
std::move(dantzig_wolfe_formulation),
*m_master_optimizer_factory,
m_dual_price_smoothing_stabilization ? *m_dual_price_smoothing_stabilization : *dual_price_smoothing,
m_max_parallel_sub_problems.has_value() ? m_max_parallel_sub_problems.value() : 1,
m_use_hard_branching.has_value() && m_use_hard_branching.value(),
std::move(sub_problems_specifications),
Expand Down Expand Up @@ -181,3 +189,15 @@ idol::DantzigWolfe::Decomposition::with_max_parallel_sub_problems(unsigned int t
return *this;
}

idol::DantzigWolfe::Decomposition &idol::DantzigWolfe::Decomposition::with_dual_price_smoothing_stabilization(
const idol::DantzigWolfe::DualPriceSmoothingStabilization &t_stabilization) {

if (m_dual_price_smoothing_stabilization) {
throw Exception("A dual price smoothing stabilization has already been configured.");
}

m_dual_price_smoothing_stabilization.reset(t_stabilization.clone());

return *this;
}

Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
idol::Optimizers::DantzigWolfeDecomposition::DantzigWolfeDecomposition(const Model& t_model,
idol::DantzigWolfe::Formulation &&t_formulation,
const OptimizerFactory& t_master_optimizer_factory,
const DantzigWolfe::DualPriceSmoothingStabilization& t_stabilization,
unsigned int t_max_parallel_pricing,
bool t_use_hard_branching,
std::vector<idol::DantzigWolfe::SubProblem>&& t_sub_problem_specifications,
Expand All @@ -16,6 +17,7 @@ idol::Optimizers::DantzigWolfeDecomposition::DantzigWolfeDecomposition(const Mod
m_max_parallel_pricing(t_max_parallel_pricing),
m_use_hard_branching(t_use_hard_branching),
m_sub_problem_specifications(std::move(t_sub_problem_specifications)),
m_stabilization(t_stabilization()),
m_strategy(t_strategy())
{

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ void idol::Optimizers::DantzigWolfeDecomposition::ColumnGeneration::execute() {
m_status = Loaded;
m_reason = NotSpecified;
m_last_master_solution.reset();
m_stability_center.reset();
m_iteration_count = 0;
m_n_generated_columns = 0;
m_solve_dual_master = true;
Expand All @@ -25,6 +24,7 @@ void idol::Optimizers::DantzigWolfeDecomposition::ColumnGeneration::execute() {
m_is_terminated = false;
m_current_iteration_is_using_farkas = false;
initialize_sub_problem_phases();
m_parent.m_stabilization->initialize();

if (m_use_farkas_for_infeasibility) {
m_parent.m_formulation.master().optimizer().set_param_infeasible_or_unbounded_info(true);
Expand Down Expand Up @@ -96,7 +96,7 @@ void idol::Optimizers::DantzigWolfeDecomposition::ColumnGeneration::solve_dual_m
void idol::Optimizers::DantzigWolfeDecomposition::ColumnGeneration::update_sub_problems() {

auto& formulation = m_parent.m_formulation;
auto& dual_values = m_last_master_solution.value(); // TODO change this for the smoothened one
auto dual_values = m_parent.m_stabilization->compute_smoothed_dual_solution(m_last_master_solution.value());

for (unsigned int i = 0, n = formulation.n_sub_problems() ; i < n ; ++i) {
formulation.update_sub_problem_objective(i, dual_values, m_current_iteration_is_using_farkas);
Expand Down Expand Up @@ -163,7 +163,7 @@ void idol::Optimizers::DantzigWolfeDecomposition::ColumnGeneration::analyze_sub_

if (m_best_bound <= iter_lower_bound) {

m_stability_center = m_last_master_solution;
m_parent.m_stabilization->update_stability_center(m_last_master_solution.value());
m_best_bound = iter_lower_bound;

if (m_best_bound >= m_parent.get_param_best_bound_stop()) {
Expand Down

0 comments on commit 4ae65ca

Please sign in to comment.