Skip to content

Commit

Permalink
[Ant-2380] improving maintainability (#965)
Browse files Browse the repository at this point in the history
This pull request includes several changes to the `BendersBase` class
and related components to improve the handling of criterion computations
and refactor the codebase. The most important changes include the
renaming of `OuterLoopInputData` to `CriterionInputData`, the addition
of the `CouplingMapGenerator` class, and the refactoring of methods
related to criterion computations.

### Refactoring and Renaming:
* Renamed `OuterLoopInputData` to `CriterionInputData` and updated all
related references in `CriterionComputation.cpp` and
`CriterionInputDataReader.cpp`
[[1]](diffhunk://#diff-d0e3218aceff8618ccc9bf1b8ee0ed104175f6db50b089e0e2fd46c4372daf88L32-R44)
[[2]](diffhunk://#diff-68cda14d5a160cbb0d388b11de54f391a6bf6aa2a2b46ee4f97dba03c963fedcL1-R1)
[[3]](diffhunk://#diff-68cda14d5a160cbb0d388b11de54f391a6bf6aa2a2b46ee4f97dba03c963fedcL13-R83).
* Removed the `OuterloopOptionsFile` method from `BendersBase` and
updated the `setCriterionsComputation` method to
`setCriterionComputationInputs`
[[1]](diffhunk://#diff-debcbcbc301c4e3ac700146a75db0a05d686e1d30f20ce42019e1e77acf903a5L25-L29)
[[2]](diffhunk://#diff-36a63705b7409199b9d45a79b1f80f656b02e9f5a4d1a2c41703742ad41a76c2L98-R103)
[[3]](diffhunk://#diff-36a63705b7409199b9d45a79b1f80f656b02e9f5a4d1a2c41703742ad41a76c2L226-R225).

### Addition of CouplingMapGenerator:
* Added a new `CouplingMapGenerator` class to handle the building of
input maps from structure files, encapsulating this functionality
[[1]](diffhunk://#diff-e5c5805ed18be849a2bcfcaf5f3a459394022162fe8c0b168ad0164688aac93eR1-R52)
[[2]](diffhunk://#diff-2a07bb398e3d2d00e5899c2b0c02ae4da892bdcf20158651d1a4ce4c1a7b49c3R1-R9).

### Updates to Criterion Computation:
* Refactored `CriterionComputation` to use `CriterionInputData` instead
of `OuterLoopInputData`, updating methods and member variables
accordingly
[[1]](diffhunk://#diff-d0e3218aceff8618ccc9bf1b8ee0ed104175f6db50b089e0e2fd46c4372daf88L32-R44)
[[2]](diffhunk://#diff-debcbcbc301c4e3ac700146a75db0a05d686e1d30f20ce42019e1e77acf903a5L420-R415)
[[3]](diffhunk://#diff-debcbcbc301c4e3ac700146a75db0a05d686e1d30f20ce42019e1e77acf903a5R1045-R1054).

### CMakeLists and File Updates:
* Updated `CMakeLists.txt` to reflect the renaming of files and the
addition of new source files (`CouplingMapGenerator.cpp`)
[[1]](diffhunk://#diff-89a10ccfdde5ce80ade12658a06704594fe58b1f86f162a55bc68252f382ff09L26-R28)
[[2]](diffhunk://#diff-89a10ccfdde5ce80ade12658a06704594fe58b1f86f162a55bc68252f382ff09L44-L50).

### Removal of Unused Methods:
* Removed the `build_input` method from `common.cpp` as its
functionality is now encapsulated in `CouplingMapGenerator`.
  • Loading branch information
a-zakir authored Nov 26, 2024
1 parent 4252b91 commit 2715a1f
Show file tree
Hide file tree
Showing 33 changed files with 530 additions and 458 deletions.
2 changes: 1 addition & 1 deletion docs/user-guide/get-started/adequacy-criterion.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,5 @@ Several log files are written:

- `reportbenders.txt` gives information on the progress of the algorithm with an operational perspective,
- `benders_solver.log` contains more detailed information on all data of interest to follow the progress of the algorithm (`lambda_min`, `lambda_max`, detailed solving times, ...).
- The file `criterions.txt` under `lp/` dir stores adequacy criterions for all valid patterns (area+criterion)
- The file `LOLD.txt` under `lp/` dir stores adequacy criteria for all valid patterns (area+criterion)
- The file `PositiveUnsuppliedEnergy.txt` under `lp/` dir stores the amount of unsupplied energy for all valid patterns (area+criterion)
2 changes: 1 addition & 1 deletion src/cpp/benders/benders_by_batch/BendersByBatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ void BendersByBatch::SeparationLoop() {
SolveBatches();

if (Rank() == rank_0) {
outer_loop_criterion_.push_back(_data.outer_loop_current_iteration_data.outer_loop_criterion);
criteria_vector_for_each_iteration_.push_back(_data.criteria_current_iteration_data.criteria);
// TODO
// UpdateOuterLoopMaxCriterionArea();
UpdateTrace();
Expand Down
58 changes: 28 additions & 30 deletions src/cpp/benders/benders_core/BendersBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@ BendersBase::BendersBase(const BendersBaseOptions &options, Logger logger,
mathLoggerDriver_(std::move(mathLoggerDriver)) {
}

std::filesystem::path BendersBase::OuterloopOptionsFile() const {
return std::filesystem::path(_options.INPUTROOT) /
_options.EXTERNAL_LOOP_OPTIONS.OUTER_LOOP_OPTION_FILE;
}

/*!
* \brief Initialize set of data used in the loop
*/
Expand All @@ -47,7 +42,7 @@ void BendersBase::init_data() {
_data.iteration_time = 0;
_data.timer_master = 0;
_data.subproblems_walltime = 0;
outer_loop_criterion_.clear();
criteria_vector_for_each_iteration_.clear();
}

void BendersBase::OpenCsvFile() {
Expand Down Expand Up @@ -173,10 +168,10 @@ void BendersBase::update_best_ub() {
_data.best_ub = _data.ub;
_data.best_it = _data.it;
FillWorkerMasterData(relevantIterationData_.best);
_data.outer_loop_current_iteration_data.max_criterion_best_it =
_data.outer_loop_current_iteration_data.max_criterion;
_data.outer_loop_current_iteration_data.max_criterion_area_best_it =
_data.outer_loop_current_iteration_data.max_criterion_area;
_data.criteria_current_iteration_data.max_criterion_best_it =
_data.criteria_current_iteration_data.max_criterion;
_data.criteria_current_iteration_data.max_criterion_area_best_it =
_data.criteria_current_iteration_data.max_criterion_area;
relevantIterationData_.best._cut_trace = relevantIterationData_.last._cut_trace;
best_iteration_data = bendersDataToLogData(_data);
}
Expand Down Expand Up @@ -417,7 +412,7 @@ void BendersBase::SetSubproblemsVariablesIndices() {
if (!subproblem_map.empty()) {
auto subproblem = subproblem_map.begin();

criterions_computation_->SearchVariables(
criterion_computation_.SearchVariables(
subproblem->second->_solver->get_col_names());
}
}
Expand Down Expand Up @@ -539,7 +534,7 @@ void BendersBase::SaveCurrentOuterLoopIterationInOutputFile() const {
if (LastWorkerMasterData._valid) {
_writer->write_iteration(
iteration(LastWorkerMasterData),
_data.outer_loop_current_iteration_data.benders_num_run);
_data.criteria_current_iteration_data.benders_num_run);
_writer->dump();
}
}
Expand Down Expand Up @@ -599,7 +594,7 @@ Output::SolutionData BendersBase::solution() const {
void BendersBase::UpdateOuterLoopSolution() {
outer_loop_solution_data_ = BendersSolution();
outer_loop_solution_data_.best_it =
_data.outer_loop_current_iteration_data.benders_num_run;
_data.criteria_current_iteration_data.benders_num_run;
}

Output::SolutionData BendersBase::GetOuterLoopSolution() const {
Expand Down Expand Up @@ -1000,39 +995,40 @@ WorkerMasterData BendersBase::BestIterationWorkerMaster() const {
CurrentIterationData BendersBase::GetCurrentIterationData() const {
return _data;
}
OuterLoopCurrentIterationData BendersBase::GetOuterLoopData() const {
return _data.outer_loop_current_iteration_data;
CriteriaCurrentIterationData BendersBase::GetOuterLoopData() const {
return _data.criteria_current_iteration_data;
}
std::vector<double> BendersBase::GetOuterLoopCriterionAtBestBenders() const {
return ((outer_loop_criterion_.empty())
return ((criteria_vector_for_each_iteration_.empty())
? std::vector<double>()
: outer_loop_criterion_[_data.best_it - 1]);
: criteria_vector_for_each_iteration_[_data.best_it - 1]);
}

void BendersBase::init_data(double external_loop_lambda,
double external_loop_lambda_min,
double external_loop_lambda_max) {
benders_timer.restart();
auto benders_num_run =
_data.outer_loop_current_iteration_data.benders_num_run;
_data.criteria_current_iteration_data.benders_num_run;
auto outer_loop_bilevel_best_ub =
_data.outer_loop_current_iteration_data.outer_loop_bilevel_best_ub;
_data.criteria_current_iteration_data.outer_loop_bilevel_best_ub;
init_data();
_data.outer_loop_current_iteration_data.outer_loop_criterion.clear();
_data.outer_loop_current_iteration_data.benders_num_run = benders_num_run;
_data.outer_loop_current_iteration_data.outer_loop_bilevel_best_ub =
_data.criteria_current_iteration_data.criteria.clear();
_data.criteria_current_iteration_data.benders_num_run = benders_num_run;
_data.criteria_current_iteration_data.outer_loop_bilevel_best_ub =
outer_loop_bilevel_best_ub;
_data.outer_loop_current_iteration_data.external_loop_lambda =
_data.criteria_current_iteration_data.lambda =
external_loop_lambda;
_data.outer_loop_current_iteration_data.external_loop_lambda_min =
_data.criteria_current_iteration_data.lambda_min =
external_loop_lambda_min;
_data.outer_loop_current_iteration_data.external_loop_lambda_max =
_data.criteria_current_iteration_data.lambda_max =
external_loop_lambda_max;
}



bool BendersBase::isExceptionRaised() const { return exception_raised_; }

/*
* after the 1st loop of the outer loop, we must re-build the objective
* function and costs
Expand All @@ -1046,12 +1042,14 @@ void BendersBase::UpdateOverallCosts() {

relevantIterationData_.best._invest_cost = _data.invest_cost;
}

void BendersBase::SetBilevelBestub(double bilevel_best_ub) {
_data.outer_loop_current_iteration_data.outer_loop_bilevel_best_ub =
_data.criteria_current_iteration_data.outer_loop_bilevel_best_ub =
bilevel_best_ub;
}
void BendersBase::setCriterionsComputation(
std::shared_ptr<Benders::Criterion::CriterionComputation>
criterionsComputation) {
criterions_computation_ = criterionsComputation;

void BendersBase::setCriterionComputationInputs(
const Benders::Criterion::CriterionInputData &criterion_input_data) {
criterion_computation_ =
Benders::Criterion::CriterionComputation(criterion_input_data);
}
14 changes: 7 additions & 7 deletions src/cpp/benders/benders_core/BendersMathLogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,29 +216,29 @@ void PrintExternalLoopData(LogDestination& log_destination,
const HEADERSTYPE& type,
const BENDERSMETHOD& method) {
log_destination.InsertDelimiter();
log_destination << data.outer_loop_current_iteration_data.benders_num_run;
log_destination << data.criteria_current_iteration_data.benders_num_run;
log_destination.InsertDelimiter();
log_destination << std::scientific << std::setprecision(10)
<< data.outer_loop_current_iteration_data.max_criterion;
<< data.criteria_current_iteration_data.max_criterion;
log_destination.InsertDelimiter();
log_destination << data.outer_loop_current_iteration_data.max_criterion_area;
log_destination << data.criteria_current_iteration_data.max_criterion_area;
log_destination.InsertDelimiter();

log_destination
<< std::scientific << std::setprecision(10)
<< data.outer_loop_current_iteration_data.outer_loop_bilevel_best_ub;
<< data.criteria_current_iteration_data.outer_loop_bilevel_best_ub;
log_destination.InsertDelimiter();
log_destination
<< std::scientific << std::setprecision(10)
<< data.outer_loop_current_iteration_data.external_loop_lambda;
<< data.criteria_current_iteration_data.lambda;
log_destination.InsertDelimiter();
log_destination
<< std::scientific << std::setprecision(10)
<< data.outer_loop_current_iteration_data.external_loop_lambda_min;
<< data.criteria_current_iteration_data.lambda_min;
log_destination.InsertDelimiter();
log_destination
<< std::scientific << std::setprecision(10)
<< data.outer_loop_current_iteration_data.external_loop_lambda_max;
<< data.criteria_current_iteration_data.lambda_max;
PrintBendersData(log_destination, data, type, method);
}
void MathLoggerBaseExternalLoop::Print(const CurrentIterationData& data) {
Expand Down
7 changes: 4 additions & 3 deletions src/cpp/benders/benders_core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ target_sources(benders_core PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/WorkerMaster.cpp
${CMAKE_CURRENT_SOURCE_DIR}/common.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CriterionComputation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/OuterLoopInputDataReader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CriterionInputDataReader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/VariablesGroup.cpp
${CMAKE_CURRENT_SOURCE_DIR}/CouplingMapGenerator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/BendersBase.h
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/BendersMathLogger.h
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/BendersStructsDatas.h
Expand All @@ -41,13 +42,13 @@ target_sources(benders_core PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/WorkerMaster.h
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/common.h
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/CriterionComputation.h
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/OuterLoopInputDataReader.h
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/CriterionInputDataReader.h
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/VariablesGroup.h
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/CouplingMapGenerator.h
)

add_library(antaresXpansion::benders_core ALIAS benders_core)


target_include_directories(benders_core
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
Expand Down
52 changes: 52 additions & 0 deletions src/cpp/benders/benders_core/CouplingMapGenerator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <antares-xpansion/benders/benders_core/CouplingMapGenerator.h>
#include <antares-xpansion/xpansion_interfaces/LoggerUtils.h>

struct InvalidStructureFile : LogUtils::XpansionError<std::runtime_error> {
using LogUtils::XpansionError<std::runtime_error>::XpansionError;
};

/*!
* \brief Build the input from the structure file
*
* Function to build the map linking each problem name to its variables and
*their id
*
* \param root : root of the structure file
*
* \param summary_name : name of the structure file
*
* \param coupling_map : empty map to increment
*
* \note The id in the coupling_map is that of the variable in the solver
*responsible for the creation of the structure file.
*/
CouplingMap CouplingMapGenerator::BuildInput(
const std::filesystem::path& structure_path,
std::shared_ptr<ILoggerXpansion> logger, const std::string& context) {
CouplingMap coupling_map;
std::ifstream summary(structure_path, std::ios::in);
if (!summary) {
auto log_location = LOGLOCATION;
std::ostringstream msg;
msg << "Cannot open structure file " << structure_path << std::endl;
logger->display_message(msg.str(), LogUtils::LOGLEVEL::FATAL, log_location);
throw InvalidStructureFile(
PrefixMessage(LogUtils::LOGLEVEL::FATAL, context), msg.str(),
log_location);
}
std::string line;

while (std::getline(summary, line)) {
std::stringstream buffer(line);
std::string problem_name;
std::string variable_name;
int variable_id;
buffer >> problem_name;
buffer >> variable_name;
buffer >> variable_id;
coupling_map[problem_name][variable_name] = variable_id;
}

summary.close();
return coupling_map;
}
52 changes: 26 additions & 26 deletions src/cpp/benders/benders_core/CriterionComputation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,46 @@

namespace Benders::Criterion {

void CriterionComputation::ComputeOuterLoopCriterion(
void CriterionComputation::ComputeCriterion(
double subproblem_weight, const std::vector<double> &sub_problem_solution,
std::vector<double> &outerLoopCriterions,
std::vector<double> &outerLoopPatternsValues) {
auto outer_loop_input_size = var_indices_.size(); // num of patterns
outerLoopCriterions.resize(outer_loop_input_size, 0.);
outerLoopPatternsValues.resize(outer_loop_input_size, 0.);

double criterion_count_threshold =
outer_loop_input_data_.CriterionCountThreshold();

for (int pattern_index(0); pattern_index < outer_loop_input_size;
++pattern_index) {
auto pattern_variables_indices = var_indices_[pattern_index];
for (auto variables_index : pattern_variables_indices) {
const auto &solution = sub_problem_solution[variables_index];
outerLoopPatternsValues[pattern_index] += solution;
if (solution > criterion_count_threshold)
// 1h of no supplied energy
outerLoopCriterions[pattern_index] += subproblem_weight;
std::vector<double> &criteria,
std::vector<double> &patterns_values) {
auto criteria_input_size = var_indices_.size(); // num of patterns
criteria.resize(criteria_input_size, 0.);
patterns_values.resize(criteria_input_size, 0.);

double criterion_count_threshold =
criterion_input_data_.CriterionCountThreshold();

for (int pattern_index(0); pattern_index < criteria_input_size;
++pattern_index) {
auto pattern_variables_indices = var_indices_[pattern_index];
for (auto variables_index: pattern_variables_indices) {
const auto &solution = sub_problem_solution[variables_index];
patterns_values[pattern_index] += solution;
if (solution > criterion_count_threshold)
// 1h of no supplied energy
criteria[pattern_index] += subproblem_weight;
}
}
}
}

void CriterionComputation::SearchVariables(
const std::vector<std::string> &variables) {
Benders::Criterion::VariablesGroup variablesGroup(
variables, outer_loop_input_data_.OuterLoopData());
variables, criterion_input_data_.Criteria());
var_indices_ = variablesGroup.Indices();
}

const OuterLoopInputData &CriterionComputation::getOuterLoopInputData() const {
return outer_loop_input_data_;
const CriterionInputData &CriterionComputation::getCriterionInputData() const {
return criterion_input_data_;
}

std::vector<std::vector<int>> &CriterionComputation::getVarIndices() {
return var_indices_;
}
CriterionComputation::CriterionComputation(
const OuterLoopInputData &outer_loop_input_data)
: outer_loop_input_data_(outer_loop_input_data) {}

const CriterionInputData &criterion_input_data)
: criterion_input_data_(criterion_input_data) {
}
} // namespace Benders::Criterion
Loading

0 comments on commit 2715a1f

Please sign in to comment.