Skip to content

Commit

Permalink
[ANT-2299] Enable save/restore with xpress and enable by default (Ben…
Browse files Browse the repository at this point in the history
…ders) (#987)

Follow up #959 handle save/restore option inside Benders. Properly save
master and last_iteration master.

Note:
Introduce new library fmt https://github.com/fmtlib/fmt
  • Loading branch information
JasonMarechal25 authored Jan 22, 2025
1 parent c4683a8 commit d719d22
Show file tree
Hide file tree
Showing 19 changed files with 187 additions and 87 deletions.
4 changes: 2 additions & 2 deletions src/cpp/benders/benders_core/BendersBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,7 @@ void BendersBase::AddSubproblem(
subproblem_map[kvp.first] = std::make_shared<SubproblemWorker>(
kvp.second, GetSubproblemPath(kvp.first),
SubproblemWeight(_data.nsubproblem, kvp.first), _options.SOLVER_NAME,
_options.LOG_LEVEL, solver_log_manager_, _logger);
_options.LOG_LEVEL, solver_log_manager_, _logger, _options.PROBLEMS_FORMAT);
}

void BendersBase::free_subproblems() {
Expand Down Expand Up @@ -953,7 +953,7 @@ void BendersBase::ResetMasterFromLastIteration() {
reset_master<WorkerMaster>(master_variable_map_, LastMasterPath(),
get_solver_name(), get_log_level(),
_data.nsubproblem, solver_log_manager_,
IsResumeMode(), _logger);
IsResumeMode(), _logger, Options().PROBLEMS_FORMAT);
}
bool BendersBase::MasterIsEmpty() const { return master_is_empty_; }

Expand Down
6 changes: 6 additions & 0 deletions src/cpp/benders/benders_core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ target_sources(benders_core PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/LastIterationReader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/LastIterationWriter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/MasterUpdateBase.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ProblemFormatStream.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SimulationOptions.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SolverIO.cpp
${CMAKE_CURRENT_SOURCE_DIR}/StartUp.cpp
${CMAKE_CURRENT_SOURCE_DIR}/SubproblemWorker.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Worker.cpp
Expand All @@ -40,7 +42,9 @@ target_sources(benders_core PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/LastIterationWriter.h
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/MasterUpdate.h
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/ProblemFormat.h
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/ProblemFormatStream.h
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/SimulationOptions.h
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/SolverIO.h
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/StartUp.h
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/SubproblemWorker.h
${CMAKE_CURRENT_SOURCE_DIR}/include/antares-xpansion/benders/benders_core/VariablesGroup.h
Expand All @@ -56,13 +60,15 @@ target_include_directories(benders_core
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
)

find_package(fmt REQUIRED)
target_link_libraries(benders_core
PUBLIC
antaresXpansion::helpers
antaresXpansion::output_core
antaresXpansion::solvers
${JSONCPP_LIB}
antaresXpansion::outer_loop_lib
fmt::fmt
)

target_link_libraries(benders_core PRIVATE TBB::tbb)
Expand Down
18 changes: 18 additions & 0 deletions src/cpp/benders/benders_core/ProblemFormatStream.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "antares-xpansion/benders/benders_core/ProblemFormatStream.h"

auto fmt::formatter<ProblemsFormat>::format(ProblemsFormat problems_format,
format_context &ctx) const -> format_context::iterator
{
string_view result = "Unknown";
switch (problems_format) {
case ProblemsFormat::MPS_FILE:
result = "MPS_FILE";
break;
case ProblemsFormat::SAVED_FILE:
result = "SAVED_FILE";
break;
default:
result = "Unknown";
}
return formatter<string_view>::format(result, ctx);
}
1 change: 1 addition & 0 deletions src/cpp/benders/benders_core/SimulationOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <filesystem>

#include "antares-xpansion/xpansion_interfaces/LogUtils.h"
#include "antares-xpansion/benders/benders_core/ProblemFormatStream.h"
Json::Value SimulationOptions::get_value_from_json(
const std::filesystem::path &file_name) {
Json::Value _input;
Expand Down
37 changes: 37 additions & 0 deletions src/cpp/benders/benders_core/SolverIO.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

#include <antares-xpansion/benders/benders_core/SolverIO.h>
#include <antares-xpansion/benders/benders_core/ProblemFormatStream.h>
#include <fmt/format.h>

void SolverIO::write(SolverAbstract* solver,
const std::filesystem::path& path) const {
switch (format_) {
case ProblemsFormat::MPS_FILE:
solver->write_prob_mps(path);
break;
case ProblemsFormat::SAVED_FILE:
solver->save_prob(path);
break;
default:
throw LogUtils::XpansionError<std::runtime_error>(
fmt::format("Unknown file format {} for problem file: {}", format_, path.string()), LOGLOCATION);
}
}
void SolverIO::read(SolverAbstract* solver,
const std::filesystem::path& path) const {
switch (format_) {
case ProblemsFormat::MPS_FILE:
solver->read_prob_mps(path);
break;
case ProblemsFormat::SAVED_FILE:
solver->restore_prob(path);
break;
default:
throw LogUtils::XpansionError<std::runtime_error>(
fmt::format("Unknown file format {} for problem file: {}", format_, path.string()), LOGLOCATION);
}
}
void SolverIO::configure(const std::string& solver_name, ProblemsFormat format) {
solver_config_ = solver_name;
format_ = format;
}
17 changes: 11 additions & 6 deletions src/cpp/benders/benders_core/SubproblemWorker.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "antares-xpansion/benders/benders_core/SubproblemWorker.h"

#include <utility>

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

/*!
Expand All @@ -10,12 +12,15 @@
* \param problem_name : Name of the problem
*
*/
SubproblemWorker::SubproblemWorker(
VariableMap const &variable_map, const std::filesystem::path &path_to_mps,
double const &slave_weight, const std::string &solver_name,
const int log_level, SolverLogManager &solver_log_manager, Logger logger)
: Worker(std::move(logger)) {
init(variable_map, path_to_mps, solver_name, log_level, solver_log_manager);
SubproblemWorker::SubproblemWorker(VariableMap const &variable_map,
const std::filesystem::path &path_to_mps,
double const &slave_weight,
const std::string &solver_name,
const int log_level,
SolverLogManager &solver_log_manager,
Logger logger, ProblemsFormat format)
: Worker(variable_map, path_to_mps, std::move(logger)) {
init(solver_name, log_level, solver_log_manager, format);

int mps_ncols(_solver->get_ncols());
DblVector obj_func_coeffs(mps_ncols);
Expand Down
43 changes: 22 additions & 21 deletions src/cpp/benders/benders_core/Worker.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#include "antares-xpansion/benders/benders_core/Worker.h"

#include "antares-xpansion/xpansion_interfaces/LogUtils.h"
#include <utility>

#include "antares-xpansion/helpers/solver_utils.h"
#include "antares-xpansion/xpansion_interfaces/LogUtils.h"
/*!
* \brief Free the problem
*/
Expand Down Expand Up @@ -34,11 +35,9 @@ void Worker::get_value(double &lb) const {
*
* \param problem_name : name of the problem
*/
void Worker::init(VariableMap const &variable_map,
const std::filesystem::path &path_to_mps,
std::string const &solver_name, int log_level,
SolverLogManager&solver_log_manager) {
_path_to_mps = path_to_mps;
void Worker::init(const std::string &solver_name, int log_level,
SolverLogManager &solver_log_manager, ProblemsFormat format) {
solver_io_.configure(solver_name, format);
SolverFactory factory(logger_);

if (_is_master) {
Expand All @@ -51,11 +50,9 @@ void Worker::init(VariableMap const &variable_map,

_solver->set_threads(1);
_solver->set_output_log_level(log_level);
read_prob(_solver.get(), path_to_mps);
read_prob(_solver.get(), _path_to_mps);

_name_to_id = variable_map;

for (auto const &kvp : variable_map) {
for (auto const &kvp : _name_to_id) {
_id_to_name[kvp.second] = kvp.first;
}
}
Expand Down Expand Up @@ -85,7 +82,7 @@ void Worker::solve(int &lp_status, const std::string &outputroot,

msg << "written in " << error_file_path.string() << std::endl;
logger_->display_message(msg.str());
_solver->write_prob_mps(error_file_path);
writeProb(error_file_path);
Output::ProblemData data;
data.name = _path_to_mps.filename().string();
data.path = error_file_path;
Expand All @@ -100,8 +97,7 @@ void Worker::solve(int &lp_status, const std::string &outputroot,
}

if (_is_master) {
_solver->write_prob_mps(std::filesystem::path(outputroot) /
output_master_mps_file_name);
writeProb(std::filesystem::path(outputroot) / output_master_mps_file_name);
}
}
/*!
Expand Down Expand Up @@ -150,13 +146,18 @@ int Worker::Getncols() const { return _solver->get_ncols(); }
* @param problem
* @param path
*/
void Worker::read_prob(SolverAbstract * problem,
void Worker::read_prob(SolverAbstract *problem,
const std::filesystem::path &path) const {
if (path.extension() == ".mps") {
problem->read_prob_mps(path);
} else if (path.extension() == ".svf") {//Brittle
problem->restore_prob(path);
} else {
throw LogUtils::XpansionError<std::runtime_error>("Unknown file extension for problem file: " + path.string(), LOGLOCATION);
}
solver_io_.read(_solver.get(), path);
}
std::shared_ptr<SolverAbstract> Worker::solver() const { return _solver; }

Worker::Worker(VariableMap variable_map, std::filesystem::path path_to_mps,
Logger logger)
: _path_to_mps{std::move(path_to_mps)},
_name_to_id{std::move(variable_map)},
logger_{std::move(logger)} {}

void Worker::writeProb(const std::filesystem::path &out) const {
solver_io_.write(_solver.get(), out);
}
25 changes: 11 additions & 14 deletions src/cpp/benders/benders_core/WorkerMaster.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
#include "antares-xpansion/benders/benders_core/WorkerMaster.h"


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

WorkerMaster::WorkerMaster(Logger logger) : Worker(logger) {
_is_master = true;
}

/*!
* \brief Constructor of a Master Problem
*
Expand All @@ -19,17 +14,19 @@ 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)
: Worker(std::move(logger)),
subproblems_count(subproblems_count),
_mps_has_alpha(mps_has_alpha) {
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, ProblemsFormat format)
: Worker(variable_map, path_to_mps, std::move(logger)),
subproblems_count{subproblems_count},
_mps_has_alpha{mps_has_alpha}
{
_is_master = true;

init(variable_map, path_to_mps, solver_name, log_level, solver_log_manager);
init(solver_name, log_level, solver_log_manager, format);
if (!_mps_has_alpha) {
_set_upper_bounds();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <stdexcept>
#include <string>

enum class ProblemsFormat { MPS_FILE, SAVED_FILE };

inline ProblemsFormat problemsFormatFromString(const std::string &str) {
Expand All @@ -12,18 +13,4 @@ inline ProblemsFormat problemsFormatFromString(const std::string &str) {
} else {
throw std::runtime_error("Unknown ProblemsFormat: " + str);
}
}

inline std::ostream &operator<<(std::ostream &stream, ProblemsFormat const &rhs) {
switch (rhs) {
case ProblemsFormat::MPS_FILE:
stream << "MPS_FILE";
break;
case ProblemsFormat::SAVED_FILE:
stream << "SAVED_FILE";
break;
default:
stream << "Unknown";
}
return stream;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include <fmt/format.h>

#include <ostream>

#include "ProblemFormat.h"

inline std::ostream &operator<<(std::ostream &stream,
ProblemsFormat const &rhs) {
switch (rhs) {
case ProblemsFormat::MPS_FILE:
stream << "MPS_FILE";
break;
case ProblemsFormat::SAVED_FILE:
stream << "SAVED_FILE";
break;
default:
stream << "Unknown";
}
return stream;
}

template <>
struct fmt::formatter<ProblemsFormat> : formatter<string_view> {
// parse is inherited from formatter<string_view>.

auto format(ProblemsFormat problems_format,
format_context &ctx) const -> format_context::iterator;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

#include "ProblemFormat.h"
#include "antares-xpansion/multisolver_interface/SolverAbstract.h"
#include "antares-xpansion/multisolver_interface/SolverConfig.h"

class SolverIO {
SolverConfig solver_config_{"Coin"};
ProblemsFormat format_;
public:
void configure(const std::string& solver_name, ProblemsFormat format);
void write(SolverAbstract* solver, const std::filesystem::path& path) const;
void read(SolverAbstract* solver, const std::filesystem::path& path) const;
};
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ typedef std::map<std::string, SubproblemWorkerPtr> SubproblemsMapPtr;

class SubproblemWorker : public Worker {
public:
explicit SubproblemWorker(Logger logger) : Worker(logger) {}
using Worker::Worker;
SubproblemWorker(VariableMap const &variable_map,
const std::filesystem::path &path_to_mps,
double const &slave_weight, const std::string &solver_name,
const int log_level,
SolverLogManager&solver_log_manager,
Logger logger);
Logger logger, ProblemsFormat format);
virtual ~SubproblemWorker() = default;
void get_solution(std::vector<double> &solution) const;

Expand Down
Loading

0 comments on commit d719d22

Please sign in to comment.