From 61f98edf049fa66d26dade9736586e6f7ec648c5 Mon Sep 17 00:00:00 2001 From: Thomas Bittar Date: Thu, 16 Jan 2025 16:32:32 +0100 Subject: [PATCH] Round subproblem subgradient to avoid master numerical issues --- src/cpp/benders/benders_core/BendersBase.cpp | 8 +++----- src/cpp/benders/benders_core/SubproblemWorker.cpp | 10 ++++++++++ src/cpp/benders/benders_core/WorkerMaster.cpp | 6 +++--- .../benders/benders_core/SubproblemWorker.h | 5 +++-- 4 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/cpp/benders/benders_core/BendersBase.cpp b/src/cpp/benders/benders_core/BendersBase.cpp index 7b476d94f..953459c28 100644 --- a/src/cpp/benders/benders_core/BendersBase.cpp +++ b/src/cpp/benders/benders_core/BendersBase.cpp @@ -454,8 +454,8 @@ void compute_cut_val(const Point &var_name_subgradient, const Point &x_cut, * Method to add aggregated cut from subproblems to Master Problem and store * it in a map linking each subproblem to its set of non-aggregated cut * - * \param all_package : vector storing all cuts information for each - * subproblem problem + * \param subproblem_data_map : map storing all cuts information for each + * subproblem */ void BendersBase::compute_cut_aggregate( const SubProblemDataMap &subproblem_data_map) { @@ -476,9 +476,7 @@ void BendersBase::compute_cut_aggregate( /*! * \brief Add cuts in master problem * - * Add cuts in master problem according to the selected option - * - * \param all_package : storage of every subproblem information + * \param subproblem_data_map : storage of every subproblem information */ void BendersBase::BuildCutFull(const SubProblemDataMap &subproblem_data_map) { check_status(subproblem_data_map); diff --git a/src/cpp/benders/benders_core/SubproblemWorker.cpp b/src/cpp/benders/benders_core/SubproblemWorker.cpp index a156b34d7..ef1ad819f 100644 --- a/src/cpp/benders/benders_core/SubproblemWorker.cpp +++ b/src/cpp/benders/benders_core/SubproblemWorker.cpp @@ -53,6 +53,15 @@ void SubproblemWorker::fix_to(Point const &x0) const { solver_chgbounds(_solver, indexes, bndtypes, values); } +static double INTTOL = 1e-4; +void SubproblemWorker::roundIfWithinTolerance(std::vector &values, + double tolerance) const { + std::transform(values.begin(), values.end(), values.begin(), + [tolerance](double value) -> double { + return std::abs(value) < tolerance ? 0 : value; + }); +} + /*! * \brief Get LP solution value of a problem * @@ -62,6 +71,7 @@ void SubproblemWorker::get_subgradient(Point &s) const { s.clear(); std::vector ptr(_solver->get_ncols()); solver_getlpreducedcost(_solver, ptr); + roundIfWithinTolerance(ptr, INTTOL); for (auto const &kvp : _id_to_name) { s[kvp.second] = +ptr[kvp.first]; } diff --git a/src/cpp/benders/benders_core/WorkerMaster.cpp b/src/cpp/benders/benders_core/WorkerMaster.cpp index 17b76cb08..7ca002151 100644 --- a/src/cpp/benders/benders_core/WorkerMaster.cpp +++ b/src/cpp/benders/benders_core/WorkerMaster.cpp @@ -39,7 +39,7 @@ WorkerMaster::WorkerMaster(VariableMap const &variable_map, // Tolerance to which a value is considered zero or integral // TODO : Allow to parametrize this constant from the options file -int INTTOL = 1e-6; +static double INTTOL = 1e-4; void WorkerMaster::roundXVarIfWithinTolerance(std::vector &values, double tolerance) { int nb_candidates = _id_to_name.size(); @@ -64,10 +64,10 @@ void WorkerMaster::roundXVarIfWithinTolerance(std::vector &values, values[kvp.first] = lb[kvp.first]; } // Case integer variable - else if (col_type[kvp.first] == 'I') { + else if (col_type[kvp.first] == 'B' || col_type[kvp.first] == 'I') { int rounded = std::round(value); values[kvp.first] = - std::abs(value - std::round(value)) <= tolerance ? rounded : value; + std::abs(value - std::round(value)) < tolerance ? rounded : value; } }; } diff --git a/src/cpp/benders/benders_core/include/antares-xpansion/benders/benders_core/SubproblemWorker.h b/src/cpp/benders/benders_core/include/antares-xpansion/benders/benders_core/SubproblemWorker.h index 1369b2a8d..f688c9745 100644 --- a/src/cpp/benders/benders_core/include/antares-xpansion/benders/benders_core/SubproblemWorker.h +++ b/src/cpp/benders/benders_core/include/antares-xpansion/benders/benders_core/SubproblemWorker.h @@ -18,11 +18,12 @@ class SubproblemWorker : public Worker { SubproblemWorker(VariableMap const &variable_map, const std::filesystem::path &path_to_mps, double const &slave_weight, const std::string &solver_name, - const int log_level, - SolverLogManager&solver_log_manager, + const int log_level, SolverLogManager &solver_log_manager, Logger logger); virtual ~SubproblemWorker() = default; void get_solution(std::vector &solution) const; + void roundIfWithinTolerance(std::vector &values, + double tolerance) const; public: void fix_to(Point const &x0) const;