Skip to content

Commit

Permalink
[ant-1860] Save not-supplied energy values (#863)
Browse files Browse the repository at this point in the history
save outer loop -{not-supplied energy && criterion} for each selected
area
  • Loading branch information
a-zakir authored Jul 12, 2024
1 parent 8692890 commit 86afb1d
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 26 deletions.
21 changes: 11 additions & 10 deletions src/cpp/benders/benders_core/BendersBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,8 +400,7 @@ void BendersBase::GetSubproblemCut(SubProblemDataMap &subproblem_data_map) {
if (_options.EXTERNAL_LOOP_OPTIONS.DO_OUTER_LOOP) {
std::vector<double> 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);
Expand Down Expand Up @@ -1023,12 +1022,14 @@ std::vector<double> BendersBase::GetOuterLoopCriterionAtBestBenders() const {
: outer_loop_criterion_[_data.best_it - 1]);
}

std::vector<double> BendersBase::ComputeOuterLoopCriterion(
void BendersBase::ComputeOuterLoopCriterion(
const std::string &subproblem_name,
const std::vector<double> &sub_problem_solution) {
const std::vector<double> &sub_problem_solution,
PlainData::SubProblemData &subproblem_data) {
auto outer_loop_input_size = var_indices_.size(); // num of patterns
std::vector<double> 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();
Expand All @@ -1037,14 +1038,14 @@ std::vector<double> 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 {
Expand Down
5 changes: 5 additions & 0 deletions src/cpp/benders/benders_core/BendersMathLogger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -298,3 +299,7 @@ MathLoggerImplementation::MathLoggerImplementation(const BENDERSMETHOD& method,
break;
}
}

MathLoggerImplementation::MathLoggerImplementation(
std::shared_ptr<MathLogger> implementation)
: implementation_(std::move(implementation)) {}
19 changes: 19 additions & 0 deletions src/cpp/benders/benders_core/OuterLoopInputDataReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <utility>

#include "StringManip.h"

using namespace Outerloop;

/**
Expand Down Expand Up @@ -56,6 +58,23 @@ std::vector<OuterLoopSingleInputData> OuterLoopInputData::OuterLoopData()
return outer_loop_data_;
}

std::vector<std::string> OuterLoopInputData::PatternBodies() const {
std::vector<std::string> 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;
Expand Down
5 changes: 3 additions & 2 deletions src/cpp/benders/benders_core/include/BendersBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,9 +235,10 @@ class BendersBase {
SolverLogManager solver_log_manager_;

// outer loop criterion per pattern
std::vector<double> ComputeOuterLoopCriterion(
void ComputeOuterLoopCriterion(
const std::string &subproblem_name,
const std::vector<double> &sub_problem_solution);
const std::vector<double> &sub_problem_solution,
PlainData::SubProblemData &subproblem_data);

void UpdateOuterLoopMaxCriterionArea();
void UpdateOuterLoopSolution();
Expand Down
49 changes: 49 additions & 0 deletions src/cpp/benders/benders_core/include/BendersMathLogger.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,27 @@ struct MathLoggerBendersByBatchExternalLoop : public MathLoggerBendersByBatch {
virtual ~MathLoggerBendersByBatchExternalLoop() = default;
};

template <class T>
struct MathLoggerExternalLoopSpecific : public MathLogger {
explicit MathLoggerExternalLoopSpecific(
const std::filesystem::path& file_path,
const std::vector<std::string>& 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<std::string> headers_;
T OuterLoopCurrentIterationData::*ptr_;
};

class MathLoggerImplementation : public MathLoggerBehaviour {
public:
explicit MathLoggerImplementation(const BENDERSMETHOD& method,
Expand All @@ -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<MathLogger> implementation);

void Print(const CurrentIterationData& data) { implementation_->Print(data); }

Expand Down Expand Up @@ -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<MathLoggerImplementation> logger);
template <class T>
void add_logger(const std::filesystem::path& file_path,
const std::vector<std::string>& headers,
T OuterLoopCurrentIterationData::*t);
void Print(const CurrentIterationData& data);
virtual void PrintIterationSeparatorBegin() override;
virtual void PrintIterationSeparatorEnd() override;
Expand All @@ -180,3 +206,26 @@ class MathLoggerDriver : public ILoggerXpansion {
private:
std::vector<std::shared_ptr<MathLoggerImplementation>> math_loggers_;
};

template <class T>
void MathLoggerDriver::add_logger(const std::filesystem::path& file_path,
const std::vector<std::string>& headers,
T OuterLoopCurrentIterationData::*t) {
auto impl = std::make_shared<MathLoggerExternalLoopSpecific<T>>(file_path,
headers, t);
add_logger(std::make_shared<MathLoggerImplementation>(impl));
}

template <class T>
void MathLoggerExternalLoopSpecific<T>::setHeadersList() {
MathLogger::setHeadersList(headers_);
}
template <class T>
void MathLoggerExternalLoopSpecific<T>::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;
}
1 change: 1 addition & 0 deletions src/cpp/benders/benders_core/include/BendersStructsDatas.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
struct OuterLoopCurrentIterationData{
int benders_num_run = 0;
std::vector<double> outer_loop_criterion = {};
std::vector<double> outer_loop_patterns_values = {};
double max_criterion = 0.;
double max_criterion_best_it = 0.;
double outer_loop_bilevel_best_ub = +1e20;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ class OuterLoopInputData {
OuterLoopInputData() = default;

[[nodiscard]] std::vector<OuterLoopSingleInputData> OuterLoopData() const;
[[nodiscard]] std::vector<std::string> PatternBodies() const;
[[nodiscard]] std::string PatternsPrefix() const;

void SetStoppingThreshold(double outer_loop_stopping_threshold);
[[nodiscard]] double StoppingThreshold() const;
Expand Down
2 changes: 2 additions & 0 deletions src/cpp/benders/benders_core/include/SubproblemCut.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ struct SubProblemData {
double subproblem_cost;
Point var_name_and_subgradient;
std::vector<double> outer_loop_criterions;
// no-supplied energy
std::vector<double> outer_loop_patterns_values;
double single_subpb_costs_under_approx;
double subproblem_timer;
int simplex_iter;
Expand Down
38 changes: 26 additions & 12 deletions src/cpp/benders/benders_mpi/BendersMPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,7 @@ void BendersMpi::gather_subproblems_cut_package_and_build_cuts(
std::plus<double>(), 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);
Expand All @@ -161,25 +159,30 @@ void BendersMpi::gather_subproblems_cut_package_and_build_cuts(
}
}

std::vector<double>
BendersMpi::ComputeSubproblemsContributionToOuterLoopCriterion(
void BendersMpi::ComputeSubproblemsContributionToOuterLoopCriterion(
const SubProblemDataMap &subproblem_data_map) {
std::vector<double> outer_loop_criterion_per_sub_problem_per_pattern(
var_indices_.size(), {});
std::vector<double> outer_loop_criterion_sub_problems_map_result(
_data.outer_loop_current_iteration_data.outer_loop_criterion.resize(
var_indices_.size(), 0.);
std::vector<double> 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<double>(
outer_loop_criterion_per_sub_problem_per_pattern,
AddVectors<double>(outer_loop_criterion_per_sub_problem_per_pattern,
subproblem_data.outer_loop_criterions);
AddVectors<double>(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<double>(),
rank_0);

return outer_loop_criterion_sub_problems_map_result;
_data.outer_loop_current_iteration_data.outer_loop_criterion,
std::plus<double>(), rank_0);
Reduce(outer_loop_patterns_values_per_sub_problem_per_pattern,
_data.outer_loop_current_iteration_data.outer_loop_patterns_values,
std::plus<double>(), rank_0);
}

SubProblemDataMap BendersMpi::get_subproblem_cut_package() {
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 1 addition & 2 deletions src/cpp/benders/benders_mpi/include/BendersMPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<double>
ComputeSubproblemsContributionToOuterLoopCriterion(
virtual void ComputeSubproblemsContributionToOuterLoopCriterion(
const SubProblemDataMap &subproblem_data_map);
};

0 comments on commit 86afb1d

Please sign in to comment.