Skip to content

Commit

Permalink
Fix numerical issues when settings candidates from master to subpb
Browse files Browse the repository at this point in the history
  • Loading branch information
tbittar committed Jan 15, 2025
1 parent d150686 commit 9bbb09b
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 23 deletions.
15 changes: 1 addition & 14 deletions src/cpp/benders/benders_core/SubproblemWorker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,6 @@

#include "antares-xpansion/helpers/solver_utils.h"

// 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 void roundingIfWithinTolerance(std::vector<double> &values,
double tolerance) {
std::transform(
values.begin(), values.end(), values.begin(), [tolerance](double value) {
double rounded = std::round(value);
// Check if the value is within the tolerance of the rounded value
return (std::abs(value - rounded) <= tolerance) ? rounded : value;
});
}

/*!
* \brief Constructor of a Worker Slave
*
Expand Down Expand Up @@ -62,7 +49,7 @@ void SubproblemWorker::fix_to(Point const &x0) const {
values[i] = x0.find(kvp.second)->second;
++i;
}
roundingIfWithinTolerance(values, INTTOL);

solver_chgbounds(_solver, indexes, bndtypes, values);
}

Expand Down
51 changes: 45 additions & 6 deletions src/cpp/benders/benders_core/WorkerMaster.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include "antares-xpansion/benders/benders_core/WorkerMaster.h"


#include "antares-xpansion/helpers/solver_utils.h"

WorkerMaster::WorkerMaster(Logger logger) : Worker(logger) {
Expand All @@ -19,11 +18,12 @@ WorkerMaster::WorkerMaster(Logger logger) : Worker(logger) {
* \param log_level : solver log level
* \param subproblems_count : number of subproblems
*/
WorkerMaster::WorkerMaster(
VariableMap const &variable_map, const std::filesystem::path &path_to_mps,
const std::string &solver_name, const int log_level, int subproblems_count,
SolverLogManager&solver_log_manager,
const bool mps_has_alpha, Logger logger)
WorkerMaster::WorkerMaster(VariableMap const &variable_map,
const std::filesystem::path &path_to_mps,
const std::string &solver_name, const int log_level,
int subproblems_count,
SolverLogManager &solver_log_manager,
const bool mps_has_alpha, Logger logger)
: Worker(std::move(logger)),
subproblems_count(subproblems_count),
_mps_has_alpha(mps_has_alpha) {
Expand All @@ -37,6 +37,41 @@ WorkerMaster::WorkerMaster(
_set_nb_units_var_ids();
}

// Tolerance to which a value is considered zero or integral
// TODO : Allow to parametrize this constant from the options file
int INTTOL = 1e-6;
void WorkerMaster::roundXVarIfWithinTolerance(std::vector<double> &values,
double tolerance) {
int nb_candidates = _id_to_name.size();

std::vector<char> col_type(nb_candidates);
std::vector<double> lb(nb_candidates);
std::vector<double> ub(nb_candidates);
// Assumes that candidates are the first variables of the master
solver_getcolinfo(*_solver, col_type, lb, ub, 0, nb_candidates - 1);
for (auto const &kvp : _id_to_name) {
double value = values[kvp.first];
// Case variable near 0
if (std::abs(value) < tolerance) {
values[kvp.first] = 0;
}
// Case variable slighly above ub
else if (value > ub[kvp.first] && value < ub[kvp.first] + tolerance) {
values[kvp.first] = ub[kvp.first];
}
// Case variable slighly lower than lb
else if (value < lb[kvp.first] && value > lb[kvp.first] - tolerance) {
values[kvp.first] = lb[kvp.first];
}
// Case integer variable
else if (col_type[kvp.first] == 'I') {
int rounded = std::round(value);
values[kvp.first] =
std::abs(value - std::round(value)) <= tolerance ? rounded : value;
}
};
}

/*!
* \brief Return optimal variables of a problem
*
Expand All @@ -58,7 +93,11 @@ void WorkerMaster::get(Point &x_out, double &overall_subpb_cost_under_approx,
} else {
_solver->get_lp_sol(ptr.data(), nullptr, nullptr);
}

assert(id_single_subpb_costs_under_approx_.back() + 1 == ptr.size());

roundXVarIfWithinTolerance(ptr, INTTOL);

for (auto const &kvp : _id_to_name) {
x_out[kvp.second] = ptr[kvp.first];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ class WorkerMaster : public Worker {
WorkerMaster(VariableMap const &variable_map,
const std::filesystem::path &path_to_mps,
const std::string &solver_name, int log_level,
int subproblems_count,
SolverLogManager&solver_log_manager,
int subproblems_count, SolverLogManager &solver_log_manager,
bool mps_has_alpha, Logger logger);
~WorkerMaster() override = default;

Expand All @@ -36,7 +35,9 @@ class WorkerMaster : public Worker {

virtual void DeactivateIntegrityConstraints() const;
virtual void ActivateIntegrityConstraints() const;
[[nodiscard]] virtual std::vector<int> get_id_nb_units() const { return _id_nb_units; };
[[nodiscard]] virtual std::vector<int> get_id_nb_units() const {
return _id_nb_units;
};

private:
std::vector<int> _id_nb_units;
Expand All @@ -60,4 +61,6 @@ class WorkerMaster : public Worker {
void _set_upper_bounds() const;
void _set_alpha_var();
void _set_nb_units_var_ids();
void roundXVarIfWithinTolerance(std::vector<double> &values,
double tolerance);
};

0 comments on commit 9bbb09b

Please sign in to comment.