Skip to content

Commit

Permalink
merge classical and by batch benders (#738)
Browse files Browse the repository at this point in the history
Goal:
one benders executable instead the classical benders and the by batch
one.
how:
the choice of the algorithm is decided by the batch_size parameter

close #727
  • Loading branch information
a-zakir authored Feb 7, 2024
1 parent 5eadd1c commit b195dd8
Show file tree
Hide file tree
Showing 33 changed files with 113 additions and 315 deletions.
6 changes: 3 additions & 3 deletions src/cpp/benders/benders_by_batch/BendersByBatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ void BendersByBatch::InitializeProblems() {
MatchProblemToId();

BuildMasterProblem();
const auto &coupling_map_size = coupling_map.size();
const auto &coupling_map_size = coupling_map_.size();
std::vector<std::string> problem_names;
for (const auto &[problem_name, _] : coupling_map) {
for (const auto &[problem_name, _] : coupling_map_) {
problem_names.emplace_back(problem_name);
}
auto batch_size =
Expand All @@ -40,7 +40,7 @@ void BendersByBatch::InitializeProblems() {
Rank()) { // Assign [problemNumber % WorldSize] to processID

const auto subProblemFilePath = GetSubproblemPath(problem_name);
AddSubproblem({problem_name, coupling_map[problem_name]});
AddSubproblem({problem_name, coupling_map_[problem_name]});
AddSubproblemName(problem_name);
}
problem_count++;
Expand Down
39 changes: 9 additions & 30 deletions src/cpp/benders/benders_core/BendersBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -662,31 +662,21 @@ void BendersBase::set_solver_log_file(const std::filesystem::path &log_file) {
}

/*!
* \brief Build the input from the structure file
* \brief set the input
*
* 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.
* \param coupling_map : CouplingMap
*/
void BendersBase::build_input_map() {
auto input = build_input(get_structure_path());
_totalNbProblems = input.size();
void BendersBase::set_input_map(const CouplingMap &coupling_map) {
coupling_map_ = coupling_map;
_totalNbProblems = coupling_map_.size();
_writer->write_nbweeks(_totalNbProblems);
_data.nsubproblem = _totalNbProblems - 1;
master_variable_map = get_master_variable_map(input);
coupling_map = GetCouplingMap(input);
master_variable_map_ = get_master_variable_map(coupling_map_);
coupling_map_.erase(get_master_name());
}

std::map<std::string, int> BendersBase::get_master_variable_map(
std::map<std::string, std::map<std::string, int>> input_map) const {
const std::map<std::string, std::map<std::string, int>> &input_map) const {
auto const it_master(input_map.find(get_master_name()));
if (it_master == input_map.end()) {
_logger->display_message(LOGLOCATION + "UNABLE TO FIND " +
Expand All @@ -696,17 +686,6 @@ std::map<std::string, int> BendersBase::get_master_variable_map(
return it_master->second;
}

CouplingMap BendersBase::GetCouplingMap(CouplingMap input) const {
CouplingMap couplingMap;
auto master_name = get_master_name();
std::copy_if(input.begin(), input.end(),
std::inserter(couplingMap, couplingMap.end()),
[master_name](const CouplingMap::value_type &kvp) {
return kvp.first != master_name;
});
return couplingMap;
}

void BendersBase::reset_master(WorkerMaster *worker_master) {
_master.reset(worker_master);
}
Expand All @@ -726,7 +705,7 @@ void BendersBase::free_subproblems() {
}
void BendersBase::MatchProblemToId() {
int count = 0;
for (const auto &problem : coupling_map) {
for (const auto &problem : coupling_map_) {
_problem_to_id[problem.first] = count;
count++;
}
Expand Down
9 changes: 4 additions & 5 deletions src/cpp/benders/benders_core/include/BendersBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@ class BendersBase {
}
double execution_time() const;
virtual std::string BendersName() const = 0;
void set_input_map(const CouplingMap &coupling_map);

protected:
CurrentIterationData _data;
VariableMap master_variable_map;
CouplingMap coupling_map;
VariableMap master_variable_map_;
CouplingMap coupling_map_;
std::shared_ptr<MathLoggerDriver> mathLoggerDriver_;

protected:
Expand Down Expand Up @@ -75,7 +76,6 @@ class BendersBase {
[[nodiscard]] std::filesystem::path get_structure_path() const;
[[nodiscard]] LogData bendersDataToLogData(
const CurrentIterationData &data) const;
virtual void build_input_map();
virtual void reset_master(WorkerMaster *worker_master);
void free_master() const;
void free_subproblems();
Expand Down Expand Up @@ -158,8 +158,7 @@ class BendersBase {
void compute_cut_aggregate(const SubProblemDataMap &subproblem_data_map);
void compute_cut(const SubProblemDataMap &subproblem_data_map);
[[nodiscard]] std::map<std::string, int> get_master_variable_map(
std::map<std::string, std::map<std::string, int>> input_map) const;
[[nodiscard]] CouplingMap GetCouplingMap(CouplingMap input) const;
const std::map<std::string, std::map<std::string, int>> &input_map) const;
[[nodiscard]] virtual bool shouldParallelize() const = 0;
Output::Iteration iteration(const WorkerMasterDataPtr &masterDataPtr_l) const;
LogData FinalLogData() const;
Expand Down
2 changes: 1 addition & 1 deletion src/cpp/benders/benders_core/include/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ typedef std::vector<ActiveCut> ActiveCutStorage;
typedef std::pair<std::string, std::string> mps_coupling;
typedef std::list<mps_coupling> mps_coupling_list;

enum class BENDERSMETHOD { BENDERS, BENDERSBYBATCH, MERGEMPS };
enum class BENDERSMETHOD { BENDERS, BENDERSBYBATCH };

struct Predicate {
bool operator()(PointPtr const &lhs, PointPtr const &rhs) const {
Expand Down
7 changes: 2 additions & 5 deletions src/cpp/benders/benders_mpi/BendersMPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void BendersMpi::InitializeProblems() {
BuildMasterProblem();
int current_problem_id = 0;
// Dispatch subproblems to process
for (const auto &problem : coupling_map) {
for (const auto &problem : coupling_map_) {
// In case there are more subproblems than process
if (auto process_to_feed = current_problem_id % _world.size();
process_to_feed ==
Expand All @@ -43,7 +43,7 @@ void BendersMpi::InitializeProblems() {
}
void BendersMpi::BuildMasterProblem() {
if (_world.rank() == rank_0) {
reset_master(new WorkerMaster(master_variable_map, get_master_path(),
reset_master(new WorkerMaster(master_variable_map_, get_master_path(),
get_solver_name(), get_log_level(),
_data.nsubproblem, solver_log_manager_,
IsResumeMode(), _logger));
Expand Down Expand Up @@ -284,9 +284,6 @@ void BendersMpi::PreRunInitialization() {
}

void BendersMpi::launch() {
build_input_map();
_world.barrier();

InitializeProblems();
_world.barrier();

Expand Down
6 changes: 2 additions & 4 deletions src/cpp/benders/benders_sequential/BendersSequential.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ BendersSequential::BendersSequential(
void BendersSequential::InitializeProblems() {
MatchProblemToId();

reset_master(new WorkerMaster(master_variable_map, get_master_path(),
reset_master(new WorkerMaster(master_variable_map_, get_master_path(),
get_solver_name(), get_log_level(),
_data.nsubproblem, solver_log_manager_,
IsResumeMode(), _logger));
for (const auto &problem : coupling_map) {
for (const auto &problem : coupling_map_) {
const auto subProblemFilePath = GetSubproblemPath(problem.first);

AddSubproblem(problem);
Expand Down Expand Up @@ -129,8 +129,6 @@ void BendersSequential::Run() {
}

void BendersSequential::launch() {
build_input_map();

LOG(INFO) << "Building input" << std::endl;

LOG(INFO) << "Constructing workers..." << std::endl;
Expand Down
55 changes: 30 additions & 25 deletions src/cpp/benders/factories/BendersFactory.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@

#include "BendersFactory.h"

#include <filesystem>

#include "BendersFactory.h"
#include "LogUtils.h"
#include "LoggerFactories.h"
#include "StartUp.h"
Expand All @@ -12,9 +11,16 @@
#include "gflags/gflags.h"
#include "glog/logging.h"

BENDERSMETHOD DeduceBendersMethod(size_t coupling_map_size, size_t batch_size) {
auto method = (batch_size == 0 || batch_size == coupling_map_size - 1)
? BENDERSMETHOD::BENDERS
: BENDERSMETHOD::BENDERSBYBATCH;

return method;
}

int RunBenders(char** argv, const std::filesystem::path& options_file,
mpi::environment& env, mpi::communicator& world,
const BENDERSMETHOD& method) {
mpi::environment& env, mpi::communicator& world) {
// Read options, needed to have options.OUTPUTROOT
BendersLoggerBase benders_loggers;
Logger logger;
Expand All @@ -40,6 +46,9 @@ int RunBenders(char** argv, const std::filesystem::path& options_file,
std::filesystem::path(options.OUTPUTROOT) / "benders_solver.log";

Writer writer;
const auto coupling_map = build_input(benders_options.STRUCTURE_FILE);
const auto method =
DeduceBendersMethod(coupling_map.size(), options.BATCH_SIZE);

if (world.rank() == 0) {
auto benders_log_console = benders_options.LOG_LEVEL > 0;
Expand All @@ -63,17 +72,18 @@ int RunBenders(char** argv, const std::filesystem::path& options_file,
benders_loggers.AddLogger(logger);
benders_loggers.AddLogger(math_log_driver);
pBendersBase benders;
if (method == BENDERSMETHOD::BENDERS) {
benders = std::make_shared<BendersMpi>(benders_options, logger, writer,
env, world, math_log_driver);
} else if (method == BENDERSMETHOD::BENDERSBYBATCH) {
benders = std::make_shared<BendersByBatch>(
benders_options, logger, writer, env, world, math_log_driver);
} else {
auto err_msg = "Error only benders or benders-by-batch allowed!";
benders_loggers.display_message(err_msg);
std::exit(1);
switch (method) {
case BENDERSMETHOD::BENDERS:
benders = std::make_shared<BendersMpi>(benders_options, logger, writer,
env, world, math_log_driver);
break;
case BENDERSMETHOD::BENDERSBYBATCH:
benders = std::make_shared<BendersByBatch>(
benders_options, logger, writer, env, world, math_log_driver);
break;
}

benders->set_input_map(coupling_map);
std::ostringstream oss_l = start_message(options, benders->BendersName());
oss_l << std::endl;
benders_loggers.display_message(oss_l.str());
Expand Down Expand Up @@ -116,10 +126,10 @@ int RunBenders(char** argv, const std::filesystem::path& options_file,
}

BendersMainFactory::BendersMainFactory(int argc, char** argv,
const BENDERSMETHOD& method,

mpi::environment& env,
mpi::communicator& world)
: argv_(argv), method_(method), penv_(&env), pworld_(&world) {
: argv_(argv), penv_(&env), pworld_(&world) {
// First check usage (options are given)
if (world.rank() == 0) {
usage(argc);
Expand All @@ -128,19 +138,14 @@ BendersMainFactory::BendersMainFactory(int argc, char** argv,
options_file_ = std::filesystem::path(argv_[1]);
}
BendersMainFactory::BendersMainFactory(
int argc, char** argv, const BENDERSMETHOD& method,
const std::filesystem::path& options_file, mpi::environment& env,
mpi::communicator& world)
: argv_(argv),
method_(method),
options_file_(options_file),
penv_(&env),
pworld_(&world) {
int argc, char** argv, const std::filesystem::path& options_file,
mpi::environment& env, mpi::communicator& world)
: argv_(argv), options_file_(options_file), penv_(&env), pworld_(&world) {
// First check usage (options are given)
if (world.rank() == 0) {
usage(argc);
}
}
int BendersMainFactory::Run() const {
return RunBenders(argv_, options_file_, *penv_, *pworld_, method_);
return RunBenders(argv_, options_file_, *penv_, *pworld_);
}
4 changes: 0 additions & 4 deletions src/cpp/benders/factories/include/BendersFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,19 @@
#include "BendersSequential.h"
#include "ILogger.h"
#include "OutputWriter.h"
#include "common.h"

class BendersMainFactory {
private:
char** argv_;
BENDERSMETHOD method_;
std::filesystem::path options_file_;
boost::mpi::environment* penv_ = nullptr;
boost::mpi::communicator* pworld_ = nullptr;

public:
explicit BendersMainFactory(int argc, char** argv,
const BENDERSMETHOD& method,
boost::mpi::environment& env,
boost::mpi::communicator& world);
explicit BendersMainFactory(int argc, char** argv,
const BENDERSMETHOD& method,
const std::filesystem::path& options_file,
boost::mpi::environment& env,
boost::mpi::communicator& world);
Expand Down
2 changes: 0 additions & 2 deletions src/cpp/exe/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,3 @@ add_subdirectory ("${CMAKE_CURRENT_SOURCE_DIR}/antares_archive_updater")

add_subdirectory ("${CMAKE_CURRENT_SOURCE_DIR}/benders")


add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/benders_by_batch")
3 changes: 1 addition & 2 deletions src/cpp/exe/benders/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
int main(int argc, char **argv) {
mpi::environment env(argc, argv);
mpi::communicator world;
auto benders_factory =
BendersMainFactory(argc, argv, BENDERSMETHOD::BENDERS, env, world);
auto benders_factory = BendersMainFactory(argc, argv, env, world);
return benders_factory.Run();
}
24 changes: 0 additions & 24 deletions src/cpp/exe/benders_by_batch/CMakeLists.txt

This file was deleted.

12 changes: 0 additions & 12 deletions src/cpp/exe/benders_by_batch/main.cpp

This file was deleted.

3 changes: 1 addition & 2 deletions src/cpp/exe/full_run/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,9 @@ int main(int argc, char** argv) {
world.barrier();
int argc_ = 2;
const auto options_file = options_parser.BendersOptionsFile();
const auto benders_method = options_parser.Method();

auto benders_factory =
BendersMainFactory(argc_, argv, benders_method, options_file, env, world);
BendersMainFactory(argc_, argv, options_file, env, world);
benders_factory.Run();

if (world.rank() == 0) {
Expand Down
Loading

0 comments on commit b195dd8

Please sign in to comment.