From 8b3bae583cc922f8864d56bbee0138e7d70f8a8a Mon Sep 17 00:00:00 2001 From: azakir <32519851+a-zakir@users.noreply.github.com> Date: Tue, 8 Nov 2022 15:30:45 +0100 Subject: [PATCH 1/2] Managing log between standard output and file (#566) * Pb Gen log: redirect Solver log to file * redirect SolverCbc message handler to file * set log level of ClpSolver message handler * SolverClp/Cbc use inner message_handler instead of creating it * add error localisation in debug * disable debug log for console * add final specifer log level --- .gitignore | 7 ++- antares-deps | 2 +- src/cpp/exe/lpnamer/main.cpp | 9 +-- .../helper/ProblemGenerationLogger.cpp | 59 ++++++++++++----- .../lpnamer/helper/ProblemGenerationLogger.h | 63 ++++++++++++------- .../input_reader/LinkProfileReader.cpp | 9 +-- .../LinkProblemsGenerator.cpp | 6 +- .../problem_modifier/LinkProblemsGenerator.h | 13 ++-- .../problem_modifier/MasterGeneration.cpp | 11 ++-- .../problem_modifier/MasterGeneration.h | 6 +- .../problem_modifier/MasterProblemBuilder.cpp | 5 +- .../problem_modifier/MasterProblemBuilder.h | 4 +- src/cpp/multisolver_interface/SolverCbc.cpp | 39 ++++++------ src/cpp/multisolver_interface/SolverCbc.h | 3 +- src/cpp/multisolver_interface/SolverClp.cpp | 11 ++-- src/cpp/multisolver_interface/SolverClp.h | 5 +- src/cpp/multisolver_interface/SolverCplex.h | 2 +- src/cpp/multisolver_interface/SolverXpress.h | 2 +- .../cpp/lp_namer/MasterProblemBuilderTest.cpp | 12 ++-- vcpkg | 2 +- 20 files changed, 169 insertions(+), 101 deletions(-) diff --git a/.gitignore b/.gitignore index 37f4369c81..3f266d78da 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ _build _install antares-deps +include/google # Cmake generated files CMakeCache.txt @@ -53,4 +54,8 @@ build_config.yaml coverage-reports # Doc pdf file -antaresxpansionuserguide.pdf \ No newline at end of file +antaresxpansionuserguide.pdf +include/google/protobuf/message.h + +# vscode +.vscode diff --git a/antares-deps b/antares-deps index 25a4431084..d1e25edbf0 160000 --- a/antares-deps +++ b/antares-deps @@ -1 +1 @@ -Subproject commit 25a4431084ecae940cbb6b534124dc23cd59ceaa +Subproject commit d1e25edbf0340b483ad7b31edc472039f62165a8 diff --git a/src/cpp/exe/lpnamer/main.cpp b/src/cpp/exe/lpnamer/main.cpp index 6728e2e56b..7f825786d5 100644 --- a/src/cpp/exe/lpnamer/main.cpp +++ b/src/cpp/exe/lpnamer/main.cpp @@ -65,8 +65,8 @@ int main(int argc, char **argv) { po::notify(opts); /**/ using namespace ProblemGenerationLog; - auto logFile = std::make_shared( - root / "lp" / "ProblemGenerationLog.txt"); + const auto log_file_path = root / "lp" / "ProblemGenerationLog.txt"; + auto logFile = std::make_shared(log_file_path); auto logStd = std::make_shared(std::cout); @@ -96,12 +96,13 @@ int main(int argc, char **argv) { Couplings couplings; std::string solver_name = "CBC"; std::vector links = linkBuilder.getLinks(); - LinkProblemsGenerator linkProblemsGenerator(links, solver_name, logger); + LinkProblemsGenerator linkProblemsGenerator(links, solver_name, logger, + log_file_path); linkProblemsGenerator.treatloop(root, couplings); MasterGeneration master_generation(root, links, additionalConstraints, couplings, master_formulation, - solver_name, logger); + solver_name, logger, log_file_path); return 0; } catch (std::exception &e) { diff --git a/src/cpp/lpnamer/helper/ProblemGenerationLogger.cpp b/src/cpp/lpnamer/helper/ProblemGenerationLogger.cpp index 067d7ee15e..a900b0b4d8 100644 --- a/src/cpp/lpnamer/helper/ProblemGenerationLogger.cpp +++ b/src/cpp/lpnamer/helper/ProblemGenerationLogger.cpp @@ -1,10 +1,11 @@ #include "ProblemGenerationLogger.h" + #include "Clock.h" namespace ProblemGenerationLog { -std::string LogLevelToStr(const LOGLEVEL logLevel) { - switch (logLevel) { +std::string LogLevelToStr(const LOGLEVEL log_level) { + switch (log_level) { case LOGLEVEL::TRACE: return " "; case LOGLEVEL::DEBUG: @@ -25,6 +26,7 @@ std::string LogLevelToStr(const LOGLEVEL logLevel) { ProblemGenerationFileLogger::ProblemGenerationFileLogger( const std::filesystem::path& logFilePath) : logFilePath_(logFilePath) { + SetType(LOGGERTYPE::FILE); logFile_.open(logFilePath_, std::ofstream::out | std::ofstream::app); if (logFile_.fail()) { std::cerr << "ProblemGenerationFileLogger: Invalid file (" @@ -39,6 +41,7 @@ void ProblemGenerationFileLogger::DisplayMessage(const std::string& message) { ProblemGenerationOstreamLogger::ProblemGenerationOstreamLogger( std::ostream& stream) : stream_(stream) { + SetType(LOGGERTYPE::CONSOLE); if (stream_.fail()) { std::cerr << "ProblemGenerationOstreamLogger: Invalid stream passed as parameter" @@ -49,33 +52,61 @@ void ProblemGenerationOstreamLogger::DisplayMessage( const std::string& message) { stream_ << message << std::endl; } - -void ProblemGenerationLogger::DisplayMessage(const std::string& message)const { - for (const auto& logger : loggers_) { +void ProblemGenerationLogger::AddLogger( + const ProblemGenerationILoggerSharedPointer& logger) { + loggers_.push_back(logger); + try_to_add_logger_to_enabled_list(logger); +} +void ProblemGenerationLogger::DisplayMessage(const std::string& message) const { + for (const auto& logger : enabled_loggers_) { logger->DisplayMessage(message); } } void ProblemGenerationLogger::DisplayMessage(const std::string& message, - const LOGLEVEL logLevel)const { - for (const auto& logger : loggers_) { - logger->DisplayMessage(LogLevelToStr(logLevel)); + const LOGLEVEL log_level) const { + for (const auto& logger : enabled_loggers_) { + logger->DisplayMessage(LogLevelToStr(log_level)); logger->DisplayMessage(message); } } -std::string ProblemGenerationLogger::PrefixMessage(const LOGLEVEL& logLevel) const { - return LogLevelToStr(logLevel) + clock_utils::timeToStr(std::time(nullptr))+ ": "; +void ProblemGenerationLogger::setLogLevel(const LOGLEVEL log_level) { + log_level_ = log_level; + prefix_ = LogLevelToStr(log_level_); + update_enabled_logger(); +} +void ProblemGenerationLogger::update_enabled_logger() { + enabled_loggers_.clear(); + for (const auto& logger : loggers_) { + try_to_add_logger_to_enabled_list(logger); + } +} +bool ProblemGenerationLogger::try_to_add_logger_to_enabled_list( + const ProblemGenerationILoggerSharedPointer& logger) { + if ((logger->Type() == LOGGERTYPE::CONSOLE && log_level_ != LOGLEVEL::DEBUG && + log_level_ != LOGLEVEL::TRACE) || + logger->Type() == LOGGERTYPE::FILE) { + enabled_loggers_.insert(logger); + return true; + } + return false; +} +std::string ProblemGenerationLogger::PrefixMessage( + const LOGLEVEL& log_level) const { + return LogLevelToStr(log_level) + clock_utils::timeToStr(std::time(nullptr)) + + ": "; } ProblemGenerationLogger& ProblemGenerationLogger::operator<<( - const LOGLEVEL logLevel) { - for (const auto& subLogger : loggers_) { - subLogger->GetOstreamObject() << PrefixMessage(logLevel); + const LOGLEVEL log_level) { + setLogLevel(log_level); + for (const auto& subLogger : enabled_loggers_) { + subLogger->GetOstreamObject() << PrefixMessage(log_level); } return *this; } ProblemGenerationLogger& ProblemGenerationLogger::operator<<( std::ostream& (*f)(std::ostream&)) { - for (const auto& subLogger : loggers_) { + for (const auto& subLogger : enabled_loggers_) { subLogger->GetOstreamObject() << f; } return *this; diff --git a/src/cpp/lpnamer/helper/ProblemGenerationLogger.h b/src/cpp/lpnamer/helper/ProblemGenerationLogger.h index d7c91c7d99..eb3e9d1789 100644 --- a/src/cpp/lpnamer/helper/ProblemGenerationLogger.h +++ b/src/cpp/lpnamer/helper/ProblemGenerationLogger.h @@ -8,16 +8,31 @@ #include #include #include +#include #include - +inline std::string LogLocationToStr(int line, const char* file, + const char* func) { + return std::string("This is line ") + std::to_string(line) + " of file " + + file + " (function " + func + ")\n"; +} +#define LOGLOCATION LogLocationToStr(__LINE__, __FILE__, __func__) namespace ProblemGenerationLog { + enum class LOGLEVEL { NONE, TRACE, DEBUG, INFO, WARNING, ERROR, FATAL }; -std::string LogLevelToStr(const LOGLEVEL logLevel); +enum class LOGGERTYPE { NONE, FILE, CONSOLE }; +std::string LogLevelToStr(const LOGLEVEL log_level); class ProblemGenerationILogger { public: virtual ~ProblemGenerationILogger() = default; virtual void DisplayMessage(const std::string& message) = 0; virtual std::ostream& GetOstreamObject() = 0; + LOGGERTYPE Type() const { return type_; } + + protected: + void SetType(const LOGGERTYPE& type) { type_ = type; } + + private: + LOGGERTYPE type_ = LOGGERTYPE::NONE; }; using ProblemGenerationILoggerSharedPointer = std::shared_ptr; @@ -28,7 +43,8 @@ class ProblemGenerationFileLogger : public ProblemGenerationILogger { public: ~ProblemGenerationFileLogger() override { logFile_.close(); } - explicit ProblemGenerationFileLogger(const std::filesystem::path& logFilePath); + explicit ProblemGenerationFileLogger( + const std::filesystem::path& logFilePath); void DisplayMessage(const std::string& message) override; std::ostream& GetOstreamObject() override { return logFile_; } }; @@ -38,10 +54,10 @@ class ProblemGenerationOstreamLogger : public ProblemGenerationILogger { std::ostream& stream_; public: - ~ProblemGenerationOstreamLogger() override = default; - explicit ProblemGenerationOstreamLogger(std::ostream& stream) ; + ~ProblemGenerationOstreamLogger() override = default; + explicit ProblemGenerationOstreamLogger(std::ostream& stream); void DisplayMessage(const std::string& message) override; - std::ostream& GetOstreamObject() override{ return stream_; } + std::ostream& GetOstreamObject() override { return stream_; } }; class ProblemGenerationLogger; @@ -51,26 +67,23 @@ using ProblemGenerationLoggerSharedPointer = class ProblemGenerationLogger { private: std::string prefix_; - LOGLEVEL logLevel_; + LOGLEVEL log_level_; public: - explicit ProblemGenerationLogger(const LOGLEVEL logLevel) - : prefix_(LogLevelToStr(logLevel)), logLevel_(logLevel) {} + explicit ProblemGenerationLogger(const LOGLEVEL log_level) + : prefix_(LogLevelToStr(log_level)), log_level_(log_level) {} ~ProblemGenerationLogger() = default; - void AddLogger(const ProblemGenerationILoggerSharedPointer& logger) { - loggers_.push_back(logger); - } - void DisplayMessage(const std::string& message)const; - void DisplayMessage(const std::string& message, const LOGLEVEL logLevel)const; - void setLogLevel(const LOGLEVEL logLevel) { - logLevel_ = logLevel; - prefix_ = LogLevelToStr(logLevel_); - } - std::string PrefixMessage() const { return PrefixMessage(logLevel_); } + void AddLogger(const ProblemGenerationILoggerSharedPointer& logger); + void DisplayMessage(const std::string& message) const; + void DisplayMessage(const std::string& message, + const LOGLEVEL log_level) const; + void setLogLevel(const LOGLEVEL log_level); + + std::string PrefixMessage() const { return PrefixMessage(log_level_); } std::string PrefixMessage(const LOGLEVEL&) const; - ProblemGenerationLogger& operator()(const LOGLEVEL logLevel) { - return (*this) << logLevel; + ProblemGenerationLogger& operator()(const LOGLEVEL log_level) { + return (*this) << log_level; } ProblemGenerationLogger& operator()() { return (*this) << PrefixMessage(); } @@ -79,17 +92,21 @@ class ProblemGenerationLogger { const ProblemGenerationLoggerSharedPointer logger) { return (*logger); } - ProblemGenerationLogger& operator<<(const LOGLEVEL logLevel); + ProblemGenerationLogger& operator<<(const LOGLEVEL log_level); template ProblemGenerationLogger& operator<<(T const& t); private: std::list loggers_; + std::set enabled_loggers_; + void update_enabled_logger(); + bool try_to_add_logger_to_enabled_list( + const ProblemGenerationILoggerSharedPointer& logger); }; template ProblemGenerationLogger& ProblemGenerationLogger::operator<<(T const& t) { - for (const auto& subLogger : loggers_) { + for (const auto& subLogger : enabled_loggers_) { subLogger->GetOstreamObject() << t; } return *this; diff --git a/src/cpp/lpnamer/input_reader/LinkProfileReader.cpp b/src/cpp/lpnamer/input_reader/LinkProfileReader.cpp index e678114e93..275921c759 100644 --- a/src/cpp/lpnamer/input_reader/LinkProfileReader.cpp +++ b/src/cpp/lpnamer/input_reader/LinkProfileReader.cpp @@ -6,7 +6,7 @@ std::vector LinkProfileReader::ReadLinkProfile( const std::filesystem::path &direct_filename, const std::filesystem::path &indirect_file_name) { (*logger_)(ProblemGenerationLog::LOGLEVEL::DEBUG) - << "direct_filename : " << direct_filename << "\n" + << LOGLOCATION << "direct_filename : " << direct_filename << "\n" << "indirect_file_name: " << indirect_file_name << "\n"; EnsureFileIsGood(direct_filename); EnsureFileIsGood(indirect_file_name); @@ -16,7 +16,7 @@ std::vector LinkProfileReader::ReadLinkProfile( return result; } void LinkProfileReader::EnsureFileIsGood( - const std::filesystem::path &direct_filename)const { + const std::filesystem::path &direct_filename) const { if (std::ifstream infile(direct_filename); !infile.good()) { (*logger_)(ProblemGenerationLog::LOGLEVEL::FATAL) << "unable to open file" << direct_filename; @@ -67,7 +67,8 @@ void LinkProfileReader::ReadLinkProfile(const std::filesystem::path &filename, } void LinkProfileReader::UpdateProfile(std::vector &result, bool directProfile, double value, - int chronicle_id, size_t time_step)const { + int chronicle_id, + size_t time_step) const { LinkProfile &profile = result.at(chronicle_id); if (directProfile) { profile.direct_link_profile.at(time_step) = value; @@ -77,7 +78,7 @@ void LinkProfileReader::UpdateProfile(std::vector &result, } void LinkProfileReader::ConstructChronicle(std::vector &result, - int chronicle_id) const{ + int chronicle_id) const { if (result.size() <= chronicle_id) { result.emplace_back(); } diff --git a/src/cpp/lpnamer/problem_modifier/LinkProblemsGenerator.cpp b/src/cpp/lpnamer/problem_modifier/LinkProblemsGenerator.cpp index ffed00ab3b..b3727332d6 100644 --- a/src/cpp/lpnamer/problem_modifier/LinkProblemsGenerator.cpp +++ b/src/cpp/lpnamer/problem_modifier/LinkProblemsGenerator.cpp @@ -12,7 +12,7 @@ ProblemData::ProblemData(const std::string &problem_mps, : _problem_mps(problem_mps), _variables_txt(variables_txt) {} std::vector LinkProblemsGenerator::readMPSList( - const std::filesystem::path &mps_filePath_p)const { + const std::filesystem::path &mps_filePath_p) const { std::string line; std::vector result; std::ifstream mps_filestream(mps_filePath_p.c_str()); @@ -82,8 +82,8 @@ void LinkProblemsGenerator::treat(const std::filesystem::path &root, variableReader.getIndirectCostVarColumns(); SolverFactory factory; - auto in_prblm = - std::make_shared(factory.create_solver(_solver_name)); + auto in_prblm = std::make_shared( + factory.create_solver(_solver_name, log_file_path_)); in_prblm->read_prob_mps(mps_name); solver_rename_vars(in_prblm, var_names); diff --git a/src/cpp/lpnamer/problem_modifier/LinkProblemsGenerator.h b/src/cpp/lpnamer/problem_modifier/LinkProblemsGenerator.h index 22b491cc22..9506bd6539 100644 --- a/src/cpp/lpnamer/problem_modifier/LinkProblemsGenerator.h +++ b/src/cpp/lpnamer/problem_modifier/LinkProblemsGenerator.h @@ -31,20 +31,25 @@ class LinkProblemsGenerator { public: LinkProblemsGenerator( const std::vector& links, const std::string& solver_name, - ProblemGenerationLog::ProblemGenerationLoggerSharedPointer logger) - : _links(links), _solver_name(solver_name), logger_(logger) {} + ProblemGenerationLog::ProblemGenerationLoggerSharedPointer logger, + const std::filesystem::path& log_file_path) + : _links(links), + _solver_name(solver_name), + logger_(logger), + log_file_path_(log_file_path) {} void treatloop(const std::filesystem::path& root, Couplings& couplings) const; private: std::vector readMPSList( - const std::filesystem::path& mps_filePath_p)const; + const std::filesystem::path& mps_filePath_p) const; void treat(const std::filesystem::path& root, ProblemData const&, - Couplings& couplings)const; + Couplings& couplings) const; const std::vector& _links; std::string _solver_name; ProblemGenerationLog::ProblemGenerationLoggerSharedPointer logger_; mutable std::mutex coupling_mutex_; + std::filesystem::path log_file_path_; }; diff --git a/src/cpp/lpnamer/problem_modifier/MasterGeneration.cpp b/src/cpp/lpnamer/problem_modifier/MasterGeneration.cpp index 2e160714e1..78e8ada93a 100644 --- a/src/cpp/lpnamer/problem_modifier/MasterGeneration.cpp +++ b/src/cpp/lpnamer/problem_modifier/MasterGeneration.cpp @@ -11,11 +11,12 @@ MasterGeneration::MasterGeneration( const std::filesystem::path &rootPath, const std::vector &links, const AdditionalConstraints &additionalConstraints_p, Couplings &couplings, std::string const &master_formulation, std::string const &solver_name, - ProblemGenerationLog::ProblemGenerationLoggerSharedPointer logger) + ProblemGenerationLog::ProblemGenerationLoggerSharedPointer logger, + const std::filesystem::path &log_file_path) : logger_(logger) { add_candidates(links); write_master_mps(rootPath, master_formulation, solver_name, - additionalConstraints_p); + additionalConstraints_p, log_file_path); write_structure_file(rootPath, couplings); } @@ -34,9 +35,11 @@ void MasterGeneration::add_candidates(const std::vector &links) { void MasterGeneration::write_master_mps( const std::filesystem::path &rootPath, std::string const &master_formulation, std::string const &solver_name, - const AdditionalConstraints &additionalConstraints_p) const{ + const AdditionalConstraints &additionalConstraints_p, + const std::filesystem::path &log_file_path) const { SolverAbstract::Ptr master_l = - MasterProblemBuilder(master_formulation).build(solver_name, candidates); + MasterProblemBuilder(master_formulation) + .build(solver_name, candidates, log_file_path); treatAdditionalConstraints(master_l, additionalConstraints_p, logger_); std::string const &lp_name = "master"; diff --git a/src/cpp/lpnamer/problem_modifier/MasterGeneration.h b/src/cpp/lpnamer/problem_modifier/MasterGeneration.h index 76db4000c1..7c9588df97 100644 --- a/src/cpp/lpnamer/problem_modifier/MasterGeneration.h +++ b/src/cpp/lpnamer/problem_modifier/MasterGeneration.h @@ -24,14 +24,16 @@ class MasterGeneration { const AdditionalConstraints &additionalConstraints_p, Couplings &couplings, std::string const &master_formulation, std::string const &solver_name, - ProblemGenerationLog::ProblemGenerationLoggerSharedPointer logger); + ProblemGenerationLog::ProblemGenerationLoggerSharedPointer logger, + const std::filesystem::path &log_file_path); private: /*methods*/ void add_candidates(const std::vector &links); void write_master_mps(const std::filesystem::path &rootPath, std::string const &master_formulation, std::string const &solver_name, - const AdditionalConstraints &additionalConstraints_p) const; + const AdditionalConstraints &additionalConstraints_p, + const std::filesystem::path &log_file_path) const; void write_structure_file(const std::filesystem::path &rootPath, const Couplings &couplings) const; diff --git a/src/cpp/lpnamer/problem_modifier/MasterProblemBuilder.cpp b/src/cpp/lpnamer/problem_modifier/MasterProblemBuilder.cpp index 968eb46fc5..8b0e73597b 100644 --- a/src/cpp/lpnamer/problem_modifier/MasterProblemBuilder.cpp +++ b/src/cpp/lpnamer/problem_modifier/MasterProblemBuilder.cpp @@ -13,12 +13,13 @@ MasterProblemBuilder::MasterProblemBuilder( : _master_formulation(master_formulation) {} std::shared_ptr MasterProblemBuilder::build( - const std::string& solverName, const std::vector& candidates) { + const std::string& solverName, const std::vector& candidates, + const std::filesystem::path& log_file_path) { _indexOfNvar.clear(); _indexOfPmaxVar.clear(); SolverFactory factory; - auto master_l = factory.create_solver(solverName); + auto master_l = factory.create_solver(solverName, log_file_path); addVariablesPmaxOnEachCandidate(candidates, master_l); diff --git a/src/cpp/lpnamer/problem_modifier/MasterProblemBuilder.h b/src/cpp/lpnamer/problem_modifier/MasterProblemBuilder.h index f7c4f119bd..6f1c9ccd0e 100644 --- a/src/cpp/lpnamer/problem_modifier/MasterProblemBuilder.h +++ b/src/cpp/lpnamer/problem_modifier/MasterProblemBuilder.h @@ -4,6 +4,7 @@ #include +#include #include #include "ActiveLinks.h" @@ -17,7 +18,8 @@ class MasterProblemBuilder { public: explicit MasterProblemBuilder(const std::string& master_formulation); std::shared_ptr build( - const std::string& solverName, const std::vector& candidates); + const std::string& solverName, const std::vector& candidates, + const std::filesystem::path& log_file_path); private: void addNvarOnEachIntegerCandidate( diff --git a/src/cpp/multisolver_interface/SolverCbc.cpp b/src/cpp/multisolver_interface/SolverCbc.cpp index 1906828d79..ff616b0563 100644 --- a/src/cpp/multisolver_interface/SolverCbc.cpp +++ b/src/cpp/multisolver_interface/SolverCbc.cpp @@ -19,25 +19,27 @@ SolverCbc::SolverCbc(const std::filesystem::path &log_file) : SolverCbc() { << std::endl; } else { setvbuf(_fp, nullptr, _IONBF, 0); - _message_handler.setFilePointer(_fp); + _clp_inner_solver.messageHandler()->setFilePointer(_fp); + _cbc.messageHandler()->setFilePointer(_fp); } } } SolverCbc::SolverCbc() { _NumberOfProblems += 1; - _current_log_level = 0; + set_output_log_level(0); } -SolverCbc::SolverCbc(const std::shared_ptr toCopy) - : SolverCbc() { +SolverCbc::SolverCbc(const std::shared_ptr toCopy) { // Try to cast the solver in fictif to a SolverCPLEX if (const auto c = dynamic_cast(toCopy.get())) { + _NumberOfProblems += 1; _clp_inner_solver = OsiClpSolverInterface(c->_clp_inner_solver); _log_file = toCopy->_log_file; _fp = fopen(_log_file.string().c_str(), "a+"); if (_fp != nullptr) { setvbuf(_fp, nullptr, _IONBF, 0); - _message_handler.setFilePointer(_fp); + _clp_inner_solver.messageHandler()->setFilePointer(_fp); + _cbc.messageHandler()->setFilePointer(_fp); } defineCbcModelFromInnerSolver(); } else { @@ -619,19 +621,20 @@ void SolverCbc::set_output_log_level(int loglevel) { // Saving asked log_level for calls in solve, when Cbc is reinitialized _current_log_level = loglevel; - _clp_inner_solver.passInMessageHandler(&_message_handler); - _cbc.passInMessageHandler(&_message_handler); - if (loglevel > 0) { - _message_handler.setLogLevel(0, 1); // Coin messages - _message_handler.setLogLevel(1, 1); // Clp messages - _message_handler.setLogLevel(2, 1); // Presolve messages - _message_handler.setLogLevel(3, 1); // Cgl messages - } else { - _message_handler.setLogLevel(0, 0); // Coin messages - _message_handler.setLogLevel(1, 0); // Clp messages - _message_handler.setLogLevel(2, 0); // Presolve messages - _message_handler.setLogLevel(3, 0); // Cgl messages - _message_handler.setLogLevel(0); + for (const auto message_handler : + {_clp_inner_solver.messageHandler(), _cbc.messageHandler()}) { + if (loglevel > 0) { + message_handler->setLogLevel(0, 1); // Coin messages + message_handler->setLogLevel(1, 1); // Clp messages + message_handler->setLogLevel(2, 1); // Presolve messages + message_handler->setLogLevel(3, 1); // Cgl messages + } else { + message_handler->setLogLevel(0, 0); // Coin messages + message_handler->setLogLevel(1, 0); // Clp messages + message_handler->setLogLevel(2, 0); // Presolve messages + message_handler->setLogLevel(3, 0); // Cgl messages + message_handler->setLogLevel(0); + } } } diff --git a/src/cpp/multisolver_interface/SolverCbc.h b/src/cpp/multisolver_interface/SolverCbc.h index bcbb5f9a6d..cba1802ee5 100644 --- a/src/cpp/multisolver_interface/SolverCbc.h +++ b/src/cpp/multisolver_interface/SolverCbc.h @@ -27,7 +27,6 @@ class SolverCbc : public SolverAbstract { const std::string name_ = "CBC"; OsiClpSolverInterface _clp_inner_solver; CbcModel _cbc; - CoinMessageHandler _message_handler; int _current_log_level; /************************************************************************************************* @@ -184,7 +183,7 @@ class SolverCbc : public SolverAbstract { --------------------------- *************************************************************************************************/ public: - virtual void set_output_log_level(int loglevel) override; + void set_output_log_level(int loglevel) final; virtual void set_algorithm(std::string const &algo) override; virtual void set_threads(int n_threads) override; virtual void set_optimality_gap(double gap) override; diff --git a/src/cpp/multisolver_interface/SolverClp.cpp b/src/cpp/multisolver_interface/SolverClp.cpp index dc7860b3eb..4067ec7144 100644 --- a/src/cpp/multisolver_interface/SolverClp.cpp +++ b/src/cpp/multisolver_interface/SolverClp.cpp @@ -19,18 +19,18 @@ SolverClp::SolverClp(const std::filesystem::path &log_file) : SolverClp() { << std::endl; } else { setvbuf(_fp, NULL, _IONBF, 0); - _message_handler.setFilePointer(_fp); + _clp.messageHandler()->setFilePointer(_fp); } } } SolverClp::SolverClp() { _NumberOfProblems += 1; _fp = nullptr; + set_output_log_level(0); } SolverClp::SolverClp(const std::shared_ptr toCopy) : SolverClp() { - _fp = nullptr; // Try to cast the solver in fictif to a SolverCPLEX if (const auto c = dynamic_cast(toCopy.get())) { _clp = ClpSimplex(c->_clp); @@ -38,7 +38,7 @@ SolverClp::SolverClp(const std::shared_ptr toCopy) _fp = fopen(_log_file.string().c_str(), "a+"); if (_fp != nullptr) { setvbuf(_fp, nullptr, _IONBF, 0); - _message_handler.setFilePointer(_fp); + _clp.messageHandler()->setFilePointer(_fp); } } else { _NumberOfProblems -= 1; @@ -493,11 +493,10 @@ void SolverClp::get_mip_sol(double *primals) { --------------------------- *************************************************************************************************/ void SolverClp::set_output_log_level(int loglevel) { - _clp.passInMessageHandler(&_message_handler); if (loglevel > 0) { - _message_handler.setLogLevel(1); + _clp.messageHandler()->setLogLevel(1); } else { - _message_handler.setLogLevel(0); + _clp.messageHandler()->setLogLevel(0); } } diff --git a/src/cpp/multisolver_interface/SolverClp.h b/src/cpp/multisolver_interface/SolverClp.h index 16fb69ddf5..c8739a34e9 100644 --- a/src/cpp/multisolver_interface/SolverClp.h +++ b/src/cpp/multisolver_interface/SolverClp.h @@ -28,7 +28,6 @@ class SolverClp : public SolverAbstract { public: ClpSimplex _clp; - CoinMessageHandler _message_handler; const std::string name_ = "CLP"; /************************************************************************************************* @@ -56,7 +55,7 @@ class SolverClp : public SolverAbstract { SolverClp(const SolverClp &other) = delete; SolverClp &operator=(const SolverClp &other) = delete; - virtual ~SolverClp(); + ~SolverClp() override; virtual int get_number_of_instances() override; virtual std::string get_solver_name() const override { return name_; } @@ -181,7 +180,7 @@ class SolverClp : public SolverAbstract { --------------------------- *************************************************************************************************/ public: - virtual void set_output_log_level(int loglevel) override; + void set_output_log_level(int loglevel) final; virtual void set_algorithm(std::string const &algo) override; virtual void set_threads(int n_threads) override; virtual void set_optimality_gap(double gap) override; diff --git a/src/cpp/multisolver_interface/SolverCplex.h b/src/cpp/multisolver_interface/SolverCplex.h index c681666dcf..37610dfa1e 100644 --- a/src/cpp/multisolver_interface/SolverCplex.h +++ b/src/cpp/multisolver_interface/SolverCplex.h @@ -180,7 +180,7 @@ class SolverCplex : public SolverAbstract { --------------------------- *************************************************************************************************/ public: - virtual void set_output_log_level(int loglevel) override; + void set_output_log_level(int loglevel) final; virtual void set_algorithm(std::string const &algo) override; virtual void set_threads(int n_threads) override; virtual void set_optimality_gap(double gap) override; diff --git a/src/cpp/multisolver_interface/SolverXpress.h b/src/cpp/multisolver_interface/SolverXpress.h index fa0709c368..d08b57efaf 100644 --- a/src/cpp/multisolver_interface/SolverXpress.h +++ b/src/cpp/multisolver_interface/SolverXpress.h @@ -179,7 +179,7 @@ class SolverXpress : public SolverAbstract { --------------------------- *************************************************************************************************/ public: - virtual void set_output_log_level(int loglevel) override; + void set_output_log_level(int loglevel) final; virtual void set_algorithm(std::string const &algo) override; virtual void set_threads(int n_threads) override; virtual void set_optimality_gap(double gap) override; diff --git a/tests/cpp/lp_namer/MasterProblemBuilderTest.cpp b/tests/cpp/lp_namer/MasterProblemBuilderTest.cpp index cde259b480..827f0f6068 100644 --- a/tests/cpp/lp_namer/MasterProblemBuilderTest.cpp +++ b/tests/cpp/lp_namer/MasterProblemBuilderTest.cpp @@ -33,8 +33,8 @@ TEST(MasterProblemBuilderTest, test_one_candidate_not_integer) { candidateFromLink.end()); } - auto master_problem = - MasterProblemBuilder(master_formulation).build(solver_name, candidates); + auto master_problem = MasterProblemBuilder(master_formulation) + .build(solver_name, candidates, ""); ASSERT_EQ(master_problem->get_ncols(), 1); ASSERT_EQ( master_problem->get_col_names(0, master_problem->get_ncols() - 1)[0], @@ -87,8 +87,8 @@ TEST(MasterProblemBuilderTest, test_one_candidate_integer_problem_integer) { candidateFromLink.end()); } - auto master_problem = - MasterProblemBuilder(master_formulation).build(solver_name, candidates); + auto master_problem = MasterProblemBuilder(master_formulation) + .build(solver_name, candidates, ""); ASSERT_EQ(master_problem->get_ncols(), 2); std::vector colTypeArray(master_problem->get_ncols()); @@ -149,8 +149,8 @@ TEST(MasterProblemBuilderTest, test_one_candidate_integer_problem_relaxed) { candidateFromLink.end()); } - auto master_problem = - MasterProblemBuilder(master_formulation).build(solver_name, candidates); + auto master_problem = MasterProblemBuilder(master_formulation) + .build(solver_name, candidates, ""); ASSERT_EQ(master_problem->get_ncols(), 1); ASSERT_EQ( master_problem->get_col_names(0, master_problem->get_ncols() - 1)[0], diff --git a/vcpkg b/vcpkg index 773516ecf6..01b29f6d82 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit 773516ecf6014d89cc69b11bb54605ad4be56694 +Subproject commit 01b29f6d8212bc845da64773b18665d682f5ab66 From b0a433c7b62fd583653faf1d90282c783e1b8987 Mon Sep 17 00:00:00 2001 From: azakir <32519851+a-zakir@users.noreply.github.com> Date: Wed, 9 Nov 2022 09:22:52 +0100 Subject: [PATCH 2/2] ziplib adr (#486) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ziplib adr * add libzip and libzippp description * complete * Update conception/ziblib/choose-ziplib.md Co-authored-by: Florian Omnès * update lib zip adr * update adr * merge dev & rename zip Adr Co-authored-by: Florian Omnès --- .../Architecture_decision_records/Zip_Lib.md | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 conception/Architecture_decision_records/Zip_Lib.md diff --git a/conception/Architecture_decision_records/Zip_Lib.md b/conception/Architecture_decision_records/Zip_Lib.md new file mode 100644 index 0000000000..c374cbd74e --- /dev/null +++ b/conception/Architecture_decision_records/Zip_Lib.md @@ -0,0 +1,34 @@ +Choose Zip Library +=== +This ADR aims to select the library that will be used to manage MPS files in ZIP archives. + +Status +=== +[minizip-ng](https://github.com/zlib-ng/minizip-ng): Accepted [08/2022] + +Context +=== +Mps files produced by both Antares Simulator and Xpansion can have a signicant weigths on disk space. It's has been proven that putting them in an archive does not alterate Antares and Xpansion algorithms and naturaly resulting zipped files has a less demand on disk space. + +Decision +=== + +[libzip](https://libzip.org/) is a C library for reading, creating, and modifying zip archives. It's the most cited lib based on Google searchs. The first inconvenient of this lib is the repetitive manipulation of pointers and the risks that come with. +[libzippp](https://github.com/ctabin/libzippp) is a simple basic C++ wrapper around the [libzip](https://libzip.org/) library. It is meant to be a portable and easy-to-use library for ZIP handling. + + +libzip & libzippp were rejected because of the way they handle writes: + + - Create a temporary copy of the archive cp archive.zip archive.zip. + - Write the new entry/entries to the temporary archive + - Replace the archive with the temporary archive mv archive.zip. archive.zip + +This strategy ensures that a valid archive remains even in case the program is interrupted, mv being considered an atomic operation. However, it generates a lot of I/O, which is not suitable for us. This behavior cannot be disabled, meaning it is impossible to write entries straight to the archive. + +[minizip-ng](https://github.com/zlib-ng/minizip-ng) on the other hand writes directly to the archive. Attention must be paid to call mz_zip_writer_close in case of user/system interruption. Signal handlers can be used, see e.g AntaresSimulatorTeam/Antares_Simulator#827 + +libzip and it's wrapper libzippp : rejected + +Consequences +=== +Add [minizip-ng](https://github.com/zlib-ng/minizip-ng) as dependency in [antares-deps](https://github.com/AntaresSimulatorTeam/antares-deps) \ No newline at end of file