From 86afb1ded2b78c619e7bc9f8592f1ca87f1d3926 Mon Sep 17 00:00:00 2001 From: Abdoulbari Zaher <32519851+a-zakir@users.noreply.github.com> Date: Fri, 12 Jul 2024 11:34:08 +0200 Subject: [PATCH] [ant-1860] Save not-supplied energy values (#863) save outer loop -{not-supplied energy && criterion} for each selected area --- src/cpp/benders/benders_core/BendersBase.cpp | 21 ++++---- .../benders_core/BendersMathLogger.cpp | 5 ++ .../benders_core/OuterLoopInputDataReader.cpp | 19 +++++++ .../benders_core/include/BendersBase.h | 5 +- .../benders_core/include/BendersMathLogger.h | 49 +++++++++++++++++++ .../include/BendersStructsDatas.h | 1 + .../include/OuterLoopInputDataReader.h | 2 + .../benders_core/include/SubproblemCut.h | 2 + src/cpp/benders/benders_mpi/BendersMPI.cpp | 38 +++++++++----- .../benders/benders_mpi/include/BendersMPI.h | 3 +- 10 files changed, 119 insertions(+), 26 deletions(-) diff --git a/src/cpp/benders/benders_core/BendersBase.cpp b/src/cpp/benders/benders_core/BendersBase.cpp index 4041a19ac..05986f191 100644 --- a/src/cpp/benders/benders_core/BendersBase.cpp +++ b/src/cpp/benders/benders_core/BendersBase.cpp @@ -400,8 +400,7 @@ void BendersBase::GetSubproblemCut(SubProblemDataMap &subproblem_data_map) { if (_options.EXTERNAL_LOOP_OPTIONS.DO_OUTER_LOOP) { std::vector solution; worker->get_solution(solution); - subproblem_data.outer_loop_criterions = - ComputeOuterLoopCriterion(name, solution); + ComputeOuterLoopCriterion(name, solution, subproblem_data); } worker->get_subgradient(subproblem_data.var_name_and_subgradient); worker->get_splex_num_of_ite_last(subproblem_data.simplex_iter); @@ -1023,12 +1022,14 @@ std::vector BendersBase::GetOuterLoopCriterionAtBestBenders() const { : outer_loop_criterion_[_data.best_it - 1]); } -std::vector BendersBase::ComputeOuterLoopCriterion( +void BendersBase::ComputeOuterLoopCriterion( const std::string &subproblem_name, - const std::vector &sub_problem_solution) { + const std::vector &sub_problem_solution, + PlainData::SubProblemData &subproblem_data) { auto outer_loop_input_size = var_indices_.size(); // num of patterns - std::vector outer_loop_criterion_per_sub_problem(outer_loop_input_size, - {}); + subproblem_data.outer_loop_criterions.resize(outer_loop_input_size, 0.); + subproblem_data.outer_loop_patterns_values.resize(outer_loop_input_size, 0.); + auto subproblem_weight = SubproblemWeight(_data.nsubproblem, subproblem_name); double criterion_count_threshold = outer_loop_input_data_.CriterionCountThreshold(); @@ -1037,14 +1038,14 @@ std::vector BendersBase::ComputeOuterLoopCriterion( ++pattern_index) { auto pattern_variables_indices = var_indices_[pattern_index]; for (auto variables_index : pattern_variables_indices) { - if (auto solution = sub_problem_solution[variables_index]; - solution > criterion_count_threshold) + const auto &solution = sub_problem_solution[variables_index]; + subproblem_data.outer_loop_patterns_values[pattern_index] += solution; + if (solution > criterion_count_threshold) // 1h of no supplied energy - outer_loop_criterion_per_sub_problem[pattern_index] += + subproblem_data.outer_loop_criterions[pattern_index] += subproblem_weight; } } - return outer_loop_criterion_per_sub_problem; } double BendersBase::ExternalLoopLambdaMax() const { diff --git a/src/cpp/benders/benders_core/BendersMathLogger.cpp b/src/cpp/benders/benders_core/BendersMathLogger.cpp index 359af3220..8d83f0e5f 100644 --- a/src/cpp/benders/benders_core/BendersMathLogger.cpp +++ b/src/cpp/benders/benders_core/BendersMathLogger.cpp @@ -99,6 +99,7 @@ void MathLoggerBase::Print(const CurrentIterationData& data) { PrintBendersData(LogsDestination(), data, HeadersType(), BENDERSMETHOD::BENDERS); } + void MathLoggerBase::setHeadersList() { auto type = HeadersType(); HeadersManager headers_manager(type, BENDERSMETHOD::BENDERS); @@ -298,3 +299,7 @@ MathLoggerImplementation::MathLoggerImplementation(const BENDERSMETHOD& method, break; } } + +MathLoggerImplementation::MathLoggerImplementation( + std::shared_ptr implementation) + : implementation_(std::move(implementation)) {} diff --git a/src/cpp/benders/benders_core/OuterLoopInputDataReader.cpp b/src/cpp/benders/benders_core/OuterLoopInputDataReader.cpp index df9cdf889..dd3172f30 100644 --- a/src/cpp/benders/benders_core/OuterLoopInputDataReader.cpp +++ b/src/cpp/benders/benders_core/OuterLoopInputDataReader.cpp @@ -2,6 +2,8 @@ #include +#include "StringManip.h" + using namespace Outerloop; /** @@ -56,6 +58,23 @@ std::vector OuterLoopInputData::OuterLoopData() return outer_loop_data_; } +std::vector OuterLoopInputData::PatternBodies() const { + std::vector ret; + for (const auto &data : outer_loop_data_) { + ret.push_back(data.Pattern().GetBody()); + } + return ret; +} + +std::string OuterLoopInputData::PatternsPrefix() const { + std::string ret(""); + if (!outer_loop_data_.empty()) { + ret = + StringManip::split(outer_loop_data_[0].Pattern().GetPrefix(), "::")[0]; + } + return ret; +} + void OuterLoopInputData::SetStoppingThreshold( double outer_loop_stopping_threshold) { outer_loop_stopping_threshold_ = outer_loop_stopping_threshold; diff --git a/src/cpp/benders/benders_core/include/BendersBase.h b/src/cpp/benders/benders_core/include/BendersBase.h index 3ccb9d2bc..26c72a1aa 100644 --- a/src/cpp/benders/benders_core/include/BendersBase.h +++ b/src/cpp/benders/benders_core/include/BendersBase.h @@ -235,9 +235,10 @@ class BendersBase { SolverLogManager solver_log_manager_; // outer loop criterion per pattern - std::vector ComputeOuterLoopCriterion( + void ComputeOuterLoopCriterion( const std::string &subproblem_name, - const std::vector &sub_problem_solution); + const std::vector &sub_problem_solution, + PlainData::SubProblemData &subproblem_data); void UpdateOuterLoopMaxCriterionArea(); void UpdateOuterLoopSolution(); diff --git a/src/cpp/benders/benders_core/include/BendersMathLogger.h b/src/cpp/benders/benders_core/include/BendersMathLogger.h index 53baf65d4..07c188e40 100644 --- a/src/cpp/benders/benders_core/include/BendersMathLogger.h +++ b/src/cpp/benders/benders_core/include/BendersMathLogger.h @@ -133,6 +133,27 @@ struct MathLoggerBendersByBatchExternalLoop : public MathLoggerBendersByBatch { virtual ~MathLoggerBendersByBatchExternalLoop() = default; }; +template +struct MathLoggerExternalLoopSpecific : public MathLogger { + explicit MathLoggerExternalLoopSpecific( + const std::filesystem::path& file_path, + const std::vector& headers, + T OuterLoopCurrentIterationData::*ptr) + : MathLogger(file_path), ptr_(ptr) { + headers_.push_back("Outer loop"); + headers_.insert(headers_.end(), headers.begin(), headers.end()); + } + + void setHeadersList() override; + void Print(const CurrentIterationData& data) override; + + virtual ~MathLoggerExternalLoopSpecific() = default; + + private: + std::vector headers_; + T OuterLoopCurrentIterationData::*ptr_; +}; + class MathLoggerImplementation : public MathLoggerBehaviour { public: explicit MathLoggerImplementation(const BENDERSMETHOD& method, @@ -142,6 +163,7 @@ class MathLoggerImplementation : public MathLoggerBehaviour { explicit MathLoggerImplementation(const BENDERSMETHOD& method, std::streamsize width = 40, HEADERSTYPE type = HEADERSTYPE::LONG); + explicit MathLoggerImplementation(std::shared_ptr implementation); void Print(const CurrentIterationData& data) { implementation_->Print(data); } @@ -172,6 +194,10 @@ class MathLoggerDriver : public ILoggerXpansion { void write_header(); void display_message(const std::string& str) override; void add_logger(std::shared_ptr logger); + template + void add_logger(const std::filesystem::path& file_path, + const std::vector& headers, + T OuterLoopCurrentIterationData::*t); void Print(const CurrentIterationData& data); virtual void PrintIterationSeparatorBegin() override; virtual void PrintIterationSeparatorEnd() override; @@ -180,3 +206,26 @@ class MathLoggerDriver : public ILoggerXpansion { private: std::vector> math_loggers_; }; + +template +void MathLoggerDriver::add_logger(const std::filesystem::path& file_path, + const std::vector& headers, + T OuterLoopCurrentIterationData::*t) { + auto impl = std::make_shared>(file_path, + headers, t); + add_logger(std::make_shared(impl)); +} + +template +void MathLoggerExternalLoopSpecific::setHeadersList() { + MathLogger::setHeadersList(headers_); +} +template +void MathLoggerExternalLoopSpecific::Print( + const CurrentIterationData& data) { + LogsDestination() << data.outer_loop_current_iteration_data.benders_num_run; + for (const auto& t : data.outer_loop_current_iteration_data.*ptr_) { + LogsDestination() << std::scientific << std::setprecision(10) << t; + } + LogsDestination() << std::endl; +} \ No newline at end of file diff --git a/src/cpp/benders/benders_core/include/BendersStructsDatas.h b/src/cpp/benders/benders_core/include/BendersStructsDatas.h index bbdc27211..cd8157365 100644 --- a/src/cpp/benders/benders_core/include/BendersStructsDatas.h +++ b/src/cpp/benders/benders_core/include/BendersStructsDatas.h @@ -8,6 +8,7 @@ struct OuterLoopCurrentIterationData{ int benders_num_run = 0; std::vector outer_loop_criterion = {}; + std::vector outer_loop_patterns_values = {}; double max_criterion = 0.; double max_criterion_best_it = 0.; double outer_loop_bilevel_best_ub = +1e20; diff --git a/src/cpp/benders/benders_core/include/OuterLoopInputDataReader.h b/src/cpp/benders/benders_core/include/OuterLoopInputDataReader.h index e6c84c1bc..0efea089d 100644 --- a/src/cpp/benders/benders_core/include/OuterLoopInputDataReader.h +++ b/src/cpp/benders/benders_core/include/OuterLoopInputDataReader.h @@ -81,6 +81,8 @@ class OuterLoopInputData { OuterLoopInputData() = default; [[nodiscard]] std::vector OuterLoopData() const; + [[nodiscard]] std::vector PatternBodies() const; + [[nodiscard]] std::string PatternsPrefix() const; void SetStoppingThreshold(double outer_loop_stopping_threshold); [[nodiscard]] double StoppingThreshold() const; diff --git a/src/cpp/benders/benders_core/include/SubproblemCut.h b/src/cpp/benders/benders_core/include/SubproblemCut.h index 6c070750d..ddcf43a87 100644 --- a/src/cpp/benders/benders_core/include/SubproblemCut.h +++ b/src/cpp/benders/benders_core/include/SubproblemCut.h @@ -10,6 +10,8 @@ struct SubProblemData { double subproblem_cost; Point var_name_and_subgradient; std::vector outer_loop_criterions; + // no-supplied energy + std::vector outer_loop_patterns_values; double single_subpb_costs_under_approx; double subproblem_timer; int simplex_iter; diff --git a/src/cpp/benders/benders_mpi/BendersMPI.cpp b/src/cpp/benders/benders_mpi/BendersMPI.cpp index 45a8c7868..43af10109 100644 --- a/src/cpp/benders/benders_mpi/BendersMPI.cpp +++ b/src/cpp/benders/benders_mpi/BendersMPI.cpp @@ -147,9 +147,7 @@ void BendersMpi::gather_subproblems_cut_package_and_build_cuts( std::plus(), rank_0); SetSubproblemsCumulativeCpuTime(cumulative_subproblems_timer_per_iter); if (Options().EXTERNAL_LOOP_OPTIONS.DO_OUTER_LOOP) { - _data.outer_loop_current_iteration_data.outer_loop_criterion = - ComputeSubproblemsContributionToOuterLoopCriterion( - subproblem_data_map); + ComputeSubproblemsContributionToOuterLoopCriterion(subproblem_data_map); if (_world.rank() == rank_0) { outer_loop_criterion_.push_back( _data.outer_loop_current_iteration_data.outer_loop_criterion); @@ -161,25 +159,30 @@ void BendersMpi::gather_subproblems_cut_package_and_build_cuts( } } -std::vector -BendersMpi::ComputeSubproblemsContributionToOuterLoopCriterion( +void BendersMpi::ComputeSubproblemsContributionToOuterLoopCriterion( const SubProblemDataMap &subproblem_data_map) { std::vector outer_loop_criterion_per_sub_problem_per_pattern( var_indices_.size(), {}); - std::vector outer_loop_criterion_sub_problems_map_result( + _data.outer_loop_current_iteration_data.outer_loop_criterion.resize( + var_indices_.size(), 0.); + std::vector outer_loop_patterns_values_per_sub_problem_per_pattern( var_indices_.size(), {}); + _data.outer_loop_current_iteration_data.outer_loop_patterns_values.resize( + var_indices_.size(), 0.); for (const auto &[subproblem_name, subproblem_data] : subproblem_data_map) { - AddVectors( - outer_loop_criterion_per_sub_problem_per_pattern, + AddVectors(outer_loop_criterion_per_sub_problem_per_pattern, subproblem_data.outer_loop_criterions); + AddVectors(outer_loop_patterns_values_per_sub_problem_per_pattern, + subproblem_data.outer_loop_patterns_values); } Reduce(outer_loop_criterion_per_sub_problem_per_pattern, - outer_loop_criterion_sub_problems_map_result, std::plus(), - rank_0); - - return outer_loop_criterion_sub_problems_map_result; + _data.outer_loop_current_iteration_data.outer_loop_criterion, + std::plus(), rank_0); + Reduce(outer_loop_patterns_values_per_sub_problem_per_pattern, + _data.outer_loop_current_iteration_data.outer_loop_patterns_values, + std::plus(), rank_0); } SubProblemDataMap BendersMpi::get_subproblem_cut_package() { @@ -339,6 +342,17 @@ void BendersMpi::PreRunInitialization() { if (is_trace()) { OpenCsvFile(); } + + if (Options().EXTERNAL_LOOP_OPTIONS.DO_OUTER_LOOP) { + const auto &headers = outer_loop_input_data_.PatternBodies(); + mathLoggerDriver_->add_logger( + std::filesystem::path(Options().OUTPUTROOT) / "criterions.txt", + headers, &OuterLoopCurrentIterationData::outer_loop_criterion); + mathLoggerDriver_->add_logger( + std::filesystem::path(Options().OUTPUTROOT) / + (outer_loop_input_data_.PatternsPrefix() + ".txt"), + headers, &OuterLoopCurrentIterationData::outer_loop_patterns_values); + } } mathLoggerDriver_->write_header(); init_data_ = false; diff --git a/src/cpp/benders/benders_mpi/include/BendersMPI.h b/src/cpp/benders/benders_mpi/include/BendersMPI.h index ceff3d3dc..62767ab99 100644 --- a/src/cpp/benders/benders_mpi/include/BendersMPI.h +++ b/src/cpp/benders/benders_mpi/include/BendersMPI.h @@ -93,7 +93,6 @@ class BendersMpi : public BendersBase { void AllReduce(const T &in_value, T &out_value, Op op) const { mpi::all_reduce(_world, in_value, out_value, op); } - virtual std::vector - ComputeSubproblemsContributionToOuterLoopCriterion( + virtual void ComputeSubproblemsContributionToOuterLoopCriterion( const SubProblemDataMap &subproblem_data_map); };