diff --git a/README.md b/README.md index e2b5d6c3..0c3b9d14 100644 --- a/README.md +++ b/README.md @@ -101,8 +101,8 @@ auto follower_c3 = high_point_relaxation.add_ctr(2 * x - y <= 15); auto follower_c4 = high_point_relaxation.add_ctr(2 * x + 10 * y >= 15); // Prepare bilevel description -Bilevel::LowerLevelDescription description(env); -description.set_follower_obj_expr(y); +Bilevel::Description description(env); +description.set_lower_objective(y); description.set_follower_var(y); description.set_follower_ctr(follower_c1); description.set_follower_ctr(follower_c2); diff --git a/examples/bilevel/kkt.example.cpp b/examples/bilevel/kkt.example.cpp index d5c5711b..01a41bef 100644 --- a/examples/bilevel/kkt.example.cpp +++ b/examples/bilevel/kkt.example.cpp @@ -4,7 +4,7 @@ #include #include #include "idol/bilevel/optimizers/wrappers/MibS/MibS.h" -#include "idol/bilevel/modeling/LowerLevelDescription.h" +#include "idol/bilevel/modeling/Description.h" #include "idol/mixed-integer/optimizers/wrappers/Gurobi/Gurobi.h" #include "idol/bilevel/modeling/read_from_file.h" #include "idol/mixed-integer/modeling/models/KKT.h" @@ -48,13 +48,13 @@ int main(int t_argc, const char** t_argv) { high_point_relaxation.add_ctr(-x + 5 * y <= 12.5); // Prepare bilevel description - Bilevel::LowerLevelDescription description(env); - description.set_follower_obj_expr(- y); - description.make_follower_var(y); - description.make_follower_ctr(follower_c1); - description.make_follower_ctr(follower_c2); - description.make_follower_ctr(follower_c3); - description.make_follower_ctr(follower_c4); + Bilevel::Description description(env); + description.set_lower_objective(-y); + description.make_lower_level(y); + description.make_follower(follower_c1); + description.make_follower(follower_c2); + description.make_follower(follower_c3); + description.make_follower(follower_c4); Reformulators::KKT reformulator(high_point_relaxation, description); diff --git a/examples/bilevel/mibs.example.cpp b/examples/bilevel/mibs.example.cpp index 5c823ae9..47e4fc8a 100644 --- a/examples/bilevel/mibs.example.cpp +++ b/examples/bilevel/mibs.example.cpp @@ -4,7 +4,7 @@ #include #include #include "idol/bilevel/optimizers/wrappers/MibS/MibS.h" -#include "idol/bilevel/modeling/LowerLevelDescription.h" +#include "idol/bilevel/modeling/Description.h" using namespace idol; @@ -41,13 +41,13 @@ int main(int t_argc, const char** t_argv) { auto follower_c4 = high_point_relaxation.add_ctr(2 * x + 10 * y >= 15); // Prepare bilevel description - Bilevel::LowerLevelDescription description(env); - description.set_follower_obj_expr(y); - description.make_follower_var(y); - description.make_follower_ctr(follower_c1); - description.make_follower_ctr(follower_c2); - description.make_follower_ctr(follower_c3); - description.make_follower_ctr(follower_c4); + Bilevel::Description description(env); + description.set_lower_objective(y); + description.make_lower_level(y); + description.make_follower(follower_c1); + description.make_follower(follower_c2); + description.make_follower(follower_c3); + description.make_follower(follower_c4); // Use coin-or/MibS as external solver high_point_relaxation.use( diff --git a/examples/bilevel/padm.example.cpp b/examples/bilevel/padm.example.cpp index 7ba09e31..72fdff46 100644 --- a/examples/bilevel/padm.example.cpp +++ b/examples/bilevel/padm.example.cpp @@ -3,7 +3,7 @@ // #include #include -#include +#include #include #include #include "idol/mixed-integer/optimizers/padm/PADM.h" @@ -25,23 +25,23 @@ int main(int t_argc, const char** t_argv) { auto c = model.add_qctr(x + delta * x + y - 1, LessOrEqual); model.add_ctr(y == 1); - Bilevel::LowerLevelDescription description(env); - description.make_follower_var(x); - description.make_follower_var(y); - //description.make_follower_ctr(c); - description.set_follower_obj_expr(-2 * x - y); + Bilevel::Description description(env); + description.make_lower_level(x); + description.make_lower_level(y); + description.make_lower_level(c); + description.set_lower_objective(-2 * x - y); Reformulators::KKT reformulator(model, description); Model single_level(env); reformulator.add_strong_duality_reformulation(single_level); - Annotation decomposition(env, "sub_problem"); + Annotation decomposition(env, "sub_problem"); for (const auto& var : single_level.vars()) { var.set(decomposition, var.id() == delta.id()); } - Annotation penalized_constraints(env, "penalized_constraints"); + Annotation penalized_constraints(env, "penalized_constraints"); for (const auto& ctr : single_level.ctrs()) { ctr.set(penalized_constraints, true); } diff --git a/examples/mixed-integer/assignment-bap.example.cpp b/examples/mixed-integer/assignment-bap.example.cpp index 1581cb24..2263f37c 100644 --- a/examples/mixed-integer/assignment-bap.example.cpp +++ b/examples/mixed-integer/assignment-bap.example.cpp @@ -33,7 +33,7 @@ int main(int t_argc, const char** t_argv) { Model model(env); // Create decomposition annotation - Annotation decomposition(env, "decomposition", MasterId); + Annotation decomposition(env, "decomposition", MasterId); // Create assignment variables (x_ij binaries) auto x = model.add_vars(Dim<2>(n_agents, n_jobs), 0., 1., Binary, 0., "x"); diff --git a/examples/mixed-integer/assignment-penalty-bap.example.cpp b/examples/mixed-integer/assignment-penalty-bap.example.cpp index aec47622..1411eade 100644 --- a/examples/mixed-integer/assignment-penalty-bap.example.cpp +++ b/examples/mixed-integer/assignment-penalty-bap.example.cpp @@ -31,7 +31,7 @@ int main(int t_argc, const char** t_argv) { Model model(env); // Create decomposition annotation - Annotation decomposition(env, "decomposition", MasterId); + Annotation decomposition(env, "decomposition", MasterId); // Create penalized constraints annotation Annotation penalized_constraints(env, "penalized_constraints", false); diff --git a/examples/mixed-integer/facility.example.cpp b/examples/mixed-integer/facility.example.cpp index e4e19ba3..c4289b49 100644 --- a/examples/mixed-integer/facility.example.cpp +++ b/examples/mixed-integer/facility.example.cpp @@ -19,7 +19,7 @@ int main(int t_argc, const char** t_argv) { Env env; // Read instance - const auto instance = Problems::FLP::read_instance_1991_Cornuejols_et_al("/home/henri/Research/idol/tests/data/facility-location-problem/instance_F10_C20__4.txt"); + const auto instance = Problems::FLP::read_instance_1991_Cornuejols_et_al("facility.data.txt"); const unsigned int n_customers = instance.n_customers(); const unsigned int n_facilities = instance.n_facilities(); diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index d1aebb2f..224a6c66 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -184,7 +184,7 @@ add_library(idol STATIC src/bilevel/modeling/read_from_file.cpp include/idol/mixed-integer/optimizers/wrappers/Mosek/MosekCallbackI.h src/mixed-integer/optimizers/wrappers/Mosek/MosekCallbackI.cpp - include/idol/bilevel/modeling/LowerLevelDescription.h + include/idol/bilevel/modeling/Description.h include/idol/bilevel/modeling/write_to_file.h src/bilevel/modeling/write_to_file.cpp include/idol/general/utils/LimitedWidthStream.h diff --git a/lib/include/idol/bilevel/modeling/Description.h b/lib/include/idol/bilevel/modeling/Description.h new file mode 100644 index 00000000..ed7e19d2 --- /dev/null +++ b/lib/include/idol/bilevel/modeling/Description.h @@ -0,0 +1,65 @@ +// +// Created by henri on 20.06.24. +// + +#ifndef IDOL_DESCRIPTION_H +#define IDOL_DESCRIPTION_H + +#include + +#include "idol/mixed-integer/modeling/constraints/Ctr.h" +#include "idol/mixed-integer/modeling/variables/Var.h" +#include "idol/mixed-integer/modeling/objects/Versions.h" +#include "idol/mixed-integer/modeling/models/Model.h" + +namespace idol::Bilevel { + class Description; +} + +class idol::Bilevel::Description { + Annotation m_lower_level; + AffExpr m_follower_objective; +public: + Description(Env& t_env, const std::string& t_name) : m_lower_level(t_env, t_name + "_lower_level", MasterId) {} + + explicit Description(Env& t_env) : Description(t_env, "bilevel") {} + + explicit Description(const Annotation& t_lower_level) : m_lower_level(t_lower_level) {} + + Description(const Annotation& t_lower_level, + AffExpr t_follower_objective) + : m_lower_level(t_lower_level), + m_follower_objective(std::move(t_follower_objective)) {} + + [[nodiscard]] const Annotation& lower_level() const { return m_lower_level; } + + [[nodiscard]] const AffExpr& follower_obj() const { return m_follower_objective; } + + void make_leader(const Var& t_var) { t_var.set(m_lower_level, MasterId); } + + void make_leader(const Ctr& t_ctr) { t_ctr.set(m_lower_level, MasterId); } + + void make_leader(const QCtr& t_ctr) { t_ctr.set(m_lower_level, MasterId); } + + void make_lower_level(const Var& t_var) { t_var.set(m_lower_level, 0); } + + void make_follower(const Ctr& t_ctr) { t_ctr.set(m_lower_level, 0); } + + void make_lower_level(const QCtr& t_ctr) { t_ctr.set(m_lower_level, 0); } + + void set_lower_objective(AffExpr t_objective) { m_follower_objective = std::move(t_objective); } + + [[nodiscard]] bool is_leader(const Var& t_var) const { return t_var.get(m_lower_level) == MasterId; } + + [[nodiscard]] bool is_leader(const Ctr& t_ctr) const { return t_ctr.get(m_lower_level) == MasterId; } + + [[nodiscard]] bool is_leader(const QCtr& t_ctr) const { return t_ctr.get(m_lower_level) == MasterId; } + + [[nodiscard]] bool is_follower(const Var& t_var) const { return t_var.get(m_lower_level) != MasterId; } + + [[nodiscard]] bool is_follower(const Ctr& t_ctr) const { return t_ctr.get(m_lower_level) != MasterId; } + + [[nodiscard]] bool is_follower(const QCtr& t_ctr) const { return t_ctr.get(m_lower_level) != MasterId; } +}; + +#endif //IDOL_DESCRIPTION_H diff --git a/lib/include/idol/bilevel/modeling/LowerLevelDescription.h b/lib/include/idol/bilevel/modeling/LowerLevelDescription.h deleted file mode 100644 index 4070e2dd..00000000 --- a/lib/include/idol/bilevel/modeling/LowerLevelDescription.h +++ /dev/null @@ -1,67 +0,0 @@ -// -// Created by henri on 20.06.24. -// - -#ifndef IDOL_LOWERLEVELDESCRIPTION_H -#define IDOL_LOWERLEVELDESCRIPTION_H - -#include - -#include "idol/mixed-integer/modeling/constraints/Ctr.h" -#include "idol/mixed-integer/modeling/variables/Var.h" -#include "idol/mixed-integer/modeling/objects/Versions.h" -#include "idol/mixed-integer/modeling/models/Model.h" - -namespace idol::Bilevel { - class LowerLevelDescription; -} - -class idol::Bilevel::LowerLevelDescription { - Annotation m_follower_variables; - Annotation m_follower_constraints; - AffExpr m_follower_objective; -public: - LowerLevelDescription(Env& t_env, const std::string& t_name) - : m_follower_variables(t_env, t_name + "_follower_variables", MasterId), - m_follower_constraints(t_env, t_name + "_follower_constraints", MasterId) {} - - explicit LowerLevelDescription(Env& t_env) : LowerLevelDescription(t_env, "bilevel") {} - - LowerLevelDescription(const Annotation& t_follower_variables, - const Annotation& t_follower_constraints) - : m_follower_variables(t_follower_variables), - m_follower_constraints(t_follower_constraints) {} - - LowerLevelDescription(const Annotation& t_follower_variables, - const Annotation& t_follower_constraints, - AffExpr t_follower_objective) - : m_follower_variables(t_follower_variables), - m_follower_constraints(t_follower_constraints), - m_follower_objective(std::move(t_follower_objective)) {} - - [[nodiscard]] const Annotation& follower_vars() const { return m_follower_variables; } - - [[nodiscard]] const Annotation& follower_ctrs() const { return m_follower_constraints; } - - [[nodiscard]] const AffExpr& follower_obj() const { return m_follower_objective; } - - void make_leader_var(const Var& t_var) { t_var.set(m_follower_variables, MasterId); } - - void make_leader_ctr(const Ctr& t_ctr) { t_ctr.set(m_follower_constraints, MasterId); } - - void make_follower_var(const Var& t_var) { t_var.set(m_follower_variables, 0); } - - void make_follower_ctr(const Ctr& t_ctr) { t_ctr.set(m_follower_constraints, 0); } - - void set_follower_obj_expr(AffExpr t_objective) { m_follower_objective = std::move(t_objective); } - - bool is_leader(const Var& t_var) const { return t_var.get(m_follower_variables) == MasterId; } - - bool is_leader(const Ctr& t_ctr) const { return t_ctr.get(m_follower_constraints) == MasterId; } - - bool is_follower(const Var& t_var) const { return t_var.get(m_follower_variables) != MasterId; } - - bool is_follower(const Ctr& t_ctr) const { return t_ctr.get(m_follower_constraints) != MasterId; } -}; - -#endif //IDOL_LOWERLEVELDESCRIPTION_H diff --git a/lib/include/idol/bilevel/modeling/read_from_file.h b/lib/include/idol/bilevel/modeling/read_from_file.h index 7a3552e6..a44d0bc1 100644 --- a/lib/include/idol/bilevel/modeling/read_from_file.h +++ b/lib/include/idol/bilevel/modeling/read_from_file.h @@ -7,7 +7,7 @@ #include #include "idol/mixed-integer/modeling/models/Model.h" -#include "LowerLevelDescription.h" +#include "Description.h" namespace idol::Bilevel { @@ -15,13 +15,13 @@ namespace idol::Bilevel { idol::Model read_from_file(Env &t_env, const std::string &t_path_to_aux, - idol::Bilevel::LowerLevelDescription& t_lower_level_description, + idol::Bilevel::Description& t_lower_level_description, const std::function &t_mps_reader); } - template Model read_from_file(Env& t_env, const std::string& t_path_to_aux, Bilevel::LowerLevelDescription& t_lower_level_description); + template Model read_from_file(Env& t_env, const std::string& t_path_to_aux, Bilevel::Description& t_lower_level_description); - template std::pair read_from_file(Env& t_env, const std::string& t_path_to_aux); + template std::pair read_from_file(Env& t_env, const std::string& t_path_to_aux); } @@ -29,17 +29,17 @@ template idol::Model idol::Bilevel::read_from_file(idol::Env& t_env, const std::string& t_path_to_aux, - idol::Bilevel::LowerLevelDescription& t_lower_level_description) { + idol::Bilevel::Description& t_lower_level_description) { return idol::Bilevel::impl::read_from_file(t_env, t_path_to_aux, t_lower_level_description, [](Env& t_env, const std::string& t_file) { return BackendT::read_from_file(t_env, t_file); }); } template -std::pair +std::pair idol::Bilevel::read_from_file(idol::Env& t_env, const std::string& t_path_to_aux) { - Bilevel::LowerLevelDescription lower_level_description(t_env); + Bilevel::Description lower_level_description(t_env); auto high_point_relaxation = Bilevel::impl::read_from_file(t_env, t_path_to_aux, lower_level_description,[](Env& t_env, const std::string& t_file) { return BackendT::read_from_file(t_env, t_file); }); diff --git a/lib/include/idol/bilevel/modeling/write_to_file.h b/lib/include/idol/bilevel/modeling/write_to_file.h index 8ec91bbf..1d358bc2 100644 --- a/lib/include/idol/bilevel/modeling/write_to_file.h +++ b/lib/include/idol/bilevel/modeling/write_to_file.h @@ -7,10 +7,10 @@ #include #include "idol/mixed-integer/modeling/models/Model.h" -#include "LowerLevelDescription.h" +#include "Description.h" namespace idol::Bilevel { - void write_to_file(const Model& t_model, const Bilevel::LowerLevelDescription& t_description, const std::string& t_filename); + void write_to_file(const Model& t_model, const Bilevel::Description& t_description, const std::string& t_filename); } #endif //IDOL_WRITE_TO_FILE_H diff --git a/lib/include/idol/bilevel/optimizers/wrappers/MibS/MibS.h b/lib/include/idol/bilevel/optimizers/wrappers/MibS/MibS.h index 16caaf3d..80bafdcb 100644 --- a/lib/include/idol/bilevel/optimizers/wrappers/MibS/MibS.h +++ b/lib/include/idol/bilevel/optimizers/wrappers/MibS/MibS.h @@ -9,7 +9,7 @@ #include "idol/general/optimizers/OptimizerFactory.h" #include "idol/mixed-integer/modeling/annotations/Annotation.h" #include "idol/mixed-integer/modeling/constraints/Ctr.h" -#include "idol/bilevel/modeling/LowerLevelDescription.h" +#include "idol/bilevel/modeling/Description.h" #include "idol/mixed-integer/optimizers/callbacks/CallbackFactory.h" #ifdef IDOL_USE_OSI @@ -23,7 +23,7 @@ namespace idol::Bilevel { class OsiSolverInterface; class idol::Bilevel::MibS : public OptimizerFactoryWithDefaultParameters { - Bilevel::LowerLevelDescription m_description; + Bilevel::Description m_description; std::optional m_use_file_interface; std::optional m_use_cplex_for_feasibility; std::list> m_callbacks; @@ -31,7 +31,7 @@ class idol::Bilevel::MibS : public OptimizerFactoryWithDefaultParameters { std::unique_ptr m_osi_interface; #endif public: - MibS(Bilevel::LowerLevelDescription t_description); + MibS(Bilevel::Description t_description); MibS(const MibS& t_src); MibS(MibS&&) noexcept = delete; diff --git a/lib/include/idol/bilevel/optimizers/wrappers/MibS/Optimizers_MibS.h b/lib/include/idol/bilevel/optimizers/wrappers/MibS/Optimizers_MibS.h index 5eb6c934..b040aa1e 100644 --- a/lib/include/idol/bilevel/optimizers/wrappers/MibS/Optimizers_MibS.h +++ b/lib/include/idol/bilevel/optimizers/wrappers/MibS/Optimizers_MibS.h @@ -11,7 +11,7 @@ #include "idol/general/optimizers/Optimizer.h" #include "idol/mixed-integer/modeling/annotations/Annotation.h" #include "idol/mixed-integer/modeling/constraints/Ctr.h" -#include "idol/bilevel/modeling/LowerLevelDescription.h" +#include "idol/bilevel/modeling/Description.h" #include "impl_MibS.h" #include "idol/mixed-integer/optimizers/callbacks/Callback.h" @@ -20,7 +20,7 @@ namespace idol::Optimizers::Bilevel { } class idol::Optimizers::Bilevel::MibS : public Optimizer { - const idol::Bilevel::LowerLevelDescription m_description; + const idol::Bilevel::Description m_description; std::unique_ptr m_mibs; std::unique_ptr m_osi_solver; @@ -30,7 +30,7 @@ class idol::Optimizers::Bilevel::MibS : public Optimizer { std::list> m_callbacks; public: MibS(const idol::Model& t_parent, - idol::Bilevel::LowerLevelDescription t_description, + idol::Bilevel::Description t_description, OsiSolverInterface* t_osi_solver, bool t_use_file, bool t_use_cplex_for_feasibility); diff --git a/lib/include/idol/bilevel/optimizers/wrappers/MibS/impl_MibSFromAPI.h b/lib/include/idol/bilevel/optimizers/wrappers/MibS/impl_MibSFromAPI.h index 99c7175a..3d0079e5 100644 --- a/lib/include/idol/bilevel/optimizers/wrappers/MibS/impl_MibSFromAPI.h +++ b/lib/include/idol/bilevel/optimizers/wrappers/MibS/impl_MibSFromAPI.h @@ -9,7 +9,7 @@ #include "idol/mixed-integer/modeling/models/Model.h" #include "MibSModel.hpp" -#include "idol/bilevel/modeling/LowerLevelDescription.h" +#include "idol/bilevel/modeling/Description.h" #include "impl_MibS.h" #include "idol/mixed-integer/optimizers/callbacks/Callback.h" @@ -22,7 +22,7 @@ namespace idol { class idol::impl::MibSFromAPI : public idol::impl::MibS { const idol::Model& m_model; - const idol::Bilevel::LowerLevelDescription& m_description; + const idol::Bilevel::Description& m_description; const std::list>& m_callbacks; const bool m_logs; const bool m_use_cplex_for_feasibility; @@ -46,7 +46,7 @@ class idol::impl::MibSFromAPI : public idol::impl::MibS { std::vector parse_objective(); public: MibSFromAPI(const idol::Model& t_model, - const idol::Bilevel::LowerLevelDescription& t_description, + const idol::Bilevel::Description& t_description, OsiSolverInterface* t_osi_solver, const std::list>& t_callbacks, bool t_use_cplex_for_feasibility, diff --git a/lib/include/idol/bilevel/optimizers/wrappers/MibS/impl_MibSFromFile.h b/lib/include/idol/bilevel/optimizers/wrappers/MibS/impl_MibSFromFile.h index c8efeaac..bedb865c 100644 --- a/lib/include/idol/bilevel/optimizers/wrappers/MibS/impl_MibSFromFile.h +++ b/lib/include/idol/bilevel/optimizers/wrappers/MibS/impl_MibSFromFile.h @@ -10,7 +10,7 @@ #include "idol/mixed-integer/modeling/models/Model.h" #include "MibSModel.hpp" -#include "idol/bilevel/modeling/LowerLevelDescription.h" +#include "idol/bilevel/modeling/Description.h" #include "impl_MibS.h" namespace idol::impl { @@ -19,7 +19,7 @@ namespace idol::impl { class idol::impl::MibSFromFile : public idol::impl::MibS { const idol::Model& m_model; - const idol::Bilevel::LowerLevelDescription& m_description; + const idol::Bilevel::Description& m_description; const bool m_logs; const bool m_use_cplex_for_feasibility; @@ -31,7 +31,7 @@ class idol::impl::MibSFromFile : public idol::impl::MibS { void make_variable_index_in_mps(); public: MibSFromFile(const idol::Model& t_model, - const idol::Bilevel::LowerLevelDescription& t_description, + const idol::Bilevel::Description& t_description, OsiSolverInterface* t_osi_solver, bool t_use_cplex_for_feasibility, bool t_logs); diff --git a/lib/include/idol/mixed-integer/modeling/annotations/Annotation.h b/lib/include/idol/mixed-integer/modeling/annotations/Annotation.h index 97343df8..5997a285 100644 --- a/lib/include/idol/mixed-integer/modeling/annotations/Annotation.h +++ b/lib/include/idol/mixed-integer/modeling/annotations/Annotation.h @@ -8,75 +8,29 @@ #include "impl_Annotation.h" namespace idol { - class Var; - class Ctr; - - template + template class Annotation; } -template +template class idol::Annotation : public impl::Annotation { - static_assert(std::is_same_v || std::is_same_v); public: - /** - * Constructor. - * - * Creates a new annotation stored in `t_env` with name `t_name`. No default value is given. - * @param t_env The environment which will store the annotation - * @param t_name The given name to the annotation - */ - Annotation(Env& t_env, std::string t_name) : impl::Annotation(t_env, std::is_same_v, std::move(t_name)) {} + Annotation(Env& t_env, std::string t_name) : impl::Annotation(t_env, std::move(t_name)) {} - /** - * Constructor. - * - * Creates a new annotation stored in `t_env` with name `t_name` and a default value. The default value is built - * "in place" by calling the constructor of `ValueT` with the arguments given after `t_name`. - * @tparam ArgsT Parameter pack template types for constructing the default value of the annotation - * @param t_env The environment which will store the annotation - * @param t_name The given name to the annotation - * @param t_args Parameter pack arguments for constructing the default value of the annotation - */ template Annotation(Env& t_env, std::string t_name, ArgsT&& ...t_args) - : impl::Annotation(t_env, std::is_same_v, std::move(t_name)) { + : impl::Annotation(t_env, std::move(t_name)) { set_default_value(std::forward(t_args)...); } - /** - * Creates a new annotation stored in `t_env` with name `t_name` and a default value. The default value is built - * "in place" by calling the constructor of `ValueT` with the arguments given after `t_name`. - * @tparam ArgsT Parameter pack template types for constructing the default value of the annotation - * @param t_env The environment which will store the annotation - * @param t_name The given name to the annotation - * @param t_args Parameter pack arguments for constructing the default value of the annotation - * @return The created annotation - */ template - static Annotation make_with_default_value(Env& t_env, std::string t_name, ArgsT&& ...t_args) { - Annotation result(t_env, std::move(t_name)); + static Annotation make_with_default_value(Env& t_env, std::string t_name, ArgsT&& ...t_args) { + Annotation result(t_env, std::move(t_name)); result.set_default_value(std::forward(t_args)...); return result; } - /** - * Returns true if the annotation is for variables, false otherwise. - * @return true if the annotation is for variables, false otherwise - */ - [[nodiscard]] bool is_var_annotation() const override { return std::is_same_v; } - - /** - * Returns true if the annotation is for constraints, false otherwise. - * @return true if the annotation is for constraints, false otherwise - */ - [[nodiscard]] bool is_ctr_annotation() const override { return std::is_same_v; } - - /** - * Returns the default value of the annotation. - * @return The default value of the annotation - */ [[nodiscard]] const ValueT& default_value() const { return impl::Annotation::cast_default_value(); } }; diff --git a/lib/include/idol/mixed-integer/modeling/annotations/impl_Annotation.h b/lib/include/idol/mixed-integer/modeling/annotations/impl_Annotation.h index 5d80bda6..41826e5d 100644 --- a/lib/include/idol/mixed-integer/modeling/annotations/impl_Annotation.h +++ b/lib/include/idol/mixed-integer/modeling/annotations/impl_Annotation.h @@ -31,14 +31,10 @@ class idol::impl::Annotation { template void set_default_value(ArgsT&& ...t_args); template [[nodiscard]] const T& cast_default_value() const { return std::any_cast(m_id->default_value); } public: - Annotation(::idol::Env& t_env, bool t_is_var_annotation, std::string&& t_name); + Annotation(::idol::Env& t_env, std::string&& t_name); virtual ~Annotation() = default; - [[nodiscard]] virtual bool is_var_annotation() const = 0; - - [[nodiscard]] virtual bool is_ctr_annotation() const = 0; - /** * Returns the id of the annotation. * diff --git a/lib/include/idol/mixed-integer/modeling/models/KKT.h b/lib/include/idol/mixed-integer/modeling/models/KKT.h index 42a6e647..d8a05afd 100644 --- a/lib/include/idol/mixed-integer/modeling/models/KKT.h +++ b/lib/include/idol/mixed-integer/modeling/models/KKT.h @@ -6,7 +6,7 @@ #define IDOL_KKT_H #include "Model.h" -#include "idol/bilevel/modeling/LowerLevelDescription.h" +#include "idol/bilevel/modeling/Description.h" namespace idol::Reformulators { class KKT; @@ -15,7 +15,7 @@ namespace idol::Reformulators { class idol::Reformulators::KKT { const Model& m_src_model; - const Bilevel::LowerLevelDescription& m_description; + const Bilevel::Description& m_description; std::vector> m_dual_variables_for_constraints; std::vector> m_dual_variables_for_lower_bounds; @@ -32,7 +32,7 @@ class idol::Reformulators::KKT { void create_dual_objective(); public: KKT(const Model& t_src_model, - const Bilevel::LowerLevelDescription& t_lower_level_description); + const Bilevel::Description& t_lower_level_description); void add_primal_variables(idol::Model &t_destination) const; void add_primal_constraints(Model &t_destination) const; diff --git a/lib/include/idol/mixed-integer/modeling/objects/Env.h b/lib/include/idol/mixed-integer/modeling/objects/Env.h index 94553697..ac27f00d 100644 --- a/lib/include/idol/mixed-integer/modeling/objects/Env.h +++ b/lib/include/idol/mixed-integer/modeling/objects/Env.h @@ -52,8 +52,7 @@ class idol::impl::Env { unsigned int m_max_object_id = 0; IdProvider<1> m_model_ids; - IdProvider<0> m_var_annotation_ids; - IdProvider<0> m_ctr_annotation_ids; + IdProvider<0> m_annotation_ids; std::list> m_variables; /// Every version of each variable in the environment is stored here std::list> m_constraints; /// Every version of each constraint in the environment is stored here @@ -71,7 +70,7 @@ class idol::impl::Env { void free_model_id(const ::idol::Model& t_model); - unsigned int create_annotation_id(bool t_is_variable) { return t_is_variable ? m_var_annotation_ids.create() : m_ctr_annotation_ids.create(); } + unsigned int create_annotation_id() { return m_annotation_ids.create(); } void free_annotation_id(const impl::Annotation& t_annotation); diff --git a/lib/include/idol/mixed-integer/modeling/objects/Object.h b/lib/include/idol/mixed-integer/modeling/objects/Object.h index fb588341..bd9eadbb 100644 --- a/lib/include/idol/mixed-integer/modeling/objects/Object.h +++ b/lib/include/idol/mixed-integer/modeling/objects/Object.h @@ -75,7 +75,7 @@ class idol::Object { * @param t_annotation The annotation. * @return The value of the annotation. */ - template const ValueT& get(const Annotation& t_annotation) const { + template const ValueT& get(const Annotation& t_annotation) const { const auto& result = m_object_id->versions().template get_annotation(t_annotation.id()); if (result) { return *result; @@ -93,7 +93,7 @@ class idol::Object { * @param t_annotation The annotation. * @param t_args The parameter pack arguments used to construct "in place" the value of the annotation. */ - template void set(const Annotation& t_annotation, ArgsT&& ...t_args) const { m_object_id->versions().template set_annotation(t_annotation.id(), std::forward(t_args)...); } + template void set(const Annotation& t_annotation, ArgsT&& ...t_args) const { m_object_id->versions().template set_annotation(t_annotation.id(), std::forward(t_args)...); } }; namespace idol { diff --git a/lib/include/idol/mixed-integer/optimizers/dantzig-wolfe/DantzigWolfeDecomposition.h b/lib/include/idol/mixed-integer/optimizers/dantzig-wolfe/DantzigWolfeDecomposition.h index 670850b3..3504c872 100644 --- a/lib/include/idol/mixed-integer/optimizers/dantzig-wolfe/DantzigWolfeDecomposition.h +++ b/lib/include/idol/mixed-integer/optimizers/dantzig-wolfe/DantzigWolfeDecomposition.h @@ -19,8 +19,7 @@ namespace idol { } class idol::DantzigWolfeDecomposition : public OptimizerFactoryWithDefaultParameters { - std::optional> m_ctr_decomposition; - std::optional> m_var_decomposition; + std::optional> m_decomposition; std::unique_ptr m_master_optimizer_factory; std::unique_ptr m_infeasibility_strategy; std::unique_ptr m_dual_price_smoothing_stabilization; @@ -31,21 +30,18 @@ class idol::DantzigWolfeDecomposition : public OptimizerFactoryWithDefaultParame std::optional m_default_sub_problem_spec; Map m_sub_problem_specs; - std::vector create_sub_problems_specifications(const DantzigWolfe::Formulation &t_dantzig_wolfe_formulation) const; + [[nodiscard]] std::vector create_sub_problems_specifications(const DantzigWolfe::Formulation &t_dantzig_wolfe_formulation) const; static void add_aggregation_constraints(DantzigWolfe::Formulation& t_dantzig_wolfe_formulation, const std::vector& t_sub_problem_specifications) ; public: DantzigWolfeDecomposition() = default; - explicit DantzigWolfeDecomposition(Annotation t_decomposition); - - DantzigWolfeDecomposition(Annotation t_ctr_decomposition, - Annotation t_var_decomposition); + explicit DantzigWolfeDecomposition(Annotation t_decomposition); DantzigWolfeDecomposition(const DantzigWolfeDecomposition& t_src); Optimizer *operator()(const Model &t_model) const override; - DantzigWolfeDecomposition *clone() const override; + [[nodiscard]] DantzigWolfeDecomposition *clone() const override; DantzigWolfeDecomposition& with_master_optimizer(const OptimizerFactory& t_optimizer_factory); @@ -65,7 +61,7 @@ class idol::DantzigWolfeDecomposition : public OptimizerFactoryWithDefaultParame DantzigWolfeDecomposition& with_dual_price_smoothing_stabilization(const DantzigWolfe::DualPriceSmoothingStabilization& t_stabilization); - const DantzigWolfe::SubProblem& get_sub_problem_spec(unsigned int t_id) const; + [[nodiscard]] const DantzigWolfe::SubProblem& get_sub_problem_spec(unsigned int t_id) const; }; #endif //IDOL_DANTZIGWOLFEDECOMPOSITION_H diff --git a/lib/include/idol/mixed-integer/optimizers/dantzig-wolfe/Formulation.h b/lib/include/idol/mixed-integer/optimizers/dantzig-wolfe/Formulation.h index 025ddcf8..dc5173b3 100644 --- a/lib/include/idol/mixed-integer/optimizers/dantzig-wolfe/Formulation.h +++ b/lib/include/idol/mixed-integer/optimizers/dantzig-wolfe/Formulation.h @@ -16,8 +16,7 @@ namespace idol::DantzigWolfe { class idol::DantzigWolfe::Formulation { using PresentGeneratorsList = std::list>; - Annotation m_decomposition_by_ctr; - Annotation m_decomposition_by_var; + Annotation m_decomposition; struct GenerationPattern { AffExpr objective; @@ -49,11 +48,7 @@ class idol::DantzigWolfe::Formulation { void apply_sub_problem_bound_on_master(bool t_is_lb, const idol::Var &t_var, unsigned int t_sub_problem_id, double t_value); LinExpr reformulate_sub_problem_variable(const Var &t_var, unsigned int t_sub_problem_id); public: - Formulation(const Model& t_original_formulation, const Annotation& t_decomposition); - - Formulation(const Model& t_original_formulation, - Annotation t_ctr_decomposition, - Annotation t_var_decomposition); + Formulation(const Model& t_original_formulation, const Annotation& t_decomposition); Model& master() { return m_master; } const Model& master() const { return m_master; } @@ -72,9 +67,7 @@ class idol::DantzigWolfe::Formulation { Model& get_model(const Ctr& t_ctr); const Model& get_model(const Ctr& t_ctr) const; - const Annotation& decomposition_by_constraint() const { return m_decomposition_by_ctr; } - - const Annotation& decomposition_by_variable() const { return m_decomposition_by_var; } + const Annotation& decomposition() const { return m_decomposition; } const GeneratorPool& column_pool(unsigned int t_sub_problem_id) const { return m_pools[t_sub_problem_id]; } diff --git a/lib/include/idol/mixed-integer/optimizers/padm/Formulation.h b/lib/include/idol/mixed-integer/optimizers/padm/Formulation.h index e672645c..b1c45715 100644 --- a/lib/include/idol/mixed-integer/optimizers/padm/Formulation.h +++ b/lib/include/idol/mixed-integer/optimizers/padm/Formulation.h @@ -20,30 +20,30 @@ namespace idol { class idol::ADM::Formulation { public: Formulation(const Model& t_src_model, - Annotation t_decomposition, - std::optional> t_penalized_constraints, + Annotation t_decomposition, + std::optional> t_penalized_constraints, bool t_independent_penalty_update, std::pair t_rescaling); Model& sub_problem(const Var& t_var); - const Model& sub_problem(const Var& t_var) const; + [[nodiscard]] const Model& sub_problem(const Var& t_var) const; - unsigned int sub_problem_id(const Var& t_var) const; + [[nodiscard]] unsigned int sub_problem_id(const Var& t_var) const; Model& sub_problem(unsigned int t_sub_problem_id) { return m_sub_problems[t_sub_problem_id]; } - const Model& sub_problem(unsigned int t_sub_problem_id) const { return m_sub_problems[t_sub_problem_id]; } + [[nodiscard]] const Model& sub_problem(unsigned int t_sub_problem_id) const { return m_sub_problems[t_sub_problem_id]; } - unsigned int n_sub_problems() const { return m_sub_problems.size(); } + [[nodiscard]] unsigned int n_sub_problems() const { return m_sub_problems.size(); } auto sub_problems() { return IteratorForward(m_sub_problems); } - auto sub_problems() const { return ConstIteratorForward(m_sub_problems); } + [[nodiscard]] auto sub_problems() const { return ConstIteratorForward(m_sub_problems); } - auto l1_vars(unsigned int t_sub_problem_id) const { return ConstIteratorForward(m_l1_vars_in_sub_problem[t_sub_problem_id]); } + [[nodiscard]] auto l1_vars(unsigned int t_sub_problem_id) const { return ConstIteratorForward(m_l1_vars_in_sub_problem[t_sub_problem_id]); } - bool has_penalized_constraints() const { return m_penalized_constraints.has_value(); } + [[nodiscard]] bool has_penalized_constraints() const { return m_penalized_constraints.has_value(); } void fix_sub_problem(unsigned int t_sub_problem_id, const std::vector& t_primals); @@ -61,8 +61,8 @@ class idol::ADM::Formulation { }; private: - Annotation m_decomposition; - std::optional> m_penalized_constraints; + Annotation m_decomposition; + std::optional> m_penalized_constraints; bool m_independent_penalty_update; std::pair m_rescaling; @@ -72,7 +72,7 @@ class idol::ADM::Formulation { std::vector> m_l1_vars_in_sub_problem; Map m_l1_vars; - unsigned int compute_n_sub_problems(const Model& t_src_model) const; + [[nodiscard]] unsigned int compute_n_sub_problems(const Model& t_src_model) const; void initialize_sub_problems(const Model& t_src_model, unsigned int n_sub_problems); void initialize_patterns(const Model& t_src_model, unsigned int n_sub_problems); void initialize_slacks(const Model& t_src_model, unsigned int n_sub_problems); diff --git a/lib/include/idol/mixed-integer/optimizers/padm/PADM.h b/lib/include/idol/mixed-integer/optimizers/padm/PADM.h index 898b53be..449b4c30 100644 --- a/lib/include/idol/mixed-integer/optimizers/padm/PADM.h +++ b/lib/include/idol/mixed-integer/optimizers/padm/PADM.h @@ -20,9 +20,9 @@ namespace idol { class idol::PADM : public OptimizerFactoryWithDefaultParameters { public: - explicit PADM(Annotation t_decomposition); + explicit PADM(Annotation t_decomposition); - PADM(Annotation t_decomposition, Annotation t_penalized_constraints); + PADM(Annotation t_decomposition, Annotation t_penalized_constraints); PADM(const PADM& t_src); PADM(PADM&&) = default; @@ -50,8 +50,8 @@ class idol::PADM : public OptimizerFactoryWithDefaultParameters { OptimizerFactory *clone() const override; private: - Annotation m_decomposition; - std::optional> m_penalized_constraints; + Annotation m_decomposition; + std::optional> m_penalized_constraints; std::optional m_default_sub_problem_spec; Map m_sub_problem_specs; std::optional> m_rescaling; diff --git a/lib/include/idol/mixed-integer/optimizers/padm/PenaltyMethod.h b/lib/include/idol/mixed-integer/optimizers/padm/PenaltyMethod.h index 68868fc5..ce0f14f4 100644 --- a/lib/include/idol/mixed-integer/optimizers/padm/PenaltyMethod.h +++ b/lib/include/idol/mixed-integer/optimizers/padm/PenaltyMethod.h @@ -20,12 +20,12 @@ namespace idol { class idol::PenaltyMethod : public OptimizerFactoryWithDefaultParameters { public: - explicit PenaltyMethod(Annotation t_penalized_constraints); + explicit PenaltyMethod(Annotation t_penalized_constraints); PenaltyMethod(const PenaltyMethod& t_src); PenaltyMethod(PenaltyMethod&&) = default; - PenaltyMethod& operator=(const PenaltyMethod&) = default; + PenaltyMethod& operator=(const PenaltyMethod&) = delete; PenaltyMethod& operator=(PenaltyMethod&&) = default; PenaltyMethod& with_optimizer(const OptimizerFactory& t_optimizer_factory); @@ -42,10 +42,10 @@ class idol::PenaltyMethod : public OptimizerFactoryWithDefaultParameters m_decomposition; - Annotation m_penalized_constraints; + Annotation m_decomposition; + Annotation m_penalized_constraints; std::unique_ptr m_optimizer; std::optional> m_rescaling; std::unique_ptr m_penalty_update; diff --git a/lib/include/idol/robust/modeling/StageDescription.h b/lib/include/idol/robust/modeling/StageDescription.h index 882826ca..d07d24ce 100644 --- a/lib/include/idol/robust/modeling/StageDescription.h +++ b/lib/include/idol/robust/modeling/StageDescription.h @@ -15,7 +15,7 @@ namespace idol::Robust { class idol::Robust::StageDescription { Annotation m_stage_variables; - Annotation m_stage_constraints; + Annotation m_stage_constraints; public: StageDescription(Env& t_env, const std::string& t_name) : m_stage_variables(t_env, t_name + "_stage_variables", MasterId), @@ -24,13 +24,13 @@ class idol::Robust::StageDescription { explicit StageDescription(Env& t_env) : StageDescription(t_env, "robust") {} StageDescription(const Annotation& t_stage_variables, - const Annotation& t_stage_constraints) + const Annotation& t_stage_constraints) : m_stage_variables(t_stage_variables), m_stage_constraints(t_stage_constraints) {} [[nodiscard]] const Annotation& stage_vars() const { return m_stage_variables; } - [[nodiscard]] const Annotation& stage_ctrs() const { return m_stage_constraints; } + [[nodiscard]] const Annotation& stage_ctrs() const { return m_stage_constraints; } void set_stage(const Var& t_var, unsigned int t_stage) { if (t_stage == 0) { diff --git a/lib/src/bilevel/modeling/read_from_file.cpp b/lib/src/bilevel/modeling/read_from_file.cpp index 58f85b88..d11d0cd2 100644 --- a/lib/src/bilevel/modeling/read_from_file.cpp +++ b/lib/src/bilevel/modeling/read_from_file.cpp @@ -20,7 +20,7 @@ class AuxParser { unsigned int m_n_variables = 0; unsigned int m_n_constraints = 0; std::unique_ptr m_high_point_relaxation; - Bilevel::LowerLevelDescription& m_lower_level_description; + Bilevel::Description& m_lower_level_description; void read_aux_file(const std::string& t_path_to_aux, const std::function& t_read_model_from_file); bool read_tag(std::ifstream& t_file, const std::string& t_tag, bool t_mandatory = true); @@ -38,7 +38,7 @@ class AuxParser { void create_lower_level_objective(); public: explicit AuxParser(Env& t_env, - Bilevel::LowerLevelDescription& t_lower_level_description, + Bilevel::Description& t_lower_level_description, const std::string& t_path_to_aux, const std::function& t_create_model_from_mps); @@ -46,7 +46,7 @@ class AuxParser { }; AuxParser::AuxParser(Env &t_env, - Bilevel::LowerLevelDescription &t_lower_level_description, + Bilevel::Description &t_lower_level_description, const std::string& t_path_to_aux, const std::function& t_create_model_from_mps ) @@ -206,11 +206,11 @@ void AuxParser::set_var_annotations() { for (const auto& var : m_high_point_relaxation->vars()) { if (m_lower_level_variables.find(var.name()) == m_lower_level_variables.end()) { - m_lower_level_description.make_leader_var(var); + m_lower_level_description.make_leader(var); continue; } - m_lower_level_description.make_follower_var(var); + m_lower_level_description.make_lower_level(var); } @@ -221,11 +221,11 @@ void AuxParser::set_ctr_annotations() { for (const auto& ctr : m_high_point_relaxation->ctrs()) { if (m_lower_level_constraints.find(ctr.name()) == m_lower_level_constraints.end()) { - m_lower_level_description.make_leader_ctr(ctr); + m_lower_level_description.make_leader(ctr); continue; } - m_lower_level_description.make_follower_ctr(ctr); + m_lower_level_description.make_follower(ctr); } @@ -243,13 +243,13 @@ void AuxParser::create_lower_level_objective() { } - m_lower_level_description.set_follower_obj_expr(std::move(obj)); + m_lower_level_description.set_lower_objective(std::move(obj)); } idol::Model idol::Bilevel::impl::read_from_file(Env& t_env, const std::string& t_path_to_aux, - Bilevel::LowerLevelDescription& t_lower_level_description, + Bilevel::Description& t_lower_level_description, const std::function& t_mps_reader) { AuxParser parser(t_env, t_lower_level_description, t_path_to_aux, t_mps_reader); diff --git a/lib/src/bilevel/modeling/write_to_file.cpp b/lib/src/bilevel/modeling/write_to_file.cpp index fe8f4dce..71c65fd3 100644 --- a/lib/src/bilevel/modeling/write_to_file.cpp +++ b/lib/src/bilevel/modeling/write_to_file.cpp @@ -9,13 +9,13 @@ using namespace idol; class AuxWriter { const Model& m_model; - const Bilevel::LowerLevelDescription& m_description; + const Bilevel::Description& m_description; const std::string& m_filename; protected: std::list make_lower_level_vars_list(); std::list make_lower_level_ctrs_list(); public: - AuxWriter(const Model& t_model, const Bilevel::LowerLevelDescription& t_description, const std::string& t_filename) + AuxWriter(const Model& t_model, const Bilevel::Description& t_description, const std::string& t_filename) : m_model(t_model), m_description(t_description), m_filename(t_filename) {} void write(); }; @@ -54,7 +54,7 @@ std::list AuxWriter::make_lower_level_vars_list() { std::list result; - const auto& follower_vars = m_description.follower_vars(); + const auto& follower_vars = m_description.lower_level(); for (const auto& var : m_model.vars()) { if (var.get(follower_vars) != MasterId) { @@ -69,10 +69,10 @@ std::list AuxWriter::make_lower_level_ctrs_list() { std::list result; - const auto& follower_ctrs = m_description.follower_ctrs(); + const auto& lower_level = m_description.lower_level(); for (const auto& ctr : m_model.ctrs()) { - if (ctr.get(follower_ctrs) != MasterId) { + if (ctr.get(lower_level) != MasterId) { result.emplace_back(ctr); } } @@ -82,12 +82,12 @@ std::list AuxWriter::make_lower_level_ctrs_list() { class MpsWriter { const Model &m_model; - const Bilevel::LowerLevelDescription &m_description; + const Bilevel::Description &m_description; const std::string &m_filename; protected: std::list make_vars_list(const std::function& t_filter); public: - MpsWriter(const Model &t_model, const Bilevel::LowerLevelDescription &t_description, const std::string &t_filename) + MpsWriter(const Model &t_model, const Bilevel::Description &t_description, const std::string &t_filename) : m_model(t_model), m_description(t_description), m_filename(t_filename) {} void write(); }; @@ -197,7 +197,7 @@ std::list MpsWriter::make_vars_list(const std::function return result; } -void idol::Bilevel::write_to_file(const Model& t_model, const Bilevel::LowerLevelDescription& t_description, const std::string& t_filename) { +void idol::Bilevel::write_to_file(const Model& t_model, const Bilevel::Description& t_description, const std::string& t_filename) { // LP file MpsWriter(t_model, t_description, t_filename).write(); diff --git a/lib/src/bilevel/optimizers/wrappers/MibS/MibS.cpp b/lib/src/bilevel/optimizers/wrappers/MibS/MibS.cpp index 450426c0..75e1f95b 100644 --- a/lib/src/bilevel/optimizers/wrappers/MibS/MibS.cpp +++ b/lib/src/bilevel/optimizers/wrappers/MibS/MibS.cpp @@ -15,7 +15,7 @@ #include #endif -idol::Bilevel::MibS::MibS(Bilevel::LowerLevelDescription t_description) +idol::Bilevel::MibS::MibS(Bilevel::Description t_description) : m_description(std::move(t_description)) { } diff --git a/lib/src/bilevel/optimizers/wrappers/MibS/Optimizers_MibS.cpp b/lib/src/bilevel/optimizers/wrappers/MibS/Optimizers_MibS.cpp index 2440cfe9..0620bfd8 100644 --- a/lib/src/bilevel/optimizers/wrappers/MibS/Optimizers_MibS.cpp +++ b/lib/src/bilevel/optimizers/wrappers/MibS/Optimizers_MibS.cpp @@ -10,7 +10,7 @@ #include idol::Optimizers::Bilevel::MibS::MibS(const idol::Model &t_parent, - idol::Bilevel::LowerLevelDescription t_description, + idol::Bilevel::Description t_description, OsiSolverInterface* t_osi_solver, bool t_use_file, bool t_use_cplex_for_feasibility) diff --git a/lib/src/bilevel/optimizers/wrappers/MibS/impl_MibSFromAPI.cpp b/lib/src/bilevel/optimizers/wrappers/MibS/impl_MibSFromAPI.cpp index 0ae20c0e..c52644a5 100644 --- a/lib/src/bilevel/optimizers/wrappers/MibS/impl_MibSFromAPI.cpp +++ b/lib/src/bilevel/optimizers/wrappers/MibS/impl_MibSFromAPI.cpp @@ -27,7 +27,7 @@ namespace idol { } idol::impl::MibSFromAPI::MibSFromAPI(const idol::Model &t_model, - const idol::Bilevel::LowerLevelDescription &t_description, + const idol::Bilevel::Description &t_description, OsiSolverInterface* t_osi_solver, const std::list>& t_callbacks, bool t_use_cplex_for_feasibility, diff --git a/lib/src/bilevel/optimizers/wrappers/MibS/impl_MibSFromFile.cpp b/lib/src/bilevel/optimizers/wrappers/MibS/impl_MibSFromFile.cpp index 63f18280..b0928c2a 100644 --- a/lib/src/bilevel/optimizers/wrappers/MibS/impl_MibSFromFile.cpp +++ b/lib/src/bilevel/optimizers/wrappers/MibS/impl_MibSFromFile.cpp @@ -23,7 +23,7 @@ #endif idol::impl::MibSFromFile::MibSFromFile(const idol::Model &t_model, - const idol::Bilevel::LowerLevelDescription &t_description, + const idol::Bilevel::Description &t_description, OsiSolverInterface* t_osi_solver, bool t_use_cplex_for_feasibility, bool t_logs) diff --git a/lib/src/mixed-integer/modeling/annotations/impl_Annotation.cpp b/lib/src/mixed-integer/modeling/annotations/impl_Annotation.cpp index 033f45d1..feb6cd59 100644 --- a/lib/src/mixed-integer/modeling/annotations/impl_Annotation.cpp +++ b/lib/src/mixed-integer/modeling/annotations/impl_Annotation.cpp @@ -7,10 +7,10 @@ #include "idol/mixed-integer/modeling/constraints/TempCtr.h" #include "idol/mixed-integer/modeling/objects/Env.h" -idol::impl::Annotation::Annotation(::idol::Env &t_env, bool t_is_var_annotation, std::string &&t_name) +idol::impl::Annotation::Annotation(::idol::Env &t_env, std::string &&t_name) : m_id([&]() { - auto id = t_env.create_annotation_id(t_is_var_annotation); - auto name =t_name.empty() ? "Annotation_" + std::to_string(t_is_var_annotation) + "_" + std::to_string(t_is_var_annotation) : std::move(t_name); + const auto id = t_env.create_annotation_id(); + auto name = t_name.empty() ? "a" + std::to_string(id) : std::move(t_name); return std::make_shared(t_env, id, std::move(name)); }()) {} diff --git a/lib/src/mixed-integer/modeling/models/KKT.cpp b/lib/src/mixed-integer/modeling/models/KKT.cpp index e9b35315..3b183cb8 100644 --- a/lib/src/mixed-integer/modeling/models/KKT.cpp +++ b/lib/src/mixed-integer/modeling/models/KKT.cpp @@ -9,7 +9,7 @@ #include "idol/mixed-integer/modeling/constraints/TempQCtr.h" idol::Reformulators::KKT::KKT(const idol::Model &t_src_model, - const idol::Bilevel::LowerLevelDescription &t_lower_level_description) + const idol::Bilevel::Description &t_lower_level_description) : m_src_model(t_src_model), m_description(t_lower_level_description) { create_dual_variables_for_constraints(); diff --git a/lib/src/mixed-integer/modeling/objects/Env.cpp b/lib/src/mixed-integer/modeling/objects/Env.cpp index 827c691b..8a0a7452 100644 --- a/lib/src/mixed-integer/modeling/objects/Env.cpp +++ b/lib/src/mixed-integer/modeling/objects/Env.cpp @@ -9,9 +9,5 @@ void idol::impl::Env::free_model_id(const Model &t_model) { } void idol::impl::Env::free_annotation_id(const impl::Annotation &t_annotation) { - if (t_annotation.is_var_annotation()) { - m_var_annotation_ids.free(t_annotation.id()); - } else { - m_ctr_annotation_ids.free(t_annotation.id()); - } + m_annotation_ids.free(t_annotation.id()); } diff --git a/lib/src/mixed-integer/optimizers/dantzig-wolfe/DantzigWolfeDecomposition.cpp b/lib/src/mixed-integer/optimizers/dantzig-wolfe/DantzigWolfeDecomposition.cpp index 86bdfa86..0b216fb4 100644 --- a/lib/src/mixed-integer/optimizers/dantzig-wolfe/DantzigWolfeDecomposition.cpp +++ b/lib/src/mixed-integer/optimizers/dantzig-wolfe/DantzigWolfeDecomposition.cpp @@ -16,22 +16,12 @@ idol::DantzigWolfeDecomposition *idol::DantzigWolfeDecomposition::clone() const return new DantzigWolfeDecomposition(*this); } -idol::DantzigWolfeDecomposition::DantzigWolfeDecomposition(idol::Annotation t_decomposition) - : m_ctr_decomposition(std::move(t_decomposition)) {} - -idol::DantzigWolfeDecomposition::DantzigWolfeDecomposition( - idol::Annotation t_ctr_decomposition, - idol::Annotation t_var_decomposition) - : m_ctr_decomposition(std::move(t_ctr_decomposition)), - m_var_decomposition(std::move(t_var_decomposition)) -{ - -} +idol::DantzigWolfeDecomposition::DantzigWolfeDecomposition(idol::Annotation t_decomposition) + : m_decomposition(std::move(t_decomposition)) {} idol::DantzigWolfeDecomposition::DantzigWolfeDecomposition(const DantzigWolfeDecomposition& t_src) : OptimizerFactoryWithDefaultParameters(t_src), - m_ctr_decomposition(t_src.m_ctr_decomposition), - m_var_decomposition(t_src.m_var_decomposition), + 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), @@ -49,23 +39,15 @@ idol::Optimizer *idol::DantzigWolfeDecomposition::operator()(const Model &t_mode throw Exception("No optimizer for master has been configured."); } - if (!m_ctr_decomposition.has_value()) { + if (!m_decomposition.has_value()) { throw Exception("No decomposition has been configured."); } - std::unique_ptr dantzig_wolfe_formulation; - if (m_var_decomposition.has_value()) { - dantzig_wolfe_formulation = std::make_unique(t_model, - m_ctr_decomposition.value(), - m_var_decomposition.value()); - } else { - dantzig_wolfe_formulation = std::make_unique(t_model, - m_ctr_decomposition.value()); - } + DantzigWolfe::Formulation dantzig_wolfe_formulation(t_model,m_decomposition.value()); - auto sub_problems_specifications = create_sub_problems_specifications(*dantzig_wolfe_formulation); + auto sub_problems_specifications = create_sub_problems_specifications(dantzig_wolfe_formulation); - add_aggregation_constraints(*dantzig_wolfe_formulation, sub_problems_specifications); + add_aggregation_constraints(dantzig_wolfe_formulation, sub_problems_specifications); std::unique_ptr default_strategy; if (!m_infeasibility_strategy) { @@ -86,7 +68,7 @@ idol::Optimizer *idol::DantzigWolfeDecomposition::operator()(const Model &t_mode const bool remove_infeasible_column = m_use_infeasible_column_removal_when_branching.has_value() ? m_use_infeasible_column_removal_when_branching.value() : use_hard_branching; auto result = new Optimizers::DantzigWolfeDecomposition(t_model, - std::move(*dantzig_wolfe_formulation), + 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, diff --git a/lib/src/mixed-integer/optimizers/dantzig-wolfe/Formulation.cpp b/lib/src/mixed-integer/optimizers/dantzig-wolfe/Formulation.cpp index 897dd3e3..59d3a3ff 100644 --- a/lib/src/mixed-integer/optimizers/dantzig-wolfe/Formulation.cpp +++ b/lib/src/mixed-integer/optimizers/dantzig-wolfe/Formulation.cpp @@ -9,10 +9,8 @@ #include "idol/mixed-integer/modeling/constraints/TempCtr.h" idol::DantzigWolfe::Formulation::Formulation(const idol::Model &t_original_formulation, - idol::Annotation t_ctr_decomposition, - idol::Annotation t_var_decomposition) - : m_decomposition_by_ctr(std::move(t_ctr_decomposition)), - m_decomposition_by_var(std::move(t_var_decomposition)), + const idol::Annotation& t_decomposition) + : m_decomposition(t_decomposition), m_master(t_original_formulation.env()) { @@ -31,21 +29,13 @@ idol::DantzigWolfe::Formulation::Formulation(const idol::Model &t_original_formu } -idol::DantzigWolfe::Formulation::Formulation(const Model &t_original_formulation, - const Annotation& t_decomposition) - : Formulation(t_original_formulation, - t_decomposition, - Annotation(t_original_formulation.env(), t_decomposition.name(), MasterId)) { - -} - unsigned int idol::DantzigWolfe::Formulation::compute_n_sub_problems(const Model& t_original_formulation) { std::optional n_sub_problems; for (const auto& ctr : t_original_formulation.ctrs()) { - const unsigned int sub_problem_id = ctr.get(m_decomposition_by_ctr); + const unsigned int sub_problem_id = ctr.get(m_decomposition); if (sub_problem_id == MasterId) { continue; @@ -64,7 +54,7 @@ unsigned int idol::DantzigWolfe::Formulation::compute_n_sub_problems(const Model for (const auto& var : t_original_formulation.vars()) { - const unsigned int sub_problem_id = var.get(m_decomposition_by_var); + const unsigned int sub_problem_id = var.get(m_decomposition); if (sub_problem_id == MasterId) { continue; @@ -90,18 +80,18 @@ void idol::DantzigWolfe::Formulation::set_decomposition_by_var(const Model& t_or if (t_sub_problem_id == MasterId) { return; } - const unsigned int current_sub_problem_id = t_var.get(m_decomposition_by_var); + const unsigned int current_sub_problem_id = t_var.get(m_decomposition); if (current_sub_problem_id != MasterId && current_sub_problem_id != t_sub_problem_id) { throw Exception("Impossible decomposition."); } - t_var.set(m_decomposition_by_var, t_sub_problem_id); + t_var.set(m_decomposition, t_sub_problem_id); }; for (const auto &ctr: t_original_formulation.ctrs()) { - const unsigned int sub_problem_id = ctr.get(m_decomposition_by_ctr); + const unsigned int sub_problem_id = ctr.get(m_decomposition); const auto &row = t_original_formulation.get_ctr_row(ctr); @@ -170,7 +160,7 @@ void idol::DantzigWolfe::Formulation::dispatch_constraints(const idol::Model &t_ for (const auto& ctr : t_original_formulation.ctrs()) { - const unsigned int sub_problem_id = ctr.get(m_decomposition_by_ctr); + const unsigned int sub_problem_id = ctr.get(m_decomposition); const auto& row = t_original_formulation.get_ctr_row(ctr); const double rhs = t_original_formulation.get_ctr_rhs(ctr); const auto type = t_original_formulation.get_ctr_type(ctr); @@ -212,7 +202,7 @@ idol::DantzigWolfe::Formulation::decompose_expression(const LinExpr &t_line for (const auto& [var, constant] : t_linear) { - const unsigned int sub_problem_id = var.get(m_decomposition_by_var); + const unsigned int sub_problem_id = var.get(m_decomposition); if (sub_problem_id == MasterId) { master_part += constant * var; @@ -247,22 +237,22 @@ void idol::DantzigWolfe::Formulation::dispatch_objective_function(const idol::Mo } idol::Model &idol::DantzigWolfe::Formulation::get_model(const idol::Var &t_var) { - const unsigned int sub_problem_id = t_var.get(m_decomposition_by_var); + const unsigned int sub_problem_id = t_var.get(m_decomposition); return sub_problem_id == MasterId ? m_master : m_sub_problems[sub_problem_id]; } const idol::Model &idol::DantzigWolfe::Formulation::get_model(const idol::Var &t_var) const { - const unsigned int sub_problem_id = t_var.get(m_decomposition_by_var); + const unsigned int sub_problem_id = t_var.get(m_decomposition); return sub_problem_id == MasterId ? m_master : m_sub_problems[sub_problem_id]; } idol::Model &idol::DantzigWolfe::Formulation::get_model(const idol::Ctr &t_ctr) { - const unsigned int sub_problem_id = t_ctr.get(m_decomposition_by_ctr); + const unsigned int sub_problem_id = t_ctr.get(m_decomposition); return sub_problem_id == MasterId ? m_master : m_sub_problems[sub_problem_id]; } const idol::Model &idol::DantzigWolfe::Formulation::get_model(const idol::Ctr &t_ctr) const { - const unsigned int sub_problem_id = t_ctr.get(m_decomposition_by_ctr); + const unsigned int sub_problem_id = t_ctr.get(m_decomposition); return sub_problem_id == MasterId ? m_master : m_sub_problems[sub_problem_id]; } @@ -348,7 +338,7 @@ void idol::DantzigWolfe::Formulation::update_sub_problem_objective(unsigned int double idol::DantzigWolfe::Formulation::get_original_space_var_primal(const idol::Var &t_var, const idol::PrimalPoint &t_master_primal) const { - const unsigned int sub_problem_id = t_var.get(m_decomposition_by_var); + const unsigned int sub_problem_id = t_var.get(m_decomposition); if (sub_problem_id == MasterId) { return t_master_primal.get(t_var); @@ -368,7 +358,7 @@ double idol::DantzigWolfe::Formulation::get_original_space_var_primal(const idol void idol::DantzigWolfe::Formulation::update_var_lb(const idol::Var &t_var, double t_lb, bool t_hard, bool t_remove_infeasible_columns) { - const unsigned int sub_problem_id = t_var.get(m_decomposition_by_var); + const unsigned int sub_problem_id = t_var.get(m_decomposition); if (sub_problem_id == MasterId) { m_master.set_var_lb(t_var, t_lb); @@ -392,7 +382,7 @@ void idol::DantzigWolfe::Formulation::update_var_lb(const idol::Var &t_var, doub void idol::DantzigWolfe::Formulation::update_var_ub(const idol::Var &t_var, double t_ub, bool t_hard, bool t_remove_infeasible_columns) { - const unsigned int sub_problem_id = t_var.get(m_decomposition_by_var); + const unsigned int sub_problem_id = t_var.get(m_decomposition); if (sub_problem_id == MasterId) { m_master.set_var_ub(t_var, t_ub); @@ -492,7 +482,7 @@ void idol::DantzigWolfe::Formulation::update_obj(const idol::QuadExpr void idol::DantzigWolfe::Formulation::update_var_obj(const idol::Var &t_var, double t_obj) { - const unsigned int sub_problem_id = t_var.get(m_decomposition_by_var); + const unsigned int sub_problem_id = t_var.get(m_decomposition); if (sub_problem_id == MasterId) { m_master.set_var_obj(t_var, t_obj); @@ -557,7 +547,7 @@ void idol::DantzigWolfe::Formulation::add(const idol::Var &t_var, throw Exception("TODO Was using Column::obj"); /* - const auto sub_problem_id = t_var.get(m_decomposition_by_var); + const auto sub_problem_id = t_var.get(m_decomposition); if (sub_problem_id == MasterId) { m_master.add(t_var, TempVar(t_lb, t_ub, t_type, Column(t_column))); @@ -572,7 +562,7 @@ void idol::DantzigWolfe::Formulation::add(const idol::Ctr &t_ctr, idol::CtrType throw Exception("TODO: Was using Constant in add(const Ctr& ...)"); /* - const auto sub_problem_id = t_ctr.get(m_decomposition_by_ctr); + const auto sub_problem_id = t_ctr.get(m_decomposition); if (sub_problem_id != MasterId) { @@ -601,7 +591,7 @@ void idol::DantzigWolfe::Formulation::add(const idol::Ctr &t_ctr, idol::CtrType void idol::DantzigWolfe::Formulation::remove(const idol::Var &t_var) { - const auto sub_problem_id = t_var.get(m_decomposition_by_var); + const auto sub_problem_id = t_var.get(m_decomposition); if (sub_problem_id != MasterId) { m_generation_patterns[sub_problem_id].objective.linear().remove(t_var); @@ -615,7 +605,7 @@ void idol::DantzigWolfe::Formulation::remove(const idol::Var &t_var) { void idol::DantzigWolfe::Formulation::remove(const idol::Ctr &t_ctr) { - const auto sub_problem_id = t_ctr.get(m_decomposition_by_ctr); + const auto sub_problem_id = t_ctr.get(m_decomposition); if (sub_problem_id == MasterId) { m_master.remove(t_ctr); diff --git a/lib/src/mixed-integer/optimizers/dantzig-wolfe/Optimizers_DantzigWolfeDecomposition.cpp b/lib/src/mixed-integer/optimizers/dantzig-wolfe/Optimizers_DantzigWolfeDecomposition.cpp index dc51384e..ef5da78e 100644 --- a/lib/src/mixed-integer/optimizers/dantzig-wolfe/Optimizers_DantzigWolfeDecomposition.cpp +++ b/lib/src/mixed-integer/optimizers/dantzig-wolfe/Optimizers_DantzigWolfeDecomposition.cpp @@ -74,7 +74,7 @@ void idol::Optimizers::DantzigWolfeDecomposition::add(const idol::Var &t_var) { const auto ub = parent.get_var_ub(t_var); const auto type = parent.get_var_type(t_var); const auto& column = parent.get_var_column(t_var); - const auto& sub_problem_id = t_var.get(m_formulation.decomposition_by_variable()); + const auto& sub_problem_id = t_var.get(m_formulation.decomposition()); if (sub_problem_id != MasterId) { const unsigned int n_sub_problems = m_formulation.n_sub_problems(); diff --git a/lib/src/mixed-integer/optimizers/padm/Formulation.cpp b/lib/src/mixed-integer/optimizers/padm/Formulation.cpp index 96ceaa15..bfc2d022 100644 --- a/lib/src/mixed-integer/optimizers/padm/Formulation.cpp +++ b/lib/src/mixed-integer/optimizers/padm/Formulation.cpp @@ -12,8 +12,8 @@ #include idol::ADM::Formulation::Formulation(const Model& t_src_model, - Annotation t_decomposition, - std::optional> t_penalized_constraints, + Annotation t_decomposition, + std::optional> t_penalized_constraints, bool t_independent_penalty_update, std::pair t_rescaling) : m_decomposition(std::move(t_decomposition)), diff --git a/lib/src/mixed-integer/optimizers/padm/PADM.cpp b/lib/src/mixed-integer/optimizers/padm/PADM.cpp index 06f8788a..5bd181c8 100644 --- a/lib/src/mixed-integer/optimizers/padm/PADM.cpp +++ b/lib/src/mixed-integer/optimizers/padm/PADM.cpp @@ -7,13 +7,13 @@ #include #include "idol/mixed-integer/optimizers/padm/Optimizers_PADM.h" -idol::PADM::PADM(idol::Annotation t_decomposition) +idol::PADM::PADM(idol::Annotation t_decomposition) : m_decomposition(std::move(t_decomposition)) { } -idol::PADM::PADM(idol::Annotation t_decomposition, - idol::Annotation t_penalized_constraints) +idol::PADM::PADM(idol::Annotation t_decomposition, + idol::Annotation t_penalized_constraints) : m_decomposition(std::move(t_decomposition)), m_penalized_constraints(t_penalized_constraints) { diff --git a/lib/src/mixed-integer/optimizers/padm/PenaltyMethod.cpp b/lib/src/mixed-integer/optimizers/padm/PenaltyMethod.cpp index 73123cf2..fa5b1556 100644 --- a/lib/src/mixed-integer/optimizers/padm/PenaltyMethod.cpp +++ b/lib/src/mixed-integer/optimizers/padm/PenaltyMethod.cpp @@ -6,7 +6,7 @@ #include -idol::PenaltyMethod::PenaltyMethod(idol::Annotation t_penalized_constraints) +idol::PenaltyMethod::PenaltyMethod(idol::Annotation t_penalized_constraints) : m_decomposition(t_penalized_constraints.env(), "decomposition", 0), m_penalized_constraints(std::move(t_penalized_constraints)) { diff --git a/tests/branch-and-price/assignment.cpp b/tests/branch-and-price/assignment.cpp index 81a40262..5a618128 100644 --- a/tests/branch-and-price/assignment.cpp +++ b/tests/branch-and-price/assignment.cpp @@ -51,10 +51,10 @@ TEST_CASE("Solve Generalized Assignment Problem instances with different branch- const unsigned int n_agents = instance.n_agents(); const unsigned int n_jobs = instance.n_jobs(); - Annotation std_decomposition(env, "by_machines", MasterId); + Annotation std_decomposition(env, "by_machines", MasterId); - Annotation nested_decomposition1(env, "nested_decomposition1", MasterId); - Annotation nested_decomposition2(env, "nested_decomposition2", MasterId); + Annotation nested_decomposition1(env, "nested_decomposition1", MasterId); + Annotation nested_decomposition2(env, "nested_decomposition2", MasterId); const auto farkas_pricing = is_HiGHS() ? GENERATE(false) : GENERATE(true, false);