diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..f2dd0de37 --- /dev/null +++ b/.clang-format @@ -0,0 +1,168 @@ +--- +Language: Cpp +# BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: false +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: true +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^' + Priority: 2 + SortPriority: 0 + - Regex: '^<.*\.h>' + Priority: 1 + SortPriority: 0 + - Regex: '^<.*' + Priority: 2 + SortPriority: 0 + - Regex: '.*' + Priority: 3 + SortPriority: 0 +IncludeIsMainRegex: '([-_](test|unittest))?$' +IncludeIsMainSourceRegex: '' +IndentCaseLabels: true +IndentGotoLabels: true +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + CanonicalDelimiter: '' + BasedOnStyle: google +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +Standard: Auto +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +... + diff --git a/src/cpp/benders/benders_core/BendersBase.cpp b/src/cpp/benders/benders_core/BendersBase.cpp index 90f9149bf..42674f1ee 100644 --- a/src/cpp/benders/benders_core/BendersBase.cpp +++ b/src/cpp/benders/benders_core/BendersBase.cpp @@ -1,30 +1,31 @@ #include "BendersBase.h" -#include "Timer.h" -#include "solver_utils.h" -#include "helpers/Path.h" +#include "Timer.h" #include "glog/logging.h" +#include "helpers/Path.h" +#include "solver_utils.h" -BendersBase::BendersBase(BendersBaseOptions const &options, Logger &logger, Writer writer) : _options(options), _logger(logger), _writer(writer) {} +BendersBase::BendersBase(BendersBaseOptions const &options, Logger &logger, + Writer writer) + : _options(options), _logger(logger), _writer(writer) {} /*! * \brief Initialize set of data used in the loop */ -void BendersBase::init_data() -{ - _data.nbasis = 0; - _data.lb = -1e20; - _data.ub = +1e20; - _data.best_ub = +1e20; - _data.stop = false; - _data.it = 0; - _data.alpha = 0; - _data.invest_cost = 0; - _data.deletedcut = 0; - _data.maxsimplexiter = 0; - _data.minsimplexiter = std::numeric_limits::max(); - _data.best_it = 0; - _data.stopping_criterion = StoppingCriterion::empty; +void BendersBase::init_data() { + _data.nbasis = 0; + _data.lb = -1e20; + _data.ub = +1e20; + _data.best_ub = +1e20; + _data.stop = false; + _data.it = 0; + _data.alpha = 0; + _data.invest_cost = 0; + _data.deletedcut = 0; + _data.maxsimplexiter = 0; + _data.minsimplexiter = std::numeric_limits::max(); + _data.best_it = 0; + _data.stopping_criterion = StoppingCriterion::empty; } /*! @@ -33,60 +34,51 @@ void BendersBase::init_data() * Method to print trace of the Benders algorithm in a csv file * */ -void BendersBase::print_csv() -{ - std::string const output(Path(_options.OUTPUTROOT) / (_options.CSV_NAME + ".csv")); - std::ofstream file(output, std::ios::out | std::ios::trunc); - if (file) - { - file << "Ite;Worker;Problem;Id;UB;LB;bestUB;simplexiter;jump;alpha_i;deletedcut;time;basis;" << std::endl; - int const nite = _trace.size(); - for (int i = 0; i < nite; i++) - { - print_csv_iteration(file, i); - } - file.close(); - } - else - { - LOG(INFO) << "Impossible to open the .csv file" << std::endl; - } +void BendersBase::print_csv() { + std::string const output(Path(_options.OUTPUTROOT) / + (_options.CSV_NAME + ".csv")); + std::ofstream file(output, std::ios::out | std::ios::trunc); + if (file) { + file << "Ite;Worker;Problem;Id;UB;LB;bestUB;simplexiter;jump;alpha_i;" + "deletedcut;time;basis;" + << std::endl; + int const nite = _trace.size(); + for (int i = 0; i < nite; i++) { + print_csv_iteration(file, i); + } + file.close(); + } else { + LOG(INFO) << "Impossible to open the .csv file" << std::endl; + } } -void BendersBase::print_csv_iteration(std::ostream &file, int ite) -{ - - if (_trace[ite]->_valid) - { - Point xopt; - // Write first problem : use result of best iteration - if (ite == 0) - { - int best_it_index = _data.best_it - 1; - if (best_it_index >= 0 && _trace.size() > best_it_index) - { - xopt = _trace[best_it_index]->get_point(); - } - } - else - { - xopt = _trace[ite - 1]->get_point(); - } - print_master_and_cut(file, ite + 1, _trace[ite], xopt); - } +void BendersBase::print_csv_iteration(std::ostream &file, int ite) { + if (_trace[ite]->_valid) { + Point xopt; + // Write first problem : use result of best iteration + if (ite == 0) { + int best_it_index = _data.best_it - 1; + if (best_it_index >= 0 && _trace.size() > best_it_index) { + xopt = _trace[best_it_index]->get_point(); + } + } else { + xopt = _trace[ite - 1]->get_point(); + } + print_master_and_cut(file, ite + 1, _trace[ite], xopt); + } } -void BendersBase::print_master_and_cut(std::ostream &file, int ite, WorkerMasterDataPtr &trace, Point const &xopt) -{ - file << ite << ";"; - - print_master_csv(file, trace, xopt); - - for (auto &kvp : trace->_cut_trace) - { - const SlaveCutDataHandler handler(kvp.second); - file << ite << ";"; - print_cut_csv(file, handler, kvp.first, _problem_to_id[kvp.first]); - } +void BendersBase::print_master_and_cut(std::ostream &file, int ite, + WorkerMasterDataPtr &trace, + Point const &xopt) { + file << ite << ";"; + + print_master_csv(file, trace, xopt); + + for (auto &kvp : trace->_cut_trace) { + const SlaveCutDataHandler handler(kvp.second); + file << ite << ";"; + print_cut_csv(file, handler, kvp.first, _problem_to_id[kvp.first]); + } } /*! @@ -102,21 +94,22 @@ void BendersBase::print_master_and_cut(std::ostream &file, int ite, WorkerMaster * * \param nslaves : number of slaves */ -void BendersBase::print_master_csv(std::ostream &stream, const WorkerMasterDataPtr &trace, Point const &xopt) const -{ - stream << "Master" - << ";"; - stream << _options.MASTER_NAME << ";"; - stream << _data.nslaves << ";"; - stream << trace->_ub << ";"; - stream << trace->_lb << ";"; - stream << trace->_bestub << ";"; - stream << ";"; - stream << norm_point(xopt, trace->get_point()) << ";"; - stream << ";"; - stream << trace->_deleted_cut << ";"; - stream << trace->_time << ";"; - stream << trace->_nbasis << ";" << std::endl; +void BendersBase::print_master_csv(std::ostream &stream, + const WorkerMasterDataPtr &trace, + Point const &xopt) const { + stream << "Master" + << ";"; + stream << _options.MASTER_NAME << ";"; + stream << _data.nslaves << ";"; + stream << trace->_ub << ";"; + stream << trace->_lb << ";"; + stream << trace->_bestub << ";"; + stream << ";"; + stream << norm_point(xopt, trace->get_point()) << ";"; + stream << ";"; + stream << trace->_deleted_cut << ";"; + stream << trace->_time << ";"; + stream << trace->_nbasis << ";" << std::endl; } /*! @@ -130,27 +123,30 @@ void BendersBase::print_master_csv(std::ostream &stream, const WorkerMasterDataP * * \param islaves : problem id */ -void BendersBase::print_cut_csv(std::ostream &stream, SlaveCutDataHandler const &handler, std::string const &name, int const islaves) const -{ - stream << "Slave" - << ";"; - stream << name << ";"; - stream << islaves << ";"; - stream << handler.get_dbl(SLAVE_COST) << ";"; - stream << ";"; - stream << ";"; - stream << handler.get_int(SIMPLEXITER) << ";"; - stream << ";"; - stream << handler.get_dbl(ALPHA_I) << ";"; - stream << ";"; - stream << handler.get_dbl(SLAVE_TIMER) << ";"; - stream << std::endl; +void BendersBase::print_cut_csv(std::ostream &stream, + SlaveCutDataHandler const &handler, + std::string const &name, + int const islaves) const { + stream << "Slave" + << ";"; + stream << name << ";"; + stream << islaves << ";"; + stream << handler.get_dbl(SLAVE_COST) << ";"; + stream << ";"; + stream << ";"; + stream << handler.get_int(SIMPLEXITER) << ";"; + stream << ";"; + stream << handler.get_dbl(ALPHA_I) << ";"; + stream << ";"; + stream << handler.get_dbl(SLAVE_TIMER) << ";"; + stream << std::endl; } /*! * \brief Update best upper bound and best optimal variables * - * Function to update best upper bound and best optimal variables regarding the current ones + * Function to update best upper bound and best optimal variables regarding + *the current ones * * \param best_ub : current best upper bound * @@ -160,14 +156,12 @@ void BendersBase::print_cut_csv(std::ostream &stream, SlaveCutDataHandler const * * \param x0 : current optimal variables */ -void BendersBase::update_best_ub() -{ - if (_data.best_ub > _data.ub) - { - _data.best_ub = _data.ub; - _data.bestx = _data.x0; - _data.best_it = _data.it; - } +void BendersBase::update_best_ub() { + if (_data.best_ub > _data.ub) { + _data.best_ub = _data.ub; + _data.bestx = _data.x0; + _data.best_it = _data.it; + } } /*! @@ -176,16 +170,13 @@ void BendersBase::update_best_ub() * \param simplexiter : int to compare to current max and min * */ -void BendersBase::bound_simplex_iter(int simplexiter) -{ - if (_data.maxsimplexiter < simplexiter) - { - _data.maxsimplexiter = simplexiter; - } - if (_data.minsimplexiter > simplexiter) - { - _data.minsimplexiter = simplexiter; - } +void BendersBase::bound_simplex_iter(int simplexiter) { + if (_data.maxsimplexiter < simplexiter) { + _data.maxsimplexiter = simplexiter; + } + if (_data.minsimplexiter > simplexiter) { + _data.minsimplexiter = simplexiter; + } } /*! @@ -194,21 +185,22 @@ void BendersBase::bound_simplex_iter(int simplexiter) * Method updating the stopping criterion and reinitializing some datas * */ -bool BendersBase::stopping_criterion() -{ - _data.deletedcut = 0; - _data.maxsimplexiter = 0; - _data.minsimplexiter = std::numeric_limits::max(); - if (_data.elapsed_time > _options.TIME_LIMIT) - _data.stopping_criterion = StoppingCriterion::timelimit; - else if ((_options.MAX_ITERATIONS != -1) && (_data.it > _options.MAX_ITERATIONS)) - _data.stopping_criterion = StoppingCriterion::max_iteration; - else if (_data.lb + _options.ABSOLUTE_GAP >= _data.best_ub) - _data.stopping_criterion = StoppingCriterion::absolute_gap; - else if (((_data.best_ub - _data.lb) / _data.best_ub) <= _options.RELATIVE_GAP) - _data.stopping_criterion = StoppingCriterion::relative_gap; - - return _data.stopping_criterion != StoppingCriterion::empty; +bool BendersBase::stopping_criterion() { + _data.deletedcut = 0; + _data.maxsimplexiter = 0; + _data.minsimplexiter = std::numeric_limits::max(); + if (_data.elapsed_time > _options.TIME_LIMIT) + _data.stopping_criterion = StoppingCriterion::timelimit; + else if ((_options.MAX_ITERATIONS != -1) && + (_data.it > _options.MAX_ITERATIONS)) + _data.stopping_criterion = StoppingCriterion::max_iteration; + else if (_data.lb + _options.ABSOLUTE_GAP >= _data.best_ub) + _data.stopping_criterion = StoppingCriterion::absolute_gap; + else if (((_data.best_ub - _data.lb) / _data.best_ub) <= + _options.RELATIVE_GAP) + _data.stopping_criterion = StoppingCriterion::relative_gap; + + return _data.stopping_criterion != StoppingCriterion::empty; } /*! @@ -216,20 +208,19 @@ bool BendersBase::stopping_criterion() * * Fonction to store the current Benders data in the trace */ -void BendersBase::update_trace() -{ - _trace[_data.it - 1]->_lb = _data.lb; - _trace[_data.it - 1]->_ub = _data.ub; - _trace[_data.it - 1]->_bestub = _data.best_ub; - _trace[_data.it - 1]->_x0 = PointPtr(new Point(_data.x0)); - _trace[_data.it - 1]->_max_invest = PointPtr(new Point(_data.max_invest)); - _trace[_data.it - 1]->_min_invest = PointPtr(new Point(_data.min_invest)); - _trace[_data.it - 1]->_deleted_cut = _data.deletedcut; - _trace[_data.it - 1]->_time = _data.timer_master; - _trace[_data.it - 1]->_nbasis = _data.nbasis; - _trace[_data.it - 1]->_invest_cost = _data.invest_cost; - _trace[_data.it - 1]->_operational_cost = _data.slave_cost; - _trace[_data.it - 1]->_valid = true; +void BendersBase::update_trace() { + _trace[_data.it - 1]->_lb = _data.lb; + _trace[_data.it - 1]->_ub = _data.ub; + _trace[_data.it - 1]->_bestub = _data.best_ub; + _trace[_data.it - 1]->_x0 = PointPtr(new Point(_data.x0)); + _trace[_data.it - 1]->_max_invest = PointPtr(new Point(_data.max_invest)); + _trace[_data.it - 1]->_min_invest = PointPtr(new Point(_data.min_invest)); + _trace[_data.it - 1]->_deleted_cut = _data.deletedcut; + _trace[_data.it - 1]->_time = _data.timer_master; + _trace[_data.it - 1]->_nbasis = _data.nbasis; + _trace[_data.it - 1]->_invest_cost = _data.invest_cost; + _trace[_data.it - 1]->_operational_cost = _data.slave_cost; + _trace[_data.it - 1]->_valid = true; } /*! @@ -238,65 +229,66 @@ void BendersBase::update_trace() * \param all_package : storage of each slaves status * \param data : BendersData used to get master solving status */ -void BendersBase::check_status(AllCutPackage const &all_package) const -{ - if (_data.master_status != SOLVER_STATUS::OPTIMAL) - { - LOG(INFO) << "Master status is " << _data.master_status << std::endl; - throw InvalidSolverStatusException("Master status is " + std::to_string(_data.master_status)); - } - for (const auto &package : all_package) - { - for (const auto &kvp : package) - { - SlaveCutDataPtr slave_cut_data(new SlaveCutData(kvp.second)); - SlaveCutDataHandlerPtr const handler(new SlaveCutDataHandler(slave_cut_data)); - if (handler->get_int(LPSTATUS) != SOLVER_STATUS::OPTIMAL) - { - std::stringstream stream; - stream << "Slave " << kvp.first << " status is " << handler->get_int(LPSTATUS); - LOG(INFO) << stream.str() << std::endl; - - throw InvalidSolverStatusException(stream.str()); - } - } - } +void BendersBase::check_status(AllCutPackage const &all_package) const { + if (_data.master_status != SOLVER_STATUS::OPTIMAL) { + LOG(INFO) << "Master status is " << _data.master_status << std::endl; + throw InvalidSolverStatusException("Master status is " + + std::to_string(_data.master_status)); + } + for (const auto &package : all_package) { + for (const auto &kvp : package) { + SlaveCutDataPtr slave_cut_data(new SlaveCutData(kvp.second)); + SlaveCutDataHandlerPtr const handler( + new SlaveCutDataHandler(slave_cut_data)); + if (handler->get_int(LPSTATUS) != SOLVER_STATUS::OPTIMAL) { + std::stringstream stream; + stream << "Slave " << kvp.first << " status is " + << handler->get_int(LPSTATUS); + LOG(INFO) << stream.str() << std::endl; + + throw InvalidSolverStatusException(stream.str()); + } + } + } } /*! * \brief Solve and get optimal variables of the Master Problem * - * Method to solve and get optimal variables of the Master Problem and update upper and lower bound + * Method to solve and get optimal variables of the Master Problem and update + * upper and lower bound * */ -void BendersBase::get_master_value() -{ - Timer timer_master; - _data.alpha_i.resize(_data.nslaves); - if (_options.BOUND_ALPHA) - { - _master->fix_alpha(_data.best_ub); - } - _master->solve(_data.master_status, _options.OUTPUTROOT); - _master->get(_data.x0, _data.alpha, _data.alpha_i); /*Get the optimal variables of the Master Problem*/ - _master->get_value(_data.lb); /*Get the optimal value of the Master Problem*/ - - _data.invest_cost = _data.lb - _data.alpha; - - for (auto pairIdName : _master->_id_to_name) - { - _master->_solver->get_ub(&_data.max_invest[pairIdName.second], pairIdName.first, pairIdName.first); - _master->_solver->get_lb(&_data.min_invest[pairIdName.second], pairIdName.first, pairIdName.first); - } - - _data.ub = _data.invest_cost; - _data.timer_master = timer_master.elapsed(); +void BendersBase::get_master_value() { + Timer timer_master; + _data.alpha_i.resize(_data.nslaves); + if (_options.BOUND_ALPHA) { + _master->fix_alpha(_data.best_ub); + } + _master->solve(_data.master_status, _options.OUTPUTROOT); + _master->get( + _data.x0, _data.alpha, + _data.alpha_i); /*Get the optimal variables of the Master Problem*/ + _master->get_value(_data.lb); /*Get the optimal value of the Master Problem*/ + + _data.invest_cost = _data.lb - _data.alpha; + + for (auto pairIdName : _master->_id_to_name) { + _master->_solver->get_ub(&_data.max_invest[pairIdName.second], + pairIdName.first, pairIdName.first); + _master->_solver->get_lb(&_data.min_invest[pairIdName.second], + pairIdName.first, pairIdName.first); + } + + _data.ub = _data.invest_cost; + _data.timer_master = timer_master.elapsed(); } /*! * \brief Solve and store optimal variables of all Slaves Problems * - * Method to solve and store optimal variables of all Slaves Problems after fixing trial values + * Method to solve and store optimal variables of all Slaves Problems after + * fixing trial values * * \param slave_cut_package : map storing for each slave its cut * @@ -306,96 +298,93 @@ void BendersBase::get_master_value() * * \param options : set of parameters */ -void BendersBase::get_slave_cut(SlaveCutPackage &slave_cut_package) -{ - for (auto &kvp : _map_slaves) - { - Timer timer_slave; - WorkerSlavePtr &ptr(kvp.second); - SlaveCutDataPtr slave_cut_data(new SlaveCutData); - SlaveCutDataHandlerPtr handler(new SlaveCutDataHandler(slave_cut_data)); - ptr->fix_to(_data.x0); - ptr->solve(handler->get_int(LPSTATUS), _options.OUTPUTROOT); - - ptr->get_value(handler->get_dbl(SLAVE_COST)); - ptr->get_subgradient(handler->get_subgradient()); - ptr->get_splex_num_of_ite_last(handler->get_int(SIMPLEXITER)); - handler->get_dbl(SLAVE_TIMER) = timer_slave.elapsed(); - slave_cut_package[kvp.first] = *slave_cut_data; - } +void BendersBase::get_slave_cut(SlaveCutPackage &slave_cut_package) { + for (auto &kvp : _map_slaves) { + Timer timer_slave; + WorkerSlavePtr &ptr(kvp.second); + SlaveCutDataPtr slave_cut_data(new SlaveCutData); + SlaveCutDataHandlerPtr handler(new SlaveCutDataHandler(slave_cut_data)); + ptr->fix_to(_data.x0); + ptr->solve(handler->get_int(LPSTATUS), _options.OUTPUTROOT); + + ptr->get_value(handler->get_dbl(SLAVE_COST)); + ptr->get_subgradient(handler->get_subgradient()); + ptr->get_splex_num_of_ite_last(handler->get_int(SIMPLEXITER)); + handler->get_dbl(SLAVE_TIMER) = timer_slave.elapsed(); + slave_cut_package[kvp.first] = *slave_cut_data; + } } /*! * \brief Add cut to Master Problem and store the cut in a set * - * Method to add cut from a slave to the Master Problem and store this cut in a map linking each slave to its set of cuts. + * Method to add cut from a slave to the Master Problem and store this cut in a + * map linking each slave to its set of cuts. * - * \param all_package : vector storing all cuts information for each slave problem + * \param all_package : vector storing all cuts information for each slave + * problem * */ -void BendersBase::compute_cut(AllCutPackage const &all_package) -{ - for (int i(0); i < all_package.size(); i++) - { - for (auto const &itmap : all_package[i]) - { - SlaveCutDataPtr slave_cut_data(new SlaveCutData(itmap.second)); - SlaveCutDataHandlerPtr handler(new SlaveCutDataHandler(slave_cut_data)); - handler->get_dbl(ALPHA_I) = _data.alpha_i[_problem_to_id[itmap.first]]; - _data.ub += handler->get_dbl(SLAVE_COST); - SlaveCutTrimmer cut(handler, _data.x0); - - _master->add_cut_slave(_problem_to_id[itmap.first], handler->get_subgradient(), _data.x0, handler->get_dbl(SLAVE_COST)); - _all_cuts_storage[itmap.first].insert(cut); - _trace[_data.it - 1]->_cut_trace[itmap.first] = slave_cut_data; - - bound_simplex_iter(handler->get_int(SIMPLEXITER)); - } - } +void BendersBase::compute_cut(AllCutPackage const &all_package) { + for (int i(0); i < all_package.size(); i++) { + for (auto const &itmap : all_package[i]) { + SlaveCutDataPtr slave_cut_data(new SlaveCutData(itmap.second)); + SlaveCutDataHandlerPtr handler(new SlaveCutDataHandler(slave_cut_data)); + handler->get_dbl(ALPHA_I) = _data.alpha_i[_problem_to_id[itmap.first]]; + _data.ub += handler->get_dbl(SLAVE_COST); + SlaveCutTrimmer cut(handler, _data.x0); + + _master->add_cut_slave(_problem_to_id[itmap.first], + handler->get_subgradient(), _data.x0, + handler->get_dbl(SLAVE_COST)); + _all_cuts_storage[itmap.first].insert(cut); + _trace[_data.it - 1]->_cut_trace[itmap.first] = slave_cut_data; + + bound_simplex_iter(handler->get_int(SIMPLEXITER)); + } + } } /*! * \brief Add aggregated cut to Master Problem and store it in a set * - * Method to add aggregated cut from slaves to Master Problem and store it in a map linking each slave to its set of non-aggregated cut + * Method to add aggregated cut from slaves to Master Problem and store it in a + * map linking each slave to its set of non-aggregated cut * - * \param all_package : vector storing all cuts information for each slave problem + * \param all_package : vector storing all cuts information for each slave + * problem */ -void BendersBase::compute_cut_aggregate(AllCutPackage const &all_package) -{ - Point s; - double rhs(0); - for (int i(0); i < all_package.size(); i++) - { - for (auto const &itmap : all_package[i]) - { - SlaveCutDataPtr slave_cut_data(new SlaveCutData(itmap.second)); - SlaveCutDataHandlerPtr handler(new SlaveCutDataHandler(slave_cut_data)); - _data.ub += handler->get_dbl(SLAVE_COST); - rhs += handler->get_dbl(SLAVE_COST); - - compute_cut_val(handler, _data.x0, s); - - SlaveCutTrimmer cut(handler, _data.x0); - - _all_cuts_storage.find(itmap.first)->second.insert(cut); - _trace[_data.it - 1]->_cut_trace[itmap.first] = slave_cut_data; - - bound_simplex_iter(handler->get_int(SIMPLEXITER)); - } - } - _master->add_cut(s, _data.x0, rhs); +void BendersBase::compute_cut_aggregate(AllCutPackage const &all_package) { + Point s; + double rhs(0); + for (int i(0); i < all_package.size(); i++) { + for (auto const &itmap : all_package[i]) { + SlaveCutDataPtr slave_cut_data(new SlaveCutData(itmap.second)); + SlaveCutDataHandlerPtr handler(new SlaveCutDataHandler(slave_cut_data)); + _data.ub += handler->get_dbl(SLAVE_COST); + rhs += handler->get_dbl(SLAVE_COST); + + compute_cut_val(handler, _data.x0, s); + + SlaveCutTrimmer cut(handler, _data.x0); + + _all_cuts_storage.find(itmap.first)->second.insert(cut); + _trace[_data.it - 1]->_cut_trace[itmap.first] = slave_cut_data; + + bound_simplex_iter(handler->get_int(SIMPLEXITER)); + } + } + _master->add_cut(s, _data.x0, rhs); } -void BendersBase::compute_cut_val(const SlaveCutDataHandlerPtr &handler, const Point &x0, Point &s) const -{ - for (auto const &var : x0) - { - if (handler->get_subgradient().find(var.first) != handler->get_subgradient().end()) - { - s[var.first] += handler->get_subgradient().find(var.first)->second; - } - } +void BendersBase::compute_cut_val(const SlaveCutDataHandlerPtr &handler, + const Point &x0, Point &s) const { + for (auto const &var : x0) { + if (handler->get_subgradient().find(var.first) != + handler->get_subgradient().end()) { + s[var.first] += handler->get_subgradient().find(var.first)->second; + } + } } /*! * \brief Add cuts in master problem @@ -404,131 +393,124 @@ void BendersBase::compute_cut_val(const SlaveCutDataHandlerPtr &handler, const P * * \param all_package : storage of every slave information * - * \param slave_cut_id : map linking each slaves to their cuts ids in the master problem + * \param slave_cut_id : map linking each slaves to their cuts ids in the + *master problem * - * \param dynamic_aggregate_cuts : vector of tuple storing cut information (rhs, x0, subgradient) + * \param dynamic_aggregate_cuts : vector of tuple storing cut information + *(rhs, x0, subgradient) */ -void BendersBase::build_cut_full(AllCutPackage const &all_package) -{ - check_status(all_package); - if (_options.AGGREGATION) - { - compute_cut_aggregate(all_package); - } - else - { - compute_cut(all_package); - } +void BendersBase::build_cut_full(AllCutPackage const &all_package) { + check_status(all_package); + if (_options.AGGREGATION) { + compute_cut_aggregate(all_package); + } else { + compute_cut(all_package); + } } -LogData BendersBase::build_log_data_from_data() const -{ - auto logData = defineLogDataFromBendersDataAndTrace(_data, _trace); - logData.optimality_gap = _options.ABSOLUTE_GAP; - logData.relative_gap = _options.RELATIVE_GAP; - logData.max_iterations = _options.MAX_ITERATIONS; - return logData; +LogData BendersBase::build_log_data_from_data() const { + auto logData = defineLogDataFromBendersDataAndTrace(_data, _trace); + logData.optimality_gap = _options.ABSOLUTE_GAP; + logData.relative_gap = _options.RELATIVE_GAP; + logData.max_iterations = _options.MAX_ITERATIONS; + return logData; } -void BendersBase::post_run_actions() const -{ - LogData logData = build_log_data_from_data(); +void BendersBase::post_run_actions() const { + LogData logData = build_log_data_from_data(); - _logger->log_stop_criterion_reached(_data.stopping_criterion); - _logger->log_at_ending(logData); + _logger->log_stop_criterion_reached(_data.stopping_criterion); + _logger->log_at_ending(logData); - _writer->end_writing(output_data()); + _writer->end_writing(output_data()); } -Output::IterationsData BendersBase::output_data() const -{ - Output::IterationsData iterations_data; - Output::Iterations iters; - iterations_data.nbWeeks_p = _nbWeeks; - // Iterations - for (auto masterDataPtr_l : _trace) - { - if (masterDataPtr_l->_valid) - { - iters.push_back(iteration(masterDataPtr_l)); - } - } - iterations_data.iters = iters; - iterations_data.solution_data = solution(); - iterations_data.elapsed_time = _data.elapsed_time; - return iterations_data; +Output::IterationsData BendersBase::output_data() const { + Output::IterationsData iterations_data; + Output::Iterations iters; + iterations_data.nbWeeks_p = _nbWeeks; + // Iterations + for (auto masterDataPtr_l : _trace) { + if (masterDataPtr_l->_valid) { + iters.push_back(iteration(masterDataPtr_l)); + } + } + iterations_data.iters = iters; + iterations_data.solution_data = solution(); + iterations_data.elapsed_time = _data.elapsed_time; + return iterations_data; } -Output::Iteration BendersBase::iteration(const WorkerMasterDataPtr &masterDataPtr_l) const -{ - Output::Iteration iteration; - iteration.time = masterDataPtr_l->_time; - iteration.lb = masterDataPtr_l->_lb; - iteration.ub = masterDataPtr_l->_ub; - iteration.best_ub = masterDataPtr_l->_bestub; - iteration.optimality_gap = masterDataPtr_l->_bestub - masterDataPtr_l->_lb; - iteration.relative_gap = (masterDataPtr_l->_bestub - masterDataPtr_l->_lb) / masterDataPtr_l->_bestub; - iteration.investment_cost = masterDataPtr_l->_invest_cost; - iteration.operational_cost = masterDataPtr_l->_operational_cost; - iteration.overall_cost = masterDataPtr_l->_invest_cost + masterDataPtr_l->_operational_cost; - iteration.candidates = candidates_data(masterDataPtr_l); - return iteration; +Output::Iteration BendersBase::iteration( + const WorkerMasterDataPtr &masterDataPtr_l) const { + Output::Iteration iteration; + iteration.time = masterDataPtr_l->_time; + iteration.lb = masterDataPtr_l->_lb; + iteration.ub = masterDataPtr_l->_ub; + iteration.best_ub = masterDataPtr_l->_bestub; + iteration.optimality_gap = masterDataPtr_l->_bestub - masterDataPtr_l->_lb; + iteration.relative_gap = (masterDataPtr_l->_bestub - masterDataPtr_l->_lb) / + masterDataPtr_l->_bestub; + iteration.investment_cost = masterDataPtr_l->_invest_cost; + iteration.operational_cost = masterDataPtr_l->_operational_cost; + iteration.overall_cost = + masterDataPtr_l->_invest_cost + masterDataPtr_l->_operational_cost; + iteration.candidates = candidates_data(masterDataPtr_l); + return iteration; } -Output::CandidatesVec BendersBase::candidates_data(const WorkerMasterDataPtr &masterDataPtr_l) const -{ - Output::CandidatesVec candidates_vec; - for (const auto &pairNameValue_l : masterDataPtr_l->get_point()) - { - Output::CandidateData candidate_data; - candidate_data.name = pairNameValue_l.first; - candidate_data.invest = pairNameValue_l.second; - candidate_data.min = masterDataPtr_l->get_min_invest()[pairNameValue_l.first]; - candidate_data.max = masterDataPtr_l->get_max_invest()[pairNameValue_l.first]; - candidates_vec.push_back(candidate_data); - } - - return candidates_vec; +Output::CandidatesVec BendersBase::candidates_data( + const WorkerMasterDataPtr &masterDataPtr_l) const { + Output::CandidatesVec candidates_vec; + for (const auto &pairNameValue_l : masterDataPtr_l->get_point()) { + Output::CandidateData candidate_data; + candidate_data.name = pairNameValue_l.first; + candidate_data.invest = pairNameValue_l.second; + candidate_data.min = + masterDataPtr_l->get_min_invest()[pairNameValue_l.first]; + candidate_data.max = + masterDataPtr_l->get_max_invest()[pairNameValue_l.first]; + candidates_vec.push_back(candidate_data); + } + + return candidates_vec; } -Output::SolutionData BendersBase::solution() const -{ - Output::SolutionData solution_data; - solution_data.nbWeeks_p = _nbWeeks; - solution_data.best_it = _data.best_it; - solution_data.problem_status = status_from_criterion(); - size_t bestItIndex_l = _data.best_it - 1; - - if (bestItIndex_l < _trace.size()) - { - solution_data.solution = iteration(_trace[bestItIndex_l]); - solution_data.solution.optimality_gap = _data.best_ub - _data.lb; - solution_data.solution.relative_gap = solution_data.solution.optimality_gap / _data.best_ub; - solution_data.stopping_criterion = criterion_to_str(_data.stopping_criterion); - } - return solution_data; +Output::SolutionData BendersBase::solution() const { + Output::SolutionData solution_data; + solution_data.nbWeeks_p = _nbWeeks; + solution_data.best_it = _data.best_it; + solution_data.problem_status = status_from_criterion(); + size_t bestItIndex_l = _data.best_it - 1; + + if (bestItIndex_l < _trace.size()) { + solution_data.solution = iteration(_trace[bestItIndex_l]); + solution_data.solution.optimality_gap = _data.best_ub - _data.lb; + solution_data.solution.relative_gap = + solution_data.solution.optimality_gap / _data.best_ub; + solution_data.stopping_criterion = + criterion_to_str(_data.stopping_criterion); + } + return solution_data; } -std::string BendersBase::status_from_criterion() const -{ - switch (_data.stopping_criterion) - { - case StoppingCriterion::absolute_gap: - case StoppingCriterion::relative_gap: - case StoppingCriterion::max_iteration: - case StoppingCriterion::timelimit: - return Output::STATUS_OPTIMAL_C; - - default: - return Output::STATUS_ERROR_C; - } +std::string BendersBase::status_from_criterion() const { + switch (_data.stopping_criterion) { + case StoppingCriterion::absolute_gap: + case StoppingCriterion::relative_gap: + case StoppingCriterion::max_iteration: + case StoppingCriterion::timelimit: + return Output::STATUS_OPTIMAL_C; + + default: + return Output::STATUS_ERROR_C; + } } /*! * \brief Get path to slave problem mps file from options */ -std::string BendersBase::get_slave_path(std::string const &slave_name) const -{ - return (Path(_options.INPUTROOT) / (slave_name + MPS_SUFFIX)).get_str(); +std::string BendersBase::get_slave_path(std::string const &slave_name) const { + return (Path(_options.INPUTROOT) / (slave_name + MPS_SUFFIX)).get_str(); } /*! @@ -538,35 +520,28 @@ std::string BendersBase::get_slave_path(std::string const &slave_name) const * * \param name : slave name */ -double BendersBase::slave_weight(int nslaves, std::string const &name) const -{ - if (_options.SLAVE_WEIGHT == SLAVE_WEIGHT_UNIFORM_CST_STR) - { - return 1 / static_cast(nslaves); - } - else if (_options.SLAVE_WEIGHT == SLAVE_WEIGHT_CST_STR) - { - double const weight(_options.SLAVE_WEIGHT_VALUE); - return 1 / weight; - } - else - { - return _options.weights.find(name)->second; - } +double BendersBase::slave_weight(int nslaves, std::string const &name) const { + if (_options.SLAVE_WEIGHT == SLAVE_WEIGHT_UNIFORM_CST_STR) { + return 1 / static_cast(nslaves); + } else if (_options.SLAVE_WEIGHT == SLAVE_WEIGHT_CST_STR) { + double const weight(_options.SLAVE_WEIGHT_VALUE); + return 1 / weight; + } else { + return _options.weights.find(name)->second; + } } /*! * \brief Get path to master problem mps file from options */ -std::string BendersBase::get_master_path() const -{ - return (Path(_options.INPUTROOT) / (_options.MASTER_NAME + MPS_SUFFIX)).get_str(); +std::string BendersBase::get_master_path() const { + return (Path(_options.INPUTROOT) / (_options.MASTER_NAME + MPS_SUFFIX)) + .get_str(); } /*! * \brief Get path to structure txt file from options */ -std::string BendersBase::get_structure_path() const -{ - return (Path(_options.INPUTROOT) / _options.STRUCTURE_FILE).get_str(); +std::string BendersBase::get_structure_path() const { + return (Path(_options.INPUTROOT) / _options.STRUCTURE_FILE).get_str(); } \ No newline at end of file diff --git a/src/cpp/benders/benders_core/SimplexBasis.cpp b/src/cpp/benders/benders_core/SimplexBasis.cpp index 7eb663b69..8197040e2 100644 --- a/src/cpp/benders/benders_core/SimplexBasis.cpp +++ b/src/cpp/benders/benders_core/SimplexBasis.cpp @@ -1,71 +1,58 @@ #include "SimplexBasis.h" +SimplexBasisHandler::SimplexBasisHandler() {} -SimplexBasisHandler::SimplexBasisHandler() { -} - -SimplexBasisHandler::SimplexBasisHandler(SimplexBasisPtr & data) :_data(data) { -} +SimplexBasisHandler::SimplexBasisHandler(SimplexBasisPtr& data) : _data(data) {} -SimplexBasisHandler::~SimplexBasisHandler() { - -} +SimplexBasisHandler::~SimplexBasisHandler() {} /*! -* \brief Stream output overloading for vector of IntVector -* -* \param stream : stream output -* -* \param rhs : vector of IntVector -*/ -bool SimplexBasisHandler::operator<(SimplexBasisHandler const & other) const -{ - return((get_row() < other.get_row()) || ((get_row() == other.get_row()) && (get_col() < other.get_col()))); + * \brief Stream output overloading for vector of IntVector + * + * \param stream : stream output + * + * \param rhs : vector of IntVector + */ +bool SimplexBasisHandler::operator<(SimplexBasisHandler const& other) const { + return ((get_row() < other.get_row()) || + ((get_row() == other.get_row()) && (get_col() < other.get_col()))); } /*! -* \brief Get basis status of the column in constraint matrix -*/ -IntVector & SimplexBasisHandler::get_col() { - return _data->second; -} + * \brief Get basis status of the column in constraint matrix + */ +IntVector& SimplexBasisHandler::get_col() { return _data->second; } /*! -* \brief Get basis status of each variable in the matrix -*/ -IntVector & SimplexBasisHandler::get_row() { - return _data->first; -} + * \brief Get basis status of each variable in the matrix + */ +IntVector& SimplexBasisHandler::get_row() { return _data->first; } /*! -* \brief Get basis status of the column in constraint matrix -*/ -IntVector const & SimplexBasisHandler::get_col() const { - return _data->second; -} + * \brief Get basis status of the column in constraint matrix + */ +IntVector const& SimplexBasisHandler::get_col() const { return _data->second; } /*! -* \brief Get basis status of each variable in the matrix -*/ -IntVector const & SimplexBasisHandler::get_row() const { - return _data->first; -} + * \brief Get basis status of each variable in the matrix + */ +IntVector const& SimplexBasisHandler::get_row() const { return _data->first; } /*! -* \brief Print function for simplex basis -* -* \param stream : stream output -*/ -void SimplexBasisHandler::print(std::ostream & stream)const { - std::stringstream buffer; - buffer << "Rows : ("; - for (int i(0); i < get_row().size(); i++) { - buffer << get_row()[i] << " "; - } - buffer << ") || Cols : ("; - for (int i(0); i < get_col().size(); i++) { - buffer << get_col()[i] << " "; - } - buffer << ")"; - stream << buffer.str(); + * \brief Print function for simplex basis + * + * \param stream : stream output + */ +void SimplexBasisHandler::print(std::ostream& stream) const { + std::stringstream buffer; + buffer << "Rows : ("; + for (int i(0); i < get_row().size(); i++) { + buffer << get_row()[i] << " "; + } + buffer << ") || Cols : ("; + for (int i(0); i < get_col().size(); i++) { + buffer << get_col()[i] << " "; + } + buffer << ")"; + stream << buffer.str(); } diff --git a/src/cpp/benders/benders_core/SimulationOptions.cpp b/src/cpp/benders/benders_core/SimulationOptions.cpp index 22f373871..d417a0b38 100644 --- a/src/cpp/benders/benders_core/SimulationOptions.cpp +++ b/src/cpp/benders/benders_core/SimulationOptions.cpp @@ -1,35 +1,35 @@ #include "SimulationOptions.h" + #include "helpers/Path.h" /*! * \brief Constructor of Benders Options * */ -SimulationOptions::SimulationOptions() : +SimulationOptions::SimulationOptions() + : #define BENDERS_OPTIONS_MACRO(name__, type__, default__) name__(default__), #include "SimulationOptions.hxx" #undef BENDERS_OPTIONS_MACRO - _weights() -{ + _weights() { } /*! * \brief Constructor of Benders Options * \param options_filename file that contains options */ -SimulationOptions::SimulationOptions(const std::string &options_filename) : SimulationOptions() -{ - read(options_filename); +SimulationOptions::SimulationOptions(const std::string &options_filename) + : SimulationOptions() { + read(options_filename); } /*! * \brief Write default options in "options_default" txt file */ -void SimulationOptions::write_default() const -{ - std::ofstream file("options_default.txt"); - print(file); - file.close(); +void SimulationOptions::write_default() const { + std::ofstream file("options_default.txt"); + print(file); + file.close(); } /*! @@ -37,74 +37,60 @@ void SimulationOptions::write_default() const * * \param file_name : path to options txt file */ -void SimulationOptions::read(std::string const &file_name) -{ - std::ifstream file(file_name.c_str()); - if (file.good()) - { - std::string line; - std::string name; - while (std::getline(file, line)) - { - std::stringstream buffer(line); - buffer >> name; +void SimulationOptions::read(std::string const &file_name) { + std::ifstream file(file_name.c_str()); + if (file.good()) { + std::string line; + std::string name; + while (std::getline(file, line)) { + std::stringstream buffer(line); + buffer >> name; #define BENDERS_OPTIONS_MACRO(name__, type__, default__) \ - if (#name__ == name) \ - buffer >> name__; + if (#name__ == name) buffer >> name__; #include "SimulationOptions.hxx" #undef BENDERS_OPTIONS_MACRO - } - set_weights(); - } - else - { - std::cout << "setting option to default" << std::endl; - write_default(); - } + } + set_weights(); + } else { + std::cout << "setting option to default" << std::endl; + write_default(); + } } -void SimulationOptions::set_weights() -{ - if (SLAVE_WEIGHT != SLAVE_WEIGHT_UNIFORM_CST_STR && SLAVE_WEIGHT != SLAVE_WEIGHT_CST_STR) - { - std::string line; - std::string filename(Path(INPUTROOT) / SLAVE_WEIGHT); - std::ifstream file(filename); - - if (!file) - { - std::cout << "Cannot open file " << filename << std::endl; - } - double weights_sum = -1; - while (std::getline(file, line)) - { - std::stringstream buffer(line); - std::string problem_name; - - buffer >> problem_name; - if (problem_name == WEIGHT_SUM_CST_STR) - { - buffer >> weights_sum; - } - else - { - buffer >> _weights[problem_name]; - } - } - - if (weights_sum == -1) - { - std::cout << "ERROR : Invalid weight file format : Key WEIGHT_SUM not found." << std::endl; - std::exit(1); - } - else - { - for (const auto &kvp : _weights) - { - _weights[kvp.first] /= weights_sum; - } - } - } +void SimulationOptions::set_weights() { + if (SLAVE_WEIGHT != SLAVE_WEIGHT_UNIFORM_CST_STR && + SLAVE_WEIGHT != SLAVE_WEIGHT_CST_STR) { + std::string line; + std::string filename(Path(INPUTROOT) / SLAVE_WEIGHT); + std::ifstream file(filename); + + if (!file) { + std::cout << "Cannot open file " << filename << std::endl; + } + double weights_sum = -1; + while (std::getline(file, line)) { + std::stringstream buffer(line); + std::string problem_name; + + buffer >> problem_name; + if (problem_name == WEIGHT_SUM_CST_STR) { + buffer >> weights_sum; + } else { + buffer >> _weights[problem_name]; + } + } + + if (weights_sum == -1) { + std::cout + << "ERROR : Invalid weight file format : Key WEIGHT_SUM not found." + << std::endl; + std::exit(1); + } else { + for (const auto &kvp : _weights) { + _weights[kvp.first] /= weights_sum; + } + } + } } /*! @@ -112,54 +98,51 @@ void SimulationOptions::set_weights() * * \param stream : output stream */ -void SimulationOptions::print(std::ostream &stream) const -{ -#define BENDERS_OPTIONS_MACRO(name__, type__, default__) stream << std::setw(30) << #name__ << std::setw(50) << name__ << std::endl; +void SimulationOptions::print(std::ostream &stream) const { +#define BENDERS_OPTIONS_MACRO(name__, type__, default__) \ + stream << std::setw(30) << #name__ << std::setw(50) << name__ << std::endl; #include "SimulationOptions.hxx" #undef BENDERS_OPTIONS_MACRO - stream << std::endl; + stream << std::endl; - if (SLAVE_NUMBER == 1) - { - stream << "Sequential launch (only one slave problem)" << std::endl; - } + if (SLAVE_NUMBER == 1) { + stream << "Sequential launch (only one slave problem)" << std::endl; + } } -BaseOptions SimulationOptions::get_base_options() const -{ - BaseOptions result; +BaseOptions SimulationOptions::get_base_options() const { + BaseOptions result; - result.LOG_LEVEL = LOG_LEVEL; - result.SLAVE_NUMBER = SLAVE_NUMBER; + result.LOG_LEVEL = LOG_LEVEL; + result.SLAVE_NUMBER = SLAVE_NUMBER; - result.SLAVE_WEIGHT_VALUE = SLAVE_WEIGHT_VALUE; + result.SLAVE_WEIGHT_VALUE = SLAVE_WEIGHT_VALUE; - result.OUTPUTROOT = OUTPUTROOT; - result.SLAVE_WEIGHT = SLAVE_WEIGHT; - result.MASTER_NAME = MASTER_NAME; - result.STRUCTURE_FILE = STRUCTURE_FILE; - result.INPUTROOT = INPUTROOT; - result.SOLVER_NAME = SOLVER_NAME; - result.weights = _weights; + result.OUTPUTROOT = OUTPUTROOT; + result.SLAVE_WEIGHT = SLAVE_WEIGHT; + result.MASTER_NAME = MASTER_NAME; + result.STRUCTURE_FILE = STRUCTURE_FILE; + result.INPUTROOT = INPUTROOT; + result.SOLVER_NAME = SOLVER_NAME; + result.weights = _weights; - return result; + return result; } -BendersBaseOptions SimulationOptions::get_benders_options() const -{ - BendersBaseOptions result(get_base_options()); +BendersBaseOptions SimulationOptions::get_benders_options() const { + BendersBaseOptions result(get_base_options()); - result.MAX_ITERATIONS = MAX_ITERATIONS; + result.MAX_ITERATIONS = MAX_ITERATIONS; - result.ABSOLUTE_GAP = ABSOLUTE_GAP; - result.RELATIVE_GAP = RELATIVE_GAP; - result.TIME_LIMIT = TIME_LIMIT; + result.ABSOLUTE_GAP = ABSOLUTE_GAP; + result.RELATIVE_GAP = RELATIVE_GAP; + result.TIME_LIMIT = TIME_LIMIT; - result.AGGREGATION = AGGREGATION; - result.TRACE = TRACE; - result.BOUND_ALPHA = BOUND_ALPHA; + result.AGGREGATION = AGGREGATION; + result.TRACE = TRACE; + result.BOUND_ALPHA = BOUND_ALPHA; - result.CSV_NAME = CSV_NAME; + result.CSV_NAME = CSV_NAME; - return result; + return result; } \ No newline at end of file diff --git a/src/cpp/benders/benders_core/SlaveCut.cpp b/src/cpp/benders/benders_core/SlaveCut.cpp index 0a06c26d1..5322a34fa 100644 --- a/src/cpp/benders/benders_core/SlaveCut.cpp +++ b/src/cpp/benders/benders_core/SlaveCut.cpp @@ -1,170 +1,157 @@ #include "SlaveCut.h" /*! -* \brief Constructor of a slave cut handler from slave cut data -* -* \param data : pointer to a slave cut data -*/ -SlaveCutDataHandler::SlaveCutDataHandler(SlaveCutDataPtr & data) :_data(data) { - //get_subgradient().clear(); - get_int().resize(SlaveCutInt::MAXINTEGER); - get_dbl().resize(SlaveCutDbl::MAXDBL); - get_str().resize(SlaveCutStr::MAXSTR); + * \brief Constructor of a slave cut handler from slave cut data + * + * \param data : pointer to a slave cut data + */ +SlaveCutDataHandler::SlaveCutDataHandler(SlaveCutDataPtr& data) : _data(data) { + // get_subgradient().clear(); + get_int().resize(SlaveCutInt::MAXINTEGER); + get_dbl().resize(SlaveCutDbl::MAXDBL); + get_str().resize(SlaveCutStr::MAXSTR); } -SlaveCutDataHandler::~SlaveCutDataHandler() { - -} +SlaveCutDataHandler::~SlaveCutDataHandler() {} /*! -* \brief Get subgradient of a slave cut -*/ -Point & SlaveCutDataHandler::get_subgradient() { - return _data->first.first.first; + * \brief Get subgradient of a slave cut + */ +Point& SlaveCutDataHandler::get_subgradient() { + return _data->first.first.first; } /*! -* \brief Get int variable of a slave cut -*/ -IntVector & SlaveCutDataHandler::get_int() { - return _data->first.first.second; -} + * \brief Get int variable of a slave cut + */ +IntVector& SlaveCutDataHandler::get_int() { return _data->first.first.second; } /*! -* \brief Get double variable of a slave cut -*/ -DblVector & SlaveCutDataHandler::get_dbl() { - return _data->first.second; -} + * \brief Get double variable of a slave cut + */ +DblVector& SlaveCutDataHandler::get_dbl() { return _data->first.second; } /*! -* \brief Get string variable of a slave cut -*/ -StrVector & SlaveCutDataHandler::get_str() { - return _data->second; -} + * \brief Get string variable of a slave cut + */ +StrVector& SlaveCutDataHandler::get_str() { return _data->second; } /*! -* \brief Get int variable of a slave cut (SIMPLEXITE, LPSTATUS) -*/ -int & SlaveCutDataHandler::get_int(SlaveCutInt key) { - return get_int()[key]; -} + * \brief Get int variable of a slave cut (SIMPLEXITE, LPSTATUS) + */ +int& SlaveCutDataHandler::get_int(SlaveCutInt key) { return get_int()[key]; } /*! -* \brief Get double variable of a slave cut (SLAVECOST, ALPHA_I, SLAVE_TIMER) -*/ -double & SlaveCutDataHandler::get_dbl(SlaveCutDbl key) { - return get_dbl()[key]; -} + * \brief Get double variable of a slave cut (SLAVECOST, ALPHA_I, SLAVE_TIMER) + */ +double& SlaveCutDataHandler::get_dbl(SlaveCutDbl key) { return get_dbl()[key]; } /*! -* \brief Get string variable of a slave cut -*/ -std::string & SlaveCutDataHandler::get_str(SlaveCutStr key) { - return get_str()[key]; + * \brief Get string variable of a slave cut + */ +std::string& SlaveCutDataHandler::get_str(SlaveCutStr key) { + return get_str()[key]; } /*! -* \brief Get subgradient of a slave cut -*/ -Point const & SlaveCutDataHandler::get_subgradient() const { - return _data->first.first.first; + * \brief Get subgradient of a slave cut + */ +Point const& SlaveCutDataHandler::get_subgradient() const { + return _data->first.first.first; } /*! -* \brief Get int variable of a slave cut -*/ -IntVector const & SlaveCutDataHandler::get_int() const { - return _data->first.first.second; + * \brief Get int variable of a slave cut + */ +IntVector const& SlaveCutDataHandler::get_int() const { + return _data->first.first.second; } /*! -* \brief Get double variable of a slave cut -*/ -DblVector const & SlaveCutDataHandler::get_dbl() const { - return _data->first.second; + * \brief Get double variable of a slave cut + */ +DblVector const& SlaveCutDataHandler::get_dbl() const { + return _data->first.second; } /*! -* \brief Get string variable of a slave cut -*/ -StrVector const & SlaveCutDataHandler::get_str() const { - return _data->second; -} + * \brief Get string variable of a slave cut + */ +StrVector const& SlaveCutDataHandler::get_str() const { return _data->second; } /*! -* \brief Get int variable of a slave cut (SIMPLEXITE, LPSTATUS) -*/ -int SlaveCutDataHandler::get_int(SlaveCutInt key)const { - return get_int()[key]; + * \brief Get int variable of a slave cut (SIMPLEXITE, LPSTATUS) + */ +int SlaveCutDataHandler::get_int(SlaveCutInt key) const { + return get_int()[key]; } /*! -* \brief Get double variable of a slave cut (SLAVECOST, ALPHA_I, SLAVE_TIMER) -*/ -double SlaveCutDataHandler::get_dbl(SlaveCutDbl key) const { - return get_dbl()[key]; + * \brief Get double variable of a slave cut (SLAVECOST, ALPHA_I, SLAVE_TIMER) + */ +double SlaveCutDataHandler::get_dbl(SlaveCutDbl key) const { + return get_dbl()[key]; } /*! -* \brief Get string variable of a slave cut -*/ -std::string const & SlaveCutDataHandler::get_str(SlaveCutStr key) const { - return get_str()[key]; + * \brief Get string variable of a slave cut + */ +std::string const& SlaveCutDataHandler::get_str(SlaveCutStr key) const { + return get_str()[key]; } /*! -* \brief Comparator overloading of slave cut trimmer -*/ -bool SlaveCutTrimmer::operator<(SlaveCutTrimmer const & other) const { - Predicate point_comp; - if (std::fabs(_const_cut - other._const_cut) < EPSILON_PREDICATE) { - return point_comp(_data_cut->get_subgradient(), other._data_cut->get_subgradient()); - } - else { - return (_const_cut < other._const_cut); - } + * \brief Comparator overloading of slave cut trimmer + */ +bool SlaveCutTrimmer::operator<(SlaveCutTrimmer const& other) const { + Predicate point_comp; + if (std::fabs(_const_cut - other._const_cut) < EPSILON_PREDICATE) { + return point_comp(_data_cut->get_subgradient(), + other._data_cut->get_subgradient()); + } else { + return (_const_cut < other._const_cut); + } } /*! -* \brief Constructor of Slave cut trimmer from an handler and trial values -*/ -SlaveCutTrimmer::SlaveCutTrimmer(SlaveCutDataHandlerPtr & data, Point & x0) : _data_cut(data), _x0(x0) { - _const_cut = _data_cut->get_dbl(SLAVE_COST); - for (auto const & kvp : _x0) { - if (get_subgradient().find(kvp.first) != get_subgradient().end()) { - _const_cut -= get_subgradient().find(kvp.first)->second * kvp.second; - } - } + * \brief Constructor of Slave cut trimmer from an handler and trial values + */ +SlaveCutTrimmer::SlaveCutTrimmer(SlaveCutDataHandlerPtr& data, Point& x0) + : _data_cut(data), _x0(x0) { + _const_cut = _data_cut->get_dbl(SLAVE_COST); + for (auto const& kvp : _x0) { + if (get_subgradient().find(kvp.first) != get_subgradient().end()) { + _const_cut -= get_subgradient().find(kvp.first)->second * kvp.second; + } + } } /*! -* \brief Get subgradient of a slave cut trimmer -*/ -Point const & SlaveCutTrimmer::get_subgradient() const { - return _data_cut->get_subgradient(); + * \brief Get subgradient of a slave cut trimmer + */ +Point const& SlaveCutTrimmer::get_subgradient() const { + return _data_cut->get_subgradient(); } /*! -* \brief Function to print a slave cut trimmer -* -* \param stream : output stream -*/ -void SlaveCutTrimmer::print(std::ostream & stream)const { - std::stringstream buffer; - buffer << _const_cut << get_subgradient(); - stream << buffer.str(); + * \brief Function to print a slave cut trimmer + * + * \param stream : output stream + */ +void SlaveCutTrimmer::print(std::ostream& stream) const { + std::stringstream buffer; + buffer << _const_cut << get_subgradient(); + stream << buffer.str(); } /*! -* \brief Function to print a slave cut handler -* -* \param stream : output stream -*/ -void SlaveCutDataHandler::print(std::ostream & stream)const { - std::stringstream buffer; - buffer << get_dbl(SLAVE_COST) << get_subgradient(); - stream << buffer.str(); - stream << " Simplexiter " << get_int(SIMPLEXITER) << " | "; + * \brief Function to print a slave cut handler + * + * \param stream : output stream + */ +void SlaveCutDataHandler::print(std::ostream& stream) const { + std::stringstream buffer; + buffer << get_dbl(SLAVE_COST) << get_subgradient(); + stream << buffer.str(); + stream << " Simplexiter " << get_int(SIMPLEXITER) << " | "; } diff --git a/src/cpp/benders/benders_core/Worker.cpp b/src/cpp/benders/benders_core/Worker.cpp index 01ef7b707..24f52e172 100644 --- a/src/cpp/benders/benders_core/Worker.cpp +++ b/src/cpp/benders/benders_core/Worker.cpp @@ -1,19 +1,17 @@ -#include "glog/logging.h" -#include "helpers/Path.h" #include "Worker.h" +#include "glog/logging.h" +#include "helpers/Path.h" #include "solver_utils.h" /*! * \brief Free the problem */ -void Worker::free() -{ - if (_solver) - { - _solver.reset(); - _solver = nullptr; - } +void Worker::free() { + if (_solver) { + _solver.reset(); + _solver = nullptr; + } } /*! @@ -21,52 +19,44 @@ void Worker::free() * * \param lb : double which receives the optimal value */ -void Worker::get_value(double &lb) const -{ - if (_is_master && _solver->get_n_integer_vars() > 0) - { - lb = _solver->get_mip_value(); - } - else - { - lb = _solver->get_lp_value(); - } +void Worker::get_value(double &lb) const { + if (_is_master && _solver->get_n_integer_vars() > 0) { + lb = _solver->get_mip_value(); + } else { + lb = _solver->get_lp_value(); + } } /*! * \brief Initialization of a problem * - * \param variable_map : map linking each problem name to its variables and their ids + * \param variable_map : map linking each problem name to its variables and + * their ids * * \param problem_name : name of the problem */ void Worker::init(Str2Int const &variable_map, std::string const &path_to_mps, - std::string const &solver_name, int log_level) -{ - _path_to_mps = path_to_mps; + std::string const &solver_name, int log_level) { + _path_to_mps = path_to_mps; - SolverFactory factory; - if (_is_master) - { - _solver = factory.create_solver(solver_name, SOLVER_TYPE::INTEGER); - } - else - { - _solver = factory.create_solver(solver_name, SOLVER_TYPE::CONTINUOUS); - } + SolverFactory factory; + if (_is_master) { + _solver = factory.create_solver(solver_name, SOLVER_TYPE::INTEGER); + } else { + _solver = factory.create_solver(solver_name, SOLVER_TYPE::CONTINUOUS); + } - _solver->init(); - _solver->set_threads(1); - _solver->set_output_log_level(log_level); - _solver->read_prob_mps(path_to_mps); + _solver->init(); + _solver->set_threads(1); + _solver->set_output_log_level(log_level); + _solver->read_prob_mps(path_to_mps); - int var_index; - for (auto const &kvp : variable_map) - { - var_index = _solver->get_col_index(kvp.first); - _id_to_name[var_index] = kvp.first; - _name_to_id[kvp.first] = var_index; - } + int var_index; + for (auto const &kvp : variable_map) { + var_index = _solver->get_col_index(kvp.first); + _id_to_name[var_index] = kvp.first; + _name_to_id[kvp.first] = var_index; + } } /*! @@ -74,41 +64,38 @@ void Worker::init(Str2Int const &variable_map, std::string const &path_to_mps, * * \param lp_status : problem status after optimization */ -void Worker::solve(int &lp_status, const std::string &outputroot) const -{ - - if (_is_master && _solver->get_n_integer_vars() > 0) - { - lp_status = _solver->solve_mip(); - } - else - { - lp_status = _solver->solve_lp(); - } +void Worker::solve(int &lp_status, const std::string &outputroot) const { + if (_is_master && _solver->get_n_integer_vars() > 0) { + lp_status = _solver->solve_mip(); + } else { + lp_status = _solver->solve_lp(); + } - if (lp_status != SOLVER_STATUS::OPTIMAL) - { - LOG(INFO) << "lp_status is : " << lp_status << std::endl; - std::stringstream buffer; - buffer << Path(outputroot) / (_path_to_mps + "_lp_status_") / (_solver->SOLVER_STRING_STATUS[lp_status] + MPS_SUFFIX); - LOG(INFO) << "lp_status is : " << _solver->SOLVER_STRING_STATUS[lp_status] << std::endl; - LOG(INFO) << "written in " << buffer.str() << std::endl; - _solver->write_prob_mps(buffer.str()); + if (lp_status != SOLVER_STATUS::OPTIMAL) { + LOG(INFO) << "lp_status is : " << lp_status << std::endl; + std::stringstream buffer; + buffer << Path(outputroot) / (_path_to_mps + "_lp_status_") / + (_solver->SOLVER_STRING_STATUS[lp_status] + MPS_SUFFIX); + LOG(INFO) << "lp_status is : " << _solver->SOLVER_STRING_STATUS[lp_status] + << std::endl; + LOG(INFO) << "written in " << buffer.str() << std::endl; + _solver->write_prob_mps(buffer.str()); - throw InvalidSolverStatusException("Invalid solver status " + _solver->SOLVER_STRING_STATUS[lp_status] + " optimality expected"); - } + throw InvalidSolverStatusException( + "Invalid solver status " + _solver->SOLVER_STRING_STATUS[lp_status] + + " optimality expected"); + } - if (_is_master) - { - _solver->write_prob_mps((Path(outputroot) / OUTPUT_MASTER_MPS_FILE_NAME).get_str()); - } + if (_is_master) { + _solver->write_prob_mps( + (Path(outputroot) / OUTPUT_MASTER_MPS_FILE_NAME).get_str()); + } } /*! * \brief Get the number of iteration needed to solve a problem * * \param result : result */ -void Worker::get_splex_num_of_ite_last(int &result) const -{ - result = _solver->get_splex_num_of_ite_last(); +void Worker::get_splex_num_of_ite_last(int &result) const { + result = _solver->get_splex_num_of_ite_last(); } diff --git a/src/cpp/benders/benders_core/WorkerMaster.cpp b/src/cpp/benders/benders_core/WorkerMaster.cpp index 57e79974c..d021819b8 100644 --- a/src/cpp/benders/benders_core/WorkerMaster.cpp +++ b/src/cpp/benders/benders_core/WorkerMaster.cpp @@ -1,18 +1,15 @@ -#include "glog/logging.h" - #include "WorkerMaster.h" +#include "glog/logging.h" #include "solver_utils.h" -WorkerMaster::WorkerMaster() -{ - _is_master = true; -} +WorkerMaster::WorkerMaster() { _is_master = true; } /*! * \brief Constructor of a Master Problem * - * Construct a Master Problem by loading mps and mapping files and adding the variable alpha + * Construct a Master Problem by loading mps and mapping files and adding the + * variable alpha * * \param variable_map : map linking each variable to its id in the problem * \param path_to_mps : path to the problem mps file @@ -20,50 +17,46 @@ WorkerMaster::WorkerMaster() * \param log_level : solver log level * \param nslaves : number of slaves */ -WorkerMaster::WorkerMaster(Str2Int const &variable_map, std::string const &path_to_mps, const std::string &solver_name, const int log_level, int nslaves) : Worker(), _nslaves(nslaves) -{ - _is_master = true; - init(variable_map, path_to_mps, solver_name, log_level); - - _set_upper_bounds(); - _add_alpha_var(); -} -WorkerMaster::~WorkerMaster() -{ +WorkerMaster::WorkerMaster(Str2Int const &variable_map, + std::string const &path_to_mps, + const std::string &solver_name, const int log_level, + int nslaves) + : Worker(), _nslaves(nslaves) { + _is_master = true; + init(variable_map, path_to_mps, solver_name, log_level); + + _set_upper_bounds(); + _add_alpha_var(); } +WorkerMaster::~WorkerMaster() {} /*! * \brief Return optimal variables of a problem * - * Set optimal variables of a problem which has the form (min(x,alpha) : f(x) + alpha) + * Set optimal variables of a problem which has the form (min(x,alpha) : f(x) + + * alpha) * * \param x0 : reference to an empty map list * * \param alpha : reference to an empty double */ -void WorkerMaster::get(Point &x0, double &alpha, DblVector &alpha_i) -{ - x0.clear(); - std::vector ptr(_solver->get_ncols()); - - if (_solver->get_n_integer_vars() > 0) - { - _solver->get_mip_sol(ptr.data()); - } - else - { - _solver->get_lp_sol(ptr.data(), NULL, NULL); - } - assert(_id_alpha_i.back() + 1 == ptr.size()); - for (auto const &kvp : _id_to_name) - { - x0[kvp.second] = ptr[kvp.first]; - } - alpha = ptr[_id_alpha]; - for (int i(0); i < _id_alpha_i.size(); ++i) - { - alpha_i[i] = ptr[_id_alpha_i[i]]; - } +void WorkerMaster::get(Point &x0, double &alpha, DblVector &alpha_i) { + x0.clear(); + std::vector ptr(_solver->get_ncols()); + + if (_solver->get_n_integer_vars() > 0) { + _solver->get_mip_sol(ptr.data()); + } else { + _solver->get_lp_sol(ptr.data(), NULL, NULL); + } + assert(_id_alpha_i.back() + 1 == ptr.size()); + for (auto const &kvp : _id_to_name) { + x0[kvp.second] = ptr[kvp.first]; + } + alpha = ptr[_id_alpha]; + for (int i(0); i < _id_alpha_i.size(); ++i) { + alpha_i[i] = ptr[_id_alpha_i[i]]; + } } /*! @@ -71,34 +64,28 @@ void WorkerMaster::get(Point &x0, double &alpha, DblVector &alpha_i) * * \param dual : reference to a vector of double */ -void WorkerMaster::get_dual_values(std::vector &dual) const -{ - dual.resize(get_number_constraint()); - solver_getlpdual(_solver, dual); +void WorkerMaster::get_dual_values(std::vector &dual) const { + dual.resize(get_number_constraint()); + solver_getlpdual(_solver, dual); } /*! * \brief Return number of constraint in a problem */ -int WorkerMaster::get_number_constraint() const -{ - return _solver->get_nrows(); -} +int WorkerMaster::get_number_constraint() const { return _solver->get_nrows(); } /*! * \brief Delete nrows last rows of a problem * * \param nrows : number of rows to delete */ -void WorkerMaster::delete_constraint(int const nrows) const -{ - std::vector mindex(nrows, 0); - int const nconstraint(get_number_constraint()); - for (int i(0); i < nrows; i++) - { - mindex[i] = nconstraint - nrows + i; - } - solver_deactivaterows(_solver, mindex); +void WorkerMaster::delete_constraint(int const nrows) const { + std::vector mindex(nrows, 0); + int const nconstraint(get_number_constraint()); + for (int i(0); i < nrows; i++) { + mindex[i] = nconstraint - nrows + i; + } + solver_deactivaterows(_solver, mindex); } /*! @@ -108,49 +95,47 @@ void WorkerMaster::delete_constraint(int const nrows) const * \param x0 : optimal Master variables * \param rhs : optimal slave value */ -void WorkerMaster::add_cut(Point const &s, Point const &x0, double const &rhs) const -{ - // cut is -rhs >= alpha + s^(x-x0) - int ncoeffs(1 + (int)s.size()); - std::vector rowtype(1, 'L'); - std::vector rowrhs(1, 0); - std::vector matval(ncoeffs, 1); - std::vector mstart = {0, ncoeffs}; - std::vector mclind(ncoeffs); - - define_rhs_with_master_variable(s, x0, rhs, rowrhs); - define_matval_mclind(s, matval, mclind); - - solver_addrows(_solver, rowtype, rowrhs, {}, mstart, mclind, matval); +void WorkerMaster::add_cut(Point const &s, Point const &x0, + double const &rhs) const { + // cut is -rhs >= alpha + s^(x-x0) + int ncoeffs(1 + (int)s.size()); + std::vector rowtype(1, 'L'); + std::vector rowrhs(1, 0); + std::vector matval(ncoeffs, 1); + std::vector mstart = {0, ncoeffs}; + std::vector mclind(ncoeffs); + + define_rhs_with_master_variable(s, x0, rhs, rowrhs); + define_matval_mclind(s, matval, mclind); + + solver_addrows(_solver, rowtype, rowrhs, {}, mstart, mclind, matval); } -void WorkerMaster::define_rhs_with_master_variable(const Point &s, const Point &x0, const double &rhs, - std::vector &rowrhs) const -{ - rowrhs.front() -= rhs; - for (auto const &kvp : _name_to_id) - { - if (s.find(kvp.first) != s.end()) - { - rowrhs.front() += (s.find(kvp.first)->second * x0.find(kvp.first)->second); - } - } +void WorkerMaster::define_rhs_with_master_variable( + const Point &s, const Point &x0, const double &rhs, + std::vector &rowrhs) const { + rowrhs.front() -= rhs; + for (auto const &kvp : _name_to_id) { + if (s.find(kvp.first) != s.end()) { + rowrhs.front() += + (s.find(kvp.first)->second * x0.find(kvp.first)->second); + } + } } -void WorkerMaster::define_matval_mclind(const Point &s, std::vector &matval, std::vector &mclind) const -{ - size_t mclindCnt_l(0); - for (auto const &kvp : _name_to_id) - { - if (s.find(kvp.first) != s.end()) - { - mclind[mclindCnt_l] = kvp.second; - matval[mclindCnt_l] = s.find(kvp.first)->second; - ++mclindCnt_l; - } - } - mclind.back() = _id_alpha; - matval.back() = -1; +void WorkerMaster::define_matval_mclind(const Point &s, + std::vector &matval, + std::vector &mclind) const { + size_t mclindCnt_l(0); + for (auto const &kvp : _name_to_id) { + if (s.find(kvp.first) != s.end()) { + mclind[mclindCnt_l] = kvp.second; + matval[mclindCnt_l] = s.find(kvp.first)->second; + ++mclindCnt_l; + } + } + mclind.back() = _id_alpha; + matval.back() = -1; } /*! @@ -160,25 +145,25 @@ void WorkerMaster::define_matval_mclind(const Point &s, std::vector &mat * \param sx0 : subgradient times x0 * \param rhs : optimal slave value */ -void WorkerMaster::add_dynamic_cut(Point const &s, double const &sx0, double const &rhs) const -{ - // cut is -rhs >= alpha + s^(x-x0) - int ncoeffs(1 + (int)s.size()); - std::vector rowtype(1, 'L'); - std::vector rowrhs(1, 0); - std::vector matval(ncoeffs, 1); - std::vector mstart = {0, ncoeffs}; - std::vector mclind(ncoeffs); - - define_rhs_from_sx0(sx0, rhs, rowrhs); - define_matval_mclind(s, matval, mclind); - solver_addrows(_solver, rowtype, rowrhs, {}, mstart, mclind, matval); +void WorkerMaster::add_dynamic_cut(Point const &s, double const &sx0, + double const &rhs) const { + // cut is -rhs >= alpha + s^(x-x0) + int ncoeffs(1 + (int)s.size()); + std::vector rowtype(1, 'L'); + std::vector rowrhs(1, 0); + std::vector matval(ncoeffs, 1); + std::vector mstart = {0, ncoeffs}; + std::vector mclind(ncoeffs); + + define_rhs_from_sx0(sx0, rhs, rowrhs); + define_matval_mclind(s, matval, mclind); + solver_addrows(_solver, rowtype, rowrhs, {}, mstart, mclind, matval); } -void WorkerMaster::define_rhs_from_sx0(const double &sx0, const double &rhs, std::vector &rowrhs) const -{ - rowrhs.front() -= rhs; - rowrhs.front() += sx0; +void WorkerMaster::define_rhs_from_sx0(const double &sx0, const double &rhs, + std::vector &rowrhs) const { + rowrhs.front() -= rhs; + rowrhs.front() += sx0; } /*! @@ -189,37 +174,35 @@ void WorkerMaster::define_rhs_from_sx0(const double &sx0, const double &rhs, std * \param sx0 : subgradient times x0 * \param rhs : optimal slave value */ -void WorkerMaster::add_cut_by_iter(int const i, Point const &s, double const &sx0, double const &rhs) const -{ - // cut is -rhs >= alpha + s^(x-x0) - int ncoeffs(1 + (int)s.size()); - std::vector rowtype(1, 'L'); - std::vector rowrhs(1, 0); - std::vector matval(ncoeffs, 1); - std::vector mstart = {0, ncoeffs}; - std::vector mclind(ncoeffs); - - define_rhs_from_sx0(sx0, rhs, rowrhs); - define_matval_mclind_for_index(i, s, matval, mclind); - - solver_addrows(_solver, rowtype, rowrhs, {}, mstart, mclind, matval); +void WorkerMaster::add_cut_by_iter(int const i, Point const &s, + double const &sx0, double const &rhs) const { + // cut is -rhs >= alpha + s^(x-x0) + int ncoeffs(1 + (int)s.size()); + std::vector rowtype(1, 'L'); + std::vector rowrhs(1, 0); + std::vector matval(ncoeffs, 1); + std::vector mstart = {0, ncoeffs}; + std::vector mclind(ncoeffs); + + define_rhs_from_sx0(sx0, rhs, rowrhs); + define_matval_mclind_for_index(i, s, matval, mclind); + + solver_addrows(_solver, rowtype, rowrhs, {}, mstart, mclind, matval); } -void WorkerMaster::define_matval_mclind_for_index(const int i, const Point &s, std::vector &matval, - std::vector &mclind) const -{ - size_t mclindCnt_l(0); - for (auto const &kvp : _name_to_id) - { - if (s.find(kvp.first) != s.end()) - { - mclind[mclindCnt_l] = kvp.second; - matval[mclindCnt_l] = s.find(kvp.first)->second; - ++mclindCnt_l; - } - } - mclind.back() = _id_alpha_i[i]; - matval.back() = -1; +void WorkerMaster::define_matval_mclind_for_index( + const int i, const Point &s, std::vector &matval, + std::vector &mclind) const { + size_t mclindCnt_l(0); + for (auto const &kvp : _name_to_id) { + if (s.find(kvp.first) != s.end()) { + mclind[mclindCnt_l] = kvp.second; + matval[mclindCnt_l] = s.find(kvp.first)->second; + ++mclindCnt_l; + } + } + mclind.back() = _id_alpha_i[i]; + matval.back() = -1; } /*! @@ -230,84 +213,83 @@ void WorkerMaster::define_matval_mclind_for_index(const int i, const Point &s, s * \param x0 : optimal Master variables * \param rhs : optimal slave value */ -void WorkerMaster::add_cut_slave(int i, Point const &s, Point const &x0, double const &rhs) const -{ - // cut is -rhs >= alpha + s^(x-x0) - int ncoeffs(1 + (int)s.size()); - std::vector rowtype(1, 'L'); - std::vector rowrhs(1, 0); - std::vector matval(ncoeffs, 1); - std::vector mstart = {0, ncoeffs}; - std::vector mclind(ncoeffs); - - define_rhs_with_master_variable(s, x0, rhs, rowrhs); - define_matval_mclind_for_index(i, s, matval, mclind); - - solver_addrows(_solver, rowtype, rowrhs, {}, mstart, mclind, matval); +void WorkerMaster::add_cut_slave(int i, Point const &s, Point const &x0, + double const &rhs) const { + // cut is -rhs >= alpha + s^(x-x0) + int ncoeffs(1 + (int)s.size()); + std::vector rowtype(1, 'L'); + std::vector rowrhs(1, 0); + std::vector matval(ncoeffs, 1); + std::vector mstart = {0, ncoeffs}; + std::vector mclind(ncoeffs); + + define_rhs_with_master_variable(s, x0, rhs, rowrhs); + define_matval_mclind_for_index(i, s, matval, mclind); + + solver_addrows(_solver, rowtype, rowrhs, {}, mstart, mclind, matval); } -void WorkerMaster::_set_upper_bounds() const -{ - // Cbc solver sets infinite upper bounds to DBL_MAX = 1.79769e+308 which is way too large - // as it appears in datas.max_invest. We set it to 1e20 - int ncols = _solver->get_ncols(); - DblVector bounds(ncols); - _solver->get_ub(bounds.data(), 0, ncols - 1); - CharVector bndTypes(ncols, 'U'); - IntVector indices(ncols); - for (int i = 0; i < _solver->get_ncols(); i++) - { - indices[i] = i; - bounds[i] = std::min(bounds[i], 1e20); - } - _solver->chg_bounds(indices, bndTypes, bounds); +void WorkerMaster::_set_upper_bounds() const { + // Cbc solver sets infinite upper bounds to DBL_MAX = 1.79769e+308 which is + // way too large as it appears in datas.max_invest. We set it to 1e20 + int ncols = _solver->get_ncols(); + DblVector bounds(ncols); + _solver->get_ub(bounds.data(), 0, ncols - 1); + CharVector bndTypes(ncols, 'U'); + IntVector indices(ncols); + for (int i = 0; i < _solver->get_ncols(); i++) { + indices[i] = i; + bounds[i] = std::min(bounds[i], 1e20); + } + _solver->chg_bounds(indices, bndTypes, bounds); } -void WorkerMaster::_add_alpha_var() -{ - // add the variable alpha - auto const it(_name_to_id.find("alpha")); - if (it == _name_to_id.end()) - { - double lb(-1e10); /*!< Lower Bound */ - double ub(+1e20); /*!< Upper Bound*/ - double obj(+1); - std::vector start(2, 0); - _id_alpha = _solver->get_ncols(); /* Set the number of columns in _id_alpha */ - - solver_addcols(_solver, DblVector(1, obj), IntVector(1, 0), IntVector(0, 0), DblVector(0, 0.0), - DblVector(1, lb), DblVector(1, ub), CharVector(1, 'C'), StrVector(1, "alpha")); /* Add variable alpha and its parameters */ - - _id_alpha_i.resize(_nslaves, -1); - for (int i(0); i < _nslaves; ++i) - { - std::stringstream buffer; - buffer << "alpha_" << i; - _id_alpha_i[i] = _solver->get_ncols(); - solver_addcols(_solver, DblVector(1, 0.0), IntVector(1, 0), IntVector(0, 0), DblVector(0, 0.0), - DblVector(1, lb), DblVector(1, ub), CharVector(1, 'C'), - StrVector(1, buffer.str())); /* Add variable alpha_i and its parameters */ - } - - std::vector rowtype = {'E'}; - std::vector rowrhs = {0}; - std::vector mstart = {0, _nslaves + 1}; - std::vector matval(_nslaves + 1, 0); - std::vector mclind(_nslaves + 1); - mclind[0] = _id_alpha; - matval[0] = 1; - for (int i(0); i < _nslaves; ++i) - { - mclind[i + 1] = _id_alpha_i[i]; - matval[i + 1] = -1; - } - - solver_addrows(_solver, rowtype, rowrhs, {}, mstart, mclind, matval); - } - else - { - LOG(INFO) << "ERROR a variable named alpha is in input" << std::endl; - } +void WorkerMaster::_add_alpha_var() { + // add the variable alpha + auto const it(_name_to_id.find("alpha")); + if (it == _name_to_id.end()) { + double lb(-1e10); /*!< Lower Bound */ + double ub(+1e20); /*!< Upper Bound*/ + double obj(+1); + std::vector start(2, 0); + _id_alpha = + _solver->get_ncols(); /* Set the number of columns in _id_alpha */ + + solver_addcols( + _solver, DblVector(1, obj), IntVector(1, 0), IntVector(0, 0), + DblVector(0, 0.0), DblVector(1, lb), DblVector(1, ub), + CharVector(1, 'C'), + StrVector(1, "alpha")); /* Add variable alpha and its parameters */ + + _id_alpha_i.resize(_nslaves, -1); + for (int i(0); i < _nslaves; ++i) { + std::stringstream buffer; + buffer << "alpha_" << i; + _id_alpha_i[i] = _solver->get_ncols(); + solver_addcols( + _solver, DblVector(1, 0.0), IntVector(1, 0), IntVector(0, 0), + DblVector(0, 0.0), DblVector(1, lb), DblVector(1, ub), + CharVector(1, 'C'), + StrVector( + 1, buffer.str())); /* Add variable alpha_i and its parameters */ + } + + std::vector rowtype = {'E'}; + std::vector rowrhs = {0}; + std::vector mstart = {0, _nslaves + 1}; + std::vector matval(_nslaves + 1, 0); + std::vector mclind(_nslaves + 1); + mclind[0] = _id_alpha; + matval[0] = 1; + for (int i(0); i < _nslaves; ++i) { + mclind[i + 1] = _id_alpha_i[i]; + matval[i + 1] = -1; + } + + solver_addrows(_solver, rowtype, rowrhs, {}, mstart, mclind, matval); + } else { + LOG(INFO) << "ERROR a variable named alpha is in input" << std::endl; + } } /*! @@ -315,10 +297,9 @@ void WorkerMaster::_add_alpha_var() * * \param bestUB : bound to fix */ -void WorkerMaster::fix_alpha(double const &bestUB) const -{ - std::vector mindex(1, _id_alpha); - std::vector bnd_types(1, 'U'); - std::vector bnd_values(1, bestUB); - _solver->chg_bounds(mindex, bnd_types, bnd_values); +void WorkerMaster::fix_alpha(double const &bestUB) const { + std::vector mindex(1, _id_alpha); + std::vector bnd_types(1, 'U'); + std::vector bnd_values(1, bestUB); + _solver->chg_bounds(mindex, bnd_types, bnd_values); } diff --git a/src/cpp/benders/benders_core/WorkerSlave.cpp b/src/cpp/benders/benders_core/WorkerSlave.cpp index b22fb322d..b034b8594 100644 --- a/src/cpp/benders/benders_core/WorkerSlave.cpp +++ b/src/cpp/benders/benders_core/WorkerSlave.cpp @@ -10,24 +10,23 @@ * \param problem_name : Name of the problem * */ -WorkerSlave::WorkerSlave(Str2Int const &variable_map, std::string const &path_to_mps, double const &slave_weight, const std::string &solver_name, const int log_level) -{ +WorkerSlave::WorkerSlave(Str2Int const &variable_map, + std::string const &path_to_mps, + double const &slave_weight, + const std::string &solver_name, const int log_level) { + init(variable_map, path_to_mps, solver_name, log_level); - init(variable_map, path_to_mps, solver_name, log_level); - - int mps_ncols(_solver->get_ncols()); - DblVector obj_func_coeffs(mps_ncols); - IntVector sequence(mps_ncols); - for (int i = 0; i < mps_ncols; ++i) - { - sequence[i] = i; - } - solver_get_obj_func_coeffs(_solver, obj_func_coeffs, 0, mps_ncols - 1); - for (auto &c : obj_func_coeffs) - { - c *= slave_weight; - } - _solver->chg_obj(sequence, obj_func_coeffs); + int mps_ncols(_solver->get_ncols()); + DblVector obj_func_coeffs(mps_ncols); + IntVector sequence(mps_ncols); + for (int i = 0; i < mps_ncols; ++i) { + sequence[i] = i; + } + solver_get_obj_func_coeffs(_solver, obj_func_coeffs, 0, mps_ncols - 1); + for (auto &c : obj_func_coeffs) { + c *= slave_weight; + } + _solver->chg_obj(sequence, obj_func_coeffs); } /*! @@ -37,22 +36,20 @@ WorkerSlave::WorkerSlave(Str2Int const &variable_map, std::string const &path_to * * \param x0 : Set of variables to fix */ -void WorkerSlave::fix_to(Point const &x0) const -{ - int nbnds((int)_name_to_id.size()); - std::vector indexes(nbnds); - std::vector bndtypes(nbnds, 'B'); - std::vector values(nbnds); +void WorkerSlave::fix_to(Point const &x0) const { + int nbnds((int)_name_to_id.size()); + std::vector indexes(nbnds); + std::vector bndtypes(nbnds, 'B'); + std::vector values(nbnds); - int i(0); - for (auto const &kvp : _id_to_name) - { - indexes[i] = kvp.first; - values[i] = x0.find(kvp.second)->second; - ++i; - } + int i(0); + for (auto const &kvp : _id_to_name) { + indexes[i] = kvp.first; + values[i] = x0.find(kvp.second)->second; + ++i; + } - solver_chgbounds(_solver, indexes, bndtypes, values); + solver_chgbounds(_solver, indexes, bndtypes, values); } /*! @@ -60,15 +57,13 @@ void WorkerSlave::fix_to(Point const &x0) const * * \param s : Empty point which receives the solution */ -void WorkerSlave::get_subgradient(Point &s) const -{ - s.clear(); - std::vector ptr(_solver->get_ncols()); - solver_getlpreducedcost(_solver, ptr); - for (auto const &kvp : _id_to_name) - { - s[kvp.second] = +ptr[kvp.first]; - } +void WorkerSlave::get_subgradient(Point &s) const { + s.clear(); + std::vector ptr(_solver->get_ncols()); + solver_getlpreducedcost(_solver, ptr); + for (auto const &kvp : _id_to_name) { + s[kvp.second] = +ptr[kvp.first]; + } } /*! @@ -76,10 +71,9 @@ void WorkerSlave::get_subgradient(Point &s) const * * Method to store simplex basis of a problem, and build the distance matrix */ -SimplexBasis WorkerSlave::get_basis() const -{ - IntVector cstatus(_solver->get_ncols()); - IntVector rstatus(_solver->get_nrows()); - solver_getbasis(_solver, rstatus, cstatus); - return std::make_pair(rstatus, cstatus); +SimplexBasis WorkerSlave::get_basis() const { + IntVector cstatus(_solver->get_ncols()); + IntVector rstatus(_solver->get_nrows()); + solver_getbasis(_solver, rstatus, cstatus); + return std::make_pair(rstatus, cstatus); } diff --git a/src/cpp/benders/benders_core/WorkerTrace.cpp b/src/cpp/benders/benders_core/WorkerTrace.cpp index 827a3e552..c6b8fb9ff 100644 --- a/src/cpp/benders/benders_core/WorkerTrace.cpp +++ b/src/cpp/benders/benders_core/WorkerTrace.cpp @@ -1,41 +1,32 @@ #include "WorkerTrace.h" /*! -* \brief Get point -*/ -Point WorkerMasterData::get_point() const{ - return *_x0; + * \brief Get point + */ +Point WorkerMasterData::get_point() const { return *_x0; } + +Point WorkerMasterData::get_min_invest() const { return *_min_invest; } + +Point WorkerMasterData::get_max_invest() const { return *_max_invest; } + +LogData defineLogDataFromBendersDataAndTrace(const BendersData& data, + const BendersTrace& trace) { + LogData result; + + result.it = data.it; + result.best_it = data.best_it; + result.lb = data.lb; + result.best_ub = data.best_ub; + result.x0 = data.bestx; + size_t bestItIndex_l = data.best_it - 1; + + if (bestItIndex_l < trace.size()) { + const WorkerMasterDataPtr& bestItTrace = trace[bestItIndex_l]; + result.slave_cost = bestItTrace->_operational_cost; + result.invest_cost = bestItTrace->_invest_cost; + result.min_invest = bestItTrace->get_min_invest(); + result.max_invest = bestItTrace->get_max_invest(); + } + + return result; } - -Point WorkerMasterData::get_min_invest() const{ - return *_min_invest; -} - -Point WorkerMasterData::get_max_invest() const{ - return *_max_invest; -} - -LogData defineLogDataFromBendersDataAndTrace(const BendersData& data, const BendersTrace& trace){ - - LogData result; - - result.it = data.it; - result.best_it = data.best_it; - result.lb = data.lb; - result.best_ub = data.best_ub; - result.x0 = data.bestx; - size_t bestItIndex_l = data.best_it - 1; - - if (bestItIndex_l < trace.size()) - { - const WorkerMasterDataPtr& bestItTrace = trace[bestItIndex_l]; - result.slave_cost = bestItTrace->_operational_cost; - result.invest_cost = bestItTrace->_invest_cost; - result.min_invest = bestItTrace->get_min_invest(); - result.max_invest = bestItTrace->get_max_invest(); - } - - return result; -} - - diff --git a/src/cpp/benders/benders_core/common.cpp b/src/cpp/benders/benders_core/common.cpp index e92eb6131..b0fed7df2 100644 --- a/src/cpp/benders/benders_core/common.cpp +++ b/src/cpp/benders/benders_core/common.cpp @@ -7,30 +7,28 @@ * * \param x1 : second point */ -double norm_point(Point const &x0, Point const &x1) -{ - double result(0); - for (auto &kvp : x0) - { - result += (x0.find(kvp.first)->second - x1.find(kvp.first)->second) * (x0.find(kvp.first)->second - x1.find(kvp.first)->second); - } - result = std::sqrt(result); - return result; +double norm_point(Point const &x0, Point const &x1) { + double result(0); + for (auto &kvp : x0) { + result += (x0.find(kvp.first)->second - x1.find(kvp.first)->second) * + (x0.find(kvp.first)->second - x1.find(kvp.first)->second); + } + result = std::sqrt(result); + return result; } -LogData bendersDataToLogData(const BendersData &data) -{ - LogData result; - result.lb = data.lb; - result.best_ub = data.best_ub; - result.it = data.it; - result.best_it = data.best_it; - result.slave_cost = data.slave_cost; - result.invest_cost = data.invest_cost; - result.x0 = data.x0; - result.min_invest = data.min_invest; - result.max_invest = data.max_invest; - return result; +LogData bendersDataToLogData(const BendersData &data) { + LogData result; + result.lb = data.lb; + result.best_ub = data.best_ub; + result.it = data.it; + result.best_it = data.best_it; + result.slave_cost = data.slave_cost; + result.invest_cost = data.invest_cost; + result.x0 = data.x0; + result.min_invest = data.min_invest; + result.max_invest = data.max_invest; + return result; } /*! @@ -38,19 +36,18 @@ LogData bendersDataToLogData(const BendersData &data) * * \param argc : number of arguments in command line */ -void usage(int argc) -{ - if (argc < 2) - { - std::cerr << "Error: usage is : " << std::endl; - std::exit(1); - } +void usage(int argc) { + if (argc < 2) { + std::cerr << "Error: usage is : " << std::endl; + std::exit(1); + } } /*! * \brief Build the input from the structure file * - * Function to build the map linking each problem name to its variables and their id + * Function to build the map linking each problem name to its variables and + *their id * * \param root : root of the structure file * @@ -58,48 +55,44 @@ void usage(int argc) * * \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. + * \note The id in the coupling_map is that of the variable in the solver + *responsible for the creation of the structure file. */ -CouplingMap build_input(const std::string &structure_path, const int slave_number, const std::string &master_name) -{ - CouplingMap coupling_map; - std::ifstream summary(structure_path, std::ios::in); - if (!summary) - { - std::cout << "Cannot open file summary " << structure_path << std::endl; - return coupling_map; - } - std::string line; +CouplingMap build_input(const std::string &structure_path, + const int slave_number, + const std::string &master_name) { + CouplingMap coupling_map; + std::ifstream summary(structure_path, std::ios::in); + if (!summary) { + std::cout << "Cannot open file summary " << structure_path << std::endl; + return coupling_map; + } + std::string line; - while (std::getline(summary, line)) - { - std::stringstream buffer(line); - std::string problem_name; - std::string variable_name; - int variable_id; - buffer >> problem_name; - buffer >> variable_name; - buffer >> variable_id; - coupling_map[problem_name][variable_name] = variable_id; - } + while (std::getline(summary, line)) { + std::stringstream buffer(line); + std::string problem_name; + std::string variable_name; + int variable_id; + buffer >> problem_name; + buffer >> variable_name; + buffer >> variable_id; + coupling_map[problem_name][variable_name] = variable_id; + } - if (slave_number >= 0) - { - int n(0); - CouplingMap trimmer; - for (auto const &problem : coupling_map) - { - if (problem.first == master_name) - trimmer.insert(problem); - else if (n < slave_number) - { - trimmer.insert(problem); - ++n; - } - } - coupling_map = trimmer; + if (slave_number >= 0) { + int n(0); + CouplingMap trimmer; + for (auto const &problem : coupling_map) { + if (problem.first == master_name) + trimmer.insert(problem); + else if (n < slave_number) { + trimmer.insert(problem); + ++n; + } } - summary.close(); - return coupling_map; + coupling_map = trimmer; + } + summary.close(); + return coupling_map; } diff --git a/src/cpp/benders/benders_core/include/BendersBase.h b/src/cpp/benders/benders_core/include/BendersBase.h index 9c65e0453..a5f28b0a0 100644 --- a/src/cpp/benders/benders_core/include/BendersBase.h +++ b/src/cpp/benders/benders_core/include/BendersBase.h @@ -1,83 +1,86 @@ #pragma once -#include "common.h" +#include "OutputWriter.h" +#include "SimulationOptions.h" #include "SlaveCut.h" #include "Worker.h" -#include "WorkerSlave.h" #include "WorkerMaster.h" +#include "WorkerSlave.h" #include "WorkerTrace.h" -#include "SimulationOptions.h" +#include "common.h" #include "core/ILogger.h" -#include "OutputWriter.h" - -class BendersBase -{ -public: - virtual ~BendersBase() = default; - BendersBase(BendersBaseOptions const &options, Logger &logger, Writer writer); +class BendersBase { + public: + virtual ~BendersBase() = default; + BendersBase(BendersBaseOptions const &options, Logger &logger, Writer writer); - WorkerMasterPtr _master; - SlavesMapPtr _map_slaves; + WorkerMasterPtr _master; + SlavesMapPtr _map_slaves; - Str2Int _problem_to_id; - BendersData _data; - BendersBaseOptions _options; - StrVector _slaves; + Str2Int _problem_to_id; + BendersData _data; + BendersBaseOptions _options; + StrVector _slaves; - AllCutStorage _all_cuts_storage; - BendersTrace _trace; + AllCutStorage _all_cuts_storage; + BendersTrace _trace; - Logger _logger; - Writer _writer; + Logger _logger; + Writer _writer; - virtual void launch() = 0; + virtual void launch() = 0; -protected: - virtual void free() = 0; - virtual void run() = 0; + protected: + virtual void free() = 0; + virtual void run() = 0; - // map linking each problem name to its variables and their ids - CouplingMap _input; - int _nbWeeks = 0; + // map linking each problem name to its variables and their ids + CouplingMap _input; + int _nbWeeks = 0; -public: - void init_data(); + public: + void init_data(); - void print_csv(); - void print_csv_iteration(std::ostream &file, int ite); - void print_master_and_cut(std::ostream &file, int ite, WorkerMasterDataPtr &trace, Point const &xopt); - void print_master_csv(std::ostream &stream, const WorkerMasterDataPtr &trace, Point const &xopt) const; - void print_cut_csv(std::ostream &stream, SlaveCutDataHandler const &handler, std::string const &name, int const islaves) const; + void print_csv(); + void print_csv_iteration(std::ostream &file, int ite); + void print_master_and_cut(std::ostream &file, int ite, + WorkerMasterDataPtr &trace, Point const &xopt); + void print_master_csv(std::ostream &stream, const WorkerMasterDataPtr &trace, + Point const &xopt) const; + void print_cut_csv(std::ostream &stream, SlaveCutDataHandler const &handler, + std::string const &name, int const islaves) const; - void update_best_ub(); - void bound_simplex_iter(int simplexiter); - bool stopping_criterion(); - void update_trace(); - void check_status(AllCutPackage const &all_package) const; + void update_best_ub(); + void bound_simplex_iter(int simplexiter); + bool stopping_criterion(); + void update_trace(); + void check_status(AllCutPackage const &all_package) const; - void get_master_value(); - void get_slave_cut(SlaveCutPackage &slave_cut_package); + void get_master_value(); + void get_slave_cut(SlaveCutPackage &slave_cut_package); - LogData build_log_data_from_data() const; - void post_run_actions() const; - Output::IterationsData output_data() const; - Output::Iteration iteration(const WorkerMasterDataPtr &masterDataPtr_l) const; - Output::CandidatesVec candidates_data(const WorkerMasterDataPtr &masterDataPtr_l) const; - Output::SolutionData solution() const; - std::string status_from_criterion() const; + LogData build_log_data_from_data() const; + void post_run_actions() const; + Output::IterationsData output_data() const; + Output::Iteration iteration(const WorkerMasterDataPtr &masterDataPtr_l) const; + Output::CandidatesVec candidates_data( + const WorkerMasterDataPtr &masterDataPtr_l) const; + Output::SolutionData solution() const; + std::string status_from_criterion() const; - void compute_cut_val(const SlaveCutDataHandlerPtr &handler, const Point &x0, Point &s) const; + void compute_cut_val(const SlaveCutDataHandlerPtr &handler, const Point &x0, + Point &s) const; - void compute_cut_aggregate(const AllCutPackage &all_package); + void compute_cut_aggregate(const AllCutPackage &all_package); - void compute_cut(const AllCutPackage &all_package); + void compute_cut(const AllCutPackage &all_package); - void build_cut_full(const AllCutPackage &all_package); + void build_cut_full(const AllCutPackage &all_package); - std::string get_slave_path(std::string const &slave_name) const; - double slave_weight(int nslaves, std::string const &name) const; - std::string get_master_path() const; - std::string get_structure_path() const; + std::string get_slave_path(std::string const &slave_name) const; + double slave_weight(int nslaves, std::string const &name) const; + std::string get_master_path() const; + std::string get_structure_path() const; }; using pBendersBase = std::shared_ptr; \ No newline at end of file diff --git a/src/cpp/benders/benders_core/include/SimplexBasis.h b/src/cpp/benders/benders_core/include/SimplexBasis.h index c1d41f873..f8988fa44 100644 --- a/src/cpp/benders/benders_core/include/SimplexBasis.h +++ b/src/cpp/benders/benders_core/include/SimplexBasis.h @@ -1,7 +1,7 @@ #pragma once -#include "common.h" #include "Worker.h" +#include "common.h" typedef std::pair SimplexBasis; typedef std::map SimplexBasisPackage; @@ -10,29 +10,25 @@ typedef std::vector AllBasisPackage; typedef std::shared_ptr SimplexBasisPtr; class SimplexBasisHandler { -public: - - IntVector & get_col(); - IntVector & get_row(); + public: + IntVector &get_col(); + IntVector &get_row(); - IntVector const & get_col()const; - IntVector const & get_row()const; + IntVector const &get_col() const; + IntVector const &get_row() const; -public: + public: + SimplexBasisHandler(); + explicit SimplexBasisHandler(SimplexBasisPtr const &data); + explicit SimplexBasisHandler(SimplexBasisPtr &data); + virtual ~SimplexBasisHandler(); - SimplexBasisHandler(); - explicit SimplexBasisHandler(SimplexBasisPtr const &data); - explicit SimplexBasisHandler(SimplexBasisPtr & data); - virtual ~SimplexBasisHandler(); + bool operator<(SimplexBasisHandler const &other) const; - bool operator<(SimplexBasisHandler const & other)const; - - SimplexBasisPtr _data; - void print(std::ostream & stream)const; + SimplexBasisPtr _data; + void print(std::ostream &stream) const; }; -std::ostream & operator<<(std::ostream & stream, SimplexBasisHandler const & rhs); +std::ostream &operator<<(std::ostream &stream, SimplexBasisHandler const &rhs); typedef std::set SimplexBasisStorage; - - diff --git a/src/cpp/benders/benders_core/include/SimulationOptions.h b/src/cpp/benders/benders_core/include/SimulationOptions.h index 022ec3feb..bed8328cf 100644 --- a/src/cpp/benders/benders_core/include/SimulationOptions.h +++ b/src/cpp/benders/benders_core/include/SimulationOptions.h @@ -2,24 +2,23 @@ #include "common.h" -class SimulationOptions -{ -public: +class SimulationOptions { + public: #define BENDERS_OPTIONS_MACRO(name__, type__, default__) type__ name__; #include "SimulationOptions.hxx" #undef BENDERS_OPTIONS_MACRO - SimulationOptions(); - explicit SimulationOptions(const std::string &options_filename); + SimulationOptions(); + explicit SimulationOptions(const std::string &options_filename); - void read(std::string const &file_name); - void print(std::ostream &stream) const; - BendersBaseOptions get_benders_options() const; - BaseOptions get_base_options() const; + void read(std::string const &file_name); + void print(std::ostream &stream) const; + BendersBaseOptions get_benders_options() const; + BaseOptions get_base_options() const; - void write_default() const; - Str2Dbl _weights; + void write_default() const; + Str2Dbl _weights; -private: - void set_weights(); + private: + void set_weights(); }; diff --git a/src/cpp/benders/benders_core/include/SimulationOptions.hxx b/src/cpp/benders/benders_core/include/SimulationOptions.hxx index 21ba8f1f9..1c23eb20e 100644 --- a/src/cpp/benders/benders_core/include/SimulationOptions.hxx +++ b/src/cpp/benders/benders_core/include/SimulationOptions.hxx @@ -19,7 +19,8 @@ BENDERS_OPTIONS_MACRO(OUTPUTROOT, std::string, ".") // True if a trace should be built, false otherwise BENDERS_OPTIONS_MACRO(TRACE, bool, true) -// UNIFORM (1/n), CONSTANT (to set in SLAVE_WEIGHT_VALUE), or a txt file linking each slave to its weight +// UNIFORM (1/n), CONSTANT (to set in SLAVE_WEIGHT_VALUE), or a txt file linking +// each slave to its weight BENDERS_OPTIONS_MACRO(SLAVE_WEIGHT, std::string, "CONSTANT") // If SLAVE_WEIGHT is CONSTANT, set here the divisor required diff --git a/src/cpp/benders/benders_core/include/SlaveCut.h b/src/cpp/benders/benders_core/include/SlaveCut.h index c36ff24b2..aa7827aee 100644 --- a/src/cpp/benders/benders_core/include/SlaveCut.h +++ b/src/cpp/benders/benders_core/include/SlaveCut.h @@ -1,7 +1,7 @@ #pragma once -#include "common.h" #include "Worker.h" +#include "common.h" typedef std::pair SlaveCutData1; typedef std::pair SlaveCutData2; @@ -26,69 +26,55 @@ typedef std::set SlaveCutDataHandlerPtrSet; void build_SlaveCutData(SlaveCutData &); -enum SlaveCutInt { - SIMPLEXITER = 0, - LPSTATUS, - MAXINTEGER -}; +enum SlaveCutInt { SIMPLEXITER = 0, LPSTATUS, MAXINTEGER }; -enum SlaveCutDbl { - SLAVE_COST = 0, - ALPHA_I, - SLAVE_TIMER, - MAXDBL -}; +enum SlaveCutDbl { SLAVE_COST = 0, ALPHA_I, SLAVE_TIMER, MAXDBL }; -enum SlaveCutStr { - MAXSTR = 0 -}; +enum SlaveCutStr { MAXSTR = 0 }; class SlaveCutDataHandler { -public: - - Point & get_subgradient(); - IntVector & get_int(); - DblVector & get_dbl(); - StrVector & get_str(); - - int & get_int(SlaveCutInt); - double & get_dbl(SlaveCutDbl); - std::string & get_str(SlaveCutStr); - - int get_int(SlaveCutInt)const; - double get_dbl(SlaveCutDbl)const; - std::string const & get_str(SlaveCutStr)const; - - Point const & get_subgradient()const; - IntVector const & get_int()const; - DblVector const & get_dbl()const; - StrVector const & get_str()const; - void print(std::ostream & stream)const; - -public: - - explicit SlaveCutDataHandler(SlaveCutDataPtr const &data); - explicit SlaveCutDataHandler(SlaveCutDataPtr & data); - virtual ~SlaveCutDataHandler(); - - SlaveCutDataPtr _data; + public: + Point &get_subgradient(); + IntVector &get_int(); + DblVector &get_dbl(); + StrVector &get_str(); + + int &get_int(SlaveCutInt); + double &get_dbl(SlaveCutDbl); + std::string &get_str(SlaveCutStr); + + int get_int(SlaveCutInt) const; + double get_dbl(SlaveCutDbl) const; + std::string const &get_str(SlaveCutStr) const; + + Point const &get_subgradient() const; + IntVector const &get_int() const; + DblVector const &get_dbl() const; + StrVector const &get_str() const; + void print(std::ostream &stream) const; + + public: + explicit SlaveCutDataHandler(SlaveCutDataPtr const &data); + explicit SlaveCutDataHandler(SlaveCutDataPtr &data); + virtual ~SlaveCutDataHandler(); + + SlaveCutDataPtr _data; }; class SlaveCutTrimmer { -public: - SlaveCutDataHandlerPtr _data_cut; - Point _x0; - double _const_cut; + public: + SlaveCutDataHandlerPtr _data_cut; + Point _x0; + double _const_cut; - SlaveCutTrimmer(SlaveCutDataHandlerPtr & data, Point & x0); - Point const & get_subgradient()const; + SlaveCutTrimmer(SlaveCutDataHandlerPtr &data, Point &x0); + Point const &get_subgradient() const; - bool operator<(SlaveCutTrimmer const & other)const; + bool operator<(SlaveCutTrimmer const &other) const; - void print(std::ostream & stream)const; + void print(std::ostream &stream) const; }; -std::ostream & operator<<(std::ostream & stream, SlaveCutTrimmer const & rhs); - -std::ostream & operator<<(std::ostream & stream, SlaveCutData const & rhs); +std::ostream &operator<<(std::ostream &stream, SlaveCutTrimmer const &rhs); +std::ostream &operator<<(std::ostream &stream, SlaveCutData const &rhs); diff --git a/src/cpp/benders/benders_core/include/Timer.h b/src/cpp/benders/benders_core/include/Timer.h index 7880e2c60..0784c4601 100644 --- a/src/cpp/benders/benders_core/include/Timer.h +++ b/src/cpp/benders/benders_core/include/Timer.h @@ -1,35 +1,30 @@ #pragma once -#include "common.h" - #include + +#include "common.h" typedef std::chrono::time_point TimePoint; class Timer { -public: - Timer(); - virtual ~Timer(); - - double elapsed() const; - void restart(); -private: - TimePoint _start; -}; + public: + Timer(); + virtual ~Timer(); -inline Timer::Timer() { - restart(); + double elapsed() const; + void restart(); -} + private: + TimePoint _start; +}; -inline void Timer::restart() { - _start = std::chrono::system_clock::now(); +inline Timer::Timer() { restart(); } -} +inline void Timer::restart() { _start = std::chrono::system_clock::now(); } inline double Timer::elapsed() const { - return std::chrono::duration < double - > (std::chrono::system_clock::now() - _start).count(); + return std::chrono::duration(std::chrono::system_clock::now() - + _start) + .count(); } -inline Timer::~Timer() { -} +inline Timer::~Timer() {} diff --git a/src/cpp/benders/benders_core/include/Worker.h b/src/cpp/benders/benders_core/include/Worker.h index 69e3ec5ef..4fbb82777 100644 --- a/src/cpp/benders/benders_core/include/Worker.h +++ b/src/cpp/benders/benders_core/include/Worker.h @@ -12,29 +12,30 @@ typedef std::shared_ptr WorkerPtr; * This class opens and sets a problem from a mps and a mapping variable map */ -class Worker -{ -public: - Worker() = default; - void init(Str2Int const &variable_map, std::string const &path_to_mps, - std::string const &solver_name, int log_level); - virtual ~Worker() = default; +class Worker { + public: + Worker() = default; + void init(Str2Int const &variable_map, std::string const &path_to_mps, + std::string const &solver_name, int log_level); + virtual ~Worker() = default; - void get_value(double &lb) const; + void get_value(double &lb) const; - void get_splex_num_of_ite_last(int &result) const; + void get_splex_num_of_ite_last(int &result) const; - void free(); + void free(); -public: - std::string _path_to_mps; - Str2Int _name_to_id; /*!< Link between the variable name and its identifier */ - Int2Str _id_to_name; /*!< Link between the identifier of a variable and its name*/ + public: + std::string _path_to_mps; + Str2Int _name_to_id; /*!< Link between the variable name and its identifier */ + Int2Str + _id_to_name; /*!< Link between the identifier of a variable and its name*/ -public: - void solve(int &lp_status, const std::string &outputroot) const; + public: + void solve(int &lp_status, const std::string &outputroot) const; -public: - SolverAbstract::Ptr _solver = nullptr; /*!< Problem stocked in the instance Worker*/ - bool _is_master = false; + public: + SolverAbstract::Ptr _solver = + nullptr; /*!< Problem stocked in the instance Worker*/ + bool _is_master = false; }; \ No newline at end of file diff --git a/src/cpp/benders/benders_core/include/WorkerMaster.h b/src/cpp/benders/benders_core/include/WorkerMaster.h index ad7ff159f..60392d702 100644 --- a/src/cpp/benders/benders_core/include/WorkerMaster.h +++ b/src/cpp/benders/benders_core/include/WorkerMaster.h @@ -9,36 +9,46 @@ class WorkerMaster; typedef std::shared_ptr WorkerMasterPtr; -class WorkerMaster : public Worker -{ -public: - WorkerMaster(); - WorkerMaster(Str2Int const &variable_map, std::string const &path_to_mps, const std::string &solver_name, const int log_level, int nslaves = 1); - virtual ~WorkerMaster(); - - void get(Point &x0, double &alpha, DblVector &alpha_i); - void get_dual_values(std::vector &dual) const; - int get_number_constraint() const; - - void add_cut(Point const &s, Point const &x0, double const &rhs) const; - void add_cut_by_iter(int const i, Point const &s, double const &sx0, double const &rhs) const; - void add_dynamic_cut(Point const &s, double const &sx0, double const &rhs) const; - void add_cut_slave(int i, Point const &s, Point const &x0, double const &rhs) const; - void delete_constraint(int const nrows)const; - void fix_alpha(double const &bestUB) const; - -private: - std::vector _id_alpha_i; - int _id_alpha = 0; - int _nslaves; - - void define_matval_mclind(const Point &s, std::vector &matval, std::vector &mclind) const; - - void define_rhs_with_master_variable(const Point &s, const Point &x0, const double &rhs, std::vector &rowrhs) const; - - void define_rhs_from_sx0(const double &sx0, const double &rhs, std::vector &rowrhs) const; - - void define_matval_mclind_for_index(const int i, const Point &s, std::vector &matval, std::vector &mclind) const; - void _set_upper_bounds() const; - void _add_alpha_var(); +class WorkerMaster : public Worker { + public: + WorkerMaster(); + WorkerMaster(Str2Int const &variable_map, std::string const &path_to_mps, + const std::string &solver_name, const int log_level, + int nslaves = 1); + virtual ~WorkerMaster(); + + void get(Point &x0, double &alpha, DblVector &alpha_i); + void get_dual_values(std::vector &dual) const; + int get_number_constraint() const; + + void add_cut(Point const &s, Point const &x0, double const &rhs) const; + void add_cut_by_iter(int const i, Point const &s, double const &sx0, + double const &rhs) const; + void add_dynamic_cut(Point const &s, double const &sx0, + double const &rhs) const; + void add_cut_slave(int i, Point const &s, Point const &x0, + double const &rhs) const; + void delete_constraint(int const nrows) const; + void fix_alpha(double const &bestUB) const; + + private: + std::vector _id_alpha_i; + int _id_alpha = 0; + int _nslaves; + + void define_matval_mclind(const Point &s, std::vector &matval, + std::vector &mclind) const; + + void define_rhs_with_master_variable(const Point &s, const Point &x0, + const double &rhs, + std::vector &rowrhs) const; + + void define_rhs_from_sx0(const double &sx0, const double &rhs, + std::vector &rowrhs) const; + + void define_matval_mclind_for_index(const int i, const Point &s, + std::vector &matval, + std::vector &mclind) const; + void _set_upper_bounds() const; + void _add_alpha_var(); }; diff --git a/src/cpp/benders/benders_core/include/WorkerSlave.h b/src/cpp/benders/benders_core/include/WorkerSlave.h index 4b281f3f8..08d343a89 100644 --- a/src/cpp/benders/benders_core/include/WorkerSlave.h +++ b/src/cpp/benders/benders_core/include/WorkerSlave.h @@ -1,8 +1,8 @@ #pragma once -#include "Worker.h" -#include "SlaveCut.h" #include "SimplexBasis.h" +#include "SlaveCut.h" +#include "Worker.h" /*! * \class WorkerSlave @@ -13,17 +13,18 @@ typedef std::shared_ptr WorkerSlavePtr; typedef std::vector WorkerSlaves; typedef std::map SlavesMapPtr; -class WorkerSlave : public Worker -{ -public: - WorkerSlave() = default; - WorkerSlave(Str2Int const &variable_map, std::string const &path_to_mps, double const &slave_weight, const std::string &solver_name, const int log_level); - virtual ~WorkerSlave() = default; +class WorkerSlave : public Worker { + public: + WorkerSlave() = default; + WorkerSlave(Str2Int const &variable_map, std::string const &path_to_mps, + double const &slave_weight, const std::string &solver_name, + const int log_level); + virtual ~WorkerSlave() = default; -public: - void fix_to(Point const &x0) const; + public: + void fix_to(Point const &x0) const; - void get_subgradient(Point &s) const; + void get_subgradient(Point &s) const; - SimplexBasis get_basis() const; + SimplexBasis get_basis() const; }; diff --git a/src/cpp/benders/benders_core/include/WorkerTrace.h b/src/cpp/benders/benders_core/include/WorkerTrace.h index 2fe788752..8a856032a 100644 --- a/src/cpp/benders/benders_core/include/WorkerTrace.h +++ b/src/cpp/benders/benders_core/include/WorkerTrace.h @@ -1,41 +1,38 @@ #pragma once - -#include "Worker.h" #include "SlaveCut.h" +#include "Worker.h" /*! -* \class WorkerMasterData -* \brief Class use to store trace information during the algorithm run -*/ + * \class WorkerMasterData + * \brief Class use to store trace information during the algorithm run + */ class WorkerMasterData { -public: - - WorkerMasterData() =default; - - bool _valid = false; - double _lb; - double _ub; - double _bestub; - int _deleted_cut; - int _nbasis; - double _time; - PointPtr _x0; - PointPtr _min_invest; - PointPtr _max_invest; - std::map _cut_trace; - - double _invest_cost; - double _operational_cost; - - Point get_point() const; - Point get_min_invest() const; - Point get_max_invest() const; + public: + WorkerMasterData() = default; + + bool _valid = false; + double _lb; + double _ub; + double _bestub; + int _deleted_cut; + int _nbasis; + double _time; + PointPtr _x0; + PointPtr _min_invest; + PointPtr _max_invest; + std::map _cut_trace; + + double _invest_cost; + double _operational_cost; + + Point get_point() const; + Point get_min_invest() const; + Point get_max_invest() const; }; -using WorkerMasterDataPtr=std::shared_ptr ; -using BendersTrace=std::vector ; - -LogData defineLogDataFromBendersDataAndTrace(const BendersData& data, const BendersTrace& trace); - +using WorkerMasterDataPtr = std::shared_ptr; +using BendersTrace = std::vector; +LogData defineLogDataFromBendersDataAndTrace(const BendersData& data, + const BendersTrace& trace); diff --git a/src/cpp/benders/benders_core/include/common.h b/src/cpp/benders/benders_core/include/common.h index 96d0d8539..4bcba0dd9 100644 --- a/src/cpp/benders/benders_core/include/common.h +++ b/src/cpp/benders/benders_core/include/common.h @@ -1,24 +1,25 @@ #pragma once #ifdef _MSC_VER -#pragma warning(disable : 4267) // implicit conversion, possible loss of data +#pragma warning(disable : 4267) // implicit conversion, possible loss of data #endif -#include -#include +#include +#include #include -#include #include -#include +#include #include -#include #include #include -#include #include -#include +#include +#include +#include #include -#include +#include +#include + #include "core/ILogger.h" // MultiSolver interface #include "multisolver_interface/Solver.h" @@ -47,49 +48,36 @@ typedef std::vector ActiveCutStorage; typedef std::pair mps_coupling; typedef std::list mps_coupling_list; -struct Predicate -{ - bool operator()(PointPtr const &lhs, PointPtr const &rhs) const - { - return *lhs < *rhs; - } - bool operator()(Point const &lhs, Point const &rhs) const - { - Point::const_iterator it1(lhs.begin()); - Point::const_iterator it2(rhs.begin()); - - Point::const_iterator end1(lhs.end()); - Point::const_iterator end2(rhs.end()); - - while (it1 != end1 && it2 != end2) - { - if (it1->first != it2->first) - { - return it1->first < it2->first; - } - else - { - if (std::fabs(it1->second - it2->second) < EPSILON_PREDICATE) - { - ++it1; - ++it2; - } - else - { - return it1->second < it2->second; - } - } - } - - if (it1 == end1 && it2 == end2) - { - return false; - } - else - { - return (it1 == end1); - } - } +struct Predicate { + bool operator()(PointPtr const &lhs, PointPtr const &rhs) const { + return *lhs < *rhs; + } + bool operator()(Point const &lhs, Point const &rhs) const { + Point::const_iterator it1(lhs.begin()); + Point::const_iterator it2(rhs.begin()); + + Point::const_iterator end1(lhs.end()); + Point::const_iterator end2(rhs.end()); + + while (it1 != end1 && it2 != end2) { + if (it1->first != it2->first) { + return it1->first < it2->first; + } else { + if (std::fabs(it1->second - it2->second) < EPSILON_PREDICATE) { + ++it1; + ++it2; + } else { + return it1->second < it2->second; + } + } + } + + if (it1 == end1 && it2 == end2) { + return false; + } else { + return (it1 == end1); + } + } }; /*! @@ -99,69 +87,61 @@ struct Predicate * * \param rhs : point */ -inline std::ostream &operator<<(std::ostream &stream, Point const &rhs) -{ - for (auto const &kvp : rhs) - { - if (kvp.second > 0) - { - if (kvp.second == 1) - { - stream << "+"; - stream << kvp.first; - } - else - { - stream << "+"; - stream << kvp.second; - stream << kvp.first; - } - } - else if (kvp.second < 0) - { - stream << kvp.second; - stream << kvp.first; - } - } - return stream; +inline std::ostream &operator<<(std::ostream &stream, Point const &rhs) { + for (auto const &kvp : rhs) { + if (kvp.second > 0) { + if (kvp.second == 1) { + stream << "+"; + stream << kvp.first; + } else { + stream << "+"; + stream << kvp.second; + stream << kvp.first; + } + } else if (kvp.second < 0) { + stream << kvp.second; + stream << kvp.first; + } + } + return stream; } /*! * \struct BendersData * \brief Structure used to manage every benders data */ -struct BendersData -{ - int nbasis; - double timer_slaves; - double timer_master; - double lb; - double ub; - double best_ub; - int maxsimplexiter; - int minsimplexiter; - int deletedcut; - int it; - bool stop; - double alpha; - std::vector alpha_i; - double slave_cost; - double invest_cost; - int best_it; - Point bestx; - Point x0; - Point min_invest; - Point max_invest; - int nslaves; - double dnslaves; - int master_status; - double elapsed_time; - StoppingCriterion stopping_criterion; +struct BendersData { + int nbasis; + double timer_slaves; + double timer_master; + double lb; + double ub; + double best_ub; + int maxsimplexiter; + int minsimplexiter; + int deletedcut; + int it; + bool stop; + double alpha; + std::vector alpha_i; + double slave_cost; + double invest_cost; + int best_it; + Point bestx; + Point x0; + Point min_invest; + Point max_invest; + int nslaves; + double dnslaves; + int master_status; + double elapsed_time; + StoppingCriterion stopping_criterion; }; double norm_point(Point const &x0, Point const &x1); -std::ostream &operator<<(std::ostream &stream, std::vector const &rhs); +std::ostream &operator<<(std::ostream &stream, + std::vector const &rhs); LogData bendersDataToLogData(const BendersData &data); @@ -169,43 +149,42 @@ const std::string SLAVE_WEIGHT_CST_STR("CONSTANT"); const std::string SLAVE_WEIGHT_UNIFORM_CST_STR("UNIFORM"); const std::string WEIGHT_SUM_CST_STR("WEIGHT_SUM"); const std::string MPS_SUFFIX = ".mps"; -const std::string OUTPUT_MASTER_MPS_FILE_NAME = "master_last_iteration" + MPS_SUFFIX; +const std::string OUTPUT_MASTER_MPS_FILE_NAME = + "master_last_iteration" + MPS_SUFFIX; -struct BaseOptions -{ - std::string OUTPUTROOT; - std::string INPUTROOT; - std::string STRUCTURE_FILE; - std::string MASTER_NAME; - std::string SOLVER_NAME; - std::string SLAVE_WEIGHT; +struct BaseOptions { + std::string OUTPUTROOT; + std::string INPUTROOT; + std::string STRUCTURE_FILE; + std::string MASTER_NAME; + std::string SOLVER_NAME; + std::string SLAVE_WEIGHT; - int SLAVE_NUMBER; - int LOG_LEVEL; + int SLAVE_NUMBER; + int LOG_LEVEL; - double SLAVE_WEIGHT_VALUE; + double SLAVE_WEIGHT_VALUE; - Str2Dbl weights; + Str2Dbl weights; }; typedef BaseOptions MergeMPSOptions; -struct BendersBaseOptions : public BaseOptions -{ - explicit BendersBaseOptions(const BaseOptions &base_to_copy) : BaseOptions(base_to_copy) - { - } +struct BendersBaseOptions : public BaseOptions { + explicit BendersBaseOptions(const BaseOptions &base_to_copy) + : BaseOptions(base_to_copy) {} - int MAX_ITERATIONS; + int MAX_ITERATIONS; - double ABSOLUTE_GAP; - double RELATIVE_GAP; - double TIME_LIMIT; + double ABSOLUTE_GAP; + double RELATIVE_GAP; + double TIME_LIMIT; - bool AGGREGATION; - bool TRACE; - bool BOUND_ALPHA; + bool AGGREGATION; + bool TRACE; + bool BOUND_ALPHA; - std::string CSV_NAME; + std::string CSV_NAME; }; void usage(int argc); -CouplingMap build_input(const std::string &structure_path, const int slave_number, const std::string &master_name); +CouplingMap build_input(const std::string &structure_path, + const int slave_number, const std::string &master_name); diff --git a/src/cpp/benders/benders_core/include/core/ILogger.h b/src/cpp/benders/benders_core/include/core/ILogger.h index bb8c5bc9a..b637508fe 100644 --- a/src/cpp/benders/benders_core/include/core/ILogger.h +++ b/src/cpp/benders/benders_core/include/core/ILogger.h @@ -2,78 +2,74 @@ #define ANTARESXPANSION_ILOGGER_H #include -#include #include #include +#include typedef std::map LogPoint; -enum class StoppingCriterion -{ - empty, - timelimit, - relative_gap, - absolute_gap, - max_iteration +enum class StoppingCriterion { + empty, + timelimit, + relative_gap, + absolute_gap, + max_iteration }; -inline std::string criterion_to_str(const StoppingCriterion stopping_criterion) -{ - std::string stop_crit(""); - switch (stopping_criterion) - { +inline std::string criterion_to_str( + const StoppingCriterion stopping_criterion) { + std::string stop_crit(""); + switch (stopping_criterion) { case StoppingCriterion::absolute_gap: - stop_crit = "absolute gap"; - break; + stop_crit = "absolute gap"; + break; case StoppingCriterion::relative_gap: - stop_crit = "relative gap"; - break; + stop_crit = "relative gap"; + break; case StoppingCriterion::max_iteration: - stop_crit = "maximum iterations"; - break; + stop_crit = "maximum iterations"; + break; case StoppingCriterion::timelimit: - stop_crit = "timelimit"; - break; + stop_crit = "timelimit"; + break; default: - break; - } - return stop_crit; + break; + } + return stop_crit; } -struct LogData -{ - double lb; - double best_ub; - int it; - int best_it; - double slave_cost; - double invest_cost; - LogPoint x0; - LogPoint min_invest; - LogPoint max_invest; - double optimality_gap; - double relative_gap; - double max_iterations; +struct LogData { + double lb; + double best_ub; + int it; + int best_it; + double slave_cost; + double invest_cost; + LogPoint x0; + LogPoint min_invest; + LogPoint max_invest; + double optimality_gap; + double relative_gap; + double max_iterations; }; -class ILogger -{ - -public: - virtual ~ILogger() = default; +class ILogger { + public: + virtual ~ILogger() = default; - virtual void display_message(const std::string &str) = 0; - virtual void log_at_initialization(const LogData &d) = 0; - virtual void log_iteration_candidates(const LogData &d) = 0; - virtual void log_master_solving_duration(double durationInSeconds) = 0; - virtual void log_subproblems_solving_duration(double durationInSeconds) = 0; - virtual void log_at_iteration_end(const LogData &d) = 0; - virtual void log_at_ending(const LogData &d) = 0; - virtual void log_total_duration(double durationInSeconds) = 0; - virtual void log_stop_criterion_reached(const StoppingCriterion stopping_criterion) = 0; + virtual void display_message(const std::string &str) = 0; + virtual void log_at_initialization(const LogData &d) = 0; + virtual void log_iteration_candidates(const LogData &d) = 0; + virtual void log_master_solving_duration(double durationInSeconds) = 0; + virtual void log_subproblems_solving_duration(double durationInSeconds) = 0; + virtual void log_at_iteration_end(const LogData &d) = 0; + virtual void log_at_ending(const LogData &d) = 0; + virtual void log_total_duration(double durationInSeconds) = 0; + virtual void log_stop_criterion_reached( + const StoppingCriterion stopping_criterion) = 0; }; using Logger = std::shared_ptr; -#endif // ANTARESXPANSION_ILOGGER_H +#endif // ANTARESXPANSION_ILOGGER_H diff --git a/src/cpp/benders/benders_mpi/BendersMPI.cpp b/src/cpp/benders/benders_mpi/BendersMPI.cpp index 85d55d5c1..87ec1199b 100644 --- a/src/cpp/benders/benders_mpi/BendersMPI.cpp +++ b/src/cpp/benders/benders_mpi/BendersMPI.cpp @@ -1,16 +1,17 @@ -#include +#include "BendersMPI.h" -#include "glog/logging.h" +#include -#include "BendersMPI.h" #include "Timer.h" +#include "glog/logging.h" #define __DEBUG_BENDERS_MPI__ 0 -BendersMpi::BendersMpi(BendersBaseOptions const &options, Logger &logger, Writer writer, mpi::environment &env, mpi::communicator &world) : BendersBase(options, logger, writer), _env(env), _world(world) -{ -} +BendersMpi::BendersMpi(BendersBaseOptions const &options, Logger &logger, + Writer writer, mpi::environment &env, + mpi::communicator &world) + : BendersBase(options, logger, writer), _env(env), _world(world) {} /*! * \brief Method to load each problem in a thread @@ -19,73 +20,65 @@ BendersMpi::BendersMpi(BendersBaseOptions const &options, Logger &logger, Writer * */ -void BendersMpi::load() -{ - StrVector names; - _data.nslaves = -1; - std::vector real_problem_list; - if (!_input.empty()) - { - update_real_problem_list(real_problem_list); - - mpi::broadcast(_world, _data.nslaves, 0); - int current_worker(1); - for (int islave(0); islave < _data.nslaves; ++islave, ++current_worker) - { - if (current_worker >= _world.size()) - { - current_worker = 1; - } - if (_world.rank() == 0) - { - CouplingMap::value_type kvp(*real_problem_list[islave]); - _world.send(current_worker, islave, kvp); - } - else if (_world.rank() == current_worker) - { - CouplingMap::value_type kvp; - _world.recv(0, islave, kvp); - _map_slaves[kvp.first] = WorkerSlavePtr(new WorkerSlave(kvp.second, get_slave_path(kvp.first), slave_weight(_data.nslaves, kvp.first), _options.SOLVER_NAME, _options.LOG_LEVEL)); - _slaves.push_back(kvp.first); - } - } - } +void BendersMpi::load() { + StrVector names; + _data.nslaves = -1; + std::vector real_problem_list; + if (!_input.empty()) { + update_real_problem_list(real_problem_list); + + mpi::broadcast(_world, _data.nslaves, 0); + int current_worker(1); + for (int islave(0); islave < _data.nslaves; ++islave, ++current_worker) { + if (current_worker >= _world.size()) { + current_worker = 1; + } + if (_world.rank() == 0) { + CouplingMap::value_type kvp(*real_problem_list[islave]); + _world.send(current_worker, islave, kvp); + } else if (_world.rank() == current_worker) { + CouplingMap::value_type kvp; + _world.recv(0, islave, kvp); + _map_slaves[kvp.first] = WorkerSlavePtr( + new WorkerSlave(kvp.second, get_slave_path(kvp.first), + slave_weight(_data.nslaves, kvp.first), + _options.SOLVER_NAME, _options.LOG_LEVEL)); + _slaves.push_back(kvp.first); + } + } + } } -void BendersMpi::update_real_problem_list(std::vector &real_problem_list) -{ - - if (_world.rank() == 0) - { - _data.nslaves = _options.SLAVE_NUMBER; - if (_data.nslaves < 0) - { - _data.nslaves = _input.size() - 1; - } - std::string const &master_name(_options.MASTER_NAME); - auto const it_master(_input.find(master_name)); - if (it_master == _input.end()) - { - std::cout << "UNABLE TO FIND " << master_name << std::endl; - std::exit(1); - } - // real problem list taking into account SLAVE_NUMBER - - real_problem_list.resize(_data.nslaves, _input.end()); - - CouplingMap::const_iterator it(_input.begin()); - for (int i(0); i < _data.nslaves; ++it) - { - if (it != it_master) - { - real_problem_list[i] = it; - _problem_to_id[it->first] = i; - ++i; - } - } - _master.reset(new WorkerMaster(it_master->second, get_master_path(), _options.SOLVER_NAME, _options.LOG_LEVEL, _data.nslaves)); - LOG(INFO) << "nrealslaves is " << _data.nslaves << std::endl; - } +void BendersMpi::update_real_problem_list( + std::vector &real_problem_list) { + if (_world.rank() == 0) { + _data.nslaves = _options.SLAVE_NUMBER; + if (_data.nslaves < 0) { + _data.nslaves = _input.size() - 1; + } + std::string const &master_name(_options.MASTER_NAME); + auto const it_master(_input.find(master_name)); + if (it_master == _input.end()) { + std::cout << "UNABLE TO FIND " << master_name << std::endl; + std::exit(1); + } + // real problem list taking into account SLAVE_NUMBER + + real_problem_list.resize(_data.nslaves, _input.end()); + + CouplingMap::const_iterator it(_input.begin()); + for (int i(0); i < _data.nslaves; ++it) { + if (it != it_master) { + real_problem_list[i] = it; + _problem_to_id[it->first] = i; + ++i; + } + } + _master.reset(new WorkerMaster(it_master->second, get_master_path(), + _options.SOLVER_NAME, _options.LOG_LEVEL, + _data.nslaves)); + LOG(INFO) << "nrealslaves is " << _data.nslaves << std::endl; + } } /*! * \brief Solve, get and send solution of the Master Problem to every thread @@ -94,125 +87,99 @@ void BendersMpi::update_real_problem_list(std::vectorlog_at_initialization(bendersDataToLogData(_data)); - _logger->display_message("\tSolving master..."); - get_master_value(); - _logger->log_master_solving_duration(_data.timer_master); - _logger->log_iteration_candidates(bendersDataToLogData(_data)); +void BendersMpi::solve_master_and_create_trace() { + _logger->log_at_initialization(bendersDataToLogData(_data)); + _logger->display_message("\tSolving master..."); + get_master_value(); + _logger->log_master_solving_duration(_data.timer_master); + _logger->log_iteration_candidates(bendersDataToLogData(_data)); - _trace.push_back(WorkerMasterDataPtr(new WorkerMasterData)); + _trace.push_back(WorkerMasterDataPtr(new WorkerMasterData)); } /*! * \brief Get cut information from each Slave and add it to the Master problem * - * Get cut information of every Slave Problem in each thread and send it to thread 0 to build new Master's cuts + * Get cut information of every Slave Problem in each thread and send it to + *thread 0 to build new Master's cuts * */ -void BendersMpi::step_2_build_cuts() -{ - solve_slaves_and_build_cuts(); +void BendersMpi::step_2_build_cuts() { solve_slaves_and_build_cuts(); } + +void BendersMpi::solve_slaves_and_build_cuts() { + int success = 1; + SlaveCutPackage slave_cut_package; + Timer timer_slaves; + try { + if (_world.rank() != 0) { + slave_cut_package = get_slave_package(); + } + } catch (std::exception &ex) { + success = 0; + write_exception_message(ex); + } + check_if_some_proc_had_a_failure(success); + gather_slave_cut_package_and_build_cuts(slave_cut_package, timer_slaves); } -void BendersMpi::solve_slaves_and_build_cuts() -{ - int success = 1; - SlaveCutPackage slave_cut_package; - Timer timer_slaves; - try - { - if (_world.rank() != 0) - { - slave_cut_package = get_slave_package(); - } - } - catch (std::exception &ex) - { - success = 0; - write_exception_message(ex); - } - check_if_some_proc_had_a_failure(success); - gather_slave_cut_package_and_build_cuts(slave_cut_package, timer_slaves); +void BendersMpi::gather_slave_cut_package_and_build_cuts( + const SlaveCutPackage &slave_cut_package, const Timer &timer_slaves) { + if (!_exceptionRaised) { + if (_world.rank() != 0) { + mpi::gather(_world, slave_cut_package, 0); + } else { + AllCutPackage all_package; + mpi::gather(_world, slave_cut_package, all_package, 0); + _data.timer_slaves = timer_slaves.elapsed(); + master_build_cuts(all_package); + } + } } -void BendersMpi::gather_slave_cut_package_and_build_cuts(const SlaveCutPackage &slave_cut_package, const Timer &timer_slaves) -{ - if (!_exceptionRaised) - { - if (_world.rank() != 0) - { - mpi::gather(_world, slave_cut_package, 0); - } - else - { - AllCutPackage all_package; - mpi::gather(_world, slave_cut_package, all_package, 0); - _data.timer_slaves = timer_slaves.elapsed(); - master_build_cuts(all_package); - } - } +SlaveCutPackage BendersMpi::get_slave_package() { + SlaveCutPackage slave_cut_package; + get_slave_cut(slave_cut_package); + return slave_cut_package; } -SlaveCutPackage BendersMpi::get_slave_package() -{ - SlaveCutPackage slave_cut_package; - get_slave_cut(slave_cut_package); - return slave_cut_package; -} - -void BendersMpi::master_build_cuts(AllCutPackage all_package) -{ - - _data.slave_cost = 0; - for (auto const &pack : all_package) - { - for (auto &dataVal : pack) - { - _data.slave_cost += dataVal.second.first.second[SLAVE_COST]; - } - } - all_package.erase(all_package.begin()); +void BendersMpi::master_build_cuts(AllCutPackage all_package) { + _data.slave_cost = 0; + for (auto const &pack : all_package) { + for (auto &dataVal : pack) { + _data.slave_cost += dataVal.second.first.second[SLAVE_COST]; + } + } + all_package.erase(all_package.begin()); - _logger->display_message("\tSolving subproblems..."); + _logger->display_message("\tSolving subproblems..."); - build_cut_full(all_package); - _logger->log_subproblems_solving_duration(_data.timer_slaves); + build_cut_full(all_package); + _logger->log_subproblems_solving_duration(_data.timer_slaves); } /*! @@ -223,55 +190,48 @@ void BendersMpi::master_build_cuts(AllCutPackage all_package) * \param _world : communicator variable for mpi communication */ -void BendersMpi::check_if_some_proc_had_a_failure(int success) -{ - int global_success; - mpi::all_reduce(_world, success, global_success, mpi::bitwise_and()); - if (global_success == 0) - { - _exceptionRaised = true; - } +void BendersMpi::check_if_some_proc_had_a_failure(int success) { + int global_success; + mpi::all_reduce(_world, success, global_success, mpi::bitwise_and()); + if (global_success == 0) { + _exceptionRaised = true; + } } -void BendersMpi::write_exception_message(const std::exception &ex) -{ - std::string error = "Exception raised : " + std::string(ex.what()); - LOG(WARNING) << error << std::endl; - // TODO is this IF necessary ? - if (_logger) - { - _logger->display_message(error); - } +void BendersMpi::write_exception_message(const std::exception &ex) { + std::string error = "Exception raised : " + std::string(ex.what()); + LOG(WARNING) << error << std::endl; + // TODO is this IF necessary ? + if (_logger) { + _logger->display_message(error); + } } -void BendersMpi::step_4_update_best_solution(int rank, const Timer &timer_master, const Timer &benders_timer) -{ - if (rank == 0) - { - update_best_ub(); - _logger->log_at_iteration_end(bendersDataToLogData(_data)); +void BendersMpi::step_4_update_best_solution(int rank, + const Timer &timer_master, + const Timer &benders_timer) { + if (rank == 0) { + update_best_ub(); + _logger->log_at_iteration_end(bendersDataToLogData(_data)); - update_trace(); + update_trace(); - _data.elapsed_time = benders_timer.elapsed(); - _data.timer_master = timer_master.elapsed(); - _data.stop = stopping_criterion(); - } + _data.elapsed_time = benders_timer.elapsed(); + _data.timer_master = timer_master.elapsed(); + _data.stop = stopping_criterion(); + } } /*! * \brief Method to free the memory used by each problem */ -void BendersMpi::free() -{ - if (_world.rank() == 0) - _master->free(); - else - { - for (auto &ptr : _map_slaves) - ptr.second->free(); - } - _world.barrier(); +void BendersMpi::free() { + if (_world.rank() == 0) + _master->free(); + else { + for (auto &ptr : _map_slaves) ptr.second->free(); + } + _world.barrier(); } /*! @@ -280,63 +240,57 @@ void BendersMpi::free() * Method to run Benders algorithm in parallel * */ -void BendersMpi::run() -{ - if (_world.rank() == 0) - { - for (auto const &kvp : _problem_to_id) - { - _all_cuts_storage[kvp.first] = SlaveCutStorage(); - } - } - init_data(); - _world.barrier(); - - Timer benders_timer; - while (!_data.stop) - { - Timer timer_master; - ++_data.it; - _data.deletedcut = 0; - - /*Solve Master problem, get optimal value and cost and send it to Slaves*/ - step_1_solve_master(); - - /*Gather cut from each slave in master thread and add them to Master problem*/ - if (!_exceptionRaised) - { - step_2_build_cuts(); - } - - if (!_exceptionRaised) - { - step_4_update_best_solution(_world.rank(), timer_master, benders_timer); - } - _data.stop |= _exceptionRaised; - - broadcast(_world, _data.stop, 0); - } - - if (_world.rank() == 0 && _options.TRACE) - { - print_csv(); - } +void BendersMpi::run() { + if (_world.rank() == 0) { + for (auto const &kvp : _problem_to_id) { + _all_cuts_storage[kvp.first] = SlaveCutStorage(); + } + } + init_data(); + _world.barrier(); + + Timer benders_timer; + while (!_data.stop) { + Timer timer_master; + ++_data.it; + _data.deletedcut = 0; + + /*Solve Master problem, get optimal value and cost and send it to Slaves*/ + step_1_solve_master(); + + /*Gather cut from each slave in master thread and add them to Master + * problem*/ + if (!_exceptionRaised) { + step_2_build_cuts(); + } + + if (!_exceptionRaised) { + step_4_update_best_solution(_world.rank(), timer_master, benders_timer); + } + _data.stop |= _exceptionRaised; + + broadcast(_world, _data.stop, 0); + } + + if (_world.rank() == 0 && _options.TRACE) { + print_csv(); + } } -void BendersMpi::launch() -{ - _input = build_input(get_structure_path(), _options.SLAVE_NUMBER, _options.MASTER_NAME); - _nbWeeks = _input.size(); - _world.barrier(); +void BendersMpi::launch() { + _input = build_input(get_structure_path(), _options.SLAVE_NUMBER, + _options.MASTER_NAME); + _nbWeeks = _input.size(); + _world.barrier(); - load(); - _world.barrier(); + load(); + _world.barrier(); - run(); - _world.barrier(); + run(); + _world.barrier(); - post_run_actions(); + post_run_actions(); - free(); - _world.barrier(); + free(); + _world.barrier(); } diff --git a/src/cpp/benders/benders_mpi/common_mpi.cpp b/src/cpp/benders/benders_mpi/common_mpi.cpp index 139597f9c..8b1378917 100644 --- a/src/cpp/benders/benders_mpi/common_mpi.cpp +++ b/src/cpp/benders/benders_mpi/common_mpi.cpp @@ -1,2 +1 @@ - diff --git a/src/cpp/benders/benders_mpi/include/BendersMPI.h b/src/cpp/benders/benders_mpi/include/BendersMPI.h index 9ddd6ab4f..04c56a2a8 100644 --- a/src/cpp/benders/benders_mpi/include/BendersMPI.h +++ b/src/cpp/benders/benders_mpi/include/BendersMPI.h @@ -1,57 +1,58 @@ #pragma once #include "BendersBase.h" -#include "common_mpi.h" #include "SlaveCut.h" +#include "Timer.h" #include "Worker.h" -#include "WorkerSlave.h" #include "WorkerMaster.h" +#include "WorkerSlave.h" #include "WorkerTrace.h" -#include "Timer.h" - +#include "common_mpi.h" #include "core/ILogger.h" /*! * \class BendersMpi * \brief Class use run the benders algorithm in parallel */ -class BendersMpi : public BendersBase -{ - -public: - virtual ~BendersMpi() = default; - BendersMpi(BendersBaseOptions const &options, Logger &logger, Writer writer, mpi::environment &env, mpi::communicator &world); +class BendersMpi : public BendersBase { + public: + virtual ~BendersMpi() = default; + BendersMpi(BendersBaseOptions const &options, Logger &logger, Writer writer, + mpi::environment &env, mpi::communicator &world); - void load(); - virtual void launch(); + void load(); + virtual void launch(); -protected: - virtual void free(); - virtual void run(); + protected: + virtual void free(); + virtual void run(); -private: - void step_1_solve_master(); - void step_2_build_cuts(); - void step_4_update_best_solution(int rank, const Timer &timer_master, const Timer &benders_timer); + private: + void step_1_solve_master(); + void step_2_build_cuts(); + void step_4_update_best_solution(int rank, const Timer &timer_master, + const Timer &benders_timer); - void master_build_cuts(AllCutPackage all_package); - SlaveCutPackage get_slave_package(); + void master_build_cuts(AllCutPackage all_package); + SlaveCutPackage get_slave_package(); - void solve_master_and_create_trace(); + void solve_master_and_create_trace(); - bool _exceptionRaised = false; + bool _exceptionRaised = false; - void do_solve_master_create_trace_and_update_cuts(int rank); + void do_solve_master_create_trace_and_update_cuts(int rank); - void broadcast_the_master_problem(); + void broadcast_the_master_problem(); - void solve_slaves_and_build_cuts(); - void gather_slave_cut_package_and_build_cuts(const SlaveCutPackage &slave_cut_package, const Timer &timer_slaves); + void solve_slaves_and_build_cuts(); + void gather_slave_cut_package_and_build_cuts( + const SlaveCutPackage &slave_cut_package, const Timer &timer_slaves); - void write_exception_message(const std::exception &ex); + void write_exception_message(const std::exception &ex); - void check_if_some_proc_had_a_failure(int success); - void update_real_problem_list(std::vector &real_problem_list); - mpi::environment &_env; - mpi::communicator &_world; + void check_if_some_proc_had_a_failure(int success); + void update_real_problem_list( + std::vector &real_problem_list); + mpi::environment &_env; + mpi::communicator &_world; }; diff --git a/src/cpp/benders/benders_mpi/include/common_mpi.h b/src/cpp/benders/benders_mpi/include/common_mpi.h index 0d5e6a898..b84db2550 100644 --- a/src/cpp/benders/benders_mpi/include/common_mpi.h +++ b/src/cpp/benders/benders_mpi/include/common_mpi.h @@ -2,16 +2,17 @@ #define __ACTIVE_CHECK__ 0 -#include "common.h" #include #include #include +#include #include -#include +#include #include #include -#include -#include +#include + +#include "common.h" namespace mpi = boost::mpi; diff --git a/src/cpp/benders/benders_sequential/BendersSequential.cpp b/src/cpp/benders/benders_sequential/BendersSequential.cpp index b5955254a..42c1c20f3 100644 --- a/src/cpp/benders/benders_sequential/BendersSequential.cpp +++ b/src/cpp/benders/benders_sequential/BendersSequential.cpp @@ -1,84 +1,82 @@ #include "BendersSequential.h" -#include "solver_utils.h" -#include "Timer.h" -#include #include +#include +#include "Timer.h" #include "glog/logging.h" +#include "solver_utils.h" /*! * \brief Constructor of class BendersSequential * - * Method to build a BendersSequential element, initializing each problem from a list + * Method to build a BendersSequential element, initializing each problem from + * a list * * \param options : set of options fixed by the user */ -BendersSequential::BendersSequential(BendersBaseOptions const &options, Logger &logger, Writer writer) : BendersBase(options, logger, writer) -{ -} - -void BendersSequential::initialise_problems() -{ - if (!_input.empty()) - { - _data.nslaves = _options.SLAVE_NUMBER; - if (_data.nslaves < 0) - { - _data.nslaves = _input.size() - 1; - } - - auto it(_input.begin()); - - auto const it_master = _input.find(_options.MASTER_NAME); - Str2Int const &master_variable(it_master->second); - for (int i(0); i < _data.nslaves; ++it) - { - if (it != it_master) - { - _problem_to_id[it->first] = i; - _map_slaves[it->first] = WorkerSlavePtr(new WorkerSlave(it->second, get_slave_path(it->first), slave_weight(_data.nslaves, it->first), _options.SOLVER_NAME, _options.LOG_LEVEL)); - _slaves.push_back(it->first); - i++; - } - } - _master.reset(new WorkerMaster(master_variable, get_master_path(), _options.SOLVER_NAME, _options.LOG_LEVEL, _data.nslaves)); - } +BendersSequential::BendersSequential(BendersBaseOptions const &options, + Logger &logger, Writer writer) + : BendersBase(options, logger, writer) {} + +void BendersSequential::initialise_problems() { + if (!_input.empty()) { + _data.nslaves = _options.SLAVE_NUMBER; + if (_data.nslaves < 0) { + _data.nslaves = _input.size() - 1; + } + + auto it(_input.begin()); + + auto const it_master = _input.find(_options.MASTER_NAME); + Str2Int const &master_variable(it_master->second); + for (int i(0); i < _data.nslaves; ++it) { + if (it != it_master) { + _problem_to_id[it->first] = i; + _map_slaves[it->first] = WorkerSlavePtr( + new WorkerSlave(it->second, get_slave_path(it->first), + slave_weight(_data.nslaves, it->first), + _options.SOLVER_NAME, _options.LOG_LEVEL)); + _slaves.push_back(it->first); + i++; + } + } + _master.reset(new WorkerMaster(master_variable, get_master_path(), + _options.SOLVER_NAME, _options.LOG_LEVEL, + _data.nslaves)); + } } /*! * \brief Method to free the memory used by each problem */ -void BendersSequential::free() -{ - if (_master) - _master->free(); - for (auto &ptr : _map_slaves) - ptr.second->free(); +void BendersSequential::free() { + if (_master) _master->free(); + for (auto &ptr : _map_slaves) ptr.second->free(); } /*! * \brief Build Slave cut and store it in the BendersSequential trace * - * Method to build Slaves cuts, store them in the BendersSequential trace and add them to the Master problem + * Method to build Slaves cuts, store them in the BendersSequential trace and + * add them to the Master problem * */ -void BendersSequential::build_cut() -{ - SlaveCutPackage slave_cut_package; - AllCutPackage all_package; - Timer timer_slaves; - get_slave_cut(slave_cut_package); - _data.slave_cost = 0; - for (auto pairSlavenameSlavecutdata_l : slave_cut_package) - { - _data.slave_cost += pairSlavenameSlavecutdata_l.second.first.second[SLAVE_COST]; - } - - _data.timer_slaves = timer_slaves.elapsed(); - all_package.push_back(slave_cut_package); - build_cut_full(all_package); +void BendersSequential::build_cut() { + SlaveCutPackage slave_cut_package; + AllCutPackage all_package; + Timer timer_slaves; + get_slave_cut(slave_cut_package); + _data.slave_cost = 0; + for (auto pairSlavenameSlavecutdata_l : slave_cut_package) { + _data.slave_cost += + pairSlavenameSlavecutdata_l.second.first.second[SLAVE_COST]; + } + + _data.timer_slaves = timer_slaves.elapsed(); + all_package.push_back(slave_cut_package); + build_cut_full(all_package); } /*! @@ -86,71 +84,64 @@ void BendersSequential::build_cut() * * Method to run BendersSequential algorithm */ -void BendersSequential::run() -{ - for (auto const &kvp : _problem_to_id) - { - _all_cuts_storage[kvp.first] = SlaveCutStorage(); - } - init_data(); - Timer benders_timer; - while (!_data.stop) - { - Timer timer_master; - ++_data.it; - - _logger->log_at_initialization(bendersDataToLogData(_data)); - _logger->display_message("\tSolving master..."); - get_master_value(); - _logger->log_master_solving_duration(_data.timer_master); - - _logger->log_iteration_candidates(bendersDataToLogData(_data)); - - _trace.push_back(WorkerMasterDataPtr(new WorkerMasterData)); - - _logger->display_message("\tSolving subproblems..."); - build_cut(); - _logger->log_subproblems_solving_duration(_data.timer_slaves); - - update_best_ub(); - - _logger->log_at_iteration_end(bendersDataToLogData(_data)); - - update_trace(); - - _data.timer_master = timer_master.elapsed(); - _data.elapsed_time = benders_timer.elapsed(); - _data.stop = stopping_criterion(); - } - - if (_options.TRACE) - { - print_csv(); - } +void BendersSequential::run() { + for (auto const &kvp : _problem_to_id) { + _all_cuts_storage[kvp.first] = SlaveCutStorage(); + } + init_data(); + Timer benders_timer; + while (!_data.stop) { + Timer timer_master; + ++_data.it; + + _logger->log_at_initialization(bendersDataToLogData(_data)); + _logger->display_message("\tSolving master..."); + get_master_value(); + _logger->log_master_solving_duration(_data.timer_master); + + _logger->log_iteration_candidates(bendersDataToLogData(_data)); + + _trace.push_back(WorkerMasterDataPtr(new WorkerMasterData)); + + _logger->display_message("\tSolving subproblems..."); + build_cut(); + _logger->log_subproblems_solving_duration(_data.timer_slaves); + + update_best_ub(); + + _logger->log_at_iteration_end(bendersDataToLogData(_data)); + + update_trace(); + + _data.timer_master = timer_master.elapsed(); + _data.elapsed_time = benders_timer.elapsed(); + _data.stop = stopping_criterion(); + } + + if (_options.TRACE) { + print_csv(); + } } -void BendersSequential::launch() -{ - _input = build_input(get_structure_path(), _options.SLAVE_NUMBER, _options.MASTER_NAME); - _nbWeeks = _input.size(); - LOG(INFO) << "Building input" << std::endl; - - LOG(INFO) << "Constructing workers..." << std::endl; - - initialise_problems(); - LOG(INFO) << "Running solver..." << std::endl; - try - { - run(); - LOG(INFO) << "BendersSequential solver terminated." << std::endl; - } - catch (std::exception &ex) - { - std::string error = "Exception raised : " + std::string(ex.what()); - LOG(WARNING) << error << std::endl; - _logger->display_message(error); - } - - post_run_actions(); - free(); +void BendersSequential::launch() { + _input = build_input(get_structure_path(), _options.SLAVE_NUMBER, + _options.MASTER_NAME); + _nbWeeks = _input.size(); + LOG(INFO) << "Building input" << std::endl; + + LOG(INFO) << "Constructing workers..." << std::endl; + + initialise_problems(); + LOG(INFO) << "Running solver..." << std::endl; + try { + run(); + LOG(INFO) << "BendersSequential solver terminated." << std::endl; + } catch (std::exception &ex) { + std::string error = "Exception raised : " + std::string(ex.what()); + LOG(WARNING) << error << std::endl; + _logger->display_message(error); + } + + post_run_actions(); + free(); } \ No newline at end of file diff --git a/src/cpp/benders/benders_sequential/include/BendersSequential.h b/src/cpp/benders/benders_sequential/include/BendersSequential.h index e1d3f58ae..161429aa9 100644 --- a/src/cpp/benders/benders_sequential/include/BendersSequential.h +++ b/src/cpp/benders/benders_sequential/include/BendersSequential.h @@ -8,16 +8,16 @@ * \class BendersSequential * \brief Class use run the benders algorithm in sequential */ -class BendersSequential : public BendersBase -{ -public: - explicit BendersSequential(BendersBaseOptions const &options, Logger &logger, Writer writer); - virtual ~BendersSequential() = default; - virtual void launch(); - void build_cut(); - void initialise_problems(); +class BendersSequential : public BendersBase { + public: + explicit BendersSequential(BendersBaseOptions const &options, Logger &logger, + Writer writer); + virtual ~BendersSequential() = default; + virtual void launch(); + void build_cut(); + void initialise_problems(); -protected: - virtual void free(); - virtual void run(); + protected: + virtual void free(); + virtual void run(); }; diff --git a/src/cpp/benders/factories/LoggerFactories.cpp b/src/cpp/benders/factories/LoggerFactories.cpp index b63c03e08..06697fd0e 100644 --- a/src/cpp/benders/factories/LoggerFactories.cpp +++ b/src/cpp/benders/factories/LoggerFactories.cpp @@ -1,29 +1,30 @@ #include "LoggerFactories.h" -#include "logger/UserFile.h" + #include "logger/Master.h" +#include "logger/UserFile.h" -Logger build_void_logger() -{ - Logger logger = std::make_shared(); - return logger; +Logger build_void_logger() { + Logger logger = std::make_shared(); + return logger; } -Logger build_stdout_and_file_logger(const std::string &report_file_path_string) -{ - auto masterLogger = std::make_shared(); - Logger loggerFile = std::make_shared(report_file_path_string); - Logger loggerUser = std::make_shared(std::cout); - masterLogger->addLogger(loggerFile); - masterLogger->addLogger(loggerUser); - Logger logger = masterLogger; - return logger; +Logger build_stdout_and_file_logger( + const std::string &report_file_path_string) { + auto masterLogger = std::make_shared(); + Logger loggerFile = + std::make_shared(report_file_path_string); + Logger loggerUser = std::make_shared(std::cout); + masterLogger->addLogger(loggerFile); + masterLogger->addLogger(loggerUser); + Logger logger = masterLogger; + return logger; } -std::ostringstream start_message(const SimulationOptions &options, const std::string &benders_type) -{ - std::ostringstream oss_l; - oss_l << "starting Benders " << benders_type << std::endl; - options.print(oss_l); - return oss_l; +std::ostringstream start_message(const SimulationOptions &options, + const std::string &benders_type) { + std::ostringstream oss_l; + oss_l << "starting Benders " << benders_type << std::endl; + options.print(oss_l); + return oss_l; } \ No newline at end of file diff --git a/src/cpp/benders/factories/WriterFactories.cpp b/src/cpp/benders/factories/WriterFactories.cpp index 0d8ac0190..7f7e0944a 100644 --- a/src/cpp/benders/factories/WriterFactories.cpp +++ b/src/cpp/benders/factories/WriterFactories.cpp @@ -1,21 +1,18 @@ #include "WriterFactories.h" -#include "VoidWriter.h" + #include "JsonWriter.h" #include "OutputWriter.h" +#include "VoidWriter.h" -Writer build_void_writer() -{ - return std::make_shared(); -} +Writer build_void_writer() { return std::make_shared(); } -Writer build_json_writer(const std::string &json_file_name) -{ - auto m_clock = std::make_shared(); +Writer build_json_writer(const std::string &json_file_name) { + auto m_clock = std::make_shared(); - Writer writer = std::make_shared(m_clock, json_file_name); + Writer writer = std::make_shared(m_clock, json_file_name); - writer->initialize(); - return writer; + writer->initialize(); + return writer; } diff --git a/src/cpp/benders/factories/include/LoggerFactories.h b/src/cpp/benders/factories/include/LoggerFactories.h index 2ed0bba04..e041b5664 100644 --- a/src/cpp/benders/factories/include/LoggerFactories.h +++ b/src/cpp/benders/factories/include/LoggerFactories.h @@ -2,11 +2,12 @@ #ifndef ANTARESXPANSION_LOGGERFACTORIES_H #define ANTARESXPANSION_LOGGERFACTORIES_H -#include "core/ILogger.h" #include "SimulationOptions.h" +#include "core/ILogger.h" Logger build_void_logger(); Logger build_stdout_and_file_logger(const std::string &report_file_path_string); -std::ostringstream start_message(const SimulationOptions &options, const std::string &benders_type); -#endif // ANTARESXPANSION_LOGGERFACTORIES_H +std::ostringstream start_message(const SimulationOptions &options, + const std::string &benders_type); +#endif // ANTARESXPANSION_LOGGERFACTORIES_H diff --git a/src/cpp/benders/factories/include/WriterFactories.h b/src/cpp/benders/factories/include/WriterFactories.h index f1547bdb0..d65239e82 100644 --- a/src/cpp/benders/factories/include/WriterFactories.h +++ b/src/cpp/benders/factories/include/WriterFactories.h @@ -2,11 +2,12 @@ #ifndef ANTARESXPANSION_WRITERFACTORIES_H #define ANTARESXPANSION_WRITERFACTORIES_H -#include "OutputWriter.h" #include +#include "OutputWriter.h" + Writer build_void_writer(); Writer build_json_writer(const std::string &json_file_name); -#endif // ANTARESXPANSION_WRITERFACTORIES_H +#endif // ANTARESXPANSION_WRITERFACTORIES_H diff --git a/src/cpp/benders/logger/CandidateLog.cpp b/src/cpp/benders/logger/CandidateLog.cpp index a31003147..866b9424b 100644 --- a/src/cpp/benders/logger/CandidateLog.cpp +++ b/src/cpp/benders/logger/CandidateLog.cpp @@ -1,81 +1,88 @@ +#include "CandidateLog.h" + #include #include -#include #include #include +#include #include "core/ILogger.h" -#include "CandidateLog.h" -namespace xpansion{ +namespace xpansion { namespace logger { - std::string CandidateLog::log_iteration_candidates(const LogData &data){ - std::stringstream _stream; - _stream << getHeaderString(); - _stream << getMainBodyString(data); - return _stream.str(); - } - - std::string CandidateLog::getHeaderString() const{ - std::stringstream header; - header << indent_0 << "Candidates:" << std::endl; - return header.str(); - } - - std::string CandidateLog::getMainBodyString(const LogData &data) { - _values.clear(); - _sizes.clear(); - set_values_and_sizes(data); - return getStringBodyUsingValuesAndSizes(); - } +std::string CandidateLog::log_iteration_candidates(const LogData &data) { + std::stringstream _stream; + _stream << getHeaderString(); + _stream << getMainBodyString(data); + return _stream.str(); +} - void CandidateLog::set_values_and_sizes(const LogData &data) { - for (const auto& pairVarnameValue : data.x0) { - std::string candidate = pairVarnameValue.first; +std::string CandidateLog::getHeaderString() const { + std::stringstream header; + header << indent_0 << "Candidates:" << std::endl; + return header.str(); +} - value_map valuesMap; - valuesMap[CANDIDATE] = candidate; - valuesMap[INVEST] = get_formatted_string_from_value(pairVarnameValue.second); - valuesMap[INVEST_MIN] = get_formatted_string_from_value(data.min_invest.at(candidate)); - valuesMap[INVEST_MAX] = get_formatted_string_from_value(data.max_invest.at(candidate)); - _values.push_back(valuesMap); +std::string CandidateLog::getMainBodyString(const LogData &data) { + _values.clear(); + _sizes.clear(); + set_values_and_sizes(data); + return getStringBodyUsingValuesAndSizes(); +} - updateMaximumSizes(valuesMap); - } - } +void CandidateLog::set_values_and_sizes(const LogData &data) { + for (const auto &pairVarnameValue : data.x0) { + std::string candidate = pairVarnameValue.first; - inline std::string CandidateLog::get_formatted_string_from_value(double val) { - std::stringstream result; - result << std::fixed << std::setprecision(2) << val; - return result.str(); - } + value_map valuesMap; + valuesMap[CANDIDATE] = candidate; + valuesMap[INVEST] = + get_formatted_string_from_value(pairVarnameValue.second); + valuesMap[INVEST_MIN] = + get_formatted_string_from_value(data.min_invest.at(candidate)); + valuesMap[INVEST_MAX] = + get_formatted_string_from_value(data.max_invest.at(candidate)); + _values.push_back(valuesMap); + updateMaximumSizes(valuesMap); + } +} - void CandidateLog::updateMaximumSizes(value_map &valuesMap) {//Compute maximum string size - for (const auto& it : valuesMap) { - const std::string &key = it.first; - _sizes[key] = std::max(it.second.length(), _sizes[key]); - } - } +inline std::string CandidateLog::get_formatted_string_from_value(double val) { + std::stringstream result; + result << std::fixed << std::setprecision(2) << val; + return result.str(); +} - std::string CandidateLog::getStringBodyUsingValuesAndSizes() { - std::stringstream main_body; - for (const auto& value : _values) { - main_body << create_candidate_str(value) << std::endl; - } - return main_body.str(); - } +void CandidateLog::updateMaximumSizes( + value_map &valuesMap) { // Compute maximum string size + for (const auto &it : valuesMap) { + const std::string &key = it.first; + _sizes[key] = std::max(it.second.length(), _sizes[key]); + } +} - inline std::string CandidateLog::create_candidate_str(const value_map &value) { - std::stringstream result; - result << indent_0 << indent_1 << std::setw(_sizes.at(CANDIDATE)) << value.at(CANDIDATE); - result << " = " << std::setw(_sizes.at(INVEST)) << value.at(INVEST) << " invested MW "; - result << "-- possible interval [" << std::setw(_sizes.at(INVEST_MIN)) << value.at(INVEST_MIN); - result << "; " << std::setw(_sizes.at(INVEST_MAX)) << value.at(INVEST_MAX) << "] MW"; - return result.str(); - } +std::string CandidateLog::getStringBodyUsingValuesAndSizes() { + std::stringstream main_body; + for (const auto &value : _values) { + main_body << create_candidate_str(value) << std::endl; + } + return main_body.str(); +} +inline std::string CandidateLog::create_candidate_str(const value_map &value) { + std::stringstream result; + result << indent_0 << indent_1 << std::setw(_sizes.at(CANDIDATE)) + << value.at(CANDIDATE); + result << " = " << std::setw(_sizes.at(INVEST)) << value.at(INVEST) + << " invested MW "; + result << "-- possible interval [" << std::setw(_sizes.at(INVEST_MIN)) + << value.at(INVEST_MIN); + result << "; " << std::setw(_sizes.at(INVEST_MAX)) << value.at(INVEST_MAX) + << "] MW"; + return result.str(); +} -} // namespace logger -} // namespace xpansion \ No newline at end of file +} // namespace logger +} // namespace xpansion \ No newline at end of file diff --git a/src/cpp/benders/logger/CandidateLog.h b/src/cpp/benders/logger/CandidateLog.h index b42e91ea9..4f09af265 100644 --- a/src/cpp/benders/logger/CandidateLog.h +++ b/src/cpp/benders/logger/CandidateLog.h @@ -1,41 +1,42 @@ #ifndef ANTARESXPANSION_CANDIDATELOG_H #define ANTARESXPANSION_CANDIDATELOG_H -namespace xpansion{ -namespace logger { - typedef std::map value_map; - typedef std::map size_map; - - class CandidateLog { - public : - - std::string log_iteration_candidates(const LogData &_data); - - - private: - const std::string indent_0 = "\t\t"; - const std::string indent_1 = "\t"; - - const std::string CANDIDATE = "CANDIDATE"; - const std::string INVEST = "INVEST"; - const std::string INVEST_MIN = "INVEST_MIN"; - const std::string INVEST_MAX = "INVEST_MAX"; +#include +#include +#include +#include "core/ILogger.h" - std::list _values; - size_map _sizes; - - - std::string getHeaderString() const; - std::string getMainBodyString(const LogData &data); - void set_values_and_sizes(const LogData &data); - static std::string get_formatted_string_from_value(double val); - void updateMaximumSizes(value_map &valuesMap); - std::string getStringBodyUsingValuesAndSizes(); - std::string create_candidate_str(const value_map &value); - - }; - -} // namespace logger -} // namespace xpansion - -#endif //ANTARESXPANSION_CANDIDATELOG_H +namespace xpansion { +namespace logger { +typedef std::map value_map; +typedef std::map size_map; + +class CandidateLog { + public: + std::string log_iteration_candidates(const LogData &_data); + + private: + const std::string indent_0 = "\t\t"; + const std::string indent_1 = "\t"; + + const std::string CANDIDATE = "CANDIDATE"; + const std::string INVEST = "INVEST"; + const std::string INVEST_MIN = "INVEST_MIN"; + const std::string INVEST_MAX = "INVEST_MAX"; + + std::list _values; + size_map _sizes; + + std::string getHeaderString() const; + std::string getMainBodyString(const LogData &data); + void set_values_and_sizes(const LogData &data); + static std::string get_formatted_string_from_value(double val); + void updateMaximumSizes(value_map &valuesMap); + std::string getStringBodyUsingValuesAndSizes(); + std::string create_candidate_str(const value_map &value); +}; + +} // namespace logger +} // namespace xpansion + +#endif // ANTARESXPANSION_CANDIDATELOG_H diff --git a/src/cpp/benders/logger/Commons.h b/src/cpp/benders/logger/Commons.h index 6e385e74e..3899f5f0b 100644 --- a/src/cpp/benders/logger/Commons.h +++ b/src/cpp/benders/logger/Commons.h @@ -1,26 +1,24 @@ #ifndef ANTARESXPANSION_COMMONS_H #define ANTARESXPANSION_COMMONS_H - -namespace xpansion{ +namespace xpansion { namespace logger { namespace commons { +inline double convert_in_million_euros(double val) { return val / 1e6; } - inline double convert_in_million_euros(double val) { return val / 1e6; } - - inline std::string create_str_million_euros(double val) { - std::stringstream result; - result << std::fixed << std::setprecision(2) << convert_in_million_euros(val); - return result.str(); - } +inline std::string create_str_million_euros(double val) { + std::stringstream result; + result << std::fixed << std::setprecision(2) << convert_in_million_euros(val); + return result.str(); +} - inline std::string create_str_euros(double val) { - std::stringstream result; - result << std::scientific << std::setprecision(5) << val; - return result.str(); - } +inline std::string create_str_euros(double val) { + std::stringstream result; + result << std::scientific << std::setprecision(5) << val; + return result.str(); } -} // namespace logger -} // namespace xpansion -#endif //ANTARESXPANSION_COMMONS_H +} // namespace commons +} // namespace logger +} // namespace xpansion +#endif // ANTARESXPANSION_COMMONS_H diff --git a/src/cpp/benders/logger/IterationResultLog.cpp b/src/cpp/benders/logger/IterationResultLog.cpp index 4f4b3927b..25b71e3ff 100644 --- a/src/cpp/benders/logger/IterationResultLog.cpp +++ b/src/cpp/benders/logger/IterationResultLog.cpp @@ -1,91 +1,97 @@ +#include "IterationResultLog.h" + #include #include -#include #include #include +#include -#include "core/ILogger.h" #include "Commons.h" -#include "IterationResultLog.h" - +#include "core/ILogger.h" -namespace xpansion{ +namespace xpansion { namespace logger { - std::string IterationResultLog::Log_at_iteration_end(const LogData &data) { - setValuesFromData(data); - setMaximumStringSizes(); - return getCompleteMessageString(); - } - - void IterationResultLog::setValuesFromData(const LogData &data) { - - double low_bd = data.lb; - double abs_gap = data.best_ub - data.lb; - double rel_gap = abs_gap / data.best_ub; - const double overall_cost = data.slave_cost + data.invest_cost; - - // Quick and dirty fix when gap is negative, further investigation needed - if (abs_gap < 0) { - abs_gap = 0; - rel_gap = 0; - low_bd = data.best_ub; - } - - //Get values - - _values.clear(); - _values.push_back(create_value_map("Operational cost", commons::create_str_million_euros(data.slave_cost), " Me") ); - _values.push_back(create_value_map("Investment cost", commons::create_str_million_euros(data.invest_cost), " Me") ); - _values.push_back(create_value_map("Overall cost", commons::create_str_million_euros(overall_cost), " Me") ); - _values.push_back(create_value_map("Best Solution", commons::create_str_million_euros(data.best_ub), " Me")); - _values.push_back(create_value_map("Lower Bound", commons::create_str_million_euros(low_bd), " Me")); - _values.push_back(create_value_map("Absolute gap", commons::create_str_euros(abs_gap), " e") ); - _values.push_back(create_value_map("Relative gap", commons::create_str_euros(rel_gap), "") ); - } - - - void IterationResultLog::setMaximumStringSizes() {//Compute maximum string size - - for (auto value : _values) { - _max_sizes[LABEL] = std::max(value.at(LABEL).length(), _max_sizes[LABEL]); - _max_sizes[VALUE] = std::max(value.at(VALUE).length(), _max_sizes[VALUE]); - } - } - - std::string IterationResultLog::getCompleteMessageString() const { - std::stringstream _stream; - _stream << indent_0 << "Solution =" << std::endl; - for (const auto& value : _values) { - _stream << create_solution_str(value, _max_sizes) << std::endl; - } - return _stream.str(); - } - - inline std::string IterationResultLog::create_solution_str(const value_map& value, - const size_map& sizes) const - { - std::stringstream result; - result << indent_0 << indent_1 << std::setw(sizes.at(LABEL)) << value.at(LABEL); - result << " = " << std::setw(sizes.at(VALUE)) << value.at(VALUE) << value.at(UNIT); - return result.str(); - } - - - - - - - inline value_map IterationResultLog::create_value_map(const std::string& label, const std::string& value, const std::string& unit) const - { - value_map result; - result[LABEL] = label; - result[VALUE] = value; - result[UNIT] = unit; - - return result; - } - - -} // namespace logger -} // namespace xpansion \ No newline at end of file +std::string IterationResultLog::Log_at_iteration_end(const LogData& data) { + setValuesFromData(data); + setMaximumStringSizes(); + return getCompleteMessageString(); +} + +void IterationResultLog::setValuesFromData(const LogData& data) { + double low_bd = data.lb; + double abs_gap = data.best_ub - data.lb; + double rel_gap = abs_gap / data.best_ub; + const double overall_cost = data.slave_cost + data.invest_cost; + + // Quick and dirty fix when gap is negative, further investigation needed + if (abs_gap < 0) { + abs_gap = 0; + rel_gap = 0; + low_bd = data.best_ub; + } + + // Get values + + _values.clear(); + _values.push_back(create_value_map( + "Operational cost", commons::create_str_million_euros(data.slave_cost), + " Me")); + _values.push_back(create_value_map( + "Investment cost", commons::create_str_million_euros(data.invest_cost), + " Me")); + _values.push_back(create_value_map( + "Overall cost", commons::create_str_million_euros(overall_cost), " Me")); + _values.push_back(create_value_map( + "Best Solution", commons::create_str_million_euros(data.best_ub), " Me")); + _values.push_back(create_value_map( + "Lower Bound", commons::create_str_million_euros(low_bd), " Me")); + _values.push_back(create_value_map("Absolute gap", + commons::create_str_euros(abs_gap), " e")); + _values.push_back( + create_value_map("Relative gap", commons::create_str_euros(rel_gap), "")); +} + +void IterationResultLog::setMaximumStringSizes() { // Compute maximum string + // size + + for (auto value : _values) { + _max_sizes[LABEL] = + std::max(value.at(LABEL).length(), _max_sizes[LABEL]); + _max_sizes[VALUE] = + std::max(value.at(VALUE).length(), _max_sizes[VALUE]); + } +} + +std::string IterationResultLog::getCompleteMessageString() const { + std::stringstream _stream; + _stream << indent_0 << "Solution =" << std::endl; + for (const auto& value : _values) { + _stream << create_solution_str(value, _max_sizes) << std::endl; + } + return _stream.str(); +} + +inline std::string IterationResultLog::create_solution_str( + const value_map& value, const size_map& sizes) const { + std::stringstream result; + result << indent_0 << indent_1 << std::setw(sizes.at(LABEL)) + << value.at(LABEL); + result << " = " << std::setw(sizes.at(VALUE)) << value.at(VALUE) + << value.at(UNIT); + return result.str(); +} + +inline value_map IterationResultLog::create_value_map( + const std::string& label, const std::string& value, + const std::string& unit) const { + value_map result; + result[LABEL] = label; + result[VALUE] = value; + result[UNIT] = unit; + + return result; +} + +} // namespace logger +} // namespace xpansion \ No newline at end of file diff --git a/src/cpp/benders/logger/IterationResultLog.h b/src/cpp/benders/logger/IterationResultLog.h index d2b7ae801..11c04a635 100644 --- a/src/cpp/benders/logger/IterationResultLog.h +++ b/src/cpp/benders/logger/IterationResultLog.h @@ -1,41 +1,46 @@ #ifndef ANTARESXPANSION_ITERATIONRESULTLOG_H #define ANTARESXPANSION_ITERATIONRESULTLOG_H -namespace xpansion{ -namespace logger { - - typedef std::map value_map; - typedef std::map size_map; +#include +#include +#include +#include "core/ILogger.h" - class IterationResultLog { +namespace xpansion { +namespace logger { - public: +typedef std::map value_map; +typedef std::map size_map; - std::string Log_at_iteration_end(const LogData &data); +class IterationResultLog { + public: + std::string Log_at_iteration_end(const LogData &data); - private: - const std::string indent_0 = "\t\t"; - const std::string indent_1 = "\t"; + private: + const std::string indent_0 = "\t\t"; + const std::string indent_1 = "\t"; - const std::string LABEL = "LABEL"; - const std::string VALUE = "VALUE"; - const std::string UNIT = "UNIT"; - std::list _values; - size_map _max_sizes; - private: + const std::string LABEL = "LABEL"; + const std::string VALUE = "VALUE"; + const std::string UNIT = "UNIT"; + std::list _values; + size_map _max_sizes; - std::string create_solution_str(const value_map &value, const size_map &sizes) const; + private: + std::string create_solution_str(const value_map &value, + const size_map &sizes) const; - value_map create_value_map(const std::string &label, const std::string &value, const std::string &unit) const; + value_map create_value_map(const std::string &label, const std::string &value, + const std::string &unit) const; - void setValuesFromData(const LogData &data); + void setValuesFromData(const LogData &data); - void setMaximumStringSizes(); + void setMaximumStringSizes(); - std::string getCompleteMessageString() const; - }; + std::string getCompleteMessageString() const; +}; -} // namespace logger -} // namespace xpansion +} // namespace logger +} // namespace xpansion -#endif //ANTARESXPANSION_ITERATIONRESULTLOG_H +#endif // ANTARESXPANSION_ITERATIONRESULTLOG_H diff --git a/src/cpp/benders/logger/Master.cpp b/src/cpp/benders/logger/Master.cpp index 789dbce86..3634a3194 100644 --- a/src/cpp/benders/logger/Master.cpp +++ b/src/cpp/benders/logger/Master.cpp @@ -1,64 +1,62 @@ #include "logger/Master.h" -namespace xpansion{ +namespace xpansion { namespace logger { - - - void Master::display_message(const std::string& str) { - for (auto logger : _loggers) { - logger->display_message(str); - } - } - - void Master::log_at_initialization(const LogData &d) { - for (auto logger : _loggers) { - logger->log_at_initialization(d); - } - } - - void Master::log_iteration_candidates(const LogData &d) { - for (auto logger : _loggers) { - logger->log_iteration_candidates(d); - } - } - - void Master::log_master_solving_duration(double durationInSeconds) { - for (auto logger : _loggers) { - logger->log_master_solving_duration(durationInSeconds); - } - } - - void Master::log_subproblems_solving_duration(double durationInSeconds){ - for (auto logger : _loggers) { - logger->log_subproblems_solving_duration(durationInSeconds); - } - } - - void Master::log_at_iteration_end(const LogData &d) { - for (auto logger : _loggers) { - logger->log_at_iteration_end(d); - } - } - - void Master::log_at_ending(const LogData &d) { - for (auto logger : _loggers) { - logger->log_at_ending(d); - } - } - - void Master::log_total_duration(double durationInSeconds) { - for (auto logger : _loggers) { - logger->log_total_duration(durationInSeconds); - } - } - - void Master::log_stop_criterion_reached(const StoppingCriterion stopping_criterion) { - for (auto logger : _loggers) { - logger->log_stop_criterion_reached(stopping_criterion); - } - } - -} // namespace logger -} // namespace xpansion - +void Master::display_message(const std::string &str) { + for (auto logger : _loggers) { + logger->display_message(str); + } +} + +void Master::log_at_initialization(const LogData &d) { + for (auto logger : _loggers) { + logger->log_at_initialization(d); + } +} + +void Master::log_iteration_candidates(const LogData &d) { + for (auto logger : _loggers) { + logger->log_iteration_candidates(d); + } +} + +void Master::log_master_solving_duration(double durationInSeconds) { + for (auto logger : _loggers) { + logger->log_master_solving_duration(durationInSeconds); + } +} + +void Master::log_subproblems_solving_duration(double durationInSeconds) { + for (auto logger : _loggers) { + logger->log_subproblems_solving_duration(durationInSeconds); + } +} + +void Master::log_at_iteration_end(const LogData &d) { + for (auto logger : _loggers) { + logger->log_at_iteration_end(d); + } +} + +void Master::log_at_ending(const LogData &d) { + for (auto logger : _loggers) { + logger->log_at_ending(d); + } +} + +void Master::log_total_duration(double durationInSeconds) { + for (auto logger : _loggers) { + logger->log_total_duration(durationInSeconds); + } +} + +void Master::log_stop_criterion_reached( + const StoppingCriterion stopping_criterion) { + for (auto logger : _loggers) { + logger->log_stop_criterion_reached(stopping_criterion); + } +} + +} // namespace logger +} // namespace xpansion diff --git a/src/cpp/benders/logger/User.cpp b/src/cpp/benders/logger/User.cpp index 60c8fcc45..b943599d7 100644 --- a/src/cpp/benders/logger/User.cpp +++ b/src/cpp/benders/logger/User.cpp @@ -1,77 +1,69 @@ +#include "logger/User.h" + #include #include -#include #include #include +#include -#include "logger/User.h" #include "CandidateLog.h" -#include "IterationResultLog.h" #include "Commons.h" +#include "IterationResultLog.h" -namespace xpansion -{ - namespace logger - { - - const std::string indent_0 = "\t\t"; - const std::string indent_1 = "\t"; +namespace xpansion { +namespace logger { - User::User(std::ostream &stream) - : _stream(stream) - { - if (_stream.fail()) - { - std::cerr << "Invalid stream passed as parameter" << std::endl; - } - } +const std::string indent_0 = "\t\t"; +const std::string indent_1 = "\t"; - void User::display_message(const std::string &str) - { - _stream << str << std::endl; - } +User::User(std::ostream &stream) : _stream(stream) { + if (_stream.fail()) { + std::cerr << "Invalid stream passed as parameter" << std::endl; + } +} - void User::log_at_initialization(const LogData &d) - { - _stream << "ITERATION " << d.it << ":" << std::endl; - } +void User::display_message(const std::string &str) { + _stream << str << std::endl; +} - void User::log_iteration_candidates(const LogData &d) - { - _stream << CandidateLog().log_iteration_candidates(d); - } +void User::log_at_initialization(const LogData &d) { + _stream << "ITERATION " << d.it << ":" << std::endl; +} - void User::log_master_solving_duration(double durationInSeconds) - { - _stream << indent_1 << "Master solved in " << durationInSeconds << " s" << std::endl; - } +void User::log_iteration_candidates(const LogData &d) { + _stream << CandidateLog().log_iteration_candidates(d); +} - void User::log_subproblems_solving_duration(double durationInSeconds) - { - _stream << indent_1 << "Subproblems solved in " << durationInSeconds << " s" << std::endl; - } +void User::log_master_solving_duration(double durationInSeconds) { + _stream << indent_1 << "Master solved in " << durationInSeconds << " s" + << std::endl; +} - void User::log_at_iteration_end(const LogData &d) - { - _stream << IterationResultLog().Log_at_iteration_end(d); - } +void User::log_subproblems_solving_duration(double durationInSeconds) { + _stream << indent_1 << "Subproblems solved in " << durationInSeconds << " s" + << std::endl; +} - void User::log_at_ending(const LogData &d) - { +void User::log_at_iteration_end(const LogData &d) { + _stream << IterationResultLog().Log_at_iteration_end(d); +} - const double overall_cost = d.slave_cost + d.invest_cost; - _stream << indent_1 << "Best solution = it " << d.best_it << std::endl; - _stream << indent_1 << " Overall cost = " << commons::create_str_million_euros(overall_cost) << " Me" << std::endl; - } - void User::log_total_duration(double durationInSeconds) - { - _stream << "Problem ran in " << durationInSeconds << " s" << std::endl; - } +void User::log_at_ending(const LogData &d) { + const double overall_cost = d.slave_cost + d.invest_cost; + _stream << indent_1 << "Best solution = it " << d.best_it << std::endl; + _stream << indent_1 << " Overall cost = " + << commons::create_str_million_euros(overall_cost) << " Me" + << std::endl; +} +void User::log_total_duration(double durationInSeconds) { + _stream << "Problem ran in " << durationInSeconds << " s" << std::endl; +} - void User::log_stop_criterion_reached(const StoppingCriterion stopping_criterion) - { - _stream << "--- Run completed: " << criterion_to_str(stopping_criterion) << " reached" << std::endl; - } +void User::log_stop_criterion_reached( + const StoppingCriterion stopping_criterion) { + _stream << "--- Run completed: " << criterion_to_str(stopping_criterion) + << " reached" << std::endl; +} - } // namespace logger -} // namespace xpansion +} // namespace logger +} // namespace xpansion diff --git a/src/cpp/benders/logger/UserFile.cpp b/src/cpp/benders/logger/UserFile.cpp index 862d38e06..9f9aa1a6f 100644 --- a/src/cpp/benders/logger/UserFile.cpp +++ b/src/cpp/benders/logger/UserFile.cpp @@ -1,72 +1,58 @@ +#include "logger/UserFile.h" + #include #include -#include #include #include - -#include "logger/UserFile.h" +#include namespace xpansion { - namespace logger { +namespace logger { - UserFile::UserFile(const std::string& filename) - { - _file.open(filename); - if (_file.fail()) - { - std::cerr << "Invalid file name passed as parameter" << std::endl; - } - _userLog = std::unique_ptr(new User(_file)); - } +UserFile::UserFile(const std::string& filename) { + _file.open(filename); + if (_file.fail()) { + std::cerr << "Invalid file name passed as parameter" << std::endl; + } + _userLog = std::unique_ptr(new User(_file)); +} - UserFile::~UserFile() - { - _file.close(); - } +UserFile::~UserFile() { _file.close(); } - void UserFile::display_message(const std::string& str) - { - _userLog->display_message(str); - } +void UserFile::display_message(const std::string& str) { + _userLog->display_message(str); +} - void UserFile::log_at_initialization(const LogData& d) - { - _userLog->log_at_initialization(d); - } +void UserFile::log_at_initialization(const LogData& d) { + _userLog->log_at_initialization(d); +} - void UserFile::log_iteration_candidates(const LogData& d) - { - _userLog->log_iteration_candidates(d); - } +void UserFile::log_iteration_candidates(const LogData& d) { + _userLog->log_iteration_candidates(d); +} - void UserFile::log_master_solving_duration(double durationInSeconds) - { - _userLog->log_master_solving_duration(durationInSeconds); - } +void UserFile::log_master_solving_duration(double durationInSeconds) { + _userLog->log_master_solving_duration(durationInSeconds); +} - void UserFile::log_subproblems_solving_duration(double durationInSeconds) - { - _userLog->log_subproblems_solving_duration(durationInSeconds); - } +void UserFile::log_subproblems_solving_duration(double durationInSeconds) { + _userLog->log_subproblems_solving_duration(durationInSeconds); +} - void UserFile::log_at_iteration_end(const LogData& d) - { - _userLog->log_at_iteration_end(d); - } +void UserFile::log_at_iteration_end(const LogData& d) { + _userLog->log_at_iteration_end(d); +} - void UserFile::log_at_ending(const LogData& d) - { - _userLog->log_at_ending(d); - } +void UserFile::log_at_ending(const LogData& d) { _userLog->log_at_ending(d); } - void UserFile::log_total_duration(double durationInSeconds) - { - _userLog->log_total_duration(durationInSeconds); - } +void UserFile::log_total_duration(double durationInSeconds) { + _userLog->log_total_duration(durationInSeconds); +} - void UserFile::log_stop_criterion_reached(const StoppingCriterion stopping_criterion) { - _userLog->log_stop_criterion_reached(stopping_criterion); - } +void UserFile::log_stop_criterion_reached( + const StoppingCriterion stopping_criterion) { + _userLog->log_stop_criterion_reached(stopping_criterion); +} - } // namespace logger -} // namespace xpansion +} // namespace logger +} // namespace xpansion diff --git a/src/cpp/benders/logger/include/logger/Master.h b/src/cpp/benders/logger/include/logger/Master.h index 0826aface..1aa38256b 100644 --- a/src/cpp/benders/logger/include/logger/Master.h +++ b/src/cpp/benders/logger/include/logger/Master.h @@ -5,50 +5,49 @@ #ifndef ANTARESXPANSION_MASTER_H #define ANTARESXPANSION_MASTER_H -#include #include +#include #include #include #include "core/ILogger.h" -namespace xpansion{ +namespace xpansion { namespace logger { - class Master : public ILogger { - - public: - - Master() = default; - ~Master()= default; - - void addLogger(const std::shared_ptr& logger) {_loggers.push_back(logger);} - - void display_message(const std::string& str) override; +class Master : public ILogger { + public: + Master() = default; + ~Master() = default; - void log_at_initialization(const LogData &d) override; + void addLogger(const std::shared_ptr &logger) { + _loggers.push_back(logger); + } - void log_iteration_candidates(const LogData &d) override; + void display_message(const std::string &str) override; - void log_master_solving_duration(double durationInSeconds) override; + void log_at_initialization(const LogData &d) override; - void log_subproblems_solving_duration(double durationInSeconds) override; + void log_iteration_candidates(const LogData &d) override; - void log_at_iteration_end(const LogData &d) override; + void log_master_solving_duration(double durationInSeconds) override; - void log_at_ending(const LogData &d) override; + void log_subproblems_solving_duration(double durationInSeconds) override; - void log_total_duration(double durationInSeconds) override; + void log_at_iteration_end(const LogData &d) override; - void log_stop_criterion_reached(const StoppingCriterion stopping_criterion) override; + void log_at_ending(const LogData &d) override; - private: + void log_total_duration(double durationInSeconds) override; - std::list> _loggers; + void log_stop_criterion_reached( + const StoppingCriterion stopping_criterion) override; - }; + private: + std::list> _loggers; +}; -} // namespace logger -} // namespace xpansion +} // namespace logger +} // namespace xpansion -#endif //ANTARESXPANSION_MASTER_H +#endif // ANTARESXPANSION_MASTER_H diff --git a/src/cpp/benders/logger/include/logger/User.h b/src/cpp/benders/logger/include/logger/User.h index 39dafece5..086e7f678 100644 --- a/src/cpp/benders/logger/include/logger/User.h +++ b/src/cpp/benders/logger/include/logger/User.h @@ -9,42 +9,37 @@ #include "core/ILogger.h" -namespace xpansion{ +namespace xpansion { namespace logger { - class User : public ILogger { +class User : public ILogger { + public: + User(std::ostream &stream); - public: + void display_message(const std::string &str) override; - User(std::ostream& stream); + void log_at_initialization(const LogData &d) override; - void display_message(const std::string& str) override; + void log_iteration_candidates(const LogData &d) override; - void log_at_initialization(const LogData &d) override; + void log_master_solving_duration(double durationInSeconds) override; - void log_iteration_candidates(const LogData &d) override; + void log_subproblems_solving_duration(double durationInSeconds) override; - void log_master_solving_duration(double durationInSeconds) override; + void log_at_iteration_end(const LogData &d) override; - void log_subproblems_solving_duration(double durationInSeconds) override; + void log_at_ending(const LogData &d) override; - void log_at_iteration_end(const LogData &d) override; + void log_total_duration(double durationInSeconds) override; - void log_at_ending(const LogData &d) override; + void log_stop_criterion_reached( + const StoppingCriterion stopping_criterion) override; - void log_total_duration(double durationInSeconds) override; + private: + std::ostream &_stream; +}; - void log_stop_criterion_reached(const StoppingCriterion stopping_criterion) override; +} // namespace logger +} // namespace xpansion - - private: - - std::ostream& _stream; - - - }; - -} // namespace logger -} // namespace xpansion - -#endif //ANTARESXPANSION_USER_H +#endif // ANTARESXPANSION_USER_H diff --git a/src/cpp/benders/logger/include/logger/UserFile.h b/src/cpp/benders/logger/include/logger/UserFile.h index 76f3d2009..33030db4d 100644 --- a/src/cpp/benders/logger/include/logger/UserFile.h +++ b/src/cpp/benders/logger/include/logger/UserFile.h @@ -1,48 +1,45 @@ #ifndef ANTARESXPANSION_CONSOLE_H #define ANTARESXPANSION_CONSOLE_H -#include #include +#include #include "core/ILogger.h" #include "logger/User.h" -namespace xpansion -{ - namespace logger - { - - class UserFile : public ILogger - { +namespace xpansion { +namespace logger { - public: - explicit UserFile(const std::string &filename); - ~UserFile(); +class UserFile : public ILogger { + public: + explicit UserFile(const std::string &filename); + ~UserFile(); - void display_message(const std::string &str) override; + void display_message(const std::string &str) override; - void log_at_initialization(const LogData &d) override; + void log_at_initialization(const LogData &d) override; - void log_iteration_candidates(const LogData &d) override; + void log_iteration_candidates(const LogData &d) override; - void log_master_solving_duration(double durationInSeconds) override; + void log_master_solving_duration(double durationInSeconds) override; - void log_subproblems_solving_duration(double durationInSeconds) override; + void log_subproblems_solving_duration(double durationInSeconds) override; - void log_at_iteration_end(const LogData &d) override; + void log_at_iteration_end(const LogData &d) override; - void log_at_ending(const LogData &d) override; + void log_at_ending(const LogData &d) override; - void log_total_duration(double durationInSeconds) override; + void log_total_duration(double durationInSeconds) override; - void log_stop_criterion_reached(const StoppingCriterion stopping_criterion) override; + void log_stop_criterion_reached( + const StoppingCriterion stopping_criterion) override; - private: - std::ofstream _file; - std::unique_ptr _userLog; - }; + private: + std::ofstream _file; + std::unique_ptr _userLog; +}; - } // namespace logger -} // namespace xpansion +} // namespace logger +} // namespace xpansion -#endif // ANTARESXPANSION_CONSOLE_H +#endif // ANTARESXPANSION_CONSOLE_H diff --git a/src/cpp/benders/merge_mps/MergeMPS.cpp b/src/cpp/benders/merge_mps/MergeMPS.cpp index cb36c2f9b..f426c7679 100644 --- a/src/cpp/benders/merge_mps/MergeMPS.cpp +++ b/src/cpp/benders/merge_mps/MergeMPS.cpp @@ -1,220 +1,203 @@ #include "MergeMPS.h" -#include "helpers/Path.h" -#include "glog/logging.h" -#include "Timer.h" - -MergeMPS::MergeMPS(const MergeMPSOptions &options, Logger &logger, Writer writer) : _options(options), _logger(logger), _writer(writer) {} - -void MergeMPS::launch() -{ - auto structure_path((Path(_options.INPUTROOT) / _options.STRUCTURE_FILE).get_str()); - CouplingMap input = build_input(structure_path, _options.SLAVE_NUMBER, _options.MASTER_NAME); - - SolverFactory factory; - std::string solver_to_use = (_options.SOLVER_NAME == "COIN") ? "CBC" : _options.SOLVER_NAME; - SolverAbstract::Ptr mergedSolver_l = factory.create_solver(solver_to_use); - mergedSolver_l->init(); - mergedSolver_l->set_output_log_level(_options.LOG_LEVEL); - - int nslaves = input.size() - 1; - CouplingMap x_mps_id; - int cntProblems_l(0); - - LOG(INFO) << "Merging problems..." << std::endl; - for (auto const &kvp : input) - { - - auto problem_name((Path(_options.INPUTROOT) / (kvp.first + MPS_SUFFIX)).get_str()); - - SolverAbstract::Ptr solver_l = factory.create_solver(solver_to_use); - solver_l->init(); - solver_l->set_output_log_level(_options.LOG_LEVEL); - solver_l->read_prob_mps(problem_name); - - if (kvp.first != _options.MASTER_NAME) - { - - int mps_ncols(solver_l->get_ncols()); - - DblVector o(mps_ncols); - IntVector sequence(mps_ncols); - for (int i(0); i < mps_ncols; ++i) - { - sequence[i] = i; - } - solver_get_obj_func_coeffs(solver_l, o, 0, mps_ncols - 1); - double const weigth = slave_weight(nslaves, kvp.first); - for (auto &c : o) - { - c *= weigth; - } - solver_l->chg_obj(sequence, o); - } - StandardLp lpData(solver_l); - std::string varPrefix_l = "prob" + std::to_string(cntProblems_l) + "_"; - - lpData.append_in(mergedSolver_l, varPrefix_l); - - for (auto const &x : kvp.second) - { - int col_index = mergedSolver_l->get_col_index(varPrefix_l + x.first); - if (col_index == -1) - { - std::cerr << "missing variable " << x.first << " in " << kvp.first << " supposedly renamed to " << varPrefix_l + x.first << "."; - mergedSolver_l->write_prob_lp((Path(_options.OUTPUTROOT) / "mergeError.lp").get_str()); - mergedSolver_l->write_prob_mps((Path(_options.OUTPUTROOT) / ("mergeError" + MPS_SUFFIX)).get_str()); - std::exit(1); - } - else - { - x_mps_id[x.first][kvp.first] = col_index; - } - } - - ++cntProblems_l; - } - - IntVector mstart; - IntVector cindex; - DblVector values; - int nrows(0); - int neles(0); - size_t neles_reserve(0); - size_t nrows_reserve(0); - for (auto const &kvp : x_mps_id) - { - neles_reserve += kvp.second.size() * (kvp.second.size() - 1); - nrows_reserve += kvp.second.size() * (kvp.second.size() - 1) / 2; - } - LOG(INFO) << "About to add " << nrows_reserve << " coupling constraints" << std::endl; - values.reserve(neles_reserve); - cindex.reserve(neles_reserve); - mstart.reserve(nrows_reserve + 1); - - // adding coupling constraints - for (auto const &kvp : x_mps_id) - { - std::string const var_name(kvp.first); - LOG(INFO) << var_name << std::endl; - bool is_first(true); - int id1(-1); - std::string first_mps; - for (auto const &mps : kvp.second) - { - if (is_first) - { - is_first = false; - first_mps = mps.first; - id1 = mps.second; - } - else - { - int id2 = mps.second; - mstart.push_back(neles); - cindex.push_back(id1); - values.push_back(1); - ++neles; - - cindex.push_back(id2); - values.push_back(-1); - ++neles; - ++nrows; - } - } - } - mstart.push_back(neles); - - DblVector rhs(nrows, 0); - CharVector sense(nrows, 'E'); - solver_addrows(mergedSolver_l, sense, rhs, {}, mstart, cindex, values); - - LOG(INFO) << "Problems merged." << std::endl; - LOG(INFO) << "Writting mps file" << std::endl; - mergedSolver_l->write_prob_mps((Path(_options.OUTPUTROOT) / ("log_merged" + MPS_SUFFIX)).get_str()); - LOG(INFO) << "Writting lp file" << std::endl; - mergedSolver_l->write_prob_lp((Path(_options.OUTPUTROOT) / "log_merged.lp").get_str()); - - mergedSolver_l->set_threads(16); - - _logger->display_message("Solving..."); - Timer timer; - int status_l = 0; - if (mergedSolver_l->get_n_integer_vars() > 0) - { - status_l = mergedSolver_l->solve_mip(); - } - else - { - status_l = mergedSolver_l->solve_lp(); - } - - _logger->log_total_duration(timer.elapsed()); - - Point x0; - DblVector ptr(mergedSolver_l->get_ncols()); - double investCost_l(0); - if (mergedSolver_l->get_n_integer_vars() > 0) - { - mergedSolver_l->get_mip_sol(ptr.data()); - } - else - { - mergedSolver_l->get_lp_sol(ptr.data(), nullptr, nullptr); - } - std::vector obj_coef(mergedSolver_l->get_ncols()); - mergedSolver_l->get_obj(obj_coef.data(), 0, mergedSolver_l->get_ncols() - 1); - for (auto const &pairNameId : input[_options.MASTER_NAME]) - { - int varIndexInMerged_l = x_mps_id[pairNameId.first][_options.MASTER_NAME]; - x0[pairNameId.first] = ptr[varIndexInMerged_l]; - investCost_l += x0[pairNameId.first] * obj_coef[varIndexInMerged_l]; - } - - double overallCost_l; - if (mergedSolver_l->get_n_integer_vars() > 0) - { - overallCost_l = mergedSolver_l->get_mip_value(); - } - else - { - overallCost_l = mergedSolver_l->get_lp_value(); - } - double operationalCost_l = overallCost_l - investCost_l; - - bool optimality_l = (status_l == SOLVER_STATUS::OPTIMAL); - - Output::SolutionData sol_infos; - sol_infos.nbWeeks_p = static_cast(input.size()); - - sol_infos.solution.lb = overallCost_l; - sol_infos.solution.ub = overallCost_l; - sol_infos.solution.investment_cost = investCost_l; - sol_infos.solution.operational_cost = operationalCost_l; - sol_infos.solution.overall_cost = overallCost_l; - - Output::CandidatesVec candidates_vec; - for (const auto &pairNameValue_l : x0) - { - Output::CandidateData candidate_data; - candidate_data.name = pairNameValue_l.first; - candidate_data.invest = pairNameValue_l.second; - candidate_data.min = -1; - candidate_data.max = -1; - candidates_vec.push_back(candidate_data); - } - sol_infos.solution.candidates = candidates_vec; - if (optimality_l) - { - sol_infos.problem_status = "OPTIMAL"; - } - else - { - sol_infos.problem_status = "ERROR"; - } +#include "Timer.h" +#include "glog/logging.h" +#include "helpers/Path.h" - _writer->update_solution(sol_infos); - _writer->dump(); +MergeMPS::MergeMPS(const MergeMPSOptions &options, Logger &logger, + Writer writer) + : _options(options), _logger(logger), _writer(writer) {} + +void MergeMPS::launch() { + auto structure_path( + (Path(_options.INPUTROOT) / _options.STRUCTURE_FILE).get_str()); + CouplingMap input = + build_input(structure_path, _options.SLAVE_NUMBER, _options.MASTER_NAME); + + SolverFactory factory; + std::string solver_to_use = + (_options.SOLVER_NAME == "COIN") ? "CBC" : _options.SOLVER_NAME; + SolverAbstract::Ptr mergedSolver_l = factory.create_solver(solver_to_use); + mergedSolver_l->init(); + mergedSolver_l->set_output_log_level(_options.LOG_LEVEL); + + int nslaves = input.size() - 1; + CouplingMap x_mps_id; + int cntProblems_l(0); + + LOG(INFO) << "Merging problems..." << std::endl; + for (auto const &kvp : input) { + auto problem_name( + (Path(_options.INPUTROOT) / (kvp.first + MPS_SUFFIX)).get_str()); + + SolverAbstract::Ptr solver_l = factory.create_solver(solver_to_use); + solver_l->init(); + solver_l->set_output_log_level(_options.LOG_LEVEL); + solver_l->read_prob_mps(problem_name); + + if (kvp.first != _options.MASTER_NAME) { + int mps_ncols(solver_l->get_ncols()); + + DblVector o(mps_ncols); + IntVector sequence(mps_ncols); + for (int i(0); i < mps_ncols; ++i) { + sequence[i] = i; + } + solver_get_obj_func_coeffs(solver_l, o, 0, mps_ncols - 1); + double const weigth = slave_weight(nslaves, kvp.first); + for (auto &c : o) { + c *= weigth; + } + solver_l->chg_obj(sequence, o); + } + StandardLp lpData(solver_l); + std::string varPrefix_l = "prob" + std::to_string(cntProblems_l) + "_"; + + lpData.append_in(mergedSolver_l, varPrefix_l); + + for (auto const &x : kvp.second) { + int col_index = mergedSolver_l->get_col_index(varPrefix_l + x.first); + if (col_index == -1) { + std::cerr << "missing variable " << x.first << " in " << kvp.first + << " supposedly renamed to " << varPrefix_l + x.first << "."; + mergedSolver_l->write_prob_lp( + (Path(_options.OUTPUTROOT) / "mergeError.lp").get_str()); + mergedSolver_l->write_prob_mps( + (Path(_options.OUTPUTROOT) / ("mergeError" + MPS_SUFFIX)) + .get_str()); + std::exit(1); + } else { + x_mps_id[x.first][kvp.first] = col_index; + } + } + + ++cntProblems_l; + } + + IntVector mstart; + IntVector cindex; + DblVector values; + int nrows(0); + int neles(0); + size_t neles_reserve(0); + size_t nrows_reserve(0); + for (auto const &kvp : x_mps_id) { + neles_reserve += kvp.second.size() * (kvp.second.size() - 1); + nrows_reserve += kvp.second.size() * (kvp.second.size() - 1) / 2; + } + LOG(INFO) << "About to add " << nrows_reserve << " coupling constraints" + << std::endl; + values.reserve(neles_reserve); + cindex.reserve(neles_reserve); + mstart.reserve(nrows_reserve + 1); + + // adding coupling constraints + for (auto const &kvp : x_mps_id) { + std::string const var_name(kvp.first); + LOG(INFO) << var_name << std::endl; + bool is_first(true); + int id1(-1); + std::string first_mps; + for (auto const &mps : kvp.second) { + if (is_first) { + is_first = false; + first_mps = mps.first; + id1 = mps.second; + } else { + int id2 = mps.second; + mstart.push_back(neles); + cindex.push_back(id1); + values.push_back(1); + ++neles; + + cindex.push_back(id2); + values.push_back(-1); + ++neles; + ++nrows; + } + } + } + mstart.push_back(neles); + + DblVector rhs(nrows, 0); + CharVector sense(nrows, 'E'); + solver_addrows(mergedSolver_l, sense, rhs, {}, mstart, cindex, values); + + LOG(INFO) << "Problems merged." << std::endl; + LOG(INFO) << "Writting mps file" << std::endl; + mergedSolver_l->write_prob_mps( + (Path(_options.OUTPUTROOT) / ("log_merged" + MPS_SUFFIX)).get_str()); + LOG(INFO) << "Writting lp file" << std::endl; + mergedSolver_l->write_prob_lp( + (Path(_options.OUTPUTROOT) / "log_merged.lp").get_str()); + + mergedSolver_l->set_threads(16); + + _logger->display_message("Solving..."); + Timer timer; + int status_l = 0; + if (mergedSolver_l->get_n_integer_vars() > 0) { + status_l = mergedSolver_l->solve_mip(); + } else { + status_l = mergedSolver_l->solve_lp(); + } + + _logger->log_total_duration(timer.elapsed()); + + Point x0; + DblVector ptr(mergedSolver_l->get_ncols()); + double investCost_l(0); + if (mergedSolver_l->get_n_integer_vars() > 0) { + mergedSolver_l->get_mip_sol(ptr.data()); + } else { + mergedSolver_l->get_lp_sol(ptr.data(), nullptr, nullptr); + } + + std::vector obj_coef(mergedSolver_l->get_ncols()); + mergedSolver_l->get_obj(obj_coef.data(), 0, mergedSolver_l->get_ncols() - 1); + for (auto const &pairNameId : input[_options.MASTER_NAME]) { + int varIndexInMerged_l = x_mps_id[pairNameId.first][_options.MASTER_NAME]; + x0[pairNameId.first] = ptr[varIndexInMerged_l]; + investCost_l += x0[pairNameId.first] * obj_coef[varIndexInMerged_l]; + } + + double overallCost_l; + if (mergedSolver_l->get_n_integer_vars() > 0) { + overallCost_l = mergedSolver_l->get_mip_value(); + } else { + overallCost_l = mergedSolver_l->get_lp_value(); + } + double operationalCost_l = overallCost_l - investCost_l; + + bool optimality_l = (status_l == SOLVER_STATUS::OPTIMAL); + + Output::SolutionData sol_infos; + sol_infos.nbWeeks_p = static_cast(input.size()); + + sol_infos.solution.lb = overallCost_l; + sol_infos.solution.ub = overallCost_l; + sol_infos.solution.investment_cost = investCost_l; + sol_infos.solution.operational_cost = operationalCost_l; + sol_infos.solution.overall_cost = overallCost_l; + + Output::CandidatesVec candidates_vec; + for (const auto &pairNameValue_l : x0) { + Output::CandidateData candidate_data; + candidate_data.name = pairNameValue_l.first; + candidate_data.invest = pairNameValue_l.second; + candidate_data.min = -1; + candidate_data.max = -1; + candidates_vec.push_back(candidate_data); + } + sol_infos.solution.candidates = candidates_vec; + if (optimality_l) { + sol_infos.problem_status = "OPTIMAL"; + } else { + sol_infos.problem_status = "ERROR"; + } + + _writer->update_solution(sol_infos); + _writer->dump(); } /*! @@ -224,19 +207,13 @@ void MergeMPS::launch() * * \param name : slave name */ -double MergeMPS::slave_weight(int nslaves, std::string const &name) const -{ - if (_options.SLAVE_WEIGHT == SLAVE_WEIGHT_UNIFORM_CST_STR) - { - return 1 / static_cast(nslaves); - } - else if (_options.SLAVE_WEIGHT == SLAVE_WEIGHT_CST_STR) - { - double const weight(_options.SLAVE_WEIGHT_VALUE); - return 1 / weight; - } - else - { - return _options.weights.find(name)->second; - } +double MergeMPS::slave_weight(int nslaves, std::string const &name) const { + if (_options.SLAVE_WEIGHT == SLAVE_WEIGHT_UNIFORM_CST_STR) { + return 1 / static_cast(nslaves); + } else if (_options.SLAVE_WEIGHT == SLAVE_WEIGHT_CST_STR) { + double const weight(_options.SLAVE_WEIGHT_VALUE); + return 1 / weight; + } else { + return _options.weights.find(name)->second; + } } \ No newline at end of file diff --git a/src/cpp/benders/merge_mps/include/MergeMPS.h b/src/cpp/benders/merge_mps/include/MergeMPS.h index 2fd9e868a..43324d782 100644 --- a/src/cpp/benders/merge_mps/include/MergeMPS.h +++ b/src/cpp/benders/merge_mps/include/MergeMPS.h @@ -1,227 +1,241 @@ #pragma once -#include "common.h" #include "WriterFactories.h" +#include "common.h" #include "logger/User.h" - #include "solver_utils.h" -enum Attribute -{ - INT_VALUE, - INT_VECTOR, - CHAR_VECTOR, - DBL_VECTOR, - MAX_ATTRIBUTE +enum Attribute { + INT_VALUE, + INT_VECTOR, + CHAR_VECTOR, + DBL_VECTOR, + MAX_ATTRIBUTE }; -enum IntAttribute -{ - NROWS, - NCOLS, - NELES, - MAX_INT_ATTRIBUTE -}; +enum IntAttribute { NROWS, NCOLS, NELES, MAX_INT_ATTRIBUTE }; -enum IntVectorAttribute -{ - MSTART, - MINDEX, - MAX_INT_VECTOR_ATTRIBUTE, +enum IntVectorAttribute { + MSTART, + MINDEX, + MAX_INT_VECTOR_ATTRIBUTE, }; -enum CharVectorAttribute -{ - ROWTYPE, - COLTYPE, - MAX_CHAR_VECTOR_ATTRIBUTE +enum CharVectorAttribute { ROWTYPE, COLTYPE, MAX_CHAR_VECTOR_ATTRIBUTE }; + +enum DblVectorAttribute { + MVALUE, + RHS, + RANGE, + OBJ, + LB, + UB, + MAX_DBL_VECTOR_ATTRIBUTE }; - -enum DblVectorAttribute -{ - MVALUE, - RHS, - RANGE, - OBJ, - LB, - UB, - MAX_DBL_VECTOR_ATTRIBUTE -}; -typedef std::tuple, std::vector, std::vector> raw_standard_lp_data; - -class StandardLp -{ -private: - std::vector _colNames; - -public: - // to be used in boost serialization for mpi transfer - raw_standard_lp_data _data; - static size_t appendCNT; - -public: - void init() - { - initialise_int_values_with_zeros(); - initialise_int_vectors(); - initialise_char_vectors(); - initialise_dbl_vectors(); - } - - StandardLp(SolverAbstract::Ptr solver_p) - { - init(); - - int ncols = solver_p->get_ncols(); - int nrows = solver_p->get_nrows(); - int nelems = solver_p->get_nelems(); - - std::get(_data)[IntAttribute::NCOLS] = ncols; - std::get(_data)[IntAttribute::NROWS] = nrows; - std::get(_data)[IntAttribute::NELES] = nelems; - - _colNames = solver_p->get_col_names(0, ncols - 1); - - std::get(_data)[IntVectorAttribute::MSTART].clear(); - std::get(_data)[IntVectorAttribute::MSTART].resize(nrows + 1); - - std::get(_data)[IntVectorAttribute::MINDEX].clear(); - std::get(_data)[IntVectorAttribute::MINDEX].resize(nelems); - - std::get(_data)[CharVectorAttribute::COLTYPE].clear(); - std::get(_data)[CharVectorAttribute::COLTYPE].resize(ncols); - - std::get(_data)[CharVectorAttribute::ROWTYPE].clear(); - std::get(_data)[CharVectorAttribute::ROWTYPE].resize(nrows); - - std::get(_data)[DblVectorAttribute::MVALUE].clear(); - std::get(_data)[DblVectorAttribute::MVALUE].resize(nelems); - - std::get(_data)[DblVectorAttribute::RHS].clear(); - std::get(_data)[DblVectorAttribute::RHS].resize(nrows); - - // Range constraint don't exist in a sparse matrix formulation - std::get(_data)[DblVectorAttribute::RANGE].clear(); - std::get(_data)[DblVectorAttribute::RANGE].resize(nrows); - - std::get(_data)[DblVectorAttribute::OBJ].clear(); - std::get(_data)[DblVectorAttribute::OBJ].resize(ncols); - - std::get(_data)[DblVectorAttribute::LB].clear(); - std::get(_data)[DblVectorAttribute::LB].resize(ncols); - - std::get(_data)[DblVectorAttribute::UB].clear(); - std::get(_data)[DblVectorAttribute::UB].resize(ncols); - - solver_getrows(solver_p, - std::get(_data)[IntVectorAttribute::MSTART], - std::get(_data)[IntVectorAttribute::MINDEX], - std::get(_data)[DblVectorAttribute::MVALUE], - 0, - std::get(_data)[IntAttribute::NROWS] - 1); - - solver_getrowtype(solver_p, - std::get(_data)[CharVectorAttribute::ROWTYPE], - 0, - std::get(_data)[IntAttribute::NROWS] - 1); - - solver_getrhs(solver_p, - std::get(_data)[DblVectorAttribute::RHS], - 0, - std::get(_data)[IntAttribute::NROWS] - 1); - - solver_getcolinfo(solver_p, - std::get(_data)[CharVectorAttribute::COLTYPE], - std::get(_data)[DblVectorAttribute::LB], - std::get(_data)[DblVectorAttribute::UB], - 0, - std::get(_data)[IntAttribute::NCOLS] - 1); - - solver_get_obj_func_coeffs(solver_p, - std::get(_data)[DblVectorAttribute::OBJ], - 0, - std::get(_data)[IntAttribute::NCOLS] - 1); - - assert(std::get(_data)[IntVectorAttribute::MSTART].size() == 1 + std::get(_data)[IntAttribute::NROWS]); - - assert(std::get(_data)[CharVectorAttribute::COLTYPE].size() == std::get(_data)[IntAttribute::NCOLS]); - assert(std::get(_data)[CharVectorAttribute::ROWTYPE].size() == std::get(_data)[IntAttribute::NROWS]); - - assert(std::get(_data)[DblVectorAttribute::MVALUE].size() == std::get(_data)[IntAttribute::NELES]); - assert(std::get(_data)[DblVectorAttribute::RHS].size() == std::get(_data)[IntAttribute::NROWS]); - - assert(std::get(_data)[DblVectorAttribute::OBJ].size() == std::get(_data)[IntAttribute::NCOLS]); - assert(std::get(_data)[DblVectorAttribute::LB].size() == std::get(_data)[IntAttribute::NCOLS]); - assert(std::get(_data)[DblVectorAttribute::UB].size() == std::get(_data)[IntAttribute::NCOLS]); - } - - int append_in(SolverAbstract::Ptr containingSolver_p, std::string const &prefix_p = "") const - { - - // simply increment the columns indices - IntVector newmindex(std::get(_data)[IntVectorAttribute::MINDEX]); - int nbExistingCols(containingSolver_p->get_ncols()); - for (auto &i : newmindex) - { - i += nbExistingCols; - } - - // rename variables - std::string prefix_l = (prefix_p != "") ? prefix_p : ("prob" + std::to_string(appendCNT)); - std::vector newNames; - newNames.resize(_colNames.size()); - std::transform(_colNames.begin(), _colNames.end(), newNames.begin(), - [&prefix_l](std::string varName_p) -> std::string - { return prefix_l + varName_p; }); - - std::vector mstart(std::get(_data)[IntAttribute::NCOLS], 0); - solver_addcols(containingSolver_p, - std::get(_data)[DblVectorAttribute::OBJ], - mstart, IntVector(0, 0), DblVector(0, 0.0), - std::get(_data)[DblVectorAttribute::LB], - std::get(_data)[DblVectorAttribute::UB], - std::get(_data)[CharVectorAttribute::COLTYPE], - newNames); - - solver_addrows(containingSolver_p, - std::get(_data)[CharVectorAttribute::ROWTYPE], - std::get(_data)[DblVectorAttribute::RHS], - {}, - std::get(_data)[IntVectorAttribute::MSTART], - newmindex, - std::get(_data)[DblVectorAttribute::MVALUE]); - - ++appendCNT; - - return nbExistingCols; - } - -private: - void initialise_int_values_with_zeros() - { - std::get(_data).assign(IntAttribute::MAX_INT_ATTRIBUTE, 0); - } - void initialise_int_vectors() - { - std::get(_data).assign(IntVectorAttribute::MAX_INT_VECTOR_ATTRIBUTE, IntVector()); - } - void initialise_char_vectors() - { - std::get(_data).assign(CharVectorAttribute::MAX_CHAR_VECTOR_ATTRIBUTE, CharVector()); - } - void initialise_dbl_vectors() - { - std::get(_data).assign(DblVectorAttribute::MAX_DBL_VECTOR_ATTRIBUTE, DblVector()); - } +typedef std::tuple, std::vector, + std::vector> + raw_standard_lp_data; + +class StandardLp { + private: + std::vector _colNames; + + public: + // to be used in boost serialization for mpi transfer + raw_standard_lp_data _data; + static size_t appendCNT; + + public: + void init() { + initialise_int_values_with_zeros(); + initialise_int_vectors(); + initialise_char_vectors(); + initialise_dbl_vectors(); + } + + StandardLp(SolverAbstract::Ptr solver_p) { + init(); + + int ncols = solver_p->get_ncols(); + int nrows = solver_p->get_nrows(); + int nelems = solver_p->get_nelems(); + + std::get(_data)[IntAttribute::NCOLS] = ncols; + std::get(_data)[IntAttribute::NROWS] = nrows; + std::get(_data)[IntAttribute::NELES] = nelems; + + _colNames = solver_p->get_col_names(0, ncols - 1); + + std::get(_data)[IntVectorAttribute::MSTART].clear(); + std::get(_data)[IntVectorAttribute::MSTART].resize( + nrows + 1); + + std::get(_data)[IntVectorAttribute::MINDEX].clear(); + std::get(_data)[IntVectorAttribute::MINDEX].resize( + nelems); + + std::get(_data)[CharVectorAttribute::COLTYPE] + .clear(); + std::get(_data)[CharVectorAttribute::COLTYPE] + .resize(ncols); + + std::get(_data)[CharVectorAttribute::ROWTYPE] + .clear(); + std::get(_data)[CharVectorAttribute::ROWTYPE] + .resize(nrows); + + std::get(_data)[DblVectorAttribute::MVALUE].clear(); + std::get(_data)[DblVectorAttribute::MVALUE].resize( + nelems); + + std::get(_data)[DblVectorAttribute::RHS].clear(); + std::get(_data)[DblVectorAttribute::RHS].resize( + nrows); + + // Range constraint don't exist in a sparse matrix formulation + std::get(_data)[DblVectorAttribute::RANGE].clear(); + std::get(_data)[DblVectorAttribute::RANGE].resize( + nrows); + + std::get(_data)[DblVectorAttribute::OBJ].clear(); + std::get(_data)[DblVectorAttribute::OBJ].resize( + ncols); + + std::get(_data)[DblVectorAttribute::LB].clear(); + std::get(_data)[DblVectorAttribute::LB].resize( + ncols); + + std::get(_data)[DblVectorAttribute::UB].clear(); + std::get(_data)[DblVectorAttribute::UB].resize( + ncols); + + solver_getrows( + solver_p, + std::get(_data)[IntVectorAttribute::MSTART], + std::get(_data)[IntVectorAttribute::MINDEX], + std::get(_data)[DblVectorAttribute::MVALUE], 0, + std::get(_data)[IntAttribute::NROWS] - 1); + + solver_getrowtype( + solver_p, + std::get(_data)[CharVectorAttribute::ROWTYPE], + 0, std::get(_data)[IntAttribute::NROWS] - 1); + + solver_getrhs( + solver_p, + std::get(_data)[DblVectorAttribute::RHS], 0, + std::get(_data)[IntAttribute::NROWS] - 1); + + solver_getcolinfo( + solver_p, + std::get(_data)[CharVectorAttribute::COLTYPE], + std::get(_data)[DblVectorAttribute::LB], + std::get(_data)[DblVectorAttribute::UB], 0, + std::get(_data)[IntAttribute::NCOLS] - 1); + + solver_get_obj_func_coeffs( + solver_p, + std::get(_data)[DblVectorAttribute::OBJ], 0, + std::get(_data)[IntAttribute::NCOLS] - 1); + + assert(std::get(_data)[IntVectorAttribute::MSTART] + .size() == + 1 + std::get(_data)[IntAttribute::NROWS]); + + assert(std::get(_data)[CharVectorAttribute::COLTYPE] + .size() == + std::get(_data)[IntAttribute::NCOLS]); + assert(std::get(_data)[CharVectorAttribute::ROWTYPE] + .size() == + std::get(_data)[IntAttribute::NROWS]); + + assert(std::get(_data)[DblVectorAttribute::MVALUE] + .size() == + std::get(_data)[IntAttribute::NELES]); + assert(std::get(_data)[DblVectorAttribute::RHS] + .size() == + std::get(_data)[IntAttribute::NROWS]); + + assert(std::get(_data)[DblVectorAttribute::OBJ] + .size() == + std::get(_data)[IntAttribute::NCOLS]); + assert( + std::get(_data)[DblVectorAttribute::LB].size() == + std::get(_data)[IntAttribute::NCOLS]); + assert( + std::get(_data)[DblVectorAttribute::UB].size() == + std::get(_data)[IntAttribute::NCOLS]); + } + + int append_in(SolverAbstract::Ptr containingSolver_p, + std::string const &prefix_p = "") const { + // simply increment the columns indices + IntVector newmindex( + std::get(_data)[IntVectorAttribute::MINDEX]); + int nbExistingCols(containingSolver_p->get_ncols()); + for (auto &i : newmindex) { + i += nbExistingCols; + } + + // rename variables + std::string prefix_l = + (prefix_p != "") ? prefix_p : ("prob" + std::to_string(appendCNT)); + std::vector newNames; + newNames.resize(_colNames.size()); + std::transform(_colNames.begin(), _colNames.end(), newNames.begin(), + [&prefix_l](std::string varName_p) -> std::string { + return prefix_l + varName_p; + }); + + std::vector mstart( + std::get(_data)[IntAttribute::NCOLS], 0); + solver_addcols( + containingSolver_p, + std::get(_data)[DblVectorAttribute::OBJ], mstart, + IntVector(0, 0), DblVector(0, 0.0), + std::get(_data)[DblVectorAttribute::LB], + std::get(_data)[DblVectorAttribute::UB], + std::get(_data)[CharVectorAttribute::COLTYPE], + newNames); + + solver_addrows( + containingSolver_p, + std::get(_data)[CharVectorAttribute::ROWTYPE], + std::get(_data)[DblVectorAttribute::RHS], {}, + std::get(_data)[IntVectorAttribute::MSTART], + newmindex, + std::get(_data)[DblVectorAttribute::MVALUE]); + + ++appendCNT; + + return nbExistingCols; + } + + private: + void initialise_int_values_with_zeros() { + std::get(_data).assign( + IntAttribute::MAX_INT_ATTRIBUTE, 0); + } + void initialise_int_vectors() { + std::get(_data).assign( + IntVectorAttribute::MAX_INT_VECTOR_ATTRIBUTE, IntVector()); + } + void initialise_char_vectors() { + std::get(_data).assign( + CharVectorAttribute::MAX_CHAR_VECTOR_ATTRIBUTE, CharVector()); + } + void initialise_dbl_vectors() { + std::get(_data).assign( + DblVectorAttribute::MAX_DBL_VECTOR_ATTRIBUTE, DblVector()); + } }; -class MergeMPS -{ -public: - MergeMPS(const MergeMPSOptions &options, Logger &logger, Writer writer); - void launch(); - double slave_weight(int nslaves, std::string const &name) const; +class MergeMPS { + public: + MergeMPS(const MergeMPSOptions &options, Logger &logger, Writer writer); + void launch(); + double slave_weight(int nslaves, std::string const &name) const; - MergeMPSOptions _options; - Logger _logger; - Writer _writer; + MergeMPSOptions _options; + Logger _logger; + Writer _writer; }; diff --git a/src/cpp/benders/output/Clock.cpp b/src/cpp/benders/output/Clock.cpp index 4d2c5e2ca..15cab4746 100644 --- a/src/cpp/benders/output/Clock.cpp +++ b/src/cpp/benders/output/Clock.cpp @@ -1,11 +1,9 @@ #include "Clock.h" -#include -#include +#include +#include -std::time_t Clock::getTime() -{ - std::time_t beginTime = std::time(nullptr); - return beginTime; +std::time_t Clock::getTime() { + std::time_t beginTime = std::time(nullptr); + return beginTime; } - diff --git a/src/cpp/benders/output/JsonWriter.cpp b/src/cpp/benders/output/JsonWriter.cpp index c44fa2804..1166a10d3 100644 --- a/src/cpp/benders/output/JsonWriter.cpp +++ b/src/cpp/benders/output/JsonWriter.cpp @@ -1,142 +1,142 @@ #include "JsonWriter.h" -#include "config.h" -#include + #include +#include -namespace clock_utils -{ - std::string timeToStr(const std::time_t &time_p) - { - struct tm local_time; - localtime_platform(time_p, local_time); - // localtime_r(&time_p, &local_time); // Compliant - const char *FORMAT = "%d-%m-%Y %H:%M:%S"; - char buffer_l[100]; - strftime(buffer_l, sizeof(buffer_l), FORMAT, &local_time); - std::string strTime_l(buffer_l); - - return strTime_l; - } +#include "config.h" + +namespace clock_utils { +std::string timeToStr(const std::time_t &time_p) { + struct tm local_time; + localtime_platform(time_p, local_time); + // localtime_r(&time_p, &local_time); // Compliant + const char *FORMAT = "%d-%m-%Y %H:%M:%S"; + char buffer_l[100]; + strftime(buffer_l, sizeof(buffer_l), FORMAT, &local_time); + std::string strTime_l(buffer_l); + + return strTime_l; +} +} // namespace clock_utils +namespace Output { +JsonWriter::JsonWriter(std::shared_ptr p_clock, + const std::string &json_filename) + : _clock(p_clock), _filename(json_filename) {} + +void JsonWriter::initialize() { + updateBeginTime(); + dump(); } -namespace Output -{ - JsonWriter::JsonWriter(std::shared_ptr p_clock, const std::string &json_filename) : _clock(p_clock), _filename(json_filename) {} - - void JsonWriter::initialize() - { - updateBeginTime(); - dump(); - } - void JsonWriter::updateBeginTime() - { - _output[BEGIN_C] = clock_utils::timeToStr(_clock->getTime()); - } +void JsonWriter::updateBeginTime() { + _output[BEGIN_C] = clock_utils::timeToStr(_clock->getTime()); +} - void JsonWriter::updateEndTime() - { - _output[END_C] = clock_utils::timeToStr(_clock->getTime()); - } +void JsonWriter::updateEndTime() { + _output[END_C] = clock_utils::timeToStr(_clock->getTime()); +} - void JsonWriter::write_iterations(const IterationsData &iterations_data) - { - _output[NBWEEKS_C] = iterations_data.nbWeeks_p; - _output[DURATION_C] = iterations_data.elapsed_time; - - // Iterations - size_t iterCnt_l(0); - for (const auto &iter : iterations_data.iters) - { - ++iterCnt_l; - - std::string strIterCnt_l(std::to_string(iterCnt_l)); - _output[ITERATIONS_C][strIterCnt_l][DURATION_C] = iter.time; - _output[ITERATIONS_C][strIterCnt_l][LB_C] = iter.lb; - _output[ITERATIONS_C][strIterCnt_l][UB_C] = iter.ub; - _output[ITERATIONS_C][strIterCnt_l][BEST_UB_C] = iter.best_ub; - _output[ITERATIONS_C][strIterCnt_l][OPTIMALITY_GAP_C] = iter.optimality_gap; - _output[ITERATIONS_C][strIterCnt_l][RELATIVE_GAP_C] = iter.relative_gap; - _output[ITERATIONS_C][strIterCnt_l][INVESTMENT_COST_C] = iter.investment_cost; - _output[ITERATIONS_C][strIterCnt_l][OPERATIONAL_COST_C] = iter.operational_cost; - _output[ITERATIONS_C][strIterCnt_l][OVERALL_COST_C] = iter.overall_cost; - - Json::Value vectCandidates_l(Json::arrayValue); - for (const auto &candidate : iter.candidates) - { - Json::Value candidate_l; - candidate_l[NAME_C] = candidate.name; - candidate_l[INVEST_C] = candidate.invest; - candidate_l[MIN_C] = candidate.min; - candidate_l[MAX_C] = candidate.max; - vectCandidates_l.append(candidate_l); - } - _output[ITERATIONS_C][strIterCnt_l][CANDIDATES_C] = vectCandidates_l; - } - - // solution - _output[SOLUTION_C][ITERATION_C] = iterations_data.solution_data.best_it; - _output[SOLUTION_C][INVESTMENT_COST_C] = iterations_data.solution_data.solution.investment_cost; - _output[SOLUTION_C][OPERATIONAL_COST_C] = iterations_data.solution_data.solution.operational_cost; - _output[SOLUTION_C][OVERALL_COST_C] = iterations_data.solution_data.solution.overall_cost; - - for (const auto &candidate : iterations_data.solution_data.solution.candidates) - { - _output[SOLUTION_C][VALUES_C][candidate.name] = candidate.invest; - } - - _output[SOLUTION_C][OPTIMALITY_GAP_C] = iterations_data.solution_data.solution.optimality_gap; - _output[SOLUTION_C][RELATIVE_GAP_C] = iterations_data.solution_data.solution.relative_gap; - - _output[SOLUTION_C][STOPPING_CRITERION_C] = iterations_data.solution_data.stopping_criterion; - _output[SOLUTION_C][PROBLEM_STATUS_C] = iterations_data.solution_data.problem_status; +void JsonWriter::write_iterations(const IterationsData &iterations_data) { + _output[NBWEEKS_C] = iterations_data.nbWeeks_p; + _output[DURATION_C] = iterations_data.elapsed_time; + + // Iterations + size_t iterCnt_l(0); + for (const auto &iter : iterations_data.iters) { + ++iterCnt_l; + + std::string strIterCnt_l(std::to_string(iterCnt_l)); + _output[ITERATIONS_C][strIterCnt_l][DURATION_C] = iter.time; + _output[ITERATIONS_C][strIterCnt_l][LB_C] = iter.lb; + _output[ITERATIONS_C][strIterCnt_l][UB_C] = iter.ub; + _output[ITERATIONS_C][strIterCnt_l][BEST_UB_C] = iter.best_ub; + _output[ITERATIONS_C][strIterCnt_l][OPTIMALITY_GAP_C] = iter.optimality_gap; + _output[ITERATIONS_C][strIterCnt_l][RELATIVE_GAP_C] = iter.relative_gap; + _output[ITERATIONS_C][strIterCnt_l][INVESTMENT_COST_C] = + iter.investment_cost; + _output[ITERATIONS_C][strIterCnt_l][OPERATIONAL_COST_C] = + iter.operational_cost; + _output[ITERATIONS_C][strIterCnt_l][OVERALL_COST_C] = iter.overall_cost; + + Json::Value vectCandidates_l(Json::arrayValue); + for (const auto &candidate : iter.candidates) { + Json::Value candidate_l; + candidate_l[NAME_C] = candidate.name; + candidate_l[INVEST_C] = candidate.invest; + candidate_l[MIN_C] = candidate.min; + candidate_l[MAX_C] = candidate.max; + vectCandidates_l.append(candidate_l); } + _output[ITERATIONS_C][strIterCnt_l][CANDIDATES_C] = vectCandidates_l; + } + + // solution + _output[SOLUTION_C][ITERATION_C] = iterations_data.solution_data.best_it; + _output[SOLUTION_C][INVESTMENT_COST_C] = + iterations_data.solution_data.solution.investment_cost; + _output[SOLUTION_C][OPERATIONAL_COST_C] = + iterations_data.solution_data.solution.operational_cost; + _output[SOLUTION_C][OVERALL_COST_C] = + iterations_data.solution_data.solution.overall_cost; + + for (const auto &candidate : + iterations_data.solution_data.solution.candidates) { + _output[SOLUTION_C][VALUES_C][candidate.name] = candidate.invest; + } + + _output[SOLUTION_C][OPTIMALITY_GAP_C] = + iterations_data.solution_data.solution.optimality_gap; + _output[SOLUTION_C][RELATIVE_GAP_C] = + iterations_data.solution_data.solution.relative_gap; + + _output[SOLUTION_C][STOPPING_CRITERION_C] = + iterations_data.solution_data.stopping_criterion; + _output[SOLUTION_C][PROBLEM_STATUS_C] = + iterations_data.solution_data.problem_status; +} - void JsonWriter::update_solution(const SolutionData &solution_data) - { - _output[NBWEEKS_C] = solution_data.nbWeeks_p; - - _output[SOLUTION_C][INVESTMENT_COST_C] = solution_data.solution.investment_cost; - _output[SOLUTION_C][OPERATIONAL_COST_C] = solution_data.solution.operational_cost; - _output[SOLUTION_C][OVERALL_COST_C] = solution_data.solution.overall_cost; - _output[SOLUTION_C][LB_C] = solution_data.solution.lb; - _output[SOLUTION_C][UB_C] = solution_data.solution.ub; - _output[SOLUTION_C][OPTIMALITY_GAP_C] = solution_data.solution.optimality_gap; - _output[SOLUTION_C][RELATIVE_GAP_C] = solution_data.solution.relative_gap; - - _output[SOLUTION_C][PROBLEM_STATUS_C] = solution_data.problem_status; - _output[SOLUTION_C][STOPPING_CRITERION_C] = solution_data.stopping_criterion; - for (const auto &candidate : solution_data.solution.candidates) - { - _output[SOLUTION_C][VALUES_C][candidate.name] = candidate.invest; - } - - updateEndTime(); - } +void JsonWriter::update_solution(const SolutionData &solution_data) { + _output[NBWEEKS_C] = solution_data.nbWeeks_p; + + _output[SOLUTION_C][INVESTMENT_COST_C] = + solution_data.solution.investment_cost; + _output[SOLUTION_C][OPERATIONAL_COST_C] = + solution_data.solution.operational_cost; + _output[SOLUTION_C][OVERALL_COST_C] = solution_data.solution.overall_cost; + _output[SOLUTION_C][LB_C] = solution_data.solution.lb; + _output[SOLUTION_C][UB_C] = solution_data.solution.ub; + _output[SOLUTION_C][OPTIMALITY_GAP_C] = solution_data.solution.optimality_gap; + _output[SOLUTION_C][RELATIVE_GAP_C] = solution_data.solution.relative_gap; + + _output[SOLUTION_C][PROBLEM_STATUS_C] = solution_data.problem_status; + _output[SOLUTION_C][STOPPING_CRITERION_C] = solution_data.stopping_criterion; + for (const auto &candidate : solution_data.solution.candidates) { + _output[SOLUTION_C][VALUES_C][candidate.name] = candidate.invest; + } + + updateEndTime(); +} - /*! - * \brief write the json data into a file - */ - void JsonWriter::dump() - { - _output[ANTARES_C][VERSION_C] = ANTARES_VERSION_TAG; - _output[ANTARES_XPANSION_C][VERSION_C] = PROJECT_VER; - - std::ofstream jsonOut_l(_filename); - if (jsonOut_l) - { - // Output - jsonOut_l << _output << std::endl; - } - else - { - std::cout << "Impossible d'ouvrir le fichier json " << _filename << std::endl; - } - } +/*! + * \brief write the json data into a file + */ +void JsonWriter::dump() { + _output[ANTARES_C][VERSION_C] = ANTARES_VERSION_TAG; + _output[ANTARES_XPANSION_C][VERSION_C] = PROJECT_VER; + + std::ofstream jsonOut_l(_filename); + if (jsonOut_l) { + // Output + jsonOut_l << _output << std::endl; + } else { + std::cout << "Impossible d'ouvrir le fichier json " << _filename + << std::endl; + } +} - void JsonWriter::end_writing(const IterationsData &iterations_data) - { - updateEndTime(); - write_iterations(iterations_data); - dump(); - } -} \ No newline at end of file +void JsonWriter::end_writing(const IterationsData &iterations_data) { + updateEndTime(); + write_iterations(iterations_data); + dump(); +} +} // namespace Output \ No newline at end of file diff --git a/src/cpp/benders/output/VoidWriter.cpp b/src/cpp/benders/output/VoidWriter.cpp index fb76d55fb..bc087e0df 100644 --- a/src/cpp/benders/output/VoidWriter.cpp +++ b/src/cpp/benders/output/VoidWriter.cpp @@ -1,50 +1,43 @@ #include "VoidWriter.h" -namespace Output -{ +namespace Output { - void VoidWriter::updateBeginTime() - { - // keep this method empty - } +void VoidWriter::updateBeginTime() { + // keep this method empty +} - void VoidWriter::updateEndTime() - { - // keep this method empty - } +void VoidWriter::updateEndTime() { + // keep this method empty +} - void VoidWriter::write_iterations(const IterationsData &iterations_data) - { - // keep this method empty - } +void VoidWriter::write_iterations(const IterationsData &iterations_data) { + // keep this method empty +} - void VoidWriter::update_solution(const SolutionData &solution_data) - { - // keep this method empty - } +void VoidWriter::update_solution(const SolutionData &solution_data) { + // keep this method empty +} - /*! - * \brief write a json output with a failure status in solution. If optimization process exits before it ends, this failure will be available as an output. - * - */ - void VoidWriter::write_failure() - { - // keep this method empty - } +/*! + * \brief write a json output with a failure status in solution. If + * optimization process exits before it ends, this failure will be available as + * an output. + * + */ +void VoidWriter::write_failure() { + // keep this method empty +} - /*! - * \brief write the json data into a file - */ - void VoidWriter::dump() - { - // keep this method empty - } - void VoidWriter::initialize() - { - // keep this method empty - } +/*! + * \brief write the json data into a file + */ +void VoidWriter::dump() { + // keep this method empty +} +void VoidWriter::initialize() { + // keep this method empty +} - void VoidWriter::end_writing(const IterationsData &iterations_data) - { - // keep this method empty - } -} \ No newline at end of file +void VoidWriter::end_writing(const IterationsData &iterations_data) { + // keep this method empty +} +} // namespace Output \ No newline at end of file diff --git a/src/cpp/benders/output/include/Clock.h b/src/cpp/benders/output/include/Clock.h index 6230f9e12..87447802c 100644 --- a/src/cpp/benders/output/include/Clock.h +++ b/src/cpp/benders/output/include/Clock.h @@ -3,11 +3,10 @@ #include -class Clock -{ -public: - Clock() = default; - virtual ~Clock() = default; +class Clock { + public: + Clock() = default; + virtual ~Clock() = default; - virtual std::time_t getTime(); + virtual std::time_t getTime(); }; \ No newline at end of file diff --git a/src/cpp/benders/output/include/JsonWriter.h b/src/cpp/benders/output/include/JsonWriter.h index 7ef2f4664..d27982bf7 100644 --- a/src/cpp/benders/output/include/JsonWriter.h +++ b/src/cpp/benders/output/include/JsonWriter.h @@ -1,75 +1,73 @@ #pragma once -#include "OutputWriter.h" -#include "Clock.h" - #include -inline void localtime_platform(const std::time_t &time_p, struct tm &local_time) -{ +#include "Clock.h" +#include "OutputWriter.h" + +inline void localtime_platform(const std::time_t &time_p, + struct tm &local_time) { #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) - localtime_s(&local_time, &time_p); -#else // defined(__unix__) || (__APPLE__) - localtime_r(&time_p, &local_time); + localtime_s(&local_time, &time_p); +#else // defined(__unix__) || (__APPLE__) + localtime_r(&time_p, &local_time); #endif } -namespace clock_utils -{ - std::string timeToStr(const std::time_t &time_p); +namespace clock_utils { +std::string timeToStr(const std::time_t &time_p); } -namespace Output -{ +namespace Output { - /*! - * \class JsonWriter - * \brief JsonWriter class to describe the execuion session of an antares xpansion optimization in a json file - */ - class JsonWriter : public OutputWriter - { - private: - std::shared_ptr _clock; - std::string _filename; - // attributes of the optimization execution - Json::Value _output; +/*! + * \class JsonWriter + * \brief JsonWriter class to describe the execuion session of an antares + * xpansion optimization in a json file + */ +class JsonWriter : public OutputWriter { + private: + std::shared_ptr _clock; + std::string _filename; + // attributes of the optimization execution + Json::Value _output; - /*! - * \brief updates the execution begin time - */ - virtual void updateBeginTime(); + /*! + * \brief updates the execution begin time + */ + virtual void updateBeginTime(); - /*! - * \brief updates the end of execution time - */ - virtual void updateEndTime(); - virtual void write_iterations(const IterationsData &iterations_data); + /*! + * \brief updates the end of execution time + */ + virtual void updateEndTime(); + virtual void write_iterations(const IterationsData &iterations_data); - public: - /*! - * \brief JsonWriter default constructor - */ - JsonWriter() = delete; + public: + /*! + * \brief JsonWriter default constructor + */ + JsonWriter() = delete; - JsonWriter(std::shared_ptr p_clock, const std::string &json_filename); + JsonWriter(std::shared_ptr p_clock, const std::string &json_filename); - /*! - * \brief destructor of class JsonWriter - */ - virtual ~JsonWriter() = default; + /*! + * \brief destructor of class JsonWriter + */ + virtual ~JsonWriter() = default; - virtual void update_solution(const SolutionData &solution_data); + virtual void update_solution(const SolutionData &solution_data); - /*! - * \brief write the json data into a file - */ - virtual void dump(); + /*! + * \brief write the json data into a file + */ + virtual void dump(); - /*! - * \brief initialize outputs - * \param options : set of options used for the optimization - */ - void initialize(); + /*! + * \brief initialize outputs + * \param options : set of options used for the optimization + */ + void initialize(); - void end_writing(const IterationsData &iterations_data); - }; -} \ No newline at end of file + void end_writing(const IterationsData &iterations_data); +}; +} // namespace Output \ No newline at end of file diff --git a/src/cpp/benders/output/include/OutputWriter.h b/src/cpp/benders/output/include/OutputWriter.h index caeac6e28..26bbb309b 100644 --- a/src/cpp/benders/output/include/OutputWriter.h +++ b/src/cpp/benders/output/include/OutputWriter.h @@ -1,128 +1,103 @@ #pragma once +#include #include #include -#include - -namespace Output -{ - // string constantes - const std::string - ANTARES_C("antares"), - VERSION_C("version"), - ANTARES_XPANSION_C("antares_xpansion"), - BEGIN_C("begin"), - END_C("end"), - DURATION_C("duration"), - ITERATIONS_C("iterations"), - BEST_UB_C("best_ub"), - CANDIDATES_C("candidates"), - INVEST_C("invest"), - MAX_C("max"), - MIN_C("min"), - NAME_C("name"), - INVESTMENT_COST_C("investment_cost"), - LB_C("lb"), - OPERATIONAL_COST_C("operational_cost"), - OPTIMALITY_GAP_C("optimality_gap"), - OVERALL_COST_C("overall_cost"), - RELATIVE_GAP_C("relative_gap"), - UB_C("ub"), - NBWEEKS_C("nbWeeks"), - OPTIONS_C("options"), - SOLUTION_C("solution"), - ITERATION_C("iteration"), - PROBLEM_STATUS_C("problem_status"), - STATUS_OPTIMAL_C("OPTIMAL"), - STATUS_ERROR_C("ERROR"), - VALUES_C("values"), - STOPPING_CRITERION_C("stopping_criterion"); - struct CandidateData - { - std::string name; - double invest; - double min; - double max; - }; - typedef std::vector CandidatesVec; - struct Iteration - { - double time; - double lb; - double ub; - double best_ub; - double optimality_gap; - double relative_gap; - double investment_cost; - double operational_cost; - double overall_cost; - CandidatesVec candidates; - }; - typedef std::vector Iterations; - /*! - * \brief struct saves some entries to be later written to the json file - * - * nbWeeks_p : number of the weeks in the study - * solution : solution data as iteration - */ - struct SolutionData - { - Iteration solution; - int nbWeeks_p; - int best_it; - std::string problem_status; - std::string stopping_criterion; - }; - /*! - * \brief struct containing some entries to be later written to the json file - * - * nbWeeks_p : number of the weeks in the study - * bendersTrace_p : trace to be written ie iterations details - * bendersData_p : final benders data to get the best iteration - * min_abs_gap : minimum absolute gap wanted - * min_rel_gap : minimum relative gap wanted - * max_iter : maximum number of iterations - */ - struct IterationsData - { - int nbWeeks_p; - double elapsed_time; - Iterations iters; - SolutionData solution_data; - }; +namespace Output { - /*! - * \class OutputWriter - * \brief OutputWriter class to describe the execuion session of an antares xpansion optimization in a log file - */ - class OutputWriter - { +// string constantes +const std::string ANTARES_C("antares"), VERSION_C("version"), + ANTARES_XPANSION_C("antares_xpansion"), BEGIN_C("begin"), END_C("end"), + DURATION_C("duration"), ITERATIONS_C("iterations"), BEST_UB_C("best_ub"), + CANDIDATES_C("candidates"), INVEST_C("invest"), MAX_C("max"), MIN_C("min"), + NAME_C("name"), INVESTMENT_COST_C("investment_cost"), LB_C("lb"), + OPERATIONAL_COST_C("operational_cost"), OPTIMALITY_GAP_C("optimality_gap"), + OVERALL_COST_C("overall_cost"), RELATIVE_GAP_C("relative_gap"), UB_C("ub"), + NBWEEKS_C("nbWeeks"), OPTIONS_C("options"), SOLUTION_C("solution"), + ITERATION_C("iteration"), PROBLEM_STATUS_C("problem_status"), + STATUS_OPTIMAL_C("OPTIMAL"), STATUS_ERROR_C("ERROR"), VALUES_C("values"), + STOPPING_CRITERION_C("stopping_criterion"); +struct CandidateData { + std::string name; + double invest; + double min; + double max; +}; +typedef std::vector CandidatesVec; +struct Iteration { + double time; + double lb; + double ub; + double best_ub; + double optimality_gap; + double relative_gap; + double investment_cost; + double operational_cost; + double overall_cost; + CandidatesVec candidates; +}; +typedef std::vector Iterations; +/*! + * \brief struct saves some entries to be later written to the json file + * + * nbWeeks_p : number of the weeks in the study + * solution : solution data as iteration + */ +struct SolutionData { + Iteration solution; + int nbWeeks_p; + int best_it; + std::string problem_status; + std::string stopping_criterion; +}; +/*! + * \brief struct containing some entries to be later written to the json file + * + * nbWeeks_p : number of the weeks in the study + * bendersTrace_p : trace to be written ie iterations details + * bendersData_p : final benders data to get the best iteration + * min_abs_gap : minimum absolute gap wanted + * min_rel_gap : minimum relative gap wanted + * max_iter : maximum number of iterations + */ +struct IterationsData { + int nbWeeks_p; + double elapsed_time; + Iterations iters; + SolutionData solution_data; +}; - public: - /*! - * \brief destructor of class OutputWriter - */ - virtual ~OutputWriter() = default; +/*! + * \class OutputWriter + * \brief OutputWriter class to describe the execuion session of an antares + * xpansion optimization in a log file + */ +class OutputWriter { + public: + /*! + * \brief destructor of class OutputWriter + */ + virtual ~OutputWriter() = default; - /*! - * \brief saves some entries to be later written to the json file - * - * \param solution_data containing solution data - */ - virtual void update_solution(const SolutionData &solution_data) = 0; + /*! + * \brief saves some entries to be later written to the json file + * + * \param solution_data containing solution data + */ + virtual void update_solution(const SolutionData &solution_data) = 0; - /*! - * \brief write the log data into a file - */ - virtual void dump() = 0; + /*! + * \brief write the log data into a file + */ + virtual void dump() = 0; - /*! - * \brief initialize outputs - */ - virtual void initialize() = 0; + /*! + * \brief initialize outputs + */ + virtual void initialize() = 0; - virtual void end_writing(const IterationsData &iterations_data) = 0; - }; -} + virtual void end_writing(const IterationsData &iterations_data) = 0; +}; +} // namespace Output using Writer = std::shared_ptr; \ No newline at end of file diff --git a/src/cpp/benders/output/include/VoidWriter.h b/src/cpp/benders/output/include/VoidWriter.h index cbf79bbbc..dd73a0c5b 100644 --- a/src/cpp/benders/output/include/VoidWriter.h +++ b/src/cpp/benders/output/include/VoidWriter.h @@ -3,65 +3,64 @@ #include "OutputWriter.h" -namespace Output -{ - /*! - * \class VoidWriter - * \brief VoidWriter class to describe the execuion session of an antares xpansion optimization - */ - class VoidWriter : public OutputWriter - { +namespace Output { +/*! + * \class VoidWriter + * \brief VoidWriter class to describe the execuion session of an antares + * xpansion optimization + */ +class VoidWriter : public OutputWriter { + public: + /*! + * \brief VoidWriter default constructor + */ + VoidWriter() = default; - public: - /*! - * \brief VoidWriter default constructor - */ - VoidWriter() = default; + /*! + * \brief destructor of class VoidWriter + */ + virtual ~VoidWriter() = default; + virtual void updateBeginTime(); - /*! - * \brief destructor of class VoidWriter - */ - virtual ~VoidWriter() = default; - virtual void updateBeginTime(); + virtual void updateEndTime(); - virtual void updateEndTime(); + /*! + * \brief saves some entries to be later written + * + * \param nbWeeks_p : number of the weeks in the study + * \param bendersTrace_p : trace to be written ie iterations details + * \param bendersData_p : final benders data to get the best iteration + * \param min_abs_gap : minimum absolute gap wanted + * \param min_rel_gap : minimum relative gap wanted + * \param max_iter : maximum number of iterations + */ + virtual void write_iterations(const IterationsData &iterations_data); - /*! - * \brief saves some entries to be later written - * - * \param nbWeeks_p : number of the weeks in the study - * \param bendersTrace_p : trace to be written ie iterations details - * \param bendersData_p : final benders data to get the best iteration - * \param min_abs_gap : minimum absolute gap wanted - * \param min_rel_gap : minimum relative gap wanted - * \param max_iter : maximum number of iterations - */ - virtual void write_iterations(const IterationsData &iterations_data); + /*! + * \brief saves some entries to be later written + * + * \param nbWeeks_p : number of the weeks in the study + * \param lb_p : solution lower bound + * \param ub_p : solution upper bound + * \param investCost_p : investment cost + * \param operationalCost_p : operational cost + * \param overallCost_p : total cost, sum of invest and operational + * \param solution_p : point giving the solution and the candidates + * \param optimality_p : indicates if optimality was reached + */ + virtual void update_solution(const SolutionData &solution_data); - /*! - * \brief saves some entries to be later written - * - * \param nbWeeks_p : number of the weeks in the study - * \param lb_p : solution lower bound - * \param ub_p : solution upper bound - * \param investCost_p : investment cost - * \param operationalCost_p : operational cost - * \param overallCost_p : total cost, sum of invest and operational - * \param solution_p : point giving the solution and the candidates - * \param optimality_p : indicates if optimality was reached - */ - virtual void update_solution(const SolutionData &solution_data); + /*! + * \brief write an a priori errored json output, overwritten if optimization + * ends + */ + virtual void write_failure(); - /*! - * \brief write an a priori errored json output, overwritten if optimization ends - */ - virtual void write_failure(); - - /*! - * \brief write the json data into a file - */ - virtual void dump(); - virtual void initialize(); - virtual void end_writing(const IterationsData &iterations_data); - }; -} \ No newline at end of file + /*! + * \brief write the json data into a file + */ + virtual void dump(); + virtual void initialize(); + virtual void end_writing(const IterationsData &iterations_data); +}; +} // namespace Output \ No newline at end of file diff --git a/src/cpp/exe/benders_mpi/main.cpp b/src/cpp/exe/benders_mpi/main.cpp index 2bc9f829b..78a428779 100644 --- a/src/cpp/exe/benders_mpi/main.cpp +++ b/src/cpp/exe/benders_mpi/main.cpp @@ -1,83 +1,78 @@ // projet_benders.cpp: defines the entry point for the console application // -#include "glog/logging.h" -#include "gflags/gflags.h" -#include "Worker.h" - -#include "Timer.h" -#include "BendersSequential.h" #include "BendersMPI.h" +#include "BendersSequential.h" +#include "LoggerFactories.h" #include "OutputWriter.h" -#include "helpers/Path.h" +#include "Timer.h" +#include "Worker.h" #include "WriterFactories.h" -#include "LoggerFactories.h" +#include "gflags/gflags.h" +#include "glog/logging.h" +#include "helpers/Path.h" -int main(int argc, char **argv) -{ - mpi::environment env(argc, argv); - mpi::communicator world; +int main(int argc, char **argv) { + mpi::environment env(argc, argv); + mpi::communicator world; - // First check usage (options are given) - if (world.rank() == 0) - { - usage(argc); - } + // First check usage (options are given) + if (world.rank() == 0) { + usage(argc); + } - // Read options, needed to have options.OUTPUTROOT - SimulationOptions options(argv[1]); + // Read options, needed to have options.OUTPUTROOT + SimulationOptions options(argv[1]); - BendersBaseOptions benders_options(options.get_benders_options()); + BendersBaseOptions benders_options(options.get_benders_options()); - if (world.rank() > options.SLAVE_NUMBER + 1 && options.SLAVE_NUMBER != -1) - { - std::cout << "You need to have at least one slave by thread" << std::endl; - exit(1); - } + if (world.rank() > options.SLAVE_NUMBER + 1 && options.SLAVE_NUMBER != -1) { + std::cout << "You need to have at least one slave by thread" << std::endl; + exit(1); + } - gflags::ParseCommandLineFlags(&argc, &argv, true); - google::InitGoogleLogging(argv[0]); - auto path_to_log = (Path(options.OUTPUTROOT) / ("bendersmpiLog-rank" + std::to_string(world.rank()) + ".txt.")).get_str(); - google::SetLogDestination(google::GLOG_INFO, path_to_log.c_str()); + gflags::ParseCommandLineFlags(&argc, &argv, true); + google::InitGoogleLogging(argv[0]); + auto path_to_log = + (Path(options.OUTPUTROOT) / + ("bendersmpiLog-rank" + std::to_string(world.rank()) + ".txt.")) + .get_str(); + google::SetLogDestination(google::GLOG_INFO, path_to_log.c_str()); - std::string log_reports_name = (Path(options.OUTPUTROOT) / "reportbendersmpi.txt").get_str(); - Logger logger; - Writer writer; + std::string log_reports_name = + (Path(options.OUTPUTROOT) / "reportbendersmpi.txt").get_str(); + Logger logger; + Writer writer; - if (world.rank() == 0) - { - logger = build_stdout_and_file_logger(log_reports_name); - writer = build_json_writer(options.JSON_FILE); - std::ostringstream oss_l = start_message(options, "mpi"); - LOG(INFO) << oss_l.str() << std::endl; - } - else - { - logger = build_void_logger(); - writer = build_void_writer(); - } + if (world.rank() == 0) { + logger = build_stdout_and_file_logger(log_reports_name); + writer = build_json_writer(options.JSON_FILE); + std::ostringstream oss_l = start_message(options, "mpi"); + LOG(INFO) << oss_l.str() << std::endl; + } else { + logger = build_void_logger(); + writer = build_void_writer(); + } - world.barrier(); - Timer timer; - pBendersBase benders; + world.barrier(); + Timer timer; + pBendersBase benders; - if (world.size() == 1) - { - std::cout << "Sequential launch" << std::endl; - LOG(INFO) << "Size is 1. Launching in sequential mode..." << std::endl; + if (world.size() == 1) { + std::cout << "Sequential launch" << std::endl; + LOG(INFO) << "Size is 1. Launching in sequential mode..." << std::endl; - benders = std::make_shared(benders_options, logger, writer); - } - else - { - benders = std::make_shared(benders_options, logger, writer, env, world); - } + benders = + std::make_shared(benders_options, logger, writer); + } else { + benders = std::make_shared(benders_options, logger, writer, env, + world); + } - benders->launch(); - std::stringstream str; - str << "Optimization results available in : " - << options.JSON_FILE; - logger->display_message(str.str()); - logger->log_total_duration(timer.elapsed()); - return 0; + benders->launch(); + std::stringstream str; + str << "Optimization results available in : " << options.JSON_FILE; + logger->display_message(str.str()); + logger->log_total_duration(timer.elapsed()); + return 0; } diff --git a/src/cpp/exe/benders_sequential/main.cpp b/src/cpp/exe/benders_sequential/main.cpp index 516e9dc85..c9f6d25b0 100644 --- a/src/cpp/exe/benders_sequential/main.cpp +++ b/src/cpp/exe/benders_sequential/main.cpp @@ -1,46 +1,45 @@ // projet_benders.cpp : définit le point d'entrée pour l'application console. // -#include "glog/logging.h" - #include "BendersSequential.h" -#include "SimulationOptions.h" -#include "logger/Master.h" -#include "logger/UserFile.h" -#include "logger/User.h" -#include "OutputWriter.h" #include "JsonWriter.h" -#include "helpers/Path.h" #include "LoggerFactories.h" -#include "WriterFactories.h" +#include "OutputWriter.h" +#include "SimulationOptions.h" #include "Timer.h" +#include "WriterFactories.h" +#include "glog/logging.h" +#include "helpers/Path.h" +#include "logger/Master.h" +#include "logger/User.h" +#include "logger/UserFile.h" -int main(int argc, char **argv) -{ - // options.print(std::cout); - usage(argc); - SimulationOptions options(argv[1]); - BendersBaseOptions benders_options(options.get_benders_options()); - - google::InitGoogleLogging(argv[0]); - auto path_to_log = (Path(options.OUTPUTROOT) / "benderssequentialLog.txt.").get_str(); - google::SetLogDestination(google::GLOG_INFO, path_to_log.c_str()); - - std::ostringstream oss_l = start_message(options, "Sequential"); - LOG(INFO) << oss_l.str() << std::endl; - - const std::string &loggerFileName = (Path(options.OUTPUTROOT) / "reportbenderssequential.txt").get_str(); - Logger logger = build_stdout_and_file_logger(loggerFileName); - Writer writer = build_json_writer(options.JSON_FILE); - Timer timer; - - BendersSequential benders(benders_options, logger, writer); - benders.launch(); - std::stringstream str; - str << "Optimization results available in : " - << options.JSON_FILE; - logger->display_message(str.str()); - logger->log_total_duration(timer.elapsed()); - - return 0; +int main(int argc, char **argv) { + // options.print(std::cout); + usage(argc); + SimulationOptions options(argv[1]); + BendersBaseOptions benders_options(options.get_benders_options()); + + google::InitGoogleLogging(argv[0]); + auto path_to_log = + (Path(options.OUTPUTROOT) / "benderssequentialLog.txt.").get_str(); + google::SetLogDestination(google::GLOG_INFO, path_to_log.c_str()); + + std::ostringstream oss_l = start_message(options, "Sequential"); + LOG(INFO) << oss_l.str() << std::endl; + + const std::string &loggerFileName = + (Path(options.OUTPUTROOT) / "reportbenderssequential.txt").get_str(); + Logger logger = build_stdout_and_file_logger(loggerFileName); + Writer writer = build_json_writer(options.JSON_FILE); + Timer timer; + + BendersSequential benders(benders_options, logger, writer); + benders.launch(); + std::stringstream str; + str << "Optimization results available in : " << options.JSON_FILE; + logger->display_message(str.str()); + logger->log_total_duration(timer.elapsed()); + + return 0; } diff --git a/src/cpp/exe/lpnamer/main.cpp b/src/cpp/exe/lpnamer/main.cpp index 6780d65a2..8b1961ac8 100644 --- a/src/cpp/exe/lpnamer/main.cpp +++ b/src/cpp/exe/lpnamer/main.cpp @@ -9,22 +9,21 @@ * */ -#include +#include #include +#include #include -#include #include "ActiveLinks.h" -#include "LinkProblemsGenerator.h" #include "AdditionalConstraints.h" -#include "LauncherHelpers.h" - -#include "solver_utils.h" +#include "Candidate.h" #include "CandidatesINIReader.h" +#include "LauncherHelpers.h" +#include "LinkProblemsGenerator.h" #include "LinkProfileReader.h" #include "MasterProblemBuilder.h" #include "helpers/Path.h" -#include "Candidate.h" +#include "solver_utils.h" namespace po = boost::program_options; @@ -35,31 +34,25 @@ namespace po = boost::program_options; * \param path String corresponding to a path with mistakes * \return The correct path */ -std::string get_name(std::string const &path) -{ - size_t last_sep(path.find(Path::mSep)); - - if (last_sep == std::string::npos) - { - return path; - } - - while (true) - { - size_t next_sep = path.find(Path::mSep, last_sep + 1); - if (next_sep == std::string::npos) - { - break; - } - else - { - last_sep = next_sep; - } - } - - std::string name(path.substr(last_sep + 1)); - name = name.substr(0, name.size() - 4); - return name; +std::string get_name(std::string const &path) { + size_t last_sep(path.find(Path::mSep)); + + if (last_sep == std::string::npos) { + return path; + } + + while (true) { + size_t next_sep = path.find(Path::mSep, last_sep + 1); + if (next_sep == std::string::npos) { + break; + } else { + last_sep = next_sep; + } + } + + std::string name(path.substr(last_sep + 1)); + name = name.substr(0, name.size() - 4); + return name; } /** @@ -68,60 +61,57 @@ std::string get_name(std::string const &path) * * \param rootPath String corresponding to the path where are located input data * \param links Structure which contains the list of Activelink - * \param couplings map pairs and integer which give the correspondence between optim variable and antares variable - * \return void + * \param couplings map pairs and integer which give the correspondence between + * optim variable and antares variable \return void */ -void masterGeneration(const std::string &rootPath, - const std::vector &links, - AdditionalConstraints additionalConstraints_p, - std::map, int> &couplings, - std::string const &master_formulation, - std::string const &solver_name) -{ - std::vector candidates; - - for (const auto &link : links) - { - const auto &candidateFromLink = link.getCandidates(); - candidates.insert(candidates.end(), candidateFromLink.begin(), candidateFromLink.end()); - } - - std::sort(candidates.begin(), candidates.end(), - [](const Candidate &cand1, const Candidate &cand2) -> bool - { - return cand1.get_name() < cand2.get_name(); - }); - - SolverAbstract::Ptr master_l = MasterProblemBuilder(master_formulation).build(solver_name, candidates); - treatAdditionalConstraints(master_l, additionalConstraints_p); - - std::string const &lp_name = "master"; - master_l->write_prob_mps((Path(rootPath) / "lp" / (lp_name + ".mps")).get_str()); - - std::map> output; - for (auto const &coupling : couplings) - { - output[get_name(coupling.first.second)][coupling.first.first] = coupling.second; - } - int i = 0; - for (auto const &candidate : candidates) - { - output["master"][candidate.get_name()] = i; - ++i; - } - - std::ofstream coupling_file((Path(rootPath) / "lp" / STRUCTURE_FILE).get_str().c_str()); - for (auto const &mps : output) - { - for (auto const &pmax : mps.second) - { - coupling_file << std::setw(50) << mps.first; - coupling_file << std::setw(50) << pmax.first; - coupling_file << std::setw(10) << pmax.second; - coupling_file << std::endl; - } - } - coupling_file.close(); +void masterGeneration( + const std::string &rootPath, const std::vector &links, + AdditionalConstraints additionalConstraints_p, + std::map, int> &couplings, + std::string const &master_formulation, std::string const &solver_name) { + std::vector candidates; + + for (const auto &link : links) { + const auto &candidateFromLink = link.getCandidates(); + candidates.insert(candidates.end(), candidateFromLink.begin(), + candidateFromLink.end()); + } + + std::sort(candidates.begin(), candidates.end(), + [](const Candidate &cand1, const Candidate &cand2) -> bool { + return cand1.get_name() < cand2.get_name(); + }); + + SolverAbstract::Ptr master_l = + MasterProblemBuilder(master_formulation).build(solver_name, candidates); + treatAdditionalConstraints(master_l, additionalConstraints_p); + + std::string const &lp_name = "master"; + master_l->write_prob_mps( + (Path(rootPath) / "lp" / (lp_name + ".mps")).get_str()); + + std::map> output; + for (auto const &coupling : couplings) { + output[get_name(coupling.first.second)][coupling.first.first] = + coupling.second; + } + int i = 0; + for (auto const &candidate : candidates) { + output["master"][candidate.get_name()] = i; + ++i; + } + + std::ofstream coupling_file( + (Path(rootPath) / "lp" / STRUCTURE_FILE).get_str().c_str()); + for (auto const &mps : output) { + for (auto const &pmax : mps.second) { + coupling_file << std::setw(50) << mps.first; + coupling_file << std::setw(50) << pmax.first; + coupling_file << std::setw(10) << pmax.second; + coupling_file << std::endl; + } + } + coupling_file.close(); } /** @@ -129,69 +119,69 @@ void masterGeneration(const std::string &rootPath, * \brief Main program * * \param argc An integer argument count of the command line arguments - * \param argv Path to input data which is the 1st argument vector of the command line argument. - * \return an integer 0 corresponding to exit success + * \param argv Path to input data which is the 1st argument vector of the + * command line argument. \return an integer 0 corresponding to exit success */ -int main(int argc, char **argv) -{ - - try - { - - std::string root; - std::string master_formulation; - std::string additionalConstraintFilename_l; - - po::options_description desc("Allowed options"); - - desc.add_options()("help,h", "produce help message")("output,o", po::value(&root)->required(), "antares-xpansion study output")("formulation,f", po::value(&master_formulation)->default_value("relaxed"), "master formulation (relaxed or integer)")("exclusion-files,e", po::value(&additionalConstraintFilename_l), "path to exclusion files"); - - po::variables_map opts; - po::store(po::parse_command_line(argc, argv, desc), opts); - - if (opts.count("help")) - { - std::cout << desc << std::endl; - return 0; - } - - po::notify(opts); - - ActiveLinksBuilder linkBuilder = get_link_builders(root); - - if ((master_formulation != "relaxed") && (master_formulation != "integer")) - { - std::cout << "Invalid formulation argument : argument must be \"integer\" or \"relaxed\"" - << std::endl; - std::exit(1); - } - - AdditionalConstraints additionalConstraints; - if (!additionalConstraintFilename_l.empty()) - { - additionalConstraints = AdditionalConstraints(additionalConstraintFilename_l); - } - - std::map, int> couplings; - std::string solver_name = "CBC"; - std::vector links = linkBuilder.getLinks(); - LinkProblemsGenerator linkProblemsGenerator(links, solver_name); - linkProblemsGenerator.treatloop(root, couplings); - - masterGeneration(root, links, additionalConstraints, couplings, - master_formulation, solver_name); - - return 0; - } - catch (std::exception &e) - { - std::cerr << "error: " << e.what() << std::endl; - return 1; - } - catch (...) - { - std::cerr << "Exception of unknown type!" << std::endl; - } - - return 0; +int main(int argc, char **argv) { + try { + std::string root; + std::string master_formulation; + std::string additionalConstraintFilename_l; + + po::options_description desc("Allowed options"); + + desc.add_options()("help,h", "produce help message")( + "output,o", po::value(&root)->required(), + "antares-xpansion study output")( + "formulation,f", + po::value(&master_formulation)->default_value("relaxed"), + "master formulation (relaxed or integer)")( + "exclusion-files,e", + po::value(&additionalConstraintFilename_l), + "path to exclusion files"); + + po::variables_map opts; + po::store(po::parse_command_line(argc, argv, desc), opts); + + if (opts.count("help")) { + std::cout << desc << std::endl; + return 0; + } + + po::notify(opts); + + ActiveLinksBuilder linkBuilder = get_link_builders(root); + + if ((master_formulation != "relaxed") && + (master_formulation != "integer")) { + std::cout << "Invalid formulation argument : argument must be " + "\"integer\" or \"relaxed\"" + << std::endl; + std::exit(1); + } + + AdditionalConstraints additionalConstraints; + if (!additionalConstraintFilename_l.empty()) { + additionalConstraints = + AdditionalConstraints(additionalConstraintFilename_l); + } + + std::map, int> couplings; + std::string solver_name = "CBC"; + std::vector links = linkBuilder.getLinks(); + LinkProblemsGenerator linkProblemsGenerator(links, solver_name); + linkProblemsGenerator.treatloop(root, couplings); + + masterGeneration(root, links, additionalConstraints, couplings, + master_formulation, solver_name); + + return 0; + } catch (std::exception &e) { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } catch (...) { + std::cerr << "Exception of unknown type!" << std::endl; + } + + return 0; } diff --git a/src/cpp/exe/merge/main.cpp b/src/cpp/exe/merge/main.cpp index e5c457786..8ba60b193 100644 --- a/src/cpp/exe/merge/main.cpp +++ b/src/cpp/exe/merge/main.cpp @@ -1,48 +1,43 @@ // projet_benders.cpp : définit le point d'entrée pour l'application console. // -#include "glog/logging.h" - +#include "JsonWriter.h" #include "MergeMPS.h" -#include "Worker.h" #include "SimulationOptions.h" -#include "JsonWriter.h" - -#include "solver_utils.h" -#include "logger/User.h" -#include "helpers/Path.h" +#include "Worker.h" #include "WriterFactories.h" +#include "glog/logging.h" +#include "helpers/Path.h" +#include "logger/User.h" +#include "solver_utils.h" //@suggest: create and move to standardlp.cpp // Initialize static member size_t StandardLp::appendCNT = 0; -int main(int argc, char **argv) -{ - usage(argc); - SimulationOptions options(argv[1]); - options.print(std::cout); - - Logger logger = std::make_shared(std::cout); - - google::InitGoogleLogging(argv[0]); - auto path_to_log = (Path(options.OUTPUTROOT) / "merge_mpsLog").get_str(); - google::SetLogDestination(google::GLOG_INFO, path_to_log.c_str()); - LOG(INFO) << "starting merge_mps" << std::endl; - - Writer writer = build_json_writer(options.JSON_FILE); - try - { - MergeMPS merge_mps(options.get_base_options(), logger, writer); - merge_mps.launch(); - } - catch (std::exception &ex) - { - std::string error = "Exception raised and program stopped : " + std::string(ex.what()); - LOG(WARNING) << error << std::endl; - logger->display_message(error); - exit(1); - } - - return 0; +int main(int argc, char **argv) { + usage(argc); + SimulationOptions options(argv[1]); + options.print(std::cout); + + Logger logger = std::make_shared(std::cout); + + google::InitGoogleLogging(argv[0]); + auto path_to_log = (Path(options.OUTPUTROOT) / "merge_mpsLog").get_str(); + google::SetLogDestination(google::GLOG_INFO, path_to_log.c_str()); + LOG(INFO) << "starting merge_mps" << std::endl; + + Writer writer = build_json_writer(options.JSON_FILE); + try { + MergeMPS merge_mps(options.get_base_options(), logger, writer); + merge_mps.launch(); + } catch (std::exception &ex) { + std::string error = + "Exception raised and program stopped : " + std::string(ex.what()); + LOG(WARNING) << error << std::endl; + logger->display_message(error); + exit(1); + } + + return 0; } diff --git a/src/cpp/exe/study-updater/main.cpp b/src/cpp/exe/study-updater/main.cpp index a319f2230..e13c5f266 100644 --- a/src/cpp/exe/study-updater/main.cpp +++ b/src/cpp/exe/study-updater/main.cpp @@ -1,39 +1,37 @@ -#include +#include #include +#include #include -#include - -#include "StudyUpdater.h" #include "ActiveLinks.h" #include "CandidatesINIReader.h" +#include "LauncherHelpers.h" #include "LinkProfileReader.h" +#include "StudyUpdater.h" #include "helpers/Path.h" -#include "LauncherHelpers.h" namespace po = boost::program_options; /*! * \brief update links in the antares study directory * - * \param rootPath_p path corresponding to the path to the simulation output directory containing the lp directory - * \param links_p Structure which contains the list of links - * \param jsonPath_l path to the json output file - * \return void + * \param rootPath_p path corresponding to the path to the simulation output + * directory containing the lp directory \param links_p Structure which contains + * the list of links \param jsonPath_l path to the json output file \return void */ -void updateStudy(std::string const &rootPath_p, const std::vector &links_p, std::string const &jsonPath_l) -{ - std::string linksPath_l = (Path(rootPath_p) / ".." / "..").get_str(); - - StudyUpdater studyUpdater(linksPath_l); - int updateFailures_l = studyUpdater.update(links_p, jsonPath_l); - - if (updateFailures_l) - { - std::cout << "Error : Failed to update " << updateFailures_l << " files." - << links_p.size() - updateFailures_l << " files were updated\n"; - } +void updateStudy(std::string const &rootPath_p, + const std::vector &links_p, + std::string const &jsonPath_l) { + std::string linksPath_l = (Path(rootPath_p) / ".." / "..").get_str(); + + StudyUpdater studyUpdater(linksPath_l); + int updateFailures_l = studyUpdater.update(links_p, jsonPath_l); + + if (updateFailures_l) { + std::cout << "Error : Failed to update " << updateFailures_l << " files." + << links_p.size() - updateFailures_l << " files were updated\n"; + } } /** @@ -41,50 +39,45 @@ void updateStudy(std::string const &rootPath_p, const std::vector &l * \brief Main program * * \param argc An integer argument count of the command line arguments - * \param argv Path to input data which is the 1st argument vector of the command line argument. - * \return an integer 0 corresponding to exit success + * \param argv Path to input data which is the 1st argument vector of the + * command line argument. \return an integer 0 corresponding to exit success */ -int main(int argc, char **argv) -{ - - try - { - - std::string root; - std::string solutionFile_l; +int main(int argc, char **argv) { + try { + std::string root; + std::string solutionFile_l; - po::options_description desc("Allowed options"); + po::options_description desc("Allowed options"); - desc.add_options()("help,h", "produce help message")("study-output,o", po::value(&root)->required(), "antares-xpansion study output")("solution,s", po::value(&solutionFile_l)->required(), "path to json solution file"); + desc.add_options()("help,h", "produce help message")( + "study-output,o", po::value(&root)->required(), + "antares-xpansion study output")( + "solution,s", po::value(&solutionFile_l)->required(), + "path to json solution file"); - po::variables_map opts; - store(parse_command_line(argc, argv, desc), opts); + po::variables_map opts; + store(parse_command_line(argc, argv, desc), opts); - if (opts.count("help")) - { - std::cout << desc << std::endl; - return 0; - } + if (opts.count("help")) { + std::cout << desc << std::endl; + return 0; + } - po::notify(opts); + po::notify(opts); - ActiveLinksBuilder linksBuilder = get_link_builders(root); + ActiveLinksBuilder linksBuilder = get_link_builders(root); - const std::vector links = linksBuilder.getLinks(); + const std::vector links = linksBuilder.getLinks(); - updateStudy(root, links, solutionFile_l); + updateStudy(root, links, solutionFile_l); - return 0; - } - catch (std::exception &e) - { - std::cerr << "error: " << e.what() << std::endl; - return 1; - } - catch (...) - { - std::cerr << "Exception of unknown type!" << std::endl; - } + return 0; + } catch (std::exception &e) { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } catch (...) { + std::cerr << "Exception of unknown type!" << std::endl; + } - return 0; + return 0; } diff --git a/src/cpp/helpers/JsonXpansionReader.cpp b/src/cpp/helpers/JsonXpansionReader.cpp index 2ca99442b..32a01038d 100644 --- a/src/cpp/helpers/JsonXpansionReader.cpp +++ b/src/cpp/helpers/JsonXpansionReader.cpp @@ -1,55 +1,42 @@ #include "JsonXpansionReader.h" #include + #include #include +JsonXpansionReader::JsonXpansionReader() : _lastIterNb(0) {} -JsonXpansionReader::JsonXpansionReader(): -_lastIterNb(0) -{ -} +JsonXpansionReader::~JsonXpansionReader() {} -JsonXpansionReader::~JsonXpansionReader() -{ -} +void JsonXpansionReader::read(std::string const& filename_p) { + std::ifstream input_file_l(filename_p, std::ifstream::binary); -void JsonXpansionReader::read(std::string const & filename_p) -{ - std::ifstream input_file_l(filename_p, std::ifstream::binary); - - Json::CharReaderBuilder builder_l; - std::string errs; - if (!parseFromStream(builder_l, input_file_l, &_input, &errs)) { - std::cerr << errs << std::endl; - } - - //save lastIteration - _lastIterNb = 0; - for (auto const& iterationId_cnt : _input["iterations"].getMemberNames()) - { - int iterNb_l = std::stoi(iterationId_cnt); - _lastIterNb = (_lastIterNb < iterNb_l) ? iterNb_l : _lastIterNb; - } -} + Json::CharReaderBuilder builder_l; + std::string errs; + if (!parseFromStream(builder_l, input_file_l, &_input, &errs)) { + std::cerr << errs << std::endl; + } -int JsonXpansionReader::getBestIteration() const -{ - return _input["solution"]["iteration"].asInt(); + // save lastIteration + _lastIterNb = 0; + for (auto const& iterationId_cnt : _input["iterations"].getMemberNames()) { + int iterNb_l = std::stoi(iterationId_cnt); + _lastIterNb = (_lastIterNb < iterNb_l) ? iterNb_l : _lastIterNb; + } } -int JsonXpansionReader::getLastIteration() const -{ - return _lastIterNb; +int JsonXpansionReader::getBestIteration() const { + return _input["solution"]["iteration"].asInt(); } -JsonXpansionReader::Point JsonXpansionReader::getSolutionPoint() const -{ - Point x; - for (auto const& name_l : _input["solution"]["values"].getMemberNames()) - { - x[name_l] = _input["solution"]["values"][name_l].asDouble(); - } +int JsonXpansionReader::getLastIteration() const { return _lastIterNb; } + +JsonXpansionReader::Point JsonXpansionReader::getSolutionPoint() const { + Point x; + for (auto const& name_l : _input["solution"]["values"].getMemberNames()) { + x[name_l] = _input["solution"]["values"][name_l].asDouble(); + } - return x; + return x; } diff --git a/src/cpp/helpers/JsonXpansionReader.h b/src/cpp/helpers/JsonXpansionReader.h index c7343b690..cba21ca11 100644 --- a/src/cpp/helpers/JsonXpansionReader.h +++ b/src/cpp/helpers/JsonXpansionReader.h @@ -1,60 +1,61 @@ #pragma once - #include /*! -* \class JsonXpansionReader -* \brief Class that reads a json file describing an antares-xpansion solution -* \note does not consider if the json file was created from sequential, mpi or merge optimizers -*/ -class JsonXpansionReader -{ -private: - typedef std::map Point; - -private: - //number of the last iteration - int _lastIterNb; - - //json file content - Json::Value _input; - -public: - -/*! -* \brief JsonXpansionReader default constructor -*/ - JsonXpansionReader(); - -/*! -* \brief JsonWriter default destructor -*/ - virtual ~JsonXpansionReader(); - - -/*! -* \brief reads a json file describing the execution of an antares xpansion optimisation -* and populates the jsonXpansionReader class attributes with the data from the file -* -* \param filename_p name of the json file to read from -*/ - void read(std::string const & filename_p); - -/*! -* \brief returns the index of the best iteration indicated in the json output file -* \return iteration entry in the solution object of the read json if exists, Json::nullValue otherwise -*/ - int getBestIteration() const; - -/*! -* \brief returns the index of the last iteration indicated in the json output file -* \return index of the last iteration in the read json if possible, Json::nullValue otherwise -*/ - int getLastIteration() const; - -/*! -* \brief returns the solution to the xpansion problem indicated in the json output file -*/ - Point getSolutionPoint() const; + * \class JsonXpansionReader + * \brief Class that reads a json file describing an antares-xpansion solution + * \note does not consider if the json file was created from sequential, mpi or + * merge optimizers + */ +class JsonXpansionReader { + private: + typedef std::map Point; + + private: + // number of the last iteration + int _lastIterNb; + + // json file content + Json::Value _input; + + public: + /*! + * \brief JsonXpansionReader default constructor + */ + JsonXpansionReader(); + + /*! + * \brief JsonWriter default destructor + */ + virtual ~JsonXpansionReader(); + + /*! + * \brief reads a json file describing the execution of an antares xpansion + * optimisation and populates the jsonXpansionReader class attributes with the + * data from the file + * + * \param filename_p name of the json file to read from + */ + void read(std::string const& filename_p); + + /*! + * \brief returns the index of the best iteration indicated in the json + * output file \return iteration entry in the solution object of the read json + * if exists, Json::nullValue otherwise + */ + int getBestIteration() const; + + /*! + * \brief returns the index of the last iteration indicated in the json + * output file \return index of the last iteration in the read json if + * possible, Json::nullValue otherwise + */ + int getLastIteration() const; + + /*! + * \brief returns the solution to the xpansion problem indicated in the json + * output file + */ + Point getSolutionPoint() const; }; diff --git a/src/cpp/helpers/StringUtils.cpp b/src/cpp/helpers/StringUtils.cpp index e1bdd6610..7513a5fd4 100644 --- a/src/cpp/helpers/StringUtils.cpp +++ b/src/cpp/helpers/StringUtils.cpp @@ -1,14 +1,11 @@ -#include -#include - #include "include/helpers/StringUtils.h" +#include +#include -std::string StringUtils::ToLowercase(const std::string& s) -{ - std::string result; - std::transform(s.cbegin(), s.cend(), std::back_inserter(result), [](char const& c) { - return std::tolower(c); - }); - return result; +std::string StringUtils::ToLowercase(const std::string& s) { + std::string result; + std::transform(s.cbegin(), s.cend(), std::back_inserter(result), + [](char const& c) { return std::tolower(c); }); + return result; } diff --git a/src/cpp/helpers/include/helpers/Path.h b/src/cpp/helpers/include/helpers/Path.h index bf64b85f9..720626aff 100644 --- a/src/cpp/helpers/include/helpers/Path.h +++ b/src/cpp/helpers/include/helpers/Path.h @@ -3,12 +3,11 @@ #include #include -class Path -{ -private: +class Path { + private: std::string mPath; -public: + public: #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) // Windows static const char mSep = '\\'; @@ -16,32 +15,19 @@ class Path // Linux, Unix, Apple static const char mSep = '/'; #endif - explicit Path(const std::string &s) : mPath(s) - { - } + explicit Path(const std::string &s) : mPath(s) {} explicit Path(std::string &&s) : mPath(std::move(s)) {} - Path operator/(const Path &other) const - { + Path operator/(const Path &other) const { return Path(mPath + mSep + other.mPath); } - Path operator/(const std::string &s) const - { - return Path(mPath + mSep + s); - } - explicit operator std::string() const - { - return mPath; - } + Path operator/(const std::string &s) const { return Path(mPath + mSep + s); } + explicit operator std::string() const { return mPath; } - std::string get_str() const - { - return mPath; - } - friend std::ostream &operator<<(std::ostream &os, const Path &p) - { + std::string get_str() const { return mPath; } + friend std::ostream &operator<<(std::ostream &os, const Path &p) { os << p.mPath; return os; } }; -#endif // ANTARESXPANSION_PATH_H \ No newline at end of file +#endif // ANTARESXPANSION_PATH_H \ No newline at end of file diff --git a/src/cpp/helpers/include/helpers/StringUtils.h b/src/cpp/helpers/include/helpers/StringUtils.h index 605ee482d..ecdc1c6ea 100644 --- a/src/cpp/helpers/include/helpers/StringUtils.h +++ b/src/cpp/helpers/include/helpers/StringUtils.h @@ -4,11 +4,8 @@ #include class StringUtils { - -public : - static std::string ToLowercase(const std::string& s); - + public: + static std::string ToLowercase(const std::string& s); }; - -#endif //ANTARESXPANSION_STRINGUTILS_H +#endif // ANTARESXPANSION_STRINGUTILS_H diff --git a/src/cpp/helpers/solver_utils.h b/src/cpp/helpers/solver_utils.h index 235effb02..fef835345 100644 --- a/src/cpp/helpers/solver_utils.h +++ b/src/cpp/helpers/solver_utils.h @@ -1,54 +1,58 @@ #pragma once -#include #include +#include #include "multisolver_interface/Solver.h" -class InvalidSolverStatusException : public std::runtime_error -{ -public: - InvalidSolverStatusException(const std::string &message) - : std::runtime_error(message) - { - } +class InvalidSolverStatusException : public std::runtime_error { + public: + InvalidSolverStatusException(const std::string &message) + : std::runtime_error(message) {} }; /** - * @brief Returns the nonzeros in the constraint matrix for the rows in a given range + * @brief Returns the nonzeros in the constraint matrix for the rows in a given + * range * * @param solver_p : solver containing the model to consider. - * @param mstart_p : will be filled with the indices indicating the starting offsets in the - * mclind_p and dmatval_p arrays for each requested row. - * Column i starts at position mstart_p[i] in the mrwind_p and dmatval_p arrays, and has + * @param mstart_p : will be filled with the indices indicating the starting + * offsets in the mclind_p and dmatval_p arrays for each requested row. Column i + * starts at position mstart_p[i] in the mrwind_p and dmatval_p arrays, and has * mstart_p[i+1]-mstart_p[i] elements in it. - * @param mclind_p : will be filled with the column indices of the nonzero elements for each row. + * @param mclind_p : will be filled with the column indices of the nonzero + * elements for each row. * @param dmatval_p : will be filled with the nonzero element values. * @param first_p : First row in the range. * @param last_p : Last row in the range. */ void solver_getrows(SolverAbstract::Ptr const solver_p, - std::vector &mstart_p, std::vector &mclind_p, std::vector &dmatval_p, - int first_p, int last_p); + std::vector &mstart_p, std::vector &mclind_p, + std::vector &dmatval_p, int first_p, int last_p); /** - * @brief Returns the objective function coefficients for the columns in a given range. + * @brief Returns the objective function coefficients for the columns in a given + * range. * * @param solver_p : solver containing the model to consider. * @param obj_p : will be filled with the objective function coefficients * @param first_p : first column to consider. * @param last_p : last column to consider. */ -void solver_get_obj_func_coeffs(SolverAbstract::Ptr const solver_p, std::vector &obj_p, int first_p, int last_p); +void solver_get_obj_func_coeffs(SolverAbstract::Ptr const solver_p, + std::vector &obj_p, int first_p, + int last_p); /** * @brief Adds variables to an existent solver * * @param solver_p : solver containing the model to modify. - * @param objx_p : array containing the objective function coefficients of the new columns. - * @param mstart_p : Integer array containing the offsets in the mrwind_p and dmatval_p arrays of - * the start of the elements for each column. - * @param mrwind_p : Integer array containing the row indices for the elements in each column. + * @param objx_p : array containing the objective function coefficients of the + * new columns. + * @param mstart_p : Integer array containing the offsets in the mrwind_p and + * dmatval_p arrays of the start of the elements for each column. + * @param mrwind_p : Integer array containing the row indices for the elements + * in each column. * @param dmatval_p : Double array containing the element values. * @param bdl_p : Double array containing the lower bounds on the added columns. * @param bdu_p : Double array containing the upper bounds on the added columns. @@ -56,14 +60,15 @@ void solver_get_obj_func_coeffs(SolverAbstract::Ptr const solver_p, std::vector< * 'B' for binary variables * 'I' for integer variables * 'C' for continuous variables - * @param colNames_p : optional parameter. array containing the names of the new columns to add. + * @param colNames_p : optional parameter. array containing the names of the new + * columns to add. */ -void solver_addcols(SolverAbstract::Ptr solver_p, - std::vector const &objx_p, - std::vector const &mstart_p, std::vector const &mrwind_p, std::vector const &dmatval_p, - std::vector const &bdl_p, std::vector const &bdu_p, - std::vector const &colTypes_p, - std::vector const &colNames_p); +void solver_addcols( + SolverAbstract::Ptr solver_p, std::vector const &objx_p, + std::vector const &mstart_p, std::vector const &mrwind_p, + std::vector const &dmatval_p, std::vector const &bdl_p, + std::vector const &bdu_p, std::vector const &colTypes_p, + std::vector const &colNames_p); /** * @brief Adds constraints to an existent solver @@ -77,11 +82,15 @@ void solver_addcols(SolverAbstract::Ptr solver_p, * N : indicates a nonbinding constraint (these will be ignored). * @param rhs_p : Double array of containing the right hand side elements. * This is the UB for L and R constraints and the LB for G constraints. - * @param range_p : Double array containing the row range elements. The values in the range array will only be read for R type rows. - * for R rows we assume that the ub is the rhs and the LB is rhs-range - * @param mstart_p : Integer array of containing the offsets in the mclind_p and dmatval_p arrays of the start of the elements for each row. - * @param mclind_p : Integer array of containing the (contiguous) column indices for the elements in each row. - * @param dmatval_p : Double array of containing the (contiguous) element values. + * @param range_p : Double array containing the row range elements. The values + * in the range array will only be read for R type rows. for R rows we assume + * that the ub is the rhs and the LB is rhs-range + * @param mstart_p : Integer array of containing the offsets in the mclind_p and + * dmatval_p arrays of the start of the elements for each row. + * @param mclind_p : Integer array of containing the (contiguous) column indices + * for the elements in each row. + * @param dmatval_p : Double array of containing the (contiguous) element + * values. * * @note ignores non-binding rows */ @@ -89,15 +98,19 @@ void solver_addrows(SolverAbstract::Ptr solver_p, std::vector const &qrtype_p, std::vector const &rhs_p, std::vector const &range_p, - std::vector const &mstart_p, std::vector const &mclind_p, std::vector const &dmatval_p); + std::vector const &mstart_p, + std::vector const &mclind_p, + std::vector const &dmatval_p); /** * @brief returns the solution of a solved problem * * @param solver_p : solver containing the solved model. - * @param x_p : will be filled with the variables values of the retrieved solution + * @param x_p : will be filled with the variables values of the retrieved + * solution */ -void solver_getlpsolution(SolverAbstract::Ptr const solver_p, std::vector &x_p); +void solver_getlpsolution(SolverAbstract::Ptr const solver_p, + std::vector &x_p); /** * @brief returns the dual values of a solved problem @@ -105,7 +118,8 @@ void solver_getlpsolution(SolverAbstract::Ptr const solver_p, std::vector &dual_p); +void solver_getlpdual(SolverAbstract::Ptr const solver_p, + std::vector &dual_p); /** * @brief Returns the reduced costs of a solved problem @@ -113,7 +127,8 @@ void solver_getlpdual(SolverAbstract::Ptr const solver_p, std::vector &d * @param solver_p : solver containing the solved model. * @param dj_p : will be filled with the reduced costs */ -void solver_getlpreducedcost(SolverAbstract::Ptr const solver_p, std::vector &dj_p); +void solver_getlpreducedcost(SolverAbstract::Ptr const solver_p, + std::vector &dj_p); /** * @brief Returns the row types for the rows in a given range. @@ -128,7 +143,8 @@ void solver_getlpreducedcost(SolverAbstract::Ptr const solver_p, std::vector &qrtype_p, int first_p, int last_p); +void solver_getrowtype(SolverAbstract::Ptr const solver_p, + std::vector &qrtype_p, int first_p, int last_p); /** * @brief Returns the right hand side elements for the rows in a given range. @@ -142,37 +158,41 @@ void solver_getrowtype(SolverAbstract::Ptr const solver_p, std::vector &qr * @note if the constraint is a range, returns the ub. * @note if the constraint is unbound, still returns the ub i.e. solver's +inf. */ -void solver_getrhs(SolverAbstract::Ptr const solver_p, std::vector &rhs_p, int first_p, int last_p); +void solver_getrhs(SolverAbstract::Ptr const solver_p, + std::vector &rhs_p, int first_p, int last_p); /** - * @brief Returns the right hand side range values for the rows in a given range. + * @brief Returns the right hand side range values for the rows in a given + * range. * * @param solver_p : solver containing the model. - * @param range_p : will be filled with the right hand side range values (ie ub-lb or infinity). + * @param range_p : will be filled with the right hand side range values (ie + * ub-lb or infinity). * @param first_p : First row in the range. * @param last_p : Last row in the range */ -void solver_getrhsrange(SolverAbstract::Ptr const solver_p, std::vector &range_p, int first_p, int last_p); +void solver_getrhsrange(SolverAbstract::Ptr const solver_p, + std::vector &range_p, int first_p, int last_p); /** * @brief Returns infos about the columns * * @param solver_p : solver containing the model. - * @param coltype_p : will be filled with the types of the columns in the specified range: - * 'B' for binary variables - * 'I' for integer variables - * 'C' for continuous variables - * @param bdl_p : will be filled with the lower bounds of the columns in the specified range: - * @param bdu_p : will be filled with the upper bounds of the columns in the specified range: + * @param coltype_p : will be filled with the types of the columns in the + * specified range: 'B' for binary variables 'I' for integer variables 'C' for + * continuous variables + * @param bdl_p : will be filled with the lower bounds of the columns in the + * specified range: + * @param bdu_p : will be filled with the upper bounds of the columns in the + * specified range: * @param first_p : First column in the range. * @param last_p : Last column in the range * * @note return 'I' if the variable is binary or integer and it was fixed */ void solver_getcolinfo(SolverAbstract::Ptr const solver_p, - std::vector &coltype_p, - std::vector &bdl_p, std::vector &bdu_p, - int first_p, int last_p); + std::vector &coltype_p, std::vector &bdl_p, + std::vector &bdu_p, int first_p, int last_p); /** * @brief Deactivates some rows in an existent model @@ -180,42 +200,52 @@ void solver_getcolinfo(SolverAbstract::Ptr const solver_p, * @param solver_p : solver containing the model to modify. * @param mindex : indices of the rows to deactivate. * - * @note note that this method does not delete the rows but simply unbounds the constraint and supresses its terms - * i.e. replaces the indexed rows with -inf <= 0 <= +inf + * @note note that this method does not delete the rows but simply unbounds the + * constraint and supresses its terms i.e. replaces the indexed rows with -inf + * <= 0 <= +inf */ -void solver_deactivaterows(SolverAbstract::Ptr solver_p, std::vector const &mindex); +void solver_deactivaterows(SolverAbstract::Ptr solver_p, + std::vector const &mindex); /** * @brief Returns the current basis * * @param solver_p : solver containing the model to modify. - * @param rstatus_p : will be filled with the basis status of the slack, surplus or artificial variable associated with each row. The status will be one of: + * @param rstatus_p : will be filled with the basis status of the slack, +surplus or artificial variable associated with each row. The status will be one +of: * 0 : slack, surplus or artificial is non-basic at lower bound; * 1 : slack, surplus or artificial is basic; * 2 : slack or surplus is non-basic at upper bound. * 3 : slack or surplus is super-basic. May be NULL if not required. - * @param cstatus_p : will be filled with the basis status of the columns in the constraint matrix. The status will be one of: - * 0 : variable is non-basic at lower bound, or superbasic at zero if the variable has no lower bound; + * @param cstatus_p : will be filled with the basis status of the columns in the +constraint matrix. The status will be one of: + * 0 : variable is non-basic at lower bound, or superbasic at zero if the +variable has no lower bound; * 1 : variable is basic; * 2 : variable is non-basic at upper bound; * 3 : variable is super-basic. May be NULL if not required. */ -void solver_getbasis(SolverAbstract::Ptr solver_p, std::vector &rstatus_p, std::vector &cstatus_p); +void solver_getbasis(SolverAbstract::Ptr solver_p, std::vector &rstatus_p, + std::vector &cstatus_p); /** * @brief Returns the current basis * * @param solver_p : solver containing the model to modify. - * @param mindex_p : int array containing the indices of the columns on which the bounds will change. - * @param qbtype_p : Character array of same length as mindex_p indicating the type of bound to change: - * U : indicates change the upper bound; - * L : indicates change the lower bound; - * B : indicates change both bounds, i.e. fix the column. - * @param bnd_p : Double array of same length as mindex_p giving the new bound values. - * - * @note if the same bound is changed twice the bound at the end of the vector will be used and no warning will be issued + * @param mindex_p : int array containing the indices of the columns on which + * the bounds will change. + * @param qbtype_p : Character array of same length as mindex_p indicating the + * type of bound to change: U : indicates change the upper bound; L : indicates + * change the lower bound; B : indicates change both bounds, i.e. fix the + * column. + * @param bnd_p : Double array of same length as mindex_p giving the new bound + * values. + * + * @note if the same bound is changed twice the bound at the end of the vector + * will be used and no warning will be issued */ void solver_chgbounds(SolverAbstract::Ptr solver_p, std::vector const &mindex_p, @@ -227,9 +257,12 @@ void solver_chgbounds(SolverAbstract::Ptr solver_p, * * @param outSolver_p : solver containing the model with renamed variables. * @param inSolver_p : solver containing the model to copy. - * @param names_p : int array containing the indices of the columns on which the bounds will change. + * @param names_p : int array containing the indices of the columns on which the + * bounds will change. * - * @note care when copying between solvers of different types : no special verifications are done (eg. infinity values correspondance) + * @note care when copying between solvers of different types : no special + * verifications are done (eg. infinity values correspondance) * @note duplicate/empty names will be named automatically by ortools */ -void solver_rename_vars(SolverAbstract::Ptr outSolver_p, const std::vector &names_p); +void solver_rename_vars(SolverAbstract::Ptr outSolver_p, + const std::vector &names_p); diff --git a/src/cpp/lpnamer/helper/ColumnToChange.cpp b/src/cpp/lpnamer/helper/ColumnToChange.cpp index d972ce310..d332830f6 100644 --- a/src/cpp/lpnamer/helper/ColumnToChange.cpp +++ b/src/cpp/lpnamer/helper/ColumnToChange.cpp @@ -1,7 +1,7 @@ #include "ColumnToChange.h" bool ColumnToChange::operator==(const ColumnToChange& other) const { - bool result = id == other.id; - result &= time_step == other.time_step; - return result; - } \ No newline at end of file + bool result = id == other.id; + result &= time_step == other.time_step; + return result; +} \ No newline at end of file diff --git a/src/cpp/lpnamer/helper/ColumnToChange.h b/src/cpp/lpnamer/helper/ColumnToChange.h index 7dd5849c8..6f91d6204 100644 --- a/src/cpp/lpnamer/helper/ColumnToChange.h +++ b/src/cpp/lpnamer/helper/ColumnToChange.h @@ -2,17 +2,16 @@ #define ANTARESXPANSION_COLUMNTOCHANGE_H #include -using colId= unsigned int; -struct ColumnToChange{ +using colId = unsigned int; +struct ColumnToChange { + ColumnToChange(colId id, int time_step) : id(id), time_step(time_step){}; + bool operator==(const ColumnToChange& other) const; - ColumnToChange(colId id, int time_step):id(id),time_step(time_step){}; - bool operator==(const ColumnToChange& other) const; - - colId id; - int time_step; + colId id; + int time_step; }; using ColumnsToChange = std::vector; -using linkId=unsigned int; +using linkId = unsigned int; -#endif // ANTARESXPANSION_COLUMNTOCHANGE_H +#endif // ANTARESXPANSION_COLUMNTOCHANGE_H diff --git a/src/cpp/lpnamer/helper/common_lpnamer.h b/src/cpp/lpnamer/helper/common_lpnamer.h index b16862d4b..84c51b88d 100644 --- a/src/cpp/lpnamer/helper/common_lpnamer.h +++ b/src/cpp/lpnamer/helper/common_lpnamer.h @@ -1,26 +1,23 @@ #pragma once - +#include +#include +#include +#include #include -#include -#include #include - -#include -#include +#include #include -#include -#include -#include - +#include +#include -inline bool contains(std::string const & v1, std::string const & v2) { - return v1.find(v2) != std::string::npos; +inline bool contains(std::string const& v1, std::string const& v2) { + return v1.find(v2) != std::string::npos; } -inline int to_int(std::string const & value) { - std::stringstream buffer; - buffer << value; - int result; - buffer >> result; - return result; +inline int to_int(std::string const& value) { + std::stringstream buffer; + buffer << value; + int result; + buffer >> result; + return result; } diff --git a/src/cpp/lpnamer/input_reader/AdditionalConstraintsReader.cpp b/src/cpp/lpnamer/input_reader/AdditionalConstraintsReader.cpp index 37ea138b3..5e3c1157a 100644 --- a/src/cpp/lpnamer/input_reader/AdditionalConstraintsReader.cpp +++ b/src/cpp/lpnamer/input_reader/AdditionalConstraintsReader.cpp @@ -1,149 +1,139 @@ #include "AdditionalConstraintsReader.h" +#include #include -#include #include -#include +#include -namespace -{ +namespace { - //trim leading whitespaces - std::string ltrim(const std::string& s) - { - size_t start = s.find_first_not_of(" \n\r\t\f\v"); - return (start == std::string::npos) ? "" : s.substr(start); - } +// trim leading whitespaces +std::string ltrim(const std::string& s) { + size_t start = s.find_first_not_of(" \n\r\t\f\v"); + return (start == std::string::npos) ? "" : s.substr(start); +} - //trim trailing whitespaces - std::string rtrim(const std::string& s) - { - size_t end = s.find_last_not_of(" \n\r\t\f\v"); - return (end == std::string::npos) ? "" : s.substr(0, end + 1); - } +// trim trailing whitespaces +std::string rtrim(const std::string& s) { + size_t end = s.find_last_not_of(" \n\r\t\f\v"); + return (end == std::string::npos) ? "" : s.substr(0, end + 1); +} - //trim leading and trailing whitespaces - std::string trim(const std::string& s) - { - return rtrim(ltrim(s)); - } +// trim leading and trailing whitespaces +std::string trim(const std::string& s) { return rtrim(ltrim(s)); } -} +} // namespace std::string AdditionalConstraintsReader::illegal_chars = " \n\r\t\f\v-+=:[]()"; +void AdditionalConstraintsReader::processSectionLine() { + if (_line[_line.length() - 1] != ']') { + std::cout << "additional constraints file: line " << _lineNb + << " : section line not ending with ']'.\n"; + std::exit(1); + } -void AdditionalConstraintsReader::processSectionLine() -{ - if ( _line[_line.length()-1] != ']' ) - { - std::cout << "additional constraints file: line " << _lineNb << " : section line not ending with ']'.\n"; - std::exit(1); - } - - _section = _line.substr(1,_line.find(']')-1); + _section = _line.substr(1, _line.find(']') - 1); - if (!_sections.insert(_section).second) - { - std::cout << "additional constraints file: line " << _lineNb << " : duplicate section " << _section << "!\n"; - std::exit(1); - } + if (!_sections.insert(_section).second) { + std::cout << "additional constraints file: line " << _lineNb + << " : duplicate section " << _section << "!\n"; + std::exit(1); + } } -void AdditionalConstraintsReader::processEntryLine() -{ - size_t delimiterIt_l = _line.find(" = "); - if (delimiterIt_l == std::string::npos) - { - std::cout << "additional constraints file: line " << _lineNb << " : incorrect entry line format. Expected format 'attribute = value'!\n"; +void AdditionalConstraintsReader::processEntryLine() { + size_t delimiterIt_l = _line.find(" = "); + if (delimiterIt_l == std::string::npos) { + std::cout << "additional constraints file: line " << _lineNb + << " : incorrect entry line format. Expected format 'attribute = " + "value'!\n"; + std::exit(1); + } + + std::string attribute_l = rtrim(_line.substr(0, delimiterIt_l)); + std::string value_l = ltrim(_line.substr(delimiterIt_l + 3)); + + size_t illegalCharIndex_l = + attribute_l.find_first_of(AdditionalConstraintsReader::illegal_chars); + if (illegalCharIndex_l != std::string::npos) { + std::cout << "additional constraints file: line " << _lineNb + << " : Illegal character '" << attribute_l[illegalCharIndex_l] + << "' in attribute name!\n"; + std::exit(1); + } + + if (_values[_section].count(attribute_l)) { + std::cout << "additional constraints file: line " << _lineNb + << " : duplicate attribute " << attribute_l << "!\n"; + std::exit(1); + } else { + if ((attribute_l == "name") || (_section == "variables")) { + illegalCharIndex_l = + value_l.find_first_of(AdditionalConstraintsReader::illegal_chars); + if (illegalCharIndex_l != std::string::npos) { + std::cout << "additional constraints file: line " << _lineNb + << " : Illegal character '" << value_l[illegalCharIndex_l] + << "' in value!\n"; std::exit(1); + } } - std::string attribute_l = rtrim( _line.substr(0, delimiterIt_l) ); - std::string value_l = ltrim( _line.substr(delimiterIt_l+3) ); - - size_t illegalCharIndex_l = attribute_l.find_first_of(AdditionalConstraintsReader::illegal_chars); - if( illegalCharIndex_l != std::string::npos) - { - std::cout << "additional constraints file: line " << _lineNb << " : Illegal character '" << attribute_l[illegalCharIndex_l] << "' in attribute name!\n"; + if (attribute_l == "sign") { + if ((value_l != "greater_or_equal") && (value_l != "less_or_equal") && + (value_l != "equal")) { + std::cout << "additional constraints file: line " << _lineNb + << " : Illegal sign value : " << value_l + << "! supported values are: " + << "greater_or_equal, less_or_equal and equal.\n"; std::exit(1); + } } - if(_values[_section].count(attribute_l)) - { - std::cout << "additional constraints file: line " << _lineNb << " : duplicate attribute " << attribute_l << "!\n"; - std::exit(1); - } - else - { - if((attribute_l == "name") || (_section == "variables")) - { - illegalCharIndex_l = value_l.find_first_of(AdditionalConstraintsReader::illegal_chars); - if( illegalCharIndex_l != std::string::npos) - { - std::cout << "additional constraints file: line " << _lineNb << " : Illegal character '" << value_l[illegalCharIndex_l] << "' in value!\n"; - std::exit(1); - } - } - - if (attribute_l == "sign") - { - if ( (value_l != "greater_or_equal") && (value_l != "less_or_equal") && (value_l != "equal") ) - { - std::cout << "additional constraints file: line " << _lineNb << " : Illegal sign value : " << value_l << "! supported values are: " - <<"greater_or_equal, less_or_equal and equal.\n"; - std::exit(1); - } - } - - _values[_section][attribute_l] = value_l; - } + _values[_section][attribute_l] = value_l; + } } -AdditionalConstraintsReader::AdditionalConstraintsReader(std::string const & constraints_file_path) -{ - std::ifstream file_l(constraints_file_path); - - while (std::getline(file_l, _line)) - { - ++_lineNb; - _line = trim(_line); - std::transform(_line.begin(), _line.end(), _line.begin(), - [](unsigned char c){ return std::tolower(c); }); - - if ( (_line.length() == 0) || (_line[0] == '#') || (_line[0] == ';') ) - {//line is a comment or empty - continue; - } - else if ( _line[0] == '[' ) - {//line is a section - processSectionLine(); - } - else - { - //check we have a valid section name - if(_section == "") - { - std::cout << "additional constraints file: Section line is required before line " << _lineNb << "!\n"; - std::exit(1); - } - - processEntryLine(); - } +AdditionalConstraintsReader::AdditionalConstraintsReader( + std::string const& constraints_file_path) { + std::ifstream file_l(constraints_file_path); + + while (std::getline(file_l, _line)) { + ++_lineNb; + _line = trim(_line); + std::transform(_line.begin(), _line.end(), _line.begin(), + [](unsigned char c) { return std::tolower(c); }); + + if ((_line.length() == 0) || (_line[0] == '#') || + (_line[0] == ';')) { // line is a comment or empty + continue; + } else if (_line[0] == '[') { // line is a section + processSectionLine(); + } else { + // check we have a valid section name + if (_section == "") { + std::cout << "additional constraints file: Section line is required " + "before line " + << _lineNb << "!\n"; + std::exit(1); + } + + processEntryLine(); } + } } -std::map const & AdditionalConstraintsReader::getVariablesSection() -{ - return _values["variables"]; +std::map const& +AdditionalConstraintsReader::getVariablesSection() { + return _values["variables"]; } -std::set const & AdditionalConstraintsReader::getSections() const -{ - return _sections; +std::set const& AdditionalConstraintsReader::getSections() const { + return _sections; } -std::map const & AdditionalConstraintsReader::getSection(std::string const & sectionName_p) const -{ - return _values.at(sectionName_p); +std::map const& +AdditionalConstraintsReader::getSection( + std::string const& sectionName_p) const { + return _values.at(sectionName_p); } diff --git a/src/cpp/lpnamer/input_reader/AdditionalConstraintsReader.h b/src/cpp/lpnamer/input_reader/AdditionalConstraintsReader.h index b2fda1870..5ad436c23 100644 --- a/src/cpp/lpnamer/input_reader/AdditionalConstraintsReader.h +++ b/src/cpp/lpnamer/input_reader/AdditionalConstraintsReader.h @@ -1,84 +1,85 @@ #pragma once -#include #include #include - +#include /*! * \struct AdditionalConstraintsReader * \brief candidate exclusion constraints reading structure * */ -struct AdditionalConstraintsReader -{ +struct AdditionalConstraintsReader { + /*! + * characters to forbid in variables and constraints names + */ + static std::string illegal_chars; -/*! - * characters to forbid in variables and constraints names - */ - static std::string illegal_chars; + private: + //! set of section names contained between [] in the ini file + std::set _sections; + //! map containing the string value per section per attribute _values[section + //! name][attribute] + std::map> _values; -private: - //! set of section names contained between [] in the ini file - std::set _sections; - //! map containing the string value per section per attribute _values[section name][attribute] - std::map> _values; + //! the section that is being currently processed + std::string _section = ""; + //! line string that is being currently processed + std::string _line = ""; + //! number of the line that is being currently processed + int _lineNb = 0; - //! the section that is being currently processed - std::string _section = ""; - //! line string that is being currently processed - std::string _line = "" ; - //! number of the line that is being currently processed - int _lineNb = 0; + public: + /*! + * default constructor for struct AdditionalConstraintsReader + */ + AdditionalConstraintsReader() = default; -public: + /*! + * \brief AdditionalConstraintsReader from an inifile + * + * \param constraints_file_path String name of the file to use to read the + * additional constraints + */ + explicit AdditionalConstraintsReader( + std::string const& constraints_file_path); -/*! - * default constructor for struct AdditionalConstraintsReader - */ - AdditionalConstraintsReader() = default; + /*! + * \brief return the section defining the binary variables to add + */ + std::map const& getVariablesSection(); -/*! - * \brief AdditionalConstraintsReader from an inifile - * - * \param constraints_file_path String name of the file to use to read the additional constraints - */ - explicit AdditionalConstraintsReader(std::string const & constraints_file_path); + /*! + * \brief returns the set of the names of sections defined in the file + * + * \param constraints_file_path String name of the file to use to read the + * additional constraints + */ + std::set const& getSections() const; -/*! - * \brief return the section defining the binary variables to add - */ - std::map const & getVariablesSection(); + /*! + * \brief returns a section + * + * \param sectionName_p String name of the section to return + * + * \throw if the section does not exist + */ + std::map const& getSection( + std::string const& sectionName_p) const; -/*! - * \brief returns the set of the names of sections defined in the file - * - * \param constraints_file_path String name of the file to use to read the additional constraints - */ - std::set const & getSections() const; + private: + /*! + * \brief process a section line ie a line that indicates a section name + * + * checks that the line ends with "]" and that the section name is not + * duplicate updates the _section attribute + */ + void processSectionLine(); -/*! - * \brief returns a section - * - * \param sectionName_p String name of the section to return - * - * \throw if the section does not exist - */ - std::map const & getSection(std::string const & sectionName_p) const; - -private: -/*! - * \brief process a section line ie a line that indicates a section name - * - * checks that the line ends with "]" and that the section name is not duplicate - * updates the _section attribute - */ - void processSectionLine(); - -/*! - * \brief processes an entry line ie that indicates an attribute and a value - * - * adds the entry to the values map - */ - void processEntryLine(); + /*! + * \brief processes an entry line ie that indicates an attribute and a value + * + * adds the entry to the values map + */ + void processEntryLine(); }; diff --git a/src/cpp/lpnamer/input_reader/CandidatesINIReader.cpp b/src/cpp/lpnamer/input_reader/CandidatesINIReader.cpp index bc22cb6cf..fcb33351e 100644 --- a/src/cpp/lpnamer/input_reader/CandidatesINIReader.cpp +++ b/src/cpp/lpnamer/input_reader/CandidatesINIReader.cpp @@ -1,155 +1,167 @@ // -#include - -#include "helpers/StringUtils.h" - -#include "INIReader.h" #include "CandidatesINIReader.h" +#include -CandidatesINIReader::CandidatesINIReader(const std::string& antaresIntercoFile, const std::string& areaFile) { - - _intercoFileData = ReadAntaresIntercoFile(antaresIntercoFile); - _areaNames = ReadAreaFile(areaFile); - - for (auto const & intercoFileData : _intercoFileData) { - //TODO : check if index is available in areaNames - std::string const & pays_or(_areaNames[intercoFileData.index_pays_origine]); - std::string const & pays_ex(_areaNames[intercoFileData.index_pays_extremite]); - std::string linkName = pays_or + " - " + pays_ex; - _intercoIndexMap[linkName]=intercoFileData.index_interco; - } +#include "INIReader.h" +#include "helpers/StringUtils.h" +CandidatesINIReader::CandidatesINIReader(const std::string &antaresIntercoFile, + const std::string &areaFile) { + _intercoFileData = ReadAntaresIntercoFile(antaresIntercoFile); + _areaNames = ReadAreaFile(areaFile); + + for (auto const &intercoFileData : _intercoFileData) { + // TODO : check if index is available in areaNames + std::string const &pays_or(_areaNames[intercoFileData.index_pays_origine]); + std::string const &pays_ex( + _areaNames[intercoFileData.index_pays_extremite]); + std::string linkName = pays_or + " - " + pays_ex; + _intercoIndexMap[linkName] = intercoFileData.index_interco; + } } -std::vector CandidatesINIReader::ReadAntaresIntercoFile(const std::string& antaresIntercoFile) { - - std::vector result; - - std::ifstream interco_filestream(antaresIntercoFile); - if (!interco_filestream.good()) { - std::string message = "unable to open " + antaresIntercoFile; - throw std::runtime_error(message); - } - - std::string line; - while (std::getline(interco_filestream, line)) { - std::stringstream buffer(line); - if (!line.empty() && line.front() != '#') { - - IntercoFileData intercoData; - buffer >> intercoData.index_interco; - buffer >> intercoData.index_pays_origine; - buffer >> intercoData.index_pays_extremite; - - result.push_back(intercoData); - } +std::vector CandidatesINIReader::ReadAntaresIntercoFile( + const std::string &antaresIntercoFile) { + std::vector result; + + std::ifstream interco_filestream(antaresIntercoFile); + if (!interco_filestream.good()) { + std::string message = "unable to open " + antaresIntercoFile; + throw std::runtime_error(message); + } + + std::string line; + while (std::getline(interco_filestream, line)) { + std::stringstream buffer(line); + if (!line.empty() && line.front() != '#') { + IntercoFileData intercoData; + buffer >> intercoData.index_interco; + buffer >> intercoData.index_pays_origine; + buffer >> intercoData.index_pays_extremite; + + result.push_back(intercoData); } - return result; + } + return result; } -std::vector CandidatesINIReader::ReadAreaFile(const std::string& areaFile){ - - std::vector result; - - std::ifstream area_filestream(areaFile); - if (!area_filestream.good()) { - std::string message = "unable to open " + areaFile; - throw std::runtime_error(message); - } - - std::string line; - while (std::getline(area_filestream, line)) { - if (!line.empty() && line.front() != '#') { - result.push_back(StringUtils::ToLowercase(line)); - } +std::vector CandidatesINIReader::ReadAreaFile( + const std::string &areaFile) { + std::vector result; + + std::ifstream area_filestream(areaFile); + if (!area_filestream.good()) { + std::string message = "unable to open " + areaFile; + throw std::runtime_error(message); + } + + std::string line; + while (std::getline(area_filestream, line)) { + if (!line.empty() && line.front() != '#') { + result.push_back(StringUtils::ToLowercase(line)); } - return result; + } + return result; } -std::string getStrVal(const INIReader &reader, const std::string §ionName, const std::string& key) { - std::string val = reader.Get(sectionName, key, "NA"); - if ((val != "NA") && (val != "na")) - return val; - else - return ""; +std::string getStrVal(const INIReader &reader, const std::string §ionName, + const std::string &key) { + std::string val = reader.Get(sectionName, key, "NA"); + if ((val != "NA") && (val != "na")) + return val; + else + return ""; } -double getDblVal(const INIReader &reader, const std::string §ionName, const std::string& key) { - - double d_val(0); - - std::string val = reader.Get(sectionName, key, "NA"); - if (val != "NA") { - std::stringstream buffer(val); - buffer >> d_val;; - } - return d_val; +double getDblVal(const INIReader &reader, const std::string §ionName, + const std::string &key) { + double d_val(0); + + std::string val = reader.Get(sectionName, key, "NA"); + if (val != "NA") { + std::stringstream buffer(val); + buffer >> d_val; + ; + } + return d_val; } -bool getBoolVal(const INIReader &reader, const std::string §ionName, const std::string& key) { - - bool result = reader.GetBoolean(sectionName, key, true); - return result; +bool getBoolVal(const INIReader &reader, const std::string §ionName, + const std::string &key) { + bool result = reader.GetBoolean(sectionName, key, true); + return result; } -bool CandidatesINIReader::checkArea(std::string const & areaName_p) const -{ - bool found_l = std::find(_areaNames.cbegin(), _areaNames.cend(), areaName_p) != _areaNames.cend(); - return found_l; +bool CandidatesINIReader::checkArea(std::string const &areaName_p) const { + bool found_l = std::find(_areaNames.cbegin(), _areaNames.cend(), + areaName_p) != _areaNames.cend(); + return found_l; } -std::vector CandidatesINIReader::readCandidateData(const std::string& candidateFile){ - std::vector result; +std::vector CandidatesINIReader::readCandidateData( + const std::string &candidateFile) { + std::vector result; - INIReader reader(candidateFile); - std::stringstream ss; - std::set sections = reader.Sections(); - for (auto const & sectionName : sections) { + INIReader reader(candidateFile); + std::stringstream ss; + std::set sections = reader.Sections(); + for (auto const §ionName : sections) { + CandidateData candidateData = + readCandidateSection(candidateFile, reader, sectionName); + result.push_back(candidateData); + } - CandidateData candidateData = readCandidateSection(candidateFile, reader, sectionName); - result.push_back(candidateData); - } - - return result; + return result; } -CandidateData CandidatesINIReader::readCandidateSection(const std::string &candidateFile, const INIReader &reader, - const std::string §ionName) { - CandidateData candidateData; - candidateData.name = StringUtils::ToLowercase(getStrVal(reader,sectionName,"name")); - candidateData.link_name = StringUtils::ToLowercase(getStrVal(reader, sectionName, "link")); - size_t i = candidateData.link_name.find(" - "); - if (i != std::string::npos) { - candidateData.linkor = candidateData.link_name.substr(0, i); - candidateData.linkex = candidateData.link_name.substr(i + 3, candidateData.link_name.size()); - if(!checkArea(candidateData.linkor)) - { - std::string message = "Unrecognized area " + candidateData.linkor + " in section " + sectionName + " in " + candidateFile + "."; - throw std::runtime_error(message); - } - if(!checkArea(candidateData.linkex )) - { - std::string message = "Unrecognized area " + candidateData.linkex + " in section " + sectionName + " in " + candidateFile + "."; - throw std::runtime_error(message); - } +CandidateData CandidatesINIReader::readCandidateSection( + const std::string &candidateFile, const INIReader &reader, + const std::string §ionName) { + CandidateData candidateData; + candidateData.name = + StringUtils::ToLowercase(getStrVal(reader, sectionName, "name")); + candidateData.link_name = + StringUtils::ToLowercase(getStrVal(reader, sectionName, "link")); + size_t i = candidateData.link_name.find(" - "); + if (i != std::string::npos) { + candidateData.linkor = candidateData.link_name.substr(0, i); + candidateData.linkex = + candidateData.link_name.substr(i + 3, candidateData.link_name.size()); + if (!checkArea(candidateData.linkor)) { + std::string message = "Unrecognized area " + candidateData.linkor + + " in section " + sectionName + " in " + + candidateFile + "."; + throw std::runtime_error(message); } - - //Check if interco is available - auto it = _intercoIndexMap.find(candidateData.link_name); - if (it == _intercoIndexMap.end()) { - std::string message = "cannot link candidate " + candidateData.name + " to interco id"; - throw std::runtime_error(message); + if (!checkArea(candidateData.linkex)) { + std::string message = "Unrecognized area " + candidateData.linkex + + " in section " + sectionName + " in " + + candidateFile + "."; + throw std::runtime_error(message); } - candidateData.link_id = it->second; - candidateData.link_profile = getStrVal(reader,sectionName,"link-profile"); - candidateData.installed_link_profile_name = getStrVal(reader, sectionName, "already-installed-link-profile"); - - candidateData.annual_cost_per_mw = getDblVal(reader,sectionName,"annual-cost-per-mw"); - candidateData.max_investment = getDblVal(reader,sectionName,"max-investment"); - candidateData.unit_size = getDblVal(reader,sectionName,"unit-size"); - candidateData.max_units = getDblVal(reader,sectionName,"max-units"); - candidateData.already_installed_capacity = getDblVal(reader,sectionName,"already-installed-capacity"); - candidateData.enable = getBoolVal(reader,sectionName, "enable"); - return candidateData; + } + + // Check if interco is available + auto it = _intercoIndexMap.find(candidateData.link_name); + if (it == _intercoIndexMap.end()) { + std::string message = + "cannot link candidate " + candidateData.name + " to interco id"; + throw std::runtime_error(message); + } + candidateData.link_id = it->second; + candidateData.link_profile = getStrVal(reader, sectionName, "link-profile"); + candidateData.installed_link_profile_name = + getStrVal(reader, sectionName, "already-installed-link-profile"); + + candidateData.annual_cost_per_mw = + getDblVal(reader, sectionName, "annual-cost-per-mw"); + candidateData.max_investment = + getDblVal(reader, sectionName, "max-investment"); + candidateData.unit_size = getDblVal(reader, sectionName, "unit-size"); + candidateData.max_units = getDblVal(reader, sectionName, "max-units"); + candidateData.already_installed_capacity = + getDblVal(reader, sectionName, "already-installed-capacity"); + candidateData.enable = getBoolVal(reader, sectionName, "enable"); + return candidateData; } diff --git a/src/cpp/lpnamer/input_reader/CandidatesINIReader.h b/src/cpp/lpnamer/input_reader/CandidatesINIReader.h index 95ac91f38..3c20501fb 100644 --- a/src/cpp/lpnamer/input_reader/CandidatesINIReader.h +++ b/src/cpp/lpnamer/input_reader/CandidatesINIReader.h @@ -6,35 +6,36 @@ #include #include -#include "INIReader.h" #include "Candidate.h" +#include "INIReader.h" struct IntercoFileData { - int index_interco; - int index_pays_origine; - int index_pays_extremite; + int index_interco; + int index_pays_origine; + int index_pays_extremite; }; class CandidatesINIReader { - -public: - - CandidatesINIReader(const std::string& antaresIntercoFile, const std::string& areaFile); - - static std::vector ReadAntaresIntercoFile(const std::string& antaresIntercoFile); - static std::vector ReadAreaFile(const std::string& areaFile); - - std::vector readCandidateData(const std::string& candidateFile); - -private: - - bool checkArea(std::string const & areaName_p) const; - CandidateData readCandidateSection(const std::string &candidateFile, const INIReader &reader, const std::string §ionName); - - std::map _intercoIndexMap; - std::vector _intercoFileData; - std::vector _areaNames; + public: + CandidatesINIReader(const std::string& antaresIntercoFile, + const std::string& areaFile); + + static std::vector ReadAntaresIntercoFile( + const std::string& antaresIntercoFile); + static std::vector ReadAreaFile(const std::string& areaFile); + + std::vector readCandidateData( + const std::string& candidateFile); + + private: + bool checkArea(std::string const& areaName_p) const; + CandidateData readCandidateSection(const std::string& candidateFile, + const INIReader& reader, + const std::string& sectionName); + + std::map _intercoIndexMap; + std::vector _intercoFileData; + std::vector _areaNames; }; - -#endif //ANTARESXPANSION_CANDIDATESINIREADER_H +#endif // ANTARESXPANSION_CANDIDATESINIREADER_H diff --git a/src/cpp/lpnamer/input_reader/INIReader.h b/src/cpp/lpnamer/input_reader/INIReader.h index d7be51c13..125cc17e8 100644 --- a/src/cpp/lpnamer/input_reader/INIReader.h +++ b/src/cpp/lpnamer/input_reader/INIReader.h @@ -24,8 +24,8 @@ extern "C" { #include /* Typedef for prototype of handler function. */ -typedef int (*ini_handler)(void* user, const char* section, - const char* name, const char* value); +typedef int (*ini_handler)(void* user, const char* section, const char* name, + const char* value); /* Typedef for prototype of fgets-style reader function. */ typedef char* (*ini_reader)(char* str, int num, void* stream); @@ -109,8 +109,8 @@ home page for more info: #define _CRT_SECURE_NO_WARNINGS #endif -#include #include +#include #include #if !INI_USE_STACK @@ -121,185 +121,165 @@ home page for more info: #define MAX_NAME 50 /* Strip whitespace chars off end of given string, in place. Return s. */ -inline static char* rstrip(char* s) -{ - char* p = s + strlen(s); - while (p > s && isspace((unsigned char)(*--p))) - *p = '\0'; - return s; +inline static char* rstrip(char* s) { + char* p = s + strlen(s); + while (p > s && isspace((unsigned char)(*--p))) *p = '\0'; + return s; } /* Return pointer to first non-whitespace char in given string. */ -inline static char* lskip(const char* s) -{ - while (*s && isspace((unsigned char)(*s))) - s++; - return (char*)s; +inline static char* lskip(const char* s) { + while (*s && isspace((unsigned char)(*s))) s++; + return (char*)s; } /* Return pointer to first char (of chars) or inline comment in given string, or pointer to null at end of string if neither found. Inline comment must be prefixed by a whitespace character to register as a comment. */ -inline static char* find_chars_or_comment(const char* s, const char* chars) -{ +inline static char* find_chars_or_comment(const char* s, const char* chars) { #if INI_ALLOW_INLINE_COMMENTS - int was_space = 0; - while (*s && (!chars || !strchr(chars, *s)) && - !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { - was_space = isspace((unsigned char)(*s)); - s++; - } + int was_space = 0; + while (*s && (!chars || !strchr(chars, *s)) && + !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { + was_space = isspace((unsigned char)(*s)); + s++; + } #else - while (*s && (!chars || !strchr(chars, *s))) { - s++; - } + while (*s && (!chars || !strchr(chars, *s))) { + s++; + } #endif - return (char*)s; + return (char*)s; } /* Version of strncpy that ensures dest (size bytes) is null-terminated. */ -inline static char* strncpy0(char* dest, const char* src, size_t size) -{ - strncpy(dest, src, size); - dest[size - 1] = '\0'; - return dest; +inline static char* strncpy0(char* dest, const char* src, size_t size) { + strncpy(dest, src, size); + dest[size - 1] = '\0'; + return dest; } /* See documentation in header file. */ -inline int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, - void* user) -{ - /* Uses a fair bit of stack (use heap instead if you need to) */ +inline int ini_parse_stream(ini_reader reader, void* stream, + ini_handler handler, void* user) { + /* Uses a fair bit of stack (use heap instead if you need to) */ #if INI_USE_STACK - char line[INI_MAX_LINE]; + char line[INI_MAX_LINE]; #else - char* line; + char* line; #endif - char section[MAX_SECTION] = ""; - char prev_name[MAX_NAME] = ""; + char section[MAX_SECTION] = ""; + char prev_name[MAX_NAME] = ""; - char* start; - char* end; - char* name; - char* value; - int lineno = 0; - int error = 0; + char* start; + char* end; + char* name; + char* value; + int lineno = 0; + int error = 0; #if !INI_USE_STACK - line = (char*)malloc(INI_MAX_LINE); - if (!line) { - return -2; - } + line = (char*)malloc(INI_MAX_LINE); + if (!line) { + return -2; + } #endif - /* Scan through stream line by line */ - while (reader(line, INI_MAX_LINE, stream) != NULL) { - lineno++; + /* Scan through stream line by line */ + while (reader(line, INI_MAX_LINE, stream) != NULL) { + lineno++; - start = line; + start = line; #if INI_ALLOW_BOM - if (lineno == 1 && (unsigned char)start[0] == 0xEF && - (unsigned char)start[1] == 0xBB && - (unsigned char)start[2] == 0xBF) { - start += 3; - } + if (lineno == 1 && (unsigned char)start[0] == 0xEF && + (unsigned char)start[1] == 0xBB && (unsigned char)start[2] == 0xBF) { + start += 3; + } #endif - start = lskip(rstrip(start)); + start = lskip(rstrip(start)); - if (*start == ';' || *start == '#') { - /* Per Python configparser, allow both ; and # comments at the - start of a line */ - } + if (*start == ';' || *start == '#') { + /* Per Python configparser, allow both ; and # comments at the + start of a line */ + } #if INI_ALLOW_MULTILINE - else if (*prev_name && *start && start > line) { + else if (*prev_name && *start && start > line) { #if INI_ALLOW_INLINE_COMMENTS - end = find_chars_or_comment(start, NULL); - if (*end) - *end = '\0'; - rstrip(start); + end = find_chars_or_comment(start, NULL); + if (*end) *end = '\0'; + rstrip(start); #endif - /* Non-blank line with leading whitespace, treat as continuation - of previous name's value (as per Python configparser). */ - if (!handler(user, section, prev_name, start) && !error) - error = lineno; - } + /* Non-blank line with leading whitespace, treat as continuation + of previous name's value (as per Python configparser). */ + if (!handler(user, section, prev_name, start) && !error) error = lineno; + } #endif - else if (*start == '[') { - /* A "[section]" line */ - end = find_chars_or_comment(start + 1, "]"); - if (*end == ']') { - *end = '\0'; - strncpy0(section, start + 1, sizeof(section)); - *prev_name = '\0'; - } - else if (!error) { - /* No ']' found on section line */ - error = lineno; - } - } - else if (*start) { - /* Not a comment, must be a name[=:]value pair */ - end = find_chars_or_comment(start, "=:"); - if (*end == '=' || *end == ':') { - *end = '\0'; - name = rstrip(start); - value = lskip(end + 1); + else if (*start == '[') { + /* A "[section]" line */ + end = find_chars_or_comment(start + 1, "]"); + if (*end == ']') { + *end = '\0'; + strncpy0(section, start + 1, sizeof(section)); + *prev_name = '\0'; + } else if (!error) { + /* No ']' found on section line */ + error = lineno; + } + } else if (*start) { + /* Not a comment, must be a name[=:]value pair */ + end = find_chars_or_comment(start, "=:"); + if (*end == '=' || *end == ':') { + *end = '\0'; + name = rstrip(start); + value = lskip(end + 1); #if INI_ALLOW_INLINE_COMMENTS - end = find_chars_or_comment(value, NULL); - if (*end) - *end = '\0'; + end = find_chars_or_comment(value, NULL); + if (*end) *end = '\0'; #endif - rstrip(value); - - /* Valid name[=:]value pair found, call handler */ - strncpy0(prev_name, name, sizeof(prev_name)); - if (!handler(user, section, name, value) && !error) - error = lineno; - } - else if (!error) { - /* No '=' or ':' found on name[=:]value line */ - error = lineno; - } - } + rstrip(value); + + /* Valid name[=:]value pair found, call handler */ + strncpy0(prev_name, name, sizeof(prev_name)); + if (!handler(user, section, name, value) && !error) error = lineno; + } else if (!error) { + /* No '=' or ':' found on name[=:]value line */ + error = lineno; + } + } #if INI_STOP_ON_FIRST_ERROR - if (error) - break; + if (error) break; #endif - } + } #if !INI_USE_STACK - free(line); + free(line); #endif - return error; + return error; } /* See documentation in header file. */ -inline int ini_parse_file(FILE* file, ini_handler handler, void* user) -{ - return ini_parse_stream((ini_reader)fgets, file, handler, user); +inline int ini_parse_file(FILE* file, ini_handler handler, void* user) { + return ini_parse_stream((ini_reader)fgets, file, handler, user); } /* See documentation in header file. */ -inline int ini_parse(const char* filename, ini_handler handler, void* user) -{ - FILE* file; - int error; - - file = fopen(filename, "r"); - if (!file) - return -1; - error = ini_parse_file(file, handler, user); - fclose(file); - return error; +inline int ini_parse(const char* filename, ini_handler handler, void* user) { + FILE* file; + int error; + + file = fopen(filename, "r"); + if (!file) return -1; + error = ini_parse_file(file, handler, user); + fclose(file); + return error; } #endif /* __INI_H__ */ - #ifndef __INIREADER_H__ #define __INIREADER_H__ @@ -309,57 +289,59 @@ inline int ini_parse(const char* filename, ini_handler handler, void* user) // Read an INI file into easy-to-access name/value pairs. (Note that I've gone // for simplicity here rather than speed, but it should be pretty decent.) -class INIReader -{ -public: - // Empty Constructor - INIReader() {}; - - // Construct INIReader and parse given filename. See ini.h for more info - // about the parsing. - INIReader(std::string filename); - - // Construct INIReader and parse given file. See ini.h for more info - // about the parsing. - INIReader(FILE *file); - - // Return the result of ini_parse(), i.e., 0 on success, line number of - // first error on parse error, or -1 on file open error. - int ParseError() const; - - // Return the list of sections found in ini file - const std::set& Sections() const; - - // Get a string value from INI file, returning default_value if not found. - std::string Get(std::string section, std::string name, - std::string default_value) const; - - // Get an integer (long) value from INI file, returning default_value if - // not found or not a valid integer (decimal "1234", "-1234", or hex "0x4d2"). - long GetInteger(std::string section, std::string name, long default_value) const; - - // Get a real (floating point double) value from INI file, returning - // default_value if not found or not a valid floating point value - // according to strtod(). - double GetReal(std::string section, std::string name, double default_value) const; - - // Get a boolean value from INI file, returning default_value if not found or if - // not a valid true/false value. Valid true values are "true", "yes", "on", "1", - // and valid false values are "false", "no", "off", "0" (not case sensitive). - bool GetBoolean(std::string section, std::string name, bool default_value) const; - -protected: - int _error; - std::map _values; - std::set _sections; - static std::string MakeKey(std::string section, std::string name); - static int ValueHandler(void* user, const char* section, const char* name, - const char* value); +class INIReader { + public: + // Empty Constructor + INIReader(){}; + + // Construct INIReader and parse given filename. See ini.h for more info + // about the parsing. + INIReader(std::string filename); + + // Construct INIReader and parse given file. See ini.h for more info + // about the parsing. + INIReader(FILE* file); + + // Return the result of ini_parse(), i.e., 0 on success, line number of + // first error on parse error, or -1 on file open error. + int ParseError() const; + + // Return the list of sections found in ini file + const std::set& Sections() const; + + // Get a string value from INI file, returning default_value if not found. + std::string Get(std::string section, std::string name, + std::string default_value) const; + + // Get an integer (long) value from INI file, returning default_value if + // not found or not a valid integer (decimal "1234", "-1234", or hex "0x4d2"). + long GetInteger(std::string section, std::string name, + long default_value) const; + + // Get a real (floating point double) value from INI file, returning + // default_value if not found or not a valid floating point value + // according to strtod(). + double GetReal(std::string section, std::string name, + double default_value) const; + + // Get a boolean value from INI file, returning default_value if not found or + // if not a valid true/false value. Valid true values are "true", "yes", "on", + // "1", and valid false values are "false", "no", "off", "0" (not case + // sensitive). + bool GetBoolean(std::string section, std::string name, + bool default_value) const; + + protected: + int _error; + std::map _values; + std::set _sections; + static std::string MakeKey(std::string section, std::string name); + static int ValueHandler(void* user, const char* section, const char* name, + const char* value); }; #endif // __INIREADER_H__ - #ifndef __INIREADER__ #define __INIREADER__ @@ -367,82 +349,74 @@ class INIReader #include #include -inline INIReader::INIReader(std::string filename) -{ - _error = ini_parse(filename.c_str(), ValueHandler, this); +inline INIReader::INIReader(std::string filename) { + _error = ini_parse(filename.c_str(), ValueHandler, this); } -inline INIReader::INIReader(FILE *file) -{ - _error = ini_parse_file(file, ValueHandler, this); +inline INIReader::INIReader(FILE* file) { + _error = ini_parse_file(file, ValueHandler, this); } -inline int INIReader::ParseError() const -{ - return _error; -} +inline int INIReader::ParseError() const { return _error; } -inline const std::set& INIReader::Sections() const -{ - return _sections; +inline const std::set& INIReader::Sections() const { + return _sections; } -inline std::string INIReader::Get(std::string section, std::string name, std::string default_value) const -{ - std::string key = MakeKey(section, name); - return _values.count(key) ? _values.at(key) : default_value; +inline std::string INIReader::Get(std::string section, std::string name, + std::string default_value) const { + std::string key = MakeKey(section, name); + return _values.count(key) ? _values.at(key) : default_value; } -inline long INIReader::GetInteger(std::string section, std::string name, long default_value) const -{ - std::string valstr = Get(section, name, ""); - const char* value = valstr.c_str(); - char* end; - // This parses "1234" (decimal) and also "0x4D2" (hex) - long n = strtol(value, &end, 0); - return end > value ? n : default_value; +inline long INIReader::GetInteger(std::string section, std::string name, + long default_value) const { + std::string valstr = Get(section, name, ""); + const char* value = valstr.c_str(); + char* end; + // This parses "1234" (decimal) and also "0x4D2" (hex) + long n = strtol(value, &end, 0); + return end > value ? n : default_value; } -inline double INIReader::GetReal(std::string section, std::string name, double default_value) const -{ - std::string valstr = Get(section, name, ""); - const char* value = valstr.c_str(); - char* end; - double n = strtod(value, &end); - return end > value ? n : default_value; +inline double INIReader::GetReal(std::string section, std::string name, + double default_value) const { + std::string valstr = Get(section, name, ""); + const char* value = valstr.c_str(); + char* end; + double n = strtod(value, &end); + return end > value ? n : default_value; } -inline bool INIReader::GetBoolean(std::string section, std::string name, bool default_value) const -{ - std::string valstr = Get(section, name, ""); - // Convert to lower case to make string comparisons case-insensitive - std::transform(valstr.begin(), valstr.end(), valstr.begin(), ::tolower); - if (valstr == "true" || valstr == "yes" || valstr == "on" || valstr == "1") - return true; - else if (valstr == "false" || valstr == "no" || valstr == "off" || valstr == "0") - return false; - else - return default_value; +inline bool INIReader::GetBoolean(std::string section, std::string name, + bool default_value) const { + std::string valstr = Get(section, name, ""); + // Convert to lower case to make string comparisons case-insensitive + std::transform(valstr.begin(), valstr.end(), valstr.begin(), ::tolower); + if (valstr == "true" || valstr == "yes" || valstr == "on" || valstr == "1") + return true; + else if (valstr == "false" || valstr == "no" || valstr == "off" || + valstr == "0") + return false; + else + return default_value; } -inline std::string INIReader::MakeKey(std::string section, std::string name) -{ - std::string key = section + "=" + name; - // Convert to lower case to make section/name lookups case-insensitive - std::transform(key.begin(), key.end(), key.begin(), ::tolower); - return key; +inline std::string INIReader::MakeKey(std::string section, std::string name) { + std::string key = section + "=" + name; + // Convert to lower case to make section/name lookups case-insensitive + std::transform(key.begin(), key.end(), key.begin(), ::tolower); + return key; } -inline int INIReader::ValueHandler(void* user, const char* section, const char* name, - const char* value) -{ - INIReader* reader = (INIReader*)user; - std::string key = MakeKey(section, name); - if (reader->_values[key].size() > 0) - reader->_values[key] += "\n"; - reader->_values[key] += value; - reader->_sections.insert(section); - return 1; +inline int INIReader::ValueHandler(void* user, const char* section, + const char* name, const char* value) { + INIReader* reader = (INIReader*)user; + std::string key = MakeKey(section, name); + if (reader->_values[key].size() > 0) reader->_values[key] += "\n"; + reader->_values[key] += value; + reader->_sections.insert(section); + return 1; } #endif // __INIREADER__ diff --git a/src/cpp/lpnamer/input_reader/LinkProfileReader.cpp b/src/cpp/lpnamer/input_reader/LinkProfileReader.cpp index 4af1d0381..1d7b2964b 100644 --- a/src/cpp/lpnamer/input_reader/LinkProfileReader.cpp +++ b/src/cpp/lpnamer/input_reader/LinkProfileReader.cpp @@ -1,56 +1,52 @@ #include "LinkProfileReader.h" -#include "helpers/Path.h" -LinkProfile LinkProfileReader::ReadLinkProfile(const std::string &filename) -{ - std::ifstream infile(filename); - if (!infile.good()) - { - throw std::runtime_error("unable to open : " + filename); - } - LinkProfile result; - result._directLinkProfile.reserve(8760); - double value; - std::string line; - for (size_t line_id(0); line_id < 8760; ++line_id) - { - if (std::getline(infile, line)) - { - std::stringstream buffer(line); - buffer >> value; - result._directLinkProfile.push_back(value); - if (buffer >> value) - { - result._indirectLinkProfile.reserve(8760); - result._indirectLinkProfile.push_back(value); - } - } - else - { - throw std::runtime_error("error not enough line in link-profile " + filename); - } +#include "helpers/Path.h" +LinkProfile LinkProfileReader::ReadLinkProfile(const std::string &filename) { + std::ifstream infile(filename); + if (!infile.good()) { + throw std::runtime_error("unable to open : " + filename); + } + LinkProfile result; + result._directLinkProfile.reserve(8760); + double value; + std::string line; + for (size_t line_id(0); line_id < 8760; ++line_id) { + if (std::getline(infile, line)) { + std::stringstream buffer(line); + buffer >> value; + result._directLinkProfile.push_back(value); + if (buffer >> value) { + result._indirectLinkProfile.reserve(8760); + result._indirectLinkProfile.push_back(value); + } + } else { + throw std::runtime_error("error not enough line in link-profile " + + filename); } - infile.close(); + } + infile.close(); - return result; + return result; } -const std::map LinkProfileReader::getLinkProfileMap(const std::string &capacity_folder, const std::vector &candidateList) -{ - std::map mapLinkProfile; - for (const auto &candidate_data : candidateList) - { - importProfile(mapLinkProfile, capacity_folder, candidate_data.installed_link_profile_name); - importProfile(mapLinkProfile, capacity_folder, candidate_data.link_profile); - } - return mapLinkProfile; +const std::map LinkProfileReader::getLinkProfileMap( + const std::string &capacity_folder, + const std::vector &candidateList) { + std::map mapLinkProfile; + for (const auto &candidate_data : candidateList) { + importProfile(mapLinkProfile, capacity_folder, + candidate_data.installed_link_profile_name); + importProfile(mapLinkProfile, capacity_folder, candidate_data.link_profile); + } + return mapLinkProfile; } -void LinkProfileReader::importProfile(std::map &mapLinkProfile, const std::string &capacitySubfolder, const std::string &profile_name) -{ - if (!profile_name.empty() && mapLinkProfile.find(profile_name) == mapLinkProfile.end()) - { - - mapLinkProfile[profile_name] = LinkProfileReader::ReadLinkProfile((Path(capacitySubfolder) / profile_name).get_str()); - } +void LinkProfileReader::importProfile( + std::map &mapLinkProfile, + const std::string &capacitySubfolder, const std::string &profile_name) { + if (!profile_name.empty() && + mapLinkProfile.find(profile_name) == mapLinkProfile.end()) { + mapLinkProfile[profile_name] = LinkProfileReader::ReadLinkProfile( + (Path(capacitySubfolder) / profile_name).get_str()); + } } diff --git a/src/cpp/lpnamer/input_reader/LinkProfileReader.h b/src/cpp/lpnamer/input_reader/LinkProfileReader.h index a8922b659..e7e5c70bc 100644 --- a/src/cpp/lpnamer/input_reader/LinkProfileReader.h +++ b/src/cpp/lpnamer/input_reader/LinkProfileReader.h @@ -1,21 +1,22 @@ #ifndef ANTARESXPANSION_LINKPROFILEREADER_H #define ANTARESXPANSION_LINKPROFILEREADER_H -#include "LinkProfile.h" #include "Candidate.h" +#include "LinkProfile.h" class LinkProfileReader { - -public: - - LinkProfileReader() = default; - - static LinkProfile ReadLinkProfile(const std::string& filename); - static const std::map getLinkProfileMap(const std::string& capacity_folder, const std::vector& candidateList); -private: - static void importProfile(std::map& mapLinkProfile, const std::string& capacitySubfolder, const std::string& profile_name); - + public: + LinkProfileReader() = default; + + static LinkProfile ReadLinkProfile(const std::string& filename); + static const std::map getLinkProfileMap( + const std::string& capacity_folder, + const std::vector& candidateList); + + private: + static void importProfile(std::map& mapLinkProfile, + const std::string& capacitySubfolder, + const std::string& profile_name); }; - -#endif //ANTARESXPANSION_LINKPROFILEREADER_H +#endif // ANTARESXPANSION_LINKPROFILEREADER_H diff --git a/src/cpp/lpnamer/input_reader/VariableFileReader.cpp b/src/cpp/lpnamer/input_reader/VariableFileReader.cpp index 5f7edc3e3..0d2172965 100644 --- a/src/cpp/lpnamer/input_reader/VariableFileReader.cpp +++ b/src/cpp/lpnamer/input_reader/VariableFileReader.cpp @@ -1,93 +1,100 @@ // +#include "VariableFileReader.h" + #include #include -#include "VariableFileReader.h" - -void updateMapColumn(const std::vector& links, int link_id, colId id, int time_step,std::map& mapColumn ){ - auto it = std::find_if(links.begin(), links.end(), [link_id] (const ActiveLink& link){ - return link.get_idLink() == link_id; - }); +void updateMapColumn(const std::vector& links, int link_id, + colId id, int time_step, + std::map& mapColumn) { + auto it = std::find_if(links.begin(), links.end(), + [link_id](const ActiveLink& link) { + return link.get_idLink() == link_id; + }); - if (it != links.end()){ - mapColumn[link_id].push_back({id, time_step}); - } + if (it != links.end()) { + mapColumn[link_id].push_back({id, time_step}); + } } -VariableFileReader::VariableFileReader(const std::string& fileName, const std::vector& links, - const VariableFileReadNameConfiguration& variable_name_config) { - - std::string line; - std::ifstream file(fileName.c_str()); - if (!file.good()) { - throw std::runtime_error("Unable to open '" + fileName +"'"); - } - while (std::getline(file, line)) { - - std::string name = getVarNameFromLine(line); - _variables.push_back(name); +VariableFileReader::VariableFileReader( + const std::string& fileName, const std::vector& links, + const VariableFileReadNameConfiguration& variable_name_config) { + std::string line; + std::ifstream file(fileName.c_str()); + if (!file.good()) { + throw std::runtime_error("Unable to open '" + fileName + "'"); + } + while (std::getline(file, line)) { + std::string name = getVarNameFromLine(line); + _variables.push_back(name); - std::istringstream buffer(line); - colId id; - std::string variable; - buffer >> id; - buffer >> variable; + std::istringstream buffer(line); + colId id; + std::string variable; + buffer >> id; + buffer >> variable; - if (variable == variable_name_config.ntc_variable_name) { - int pays; - int link_id; - int time_step; - buffer >> pays; - buffer >> link_id; - buffer >> time_step; - updateMapColumn(links, link_id, id, time_step,_ntc_p_var_columns); - }else if(variable == variable_name_config.cost_extremite_variable_name){ - int link_id; - int time_step; - buffer >> link_id; - buffer >> time_step; - updateMapColumn(links, link_id, id, time_step,_indirect_cost_p_var_columns); - }else if(variable == variable_name_config.cost_origin_variable_name){ - int link_id; - int time_step; - buffer >> link_id; - buffer >> time_step; - updateMapColumn(links, link_id, id, time_step,_direct_cost_p_var_columns); - } + if (variable == variable_name_config.ntc_variable_name) { + int pays; + int link_id; + int time_step; + buffer >> pays; + buffer >> link_id; + buffer >> time_step; + updateMapColumn(links, link_id, id, time_step, _ntc_p_var_columns); + } else if (variable == variable_name_config.cost_extremite_variable_name) { + int link_id; + int time_step; + buffer >> link_id; + buffer >> time_step; + updateMapColumn(links, link_id, id, time_step, + _indirect_cost_p_var_columns); + } else if (variable == variable_name_config.cost_origin_variable_name) { + int link_id; + int time_step; + buffer >> link_id; + buffer >> time_step; + updateMapColumn(links, link_id, id, time_step, + _direct_cost_p_var_columns); } - file.close(); + } + file.close(); } -std::string VariableFileReader::getVarNameFromLine(const std::string &line) const { - std::ostringstream name; - { - std::istringstream buffer(line); - std::string part; - bool is_first(true); - while (buffer >> part) { - if (!is_first) { - name << part << "_"; - } - else { - is_first = false; - } - } +std::string VariableFileReader::getVarNameFromLine( + const std::string& line) const { + std::ostringstream name; + { + std::istringstream buffer(line); + std::string part; + bool is_first(true); + while (buffer >> part) { + if (!is_first) { + name << part << "_"; + } else { + is_first = false; + } } - return name.str(); + } + return name.str(); } const std::vector& VariableFileReader::getVariables() const { - return _variables; + return _variables; } -const std::map& VariableFileReader::getNtcVarColumns() const{ - return _ntc_p_var_columns; +const std::map& VariableFileReader::getNtcVarColumns() + const { + return _ntc_p_var_columns; } -const std::map& VariableFileReader::getDirectCostVarColumns() const { - return _direct_cost_p_var_columns; +const std::map& +VariableFileReader::getDirectCostVarColumns() const { + return _direct_cost_p_var_columns; } -const std::map& VariableFileReader::getIndirectCostVarColumns() const { - return _indirect_cost_p_var_columns; +const std::map& +VariableFileReader::getIndirectCostVarColumns() const { + return _indirect_cost_p_var_columns; } diff --git a/src/cpp/lpnamer/input_reader/VariableFileReader.h b/src/cpp/lpnamer/input_reader/VariableFileReader.h index 005856675..de8050e1d 100644 --- a/src/cpp/lpnamer/input_reader/VariableFileReader.h +++ b/src/cpp/lpnamer/input_reader/VariableFileReader.h @@ -3,39 +3,36 @@ #ifndef ANTARESXPANSION_VARIABLEFILEREADER_H #define ANTARESXPANSION_VARIABLEFILEREADER_H -#include -#include - #include #include +#include +#include + struct VariableFileReadNameConfiguration { - std::string ntc_variable_name; - std::string cost_origin_variable_name; - std::string cost_extremite_variable_name; + std::string ntc_variable_name; + std::string cost_origin_variable_name; + std::string cost_extremite_variable_name; }; class VariableFileReader { - -public: - - VariableFileReader(const std::string& fileName, const std::vector& links, - const VariableFileReadNameConfiguration& variable_name_config); - - const std::vector& getVariables() const; - const std::map& getNtcVarColumns() const; - const std::map& getDirectCostVarColumns() const; - const std::map& getIndirectCostVarColumns() const; - -private: - - std::string getVarNameFromLine(const std::string &line) const; - - std::vector _variables; - std::map _ntc_p_var_columns; - std::map _indirect_cost_p_var_columns; - std::map _direct_cost_p_var_columns; + public: + VariableFileReader( + const std::string& fileName, const std::vector& links, + const VariableFileReadNameConfiguration& variable_name_config); + + const std::vector& getVariables() const; + const std::map& getNtcVarColumns() const; + const std::map& getDirectCostVarColumns() const; + const std::map& getIndirectCostVarColumns() const; + + private: + std::string getVarNameFromLine(const std::string& line) const; + + std::vector _variables; + std::map _ntc_p_var_columns; + std::map _indirect_cost_p_var_columns; + std::map _direct_cost_p_var_columns; }; - -#endif //ANTARESXPANSION_VARIABLEFILEREADER_H +#endif // ANTARESXPANSION_VARIABLEFILEREADER_H diff --git a/src/cpp/lpnamer/model/ActiveLinks.cpp b/src/cpp/lpnamer/model/ActiveLinks.cpp index 0643f86f1..aceab85b9 100644 --- a/src/cpp/lpnamer/model/ActiveLinks.cpp +++ b/src/cpp/lpnamer/model/ActiveLinks.cpp @@ -1,189 +1,182 @@ #include "ActiveLinks.h" -#include -#include - -bool doubles_are_different(const double a, - const double b) { - constexpr double MACHINE_EPSILON = std::numeric_limits::epsilon(); - return std::abs(a - b) > MACHINE_EPSILON; -} - - -void ActiveLinksBuilder::addCandidate(const CandidateData &candidate_data) { - - unsigned int indexLink = getLinkIndexOf(candidate_data.link_id); - _links.at(indexLink).addCandidate(candidate_data, getProfileFromProfileMap(candidate_data.link_profile)); -} -ActiveLinksBuilder::ActiveLinksBuilder(const std::vector& candidateList, const std::map& profile_map): - _candidateDatas(candidateList), _profile_map(profile_map) -{ - checkCandidateNameDuplication(); - checkLinksValidity(); -} - -void ActiveLinksBuilder::checkLinksValidity() -{ - for (const auto& candidateData : _candidateDatas) - { - launchExceptionIfNoLinkProfileAssociated(candidateData.link_profile); - launchExceptionIfNoLinkProfileAssociated(candidateData.installed_link_profile_name); - - record_link_data(candidateData); - } -} - -void ActiveLinksBuilder::record_link_data(const CandidateData &candidateData) { - LinkData link_data = {candidateData.link_id, candidateData.already_installed_capacity, candidateData.installed_link_profile_name, candidateData.linkor, candidateData.linkex}; - const auto & it = _links_data.find(candidateData.link_name); - if(it == _links_data.end()){ - _links_data[candidateData.link_name] = link_data; - } else{ - const LinkName link_name = it->first; - raise_errors_if_link_data_differs_from_existing_link(link_data, link_name); - } -} +#include +#include -void ActiveLinksBuilder::raise_errors_if_link_data_differs_from_existing_link(const ActiveLinksBuilder::LinkData &link_data, - const LinkName &link_name) const { - const LinkData & old_link_data = _links_data.at(link_name); - if(doubles_are_different(link_data.installed_capacity, old_link_data.installed_capacity)){ - std::string message = "Multiple already installed capacity detected for link " + link_name; - throw std::runtime_error(message); - } - if(old_link_data.profile_name != link_data.profile_name){ - std::string message = "Multiple already_installed_profile detected for link " + link_name; - throw std::runtime_error(message); - } - if(old_link_data.id != link_data.id){ - std::string message = "Multiple link_id detected for link " + link_name; - throw std::runtime_error(message); +bool doubles_are_different(const double a, const double b) { + constexpr double MACHINE_EPSILON = std::numeric_limits::epsilon(); + return std::abs(a - b) > MACHINE_EPSILON; +} + +void ActiveLinksBuilder::addCandidate(const CandidateData& candidate_data) { + unsigned int indexLink = getLinkIndexOf(candidate_data.link_id); + _links.at(indexLink).addCandidate( + candidate_data, getProfileFromProfileMap(candidate_data.link_profile)); +} + +ActiveLinksBuilder::ActiveLinksBuilder( + const std::vector& candidateList, + const std::map& profile_map) + : _candidateDatas(candidateList), _profile_map(profile_map) { + checkCandidateNameDuplication(); + checkLinksValidity(); +} + +void ActiveLinksBuilder::checkLinksValidity() { + for (const auto& candidateData : _candidateDatas) { + launchExceptionIfNoLinkProfileAssociated(candidateData.link_profile); + launchExceptionIfNoLinkProfileAssociated( + candidateData.installed_link_profile_name); + + record_link_data(candidateData); + } +} + +void ActiveLinksBuilder::record_link_data(const CandidateData& candidateData) { + LinkData link_data = {candidateData.link_id, + candidateData.already_installed_capacity, + candidateData.installed_link_profile_name, + candidateData.linkor, candidateData.linkex}; + const auto& it = _links_data.find(candidateData.link_name); + if (it == _links_data.end()) { + _links_data[candidateData.link_name] = link_data; + } else { + const LinkName link_name = it->first; + raise_errors_if_link_data_differs_from_existing_link(link_data, link_name); + } +} + +void ActiveLinksBuilder::raise_errors_if_link_data_differs_from_existing_link( + const ActiveLinksBuilder::LinkData& link_data, + const LinkName& link_name) const { + const LinkData& old_link_data = _links_data.at(link_name); + if (doubles_are_different(link_data.installed_capacity, + old_link_data.installed_capacity)) { + std::string message = + "Multiple already installed capacity detected for link " + link_name; + throw std::runtime_error(message); + } + if (old_link_data.profile_name != link_data.profile_name) { + std::string message = + "Multiple already_installed_profile detected for link " + link_name; + throw std::runtime_error(message); + } + if (old_link_data.id != link_data.id) { + std::string message = "Multiple link_id detected for link " + link_name; + throw std::runtime_error(message); + } +} + +void ActiveLinksBuilder::launchExceptionIfNoLinkProfileAssociated( + const std::string& profileName) const { + if (!profileName.empty()) { + const auto& it_profile = _profile_map.find(profileName); + + if (it_profile == _profile_map.end()) { + std::string message = + "There is no linkProfile associated with " + profileName; + throw std::runtime_error(message); } + } } - -void ActiveLinksBuilder::launchExceptionIfNoLinkProfileAssociated(const std::string& profileName) const -{ - if (!profileName.empty()){ - const auto& it_profile = _profile_map.find(profileName); - - if (it_profile == _profile_map.end()) - { - std::string message = "There is no linkProfile associated with " + profileName; - throw std::runtime_error(message); - } - } - -} - -void ActiveLinksBuilder::checkCandidateNameDuplication() const -{ - std::unordered_set setCandidatesNames; - for (const auto& candidateData : _candidateDatas){ - auto it_inserted = setCandidatesNames.insert(candidateData.name); - if (!it_inserted.second){ - std::string message = "Candidate " + candidateData.name + " duplication detected"; - throw std::runtime_error(message); - } +void ActiveLinksBuilder::checkCandidateNameDuplication() const { + std::unordered_set setCandidatesNames; + for (const auto& candidateData : _candidateDatas) { + auto it_inserted = setCandidatesNames.insert(candidateData.name); + if (!it_inserted.second) { + std::string message = + "Candidate " + candidateData.name + " duplication detected"; + throw std::runtime_error(message); } + } } -const std::vector& ActiveLinksBuilder::getLinks() -{ - if (_links.empty()){ - create_links(); - for (const CandidateData& candidateData : _candidateDatas) { - if (candidateData.enable){ - addCandidate(candidateData); - } - } +const std::vector& ActiveLinksBuilder::getLinks() { + if (_links.empty()) { + create_links(); + for (const CandidateData& candidateData : _candidateDatas) { + if (candidateData.enable) { + addCandidate(candidateData); + } } - return _links; + } + return _links; } -int ActiveLinksBuilder::getLinkIndexOf(int link_id) const -{ - int index = -1; - for (int i = 0; i <_links.size(); i++) { - if (_links.at(i).get_idLink() == link_id){ - index = i; - break; - } +int ActiveLinksBuilder::getLinkIndexOf(int link_id) const { + int index = -1; + for (int i = 0; i < _links.size(); i++) { + if (_links.at(i).get_idLink() == link_id) { + index = i; + break; } - return index; + } + return index; } void ActiveLinksBuilder::create_links() { - for( auto const & it: _links_data){ - LinkName name = it.first; - LinkData data = it.second; - ActiveLink link(data.id, name, data._linkor, data._linkex, data.installed_capacity); - link.setAlreadyInstalledLinkProfile(getProfileFromProfileMap(data.profile_name)); - _links.push_back(link); - } + for (auto const& it : _links_data) { + LinkName name = it.first; + LinkData data = it.second; + ActiveLink link(data.id, name, data._linkor, data._linkex, + data.installed_capacity); + link.setAlreadyInstalledLinkProfile( + getProfileFromProfileMap(data.profile_name)); + _links.push_back(link); + } } -LinkProfile ActiveLinksBuilder::getProfileFromProfileMap(const std::string &profile_name) const { - LinkProfile already_installed_link_profile; - if(_profile_map.find(profile_name) != _profile_map.end()){ - already_installed_link_profile = _profile_map.at(profile_name); - } - return already_installed_link_profile; +LinkProfile ActiveLinksBuilder::getProfileFromProfileMap( + const std::string& profile_name) const { + LinkProfile already_installed_link_profile; + if (_profile_map.find(profile_name) != _profile_map.end()) { + already_installed_link_profile = _profile_map.at(profile_name); + } + return already_installed_link_profile; } -ActiveLink::ActiveLink(int idLink, const std::string &linkName, const std::string &linkor, const std::string &linkex, - const double &already_installed_capacity) : - _idLink(idLink), _name(linkName), - _linkor(linkor), _linkex(linkex), - _already_installed_capacity(already_installed_capacity) -{ -} +ActiveLink::ActiveLink(int idLink, const std::string& linkName, + const std::string& linkor, const std::string& linkex, + const double& already_installed_capacity) + : _idLink(idLink), + _name(linkName), + _linkor(linkor), + _linkex(linkex), + _already_installed_capacity(already_installed_capacity) {} -void ActiveLink::setAlreadyInstalledLinkProfile(const LinkProfile& linkProfile) -{ - _already_installed_profile = linkProfile; +void ActiveLink::setAlreadyInstalledLinkProfile( + const LinkProfile& linkProfile) { + _already_installed_profile = linkProfile; } -void ActiveLink::addCandidate(const CandidateData& candidate_data, const LinkProfile& candidate_profile) -{ - Candidate candidate(candidate_data, candidate_profile); - - _candidates.push_back(candidate); -} +void ActiveLink::addCandidate(const CandidateData& candidate_data, + const LinkProfile& candidate_profile) { + Candidate candidate(candidate_data, candidate_profile); -const std::vector& ActiveLink::getCandidates() const -{ - return _candidates; + _candidates.push_back(candidate); } -double ActiveLink::already_installed_direct_profile(size_t timeStep) const -{ - return _already_installed_profile.getDirectProfile(timeStep); +const std::vector& ActiveLink::getCandidates() const { + return _candidates; } -double ActiveLink::already_installed_indirect_profile(size_t timeStep) const -{ - return _already_installed_profile.getIndirectProfile(timeStep); +double ActiveLink::already_installed_direct_profile(size_t timeStep) const { + return _already_installed_profile.getDirectProfile(timeStep); } - -int ActiveLink::get_idLink() const { - return _idLink; +double ActiveLink::already_installed_indirect_profile(size_t timeStep) const { + return _already_installed_profile.getIndirectProfile(timeStep); } -LinkName ActiveLink::get_LinkName() const{ - return _name; -} +int ActiveLink::get_idLink() const { return _idLink; } -double ActiveLink::get_already_installed_capacity() const{ - return _already_installed_capacity; -} +LinkName ActiveLink::get_LinkName() const { return _name; } -std::string ActiveLink::get_linkor() const{ - return _linkor; +double ActiveLink::get_already_installed_capacity() const { + return _already_installed_capacity; } -std::string ActiveLink::get_linkex() const{ - return _linkex; -} +std::string ActiveLink::get_linkor() const { return _linkor; } +std::string ActiveLink::get_linkex() const { return _linkex; } diff --git a/src/cpp/lpnamer/model/ActiveLinks.h b/src/cpp/lpnamer/model/ActiveLinks.h index 059deb3db..dddf9f66c 100644 --- a/src/cpp/lpnamer/model/ActiveLinks.h +++ b/src/cpp/lpnamer/model/ActiveLinks.h @@ -3,80 +3,78 @@ #define ANTARESXPANSION_ACTIVELINKS_H #include + #include using LinkName = std::string; class ActiveLink { - -public: - ActiveLink(int idLink, const std::string &linkName, const std::string &linkor, const std::string &linkex, - const double &already_installed_capacity); - void setAlreadyInstalledLinkProfile(const LinkProfile& linkProfile); - - void addCandidate(const CandidateData& candidate_data, const LinkProfile& candidate_profile); - const std::vector& getCandidates() const; - - double already_installed_direct_profile(size_t timeStep) const; - double already_installed_indirect_profile(size_t timeStep) const; - - int get_idLink() const ; - LinkName get_LinkName() const; - std::string get_linkor() const; - std::string get_linkex() const; - double get_already_installed_capacity() const; - -private: - int _idLink; - LinkName _name; - std::string _linkor; - std::string _linkex; - double _already_installed_capacity = 1; - LinkProfile _already_installed_profile; - std::vector _candidates; + public: + ActiveLink(int idLink, const std::string& linkName, const std::string& linkor, + const std::string& linkex, + const double& already_installed_capacity); + void setAlreadyInstalledLinkProfile(const LinkProfile& linkProfile); + + void addCandidate(const CandidateData& candidate_data, + const LinkProfile& candidate_profile); + const std::vector& getCandidates() const; + + double already_installed_direct_profile(size_t timeStep) const; + double already_installed_indirect_profile(size_t timeStep) const; + + int get_idLink() const; + LinkName get_LinkName() const; + std::string get_linkor() const; + std::string get_linkex() const; + double get_already_installed_capacity() const; + + private: + int _idLink; + LinkName _name; + std::string _linkor; + std::string _linkex; + double _already_installed_capacity = 1; + LinkProfile _already_installed_profile; + std::vector _candidates; }; class ActiveLinksBuilder { + public: + ActiveLinksBuilder(const std::vector& candidateList, + const std::map& profile_map); + + const std::vector& getLinks(); + + private: + struct LinkData { + int id; + double installed_capacity; + std::string profile_name; + std::string _linkor; + std::string _linkex; + }; -public: - - ActiveLinksBuilder(const std::vector& candidateList, const std::map& profile_map); - - const std::vector& getLinks(); - -private: - struct LinkData { - int id; - double installed_capacity; - std::string profile_name; - std::string _linkor; - std::string _linkex; - }; - - void checkCandidateNameDuplication() const; - void checkLinksValidity(); - - int getLinkIndexOf(int link_id) const; - void addCandidate(const CandidateData &candidate_data); - void launchExceptionIfNoLinkProfileAssociated(const std::string& profileName) const; - - void record_link_data(const CandidateData& candidateData); - void raise_errors_if_link_data_differs_from_existing_link(const LinkData& link_data, - const LinkName& link_name) const; - void create_links(); + void checkCandidateNameDuplication() const; + void checkLinksValidity(); - LinkProfile getProfileFromProfileMap(const std::string& profile_name) const; + int getLinkIndexOf(int link_id) const; + void addCandidate(const CandidateData& candidate_data); + void launchExceptionIfNoLinkProfileAssociated( + const std::string& profileName) const; - std::map _links_data; - std::unordered_map linkToAlreadyInstalledProfileName; - std::unordered_map linkToAlreadyInstalledCapacity; - const std::vector _candidateDatas; - const std::map _profile_map; - std::vector _links; + void record_link_data(const CandidateData& candidateData); + void raise_errors_if_link_data_differs_from_existing_link( + const LinkData& link_data, const LinkName& link_name) const; + void create_links(); - + LinkProfile getProfileFromProfileMap(const std::string& profile_name) const; - + std::map _links_data; + std::unordered_map linkToAlreadyInstalledProfileName; + std::unordered_map linkToAlreadyInstalledCapacity; + const std::vector _candidateDatas; + const std::map _profile_map; + std::vector _links; }; -#endif //ANTARESXPANSION_ACTIVELINKS_H +#endif // ANTARESXPANSION_ACTIVELINKS_H diff --git a/src/cpp/lpnamer/model/Candidate.cpp b/src/cpp/lpnamer/model/Candidate.cpp index 699772666..c99dbfb28 100644 --- a/src/cpp/lpnamer/model/Candidate.cpp +++ b/src/cpp/lpnamer/model/Candidate.cpp @@ -1,53 +1,38 @@ #include "Candidate.h" -Candidate::Candidate(const CandidateData& data, const LinkProfile& profile): - _profile (profile), - _name (data.name), - _annual_cost_per_mw (data.annual_cost_per_mw), - _max_investment (data.max_investment), - _unit_size (data.unit_size), - _max_units (data.max_units) -{} - -double Candidate::direct_profile(size_t timeStep) const{ - return _profile.getDirectProfile(timeStep); -} +Candidate::Candidate(const CandidateData& data, const LinkProfile& profile) + : _profile(profile), + _name(data.name), + _annual_cost_per_mw(data.annual_cost_per_mw), + _max_investment(data.max_investment), + _unit_size(data.unit_size), + _max_units(data.max_units) {} -double Candidate::indirect_profile(size_t timeStep) const{ - return _profile.getIndirectProfile(timeStep); +double Candidate::direct_profile(size_t timeStep) const { + return _profile.getDirectProfile(timeStep); } -double Candidate::obj()const { - return _annual_cost_per_mw; +double Candidate::indirect_profile(size_t timeStep) const { + return _profile.getIndirectProfile(timeStep); } -double Candidate::lb() const { - return 0; -} +double Candidate::obj() const { return _annual_cost_per_mw; } + +double Candidate::lb() const { return 0; } double Candidate::ub() const { - double val = _max_investment; - if(val == 0.0) { - val = unit_size() * max_unit(); - } - return val; + double val = _max_investment; + if (val == 0.0) { + val = unit_size() * max_unit(); + } + return val; } -double Candidate::unit_size() const { - return _unit_size; -} -double Candidate::max_unit() const { - return _max_units; -} +double Candidate::unit_size() const { return _unit_size; } +double Candidate::max_unit() const { return _max_units; } -bool Candidate::is_integer()const { - return _unit_size!=0.0; -} +bool Candidate::is_integer() const { return _unit_size != 0.0; } -std::string Candidate::get_name() const{ - return _name; -} +std::string Candidate::get_name() const { return _name; } -void Candidate::set_name(const std::string& name){ - _name = name; -} \ No newline at end of file +void Candidate::set_name(const std::string& name) { _name = name; } \ No newline at end of file diff --git a/src/cpp/lpnamer/model/Candidate.h b/src/cpp/lpnamer/model/Candidate.h index 2912ef7cb..024538b66 100644 --- a/src/cpp/lpnamer/model/Candidate.h +++ b/src/cpp/lpnamer/model/Candidate.h @@ -1,28 +1,25 @@ #ifndef ANTARESXPANSION_CANDIDATE_H #define ANTARESXPANSION_CANDIDATE_H -#include "common_lpnamer.h" #include "LinkProfile.h" +#include "common_lpnamer.h" struct CandidateData { - - bool enable = true; - - std::string link_name; - int link_id; - std::string linkor; - std::string linkex; - std::string installed_link_profile_name; - double already_installed_capacity = 1.0; - - std::string name; - std::string link_profile; - double annual_cost_per_mw = 0.0; - double max_investment = 0.0; - double unit_size = 0.0; - double max_units = 0.0; - - + bool enable = true; + + std::string link_name; + int link_id; + std::string linkor; + std::string linkex; + std::string installed_link_profile_name; + double already_installed_capacity = 1.0; + + std::string name; + std::string link_profile; + double annual_cost_per_mw = 0.0; + double max_investment = 0.0; + double unit_size = 0.0; + double max_units = 0.0; }; /*! @@ -31,36 +28,32 @@ struct CandidateData { * */ class Candidate { + public: + Candidate() = default; + Candidate(const CandidateData& data, const LinkProfile& profile); -public: - Candidate() = default; - Candidate(const CandidateData& data, const LinkProfile& profile); - - double direct_profile(size_t timeStep) const; - double indirect_profile(size_t timeStep) const; - - double obj()const; - double lb()const; - double ub()const; - - double unit_size() const; - double max_unit() const; + double direct_profile(size_t timeStep) const; + double indirect_profile(size_t timeStep) const; - bool is_integer()const; + double obj() const; + double lb() const; + double ub() const; - std::string get_name() const; - void set_name(const std::string& name); - + double unit_size() const; + double max_unit() const; -private: + bool is_integer() const; - LinkProfile _profile; - std::string _name; - double _annual_cost_per_mw; - double _max_investment; - double _unit_size; - double _max_units; + std::string get_name() const; + void set_name(const std::string& name); + private: + LinkProfile _profile; + std::string _name; + double _annual_cost_per_mw; + double _max_investment; + double _unit_size; + double _max_units; }; -#endif //ANTARESXPANSION_CANDIDATE_H +#endif // ANTARESXPANSION_CANDIDATE_H diff --git a/src/cpp/lpnamer/model/LinkProfile.cpp b/src/cpp/lpnamer/model/LinkProfile.cpp index 48cb4ca4b..1e06de766 100644 --- a/src/cpp/lpnamer/model/LinkProfile.cpp +++ b/src/cpp/lpnamer/model/LinkProfile.cpp @@ -1,40 +1,39 @@ // -#include #include "LinkProfile.h" - +#include /*! * \brief returns true if the direct link profile column is empty * */ -bool LinkProfile::empty() const{ - return _directLinkProfile.empty(); -} +bool LinkProfile::empty() const { return _directLinkProfile.empty(); } double LinkProfile::getDirectProfile(size_t i) const { - if (i > 8759){ - throw std::runtime_error( "Link profiles can be requested between point 0 and 8759."); - } - - if (_directLinkProfile.empty()) { - return 1.0; - }else { - return _directLinkProfile[i]; - } + if (i > 8759) { + throw std::runtime_error( + "Link profiles can be requested between point 0 and 8759."); + } + + if (_directLinkProfile.empty()) { + return 1.0; + } else { + return _directLinkProfile[i]; + } } double LinkProfile::getIndirectProfile(size_t i) const { - if (i > 8759){ - throw std::runtime_error( "Link profiles can be requested between point 0 and 8759."); - } - - if (_directLinkProfile.empty() && _indirectLinkProfile.empty()) { - return 1.0; - }else if (!_indirectLinkProfile.empty()) { - return _indirectLinkProfile[i]; - }else { - return _directLinkProfile[i]; - } + if (i > 8759) { + throw std::runtime_error( + "Link profiles can be requested between point 0 and 8759."); + } + + if (_directLinkProfile.empty() && _indirectLinkProfile.empty()) { + return 1.0; + } else if (!_indirectLinkProfile.empty()) { + return _indirectLinkProfile[i]; + } else { + return _directLinkProfile[i]; + } } \ No newline at end of file diff --git a/src/cpp/lpnamer/model/LinkProfile.h b/src/cpp/lpnamer/model/LinkProfile.h index dda5b8ada..2bee53ede 100644 --- a/src/cpp/lpnamer/model/LinkProfile.h +++ b/src/cpp/lpnamer/model/LinkProfile.h @@ -10,40 +10,39 @@ */ class LinkProfile { - -public: - -/*! - * \brief LinkProfile default constructor - * - */ - LinkProfile() = default; - -/*! - * \brief returns true if the direct link profile column is empty - * - */ - bool empty() const; - - /*! - * \brief returns the value of a direct link profile - * - * \param i : period for which to get the linkprofile value (between 0 and 8759) - */ - double getDirectProfile(size_t i) const; - - /*! - * \brief returns the value of a direct link profile - * - * \param i : period for which to get the linkprofile value (between 0 and 8759) - */ - double getIndirectProfile(size_t i) const; - - //! direct linkprofile values - std::vector _directLinkProfile; - //! indirect linkprofile values if different from direct linkprofile - std::vector _indirectLinkProfile; + public: + /*! + * \brief LinkProfile default constructor + * + */ + LinkProfile() = default; + + /*! + * \brief returns true if the direct link profile column is empty + * + */ + bool empty() const; + + /*! + * \brief returns the value of a direct link profile + * + * \param i : period for which to get the linkprofile value (between 0 and + * 8759) + */ + double getDirectProfile(size_t i) const; + + /*! + * \brief returns the value of a direct link profile + * + * \param i : period for which to get the linkprofile value (between 0 and + * 8759) + */ + double getIndirectProfile(size_t i) const; + + //! direct linkprofile values + std::vector _directLinkProfile; + //! indirect linkprofile values if different from direct linkprofile + std::vector _indirectLinkProfile; }; - -#endif //ANTARESXPANSION_LINKPROFILE_H +#endif // ANTARESXPANSION_LINKPROFILE_H diff --git a/src/cpp/lpnamer/problem_modifier/AdditionalConstraints.cpp b/src/cpp/lpnamer/problem_modifier/AdditionalConstraints.cpp index 491de8462..947763246 100644 --- a/src/cpp/lpnamer/problem_modifier/AdditionalConstraints.cpp +++ b/src/cpp/lpnamer/problem_modifier/AdditionalConstraints.cpp @@ -1,173 +1,158 @@ -#include - #include "AdditionalConstraints.h" -#include "AdditionalConstraintsReader.h" - -AdditionalConstraints::AdditionalConstraints(std::string const & constraints_file_path) -{ - AdditionalConstraintsReader reader_l(constraints_file_path); +#include - //treat variables section - std::map const & variables_section = reader_l.getVariablesSection(); - addVariablesToBinarise(variables_section); +#include "AdditionalConstraintsReader.h" - //treat constraints sections - for(std::string sectionName_l : reader_l.getSections()) - { - if (sectionName_l != "variables") - { - std::map const & constarintsSection_l = reader_l.getSection(sectionName_l); - constructAdditionalConstraints(sectionName_l, constarintsSection_l); - } +AdditionalConstraints::AdditionalConstraints( + std::string const& constraints_file_path) { + AdditionalConstraintsReader reader_l(constraints_file_path); + + // treat variables section + std::map const& variables_section = + reader_l.getVariablesSection(); + addVariablesToBinarise(variables_section); + + // treat constraints sections + for (std::string sectionName_l : reader_l.getSections()) { + if (sectionName_l != "variables") { + std::map const& constarintsSection_l = + reader_l.getSection(sectionName_l); + constructAdditionalConstraints(sectionName_l, constarintsSection_l); } - + } } -void AdditionalConstraints::addVariableToBinarise(const std::string& oldVarName_p, const std::string& binVarName_p) -{ - if(!_binaryVariables.insert(binVarName_p).second) - { - std::cout << "Duplicate Binary variable name: " << binVarName_p << " was already added.\n"; - std::exit(1); - } - _variablesToBinarise[oldVarName_p] = binVarName_p; +void AdditionalConstraints::addVariableToBinarise( + const std::string& oldVarName_p, const std::string& binVarName_p) { + if (!_binaryVariables.insert(binVarName_p).second) { + std::cout << "Duplicate Binary variable name: " << binVarName_p + << " was already added.\n"; + std::exit(1); + } + _variablesToBinarise[oldVarName_p] = binVarName_p; } -void AdditionalConstraints::addVariablesToBinarise(std::map const & variables_section) -{ - for(const auto& pairOldvarNewvar_l : variables_section) - { - addVariableToBinarise(pairOldvarNewvar_l.first, pairOldvarNewvar_l.second); - } +void AdditionalConstraints::addVariablesToBinarise( + std::map const& variables_section) { + for (const auto& pairOldvarNewvar_l : variables_section) { + addVariableToBinarise(pairOldvarNewvar_l.first, pairOldvarNewvar_l.second); + } } -std::map const & AdditionalConstraints::getVariablesToBinarise() const -{ - return _variablesToBinarise; +std::map const& +AdditionalConstraints::getVariablesToBinarise() const { + return _variablesToBinarise; } -void AdditionalConstraints::constructAdditionalConstraints(const std::string& sectionName_l, const std::map& constarintsSection_l) -{ - - std::string constraintName_l = ""; - std::string constraintSign_l = ""; - double constraintRHS_l = 0; - - //check that section has defined a unique constraint name - constraintName_l = checkAndReturnConstraintName(sectionName_l, constarintsSection_l); - - //check that section has defined a sign - constraintSign_l = checkAndReturnSectionSign( sectionName_l, constarintsSection_l); - - //check that section has defined a rhs - constraintRHS_l = checkAndReturnSectionRhs(sectionName_l, constarintsSection_l); - - //create and fill the constraint - AdditionalConstraint constraint_l(sectionName_l, constraintName_l, constraintSign_l, constraintRHS_l); - bool emptyCstr_l = true; - for(const auto& pairAttributeValue_l : constarintsSection_l) - { - if(pairAttributeValue_l.first == "name" || pairAttributeValue_l.first == "rhs" || pairAttributeValue_l.first == "sign") - { - continue; - } - else - { - try - { - std::string::size_type sz; - double coeff_l = std::stod(pairAttributeValue_l.second, &sz); - if(coeff_l != 0) - { - emptyCstr_l = false; - } - constraint_l.setCoeff(pairAttributeValue_l.first, coeff_l); - } - catch(const std::invalid_argument& e) - { - std::cerr << "Invalid value " << pairAttributeValue_l.second << " in section " << sectionName_l - << ": coeff value must be a double!\n"; - std::exit(1); - } +void AdditionalConstraints::constructAdditionalConstraints( + const std::string& sectionName_l, + const std::map& constarintsSection_l) { + std::string constraintName_l = ""; + std::string constraintSign_l = ""; + double constraintRHS_l = 0; + + // check that section has defined a unique constraint name + constraintName_l = + checkAndReturnConstraintName(sectionName_l, constarintsSection_l); + + // check that section has defined a sign + constraintSign_l = + checkAndReturnSectionSign(sectionName_l, constarintsSection_l); + + // check that section has defined a rhs + constraintRHS_l = + checkAndReturnSectionRhs(sectionName_l, constarintsSection_l); + + // create and fill the constraint + AdditionalConstraint constraint_l(sectionName_l, constraintName_l, + constraintSign_l, constraintRHS_l); + bool emptyCstr_l = true; + for (const auto& pairAttributeValue_l : constarintsSection_l) { + if (pairAttributeValue_l.first == "name" || + pairAttributeValue_l.first == "rhs" || + pairAttributeValue_l.first == "sign") { + continue; + } else { + try { + std::string::size_type sz; + double coeff_l = std::stod(pairAttributeValue_l.second, &sz); + if (coeff_l != 0) { + emptyCstr_l = false; } - } - - if(emptyCstr_l) - { - std::cerr << "section " << sectionName_l << " defines an empty constraint.\n"; + constraint_l.setCoeff(pairAttributeValue_l.first, coeff_l); + } catch (const std::invalid_argument& e) { + std::cerr << "Invalid value " << pairAttributeValue_l.second + << " in section " << sectionName_l + << ": coeff value must be a double!\n"; std::exit(1); + } } + } - (*this)[constraintName_l] = constraint_l; -} + if (emptyCstr_l) { + std::cerr << "section " << sectionName_l + << " defines an empty constraint.\n"; + std::exit(1); + } -std::string AdditionalConstraints::checkAndReturnConstraintName(const std::string& sectionName_l, const std::map & constarintsSection_l) const -{ - - std::string constraintName_l = ""; - //check that section has defined a unique constraint name - auto temporatyIterator_l = constarintsSection_l.find("name"); - if( temporatyIterator_l == constarintsSection_l.end()) - { - std::cout << "section " << sectionName_l << " is missing a name.\n"; - std::exit(1); - } - else - { - constraintName_l = temporatyIterator_l->second; - if(this->count(constraintName_l)) - { - std::cout << "Duplicate constraint name " << constraintName_l << ".\n"; - std::exit(1); - } - } - return constraintName_l; + (*this)[constraintName_l] = constraint_l; } -std::string AdditionalConstraints::checkAndReturnSectionSign(const std::string& sectionName_l, const std::map& constarintsSection_l) const -{ - - //check that section has defined a sign - - std::string constraintSign_l = ""; - auto temporatyIterator_l = constarintsSection_l.find("sign"); - if(temporatyIterator_l == constarintsSection_l.end()) - { - std::cout << "section " << sectionName_l << " is missing a sign.\n"; - std::exit(1); - } - else - { - constraintSign_l = temporatyIterator_l->second; +std::string AdditionalConstraints::checkAndReturnConstraintName( + const std::string& sectionName_l, + const std::map& constarintsSection_l) const { + std::string constraintName_l = ""; + // check that section has defined a unique constraint name + auto temporatyIterator_l = constarintsSection_l.find("name"); + if (temporatyIterator_l == constarintsSection_l.end()) { + std::cout << "section " << sectionName_l << " is missing a name.\n"; + std::exit(1); + } else { + constraintName_l = temporatyIterator_l->second; + if (this->count(constraintName_l)) { + std::cout << "Duplicate constraint name " << constraintName_l << ".\n"; + std::exit(1); } - return constraintSign_l; + } + return constraintName_l; } -double AdditionalConstraints::checkAndReturnSectionRhs(const std::string& sectionName_l, const std::map& constarintsSection_l) const -{ +std::string AdditionalConstraints::checkAndReturnSectionSign( + const std::string& sectionName_l, + const std::map& constarintsSection_l) const { + // check that section has defined a sign + + std::string constraintSign_l = ""; + auto temporatyIterator_l = constarintsSection_l.find("sign"); + if (temporatyIterator_l == constarintsSection_l.end()) { + std::cout << "section " << sectionName_l << " is missing a sign.\n"; + std::exit(1); + } else { + constraintSign_l = temporatyIterator_l->second; + } + return constraintSign_l; +} - //check that section has defined a rhs - double constraintRHS_l = 0; - auto temporatyIterator_l = constarintsSection_l.find("rhs"); - if(temporatyIterator_l == constarintsSection_l.end()) - { - std::cout << "section " << sectionName_l << " is missing a rhs.\n"; - std::exit(1); - } - else - { - try - { - std::string::size_type sz; - constraintRHS_l = std::stod(temporatyIterator_l->second, &sz); - } - catch(const std::invalid_argument& e) - { - std::cerr << "Invalid value " << temporatyIterator_l->second << " in section " << sectionName_l - << ": rhs value must be a double!\n"; - std::exit(1); - } +double AdditionalConstraints::checkAndReturnSectionRhs( + const std::string& sectionName_l, + const std::map& constarintsSection_l) const { + // check that section has defined a rhs + double constraintRHS_l = 0; + auto temporatyIterator_l = constarintsSection_l.find("rhs"); + if (temporatyIterator_l == constarintsSection_l.end()) { + std::cout << "section " << sectionName_l << " is missing a rhs.\n"; + std::exit(1); + } else { + try { + std::string::size_type sz; + constraintRHS_l = std::stod(temporatyIterator_l->second, &sz); + } catch (const std::invalid_argument& e) { + std::cerr << "Invalid value " << temporatyIterator_l->second + << " in section " << sectionName_l + << ": rhs value must be a double!\n"; + std::exit(1); } - return constraintRHS_l; + } + return constraintRHS_l; } \ No newline at end of file diff --git a/src/cpp/lpnamer/problem_modifier/AdditionalConstraints.h b/src/cpp/lpnamer/problem_modifier/AdditionalConstraints.h index 9d27c4b16..1d9a51950 100644 --- a/src/cpp/lpnamer/problem_modifier/AdditionalConstraints.h +++ b/src/cpp/lpnamer/problem_modifier/AdditionalConstraints.h @@ -2,181 +2,186 @@ #include #include +#include /*! * \class AdditionalConstraint * \brief additional constraint to add to master problem * - * inherites from a map where keys are variable names and values are the variables coeffs + * inherites from a map where keys are variable names and values are the + * variables coeffs */ -class AdditionalConstraint : public std::map -{ - -private: - std::string _sectionName; - std::string _name; - std::string _sign; - double _rhs; - -public: - -/** - * \brief AdditionalConstraint default constructor - */ - AdditionalConstraint() : - _sectionName(""), - _name(""), - _sign(""), - _rhs(0) - { - } - -/** - * @brief AdditionalConstraint constructor - * - * @param sectionName_p : string value : name of the section in the ini file that declared this constraint. - * @param constraintName_p : string value : name of the constraint. - * @param sign_p : string value : sign of the constraint. One of "less_or_equal", "equal" or "greater_or_equal" - * @param rhs_p : double RHS of the constraint - */ - AdditionalConstraint(std::string const & sectionName_p, std::string const & constraintName_p, std::string const & sign_p, double rhs_p) : - _sectionName(sectionName_p), - _name(constraintName_p), - _sign(sign_p), - _rhs(rhs_p) - { - } - -/** - * @brief AdditionalConstraint destructor - */ - virtual ~AdditionalConstraint() = default; - -/** - * @brief AdditionalConstraint::_name getter - * - * @param name_p : string value : name of the constraint - */ - std::string getName() const - { - return _name; - } - -/** - * @brief AdditionalConstraint::_rhs getter - * - * @param rhs_p : double value : rhs of the constraint - */ - double getRHS() const - { - return _rhs; - } - -/** - * @brief AdditionalConstraint::_sign getter - * - * @param name_p : string value : sign of the constraint (supported values "less_or_equal", "equal", "greater_or_equal") - */ - std::string getSign() const - { - return _sign; - } - -/** - * @brief adds a term to the constraint - * - * @param varName_p : string value : name of the variable concerned - * @param varCoeff_p : double value : coefficient of the variable concerned - */ - void setCoeff(const std::string& varName_p, const double varCoeff_p) - { - (*this)[varName_p] = varCoeff_p; - } +class AdditionalConstraint : public std::map { + private: + std::string _sectionName; + std::string _name; + std::string _sign; + double _rhs; + + public: + /** + * \brief AdditionalConstraint default constructor + */ + AdditionalConstraint() : _sectionName(""), _name(""), _sign(""), _rhs(0) {} + + /** + * @brief AdditionalConstraint constructor + * + * @param sectionName_p : string value : name of the section in the ini file + * that declared this constraint. + * @param constraintName_p : string value : name of the constraint. + * @param sign_p : string value : sign of the constraint. One of + * "less_or_equal", "equal" or "greater_or_equal" + * @param rhs_p : double RHS of the constraint + */ + AdditionalConstraint(std::string const& sectionName_p, + std::string const& constraintName_p, + std::string const& sign_p, double rhs_p) + : _sectionName(sectionName_p), + _name(constraintName_p), + _sign(sign_p), + _rhs(rhs_p) {} + + /** + * @brief AdditionalConstraint destructor + */ + virtual ~AdditionalConstraint() = default; + + /** + * @brief AdditionalConstraint::_name getter + * + * @param name_p : string value : name of the constraint + */ + std::string getName() const { return _name; } + + /** + * @brief AdditionalConstraint::_rhs getter + * + * @param rhs_p : double value : rhs of the constraint + */ + double getRHS() const { return _rhs; } + + /** + * @brief AdditionalConstraint::_sign getter + * + * @param name_p : string value : sign of the constraint (supported values + * "less_or_equal", "equal", "greater_or_equal") + */ + std::string getSign() const { return _sign; } + + /** + * @brief adds a term to the constraint + * + * @param varName_p : string value : name of the variable concerned + * @param varCoeff_p : double value : coefficient of the variable concerned + */ + void setCoeff(const std::string& varName_p, const double varCoeff_p) { + (*this)[varName_p] = varCoeff_p; + } }; /*! * \struct AdditionalConstraints * \brief candidate exclusion constraint structure * - * inherites from a map where keys are unique constraint names and values are the additional constraints - */ -struct AdditionalConstraints : public std::map -{ -private: - //set of variables to which a binary corresponding variable will be created - std::map _variablesToBinarise; - std::set _binaryVariables; - -public: -/*! -* \brief default constructor for struct AdditionalConstraints -*/ - AdditionalConstraints() = default; - -/*! - * \brief AdditionalConstraints constructor from an ini file path - * - * \param constraints_file_path String corresponding to the additional constraints file path + * inherites from a map where keys are unique constraint names and values are + * the additional constraints */ - explicit AdditionalConstraints(std::string const & constraints_file_path); - -/*! - * \brief adds a binary variable to be created and links it to the corresponding variable - * - * \param oldVarName_p String name of the old variable - * \param binVarName_p String name of the new binary variable to link to the old existing one - * - * adds an entry to the AdditionalConstraints::_variablesToBinarise - */ - void addVariableToBinarise(const std::string& oldVarName_p, const std::string& binVarName_p); - -/*! - * \brief adds a binary variable to be created and links it to the corresponding variable - * - * \param variables_section std::map whose value is the name of the binary variables to create - * and whose key is the corresponding existing variable to link toe - * - * adds entries to the AdditionalConstraints::_variablesToBinarise - */ - void addVariablesToBinarise(std::map const & variables_section); - -/*! - * \brief getter for AdditionalConstraints::_variablesToBinarise - * - * \return std::map whose value is the name of the binary variables to create - * and whose key is the corresponding existing variable to link to - */ - std::map const & getVariablesToBinarise() const; - -/*! - * \brief the method is responsible for creating and filling constraints - * \param std::string sectionName_l the section name - * \param constarintsSection_l is a std::map where keys are the constraints entries ("name", "sign", "rhs") - */ - void constructAdditionalConstraints(const std::string& sectionName_l, const std::map& constarintsSection_l); - -/*! - * \brief the method is responsible for checking that section has defined a unique constraint name - * \param std::string sectionName_l the section name - * \param constarintsSection_l is a std::map where keys are the constraints entries ("name", "sign", "rhs") - * \return std::string the constraint name - */ - std::string checkAndReturnConstraintName(const std::string& sectionName_l, const std::map & constarintsSection_l) const; - -/*! - * \brief the method is responsible for checking that section has defined a sign - * \param std::string sectionName_l the section name - * \param constarintsSection_l is a std::map where keys are the constraints entries ("name", "sign", "rhs") - * \return std::string the constraint sign - */ - std::string checkAndReturnSectionSign(const std::string& sectionName_l, const std::map& constarintsSection_l) const; - -/*! - * \brief the method is responsible for checking that section has defined a rhs - * \param std::string sectionName_l the section name - * \param constarintsSection_l is a std::map where keys are the constraints entries ("name", "sign", "rhs") - * \return std::string the rhs - */ - double checkAndReturnSectionRhs(const std::string& sectionName_l, const std::map& constarintsSection_l) const ; - +struct AdditionalConstraints + : public std::map { + private: + // set of variables to which a binary corresponding variable will be created + std::map _variablesToBinarise; + std::set _binaryVariables; + + public: + /*! + * \brief default constructor for struct AdditionalConstraints + */ + AdditionalConstraints() = default; + + /*! + * \brief AdditionalConstraints constructor from an ini file path + * + * \param constraints_file_path String corresponding to the additional + * constraints file path + */ + explicit AdditionalConstraints(std::string const& constraints_file_path); + + /*! + * \brief adds a binary variable to be created and links it to the + * corresponding variable + * + * \param oldVarName_p String name of the old variable + * \param binVarName_p String name of the new binary variable to link to the + * old existing one + * + * adds an entry to the AdditionalConstraints::_variablesToBinarise + */ + void addVariableToBinarise(const std::string& oldVarName_p, + const std::string& binVarName_p); + + /*! + * \brief adds a binary variable to be created and links it to the + * corresponding variable + * + * \param variables_section std::map whose value is + * the name of the binary variables to create and whose key is the + * corresponding existing variable to link toe + * + * adds entries to the AdditionalConstraints::_variablesToBinarise + */ + void addVariablesToBinarise( + std::map const& variables_section); + + /*! + * \brief getter for AdditionalConstraints::_variablesToBinarise + * + * \return std::map whose value is the name of the + * binary variables to create and whose key is the corresponding existing + * variable to link to + */ + std::map const& getVariablesToBinarise() const; + + /*! + * \brief the method is responsible for creating and filling constraints + * \param std::string sectionName_l the section name + * \param constarintsSection_l is a std::map where + * keys are the constraints entries ("name", "sign", "rhs") + */ + void constructAdditionalConstraints( + const std::string& sectionName_l, + const std::map& constarintsSection_l); + + /*! + * \brief the method is responsible for checking that section has defined a + * unique constraint name \param std::string sectionName_l the section name + * \param constarintsSection_l is a std::map where + * keys are the constraints entries ("name", "sign", "rhs") \return + * std::string the constraint name + */ + std::string checkAndReturnConstraintName( + const std::string& sectionName_l, + const std::map& constarintsSection_l) const; + + /*! + * \brief the method is responsible for checking that section has defined a + * sign \param std::string sectionName_l the section name \param + * constarintsSection_l is a std::map where keys are + * the constraints entries ("name", "sign", "rhs") \return std::string the + * constraint sign + */ + std::string checkAndReturnSectionSign( + const std::string& sectionName_l, + const std::map& constarintsSection_l) const; + + /*! + * \brief the method is responsible for checking that section has defined a + * rhs \param std::string sectionName_l the section name \param + * constarintsSection_l is a std::map where keys are + * the constraints entries ("name", "sign", "rhs") \return std::string the rhs + */ + double checkAndReturnSectionRhs( + const std::string& sectionName_l, + const std::map& constarintsSection_l) const; }; diff --git a/src/cpp/lpnamer/problem_modifier/LauncherHelpers.cpp b/src/cpp/lpnamer/problem_modifier/LauncherHelpers.cpp index 8652e0cad..b4b82a860 100644 --- a/src/cpp/lpnamer/problem_modifier/LauncherHelpers.cpp +++ b/src/cpp/lpnamer/problem_modifier/LauncherHelpers.cpp @@ -1,147 +1,140 @@ #include "LauncherHelpers.h" + #include "Candidate.h" #include "CandidatesINIReader.h" +#include "LinkProblemsGenerator.h" #include "LinkProfileReader.h" #include "helpers/Path.h" -#include "LinkProblemsGenerator.h" -void treatAdditionalConstraints(SolverAbstract::Ptr master_p, - const AdditionalConstraints &additionalConstraints_p) -{ - // add requested binary variables - addBinaryVariables(master_p, additionalConstraints_p.getVariablesToBinarise()); - - // add the constraints - for (auto pairNameAdditionalcstr : additionalConstraints_p) - { - addAdditionalConstraint(master_p, pairNameAdditionalcstr.second); - } +void treatAdditionalConstraints( + SolverAbstract::Ptr master_p, + const AdditionalConstraints &additionalConstraints_p) { + // add requested binary variables + addBinaryVariables(master_p, + additionalConstraints_p.getVariablesToBinarise()); + + // add the constraints + for (auto pairNameAdditionalcstr : additionalConstraints_p) { + addAdditionalConstraint(master_p, pairNameAdditionalcstr.second); + } } void addAdditionalConstraint(SolverAbstract::Ptr master_p, - AdditionalConstraint &additionalConstraint_p) -{ - auto newnz = (int)additionalConstraint_p.size(); - int newrows = 1; - std::vector rtype(newrows); - std::vector rhs(newrows, additionalConstraint_p.getRHS()); - std::vector mindex(newnz); - std::vector matval(newnz); - std::vector matstart(newrows + 1); - matstart[0] = 0; - matstart[1] = newnz; - - std::string sign_l = additionalConstraint_p.getSign(); - if (sign_l == "less_or_equal") - { - rtype[0] = 'L'; - } - else if (sign_l == "greater_or_equal") - { - rtype[0] = 'U'; - } - else if (sign_l == "equal") - { - rtype[0] = 'E'; - } - else - { - std::cout << "ERROR un addAdditionalConstraint, unknown row type " - << sign_l << std::endl; - std::exit(1); - } - - int i = 0; - for (auto &pairNameCoeff : additionalConstraint_p) - { - int col_index = master_p->get_col_index(pairNameCoeff.first); - if (col_index == -1) - { - std::cout << "missing variable " << pairNameCoeff.first - << " used in additional constraint file!\n"; - std::exit(1); - } - mindex[i] = col_index; - matval[i] = pairNameCoeff.second; - i++; - } - - master_p->add_rows(1, newnz, rtype.data(), rhs.data(), nullptr, matstart.data(), - mindex.data(), matval.data()); + AdditionalConstraint &additionalConstraint_p) { + auto newnz = (int)additionalConstraint_p.size(); + int newrows = 1; + std::vector rtype(newrows); + std::vector rhs(newrows, additionalConstraint_p.getRHS()); + std::vector mindex(newnz); + std::vector matval(newnz); + std::vector matstart(newrows + 1); + matstart[0] = 0; + matstart[1] = newnz; + + std::string sign_l = additionalConstraint_p.getSign(); + if (sign_l == "less_or_equal") { + rtype[0] = 'L'; + } else if (sign_l == "greater_or_equal") { + rtype[0] = 'U'; + } else if (sign_l == "equal") { + rtype[0] = 'E'; + } else { + std::cout << "ERROR un addAdditionalConstraint, unknown row type " << sign_l + << std::endl; + std::exit(1); + } + + int i = 0; + for (auto &pairNameCoeff : additionalConstraint_p) { + int col_index = master_p->get_col_index(pairNameCoeff.first); + if (col_index == -1) { + std::cout << "missing variable " << pairNameCoeff.first + << " used in additional constraint file!\n"; + std::exit(1); + } + mindex[i] = col_index; + matval[i] = pairNameCoeff.second; + i++; + } + + master_p->add_rows(1, newnz, rtype.data(), rhs.data(), nullptr, + matstart.data(), mindex.data(), matval.data()); } -void addBinaryVariables(SolverAbstract::Ptr master_p, const std::map &variablesToBinarise_p) -{ - - for (const auto &pairOldNewVarnames : variablesToBinarise_p) - { - int col_index = master_p->get_col_index(pairOldNewVarnames.first); - - if (col_index == -1) - { - - std::cout << "missing variable " << pairOldNewVarnames.first - << " used in additional constraint file!\n"; - std::exit(1); - } - - master_p->add_cols(1, 0, std::vector(1, 0.0).data(), std::vector(2, 0).data(), - std::vector(0).data(), std::vector(0).data(), - std::vector(1, 0).data(), std::vector(1, 1e20).data()); - - // Changing column type to binary - master_p->chg_col_type(std::vector(1, master_p->get_ncols() - 1), - std::vector(1, 'B')); - - // Changing column name - master_p->chg_col_name(master_p->get_ncols() - 1, pairOldNewVarnames.second); - - // Add linking constraint - std::vector matstart(2); - matstart[0] = 0; - matstart[1] = 2; - - std::vector matind(2); - matind[0] = col_index; - matind[1] = master_p->get_ncols() - 1; - - std::vector matval(2); - std::vector oldVarUb(1); - master_p->get_ub(oldVarUb.data(), col_index, col_index); - matval[0] = 1; - matval[1] = -oldVarUb[0]; - - master_p->add_rows(1, 2, std::vector(1, 'L').data(), std::vector(1, 0.0).data(), - nullptr, matstart.data(), matind.data(), matval.data()); - master_p->chg_row_name(master_p->get_nrows() - 1, - "link_" + pairOldNewVarnames.first + "_" + pairOldNewVarnames.second); - } +void addBinaryVariables( + SolverAbstract::Ptr master_p, + const std::map &variablesToBinarise_p) { + for (const auto &pairOldNewVarnames : variablesToBinarise_p) { + int col_index = master_p->get_col_index(pairOldNewVarnames.first); + + if (col_index == -1) { + std::cout << "missing variable " << pairOldNewVarnames.first + << " used in additional constraint file!\n"; + std::exit(1); + } + + master_p->add_cols( + 1, 0, std::vector(1, 0.0).data(), std::vector(2, 0).data(), + std::vector(0).data(), std::vector(0).data(), + std::vector(1, 0).data(), std::vector(1, 1e20).data()); + + // Changing column type to binary + master_p->chg_col_type(std::vector(1, master_p->get_ncols() - 1), + std::vector(1, 'B')); + + // Changing column name + master_p->chg_col_name(master_p->get_ncols() - 1, + pairOldNewVarnames.second); + + // Add linking constraint + std::vector matstart(2); + matstart[0] = 0; + matstart[1] = 2; + + std::vector matind(2); + matind[0] = col_index; + matind[1] = master_p->get_ncols() - 1; + + std::vector matval(2); + std::vector oldVarUb(1); + master_p->get_ub(oldVarUb.data(), col_index, col_index); + matval[0] = 1; + matval[1] = -oldVarUb[0]; + + master_p->add_rows(1, 2, std::vector(1, 'L').data(), + std::vector(1, 0.0).data(), nullptr, + matstart.data(), matind.data(), matval.data()); + master_p->chg_row_name( + master_p->get_nrows() - 1, + "link_" + pairOldNewVarnames.first + "_" + pairOldNewVarnames.second); + } } /** * \fn * \brief return Active Links Builder - * \param root path corresponding to the path to the simulation output directory containing the lp directory - * \return ActiveLinksBuilder object + * \param root path corresponding to the path to the simulation output + * directory containing the lp directory \return ActiveLinksBuilder object */ -ActiveLinksBuilder get_link_builders(const std::string &root) -{ - - auto const area_file_name = (Path(root) / "area.txt").get_str(); - auto const interco_file_name = (Path(root) / "interco.txt").get_str(); +ActiveLinksBuilder get_link_builders(const std::string &root) { + auto const area_file_name = (Path(root) / "area.txt").get_str(); + auto const interco_file_name = (Path(root) / "interco.txt").get_str(); - CandidatesINIReader candidateReader(interco_file_name, area_file_name); + CandidatesINIReader candidateReader(interco_file_name, area_file_name); - // Get all mandatory path - auto const xpansion_user_dir = (Path(root) / ".." / ".." / "user" / "expansion").get_str(); - auto const candidates_file_name = (Path(xpansion_user_dir) / CANDIDATES_INI).get_str(); - auto const capacity_folder = (Path(xpansion_user_dir) / "capa").get_str(); + // Get all mandatory path + auto const xpansion_user_dir = + (Path(root) / ".." / ".." / "user" / "expansion").get_str(); + auto const candidates_file_name = + (Path(xpansion_user_dir) / CANDIDATES_INI).get_str(); + auto const capacity_folder = (Path(xpansion_user_dir) / "capa").get_str(); - // Instantiation of candidates - const auto &candidatesDatas = candidateReader.readCandidateData(candidates_file_name); - const auto &mapLinkProfile = LinkProfileReader::getLinkProfileMap(capacity_folder, candidatesDatas); + // Instantiation of candidates + const auto &candidatesDatas = + candidateReader.readCandidateData(candidates_file_name); + const auto &mapLinkProfile = + LinkProfileReader::getLinkProfileMap(capacity_folder, candidatesDatas); - return ActiveLinksBuilder(candidatesDatas, mapLinkProfile); + return ActiveLinksBuilder(candidatesDatas, mapLinkProfile); } \ No newline at end of file diff --git a/src/cpp/lpnamer/problem_modifier/LauncherHelpers.h b/src/cpp/lpnamer/problem_modifier/LauncherHelpers.h index e5bd88fc4..a0a9299fc 100644 --- a/src/cpp/lpnamer/problem_modifier/LauncherHelpers.h +++ b/src/cpp/lpnamer/problem_modifier/LauncherHelpers.h @@ -1,11 +1,10 @@ #pragma once -#include "solver_utils.h" +#include -#include "AdditionalConstraints.h" #include "ActiveLinks.h" - -#include +#include "AdditionalConstraints.h" +#include "solver_utils.h" /** * \brief adds binary variables and additional constraints to an existent solver @@ -13,7 +12,9 @@ * \param master_p solver to which the constraints and variables will be added * \param additionalConstraints_p the additional constraints to add */ -void treatAdditionalConstraints(SolverAbstract::Ptr master_p, const AdditionalConstraints& additionalConstraints_p); +void treatAdditionalConstraints( + SolverAbstract::Ptr master_p, + const AdditionalConstraints& additionalConstraints_p); /** * \brief adds an additional constraint to an existent solver @@ -21,24 +22,28 @@ void treatAdditionalConstraints(SolverAbstract::Ptr master_p, const AdditionalCo * \param master_p solver to which the constraint will be added * \param additionalConstraint_p the additional constraint to add */ -void addAdditionalConstraint(SolverAbstract::Ptr master_p, AdditionalConstraint & additionalConstraint_p); +void addAdditionalConstraint(SolverAbstract::Ptr master_p, + AdditionalConstraint& additionalConstraint_p); /** * \brief creates a binary variable and its corresponding linking constraint * - * \param master_p solver to which the binary variable and the linking constraint will be added - * \param variablesToBinarise_p map listing the variables to add and their corresponding ones + * \param master_p solver to which the binary variable and the linking + * constraint will be added \param variablesToBinarise_p map listing the + * variables to add and their corresponding ones * * for each entry (BinVar, CorrespondingVar) from the input map, * creates the binary variable BinVar - * adds the linking constraint link_BinVar_CorrespondingVar : CorrespondingVar <= UB(CorrespondingVar) * BinVar + * adds the linking constraint link_BinVar_CorrespondingVar : + * CorrespondingVar <= UB(CorrespondingVar) * BinVar */ -void addBinaryVariables(SolverAbstract::Ptr master_p, std::map const & variablesToBinarise_p); - +void addBinaryVariables( + SolverAbstract::Ptr master_p, + std::map const& variablesToBinarise_p); /** -* \brief return Active Links Builder -* \param root path corresponding to the path to the simulation output directory containing the lp directory -* \return ActiveLinksBuilder object -*/ + * \brief return Active Links Builder + * \param root path corresponding to the path to the simulation output + * directory containing the lp directory \return ActiveLinksBuilder object + */ ActiveLinksBuilder get_link_builders(const std::string& root); \ No newline at end of file diff --git a/src/cpp/lpnamer/problem_modifier/LinkProblemsGenerator.cpp b/src/cpp/lpnamer/problem_modifier/LinkProblemsGenerator.cpp index 663d7a96f..80a5a9dbb 100644 --- a/src/cpp/lpnamer/problem_modifier/LinkProblemsGenerator.cpp +++ b/src/cpp/lpnamer/problem_modifier/LinkProblemsGenerator.cpp @@ -1,46 +1,43 @@ +#include "LinkProblemsGenerator.h" + #include -#include "LinkProblemsGenerator.h" #include "VariableFileReader.h" -#include "solver_utils.h" -#include "helpers/StringUtils.h" #include "helpers/Path.h" +#include "helpers/StringUtils.h" +#include "solver_utils.h" -ProblemData::ProblemData(const std::string &problem_mps, const std::string &variables_txt) : _problem_mps(problem_mps), _variables_txt(variables_txt) -{ -} - -std::vector LinkProblemsGenerator::readMPSList(std::string const &mps_filePath_p) const -{ - std::string line; - std::vector result; - std::ifstream mps_filestream(mps_filePath_p.c_str()); - if (!mps_filestream.good()) - { - std::cout << "unable to open " << mps_filePath_p << std::endl; - std::exit(1); - } - while (std::getline(mps_filestream, line)) - { - std::stringstream buffer(line); - if (!line.empty() && line.front() != '#') - { - - std::string ProblemMps; - std::string VariablesTxt; - std::string ConstraintsTxt; - - buffer >> ProblemMps; - buffer >> VariablesTxt; - buffer >> ConstraintsTxt; - - ProblemData problemData(ProblemMps, VariablesTxt); - - result.push_back(problemData); - } +ProblemData::ProblemData(const std::string &problem_mps, + const std::string &variables_txt) + : _problem_mps(problem_mps), _variables_txt(variables_txt) {} + +std::vector LinkProblemsGenerator::readMPSList( + std::string const &mps_filePath_p) const { + std::string line; + std::vector result; + std::ifstream mps_filestream(mps_filePath_p.c_str()); + if (!mps_filestream.good()) { + std::cout << "unable to open " << mps_filePath_p << std::endl; + std::exit(1); + } + while (std::getline(mps_filestream, line)) { + std::stringstream buffer(line); + if (!line.empty() && line.front() != '#') { + std::string ProblemMps; + std::string VariablesTxt; + std::string ConstraintsTxt; + + buffer >> ProblemMps; + buffer >> VariablesTxt; + buffer >> ConstraintsTxt; + + ProblemData problemData(ProblemMps, VariablesTxt); + + result.push_back(problemData); } + } - return result; + return result; } /** @@ -48,75 +45,80 @@ std::vector LinkProblemsGenerator::readMPSList(std::string const &m * * \param root String corresponding to the path where are located input data * \param mps Strings vector with the list of mps files - * \param couplings map of pair of strings associated to an int. Determine the correspondence between optimizer variables and interconnection candidates + * \param couplings map of pair of strings associated to an int. Determine the + * correspondence between optimizer variables and interconnection candidates * \return void */ -void LinkProblemsGenerator::treat(std::string const &root, - ProblemData const &problemData, - std::map, int> &couplings) const -{ - - // get path of file problem***.mps, variable***.txt and constraints***.txt - auto const mps_name = (Path(root) / problemData._problem_mps).get_str(); - auto const var_name = (Path(root) / problemData._variables_txt).get_str(); - - // new mps file in the new lp directory - std::string const lp_name = problemData._problem_mps.substr(0, problemData._problem_mps.size() - 4); - auto const lp_mps_name = (Path(root) / "lp" / (lp_name + ".mps")).get_str(); - - // List of variables - VariableFileReadNameConfiguration variable_name_config; - variable_name_config.ntc_variable_name = "ValeurDeNTCOrigineVersExtremite"; - variable_name_config.cost_origin_variable_name = "CoutOrigineVersExtremiteDeLInterconnexion"; - variable_name_config.cost_extremite_variable_name = "CoutExtremiteVersOrigineDeLInterconnexion"; - - auto variableReader = VariableFileReader(var_name, _links, variable_name_config); - - std::vector var_names = variableReader.getVariables(); - std::map p_ntc_columns = variableReader.getNtcVarColumns(); - std::map p_direct_cost_columns = variableReader.getDirectCostVarColumns(); - std::map p_indirect_cost_columns = variableReader.getIndirectCostVarColumns(); - - SolverFactory factory; - SolverAbstract::Ptr in_prblm; - in_prblm = factory.create_solver(_solver_name); - in_prblm->read_prob_mps(mps_name); - - solver_rename_vars(in_prblm, var_names); - - auto problem_modifier = ProblemModifier(); - in_prblm = problem_modifier.changeProblem(std::move(in_prblm), _links, p_ntc_columns, p_direct_cost_columns, p_indirect_cost_columns); - - // couplings creation - for (const ActiveLink &link : _links) - { - for (const Candidate &candidate : link.getCandidates()) - { - if (problem_modifier.has_candidate_col_id(candidate.get_name())) - { - couplings[{candidate.get_name(), mps_name}] = problem_modifier.get_candidate_col_id(candidate.get_name()); - } - } +void LinkProblemsGenerator::treat( + std::string const &root, ProblemData const &problemData, + std::map, int> &couplings) const { + // get path of file problem***.mps, variable***.txt and constraints***.txt + auto const mps_name = (Path(root) / problemData._problem_mps).get_str(); + auto const var_name = (Path(root) / problemData._variables_txt).get_str(); + + // new mps file in the new lp directory + std::string const lp_name = + problemData._problem_mps.substr(0, problemData._problem_mps.size() - 4); + auto const lp_mps_name = (Path(root) / "lp" / (lp_name + ".mps")).get_str(); + + // List of variables + VariableFileReadNameConfiguration variable_name_config; + variable_name_config.ntc_variable_name = "ValeurDeNTCOrigineVersExtremite"; + variable_name_config.cost_origin_variable_name = + "CoutOrigineVersExtremiteDeLInterconnexion"; + variable_name_config.cost_extremite_variable_name = + "CoutExtremiteVersOrigineDeLInterconnexion"; + + auto variableReader = + VariableFileReader(var_name, _links, variable_name_config); + + std::vector var_names = variableReader.getVariables(); + std::map p_ntc_columns = + variableReader.getNtcVarColumns(); + std::map p_direct_cost_columns = + variableReader.getDirectCostVarColumns(); + std::map p_indirect_cost_columns = + variableReader.getIndirectCostVarColumns(); + + SolverFactory factory; + SolverAbstract::Ptr in_prblm; + in_prblm = factory.create_solver(_solver_name); + in_prblm->read_prob_mps(mps_name); + + solver_rename_vars(in_prblm, var_names); + + auto problem_modifier = ProblemModifier(); + in_prblm = problem_modifier.changeProblem( + std::move(in_prblm), _links, p_ntc_columns, p_direct_cost_columns, + p_indirect_cost_columns); + + // couplings creation + for (const ActiveLink &link : _links) { + for (const Candidate &candidate : link.getCandidates()) { + if (problem_modifier.has_candidate_col_id(candidate.get_name())) { + couplings[{candidate.get_name(), mps_name}] = + problem_modifier.get_candidate_col_id(candidate.get_name()); + } } + } - in_prblm->write_prob_mps(lp_mps_name); + in_prblm->write_prob_mps(lp_mps_name); } /** * \brief Execute the treat function for each mps elements * * \param root String corresponding to the path where are located input data - * \param couplings map of pair of strings associated to an int. Determine the correspondence between optimizer variables and interconnection candidates + * \param couplings map of pair of strings associated to an int. Determine the + * correspondence between optimizer variables and interconnection candidates * \return void */ -void LinkProblemsGenerator::treatloop(std::string const &root, std::map, - int> &couplings) const -{ - - auto const mps_file_name = (Path(root) / MPS_TXT).get_str(); - - for (auto const &mps : readMPSList(mps_file_name)) - { - treat(root, mps, couplings); - } +void LinkProblemsGenerator::treatloop( + std::string const &root, + std::map, int> &couplings) const { + auto const mps_file_name = (Path(root) / MPS_TXT).get_str(); + + for (auto const &mps : readMPSList(mps_file_name)) { + treat(root, mps, couplings); + } } diff --git a/src/cpp/lpnamer/problem_modifier/LinkProblemsGenerator.h b/src/cpp/lpnamer/problem_modifier/LinkProblemsGenerator.h index df0b0e816..eb8daa2f1 100644 --- a/src/cpp/lpnamer/problem_modifier/LinkProblemsGenerator.h +++ b/src/cpp/lpnamer/problem_modifier/LinkProblemsGenerator.h @@ -1,43 +1,42 @@ #pragma once -#include #include -#include "common_lpnamer.h" -#include "Candidate.h" + +#include + #include "ActiveLinks.h" +#include "Candidate.h" #include "ProblemModifier.h" +#include "common_lpnamer.h" +const std::string CANDIDATES_INI{"candidates.ini"}; +const std::string STRUCTURE_FILE{"structure.txt"}; +const std::string MPS_TXT{"mps.txt"}; +const std::string STUDY_FILE{"study.antares"}; -const std::string CANDIDATES_INI {"candidates.ini"}; -const std::string STRUCTURE_FILE {"structure.txt"}; -const std::string MPS_TXT {"mps.txt"}; -const std::string STUDY_FILE {"study.antares"}; - -struct ProblemData -{ - ProblemData(const std::string& problem_mps, const std::string& variables_txt); - std::string _problem_mps; - std::string _variables_txt; +struct ProblemData { + ProblemData(const std::string& problem_mps, const std::string& variables_txt); + std::string _problem_mps; + std::string _variables_txt; }; class LinkProblemsGenerator { + public: + LinkProblemsGenerator(const std::vector& links, + const std::string& solver_name) + : _links(links), _solver_name(solver_name) {} -public: - - LinkProblemsGenerator(const std::vector& links, const std::string& solver_name): - _links(links),_solver_name(solver_name) - {} - - void treatloop(std::string const & root, std::map< std::pair, int>& couplings) const; - -private: + void treatloop( + std::string const& root, + std::map, int>& couplings) const; - std::vector readMPSList(std::string const & mps_filePath_p) const; + private: + std::vector readMPSList(std::string const& mps_filePath_p) const; - void treat(std::string const& root, ProblemData const&, - std::map< std::pair, int>& couplings) const ; + void treat( + std::string const& root, ProblemData const&, + std::map, int>& couplings) const; - const std::vector& _links; - std::string _solver_name; + const std::vector& _links; + std::string _solver_name; }; diff --git a/src/cpp/lpnamer/problem_modifier/LinkdataRecord.cpp b/src/cpp/lpnamer/problem_modifier/LinkdataRecord.cpp index 17c1916a5..01c1886cf 100644 --- a/src/cpp/lpnamer/problem_modifier/LinkdataRecord.cpp +++ b/src/cpp/lpnamer/problem_modifier/LinkdataRecord.cpp @@ -1,95 +1,73 @@ #include "StudyUpdater.h" - - - - -LinkdataRecord::LinkdataRecord(bool modernAntaresVersion_p): -modernAntaresVersion_(modernAntaresVersion_p), -fileColumns{ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0} -{ +LinkdataRecord::LinkdataRecord(bool modernAntaresVersion_p) + : modernAntaresVersion_(modernAntaresVersion_p), fileColumns{0, 0, 0, 0, + 0, 0, 0, 0} {} + +LinkdataRecord::LinkdataRecord(const FileColumns& afileColumns) + : modernAntaresVersion_(true), fileColumns(afileColumns) {} + +LinkdataRecord::LinkdataRecord(double directCapacity_p, + double indirectCapacity_p, + double directHurdlesCost_p, + double indirectHurdlesCost_p, + double impedances_p) + : modernAntaresVersion_(false), + fileColumns{directCapacity_p, + indirectCapacity_p, + directHurdlesCost_p, + indirectHurdlesCost_p, + impedances_p, + 0, + 0, + 0} + +{} + +void LinkdataRecord::reset() { + fileColumns.directCapacity_ = 0; + fileColumns.indirectCapacity_ = 0; + fileColumns.directHurdlesCost_ = 0; + fileColumns.indirectHurdlesCost_ = 0; + fileColumns.impedances_ = 0; + fileColumns.loopFlow_ = 0; + fileColumns.pShiftMin_ = 0; + fileColumns.pShiftMax_ = 0; } +void LinkdataRecord::fillFromRow(std::string const& line_p) { + std::istringstream iss_l(line_p); + iss_l >> fileColumns.directCapacity_; + iss_l >> fileColumns.indirectCapacity_; + iss_l >> fileColumns.directHurdlesCost_; + iss_l >> fileColumns.indirectHurdlesCost_; + iss_l >> fileColumns.impedances_; -LinkdataRecord::LinkdataRecord(const FileColumns& afileColumns): -modernAntaresVersion_(true), -fileColumns(afileColumns) -{ + if (modernAntaresVersion_) { + iss_l >> fileColumns.loopFlow_; + iss_l >> fileColumns.pShiftMin_; + iss_l >> fileColumns.pShiftMax_; + } } - -LinkdataRecord::LinkdataRecord(double directCapacity_p, double indirectCapacity_p, - double directHurdlesCost_p, double indirectHurdlesCost_p, double impedances_p): - modernAntaresVersion_(false), - fileColumns{ - directCapacity_p, - indirectCapacity_p, - directHurdlesCost_p, - indirectHurdlesCost_p, - impedances_p, - 0, - 0, - 0} - -{ +void LinkdataRecord::updateCapacities(double directCapacity_p, + double indirectCapacity_p) { + fileColumns.directCapacity_ = directCapacity_p; + fileColumns.indirectCapacity_ = indirectCapacity_p; } -void LinkdataRecord::reset() -{ - fileColumns.directCapacity_ = 0; - fileColumns.indirectCapacity_ = 0; - fileColumns.directHurdlesCost_ = 0; - fileColumns.indirectHurdlesCost_ = 0; - fileColumns.impedances_ = 0; - fileColumns.loopFlow_ = 0; - fileColumns.pShiftMin_ = 0; - fileColumns.pShiftMax_ = 0; -} - - -void LinkdataRecord::fillFromRow(std::string const & line_p) -{ - std::istringstream iss_l(line_p); - - iss_l >> fileColumns.directCapacity_; - iss_l >> fileColumns.indirectCapacity_; - iss_l >> fileColumns.directHurdlesCost_; - iss_l >> fileColumns.indirectHurdlesCost_; - iss_l >> fileColumns.impedances_; - - if(modernAntaresVersion_) - { - iss_l >> fileColumns.loopFlow_; - iss_l >> fileColumns.pShiftMin_; - iss_l >> fileColumns.pShiftMax_; - } -} - - -void LinkdataRecord::updateCapacities(double directCapacity_p, double indirectCapacity_p) -{ - fileColumns.directCapacity_ = directCapacity_p; - fileColumns.indirectCapacity_ = indirectCapacity_p; -} - - -std::string LinkdataRecord::to_row(std::string const & sep_p) const -{ - std::string row_l = std::to_string(fileColumns.directCapacity_) + sep_p + std::to_string(fileColumns.indirectCapacity_) - + sep_p + std::to_string(fileColumns.directHurdlesCost_) + sep_p + std::to_string(fileColumns.indirectHurdlesCost_) + sep_p + std::to_string(fileColumns.impedances_); - if(modernAntaresVersion_) - { - row_l += sep_p + std::to_string(fileColumns.loopFlow_) + sep_p + std::to_string(fileColumns.pShiftMin_) + sep_p + std::to_string(fileColumns.pShiftMax_); - } - - return row_l; +std::string LinkdataRecord::to_row(std::string const& sep_p) const { + std::string row_l = std::to_string(fileColumns.directCapacity_) + sep_p + + std::to_string(fileColumns.indirectCapacity_) + sep_p + + std::to_string(fileColumns.directHurdlesCost_) + sep_p + + std::to_string(fileColumns.indirectHurdlesCost_) + sep_p + + std::to_string(fileColumns.impedances_); + if (modernAntaresVersion_) { + row_l += sep_p + std::to_string(fileColumns.loopFlow_) + sep_p + + std::to_string(fileColumns.pShiftMin_) + sep_p + + std::to_string(fileColumns.pShiftMax_); + } + + return row_l; } diff --git a/src/cpp/lpnamer/problem_modifier/MasterProblemBuilder.cpp b/src/cpp/lpnamer/problem_modifier/MasterProblemBuilder.cpp index c4f5dd635..894855a35 100644 --- a/src/cpp/lpnamer/problem_modifier/MasterProblemBuilder.cpp +++ b/src/cpp/lpnamer/problem_modifier/MasterProblemBuilder.cpp @@ -4,138 +4,135 @@ #include "MasterProblemBuilder.h" #include + #include #include -MasterProblemBuilder::MasterProblemBuilder(const std::string& master_formulation):_master_formulation (master_formulation) -{ -} +MasterProblemBuilder::MasterProblemBuilder( + const std::string& master_formulation) + : _master_formulation(master_formulation) {} -std::shared_ptr MasterProblemBuilder::build(const std::string& solverName, const std::vector& candidates) -{ - _indexOfNvar.clear(); - _indexOfPmaxVar.clear(); +std::shared_ptr MasterProblemBuilder::build( + const std::string& solverName, const std::vector& candidates) { + _indexOfNvar.clear(); + _indexOfPmaxVar.clear(); - SolverFactory factory; - auto master_l = factory.create_solver(solverName); + SolverFactory factory; + auto master_l = factory.create_solver(solverName); - addVariablesPmaxOnEachCandidate(candidates, master_l); + addVariablesPmaxOnEachCandidate(candidates, master_l); - std::vector candidatesInteger; + std::vector candidatesInteger; - std::copy_if(candidates.begin(), candidates.end(), - back_inserter(candidatesInteger), - [](const Candidate& cand) { return cand.is_integer(); }); + std::copy_if(candidates.begin(), candidates.end(), + back_inserter(candidatesInteger), + [](const Candidate& cand) { return cand.is_integer(); }); - if (_master_formulation == "integer") - { - addNvarOnEachIntegerCandidate(candidatesInteger, master_l); + if (_master_formulation == "integer") { + addNvarOnEachIntegerCandidate(candidatesInteger, master_l); - addPmaxConstraint(candidatesInteger, master_l); - } + addPmaxConstraint(candidatesInteger, master_l); + } - return master_l; + return master_l; } -void MasterProblemBuilder::addPmaxConstraint(const std::vector& candidatesInteger, SolverAbstract::Ptr& master_l) -{ - - auto n_integer = (int)candidatesInteger.size(); - if (n_integer > 0) - { - std::vector dmatval; - std::vector colind; - std::vector rowtype; - std::vector rhs; - std::vector rstart; - dmatval.reserve(2 * n_integer); - colind.reserve(2 * n_integer); - rowtype.reserve(n_integer); - rhs.reserve(n_integer); - rstart.reserve(n_integer + 1); - - int positionInIntegerCandidadeList(0); - auto nbColPmaxVar = (int)_indexOfPmaxVar.size(); - - for (const auto& candidate : candidatesInteger) - { - int pmaxVarColumNumber = getPmaxVarColumnNumberFor(candidate); - int nVarColumNumber = nbColPmaxVar + positionInIntegerCandidadeList; - - // pMax - n unit_size = 0 - rstart.push_back((int)dmatval.size()); - rhs.push_back(0); - rowtype.push_back('E'); - - colind.push_back(pmaxVarColumNumber); - dmatval.push_back(1); - - colind.push_back(nVarColumNumber); - dmatval.push_back(-candidate.unit_size()); - - positionInIntegerCandidadeList++; - } - rstart.push_back((int)dmatval.size()); - - solver_addrows(master_l, rowtype, rhs, {}, rstart, colind, dmatval); - } +void MasterProblemBuilder::addPmaxConstraint( + const std::vector& candidatesInteger, + SolverAbstract::Ptr& master_l) { + auto n_integer = (int)candidatesInteger.size(); + if (n_integer > 0) { + std::vector dmatval; + std::vector colind; + std::vector rowtype; + std::vector rhs; + std::vector rstart; + dmatval.reserve(2 * n_integer); + colind.reserve(2 * n_integer); + rowtype.reserve(n_integer); + rhs.reserve(n_integer); + rstart.reserve(n_integer + 1); + + int positionInIntegerCandidadeList(0); + auto nbColPmaxVar = (int)_indexOfPmaxVar.size(); + + for (const auto& candidate : candidatesInteger) { + int pmaxVarColumNumber = getPmaxVarColumnNumberFor(candidate); + int nVarColumNumber = nbColPmaxVar + positionInIntegerCandidadeList; + + // pMax - n unit_size = 0 + rstart.push_back((int)dmatval.size()); + rhs.push_back(0); + rowtype.push_back('E'); + + colind.push_back(pmaxVarColumNumber); + dmatval.push_back(1); + + colind.push_back(nVarColumNumber); + dmatval.push_back(-candidate.unit_size()); + + positionInIntegerCandidadeList++; + } + rstart.push_back((int)dmatval.size()); + + solver_addrows(master_l, rowtype, rhs, {}, rstart, colind, dmatval); + } } -int MasterProblemBuilder::getPmaxVarColumnNumberFor(const Candidate& candidate) -{ - const auto& it = _indexOfPmaxVar.find(candidate.get_name()); - if (it == _indexOfPmaxVar.end()) - { - std::string message = "There is no Pvar for the candidate " + candidate.get_name(); - throw std::runtime_error(message); - } - return it->second; +int MasterProblemBuilder::getPmaxVarColumnNumberFor( + const Candidate& candidate) { + const auto& it = _indexOfPmaxVar.find(candidate.get_name()); + if (it == _indexOfPmaxVar.end()) { + std::string message = + "There is no Pvar for the candidate " + candidate.get_name(); + throw std::runtime_error(message); + } + return it->second; } -void MasterProblemBuilder::addNvarOnEachIntegerCandidate(const std::vector& candidatesInteger, SolverAbstract::Ptr& master_l) const -{ - - auto nbNvar = (int) candidatesInteger.size(); - if (nbNvar > 0) - { - std::vector zeros(nbNvar, 0.0); - std::vector mstart(nbNvar, 0); - std::vector integer_type(nbNvar, 'I'); - std::vector colNames(0); - std::vector max_unit; - - for (int i = 0; i < candidatesInteger.size(); i++) - { - const auto& candidate = candidatesInteger.at(i); - max_unit.push_back(candidate.max_unit()); - } - - solver_addcols(master_l, zeros, mstart, {}, {}, zeros, max_unit, integer_type, colNames); - } +void MasterProblemBuilder::addNvarOnEachIntegerCandidate( + const std::vector& candidatesInteger, + SolverAbstract::Ptr& master_l) const { + auto nbNvar = (int)candidatesInteger.size(); + if (nbNvar > 0) { + std::vector zeros(nbNvar, 0.0); + std::vector mstart(nbNvar, 0); + std::vector integer_type(nbNvar, 'I'); + std::vector colNames(0); + std::vector max_unit; + + for (int i = 0; i < candidatesInteger.size(); i++) { + const auto& candidate = candidatesInteger.at(i); + max_unit.push_back(candidate.max_unit()); + } + + solver_addcols(master_l, zeros, mstart, {}, {}, zeros, max_unit, + integer_type, colNames); + } } -void MasterProblemBuilder::addVariablesPmaxOnEachCandidate(const std::vector& candidates, SolverAbstract::Ptr& master_l) -{ - auto nbCandidates = (int) candidates.size(); - - if (nbCandidates > 0) - { - std::vector mstart(nbCandidates, 0); - std::vector obj_candidate(nbCandidates, 0); - std::vector lb_candidate(nbCandidates, -1e20); - std::vector ub_candidate(nbCandidates, 1e20); - std::vector coltypes_candidate(nbCandidates, 'C'); - std::vector candidate_names(nbCandidates); - - for (int i = 0; i < candidates.size(); i++) { - const auto& candidate = candidates.at(i); - obj_candidate[i] = candidate.obj(); - lb_candidate[i] = candidate.lb(); - ub_candidate[i] = candidate.ub(); - candidate_names[i] = candidate.get_name(); - _indexOfPmaxVar[candidate.get_name()] = i; - } - - solver_addcols(master_l, obj_candidate, mstart, {}, {}, lb_candidate, ub_candidate, coltypes_candidate, candidate_names); - } +void MasterProblemBuilder::addVariablesPmaxOnEachCandidate( + const std::vector& candidates, SolverAbstract::Ptr& master_l) { + auto nbCandidates = (int)candidates.size(); + + if (nbCandidates > 0) { + std::vector mstart(nbCandidates, 0); + std::vector obj_candidate(nbCandidates, 0); + std::vector lb_candidate(nbCandidates, -1e20); + std::vector ub_candidate(nbCandidates, 1e20); + std::vector coltypes_candidate(nbCandidates, 'C'); + std::vector candidate_names(nbCandidates); + + for (int i = 0; i < candidates.size(); i++) { + const auto& candidate = candidates.at(i); + obj_candidate[i] = candidate.obj(); + lb_candidate[i] = candidate.lb(); + ub_candidate[i] = candidate.ub(); + candidate_names[i] = candidate.get_name(); + _indexOfPmaxVar[candidate.get_name()] = i; + } + + solver_addcols(master_l, obj_candidate, mstart, {}, {}, lb_candidate, + ub_candidate, coltypes_candidate, candidate_names); + } } diff --git a/src/cpp/lpnamer/problem_modifier/MasterProblemBuilder.h b/src/cpp/lpnamer/problem_modifier/MasterProblemBuilder.h index 5694ae0ad..fe59d2cf6 100644 --- a/src/cpp/lpnamer/problem_modifier/MasterProblemBuilder.h +++ b/src/cpp/lpnamer/problem_modifier/MasterProblemBuilder.h @@ -3,27 +3,33 @@ // #include + #include + #include "ActiveLinks.h" #ifndef ANTARESXPANSION_MASTERPROBLEMBUILDER_H #define ANTARESXPANSION_MASTERPROBLEMBUILDER_H class MasterProblemBuilder { -public: - explicit MasterProblemBuilder(const std::string& master_formulation); - std::shared_ptr build(const std::string& solverName, const std::vector& candidates); - -private : - void addNvarOnEachIntegerCandidate(const std::vector& candidatesInteger, SolverAbstract::Ptr& master_l) const; - void addVariablesPmaxOnEachCandidate(const std::vector& candidates, SolverAbstract::Ptr& master_l); - void addPmaxConstraint(const std::vector& candidatesInteger, SolverAbstract::Ptr& master_l); - int getPmaxVarColumnNumberFor(const Candidate& candidate); + public: + explicit MasterProblemBuilder(const std::string& master_formulation); + std::shared_ptr build( + const std::string& solverName, const std::vector& candidates); - std::unordered_map _indexOfPmaxVar; - std::unordered_map _indexOfNvar; - std::string _master_formulation; + private: + void addNvarOnEachIntegerCandidate( + const std::vector& candidatesInteger, + SolverAbstract::Ptr& master_l) const; + void addVariablesPmaxOnEachCandidate(const std::vector& candidates, + SolverAbstract::Ptr& master_l); + void addPmaxConstraint(const std::vector& candidatesInteger, + SolverAbstract::Ptr& master_l); + int getPmaxVarColumnNumberFor(const Candidate& candidate); + std::unordered_map _indexOfPmaxVar; + std::unordered_map _indexOfNvar; + std::string _master_formulation; }; -#endif //ANTARESXPANSION_MASTERPROBLEMBUILDER_H +#endif // ANTARESXPANSION_MASTERPROBLEMBUILDER_H diff --git a/src/cpp/lpnamer/problem_modifier/ProblemModifier.cpp b/src/cpp/lpnamer/problem_modifier/ProblemModifier.cpp index 3e1a8dc37..4688e61a2 100644 --- a/src/cpp/lpnamer/problem_modifier/ProblemModifier.cpp +++ b/src/cpp/lpnamer/problem_modifier/ProblemModifier.cpp @@ -1,253 +1,294 @@ +#include "ProblemModifier.h" + #include + #include "solver_utils.h" -#include "ProblemModifier.h" ProblemModifier::ProblemModifier() = default; std::vector extract_col_ids(const ColumnsToChange &columns_to_change) { - std::vector col_ids; - col_ids.reserve(columns_to_change.size()); - std::transform(columns_to_change.begin(),columns_to_change.end(), std::back_inserter(col_ids),[](const ColumnToChange& col){return col.id;}); - return col_ids; + std::vector col_ids; + col_ids.reserve(columns_to_change.size()); + std::transform(columns_to_change.begin(), columns_to_change.end(), + std::back_inserter(col_ids), + [](const ColumnToChange &col) { return col.id; }); + return col_ids; } void ProblemModifier::remove_bounds_for(const std::vector &col_ids) const { - change_upper_bounds_to_pos_inf(col_ids); - change_lower_bounds_to_neg_inf(col_ids); + change_upper_bounds_to_pos_inf(col_ids); + change_lower_bounds_to_neg_inf(col_ids); } -void ProblemModifier::change_lower_bounds_to_neg_inf(const std::vector &col_ids) const { - std::vector lb_char(col_ids.size(), 'L'); - std::vector neg_inf(col_ids.size(), -1e20); - _math_problem->chg_bounds(col_ids, lb_char, neg_inf); +void ProblemModifier::change_lower_bounds_to_neg_inf( + const std::vector &col_ids) const { + std::vector lb_char(col_ids.size(), 'L'); + std::vector neg_inf(col_ids.size(), -1e20); + _math_problem->chg_bounds(col_ids, lb_char, neg_inf); } -void ProblemModifier::change_upper_bounds_to_pos_inf(const std::vector &col_ids) const{ - std::vector ub_char(col_ids.size(), 'U'); - std::vector pos_inf(col_ids.size(), 1e20); - _math_problem->chg_bounds(col_ids, ub_char, pos_inf); +void ProblemModifier::change_upper_bounds_to_pos_inf( + const std::vector &col_ids) const { + std::vector ub_char(col_ids.size(), 'U'); + std::vector pos_inf(col_ids.size(), 1e20); + _math_problem->chg_bounds(col_ids, ub_char, pos_inf); } -unsigned int ProblemModifier::get_candidate_col_id(const std::string& cand_name) const { - if (_candidate_col_id.find(cand_name) == _candidate_col_id.end()){ - throw std::runtime_error("Candidate '" + cand_name + "' not added in problem"); - } - return _candidate_col_id.at(cand_name); +unsigned int ProblemModifier::get_candidate_col_id( + const std::string &cand_name) const { + if (_candidate_col_id.find(cand_name) == _candidate_col_id.end()) { + throw std::runtime_error("Candidate '" + cand_name + + "' not added in problem"); + } + return _candidate_col_id.at(cand_name); } -bool ProblemModifier::has_candidate_col_id(const std::string& cand_name) const{ - return _candidate_col_id.find(cand_name) != _candidate_col_id.end(); +bool ProblemModifier::has_candidate_col_id(const std::string &cand_name) const { + return _candidate_col_id.find(cand_name) != _candidate_col_id.end(); } -std::shared_ptr -ProblemModifier::changeProblem(std::shared_ptr mathProblem, const std::vector &active_links, - const std::map &p_ntc_columns, - const std::map &p_direct_cost_columns, - const std::map &p_indirect_cost_columns) { - _math_problem = std::move(mathProblem); - _n_cols_at_start = _math_problem->get_ncols(); - - changeProblem(active_links, p_ntc_columns, p_direct_cost_columns,p_indirect_cost_columns); - return std::move(_math_problem); +std::shared_ptr ProblemModifier::changeProblem( + std::shared_ptr mathProblem, + const std::vector &active_links, + const std::map &p_ntc_columns, + const std::map &p_direct_cost_columns, + const std::map &p_indirect_cost_columns) { + _math_problem = std::move(mathProblem); + _n_cols_at_start = _math_problem->get_ncols(); + + changeProblem(active_links, p_ntc_columns, p_direct_cost_columns, + p_indirect_cost_columns); + return std::move(_math_problem); } -void ProblemModifier::changeProblem(const std::vector &active_links, - const std::map &p_ntc_columns, - const std::map &p_direct_cost_columns, - const std::map &p_indirect_cost_columns) { - for (const auto& link : active_links) { - remove_bounds_for(extract_col_ids(p_ntc_columns.at(link.get_idLink()))); - - if (p_direct_cost_columns.find(link.get_idLink()) != p_direct_cost_columns.end()) { - change_upper_bounds_to_pos_inf(extract_col_ids(p_direct_cost_columns.at(link.get_idLink()))); - } - if (p_indirect_cost_columns.find(link.get_idLink()) != p_indirect_cost_columns.end()) { - change_upper_bounds_to_pos_inf(extract_col_ids(p_indirect_cost_columns.at(link.get_idLink()))); - } +void ProblemModifier::changeProblem( + const std::vector &active_links, + const std::map &p_ntc_columns, + const std::map &p_direct_cost_columns, + const std::map &p_indirect_cost_columns) { + for (const auto &link : active_links) { + remove_bounds_for(extract_col_ids(p_ntc_columns.at(link.get_idLink()))); + + if (p_direct_cost_columns.find(link.get_idLink()) != + p_direct_cost_columns.end()) { + change_upper_bounds_to_pos_inf( + extract_col_ids(p_direct_cost_columns.at(link.get_idLink()))); } + if (p_indirect_cost_columns.find(link.get_idLink()) != + p_indirect_cost_columns.end()) { + change_upper_bounds_to_pos_inf( + extract_col_ids(p_indirect_cost_columns.at(link.get_idLink()))); + } + } - add_new_columns(candidates_with_not_null_profile(active_links, extract_time_steps(p_ntc_columns))); - - add_new_ntc_constraints(active_links, p_ntc_columns); - add_new_direct_cost_constraints(active_links, p_direct_cost_columns); - add_new_indirect_cost_constraints(active_links, p_indirect_cost_columns); + add_new_columns(candidates_with_not_null_profile( + active_links, extract_time_steps(p_ntc_columns))); + add_new_ntc_constraints(active_links, p_ntc_columns); + add_new_direct_cost_constraints(active_links, p_direct_cost_columns); + add_new_indirect_cost_constraints(active_links, p_indirect_cost_columns); } -void ProblemModifier::add_new_ntc_constraints(const std::vector &active_links, - const std::map &p_ntc_columns) { - std::vector dmatval; - std::vector colind; - std::vector rowtype; - std::vector rhs; - std::vector rstart; - - rstart.push_back(0); - - for (const auto& link : active_links) { - for(const ColumnToChange& column : p_ntc_columns.at(link.get_idLink())){ - add_direct_profile_column_constraint(dmatval,colind,rowtype,rhs,rstart,link,column); - add_indirect_profile_ntc_column_constraint(dmatval, colind, rowtype, rhs, rstart, link, column); - } +void ProblemModifier::add_new_ntc_constraints( + const std::vector &active_links, + const std::map &p_ntc_columns) { + std::vector dmatval; + std::vector colind; + std::vector rowtype; + std::vector rhs; + std::vector rstart; + + rstart.push_back(0); + + for (const auto &link : active_links) { + for (const ColumnToChange &column : p_ntc_columns.at(link.get_idLink())) { + add_direct_profile_column_constraint(dmatval, colind, rowtype, rhs, + rstart, link, column); + add_indirect_profile_ntc_column_constraint(dmatval, colind, rowtype, rhs, + rstart, link, column); } + } - solver_addrows(_math_problem, rowtype, rhs, {}, rstart, colind, dmatval); + solver_addrows(_math_problem, rowtype, rhs, {}, rstart, colind, dmatval); } -void ProblemModifier::add_new_direct_cost_constraints(const std::vector &active_links, - const std::map &p_cost_columns){ - - std::vector dmatval; - std::vector colind; - std::vector rowtype; - std::vector rhs; - std::vector rstart; - - rstart.push_back(0); - - for (const ActiveLink& link : active_links) { - if (p_cost_columns.find(link.get_idLink()) != p_cost_columns.end()) { - for (const ColumnToChange& column : p_cost_columns.at(link.get_idLink())) { - add_direct_profile_column_constraint(dmatval, colind, rowtype, rhs, rstart, link, column); - } - } +void ProblemModifier::add_new_direct_cost_constraints( + const std::vector &active_links, + const std::map &p_cost_columns) { + std::vector dmatval; + std::vector colind; + std::vector rowtype; + std::vector rhs; + std::vector rstart; + + rstart.push_back(0); + + for (const ActiveLink &link : active_links) { + if (p_cost_columns.find(link.get_idLink()) != p_cost_columns.end()) { + for (const ColumnToChange &column : + p_cost_columns.at(link.get_idLink())) { + add_direct_profile_column_constraint(dmatval, colind, rowtype, rhs, + rstart, link, column); + } } + } - solver_addrows(_math_problem, rowtype, rhs, {}, rstart, colind, dmatval); - + solver_addrows(_math_problem, rowtype, rhs, {}, rstart, colind, dmatval); } +void ProblemModifier::add_new_indirect_cost_constraints( + const std::vector &active_links, + const std::map &p_cost_columns) { + std::vector dmatval; + std::vector colind; + std::vector rowtype; + std::vector rhs; + std::vector rstart; + + rstart.push_back(0); + + for (const auto &link : active_links) { + if (p_cost_columns.find(link.get_idLink()) != p_cost_columns.end()) { + for (const ColumnToChange &column : + p_cost_columns.at(link.get_idLink())) { + add_indirect_cost_column_constraint(dmatval, colind, rowtype, rhs, + rstart, link, column); + } + } + } -void ProblemModifier::add_new_indirect_cost_constraints(const std::vector &active_links, - const std::map &p_cost_columns){ - - std::vector dmatval; - std::vector colind; - std::vector rowtype; - std::vector rhs; - std::vector rstart; - - rstart.push_back(0); + solver_addrows(_math_problem, rowtype, rhs, {}, rstart, colind, dmatval); +} - for (const auto& link : active_links) { - if (p_cost_columns.find(link.get_idLink()) != p_cost_columns.end()) { - for (const ColumnToChange& column : p_cost_columns.at(link.get_idLink())) { - add_indirect_cost_column_constraint(dmatval, colind, rowtype, rhs, rstart, link, column); - } - } +void ProblemModifier::add_direct_profile_column_constraint( + std::vector &dmatval, std::vector &colind, + std::vector &rowtype, std::vector &rhs, + std::vector &rstart, const ActiveLink &link, + const ColumnToChange &column) { + double already_installed_capacity(link.get_already_installed_capacity()); + double direct_already_installed_profile_at_timestep = + link.already_installed_direct_profile(column.time_step); + rhs.push_back(already_installed_capacity * + direct_already_installed_profile_at_timestep); + + rowtype.push_back('L'); + colind.push_back(column.id); + dmatval.push_back(1); + for (const auto &candidate : link.getCandidates()) { + if (candidate.direct_profile(column.time_step) != 0.0) { + colind.push_back(_candidate_col_id[candidate.get_name()]); + dmatval.push_back(-candidate.direct_profile(column.time_step)); } + } + rstart.push_back((int)dmatval.size()); +} - solver_addrows(_math_problem, rowtype, rhs, {}, rstart, colind, dmatval); -} - -void ProblemModifier::add_direct_profile_column_constraint(std::vector &dmatval, std::vector &colind, - std::vector &rowtype, std::vector &rhs, - std::vector &rstart, const ActiveLink &link, - const ColumnToChange &column) { - double already_installed_capacity(link.get_already_installed_capacity()); - double direct_already_installed_profile_at_timestep = link.already_installed_direct_profile(column.time_step); - rhs.push_back(already_installed_capacity * direct_already_installed_profile_at_timestep); - - rowtype.push_back('L'); - colind.push_back(column.id); - dmatval.push_back(1); - for (const auto &candidate:link.getCandidates()) { - if (candidate.direct_profile(column.time_step) != 0.0) { - colind.push_back(_candidate_col_id[candidate.get_name()]); - dmatval.push_back(-candidate.direct_profile(column.time_step)); - } - } - rstart.push_back( (int) dmatval.size()); -} - -void ProblemModifier::add_indirect_profile_ntc_column_constraint(std::vector &dmatval, std::vector &colind, - std::vector &rowtype, std::vector &rhs, - std::vector &rstart, const ActiveLink &link, - const ColumnToChange &column) { - double already_installed_capacity(link.get_already_installed_capacity()); - double indirect_already_installed_profile_at_timestep = link.already_installed_indirect_profile(column.time_step); - rhs.push_back(-already_installed_capacity*indirect_already_installed_profile_at_timestep); - - rowtype.push_back('G'); - colind.push_back(column.id); - dmatval.push_back(1); - for (const auto &candidate:link.getCandidates()) { - if (candidate.indirect_profile(column.time_step) != 0.0) { - colind.push_back(_candidate_col_id[candidate.get_name()]); - dmatval.push_back(candidate.indirect_profile(column.time_step)); - } - } - rstart.push_back((int) dmatval.size()); -} - -void ProblemModifier::add_indirect_cost_column_constraint(std::vector &dmatval, std::vector &colind, - std::vector &rowtype, std::vector &rhs, - std::vector &rstart, const ActiveLink &link, - const ColumnToChange &column) { - double already_installed_capacity(link.get_already_installed_capacity()); - double indirect_already_installed_profile_at_timestep = link.already_installed_indirect_profile(column.time_step); - rhs.push_back(already_installed_capacity*indirect_already_installed_profile_at_timestep); - - rowtype.push_back('L'); - colind.push_back(column.id); - dmatval.push_back(1); - for (const auto &candidate:link.getCandidates()) { - if (candidate.indirect_profile(column.time_step) != 0.0) { - colind.push_back(_candidate_col_id[candidate.get_name()]); - dmatval.push_back(-candidate.indirect_profile(column.time_step)); - } - } - rstart.push_back((int) dmatval.size()); -} - -void ProblemModifier::add_new_columns(const std::vector &candidates) { - if(!candidates.empty()){ - unsigned int n_candidates = (int) candidates.size(); - std::vector objectives(n_candidates, 0); - std::vector lb(n_candidates, -1e20); - std::vector ub(n_candidates, 1e20); - std::vector coltypes(n_candidates, 'C'); - std::vector mstart(n_candidates, 0); - std::vector candidates_colnames; - - for (const auto& candidate : candidates) { - candidates_colnames.push_back(candidate.get_name()); - int new_index = (int)_candidate_col_id.size() + (int) _n_cols_at_start; - _candidate_col_id[candidate.get_name()] = new_index; - } - solver_addcols(_math_problem, objectives, mstart, {}, {}, lb, ub, coltypes, candidates_colnames); +void ProblemModifier::add_indirect_profile_ntc_column_constraint( + std::vector &dmatval, std::vector &colind, + std::vector &rowtype, std::vector &rhs, + std::vector &rstart, const ActiveLink &link, + const ColumnToChange &column) { + double already_installed_capacity(link.get_already_installed_capacity()); + double indirect_already_installed_profile_at_timestep = + link.already_installed_indirect_profile(column.time_step); + rhs.push_back(-already_installed_capacity * + indirect_already_installed_profile_at_timestep); + + rowtype.push_back('G'); + colind.push_back(column.id); + dmatval.push_back(1); + for (const auto &candidate : link.getCandidates()) { + if (candidate.indirect_profile(column.time_step) != 0.0) { + colind.push_back(_candidate_col_id[candidate.get_name()]); + dmatval.push_back(candidate.indirect_profile(column.time_step)); } + } + rstart.push_back((int)dmatval.size()); } -std::vector ProblemModifier::candidates_from_all_links(const std::vector &active_links) const { - std::vector all_candidates; - for (const auto& link : active_links){ - std::vector candidates = link.getCandidates(); - all_candidates.insert(all_candidates.end(),candidates.begin(), candidates.end()); - } - return all_candidates; -} -std::set ProblemModifier::extract_time_steps(const std::map &p_columns) const{ - std::set result; - for (const auto& columns : p_columns){ - for(const auto& column : columns.second){ - result.insert(column.time_step); - } +void ProblemModifier::add_indirect_cost_column_constraint( + std::vector &dmatval, std::vector &colind, + std::vector &rowtype, std::vector &rhs, + std::vector &rstart, const ActiveLink &link, + const ColumnToChange &column) { + double already_installed_capacity(link.get_already_installed_capacity()); + double indirect_already_installed_profile_at_timestep = + link.already_installed_indirect_profile(column.time_step); + rhs.push_back(already_installed_capacity * + indirect_already_installed_profile_at_timestep); + + rowtype.push_back('L'); + colind.push_back(column.id); + dmatval.push_back(1); + for (const auto &candidate : link.getCandidates()) { + if (candidate.indirect_profile(column.time_step) != 0.0) { + colind.push_back(_candidate_col_id[candidate.get_name()]); + dmatval.push_back(-candidate.indirect_profile(column.time_step)); } - return result; + } + rstart.push_back((int)dmatval.size()); } -std::vector ProblemModifier::candidates_with_not_null_profile(const std::vector &active_links, const std::set& time_steps) const{ - std::vector candidates = candidates_from_all_links(active_links); +void ProblemModifier::add_new_columns( + const std::vector &candidates) { + if (!candidates.empty()) { + unsigned int n_candidates = (int)candidates.size(); + std::vector objectives(n_candidates, 0); + std::vector lb(n_candidates, -1e20); + std::vector ub(n_candidates, 1e20); + std::vector coltypes(n_candidates, 'C'); + std::vector mstart(n_candidates, 0); + std::vector candidates_colnames; + + for (const auto &candidate : candidates) { + candidates_colnames.push_back(candidate.get_name()); + int new_index = (int)_candidate_col_id.size() + (int)_n_cols_at_start; + _candidate_col_id[candidate.get_name()] = new_index; + } + solver_addcols(_math_problem, objectives, mstart, {}, {}, lb, ub, coltypes, + candidates_colnames); + } +} - candidates.erase(std::remove_if(candidates.begin(), candidates.end(), [time_steps](const Candidate& cand) { - bool hasOnlyNullProfile = true; - for (int time_step : time_steps) { - hasOnlyNullProfile &= cand.direct_profile(time_step) == 0.0; - hasOnlyNullProfile &= cand.indirect_profile(time_step) == 0.0; - } - return hasOnlyNullProfile; - }), candidates.end()); +std::vector ProblemModifier::candidates_from_all_links( + const std::vector &active_links) const { + std::vector all_candidates; + for (const auto &link : active_links) { + std::vector candidates = link.getCandidates(); + all_candidates.insert(all_candidates.end(), candidates.begin(), + candidates.end()); + } + return all_candidates; +} +std::set ProblemModifier::extract_time_steps( + const std::map &p_columns) const { + std::set result; + for (const auto &columns : p_columns) { + for (const auto &column : columns.second) { + result.insert(column.time_step); + } + } + return result; +} - return candidates; +std::vector ProblemModifier::candidates_with_not_null_profile( + const std::vector &active_links, + const std::set &time_steps) const { + std::vector candidates = candidates_from_all_links(active_links); + + candidates.erase(std::remove_if(candidates.begin(), candidates.end(), + [time_steps](const Candidate &cand) { + bool hasOnlyNullProfile = true; + for (int time_step : time_steps) { + hasOnlyNullProfile &= + cand.direct_profile(time_step) == 0.0; + hasOnlyNullProfile &= + cand.indirect_profile(time_step) == + 0.0; + } + return hasOnlyNullProfile; + }), + candidates.end()); + + return candidates; } diff --git a/src/cpp/lpnamer/problem_modifier/ProblemModifier.h b/src/cpp/lpnamer/problem_modifier/ProblemModifier.h index f59611f5d..881059c5a 100644 --- a/src/cpp/lpnamer/problem_modifier/ProblemModifier.h +++ b/src/cpp/lpnamer/problem_modifier/ProblemModifier.h @@ -2,76 +2,90 @@ #ifndef ANTARESXPANSION_PROBLEMMODIFIER_H #define ANTARESXPANSION_PROBLEMMODIFIER_H -#include -#include -#include #include -#include "ActiveLinks.h" -#include "ColumnToChange.h" + #include +#include +#include +#include "ActiveLinks.h" +#include "ColumnToChange.h" class ProblemModifier { -public: - ProblemModifier(); - - std::shared_ptr changeProblem(std::shared_ptr mathProblem, const std::vector &active_links, - const std::map &p_ntc_columns, - const std::map &p_direct_cost_columns, - const std::map &p_indirect_cost_columns); - - unsigned int get_candidate_col_id(const std::string& cand_name) const; - bool has_candidate_col_id(const std::string& cand_name) const; - -private: - - void changeProblem(const std::vector &active_links, - const std::map &p_ntc_columns, - const std::map &p_direct_cost_columns, - const std::map &p_indirect_cost_columns); - - void remove_bounds_for(const std::vector &col_ids) const; - - void change_upper_bounds_to_pos_inf(const std::vector &col_id) const; - - void change_lower_bounds_to_neg_inf(const std::vector &col_id) const; - - void add_new_columns(const std::vector &candidates); - - std::vector candidates_from_all_links(const std::vector &active_links) const; - std::set extract_time_steps(const std::map &p_columns) const; - std::vector candidates_with_not_null_profile(const std::vector &active_links, const std::set& time_steps) const; - - void add_new_ntc_constraints(const std::vector &active_links, - const std::map &p_ntc_columns); - - void add_new_direct_cost_constraints(const std::vector &active_links, - const std::map &p_cost_columns); - - void add_new_indirect_cost_constraints(const std::vector &active_links, - const std::map &p_cost_columns); - - std::shared_ptr _math_problem; - std::map _candidate_col_id; - unsigned int _n_cols_at_start; - - void - add_direct_profile_column_constraint(std::vector &dmatval, std::vector &colind, - std::vector &rowtype, - std::vector &rhs, std::vector &rstart, const ActiveLink &link, - const ColumnToChange &column); - - void - add_indirect_profile_ntc_column_constraint(std::vector &dmatval, std::vector &colind, - std::vector &rowtype, - std::vector &rhs, std::vector &rstart, const ActiveLink &link, - const ColumnToChange &column); - void - add_indirect_cost_column_constraint(std::vector &dmatval, std::vector &colind, - std::vector &rowtype, - std::vector &rhs, std::vector &rstart, const ActiveLink &link, - const ColumnToChange &column); + public: + ProblemModifier(); + + std::shared_ptr changeProblem( + std::shared_ptr mathProblem, + const std::vector &active_links, + const std::map &p_ntc_columns, + const std::map &p_direct_cost_columns, + const std::map &p_indirect_cost_columns); + + unsigned int get_candidate_col_id(const std::string &cand_name) const; + bool has_candidate_col_id(const std::string &cand_name) const; + + private: + void changeProblem( + const std::vector &active_links, + const std::map &p_ntc_columns, + const std::map &p_direct_cost_columns, + const std::map &p_indirect_cost_columns); + + void remove_bounds_for(const std::vector &col_ids) const; + + void change_upper_bounds_to_pos_inf(const std::vector &col_id) const; + + void change_lower_bounds_to_neg_inf(const std::vector &col_id) const; + + void add_new_columns(const std::vector &candidates); + + std::vector candidates_from_all_links( + const std::vector &active_links) const; + std::set extract_time_steps( + const std::map &p_columns) const; + std::vector candidates_with_not_null_profile( + const std::vector &active_links, + const std::set &time_steps) const; + + void add_new_ntc_constraints( + const std::vector &active_links, + const std::map &p_ntc_columns); + + void add_new_direct_cost_constraints( + const std::vector &active_links, + const std::map &p_cost_columns); + + void add_new_indirect_cost_constraints( + const std::vector &active_links, + const std::map &p_cost_columns); + + std::shared_ptr _math_problem; + std::map _candidate_col_id; + unsigned int _n_cols_at_start; + + void add_direct_profile_column_constraint(std::vector &dmatval, + std::vector &colind, + std::vector &rowtype, + std::vector &rhs, + std::vector &rstart, + const ActiveLink &link, + const ColumnToChange &column); + + void add_indirect_profile_ntc_column_constraint(std::vector &dmatval, + std::vector &colind, + std::vector &rowtype, + std::vector &rhs, + std::vector &rstart, + const ActiveLink &link, + const ColumnToChange &column); + void add_indirect_cost_column_constraint(std::vector &dmatval, + std::vector &colind, + std::vector &rowtype, + std::vector &rhs, + std::vector &rstart, + const ActiveLink &link, + const ColumnToChange &column); }; - -#endif //ANTARESXPANSION_PROBLEMMODIFIER_H +#endif // ANTARESXPANSION_PROBLEMMODIFIER_H diff --git a/src/cpp/lpnamer/problem_modifier/StudyUpdater.cpp b/src/cpp/lpnamer/problem_modifier/StudyUpdater.cpp index a7fc59796..6952d1591 100644 --- a/src/cpp/lpnamer/problem_modifier/StudyUpdater.cpp +++ b/src/cpp/lpnamer/problem_modifier/StudyUpdater.cpp @@ -1,151 +1,147 @@ #include "StudyUpdater.h" -#include "common_lpnamer.h" #include "JsonXpansionReader.h" +#include "common_lpnamer.h" #include "helpers/Path.h" +std::string StudyUpdater::linksSubfolder_ = + static_cast(Path("") / "input" / "links"); -std::string StudyUpdater::linksSubfolder_ = static_cast( Path("") / "input" / "links"); - - -StudyUpdater::StudyUpdater(std::string const & studyPath_p): -studyPath_(studyPath_p) -{ - linksPath_ = studyPath_ + linksSubfolder_; - readAntaresVersion(); +StudyUpdater::StudyUpdater(std::string const& studyPath_p) + : studyPath_(studyPath_p) { + linksPath_ = studyPath_ + linksSubfolder_; + readAntaresVersion(); } -int StudyUpdater::getAntaresVersion() const -{ - return antaresVersion_; -} +int StudyUpdater::getAntaresVersion() const { return antaresVersion_; } + +void StudyUpdater::readAntaresVersion() { + std::ifstream studyFile_l( + static_cast(Path(studyPath_) / STUDY_FILE)); + std::string line_l; + const std::string versionProperty_l("version = "); -void StudyUpdater::readAntaresVersion() -{ - std::ifstream studyFile_l (static_cast (Path(studyPath_) / STUDY_FILE) ); - std::string line_l; - const std::string versionProperty_l("version = "); - - while( std::getline(studyFile_l, line_l) ) - { - size_t pos_l = line_l.find(versionProperty_l); - if( pos_l != std::string::npos) - { - std::stringstream buffer(line_l.substr(pos_l+versionProperty_l.size())); - buffer >> antaresVersion_; - return; - } + while (std::getline(studyFile_l, line_l)) { + size_t pos_l = line_l.find(versionProperty_l); + if (pos_l != std::string::npos) { + std::stringstream buffer(line_l.substr(pos_l + versionProperty_l.size())); + buffer >> antaresVersion_; + return; } + } - //default - std::cout << "StudyUpdater::readAntaresVersion : default version 710 returned.\n"; - antaresVersion_ = 710; + // default + std::cout + << "StudyUpdater::readAntaresVersion : default version 710 returned.\n"; + antaresVersion_ = 710; } -std::string StudyUpdater::getLinkdataFilepath(ActiveLink const& link_p) const -{ - auto linkDataFilePath = static_cast( Path(linksPath_) / link_p.get_linkor() / (link_p.get_linkex() + ".txt") ); - return linkDataFilePath; +std::string StudyUpdater::getLinkdataFilepath(ActiveLink const& link_p) const { + auto linkDataFilePath = static_cast( + Path(linksPath_) / link_p.get_linkor() / (link_p.get_linkex() + ".txt")); + return linkDataFilePath; } - -std::pair StudyUpdater::computeNewCapacities(const std::map& investments_p, const ActiveLink& link_p, int timepoint_p) const -{ - double direct_l = link_p.get_already_installed_capacity() * link_p.already_installed_direct_profile(timepoint_p); - double indirect_l = link_p.get_already_installed_capacity() * link_p.already_installed_direct_profile(timepoint_p); - - const auto& candidates = link_p.getCandidates(); - for (const auto& candidate : candidates) - { - const auto& it_candidate = investments_p.find(candidate.get_name()); - if (it_candidate == investments_p.end()) - { - std::string message = "No investment computed for the candidate " + candidate.get_name() + " on the link "+ link_p.get_LinkName(); - throw std::runtime_error(message); - } - double candidate_investment = it_candidate->second; - - direct_l += candidate_investment * candidate.direct_profile(timepoint_p); - indirect_l += candidate_investment * candidate.indirect_profile(timepoint_p); +std::pair StudyUpdater::computeNewCapacities( + const std::map& investments_p, + const ActiveLink& link_p, int timepoint_p) const { + double direct_l = link_p.get_already_installed_capacity() * + link_p.already_installed_direct_profile(timepoint_p); + double indirect_l = link_p.get_already_installed_capacity() * + link_p.already_installed_direct_profile(timepoint_p); + + const auto& candidates = link_p.getCandidates(); + for (const auto& candidate : candidates) { + const auto& it_candidate = investments_p.find(candidate.get_name()); + if (it_candidate == investments_p.end()) { + std::string message = "No investment computed for the candidate " + + candidate.get_name() + " on the link " + + link_p.get_LinkName(); + throw std::runtime_error(message); } - return std::make_pair(direct_l, indirect_l); -} + double candidate_investment = it_candidate->second; -int StudyUpdater::updateLinkdataFile(const ActiveLink& link_p, const std::map& investments_p) const -{ - std::string linkdataFilename_l = getLinkdataFilepath(link_p); - - std::ifstream inputCsv_l(linkdataFilename_l); - std::ofstream tempOutCsvFile(linkdataFilename_l + ".tmp"); - - if (!tempOutCsvFile.is_open()) - { - std::cout << "ERROR: Error writing " + linkdataFilename_l + "." << std::endl; - return 1; - } + direct_l += candidate_investment * candidate.direct_profile(timepoint_p); + indirect_l += + candidate_investment * candidate.indirect_profile(timepoint_p); + } + return std::make_pair(direct_l, indirect_l); +} - bool warned_l = false; - if (!inputCsv_l.is_open()) - { - std::cout << "WARNING: Missing file to update antares study : " << linkdataFilename_l << "." - << " Unknown valus were populated with 0 in a new created file." << std::endl; +int StudyUpdater::updateLinkdataFile( + const ActiveLink& link_p, + const std::map& investments_p) const { + std::string linkdataFilename_l = getLinkdataFilepath(link_p); + + std::ifstream inputCsv_l(linkdataFilename_l); + std::ofstream tempOutCsvFile(linkdataFilename_l + ".tmp"); + + if (!tempOutCsvFile.is_open()) { + std::cout << "ERROR: Error writing " + linkdataFilename_l + "." + << std::endl; + return 1; + } + + bool warned_l = false; + if (!inputCsv_l.is_open()) { + std::cout << "WARNING: Missing file to update antares study : " + << linkdataFilename_l << "." + << " Unknown valus were populated with 0 in a new created file." + << std::endl; + warned_l = true; + } + + bool isModernVersion_l = (antaresVersion_ >= 700); + LinkdataRecord record_l(isModernVersion_l); // csv file fields + + std::string line_l; + for (int line_cnt = 0; line_cnt < 8760; ++line_cnt) { + if (std::getline(inputCsv_l, line_l)) { + record_l.fillFromRow(line_l); + } else { + record_l.reset(); + if (!warned_l) { + std::cout << "WARNING: Missing entries in : " + linkdataFilename_l + + ". Missing valus were populated with 0." + << std::endl; warned_l = true; + } } + std::pair newCapacities_l = + computeNewCapacities(investments_p, link_p, line_cnt); + record_l.updateCapacities(newCapacities_l.first, newCapacities_l.second); + tempOutCsvFile << record_l.to_row("\t") << "\n"; + } - bool isModernVersion_l = (antaresVersion_ >= 700); - LinkdataRecord record_l(isModernVersion_l); //csv file fields - - std::string line_l; - for (int line_cnt = 0; line_cnt < 8760; ++line_cnt) - { - if (std::getline(inputCsv_l, line_l)) - { - record_l.fillFromRow(line_l); - } - else - { - record_l.reset(); - if (!warned_l) - { - std::cout << "WARNING: Missing entries in : " + linkdataFilename_l + ". Missing valus were populated with 0." << std::endl; - warned_l = true; - } - } - std::pair newCapacities_l = computeNewCapacities(investments_p, link_p, line_cnt); - record_l.updateCapacities(newCapacities_l.first, newCapacities_l.second); - tempOutCsvFile << record_l.to_row("\t") << "\n"; - } - - inputCsv_l.close(); - tempOutCsvFile.close(); + inputCsv_l.close(); + tempOutCsvFile.close(); - //delete old file and rename the temporarily created file - std::remove(linkdataFilename_l.c_str()); - std::rename((linkdataFilename_l + ".tmp").c_str(), linkdataFilename_l.c_str()); + // delete old file and rename the temporarily created file + std::remove(linkdataFilename_l.c_str()); + std::rename((linkdataFilename_l + ".tmp").c_str(), + linkdataFilename_l.c_str()); - return 0; + return 0; } +int StudyUpdater::update(std::vector const& links_p, + std::string const& jsonPath_p) const { + JsonXpansionReader jsonReader_l; + jsonReader_l.read(jsonPath_p); -int StudyUpdater::update(std::vector const& links_p, std::string const& jsonPath_p) const -{ - JsonXpansionReader jsonReader_l; - jsonReader_l.read(jsonPath_p); + std::map solution_l = jsonReader_l.getSolutionPoint(); - std::map solution_l = jsonReader_l.getSolutionPoint(); - - return update(links_p, solution_l); + return update(links_p, solution_l); } +int StudyUpdater::update( + std::vector const& links_p, + const std::map& investments_p) const { + int updateFailures_l(0); -int StudyUpdater::update(std::vector const& links_p, const std::map& investments_p) const -{ - int updateFailures_l(0); - - for (const auto& link : links_p) - { - updateFailures_l += updateLinkdataFile(link, investments_p); - } + for (const auto& link : links_p) { + updateFailures_l += updateLinkdataFile(link, investments_p); + } - return updateFailures_l; + return updateFailures_l; } \ No newline at end of file diff --git a/src/cpp/lpnamer/problem_modifier/StudyUpdater.h b/src/cpp/lpnamer/problem_modifier/StudyUpdater.h index 8fdb0b3d6..982e4a081 100644 --- a/src/cpp/lpnamer/problem_modifier/StudyUpdater.h +++ b/src/cpp/lpnamer/problem_modifier/StudyUpdater.h @@ -1,182 +1,189 @@ #pragma once -#include "LinkProblemsGenerator.h" #include "ActiveLinks.h" - - -/*! -* \class StudyUpdater -* \brief Class that updates an antares study after an antares-xpansion execution -*/ -class StudyUpdater -{ -private: - // folder containing the links files in the antares study - static std::string linksSubfolder_; - // path to the antares study - std::string studyPath_; - // path to the links folder - std::string linksPath_; - // antares version - int antaresVersion_; - -public: - -/*! - * \brief constructor of class StudyUpdater - * - * \param studyPath_p : path to the antares study folder - */ - explicit StudyUpdater(std::string const & studyPath_p); - -/*! - * \brief default destructor of calass StudyUpdater - */ - virtual ~StudyUpdater() = default; - -/*! - * \brief getter for attribute StudyUpdater::antaresVersion_ - */ - int getAntaresVersion() const; - -/*! - * \brief reads the antares version from the "study.antares" file and set StudyUpdater::antaresVersion_ - */ - void readAntaresVersion(); - -/*! - * \brief returns the path to the linkdata file related to a link - * - * \param link_p : link for which the datalink file path will be returned - */ - - std::string getLinkdataFilepath(ActiveLink const& link_p) const; - - - /*! - * \brief computes the new capacities of related to a link - * - * \param investment_p : investment to consider for the candidates of the link - * \param link_p : link for which the capacities will be computed - * \param timepoint_p : timepoint where the capcities will be computed - * - * \return a pair of the computed direct and indirect capacities - */ - std::pair computeNewCapacities(const std::map& investments_p, const ActiveLink& link_p, int timepoint_p) const; - -/*! - * \brief updates the linkdata file for a given link according to the investments of its candidates - * - * \param link_p : link for which the linkdata file will be updated - * \param investment_p : value of investment to consider for the update - * - * \return 1 if the update fails, 0 otherwise - */ - - int updateLinkdataFile(const ActiveLink& link_p, const std::map& investments_p) const; - -/*! - * \brief updates the linkdata files for multiple candidates from a solution Point - * - * \param candidates_p : the candidates for which the linkdata file will be updated - * \param investments_p : a map giving investments per candidate - * - * \return number of candidates we failed to update - */ - int update(std::vector const& links_p, const std::map& investments_p) const; +#include "LinkProblemsGenerator.h" /*! - * \brief updates the linkdata files for multiple candidates from a json file - * - * \param candidates_p : the candidates for which the linkdata file will be updated - * \param jsonPath_p : path to a json file to read the investment solution from - * - * \return number of candidates we failed to update + * \class StudyUpdater + * \brief Class that updates an antares study after an antares-xpansion + * execution */ - int update(std::vector const& links_p, std::string const& jsonPath_p) const; +class StudyUpdater { + private: + // folder containing the links files in the antares study + static std::string linksSubfolder_; + // path to the antares study + std::string studyPath_; + // path to the links folder + std::string linksPath_; + // antares version + int antaresVersion_; + + public: + /*! + * \brief constructor of class StudyUpdater + * + * \param studyPath_p : path to the antares study folder + */ + explicit StudyUpdater(std::string const& studyPath_p); + + /*! + * \brief default destructor of calass StudyUpdater + */ + virtual ~StudyUpdater() = default; + + /*! + * \brief getter for attribute StudyUpdater::antaresVersion_ + */ + int getAntaresVersion() const; + + /*! + * \brief reads the antares version from the "study.antares" file and set + * StudyUpdater::antaresVersion_ + */ + void readAntaresVersion(); + + /*! + * \brief returns the path to the linkdata file related to a link + * + * \param link_p : link for which the datalink file path will be returned + */ + + std::string getLinkdataFilepath(ActiveLink const& link_p) const; + + /*! + * \brief computes the new capacities of related to a link + * + * \param investment_p : investment to consider for the candidates of the link + * \param link_p : link for which the capacities will be computed + * \param timepoint_p : timepoint where the capcities will be computed + * + * \return a pair of the computed direct and indirect capacities + */ + std::pair computeNewCapacities( + const std::map& investments_p, + const ActiveLink& link_p, int timepoint_p) const; + + /*! + * \brief updates the linkdata file for a given link according to the + * investments of its candidates + * + * \param link_p : link for which the linkdata file will be updated + * \param investment_p : value of investment to consider for the update + * + * \return 1 if the update fails, 0 otherwise + */ + + int updateLinkdataFile( + const ActiveLink& link_p, + const std::map& investments_p) const; + + /*! + * \brief updates the linkdata files for multiple candidates from a solution + * Point + * + * \param candidates_p : the candidates for which the linkdata file will be + * updated \param investments_p : a map giving investments per candidate + * + * \return number of candidates we failed to update + */ + int update(std::vector const& links_p, + const std::map& investments_p) const; + + /*! + * \brief updates the linkdata files for multiple candidates from a json file + * + * \param candidates_p : the candidates for which the linkdata file will be + * updated \param jsonPath_p : path to a json file to read the investment + * solution from + * + * \return number of candidates we failed to update + */ + int update(std::vector const& links_p, + std::string const& jsonPath_p) const; }; /*! -* \struct LinkdataRecord -* \brief struct describing a line in a linkdata file of antares -*/ -struct LinkdataRecord -{ - //! should be set to true if antares version is 700 or more recent - const bool modernAntaresVersion_; - struct FileColumns - { - double directCapacity_; - //! 2nd column of the file : indirect capacity of the link - double indirectCapacity_; - //! 3rd column of the file : direct hurdles cost - double directHurdlesCost_; - //! 4th column of the file : indirect hurdles cost - double indirectHurdlesCost_; - //! 5th column of the file : impedances - double impedances_; - //! 6th column of the file : loop flow - double loopFlow_; - //! 7th column of the file : power shift min. - double pShiftMin_; - //! 8th column of the file : power shift max. - double pShiftMax_ ; - }; - - FileColumns fileColumns; -/*! - * \brief LinkdataRecord constructor - * - * \param modernAntaresVersion_p : value to set to modernAntaresVersion_p - */ - explicit LinkdataRecord(bool modernAntaresVersion_p); - - - -/*! - * \brief LinkdataRecord constructor to use with modern antares studies versions - * - * \param fileColumns : LinkdataRecord::FileColumns object that hold columns infos of the file - */ - explicit LinkdataRecord(const FileColumns& afileColumns); - - -/*! - * \brief LinkdataRecord constructor to use with old antares studies versions - * - * \param directCapacity_p : value to set to fileColumns.directCapacity_ - * \param indirectCapacity_p : value to set to fileColumns.indirectCapacity_ - * \param directHurdlesCost_p : value to set to fileColumns.directHurdlesCost_ - * \param indirectHurdlesCost_p : value to set to fileColumns.indirectHurdlesCost_ - * \param impedances_p : value to set to fileColumns.impedances_ - */ - LinkdataRecord(double directCapacity_p, double indirectCapacity_p, - double directHurdlesCost_p, double indirectHurdlesCost_p, double impedances_p); - -/*! - * \brief returns a one-line string describing the LinkdataRecord - * - * \param sep_p : delimiter used to separate record's attributes in the created line string - */ - std::string to_row(std::string const & sep_p) const; - -/*! - * \brief update the capacities of the LinkdataRecord - * - * \param directCapacity_p : value to set to fileColumns.directCapacity_ - * \param indirectCapacity_p : value to set to fileColumns.indirectCapacity_ - */ - void updateCapacities(double directCapacity_p, double indirectCapacity_p); - -/*! - * \brief populates the LinkdataRecord attributes for a string - * - * \param line_p : string describing the record - */ - void fillFromRow(std::string const & line_p); - -/*! - * \brief reset the LinkdataRecord attributes to 0 + * \struct LinkdataRecord + * \brief struct describing a line in a linkdata file of antares */ - void reset(); +struct LinkdataRecord { + //! should be set to true if antares version is 700 or more recent + const bool modernAntaresVersion_; + struct FileColumns { + double directCapacity_; + //! 2nd column of the file : indirect capacity of the link + double indirectCapacity_; + //! 3rd column of the file : direct hurdles cost + double directHurdlesCost_; + //! 4th column of the file : indirect hurdles cost + double indirectHurdlesCost_; + //! 5th column of the file : impedances + double impedances_; + //! 6th column of the file : loop flow + double loopFlow_; + //! 7th column of the file : power shift min. + double pShiftMin_; + //! 8th column of the file : power shift max. + double pShiftMax_; + }; + + FileColumns fileColumns; + /*! + * \brief LinkdataRecord constructor + * + * \param modernAntaresVersion_p : value to set to modernAntaresVersion_p + */ + explicit LinkdataRecord(bool modernAntaresVersion_p); + + /*! + * \brief LinkdataRecord constructor to use with modern antares studies + * versions + * + * \param fileColumns : LinkdataRecord::FileColumns object that hold columns + * infos of the file + */ + explicit LinkdataRecord(const FileColumns& afileColumns); + + /*! + * \brief LinkdataRecord constructor to use with old antares studies versions + * + * \param directCapacity_p : value to set to fileColumns.directCapacity_ + * \param indirectCapacity_p : value to set to fileColumns.indirectCapacity_ + * \param directHurdlesCost_p : value to set to fileColumns.directHurdlesCost_ + * \param indirectHurdlesCost_p : value to set to + * fileColumns.indirectHurdlesCost_ \param impedances_p : value to set to + * fileColumns.impedances_ + */ + LinkdataRecord(double directCapacity_p, double indirectCapacity_p, + double directHurdlesCost_p, double indirectHurdlesCost_p, + double impedances_p); + + /*! + * \brief returns a one-line string describing the LinkdataRecord + * + * \param sep_p : delimiter used to separate record's attributes in the + * created line string + */ + std::string to_row(std::string const& sep_p) const; + + /*! + * \brief update the capacities of the LinkdataRecord + * + * \param directCapacity_p : value to set to fileColumns.directCapacity_ + * \param indirectCapacity_p : value to set to fileColumns.indirectCapacity_ + */ + void updateCapacities(double directCapacity_p, double indirectCapacity_p); + + /*! + * \brief populates the LinkdataRecord attributes for a string + * + * \param line_p : string describing the record + */ + void fillFromRow(std::string const& line_p); + + /*! + * \brief reset the LinkdataRecord attributes to 0 + */ + void reset(); }; diff --git a/src/cpp/multisolver_interface/COIN_common_functions.cpp b/src/cpp/multisolver_interface/COIN_common_functions.cpp index 22f96db4f..66c07c4f5 100644 --- a/src/cpp/multisolver_interface/COIN_common_functions.cpp +++ b/src/cpp/multisolver_interface/COIN_common_functions.cpp @@ -1,126 +1,101 @@ #include "COIN_common_functions.h" -#include "multisolver_interface/SolverAbstract.h" -#include "CoinFinite.hpp" -#include -namespace coin_common -{ - void fill_rows_from_COIN_matrix(const CoinPackedMatrix &matrix, int *mstart, int *mclind, double *dmatval, int *nels, - int first, int last) - { +#include - const int *column = matrix.getIndices(); - const CoinBigIndex *rowStart = matrix.getVectorStarts(); - const double *vals = matrix.getElements(); +#include "CoinFinite.hpp" +#include "multisolver_interface/SolverAbstract.h" +namespace coin_common { - int firstIndexToReturn = rowStart[first]; - int lastIndexToReturn = rowStart[last + 1] - 1; - int nelemsToReturn = lastIndexToReturn - firstIndexToReturn + 1; - // Need to take into account the offset of rowstart as _clp.matrix - // returnes the entire matrix - for (int i = first; i < last + 2; i++) - { - mstart[i - first] = rowStart[i] - rowStart[first]; - } +void fill_rows_from_COIN_matrix(const CoinPackedMatrix &matrix, int *mstart, + int *mclind, double *dmatval, int *nels, + int first, int last) { + const int *column = matrix.getIndices(); + const CoinBigIndex *rowStart = matrix.getVectorStarts(); + const double *vals = matrix.getElements(); - for (int i = firstIndexToReturn; i < lastIndexToReturn + 1; i++) - { - mclind[i - firstIndexToReturn] = column[i]; - dmatval[i - firstIndexToReturn] = vals[i]; - } - *nels = nelemsToReturn; - } + int firstIndexToReturn = rowStart[first]; + int lastIndexToReturn = rowStart[last + 1] - 1; + int nelemsToReturn = lastIndexToReturn - firstIndexToReturn + 1; + // Need to take into account the offset of rowstart as _clp.matrix + // returnes the entire matrix + for (int i = first; i < last + 2; i++) { + mstart[i - first] = rowStart[i] - rowStart[first]; + } - void fill_row_type_from_row_bounds(const double *rowLower, const double *rowUpper, char *qrtype, int first, int last) - { - for (int i = first; i < last + 1; i++) - { + for (int i = firstIndexToReturn; i < lastIndexToReturn + 1; i++) { + mclind[i - firstIndexToReturn] = column[i]; + dmatval[i - firstIndexToReturn] = vals[i]; + } + *nels = nelemsToReturn; +} - if (rowLower[i] == rowUpper[i]) - { - qrtype[i - first] = 'E'; - } - else if (rowLower[i] > -COIN_DBL_MAX) - { - if (rowUpper[i] < COIN_DBL_MAX) - { - std::string error = "ERROR : Row " + std::to_string(i) + " has two different RHS, both right and left."; - throw GenericSolverException(error); - } - else - { - qrtype[i - first] = 'G'; - } - } - else if (rowUpper[i] < COIN_DBL_MAX) - { - qrtype[i - first] = 'L'; - } - else - { - std::string error = "ERROR : Row " + std::to_string(i) + " in unconstrained. No RHS found."; - throw GenericSolverException(error); - } - } +void fill_row_type_from_row_bounds(const double *rowLower, + const double *rowUpper, char *qrtype, + int first, int last) { + for (int i = first; i < last + 1; i++) { + if (rowLower[i] == rowUpper[i]) { + qrtype[i - first] = 'E'; + } else if (rowLower[i] > -COIN_DBL_MAX) { + if (rowUpper[i] < COIN_DBL_MAX) { + std::string error = "ERROR : Row " + std::to_string(i) + + " has two different RHS, both right and left."; + throw GenericSolverException(error); + } else { + qrtype[i - first] = 'G'; + } + } else if (rowUpper[i] < COIN_DBL_MAX) { + qrtype[i - first] = 'L'; + } else { + std::string error = "ERROR : Row " + std::to_string(i) + + " in unconstrained. No RHS found."; + throw GenericSolverException(error); } + } +} - void fill_rhs_from_bounds(const double *rowLower, const double *rowUpper, double *rhs, int first, int last) - { - for (int i = first; i < last + 1; i++) - { - if (rowLower[i] == rowUpper[i]) - { - rhs[i - first] = rowLower[i]; - } - else if (rowLower[i] > -COIN_DBL_MAX) - { - if (rowUpper[i] < COIN_DBL_MAX) - { - std::string error = "ERROR : Row " + std::to_string(i) + " has two different RHS, both right and left."; - throw GenericSolverException(error); - } - else - { - rhs[i - first] = rowLower[i]; - } - } - else if (rowUpper[i] < COIN_DBL_MAX) - { - rhs[i - first] = rowUpper[i]; - } - else - { - std::string error = "ERROR : Row " + std::to_string(i) + " in unconstrained. No RHS found."; - throw GenericSolverException(error); - } - } +void fill_rhs_from_bounds(const double *rowLower, const double *rowUpper, + double *rhs, int first, int last) { + for (int i = first; i < last + 1; i++) { + if (rowLower[i] == rowUpper[i]) { + rhs[i - first] = rowLower[i]; + } else if (rowLower[i] > -COIN_DBL_MAX) { + if (rowUpper[i] < COIN_DBL_MAX) { + std::string error = "ERROR : Row " + std::to_string(i) + + " has two different RHS, both right and left."; + throw GenericSolverException(error); + } else { + rhs[i - first] = rowLower[i]; + } + } else if (rowUpper[i] < COIN_DBL_MAX) { + rhs[i - first] = rowUpper[i]; + } else { + std::string error = "ERROR : Row " + std::to_string(i) + + " in unconstrained. No RHS found."; + throw GenericSolverException(error); } - void fill_row_bounds_from_new_rows_data(std::vector &rowLower, std::vector &rowUpper, int newrows, const char *qrtype, const double *rhs) - { - for (int i(0); i < newrows; i++) - { - if (qrtype[i] == 'L') - { - rowUpper[i] = rhs[i]; - rowLower[i] = -COIN_DBL_MAX; - } - else if (qrtype[i] == 'G') - { - rowUpper[i] = COIN_DBL_MAX; - rowLower[i] = rhs[i]; - } - else if (qrtype[i] == 'E') - { - rowUpper[i] = rhs[i]; - rowLower[i] = rhs[i]; - } - else - { - std::stringstream buffer; - buffer << "ERROR : add rows, qrtype " << qrtype[i] << " of row " << i << " to add unknown."; - throw GenericSolverException(buffer.str()); - } - } + } +} +void fill_row_bounds_from_new_rows_data(std::vector &rowLower, + std::vector &rowUpper, + int newrows, const char *qrtype, + const double *rhs) { + for (int i(0); i < newrows; i++) { + if (qrtype[i] == 'L') { + rowUpper[i] = rhs[i]; + rowLower[i] = -COIN_DBL_MAX; + } else if (qrtype[i] == 'G') { + rowUpper[i] = COIN_DBL_MAX; + rowLower[i] = rhs[i]; + } else if (qrtype[i] == 'E') { + rowUpper[i] = rhs[i]; + rowLower[i] = rhs[i]; + } else { + std::stringstream buffer; + buffer << "ERROR : add rows, qrtype " << qrtype[i] << " of row " << i + << " to add unknown."; + throw GenericSolverException(buffer.str()); } -} // namespace coin_common + } +} +} // namespace coin_common diff --git a/src/cpp/multisolver_interface/COIN_common_functions.h b/src/cpp/multisolver_interface/COIN_common_functions.h index d9a5efd9c..a2a22610e 100644 --- a/src/cpp/multisolver_interface/COIN_common_functions.h +++ b/src/cpp/multisolver_interface/COIN_common_functions.h @@ -1,17 +1,24 @@ #ifndef COIN_COMMON_FUNCTIONS_H #define COIN_COMMON_FUNCTIONS_H -#include "CoinPackedMatrix.hpp" #include -namespace coin_common -{ - void fill_rows_from_COIN_matrix(const CoinPackedMatrix &matrix, int *mstart, int *mclind, double *dmatval, int *nels, - int first, int last); +#include "CoinPackedMatrix.hpp" +namespace coin_common { + +void fill_rows_from_COIN_matrix(const CoinPackedMatrix &matrix, int *mstart, + int *mclind, double *dmatval, int *nels, + int first, int last); - void fill_row_type_from_row_bounds(const double *rowLower, const double *rowUpper, char *qrtype, int first, int last); +void fill_row_type_from_row_bounds(const double *rowLower, + const double *rowUpper, char *qrtype, + int first, int last); - void fill_rhs_from_bounds(const double *rowLower, const double *rowUpper, double *rhs, int first, int last); - void fill_row_bounds_from_new_rows_data(std::vector &rowLower, std::vector &rowUpper, int newrows, const char *qrtype, const double *rhs); -} // namespace coin_common +void fill_rhs_from_bounds(const double *rowLower, const double *rowUpper, + double *rhs, int first, int last); +void fill_row_bounds_from_new_rows_data(std::vector &rowLower, + std::vector &rowUpper, + int newrows, const char *qrtype, + const double *rhs); +} // namespace coin_common -#endif // COIN_COMMON_FUNCTIONS_H +#endif // COIN_COMMON_FUNCTIONS_H diff --git a/src/cpp/multisolver_interface/SolverCbc.cpp b/src/cpp/multisolver_interface/SolverCbc.cpp index f62687025..a06cd60bd 100644 --- a/src/cpp/multisolver_interface/SolverCbc.cpp +++ b/src/cpp/multisolver_interface/SolverCbc.cpp @@ -1,722 +1,596 @@ #include "SolverCbc.h" + #include "COIN_common_functions.h" /************************************************************************************************* ------------------------------------ Constructor/Desctructor -------------------------------- +----------------------------------- Constructor/Desctructor +-------------------------------- *************************************************************************************************/ int SolverCbc::_NumberOfProblems = 0; -SolverCbc::SolverCbc() -{ - int status = 0; +SolverCbc::SolverCbc() { + int status = 0; - _NumberOfProblems += 1; - _current_log_level = 0; + _NumberOfProblems += 1; + _current_log_level = 0; } -SolverCbc::SolverCbc(const SolverAbstract::Ptr fictif) : SolverCbc() -{ - // Try to cast the solver in fictif to a SolverCPLEX - if (SolverCbc *c = dynamic_cast(fictif.get())) - { - _clp_inner_solver = OsiClpSolverInterface(c->_clp_inner_solver); - defineCbcModelFromInnerSolver(); - } - else - { - _NumberOfProblems -= 1; - throw InvalidSolverForCopyException(fictif->get_solver_name(), get_solver_name()); - } +SolverCbc::SolverCbc(const SolverAbstract::Ptr fictif) : SolverCbc() { + // Try to cast the solver in fictif to a SolverCPLEX + if (SolverCbc *c = dynamic_cast(fictif.get())) { + _clp_inner_solver = OsiClpSolverInterface(c->_clp_inner_solver); + defineCbcModelFromInnerSolver(); + } else { + _NumberOfProblems -= 1; + throw InvalidSolverForCopyException(fictif->get_solver_name(), + get_solver_name()); + } } -SolverCbc::~SolverCbc() -{ - _NumberOfProblems -= 1; - free(); +SolverCbc::~SolverCbc() { + _NumberOfProblems -= 1; + free(); } -int SolverCbc::get_number_of_instances() -{ - return _NumberOfProblems; -} +int SolverCbc::get_number_of_instances() { return _NumberOfProblems; } -void SolverCbc::defineCbcModelFromInnerSolver() -{ - // Affectation of new Clp interface to Cbc - // As CbcModel _cbc is modified, need to set log level to 0 again - _cbc = CbcModel(_clp_inner_solver); - set_output_log_level(_current_log_level); +void SolverCbc::defineCbcModelFromInnerSolver() { + // Affectation of new Clp interface to Cbc + // As CbcModel _cbc is modified, need to set log level to 0 again + _cbc = CbcModel(_clp_inner_solver); + set_output_log_level(_current_log_level); } /************************************************************************************************* ------------------------------------ Output stream management ------------------------------ +----------------------------------- Output stream management +------------------------------ *************************************************************************************************/ /************************************************************************************************* ------------- Destruction of inner strctures and datas, closing environments --------------- +------------ Destruction of inner strctures and datas, closing environments +--------------- *************************************************************************************************/ -void SolverCbc::init() -{ - _clp_inner_solver = OsiClpSolverInterface(); - defineCbcModelFromInnerSolver(); +void SolverCbc::init() { + _clp_inner_solver = OsiClpSolverInterface(); + defineCbcModelFromInnerSolver(); } -void SolverCbc::free() -{ - // nothing to do here +void SolverCbc::free() { + // nothing to do here } /************************************************************************************************* -------------------------------- Reading & Writing problems ------------------------------- +------------------------------- Reading & Writing problems +------------------------------- *************************************************************************************************/ -void SolverCbc::write_prob_mps(const std::string &filename) -{ - - const int numcols = get_ncols(); - std::shared_ptr shared_integrality(new char[numcols]); - char *integrality = shared_integrality.get(); - CoinCopyN(_clp_inner_solver.getColType(false), numcols, integrality); - - bool hasInteger = false; - for (int i = 0; i < numcols; ++i) - { - if (_clp_inner_solver.isInteger(i)) - { - hasInteger = true; - break; - } - } - - CoinMpsIO writer; - writer.setInfinity(_clp_inner_solver.getInfinity()); - writer.passInMessageHandler(_clp_inner_solver.messageHandler()); - - // If the user added cuts or rows but did not added names to them - // the number of names returned by solver might be different from the - // actual number of names, resulting in a crash - std::vector rowNames(get_nrows()); - for (int i = 0; i < get_nrows(); ++i) - { - std::string const &name(_clp_inner_solver.getRowName(i)); - if (name == "") - { - std::stringstream buffer; - buffer << "R" << i; - rowNames[i] = buffer.str(); - } - else - { - rowNames[i] = name; - } - } - - std::vector colNames(get_ncols()); - for (int i = 0; i < get_ncols(); ++i) - { - std::string const &name(_clp_inner_solver.getColName(i)); - if (name == "") - { - std::stringstream buffer; - buffer << "C" << i; - colNames[i] = buffer.str(); - } - else - { - colNames[i] = name; - } - } - - writer.setMpsData( - *(_clp_inner_solver.getMatrixByCol()), - _clp_inner_solver.getInfinity(), - _clp_inner_solver.getColLower(), - _clp_inner_solver.getColUpper(), - _clp_inner_solver.getObjCoefficients(), - hasInteger ? integrality : NULL, - _clp_inner_solver.getRowLower(), - _clp_inner_solver.getRowUpper(), - colNames, - rowNames); - - std::string probName = ""; - _clp_inner_solver.getStrParam(OsiProbName, probName); - writer.setProblemName(probName.c_str()); - - double objOffset = 0.0; - _clp_inner_solver.getDblParam(OsiObjOffset, objOffset); - writer.setObjectiveOffset(objOffset); - - writer.writeMps(filename.c_str(), 0 /*gzip it*/, 1, 1, - NULL, 0, NULL); -} - -void SolverCbc::write_prob_lp(const std::string &name) -{ - _clp_inner_solver.writeLpNative(name.c_str(), NULL, NULL); -} - -void SolverCbc::read_prob_mps(const std::string &prob_name) -{ - int status = _clp_inner_solver.readMps(prob_name.c_str()); - zero_status_check(status, "read problem"); - defineCbcModelFromInnerSolver(); -} - -void SolverCbc::read_prob_lp(const std::string &prob_name) -{ - int status = _clp_inner_solver.readLp(prob_name.c_str()); - zero_status_check(status, "read problem"); - defineCbcModelFromInnerSolver(); -} - -void SolverCbc::copy_prob(const SolverAbstract::Ptr fictif_solv) -{ - std::string error = "Copy CBC problem : TO DO WHEN NEEDED"; - throw NotImplementedFeatureSolverException(error); +void SolverCbc::write_prob_mps(const std::string &filename) { + const int numcols = get_ncols(); + std::shared_ptr shared_integrality(new char[numcols]); + char *integrality = shared_integrality.get(); + CoinCopyN(_clp_inner_solver.getColType(false), numcols, integrality); + + bool hasInteger = false; + for (int i = 0; i < numcols; ++i) { + if (_clp_inner_solver.isInteger(i)) { + hasInteger = true; + break; + } + } + + CoinMpsIO writer; + writer.setInfinity(_clp_inner_solver.getInfinity()); + writer.passInMessageHandler(_clp_inner_solver.messageHandler()); + + // If the user added cuts or rows but did not added names to them + // the number of names returned by solver might be different from the + // actual number of names, resulting in a crash + std::vector rowNames(get_nrows()); + for (int i = 0; i < get_nrows(); ++i) { + std::string const &name(_clp_inner_solver.getRowName(i)); + if (name == "") { + std::stringstream buffer; + buffer << "R" << i; + rowNames[i] = buffer.str(); + } else { + rowNames[i] = name; + } + } + + std::vector colNames(get_ncols()); + for (int i = 0; i < get_ncols(); ++i) { + std::string const &name(_clp_inner_solver.getColName(i)); + if (name == "") { + std::stringstream buffer; + buffer << "C" << i; + colNames[i] = buffer.str(); + } else { + colNames[i] = name; + } + } + + writer.setMpsData( + *(_clp_inner_solver.getMatrixByCol()), _clp_inner_solver.getInfinity(), + _clp_inner_solver.getColLower(), _clp_inner_solver.getColUpper(), + _clp_inner_solver.getObjCoefficients(), hasInteger ? integrality : NULL, + _clp_inner_solver.getRowLower(), _clp_inner_solver.getRowUpper(), + colNames, rowNames); + + std::string probName = ""; + _clp_inner_solver.getStrParam(OsiProbName, probName); + writer.setProblemName(probName.c_str()); + + double objOffset = 0.0; + _clp_inner_solver.getDblParam(OsiObjOffset, objOffset); + writer.setObjectiveOffset(objOffset); + + writer.writeMps(filename.c_str(), 0 /*gzip it*/, 1, 1, NULL, 0, NULL); +} + +void SolverCbc::write_prob_lp(const std::string &name) { + _clp_inner_solver.writeLpNative(name.c_str(), NULL, NULL); +} + +void SolverCbc::read_prob_mps(const std::string &prob_name) { + int status = _clp_inner_solver.readMps(prob_name.c_str()); + zero_status_check(status, "read problem"); + defineCbcModelFromInnerSolver(); +} + +void SolverCbc::read_prob_lp(const std::string &prob_name) { + int status = _clp_inner_solver.readLp(prob_name.c_str()); + zero_status_check(status, "read problem"); + defineCbcModelFromInnerSolver(); +} + +void SolverCbc::copy_prob(const SolverAbstract::Ptr fictif_solv) { + std::string error = "Copy CBC problem : TO DO WHEN NEEDED"; + throw NotImplementedFeatureSolverException(error); } /************************************************************************************************* ------------------------ Get general informations about problem ---------------------------- +----------------------- Get general informations about problem +---------------------------- *************************************************************************************************/ -int SolverCbc::get_ncols() const -{ - int cols = _clp_inner_solver.getNumCols(); - return cols; +int SolverCbc::get_ncols() const { + int cols = _clp_inner_solver.getNumCols(); + return cols; +} + +int SolverCbc::get_nrows() const { + int rows = _clp_inner_solver.getNumRows(); + return rows; +} + +int SolverCbc::get_nelems() const { + int elems = _clp_inner_solver.getNumElements(); + return elems; } -int SolverCbc::get_nrows() const -{ - int rows = _clp_inner_solver.getNumRows(); - return rows; +int SolverCbc::get_n_integer_vars() const { + int n_int_vars = _clp_inner_solver.getNumIntegers(); + return n_int_vars; } -int SolverCbc::get_nelems() const -{ - int elems = _clp_inner_solver.getNumElements(); - return elems; -} - -int SolverCbc::get_n_integer_vars() const -{ - int n_int_vars = _clp_inner_solver.getNumIntegers(); - return n_int_vars; -} - -void SolverCbc::get_obj(double *obj, int first, int last) const -{ - const int nvars = get_ncols(); - const double *internalObj = _clp_inner_solver.getObjCoefficients(); - - for (int i = first; i < last + 1; i++) - { - obj[i - first] = internalObj[i]; - } -} - -void SolverCbc::get_rows(int *mstart, int *mclind, double *dmatval, int size, int *nels, - int first, int last) const -{ - CoinPackedMatrix matrix = *_clp_inner_solver.getMatrixByRow(); - coin_common::fill_rows_from_COIN_matrix(matrix, mstart, mclind, dmatval, nels, first, last); -} - -void SolverCbc::get_row_type(char *qrtype, int first, int last) const -{ - const double *rowLower = _clp_inner_solver.getRowLower(); - const double *rowUpper = _clp_inner_solver.getRowUpper(); - coin_common::fill_row_type_from_row_bounds(rowLower, rowUpper, qrtype, first, last); -} - -void SolverCbc::get_rhs(double *rhs, int first, int last) const -{ - const double *rowLower = _clp_inner_solver.getRowLower(); - const double *rowUpper = _clp_inner_solver.getRowUpper(); - coin_common::fill_rhs_from_bounds(rowLower, rowUpper, rhs, first, last); -} - -void SolverCbc::get_rhs_range(double *range, int first, int last) const -{ - std::stringstream buffer; - buffer << "ERROR : get rhs range not implemented in the interface for COIN CLP-CBC" << std::endl; - buffer << "ERROR : range constraints have to be set as two different constraints."; - throw NotImplementedFeatureSolverException(buffer.str()); -} - -void SolverCbc::get_col_type(char *coltype, int first, int last) const -{ - const double *colLower = _clp_inner_solver.getColLower(); - const double *colUpper = _clp_inner_solver.getColUpper(); - - for (int i(first); i < last + 1; i++) - { - if (_clp_inner_solver.isInteger(i)) - { - if (colLower[i] == 0 && colUpper[i] == 1) - { - coltype[i - first] = 'B'; - } - else - { - coltype[i - first] = 'I'; - } - } - else - { - coltype[i - first] = 'C'; - } - } -} - -void SolverCbc::get_lb(double *lb, int first, int last) const -{ - const double *colLower = _clp_inner_solver.getColLower(); - - for (int i(first); i < last + 1; i++) - { - lb[i - first] = colLower[i]; - } -} - -void SolverCbc::get_ub(double *ub, int first, int last) const -{ - const double *colUpper = _clp_inner_solver.getColUpper(); - - for (int i(first); i < last + 1; i++) - { - ub[i - first] = colUpper[i]; - } -} - -int SolverCbc::get_row_index(std::string const &name) const -{ - int id = 0; - int nrows = get_nrows(); - while (id < nrows) - { - if (_clp_inner_solver.getRowName(id) == name) - { - return id; - } - id++; - } - return -1; -} - -int SolverCbc::get_col_index(std::string const &name) const -{ - int id = 0; - int ncols = get_ncols(); - while (id < ncols) - { - if (_clp_inner_solver.getColName(id) == name) - { - return id; - } - id++; - } - return -1; -} - -std::vector SolverCbc::get_row_names(int first, int last) -{ - int size = 1 + last - first; - std::vector names; - names.reserve(size); - - std::vector solver_row_names = _clp_inner_solver.getRowNames(); - if (solver_row_names.size() < size) - { - throw InvalidRowSizeException(size, solver_row_names.size()); - } - - for (int i(first); i < last + 1; i++) - { - names.push_back(solver_row_names[i]); - } - return names; -} - -std::vector SolverCbc::get_col_names(int first, int last) -{ - int size = 1 + last - first; - std::vector names; - names.reserve(size); - - std::vector solver_col_names = _clp_inner_solver.getColNames(); - if (solver_col_names.size() < size) - { - throw InvalidColSizeException(size, solver_col_names.size()); - } - - for (int i(first); i < last + 1; i++) - { - names.push_back(solver_col_names[i]); - } - return names; +void SolverCbc::get_obj(double *obj, int first, int last) const { + const int nvars = get_ncols(); + const double *internalObj = _clp_inner_solver.getObjCoefficients(); + + for (int i = first; i < last + 1; i++) { + obj[i - first] = internalObj[i]; + } +} + +void SolverCbc::get_rows(int *mstart, int *mclind, double *dmatval, int size, + int *nels, int first, int last) const { + CoinPackedMatrix matrix = *_clp_inner_solver.getMatrixByRow(); + coin_common::fill_rows_from_COIN_matrix(matrix, mstart, mclind, dmatval, nels, + first, last); +} + +void SolverCbc::get_row_type(char *qrtype, int first, int last) const { + const double *rowLower = _clp_inner_solver.getRowLower(); + const double *rowUpper = _clp_inner_solver.getRowUpper(); + coin_common::fill_row_type_from_row_bounds(rowLower, rowUpper, qrtype, first, + last); +} + +void SolverCbc::get_rhs(double *rhs, int first, int last) const { + const double *rowLower = _clp_inner_solver.getRowLower(); + const double *rowUpper = _clp_inner_solver.getRowUpper(); + coin_common::fill_rhs_from_bounds(rowLower, rowUpper, rhs, first, last); +} + +void SolverCbc::get_rhs_range(double *range, int first, int last) const { + std::stringstream buffer; + buffer << "ERROR : get rhs range not implemented in the interface for COIN " + "CLP-CBC" + << std::endl; + buffer << "ERROR : range constraints have to be set as two different " + "constraints."; + throw NotImplementedFeatureSolverException(buffer.str()); +} + +void SolverCbc::get_col_type(char *coltype, int first, int last) const { + const double *colLower = _clp_inner_solver.getColLower(); + const double *colUpper = _clp_inner_solver.getColUpper(); + + for (int i(first); i < last + 1; i++) { + if (_clp_inner_solver.isInteger(i)) { + if (colLower[i] == 0 && colUpper[i] == 1) { + coltype[i - first] = 'B'; + } else { + coltype[i - first] = 'I'; + } + } else { + coltype[i - first] = 'C'; + } + } +} + +void SolverCbc::get_lb(double *lb, int first, int last) const { + const double *colLower = _clp_inner_solver.getColLower(); + + for (int i(first); i < last + 1; i++) { + lb[i - first] = colLower[i]; + } +} + +void SolverCbc::get_ub(double *ub, int first, int last) const { + const double *colUpper = _clp_inner_solver.getColUpper(); + + for (int i(first); i < last + 1; i++) { + ub[i - first] = colUpper[i]; + } +} + +int SolverCbc::get_row_index(std::string const &name) const { + int id = 0; + int nrows = get_nrows(); + while (id < nrows) { + if (_clp_inner_solver.getRowName(id) == name) { + return id; + } + id++; + } + return -1; +} + +int SolverCbc::get_col_index(std::string const &name) const { + int id = 0; + int ncols = get_ncols(); + while (id < ncols) { + if (_clp_inner_solver.getColName(id) == name) { + return id; + } + id++; + } + return -1; +} + +std::vector SolverCbc::get_row_names(int first, int last) { + int size = 1 + last - first; + std::vector names; + names.reserve(size); + + std::vector solver_row_names = _clp_inner_solver.getRowNames(); + if (solver_row_names.size() < size) { + throw InvalidRowSizeException(size, solver_row_names.size()); + } + + for (int i(first); i < last + 1; i++) { + names.push_back(solver_row_names[i]); + } + return names; +} + +std::vector SolverCbc::get_col_names(int first, int last) { + int size = 1 + last - first; + std::vector names; + names.reserve(size); + + std::vector solver_col_names = _clp_inner_solver.getColNames(); + if (solver_col_names.size() < size) { + throw InvalidColSizeException(size, solver_col_names.size()); + } + + for (int i(first); i < last + 1; i++) { + names.push_back(solver_col_names[i]); + } + return names; } /************************************************************************************************* ------------------------------- Methods to modify problem ---------------------------------- +------------------------------ Methods to modify problem +---------------------------------- *************************************************************************************************/ -void SolverCbc::del_rows(int first, int last) -{ - std::vector mindex(last - first + 1); - for (int i = 0; i < last - first + 1; i++) - { - mindex[i] = first + i; - } - _clp_inner_solver.deleteRows(last - first + 1, mindex.data()); -} - -void SolverCbc::add_rows(int newrows, int newnz, const char *qrtype, const double *rhs, - const double *range, const int *mstart, const int *mclind, - const double *dmatval) -{ - - std::vector rowLower(newrows); - std::vector rowUpper(newrows); - coin_common::fill_row_bounds_from_new_rows_data(rowLower, rowUpper, newrows, qrtype, rhs); - _clp_inner_solver.addRows(newrows, mstart, mclind, dmatval, rowLower.data(), rowUpper.data()); -} - -void SolverCbc::add_cols(int newcol, int newnz, const double *objx, const int *mstart, - const int *mrwind, const double *dmatval, const double *bdl, - const double *bdu) -{ - - std::vector colStart(newcol + 1); - for (int i(0); i < newcol; i++) - { - colStart[i] = mstart[i]; - } - colStart[newcol] = newnz; - - _clp_inner_solver.addCols(newcol, colStart.data(), mrwind, dmatval, bdl, bdu, objx); -} - -void SolverCbc::add_name(int type, const char *cnames, int indice) -{ - std::string error = "ERROR : addnames not implemented in the CLP interface."; - throw NotImplementedFeatureSolverException(error); -} - -void SolverCbc::chg_obj(const std::vector &mindex, const std::vector &obj) -{ - assert(obj.size() == mindex.size()); - for (int i(0); i < obj.size(); i++) - { - _clp_inner_solver.setObjCoeff(mindex[i], obj[i]); - } -} - -void SolverCbc::chg_bounds(const std::vector &mindex, const std::vector &qbtype, const std::vector &bnd) -{ - assert(qbtype.size() == mindex.size()); - assert(bnd.size() == mindex.size()); - for (int i(0); i < mindex.size(); i++) - { - if (qbtype[i] == 'L') - { - _clp_inner_solver.setColLower(mindex[i], bnd[i]); - } - else if (qbtype[i] == 'U') - { - _clp_inner_solver.setColUpper(mindex[i], bnd[i]); - } - else if (qbtype[i] == 'B') - { - _clp_inner_solver.setColLower(mindex[i], bnd[i]); - _clp_inner_solver.setColUpper(mindex[i], bnd[i]); - } - else - { - throw InvalidBoundTypeException(qbtype[i]); - } - } -} - -void SolverCbc::chg_col_type(const std::vector &mindex, const std::vector &qctype) -{ - assert(qctype.size() == mindex.size()); - std::vector bnd_index(1, 0); - std::vector bnd_type(1, 'U'); - std::vector bnd_val(1, 1.0); - - for (int i = 0; i < mindex.size(); i++) - { - if (qctype[i] == 'C') - { - _clp_inner_solver.setContinuous(mindex[i]); - } - else if (qctype[i] == 'B') - { - _clp_inner_solver.setInteger(mindex[i]); - bnd_index[0] = mindex[i]; - chg_bounds(bnd_index, bnd_type, bnd_val); - } - else if (qctype[i] == 'I') - { - _clp_inner_solver.setInteger(mindex[i]); - } - else - { - throw InvalidColTypeException(qctype[i]); - } - std::vector colT(1); - get_col_type(colT.data(), mindex[i], mindex[i]); - } -} - -void SolverCbc::chg_rhs(int id_row, double val) -{ - const double *rowLower = _clp_inner_solver.getRowLower(); - const double *rowUpper = _clp_inner_solver.getRowUpper(); - - if (rowLower[id_row] <= -COIN_DBL_MAX) - { - if (rowUpper[id_row] >= COIN_DBL_MAX) - { - std::stringstream buffer; - buffer << "ERROR : unconstrained constraint " << id_row << " in chg_rhs."; - throw GenericSolverException(buffer.str()); - } - else - { - _clp_inner_solver.setRowUpper(id_row, val); - } - } - else - { - if (rowUpper[id_row] >= COIN_DBL_MAX) - { - _clp_inner_solver.setRowLower(id_row, val); - } - else - { - std::stringstream buffer; - buffer << "ERROR : constraint " << id_row << " has both lower and upper bound in chg_rhs." << std::endl; - buffer << "Not implemented in CLP interface yet."; - throw GenericSolverException(buffer.str()); - } - } -} - -void SolverCbc::chg_coef(int id_row, int id_col, double val) -{ - - // Very tricky method by method "modifyCoefficient" of OsiClp does not work - CoinPackedMatrix matrix = *_clp_inner_solver.getMatrixByRow(); - const int *column = matrix.getIndices(); - const int *rowLength = matrix.getVectorLengths(); - const CoinBigIndex *rowStart = matrix.getVectorStarts(); - const double *vals = matrix.getElements(); - - matrix.modifyCoefficient(id_row, id_col, val); - _clp_inner_solver.replaceMatrix(matrix); -} - -void SolverCbc::chg_row_name(int id_row, std::string const &name) -{ - _clp_inner_solver.setRowName(id_row, name); -} - -void SolverCbc::chg_col_name(int id_col, std::string const &name) -{ - _clp_inner_solver.setColName(id_col, name); +void SolverCbc::del_rows(int first, int last) { + std::vector mindex(last - first + 1); + for (int i = 0; i < last - first + 1; i++) { + mindex[i] = first + i; + } + _clp_inner_solver.deleteRows(last - first + 1, mindex.data()); +} + +void SolverCbc::add_rows(int newrows, int newnz, const char *qrtype, + const double *rhs, const double *range, + const int *mstart, const int *mclind, + const double *dmatval) { + std::vector rowLower(newrows); + std::vector rowUpper(newrows); + coin_common::fill_row_bounds_from_new_rows_data(rowLower, rowUpper, newrows, + qrtype, rhs); + _clp_inner_solver.addRows(newrows, mstart, mclind, dmatval, rowLower.data(), + rowUpper.data()); +} + +void SolverCbc::add_cols(int newcol, int newnz, const double *objx, + const int *mstart, const int *mrwind, + const double *dmatval, const double *bdl, + const double *bdu) { + std::vector colStart(newcol + 1); + for (int i(0); i < newcol; i++) { + colStart[i] = mstart[i]; + } + colStart[newcol] = newnz; + + _clp_inner_solver.addCols(newcol, colStart.data(), mrwind, dmatval, bdl, bdu, + objx); +} + +void SolverCbc::add_name(int type, const char *cnames, int indice) { + std::string error = "ERROR : addnames not implemented in the CLP interface."; + throw NotImplementedFeatureSolverException(error); +} + +void SolverCbc::chg_obj(const std::vector &mindex, + const std::vector &obj) { + assert(obj.size() == mindex.size()); + for (int i(0); i < obj.size(); i++) { + _clp_inner_solver.setObjCoeff(mindex[i], obj[i]); + } +} + +void SolverCbc::chg_bounds(const std::vector &mindex, + const std::vector &qbtype, + const std::vector &bnd) { + assert(qbtype.size() == mindex.size()); + assert(bnd.size() == mindex.size()); + for (int i(0); i < mindex.size(); i++) { + if (qbtype[i] == 'L') { + _clp_inner_solver.setColLower(mindex[i], bnd[i]); + } else if (qbtype[i] == 'U') { + _clp_inner_solver.setColUpper(mindex[i], bnd[i]); + } else if (qbtype[i] == 'B') { + _clp_inner_solver.setColLower(mindex[i], bnd[i]); + _clp_inner_solver.setColUpper(mindex[i], bnd[i]); + } else { + throw InvalidBoundTypeException(qbtype[i]); + } + } +} + +void SolverCbc::chg_col_type(const std::vector &mindex, + const std::vector &qctype) { + assert(qctype.size() == mindex.size()); + std::vector bnd_index(1, 0); + std::vector bnd_type(1, 'U'); + std::vector bnd_val(1, 1.0); + + for (int i = 0; i < mindex.size(); i++) { + if (qctype[i] == 'C') { + _clp_inner_solver.setContinuous(mindex[i]); + } else if (qctype[i] == 'B') { + _clp_inner_solver.setInteger(mindex[i]); + bnd_index[0] = mindex[i]; + chg_bounds(bnd_index, bnd_type, bnd_val); + } else if (qctype[i] == 'I') { + _clp_inner_solver.setInteger(mindex[i]); + } else { + throw InvalidColTypeException(qctype[i]); + } + std::vector colT(1); + get_col_type(colT.data(), mindex[i], mindex[i]); + } +} + +void SolverCbc::chg_rhs(int id_row, double val) { + const double *rowLower = _clp_inner_solver.getRowLower(); + const double *rowUpper = _clp_inner_solver.getRowUpper(); + + if (rowLower[id_row] <= -COIN_DBL_MAX) { + if (rowUpper[id_row] >= COIN_DBL_MAX) { + std::stringstream buffer; + buffer << "ERROR : unconstrained constraint " << id_row << " in chg_rhs."; + throw GenericSolverException(buffer.str()); + } else { + _clp_inner_solver.setRowUpper(id_row, val); + } + } else { + if (rowUpper[id_row] >= COIN_DBL_MAX) { + _clp_inner_solver.setRowLower(id_row, val); + } else { + std::stringstream buffer; + buffer << "ERROR : constraint " << id_row + << " has both lower and upper bound in chg_rhs." << std::endl; + buffer << "Not implemented in CLP interface yet."; + throw GenericSolverException(buffer.str()); + } + } +} + +void SolverCbc::chg_coef(int id_row, int id_col, double val) { + // Very tricky method by method "modifyCoefficient" of OsiClp does not work + CoinPackedMatrix matrix = *_clp_inner_solver.getMatrixByRow(); + const int *column = matrix.getIndices(); + const int *rowLength = matrix.getVectorLengths(); + const CoinBigIndex *rowStart = matrix.getVectorStarts(); + const double *vals = matrix.getElements(); + + matrix.modifyCoefficient(id_row, id_col, val); + _clp_inner_solver.replaceMatrix(matrix); +} + +void SolverCbc::chg_row_name(int id_row, std::string const &name) { + _clp_inner_solver.setRowName(id_row, name); +} + +void SolverCbc::chg_col_name(int id_col, std::string const &name) { + _clp_inner_solver.setColName(id_col, name); } /************************************************************************************************* ------------------------------ Methods to solve the problem --------------------------------- +----------------------------- Methods to solve the problem +--------------------------------- *************************************************************************************************/ -int SolverCbc::solve_lp() -{ - int lp_status; - - // Passing OsiClp to Cbc to solve - // Cbc keeps only solutions of problem - defineCbcModelFromInnerSolver(); - - _cbc.solver()->initialSolve(); - - if (_cbc.isInitialSolveProvenOptimal()) - { - lp_status = OPTIMAL; - } - else if (_cbc.isInitialSolveProvenPrimalInfeasible()) - { - lp_status = INFEASIBLE; - } - else if (_cbc.isInitialSolveProvenDualInfeasible()) - { - lp_status = UNBOUNDED; - } - else - { - lp_status = UNKNOWN; - std::cout << "Error : UNKNOWN CBC STATUS after initial solve." << std::endl; - } - - return lp_status; -} - -int SolverCbc::solve_mip() -{ - int lp_status; - // Passing OsiClp to Cbc to solve - // Cbc keeps only solutions of problem - defineCbcModelFromInnerSolver(); - _cbc.branchAndBound(); - - /*std::cout << "*********************************************" << std::endl; - std::cout << "COUCOU CBC STATUS " << _cbc.status() << std::endl; - std::cout << "COUCOU CBC STATUS " << _cbc.secondaryStatus() << std::endl; - std::cout << _cbc.isProvenOptimal() << std::endl; - std::cout << "INFEAS ? " << _cbc.isProvenInfeasible() << std::endl; - std::cout << "INFEAS ? " << _cbc.isInitialSolveProvenPrimalInfeasible() << std::endl; - std::cout << "UNBD ? " << _cbc.isProvenDualInfeasible() << std::endl; - std::cout << "UNBD ? " << _cbc.isInitialSolveProvenDualInfeasible() << std::endl; - std::cout << "*********************************************" << std::endl;*/ - - if (_cbc.isProvenOptimal()) - { - if (std::abs(_cbc.solver()->getObjValue()) >= 1e20) - { - lp_status = UNBOUNDED; - } - else - { - lp_status = OPTIMAL; - } - } - else if (_cbc.isProvenInfeasible() || - _cbc.isInitialSolveProvenPrimalInfeasible()) - { - lp_status = INFEASIBLE; - } - else if (_cbc.isProvenDualInfeasible() || - _cbc.isInitialSolveProvenDualInfeasible()) - { - lp_status = UNBOUNDED; - } - else - { - lp_status = UNKNOWN; - std::cout << "Error : UNKNOWN CBC STATUS after branch and bound complete search." << std::endl; - } - - return lp_status; +int SolverCbc::solve_lp() { + int lp_status; + + // Passing OsiClp to Cbc to solve + // Cbc keeps only solutions of problem + defineCbcModelFromInnerSolver(); + + _cbc.solver()->initialSolve(); + + if (_cbc.isInitialSolveProvenOptimal()) { + lp_status = OPTIMAL; + } else if (_cbc.isInitialSolveProvenPrimalInfeasible()) { + lp_status = INFEASIBLE; + } else if (_cbc.isInitialSolveProvenDualInfeasible()) { + lp_status = UNBOUNDED; + } else { + lp_status = UNKNOWN; + std::cout << "Error : UNKNOWN CBC STATUS after initial solve." << std::endl; + } + + return lp_status; +} + +int SolverCbc::solve_mip() { + int lp_status; + // Passing OsiClp to Cbc to solve + // Cbc keeps only solutions of problem + defineCbcModelFromInnerSolver(); + _cbc.branchAndBound(); + + /*std::cout << "*********************************************" << std::endl; + std::cout << "COUCOU CBC STATUS " << _cbc.status() << std::endl; + std::cout << "COUCOU CBC STATUS " << _cbc.secondaryStatus() << std::endl; + std::cout << _cbc.isProvenOptimal() << std::endl; + std::cout << "INFEAS ? " << _cbc.isProvenInfeasible() << std::endl; + std::cout << "INFEAS ? " << _cbc.isInitialSolveProvenPrimalInfeasible() << + std::endl; std::cout << "UNBD ? " << _cbc.isProvenDualInfeasible() << + std::endl; std::cout << "UNBD ? " << + _cbc.isInitialSolveProvenDualInfeasible() << std::endl; std::cout << + "*********************************************" << std::endl;*/ + + if (_cbc.isProvenOptimal()) { + if (std::abs(_cbc.solver()->getObjValue()) >= 1e20) { + lp_status = UNBOUNDED; + } else { + lp_status = OPTIMAL; + } + } else if (_cbc.isProvenInfeasible() || + _cbc.isInitialSolveProvenPrimalInfeasible()) { + lp_status = INFEASIBLE; + } else if (_cbc.isProvenDualInfeasible() || + _cbc.isInitialSolveProvenDualInfeasible()) { + lp_status = UNBOUNDED; + } else { + lp_status = UNKNOWN; + std::cout + << "Error : UNKNOWN CBC STATUS after branch and bound complete search." + << std::endl; + } + + return lp_status; } /************************************************************************************************* -------------------------- Methods to get solutions information ----------------------------- +------------------------- Methods to get solutions information +----------------------------- *************************************************************************************************/ -void SolverCbc::get_basis(int *rstatus, int *cstatus) const -{ - _cbc.solver()->getBasisStatus(cstatus, rstatus); +void SolverCbc::get_basis(int *rstatus, int *cstatus) const { + _cbc.solver()->getBasisStatus(cstatus, rstatus); } -double SolverCbc::get_mip_value() const -{ - return _cbc.getObjValue(); -} +double SolverCbc::get_mip_value() const { return _cbc.getObjValue(); } -double SolverCbc::get_lp_value() const -{ - return _cbc.solver()->getObjValue(); -} +double SolverCbc::get_lp_value() const { return _cbc.solver()->getObjValue(); } -int SolverCbc::get_splex_num_of_ite_last() const -{ - return _cbc.solver()->getIterationCount(); +int SolverCbc::get_splex_num_of_ite_last() const { + return _cbc.solver()->getIterationCount(); } void SolverCbc::get_lp_sol(double *primals, double *duals, - double *reduced_costs) -{ - if (primals != NULL) - { - const double *primalSol = _cbc.solver()->getColSolution(); - for (int i(0); i < get_ncols(); i++) - { - primals[i] = primalSol[i]; - } - } - - if (duals != NULL) - { - const double *dualSol = _cbc.solver()->getRowPrice(); - for (int i(0); i < get_nrows(); i++) - { - duals[i] = dualSol[i]; - } - } - - if (reduced_costs != NULL) - { - const double *reducedCostSolution = _cbc.solver()->getReducedCost(); - for (int i(0); i < get_ncols(); i++) - { - reduced_costs[i] = reducedCostSolution[i]; - } - } -} - -void SolverCbc::get_mip_sol(double *primals) -{ - if (primals != NULL) - { - const double *primalSol = _cbc.getColSolution(); - for (int i(0); i < get_ncols(); i++) - { - primals[i] = primalSol[i]; - } - } + double *reduced_costs) { + if (primals != NULL) { + const double *primalSol = _cbc.solver()->getColSolution(); + for (int i(0); i < get_ncols(); i++) { + primals[i] = primalSol[i]; + } + } + + if (duals != NULL) { + const double *dualSol = _cbc.solver()->getRowPrice(); + for (int i(0); i < get_nrows(); i++) { + duals[i] = dualSol[i]; + } + } + + if (reduced_costs != NULL) { + const double *reducedCostSolution = _cbc.solver()->getReducedCost(); + for (int i(0); i < get_ncols(); i++) { + reduced_costs[i] = reducedCostSolution[i]; + } + } +} + +void SolverCbc::get_mip_sol(double *primals) { + if (primals != NULL) { + const double *primalSol = _cbc.getColSolution(); + for (int i(0); i < get_ncols(); i++) { + primals[i] = primalSol[i]; + } + } } /************************************************************************************************* ------------------------- Methods to set algorithm or logs levels --------------------------- +------------------------ Methods to set algorithm or logs levels +--------------------------- *************************************************************************************************/ -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); - } -} - -void SolverCbc::set_algorithm(std::string const &algo) -{ - throw InvalidSolverOptionException("set_algorithm : " + algo); -} - -void SolverCbc::set_threads(int n_threads) -{ - _cbc.setNumberThreads(n_threads); -} - -void SolverCbc::set_optimality_gap(double gap) -{ - throw InvalidSolverOptionException("set_optimality_gap : " + std::to_string(gap)); -} - -void SolverCbc::set_simplex_iter(int iter) -{ - throw InvalidSolverOptionException("set_simplex_iter : " + std::to_string(iter)); +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); + } +} + +void SolverCbc::set_algorithm(std::string const &algo) { + throw InvalidSolverOptionException("set_algorithm : " + algo); +} + +void SolverCbc::set_threads(int n_threads) { _cbc.setNumberThreads(n_threads); } + +void SolverCbc::set_optimality_gap(double gap) { + throw InvalidSolverOptionException("set_optimality_gap : " + + std::to_string(gap)); +} + +void SolverCbc::set_simplex_iter(int iter) { + throw InvalidSolverOptionException("set_simplex_iter : " + + std::to_string(iter)); } \ No newline at end of file diff --git a/src/cpp/multisolver_interface/SolverCbc.h b/src/cpp/multisolver_interface/SolverCbc.h index e83c135af..d6eb8b9db 100644 --- a/src/cpp/multisolver_interface/SolverCbc.h +++ b/src/cpp/multisolver_interface/SolverCbc.h @@ -1,167 +1,178 @@ #pragma once -#include "multisolver_interface/SolverAbstract.h" - -#include "Cbc_C_Interface.h" #include "CbcModel.hpp" -#include "OsiClpSolverInterface.hpp" -#include "CoinMpsIO.hpp" +#include "Cbc_C_Interface.h" #include "CoinHelperFunctions.hpp" +#include "CoinMpsIO.hpp" +#include "OsiClpSolverInterface.hpp" +#include "multisolver_interface/SolverAbstract.h" /*! * \class class SolverCbc - * \brief Daughter class of AsbtractSolver implementing solver COIN-OR CBC with intern CLP solver + * \brief Daughter class of AsbtractSolver implementing solver COIN-OR CBC with + * intern CLP solver */ -class SolverCbc : public SolverAbstract -{ - - /************************************************************************************************* - ---------------------------------------- ATTRIBUTES --------------------------------------- - *************************************************************************************************/ - static int _NumberOfProblems; /*!< Counter of the total number of Cplex problems - declared to set or end the environment */ -public: - OsiClpSolverInterface _clp_inner_solver; - CbcModel _cbc; - CoinMessageHandler _message_handler; - int _current_log_level; - - /************************************************************************************************* - ----------------------------------- Constructor/Desctructor -------------------------------- - *************************************************************************************************/ -public: - /** - * @brief Default constructor of a CBC solver - */ - SolverCbc(); - - /** - * @brief Copy constructor of solver, copy the problem toCopy in memory and name it "name" - * - * @param toCopy : Pointer to an AbstractSolver object, containing a CBC solver to copy - */ - SolverCbc(const SolverAbstract::Ptr toCopy); - - virtual ~SolverCbc(); - virtual int get_number_of_instances() override; - - virtual std::string get_solver_name() const override { return "CBC"; } - -private: - void defineCbcModelFromInnerSolver(); - - /************************************************************************************************* - --------------------------------- Output and stream management ----------------------------- - *************************************************************************************************/ - - /************************************************************************************************* - ------ Destruction or creation of inner strctures and datas, closing environments ---------- - *************************************************************************************************/ -public: - virtual void init() override; - virtual void free() override; - - /************************************************************************************************* - ------------------------------- Reading & Writing problems ------------------------------- - *************************************************************************************************/ -public: - virtual void write_prob_mps(const std::string &filename) override; - virtual void write_prob_lp(const std::string &filename) override; - - virtual void read_prob_mps(const std::string &filename) override; - virtual void read_prob_lp(const std::string &filename) override; - - virtual void copy_prob(const SolverAbstract::Ptr fictif_solv) override; - - /************************************************************************************************* - ----------------------- Get general informations about problem ---------------------------- - *************************************************************************************************/ -public: - virtual int get_ncols() const override; - virtual int get_nrows() const override; - virtual int get_nelems() const override; - virtual int get_n_integer_vars() const override; - virtual void get_obj(double *obj, int first, int last) const override; - virtual void get_rows(int *mstart, int *mclind, double *dmatval, int size, int *nels, - int first, int last) const override; - virtual void get_row_type(char *qrtype, int first, int last) const override; - virtual void get_rhs(double *rhs, int first, int last) const override; - virtual void get_rhs_range(double *range, int first, int last) const override; - virtual void get_col_type(char *coltype, int first, int last) const override; - virtual void get_lb(double *lb, int fisrt, int last) const override; - virtual void get_ub(double *ub, int fisrt, int last) const override; - - virtual int get_row_index(std::string const &name) const override; - virtual int get_col_index(std::string const &name) const override; - virtual std::vector get_row_names(int first, int last) override; - virtual std::vector get_col_names(int first, int last) override; - - /************************************************************************************************* - ------------------------------ Methods to modify problem ---------------------------------- - *************************************************************************************************/ -public: - virtual void del_rows(int first, int last) override; - virtual void add_rows(int newrows, int newnz, const char *qrtype, const double *rhs, - const double *range, const int *mstart, const int *mclind, - const double *dmatval) override; - virtual void add_cols(int newcol, int newnz, const double *objx, const int *mstart, - const int *mrwind, const double *dmatval, const double *bdl, - const double *bdu) override; - virtual void add_name(int type, const char *cnames, int indice) override; - virtual void chg_obj(const std::vector &mindex, const std::vector &obj) override; - virtual void chg_bounds(const std::vector &mindex, const std::vector &qbtype, const std::vector &bnd) override; - virtual void chg_col_type(const std::vector &mindex, const std::vector &qctype) override; - virtual void chg_rhs(int id_row, double val) override; - virtual void chg_coef(int id_row, int id_col, double val) override; - virtual void chg_row_name(int id_row, std::string const &name) override; - virtual void chg_col_name(int id_col, std::string const &name) override; - - /************************************************************************************************* - ----------------------------- Methods to solve the problem --------------------------------- - *************************************************************************************************/ -public: - virtual int solve_lp() override; - virtual int solve_mip() override; - - /************************************************************************************************* - ------------------------- Methods to get solutions information ----------------------------- - *************************************************************************************************/ -public: - /** - * @brief Returns the current basis into the user’s data arrays. - * - * @param rstatus : Integer array of length ROWS to the basis status of the slack, surplus or - artifficial variable associated with each row. The status will be one of: - 0 slack, surplus or artifficial is free; - 1 slack, surplus or artifficial is basic; - 2 slack, surplus or artifficial is at upper bound; - 3 slack, surplus or artifficial is at lower bound; - 4 slack, surplus or artifficial is super basic. - May be NULL if not required. - * @param cstatus : Integer array of length COLS to hold the basis status of the columns - in the constraint matrix. The status will be one of: - 0 variable is free; - 1 variable is basic; - 2 variable is at upper bound; - 3 variable is at lower bound; - 4 variable is super basic - May be NULL if not required. - */ - virtual void get_basis(int *rstatus, int *cstatus) const override; - virtual double get_mip_value() const override; - virtual double get_lp_value() const override; - virtual int get_splex_num_of_ite_last() const override; - virtual void get_lp_sol(double *primals, double *duals, - double *reduced_costs) override; - virtual void get_mip_sol(double *primals) override; - - /************************************************************************************************* - ------------------------ Methods to set algorithm or logs levels --------------------------- - *************************************************************************************************/ -public: - virtual void set_output_log_level(int loglevel) override; - 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; - virtual void set_simplex_iter(int iter) override; +class SolverCbc : public SolverAbstract { + /************************************************************************************************* + ---------------------------------------- ATTRIBUTES + --------------------------------------- + *************************************************************************************************/ + static int _NumberOfProblems; /*!< Counter of the total number of Cplex + problems declared to set or end the + environment */ + public: + OsiClpSolverInterface _clp_inner_solver; + CbcModel _cbc; + CoinMessageHandler _message_handler; + int _current_log_level; + + /************************************************************************************************* + ----------------------------------- Constructor/Desctructor + -------------------------------- + *************************************************************************************************/ + public: + /** + * @brief Default constructor of a CBC solver + */ + SolverCbc(); + + /** + * @brief Copy constructor of solver, copy the problem toCopy in memory and + * name it "name" + * + * @param toCopy : Pointer to an AbstractSolver object, containing a CBC + * solver to copy + */ + SolverCbc(const SolverAbstract::Ptr toCopy); + + virtual ~SolverCbc(); + virtual int get_number_of_instances() override; + + virtual std::string get_solver_name() const override { return "CBC"; } + + private: + void defineCbcModelFromInnerSolver(); + + /************************************************************************************************* + --------------------------------- Output and stream management + ----------------------------- + *************************************************************************************************/ + + /************************************************************************************************* + ------ Destruction or creation of inner strctures and datas, closing + environments ---------- + *************************************************************************************************/ + public: + virtual void init() override; + virtual void free() override; + + /************************************************************************************************* + ------------------------------- Reading & Writing problems + ------------------------------- + *************************************************************************************************/ + public: + virtual void write_prob_mps(const std::string &filename) override; + virtual void write_prob_lp(const std::string &filename) override; + + virtual void read_prob_mps(const std::string &filename) override; + virtual void read_prob_lp(const std::string &filename) override; + + virtual void copy_prob(const SolverAbstract::Ptr fictif_solv) override; + + /************************************************************************************************* + ----------------------- Get general informations about problem + ---------------------------- + *************************************************************************************************/ + public: + virtual int get_ncols() const override; + virtual int get_nrows() const override; + virtual int get_nelems() const override; + virtual int get_n_integer_vars() const override; + virtual void get_obj(double *obj, int first, int last) const override; + virtual void get_rows(int *mstart, int *mclind, double *dmatval, int size, + int *nels, int first, int last) const override; + virtual void get_row_type(char *qrtype, int first, int last) const override; + virtual void get_rhs(double *rhs, int first, int last) const override; + virtual void get_rhs_range(double *range, int first, int last) const override; + virtual void get_col_type(char *coltype, int first, int last) const override; + virtual void get_lb(double *lb, int fisrt, int last) const override; + virtual void get_ub(double *ub, int fisrt, int last) const override; + + virtual int get_row_index(std::string const &name) const override; + virtual int get_col_index(std::string const &name) const override; + virtual std::vector get_row_names(int first, int last) override; + virtual std::vector get_col_names(int first, int last) override; + + /************************************************************************************************* + ------------------------------ Methods to modify problem + ---------------------------------- + *************************************************************************************************/ + public: + virtual void del_rows(int first, int last) override; + virtual void add_rows(int newrows, int newnz, const char *qrtype, + const double *rhs, const double *range, + const int *mstart, const int *mclind, + const double *dmatval) override; + virtual void add_cols(int newcol, int newnz, const double *objx, + const int *mstart, const int *mrwind, + const double *dmatval, const double *bdl, + const double *bdu) override; + virtual void add_name(int type, const char *cnames, int indice) override; + virtual void chg_obj(const std::vector &mindex, + const std::vector &obj) override; + virtual void chg_bounds(const std::vector &mindex, + const std::vector &qbtype, + const std::vector &bnd) override; + virtual void chg_col_type(const std::vector &mindex, + const std::vector &qctype) override; + virtual void chg_rhs(int id_row, double val) override; + virtual void chg_coef(int id_row, int id_col, double val) override; + virtual void chg_row_name(int id_row, std::string const &name) override; + virtual void chg_col_name(int id_col, std::string const &name) override; + + /************************************************************************************************* + ----------------------------- Methods to solve the problem + --------------------------------- + *************************************************************************************************/ + public: + virtual int solve_lp() override; + virtual int solve_mip() override; + + /************************************************************************************************* + ------------------------- Methods to get solutions information + ----------------------------- + *************************************************************************************************/ + public: + /** + * @brief Returns the current basis into the user’s data arrays. + * + * @param rstatus : Integer array of length ROWS to the basis status of the + slack, surplus or artifficial variable associated with each row. The status + will be one of: 0 slack, surplus or artifficial is free; 1 slack, surplus or + artifficial is basic; 2 slack, surplus or artifficial is at upper bound; 3 + slack, surplus or artifficial is at lower bound; 4 slack, surplus or + artifficial is super basic. May be NULL if not required. + * @param cstatus : Integer array of length COLS to hold the basis status of + the columns in the constraint matrix. The status will be one of: 0 variable is + free; 1 variable is basic; 2 variable is at upper bound; 3 variable is at + lower bound; 4 variable is super basic May be NULL if not required. + */ + virtual void get_basis(int *rstatus, int *cstatus) const override; + virtual double get_mip_value() const override; + virtual double get_lp_value() const override; + virtual int get_splex_num_of_ite_last() const override; + virtual void get_lp_sol(double *primals, double *duals, + double *reduced_costs) override; + virtual void get_mip_sol(double *primals) override; + + /************************************************************************************************* + ------------------------ Methods to set algorithm or logs levels + --------------------------- + *************************************************************************************************/ + public: + virtual void set_output_log_level(int loglevel) override; + 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; + virtual void set_simplex_iter(int iter) override; }; \ No newline at end of file diff --git a/src/cpp/multisolver_interface/SolverClp.cpp b/src/cpp/multisolver_interface/SolverClp.cpp index 3c27471d9..61e4de83d 100644 --- a/src/cpp/multisolver_interface/SolverClp.cpp +++ b/src/cpp/multisolver_interface/SolverClp.cpp @@ -1,597 +1,473 @@ #include "SolverClp.h" + #include "COIN_common_functions.h" /************************************************************************************************* ------------------------------------ Constructor/Desctructor -------------------------------- +----------------------------------- Constructor/Desctructor +-------------------------------- *************************************************************************************************/ int SolverClp::_NumberOfProblems = 0; -SolverClp::SolverClp() -{ - int status = 0; +SolverClp::SolverClp() { + int status = 0; - _NumberOfProblems += 1; - _clp = NULL; + _NumberOfProblems += 1; + _clp = NULL; } -SolverClp::SolverClp(const SolverAbstract::Ptr fictif) : SolverClp() -{ - // Try to cast the solver in fictif to a SolverCPLEX - if (SolverClp *c = dynamic_cast(fictif.get())) - { - _clp = ClpSimplex(c->_clp); - } - else - { - _NumberOfProblems -= 1; - throw InvalidSolverForCopyException(fictif->get_solver_name(), get_solver_name()); - } +SolverClp::SolverClp(const SolverAbstract::Ptr fictif) : SolverClp() { + // Try to cast the solver in fictif to a SolverCPLEX + if (SolverClp *c = dynamic_cast(fictif.get())) { + _clp = ClpSimplex(c->_clp); + } else { + _NumberOfProblems -= 1; + throw InvalidSolverForCopyException(fictif->get_solver_name(), + get_solver_name()); + } } -SolverClp::~SolverClp() -{ - - _NumberOfProblems -= 1; - free(); +SolverClp::~SolverClp() { + _NumberOfProblems -= 1; + free(); } -int SolverClp::get_number_of_instances() -{ - return _NumberOfProblems; -} +int SolverClp::get_number_of_instances() { return _NumberOfProblems; } /************************************************************************************************* ------------------------------------ Output stream management ------------------------------ +----------------------------------- Output stream management +------------------------------ *************************************************************************************************/ /************************************************************************************************* ------------- Destruction of inner strctures and datas, closing environments --------------- +------------ Destruction of inner strctures and datas, closing environments +--------------- *************************************************************************************************/ -void SolverClp::init() -{ - _clp = ClpSimplex(); -} +void SolverClp::init() { _clp = ClpSimplex(); } -void SolverClp::free() -{ - //_clp = ClpSimplex(); +void SolverClp::free() { + //_clp = ClpSimplex(); } /************************************************************************************************* -------------------------------- Reading & Writing problems ------------------------------- +------------------------------- Reading & Writing problems +------------------------------- *************************************************************************************************/ -void SolverClp::write_prob_mps(const std::string &filename) -{ - _clp.writeMps(filename.c_str(), 1); +void SolverClp::write_prob_mps(const std::string &filename) { + _clp.writeMps(filename.c_str(), 1); } -void SolverClp::write_prob_lp(const std::string &filename) -{ - _clp.writeLp(filename.c_str()); +void SolverClp::write_prob_lp(const std::string &filename) { + _clp.writeLp(filename.c_str()); } -void SolverClp::read_prob_mps(const std::string &filename) -{ - _clp.readMps(filename.c_str(), true, false); +void SolverClp::read_prob_mps(const std::string &filename) { + _clp.readMps(filename.c_str(), true, false); } -void SolverClp::read_prob_lp(const std::string &filename) -{ - _clp.readLp(filename.c_str()); +void SolverClp::read_prob_lp(const std::string &filename) { + _clp.readLp(filename.c_str()); } -void SolverClp::copy_prob(const SolverAbstract::Ptr fictif_solv) -{ - std::string error = "Copy Clp problem : TO DO WHEN NEEDED"; - throw NotImplementedFeatureSolverException(error); +void SolverClp::copy_prob(const SolverAbstract::Ptr fictif_solv) { + std::string error = "Copy Clp problem : TO DO WHEN NEEDED"; + throw NotImplementedFeatureSolverException(error); } /************************************************************************************************* ------------------------ Get general informations about problem ---------------------------- +----------------------- Get general informations about problem +---------------------------- *************************************************************************************************/ -int SolverClp::get_ncols() const -{ - return _clp.getNumCols(); +int SolverClp::get_ncols() const { return _clp.getNumCols(); } + +int SolverClp::get_nrows() const { return _clp.getNumRows(); } + +int SolverClp::get_nelems() const { return _clp.getNumElements(); } + +int SolverClp::get_n_integer_vars() const { + int nvars = get_ncols(); + int n_int_vars(0); + for (int i(0); i < nvars; i++) { + if (_clp.isInteger(i)) { + n_int_vars += 1; + } + } + return n_int_vars; +} + +void SolverClp::get_obj(double *obj, int first, int last) const { + double *internalObj = _clp.objective(); + + for (int i = first; i < last + 1; i++) { + obj[i - first] = internalObj[i]; + } +} + +void SolverClp::get_rows(int *mstart, int *mclind, double *dmatval, int size, + int *nels, int first, int last) const { + CoinPackedMatrix matrix = *_clp.matrix(); + matrix.reverseOrdering(); + coin_common::fill_rows_from_COIN_matrix(matrix, mstart, mclind, dmatval, nels, + first, last); +} + +void SolverClp::get_row_type(char *qrtype, int first, int last) const { + const double *rowLower = _clp.getRowLower(); + const double *rowUpper = _clp.getRowUpper(); + + coin_common::fill_row_type_from_row_bounds(rowLower, rowUpper, qrtype, first, + last); +} + +void SolverClp::get_rhs(double *rhs, int first, int last) const { + const double *rowLower = _clp.getRowLower(); + const double *rowUpper = _clp.getRowUpper(); + coin_common::fill_rhs_from_bounds(rowLower, rowUpper, rhs, first, last); +} + +void SolverClp::get_rhs_range(double *range, int first, int last) const { + std::string error = + "ERROR : get rhs range not implemented for COIN CLP interface"; + throw NotImplementedFeatureSolverException(error); +} + +void SolverClp::get_col_type(char *coltype, int first, int last) const { + const double *colLower = _clp.getColLower(); + const double *colUpper = _clp.getColUpper(); + + for (int i = first; i < last + 1; i++) { + if (_clp.isInteger(i)) { + if (colLower[i] == 0 && colUpper[i] == 1) { + coltype[i - first] = 'B'; + } else { + coltype[i - first] = 'I'; + } + } else { + coltype[i - first] = 'C'; + } + } +} + +void SolverClp::get_lb(double *lb, int first, int last) const { + const double *colLower = _clp.getColLower(); + + for (int i = first; i < last + 1; i++) { + lb[i - first] = colLower[i]; + } +} + +void SolverClp::get_ub(double *ub, int first, int last) const { + const double *colUpper = _clp.getColUpper(); + + for (int i = first; i < last + 1; i++) { + ub[i - first] = colUpper[i]; + } +} + +int SolverClp::get_row_index(std::string const &name) const { + int id = 0; + int nrows = get_nrows(); + while (id < nrows) { + if (_clp.getRowName(id) == name) { + return id; + } + id++; + } + return -1; } -int SolverClp::get_nrows() const -{ - return _clp.getNumRows(); +int SolverClp::get_col_index(std::string const &name) const { + int id = 0; + int ncols = get_ncols(); + while (id < ncols) { + if (_clp.getColumnName(id) == name) { + return id; + } + id++; + } + return -1; } -int SolverClp::get_nelems() const -{ - return _clp.getNumElements(); +std::vector SolverClp::get_row_names(int first, int last) { + std::vector names; + names.reserve(1 + last - first); + + for (int i = first; i < last + 1; i++) { + names.push_back(_clp.getRowName(i)); + } + return names; } -int SolverClp::get_n_integer_vars() const -{ - int nvars = get_ncols(); - int n_int_vars(0); - for (int i(0); i < nvars; i++) - { - if (_clp.isInteger(i)) - { - n_int_vars += 1; - } - } - return n_int_vars; -} - -void SolverClp::get_obj(double *obj, int first, int last) const -{ - const int nvars = get_ncols(); - double *internalObj = _clp.objective(); +std::vector SolverClp::get_col_names(int first, int last) { + std::vector names; + names.reserve(1 + last - first); - for (int i = first; i < last + 1; i++) - { - obj[i - first] = internalObj[i]; - } -} - -void SolverClp::get_rows(int *mstart, int *mclind, double *dmatval, int size, int *nels, - int first, int last) const -{ - - CoinPackedMatrix matrix = *_clp.matrix(); - matrix.reverseOrdering(); - coin_common::fill_rows_from_COIN_matrix(matrix, mstart, mclind, dmatval, nels, first, last); -} - -void SolverClp::get_row_type(char *qrtype, int first, int last) const -{ - const double *rowLower = _clp.getRowLower(); - const double *rowUpper = _clp.getRowUpper(); - - coin_common::fill_row_type_from_row_bounds(rowLower, rowUpper, qrtype, first, last); -} - -void SolverClp::get_rhs(double *rhs, int first, int last) const -{ - const double *rowLower = _clp.getRowLower(); - const double *rowUpper = _clp.getRowUpper(); - coin_common::fill_rhs_from_bounds(rowLower, rowUpper, rhs, first, last); -} - -void SolverClp::get_rhs_range(double *range, int first, int last) const -{ - std::string error = "ERROR : get rhs range not implemented for COIN CLP interface"; - throw NotImplementedFeatureSolverException(error); -} - -void SolverClp::get_col_type(char *coltype, int first, int last) const -{ - - const double *colLower = _clp.getColLower(); - const double *colUpper = _clp.getColUpper(); - - for (int i = first; i < last + 1; i++) - { - if (_clp.isInteger(i)) - { - if (colLower[i] == 0 && colUpper[i] == 1) - { - coltype[i - first] = 'B'; - } - else - { - coltype[i - first] = 'I'; - } - } - else - { - coltype[i - first] = 'C'; - } - } -} - -void SolverClp::get_lb(double *lb, int first, int last) const -{ - const double *colLower = _clp.getColLower(); - - for (int i = first; i < last + 1; i++) - { - lb[i - first] = colLower[i]; - } -} - -void SolverClp::get_ub(double *ub, int first, int last) const -{ - const double *colUpper = _clp.getColUpper(); - - for (int i = first; i < last + 1; i++) - { - ub[i - first] = colUpper[i]; - } -} - -int SolverClp::get_row_index(std::string const &name) const -{ - int id = 0; - int nrows = get_nrows(); - while (id < nrows) - { - if (_clp.getRowName(id) == name) - { - return id; - } - id++; - } - return -1; -} - -int SolverClp::get_col_index(std::string const &name) const -{ - int id = 0; - int ncols = get_ncols(); - while (id < ncols) - { - if (_clp.getColumnName(id) == name) - { - return id; - } - id++; - } - return -1; -} - -std::vector SolverClp::get_row_names(int first, int last) -{ - std::vector names; - names.reserve(1 + last - first); - - for (int i = first; i < last + 1; i++) - { - names.push_back(_clp.getRowName(i)); - } - return names; -} - -std::vector SolverClp::get_col_names(int first, int last) -{ - std::vector names; - names.reserve(1 + last - first); - - for (int i = first; i < last + 1; i++) - { - names.push_back(_clp.getColumnName(i)); - } - return names; + for (int i = first; i < last + 1; i++) { + names.push_back(_clp.getColumnName(i)); + } + return names; } /************************************************************************************************* ------------------------------- Methods to modify problem ---------------------------------- +------------------------------ Methods to modify problem +---------------------------------- *************************************************************************************************/ -void SolverClp::del_rows(int first, int last) -{ - std::vector mindex(last - first + 1); - for (int i = 0; i < last - first + 1; i++) - { - mindex[i] = first + i; - } - _clp.deleteRows(last - first + 1, mindex.data()); -} - -void SolverClp::add_rows(int newrows, int newnz, const char *qrtype, const double *rhs, - const double *range, const int *mstart, const int *mclind, - const double *dmatval) -{ - - std::vector rowLower(newrows); - std::vector rowUpper(newrows); - coin_common::fill_row_bounds_from_new_rows_data(rowLower, rowUpper, newrows, qrtype, rhs); - - _clp.addRows(newrows, rowLower.data(), rowUpper.data(), mstart, mclind, dmatval); -} - -void SolverClp::add_cols(int newcol, int newnz, const double *objx, const int *mstart, - const int *mrwind, const double *dmatval, const double *bdl, - const double *bdu) -{ - - std::vector colStart(newcol + 1); - for (int i(0); i < newcol; i++) - { - colStart[i] = mstart[i]; - } - colStart[newcol] = newnz; - - _clp.addColumns(newcol, bdl, bdu, objx, colStart.data(), mrwind, dmatval); -} - -void SolverClp::add_name(int type, const char *cnames, int indice) -{ - std::string error = "ERROR : addnames not implemented in the CLP interface."; - throw NotImplementedFeatureSolverException(error); -} - -void SolverClp::chg_obj(const std::vector &mindex, const std::vector &obj) -{ - assert(obj.size() == mindex.size()); - for (int i(0); i < obj.size(); i++) - { - _clp.setObjCoeff(mindex[i], obj[i]); - } -} - -void SolverClp::chg_bounds(const std::vector &mindex, const std::vector &qbtype, const std::vector &bnd) -{ - assert(qbtype.size() == mindex.size()); - assert(bnd.size() == mindex.size()); - for (int i(0); i < mindex.size(); i++) - { - if (qbtype[i] == 'L') - { - _clp.setColLower(mindex[i], bnd[i]); - } - else if (qbtype[i] == 'U') - { - _clp.setColUpper(mindex[i], bnd[i]); - } - else if (qbtype[i] == 'B') - { - _clp.setColLower(mindex[i], bnd[i]); - _clp.setColUpper(mindex[i], bnd[i]); - } - else - { - throw InvalidBoundTypeException(qbtype[i]); - } - } -} - -void SolverClp::chg_col_type(const std::vector &mindex, const std::vector &qctype) -{ - assert(qctype.size() == mindex.size()); - std::vector bnd_index(1, 0); - std::vector bnd_type(1, 'U'); - std::vector bnd_val(1, 1.0); - - for (int i = 0; i < mindex.size(); i++) - { - switch (qctype[i]) - { - case 'C': - _clp.setContinuous(mindex[i]); - break; - case 'B': - _clp.setInteger(mindex[i]); - bnd_index[0] = mindex[i]; - chg_bounds(bnd_index, bnd_type, bnd_val); - break; - case 'I': - _clp.setInteger(mindex[i]); - break; - default: - throw InvalidColTypeException(qctype[i]); - } - } -} - -void SolverClp::chg_rhs(int id_row, double val) -{ - const double *rowLower = _clp.getRowLower(); - const double *rowUpper = _clp.getRowUpper(); - - if (rowLower[id_row] <= -COIN_DBL_MAX) - { - if (rowUpper[id_row] >= COIN_DBL_MAX) - { - std::stringstream buffer; - buffer << "ERROR : unconstrained constraint " << id_row << " in chg_rhs."; - throw GenericSolverException(buffer.str()); - } - else - { - _clp.setRowUpper(id_row, val); - } - } - else - { - if (rowUpper[id_row] >= COIN_DBL_MAX) - { - _clp.setRowLower(id_row, val); - } - else - { - std::stringstream buffer; - std::cout << "ERROR : constraint " << id_row << " has both different lower and upper bound in chg_rhs."; - throw GenericSolverException(buffer.str()); - } - } -} - -void SolverClp::chg_coef(int id_row, int id_col, double val) -{ - - CoinPackedMatrix *matrix = _clp.matrix(); - matrix->modifyCoefficient(id_row, id_col, val); -} - -void SolverClp::chg_row_name(int id_row, std::string const &name) -{ - std::string copy_name = name; - _clp.setRowName(id_row, copy_name); -} - -void SolverClp::chg_col_name(int id_col, std::string const &name) -{ - std::string copy_name = name; - _clp.setColumnName(id_col, copy_name); +void SolverClp::del_rows(int first, int last) { + std::vector mindex(last - first + 1); + for (int i = 0; i < last - first + 1; i++) { + mindex[i] = first + i; + } + _clp.deleteRows(last - first + 1, mindex.data()); +} + +void SolverClp::add_rows(int newrows, int newnz, const char *qrtype, + const double *rhs, const double *range, + const int *mstart, const int *mclind, + const double *dmatval) { + std::vector rowLower(newrows); + std::vector rowUpper(newrows); + coin_common::fill_row_bounds_from_new_rows_data(rowLower, rowUpper, newrows, + qrtype, rhs); + + _clp.addRows(newrows, rowLower.data(), rowUpper.data(), mstart, mclind, + dmatval); +} + +void SolverClp::add_cols(int newcol, int newnz, const double *objx, + const int *mstart, const int *mrwind, + const double *dmatval, const double *bdl, + const double *bdu) { + std::vector colStart(newcol + 1); + for (int i(0); i < newcol; i++) { + colStart[i] = mstart[i]; + } + colStart[newcol] = newnz; + + _clp.addColumns(newcol, bdl, bdu, objx, colStart.data(), mrwind, dmatval); +} + +void SolverClp::add_name(int type, const char *cnames, int indice) { + std::string error = "ERROR : addnames not implemented in the CLP interface."; + throw NotImplementedFeatureSolverException(error); +} + +void SolverClp::chg_obj(const std::vector &mindex, + const std::vector &obj) { + assert(obj.size() == mindex.size()); + for (int i(0); i < obj.size(); i++) { + _clp.setObjCoeff(mindex[i], obj[i]); + } +} + +void SolverClp::chg_bounds(const std::vector &mindex, + const std::vector &qbtype, + const std::vector &bnd) { + assert(qbtype.size() == mindex.size()); + assert(bnd.size() == mindex.size()); + for (int i(0); i < mindex.size(); i++) { + if (qbtype[i] == 'L') { + _clp.setColLower(mindex[i], bnd[i]); + } else if (qbtype[i] == 'U') { + _clp.setColUpper(mindex[i], bnd[i]); + } else if (qbtype[i] == 'B') { + _clp.setColLower(mindex[i], bnd[i]); + _clp.setColUpper(mindex[i], bnd[i]); + } else { + throw InvalidBoundTypeException(qbtype[i]); + } + } +} + +void SolverClp::chg_col_type(const std::vector &mindex, + const std::vector &qctype) { + assert(qctype.size() == mindex.size()); + std::vector bnd_index(1, 0); + std::vector bnd_type(1, 'U'); + std::vector bnd_val(1, 1.0); + + for (int i = 0; i < mindex.size(); i++) { + switch (qctype[i]) { + case 'C': + _clp.setContinuous(mindex[i]); + break; + case 'B': + _clp.setInteger(mindex[i]); + bnd_index[0] = mindex[i]; + chg_bounds(bnd_index, bnd_type, bnd_val); + break; + case 'I': + _clp.setInteger(mindex[i]); + break; + default: + throw InvalidColTypeException(qctype[i]); + } + } +} + +void SolverClp::chg_rhs(int id_row, double val) { + const double *rowLower = _clp.getRowLower(); + const double *rowUpper = _clp.getRowUpper(); + + if (rowLower[id_row] <= -COIN_DBL_MAX) { + if (rowUpper[id_row] >= COIN_DBL_MAX) { + std::stringstream buffer; + buffer << "ERROR : unconstrained constraint " << id_row << " in chg_rhs."; + throw GenericSolverException(buffer.str()); + } else { + _clp.setRowUpper(id_row, val); + } + } else { + if (rowUpper[id_row] >= COIN_DBL_MAX) { + _clp.setRowLower(id_row, val); + } else { + std::stringstream buffer; + std::cout << "ERROR : constraint " << id_row + << " has both different lower and upper bound in chg_rhs."; + throw GenericSolverException(buffer.str()); + } + } +} + +void SolverClp::chg_coef(int id_row, int id_col, double val) { + CoinPackedMatrix *matrix = _clp.matrix(); + matrix->modifyCoefficient(id_row, id_col, val); +} + +void SolverClp::chg_row_name(int id_row, std::string const &name) { + std::string copy_name = name; + _clp.setRowName(id_row, copy_name); +} + +void SolverClp::chg_col_name(int id_col, std::string const &name) { + std::string copy_name = name; + _clp.setColumnName(id_col, copy_name); } /************************************************************************************************* ------------------------------ Methods to solve the problem --------------------------------- +----------------------------- Methods to solve the problem +--------------------------------- *************************************************************************************************/ -int SolverClp::solve_lp() -{ - int lp_status; - _clp.dual(); - - int clp_status = _clp.status(); - if (clp_status == CLP_OPTIMAL) - { - lp_status = OPTIMAL; - } - else if (clp_status == CLP_PRIMAL_INFEASIBLE) - { - lp_status = INFEASIBLE; - } - else if (clp_status == CLP_DUAL_INFEASIBLE) - { - lp_status = UNBOUNDED; - } - else - { - lp_status = UNKNOWN; - std::cout << "Error : UNKNOWN CLP STATUS IS : " << clp_status << std::endl; - } - return lp_status; -} - -int SolverClp::solve_mip() -{ - int lp_status; - _clp.dual(); - - int clp_status = _clp.status(); - if (clp_status == CLP_OPTIMAL) - { - lp_status = OPTIMAL; - } - else if (clp_status == CLP_PRIMAL_INFEASIBLE) - { - lp_status = INFEASIBLE; - } - else if (clp_status == CLP_DUAL_INFEASIBLE) - { - lp_status = UNBOUNDED; - } - else - { - lp_status = UNKNOWN; - std::cout << "Error : UNKNOWN CLP STATUS IS : " << clp_status << std::endl; - } - return lp_status; +int SolverClp::solve_lp() { + int lp_status; + _clp.dual(); + + int clp_status = _clp.status(); + if (clp_status == CLP_OPTIMAL) { + lp_status = OPTIMAL; + } else if (clp_status == CLP_PRIMAL_INFEASIBLE) { + lp_status = INFEASIBLE; + } else if (clp_status == CLP_DUAL_INFEASIBLE) { + lp_status = UNBOUNDED; + } else { + lp_status = UNKNOWN; + std::cout << "Error : UNKNOWN CLP STATUS IS : " << clp_status << std::endl; + } + return lp_status; +} + +int SolverClp::solve_mip() { + int lp_status; + _clp.dual(); + + int clp_status = _clp.status(); + if (clp_status == CLP_OPTIMAL) { + lp_status = OPTIMAL; + } else if (clp_status == CLP_PRIMAL_INFEASIBLE) { + lp_status = INFEASIBLE; + } else if (clp_status == CLP_DUAL_INFEASIBLE) { + lp_status = UNBOUNDED; + } else { + lp_status = UNKNOWN; + std::cout << "Error : UNKNOWN CLP STATUS IS : " << clp_status << std::endl; + } + return lp_status; } /************************************************************************************************* -------------------------- Methods to get solutions information ----------------------------- +------------------------- Methods to get solutions information +----------------------------- *************************************************************************************************/ -void SolverClp::get_basis(int *rstatus, int *cstatus) const -{ - int ncols = get_ncols(); - for (int i = 0; i < ncols; i++) - { - cstatus[i] = _clp.getColumnStatus(i); - } +void SolverClp::get_basis(int *rstatus, int *cstatus) const { + int ncols = get_ncols(); + for (int i = 0; i < ncols; i++) { + cstatus[i] = _clp.getColumnStatus(i); + } - int nrows = get_nrows(); - for (int i = 0; i < nrows; i++) - { - rstatus[i] = _clp.getRowStatus(i); - } + int nrows = get_nrows(); + for (int i = 0; i < nrows; i++) { + rstatus[i] = _clp.getRowStatus(i); + } } -double SolverClp::get_mip_value() const -{ - return _clp.objectiveValue(); -} +double SolverClp::get_mip_value() const { return _clp.objectiveValue(); } -double SolverClp::get_lp_value() const -{ - return _clp.objectiveValue(); -} +double SolverClp::get_lp_value() const { return _clp.objectiveValue(); } -int SolverClp::get_splex_num_of_ite_last() const -{ - return _clp.numberIterations(); +int SolverClp::get_splex_num_of_ite_last() const { + return _clp.numberIterations(); } void SolverClp::get_lp_sol(double *primals, double *duals, - double *reduced_costs) -{ - if (primals != NULL) - { - double *primalSol = _clp.primalColumnSolution(); - for (int i(0); i < get_ncols(); i++) - { - primals[i] = primalSol[i]; - } - } - - if (duals != NULL) - { - double *dualSol = _clp.dualRowSolution(); - for (int i(0); i < get_nrows(); i++) - { - duals[i] = dualSol[i]; - } - } - - if (reduced_costs != NULL) - { - double *reducedCostSolution = _clp.dualColumnSolution(); - for (int i(0); i < get_ncols(); i++) - { - reduced_costs[i] = reducedCostSolution[i]; - // std::cout << "RD " << i << " " << reducedCostSolution[i] << std::endl; - } - } -} - -void SolverClp::get_mip_sol(double *primals) -{ - if (primals != NULL) - { - double *primalSol = _clp.primalColumnSolution(); - for (int i(0); i < get_ncols(); i++) - { - primals[i] = primalSol[i]; - } - } + double *reduced_costs) { + if (primals != NULL) { + double *primalSol = _clp.primalColumnSolution(); + for (int i(0); i < get_ncols(); i++) { + primals[i] = primalSol[i]; + } + } + + if (duals != NULL) { + double *dualSol = _clp.dualRowSolution(); + for (int i(0); i < get_nrows(); i++) { + duals[i] = dualSol[i]; + } + } + + if (reduced_costs != NULL) { + double *reducedCostSolution = _clp.dualColumnSolution(); + for (int i(0); i < get_ncols(); i++) { + reduced_costs[i] = reducedCostSolution[i]; + // std::cout << "RD " << i << " " << reducedCostSolution[i] << + // std::endl; + } + } +} + +void SolverClp::get_mip_sol(double *primals) { + if (primals != NULL) { + double *primalSol = _clp.primalColumnSolution(); + for (int i(0); i < get_ncols(); i++) { + primals[i] = primalSol[i]; + } + } } /************************************************************************************************* ------------------------- Methods to set algorithm or logs levels --------------------------- +------------------------ Methods to set algorithm or logs levels +--------------------------- *************************************************************************************************/ -void SolverClp::set_output_log_level(int loglevel) -{ - _clp.passInMessageHandler(&_message_handler); - if (loglevel > 0) - { - _message_handler.setLogLevel(1); - } - else - { - _message_handler.setLogLevel(0); - } -} - -void SolverClp::set_algorithm(std::string const &algo) -{ - if (algo == "DUAL") - { - _clp.setAlgorithm(1); - } - else - { - throw InvalidSolverOptionException("set_algorithm : " + algo); - } -} - -void SolverClp::set_threads(int n_threads) -{ - _clp.setNumberThreads(n_threads); -} - -void SolverClp::set_optimality_gap(double gap) -{ - throw InvalidSolverOptionException("set_optimality_gap : " + std::to_string(gap)); -} - -void SolverClp::set_simplex_iter(int iter) -{ - _clp.setMaximumIterations(iter); -} \ No newline at end of file +void SolverClp::set_output_log_level(int loglevel) { + _clp.passInMessageHandler(&_message_handler); + if (loglevel > 0) { + _message_handler.setLogLevel(1); + } else { + _message_handler.setLogLevel(0); + } +} + +void SolverClp::set_algorithm(std::string const &algo) { + if (algo == "DUAL") { + _clp.setAlgorithm(1); + } else { + throw InvalidSolverOptionException("set_algorithm : " + algo); + } +} + +void SolverClp::set_threads(int n_threads) { _clp.setNumberThreads(n_threads); } + +void SolverClp::set_optimality_gap(double gap) { + throw InvalidSolverOptionException("set_optimality_gap : " + + std::to_string(gap)); +} + +void SolverClp::set_simplex_iter(int iter) { _clp.setMaximumIterations(iter); } \ No newline at end of file diff --git a/src/cpp/multisolver_interface/SolverClp.h b/src/cpp/multisolver_interface/SolverClp.h index f3d911a7e..7e33f1dbf 100644 --- a/src/cpp/multisolver_interface/SolverClp.h +++ b/src/cpp/multisolver_interface/SolverClp.h @@ -1,169 +1,178 @@ #pragma once -#include "multisolver_interface/SolverAbstract.h" #include "ClpSimplex.hpp" - #include "CoinHelperFunctions.hpp" #include "CoinIndexedVector.hpp" +#include "multisolver_interface/SolverAbstract.h" -enum CLP_STATUS -{ - CLP_OPTIMAL, - CLP_PRIMAL_INFEASIBLE, - CLP_DUAL_INFEASIBLE, - CLP_STOPPED, - CLP_ERRORED +enum CLP_STATUS { + CLP_OPTIMAL, + CLP_PRIMAL_INFEASIBLE, + CLP_DUAL_INFEASIBLE, + CLP_STOPPED, + CLP_ERRORED }; /*! * \class class SolverXpress * \brief Daughter class of AsbtractSolver implementing solver XPRESS FICO */ -class SolverClp : public SolverAbstract -{ - - /************************************************************************************************* - ---------------------------------------- ATTRIBUTES --------------------------------------- - *************************************************************************************************/ - static int _NumberOfProblems; /*!< Counter of the total number of Cplex problems - declared to set or end the environment */ -public: - ClpSimplex _clp; - CoinMessageHandler _message_handler; - - /************************************************************************************************* - ----------------------------------- Constructor/Desctructor -------------------------------- - *************************************************************************************************/ -public: - /** - * @brief Default constructor of a CLP solver - */ - SolverClp(); - - /** - * @brief Copy constructor of CLP, copy the problem toCopy in memory and name it "name" - * - * @param toCopy : Pointer to an AbstractSolver object, containing a CLP solver to copy - */ - SolverClp(const SolverAbstract::Ptr toCopy); - - virtual ~SolverClp(); - virtual int get_number_of_instances() override; - - virtual std::string get_solver_name() const override { return "CLP"; } - - /************************************************************************************************* - --------------------------------- Output and stream management ----------------------------- - *************************************************************************************************/ - - /************************************************************************************************* - ------ Destruction or creation of inner strctures and datas, closing environments ---------- - *************************************************************************************************/ -public: - virtual void init() override; - virtual void free() override; - - /************************************************************************************************* - ------------------------------- Reading & Writing problems ------------------------------- - *************************************************************************************************/ -public: - virtual void write_prob_mps(const std::string &filename) override; - virtual void write_prob_lp(const std::string &filename) override; - - virtual void read_prob_mps(const std::string &filename) override; - virtual void read_prob_lp(const std::string &filename) override; - - virtual void copy_prob(const SolverAbstract::Ptr fictif_solv) override; - - /************************************************************************************************* - ----------------------- Get general informations about problem ---------------------------- - *************************************************************************************************/ -public: - virtual int get_ncols() const override; - virtual int get_nrows() const override; - virtual int get_nelems() const override; - virtual int get_n_integer_vars() const override; - virtual void get_obj(double *obj, int first, int last) const override; - virtual void get_rows(int *mstart, int *mclind, double *dmatval, int size, int *nels, - int first, int last) const override; - virtual void get_row_type(char *qrtype, int first, int last) const override; - virtual void get_rhs(double *rhs, int first, int last) const override; - virtual void get_rhs_range(double *range, int first, int last) const override; - virtual void get_col_type(char *coltype, int first, int last) const override; - virtual void get_lb(double *lb, int fisrt, int last) const override; - virtual void get_ub(double *ub, int fisrt, int last) const override; - - virtual int get_row_index(std::string const &name) const override; - virtual int get_col_index(std::string const &name) const override; - virtual std::vector get_row_names(int first, int last) override; - virtual std::vector get_col_names(int first, int last) override; - - /************************************************************************************************* - ------------------------------ Methods to modify problem ---------------------------------- - *************************************************************************************************/ -public: - virtual void del_rows(int first, int last) override; - virtual void add_rows(int newrows, int newnz, const char *qrtype, const double *rhs, - const double *range, const int *mstart, const int *mclind, - const double *dmatval) override; - virtual void add_cols(int newcol, int newnz, const double *objx, const int *mstart, - const int *mrwind, const double *dmatval, const double *bdl, - const double *bdu) override; - virtual void add_name(int type, const char *cnames, int indice) override; - virtual void chg_obj(const std::vector &mindex, const std::vector &obj) override; - virtual void chg_bounds(const std::vector &mindex, const std::vector &qbtype, const std::vector &bnd); - virtual void chg_col_type(const std::vector &mindex, const std::vector &qctype) override; - virtual void chg_rhs(int id_row, double val) override; - virtual void chg_coef(int id_row, int id_col, double val) override; - virtual void chg_row_name(int id_row, std::string const &name) override; - virtual void chg_col_name(int id_col, std::string const &name) override; - - /************************************************************************************************* - ----------------------------- Methods to solve the problem --------------------------------- - *************************************************************************************************/ -public: - virtual int solve_lp() override; - virtual int solve_mip() override; - - /************************************************************************************************* - ------------------------- Methods to get solutions information ----------------------------- - *************************************************************************************************/ -public: - /** - * @brief Returns the current basis into the user’s data arrays. - * - * @param rstatus : Integer array of length ROWS to the basis status of the slack, surplus or - artifficial variable associated with each row. The status will be one of: - 0 slack, surplus or artifficial is free; - 1 slack, surplus or artifficial is basic; - 2 slack, surplus or artifficial is at upper bound; - 3 slack, surplus or artifficial is at lower bound; - 4 slack, surplus or artifficial is super basic. - May be NULL if not required. - * @param cstatus : Integer array of length COLS to hold the basis status of the columns - in the constraint matrix. The status will be one of: - 0 variable is free; - 1 variable is basic; - 2 variable is at upper bound; - 3 variable is at lower bound; - 4 variable is super basic - May be NULL if not required. - */ - virtual void get_basis(int *rstatus, int *cstatus) const override; - virtual double get_mip_value() const override; - virtual double get_lp_value() const override; - virtual int get_splex_num_of_ite_last() const override; - virtual void get_lp_sol(double *primals, double *duals, - double *reduced_costs) override; - virtual void get_mip_sol(double *primals) override; - - /************************************************************************************************* - ------------------------ Methods to set algorithm or logs levels --------------------------- - *************************************************************************************************/ -public: - virtual void set_output_log_level(int loglevel) override; - 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; - virtual void set_simplex_iter(int iter) override; +class SolverClp : public SolverAbstract { + /************************************************************************************************* + ---------------------------------------- ATTRIBUTES + --------------------------------------- + *************************************************************************************************/ + static int _NumberOfProblems; /*!< Counter of the total number of Cplex + problems declared to set or end the + environment */ + public: + ClpSimplex _clp; + CoinMessageHandler _message_handler; + + /************************************************************************************************* + ----------------------------------- Constructor/Desctructor + -------------------------------- + *************************************************************************************************/ + public: + /** + * @brief Default constructor of a CLP solver + */ + SolverClp(); + + /** + * @brief Copy constructor of CLP, copy the problem toCopy in memory and name + * it "name" + * + * @param toCopy : Pointer to an AbstractSolver object, containing a CLP + * solver to copy + */ + SolverClp(const SolverAbstract::Ptr toCopy); + + virtual ~SolverClp(); + virtual int get_number_of_instances() override; + + virtual std::string get_solver_name() const override { return "CLP"; } + + /************************************************************************************************* + --------------------------------- Output and stream management + ----------------------------- + *************************************************************************************************/ + + /************************************************************************************************* + ------ Destruction or creation of inner strctures and datas, closing + environments ---------- + *************************************************************************************************/ + public: + virtual void init() override; + virtual void free() override; + + /************************************************************************************************* + ------------------------------- Reading & Writing problems + ------------------------------- + *************************************************************************************************/ + public: + virtual void write_prob_mps(const std::string &filename) override; + virtual void write_prob_lp(const std::string &filename) override; + + virtual void read_prob_mps(const std::string &filename) override; + virtual void read_prob_lp(const std::string &filename) override; + + virtual void copy_prob(const SolverAbstract::Ptr fictif_solv) override; + + /************************************************************************************************* + ----------------------- Get general informations about problem + ---------------------------- + *************************************************************************************************/ + public: + virtual int get_ncols() const override; + virtual int get_nrows() const override; + virtual int get_nelems() const override; + virtual int get_n_integer_vars() const override; + virtual void get_obj(double *obj, int first, int last) const override; + virtual void get_rows(int *mstart, int *mclind, double *dmatval, int size, + int *nels, int first, int last) const override; + virtual void get_row_type(char *qrtype, int first, int last) const override; + virtual void get_rhs(double *rhs, int first, int last) const override; + virtual void get_rhs_range(double *range, int first, int last) const override; + virtual void get_col_type(char *coltype, int first, int last) const override; + virtual void get_lb(double *lb, int fisrt, int last) const override; + virtual void get_ub(double *ub, int fisrt, int last) const override; + + virtual int get_row_index(std::string const &name) const override; + virtual int get_col_index(std::string const &name) const override; + virtual std::vector get_row_names(int first, int last) override; + virtual std::vector get_col_names(int first, int last) override; + + /************************************************************************************************* + ------------------------------ Methods to modify problem + ---------------------------------- + *************************************************************************************************/ + public: + virtual void del_rows(int first, int last) override; + virtual void add_rows(int newrows, int newnz, const char *qrtype, + const double *rhs, const double *range, + const int *mstart, const int *mclind, + const double *dmatval) override; + virtual void add_cols(int newcol, int newnz, const double *objx, + const int *mstart, const int *mrwind, + const double *dmatval, const double *bdl, + const double *bdu) override; + virtual void add_name(int type, const char *cnames, int indice) override; + virtual void chg_obj(const std::vector &mindex, + const std::vector &obj) override; + virtual void chg_bounds(const std::vector &mindex, + const std::vector &qbtype, + const std::vector &bnd); + virtual void chg_col_type(const std::vector &mindex, + const std::vector &qctype) override; + virtual void chg_rhs(int id_row, double val) override; + virtual void chg_coef(int id_row, int id_col, double val) override; + virtual void chg_row_name(int id_row, std::string const &name) override; + virtual void chg_col_name(int id_col, std::string const &name) override; + + /************************************************************************************************* + ----------------------------- Methods to solve the problem + --------------------------------- + *************************************************************************************************/ + public: + virtual int solve_lp() override; + virtual int solve_mip() override; + + /************************************************************************************************* + ------------------------- Methods to get solutions information + ----------------------------- + *************************************************************************************************/ + public: + /** + * @brief Returns the current basis into the user’s data arrays. + * + * @param rstatus : Integer array of length ROWS to the basis status of the + slack, surplus or artifficial variable associated with each row. The status + will be one of: 0 slack, surplus or artifficial is free; 1 slack, surplus or + artifficial is basic; 2 slack, surplus or artifficial is at upper bound; 3 + slack, surplus or artifficial is at lower bound; 4 slack, surplus or + artifficial is super basic. May be NULL if not required. + * @param cstatus : Integer array of length COLS to hold the basis status of + the columns in the constraint matrix. The status will be one of: 0 variable is + free; 1 variable is basic; 2 variable is at upper bound; 3 variable is at + lower bound; 4 variable is super basic May be NULL if not required. + */ + virtual void get_basis(int *rstatus, int *cstatus) const override; + virtual double get_mip_value() const override; + virtual double get_lp_value() const override; + virtual int get_splex_num_of_ite_last() const override; + virtual void get_lp_sol(double *primals, double *duals, + double *reduced_costs) override; + virtual void get_mip_sol(double *primals) override; + + /************************************************************************************************* + ------------------------ Methods to set algorithm or logs levels + --------------------------- + *************************************************************************************************/ + public: + virtual void set_output_log_level(int loglevel) override; + 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; + virtual void set_simplex_iter(int iter) override; }; \ No newline at end of file diff --git a/src/cpp/multisolver_interface/SolverCplex.cpp b/src/cpp/multisolver_interface/SolverCplex.cpp index bdcc6834b..cc8b701b7 100644 --- a/src/cpp/multisolver_interface/SolverCplex.cpp +++ b/src/cpp/multisolver_interface/SolverCplex.cpp @@ -1,590 +1,510 @@ -#include - #include "SolverCplex.h" +#include + /************************************************************************************************* ------------------------------------ Constructor/Desctructor -------------------------------- +----------------------------------- Constructor/Desctructor +-------------------------------- *************************************************************************************************/ int SolverCplex::_NumberOfProblems = 0; -SolverCplex::SolverCplex() -{ - int status(0); +SolverCplex::SolverCplex() { + int status(0); - // Openning CPLEX environment - _env = CPXopenCPLEX(&status); - zero_status_check(status, "open CPLEX"); + // Openning CPLEX environment + _env = CPXopenCPLEX(&status); + zero_status_check(status, "open CPLEX"); - _prb = NULL; + _prb = NULL; - _NumberOfProblems += 1; + _NumberOfProblems += 1; } -SolverCplex::SolverCplex(const std::string &name) -{ - int status(0); +SolverCplex::SolverCplex(const std::string &name) { + int status(0); - // Openning CPLEX environment - _env = CPXopenCPLEX(&status); - zero_status_check(status, "open CPLEX"); + // Openning CPLEX environment + _env = CPXopenCPLEX(&status); + zero_status_check(status, "open CPLEX"); - // Creating empty problem - _prb = CPXcreateprob(_env, &status, name.c_str()); - zero_status_check(status, "create problem"); + // Creating empty problem + _prb = CPXcreateprob(_env, &status, name.c_str()); + zero_status_check(status, "create problem"); - _NumberOfProblems += 1; + _NumberOfProblems += 1; } -SolverCplex::SolverCplex(const SolverAbstract::Ptr fictif) -{ - int status(0); +SolverCplex::SolverCplex(const SolverAbstract::Ptr fictif) { + int status(0); - // Openning CPLEX environment - _env = CPXopenCPLEX(&status); - zero_status_check(status, "open CPLEX"); + // Openning CPLEX environment + _env = CPXopenCPLEX(&status); + zero_status_check(status, "open CPLEX"); - // Try to cast the solver in fictif to a SolverCPLEX - if (SolverCplex *c = dynamic_cast(fictif.get())) - { - _prb = CPXcloneprob(_env, c->_prb, &status); - zero_status_check(status, "create problem"); + // Try to cast the solver in fictif to a SolverCPLEX + if (SolverCplex *c = dynamic_cast(fictif.get())) { + _prb = CPXcloneprob(_env, c->_prb, &status); + zero_status_check(status, "create problem"); - _NumberOfProblems += 1; - } - else - { - throw InvalidSolverForCopyException(fictif->get_solver_name(), get_solver_name()); - } + _NumberOfProblems += 1; + } else { + throw InvalidSolverForCopyException(fictif->get_solver_name(), + get_solver_name()); + } } -SolverCplex::~SolverCplex() -{ - _NumberOfProblems -= 1; - free(); +SolverCplex::~SolverCplex() { + _NumberOfProblems -= 1; + free(); - if (_NumberOfProblems == 0) - { - int status = CPXcloseCPLEX(&_env); - zero_status_check(status, "close CPLEX environment"); - } + if (_NumberOfProblems == 0) { + int status = CPXcloseCPLEX(&_env); + zero_status_check(status, "close CPLEX environment"); + } } -int SolverCplex::get_number_of_instances() -{ - return _NumberOfProblems; -} +int SolverCplex::get_number_of_instances() { return _NumberOfProblems; } /************************************************************************************************* ------------------------------------ Output stream management ------------------------------ +----------------------------------- Output stream management +------------------------------ *************************************************************************************************/ /************************************************************************************************* ------------- Destruction of inner strctures and datas, closing environments --------------- +------------ Destruction of inner strctures and datas, closing environments +--------------- *************************************************************************************************/ -void SolverCplex::init() -{ - // Creating empty problem - int status = 0; - const std::string name = "DefaultProblem_" + std::to_string(_NumberOfProblems); - _prb = CPXcreateprob(_env, &status, name.c_str()); - zero_status_check(status, "create problem"); +void SolverCplex::init() { + // Creating empty problem + int status = 0; + const std::string name = + "DefaultProblem_" + std::to_string(_NumberOfProblems); + _prb = CPXcreateprob(_env, &status, name.c_str()); + zero_status_check(status, "create problem"); } -void SolverCplex::free() -{ - int status(0); - status = CPXfreeprob(_env, &_prb); - zero_status_check(status, "free problem in memory"); +void SolverCplex::free() { + int status(0); + status = CPXfreeprob(_env, &_prb); + zero_status_check(status, "free problem in memory"); } /************************************************************************************************* -------------------------------- Reading & Writing problems ------------------------------- +------------------------------- Reading & Writing problems +------------------------------- *************************************************************************************************/ -void SolverCplex::write_prob_mps(const std::string &filename) -{ - std::string cplexFlags = "MPS"; - CPXwriteprob(_env, _prb, filename.c_str(), cplexFlags.c_str()); +void SolverCplex::write_prob_mps(const std::string &filename) { + std::string cplexFlags = "MPS"; + CPXwriteprob(_env, _prb, filename.c_str(), cplexFlags.c_str()); } -void SolverCplex::write_prob_lp(const std::string &filename) -{ - std::string cplexFlags = "LP"; - CPXwriteprob(_env, _prb, filename.c_str(), cplexFlags.c_str()); +void SolverCplex::write_prob_lp(const std::string &filename) { + std::string cplexFlags = "LP"; + CPXwriteprob(_env, _prb, filename.c_str(), cplexFlags.c_str()); } -void SolverCplex::read_prob_mps(const std::string &filename) -{ - std::string cplexFlags = "MPS"; - int status = CPXreadcopyprob(_env, _prb, filename.c_str(), cplexFlags.c_str()); - zero_status_check(status, "read problem"); +void SolverCplex::read_prob_mps(const std::string &filename) { + std::string cplexFlags = "MPS"; + int status = + CPXreadcopyprob(_env, _prb, filename.c_str(), cplexFlags.c_str()); + zero_status_check(status, "read problem"); } -void SolverCplex::read_prob_lp(const std::string &filename) -{ - std::string cplexFlags = "LP"; - int status = CPXreadcopyprob(_env, _prb, filename.c_str(), cplexFlags.c_str()); - zero_status_check(status, "read problem"); +void SolverCplex::read_prob_lp(const std::string &filename) { + std::string cplexFlags = "LP"; + int status = + CPXreadcopyprob(_env, _prb, filename.c_str(), cplexFlags.c_str()); + zero_status_check(status, "read problem"); } -void SolverCplex::copy_prob(const SolverAbstract::Ptr fictif_solv) -{ -} +void SolverCplex::copy_prob(const SolverAbstract::Ptr fictif_solv) {} /************************************************************************************************* ------------------------ Get general informations about problem ---------------------------- +----------------------- Get general informations about problem +---------------------------- *************************************************************************************************/ -int SolverCplex::get_ncols() const -{ - int cols(0); - cols = CPXgetnumcols(_env, _prb); - return cols; +int SolverCplex::get_ncols() const { + int cols(0); + cols = CPXgetnumcols(_env, _prb); + return cols; } -int SolverCplex::get_nrows() const -{ - int rows(0); - rows = CPXgetnumrows(_env, _prb); - return rows; +int SolverCplex::get_nrows() const { + int rows(0); + rows = CPXgetnumrows(_env, _prb); + return rows; } -int SolverCplex::get_nelems() const -{ - int elems = CPXgetnumnz(_env, _prb); - return elems; +int SolverCplex::get_nelems() const { + int elems = CPXgetnumnz(_env, _prb); + return elems; } -int SolverCplex::get_n_integer_vars() const -{ - int n_int_vars = CPXgetnumint(_env, _prb); - int n_bin_vars = CPXgetnumbin(_env, _prb); - return n_int_vars + n_bin_vars; +int SolverCplex::get_n_integer_vars() const { + int n_int_vars = CPXgetnumint(_env, _prb); + int n_bin_vars = CPXgetnumbin(_env, _prb); + return n_int_vars + n_bin_vars; } -void SolverCplex::get_obj(double *obj, int first, int last) const -{ - int status = CPXgetobj(_env, _prb, obj, first, last); - zero_status_check(status, "get obj"); +void SolverCplex::get_obj(double *obj, int first, int last) const { + int status = CPXgetobj(_env, _prb, obj, first, last); + zero_status_check(status, "get obj"); } -void SolverCplex::get_rows(int *mstart, int *mclind, double *dmatval, int size, int *nels, - int first, int last) const -{ - std::vector surplus(1); - int status = CPXgetrows(_env, _prb, nels, mstart, mclind, dmatval, size, surplus.data(), first, last); - zero_status_check(status, "get rows"); +void SolverCplex::get_rows(int *mstart, int *mclind, double *dmatval, int size, + int *nels, int first, int last) const { + std::vector surplus(1); + int status = CPXgetrows(_env, _prb, nels, mstart, mclind, dmatval, size, + surplus.data(), first, last); + zero_status_check(status, "get rows"); - // As other solvers adds the last element in mstart - mstart[last - first + 1] = size; + // As other solvers adds the last element in mstart + mstart[last - first + 1] = size; } -void SolverCplex::get_row_type(char *qrtype, int first, int last) const -{ - int status = CPXgetsense(_env, _prb, qrtype, first, last); - zero_status_check(status, "get row type"); +void SolverCplex::get_row_type(char *qrtype, int first, int last) const { + int status = CPXgetsense(_env, _prb, qrtype, first, last); + zero_status_check(status, "get row type"); } -void SolverCplex::get_rhs(double *rhs, int first, int last) const -{ - int status = CPXgetrhs(_env, _prb, rhs, first, last); - zero_status_check(status, "get rhs"); +void SolverCplex::get_rhs(double *rhs, int first, int last) const { + int status = CPXgetrhs(_env, _prb, rhs, first, last); + zero_status_check(status, "get rhs"); } -void SolverCplex::get_rhs_range(double *range, int first, int last) const -{ - int status = CPXgetrngval(_env, _prb, range, first, last); - zero_status_check(status, "get rhs range"); +void SolverCplex::get_rhs_range(double *range, int first, int last) const { + int status = CPXgetrngval(_env, _prb, range, first, last); + zero_status_check(status, "get rhs range"); } -void SolverCplex::get_col_type(char *coltype, int first, int last) const -{ - // Declaration en MIP pour creer les types de variables dans la memoire (CPLEX) - CPXchgprobtype(_env, _prb, CPXPROB_MILP); +void SolverCplex::get_col_type(char *coltype, int first, int last) const { + // Declaration en MIP pour creer les types de variables dans la memoire + // (CPLEX) + CPXchgprobtype(_env, _prb, CPXPROB_MILP); - int status = CPXgetctype(_env, _prb, coltype, first, last); - zero_status_check(status, "get col type"); + int status = CPXgetctype(_env, _prb, coltype, first, last); + zero_status_check(status, "get col type"); } -void SolverCplex::get_lb(double *lb, int first, int last) const -{ - int status = CPXgetlb(_env, _prb, lb, first, last); - zero_status_check(status, "get lb"); +void SolverCplex::get_lb(double *lb, int first, int last) const { + int status = CPXgetlb(_env, _prb, lb, first, last); + zero_status_check(status, "get lb"); } -void SolverCplex::get_ub(double *ub, int first, int last) const -{ - int status = CPXgetub(_env, _prb, ub, first, last); - zero_status_check(status, "get ub"); +void SolverCplex::get_ub(double *ub, int first, int last) const { + int status = CPXgetub(_env, _prb, ub, first, last); + zero_status_check(status, "get ub"); } -int SolverCplex::get_row_index(std::string const &name) const -{ - int id; - int status = CPXgetrowindex(_env, _prb, name.c_str(), &id); - zero_status_check(status, "get row index"); - return id; +int SolverCplex::get_row_index(std::string const &name) const { + int id; + int status = CPXgetrowindex(_env, _prb, name.c_str(), &id); + zero_status_check(status, "get row index"); + return id; } -int SolverCplex::get_col_index(std::string const &name) const -{ - int id; - int status = CPXgetcolindex(_env, _prb, name.c_str(), &id); - zero_status_check(status, "get col index"); - return id; +int SolverCplex::get_col_index(std::string const &name) const { + int id; + int status = CPXgetcolindex(_env, _prb, name.c_str(), &id); + zero_status_check(status, "get col index"); + return id; } -std::vector SolverCplex::get_row_names(int first, int last) -{ - std::vector names; - names.reserve(1 + last - first); +std::vector SolverCplex::get_row_names(int first, int last) { + std::vector names; + names.reserve(1 + last - first); - int status = 0; - const int charSize = 100; - char cur_name[charSize]; - std::vector namesPtr(charSize); - for (int i = 0; i < last - first + 1; i++) - { - int status = CPXgetrowname(_env, _prb, namesPtr.data(), cur_name, charSize, - NULL, i + first, i + first); - zero_status_check(status, "get row name"); - names.push_back(cur_name); - memset(cur_name, 0, 100); - } + int status = 0; + const int charSize = 100; + char cur_name[charSize]; + std::vector namesPtr(charSize); + for (int i = 0; i < last - first + 1; i++) { + int status = CPXgetrowname(_env, _prb, namesPtr.data(), cur_name, charSize, + NULL, i + first, i + first); + zero_status_check(status, "get row name"); + names.push_back(cur_name); + memset(cur_name, 0, 100); + } - return names; + return names; } -std::vector SolverCplex::get_col_names(int first, int last, std::vector &names) -{ - std::vector names; - names.reserve(1 + last - first); +std::vector SolverCplex::get_col_names( + int first, int last, std::vector &names) { + std::vector names; + names.reserve(1 + last - first); - const int charSize = 100; - char cur_name[charSize]; - std::vector namesPtr(charSize); - for (int i = 0; i < last - first + 1; i++) - { - int status = CPXgetcolname(_env, _prb, namesPtr.data(), cur_name, charSize, - NULL, i + first, i + first); - zero_status_check(status, "get column name"); - names.push_back(cur_name); - memset(cur_name, 0, 100); - } + const int charSize = 100; + char cur_name[charSize]; + std::vector namesPtr(charSize); + for (int i = 0; i < last - first + 1; i++) { + int status = CPXgetcolname(_env, _prb, namesPtr.data(), cur_name, charSize, + NULL, i + first, i + first); + zero_status_check(status, "get column name"); + names.push_back(cur_name); + memset(cur_name, 0, 100); + } - return names; + return names; } /************************************************************************************************* ------------------------------- Methods to modify problem ---------------------------------- +------------------------------ Methods to modify problem +---------------------------------- *************************************************************************************************/ -void SolverCplex::del_rows(int first, int last) -{ - int status = CPXdelrows(_env, _prb, first, last); - zero_status_check(status, "delete rows"); -} - -void SolverCplex::add_rows(int newrows, int newnz, const char *qrtype, const double *rhs, - const double *range, const int *mstart, const int *mclind, - const double *dmatval) -{ - int status = CPXaddrows(_env, _prb, 0, newrows, newnz, rhs, qrtype, mstart, - mclind, dmatval, NULL, NULL); - zero_status_check(status, "add rows"); -} - -void SolverCplex::add_cols(int newcol, int newnz, const double *objx, const int *mstart, - const int *mrwind, const double *dmatval, const double *bdl, - const double *bdu) -{ - int status = CPXaddcols(_env, _prb, newcol, newnz, objx, mstart, mrwind, - dmatval, bdl, bdu, NULL); - zero_status_check(status, "add cols"); -} - -void SolverCplex::add_name(int type, const char *cnames, int indice) -{ - if (type == 1) - { - // ROW - type = 'r'; - } - else if (type == 2) - { - // COLUMN - type = 'c'; - } - else - { - std::stringstream buffer; - buffer << "ERROR : wrong type sent to add_name"; - throw GenericSolverException(buffer.str()); - } - int status = CPXchgname(_env, _prb, type, indice, cnames); - zero_status_check(status, "add name"); -} - -void SolverCplex::chg_obj(const std::vector &mindex, const std::vector &obj) -{ - assert(obj.size() == mindex.size()); - int status = CPXchgobj(_env, _prb, obj.size(), mindex.data(), obj.data()); - zero_status_check(status, "change obj"); -} - -void SolverCplex::chg_bounds(const std::vector &mindex, const std::vector &qbtype, const std::vector &bnd) -{ - assert(qbtype.size() == mindex.size()); - assert(bnd.size() == mindex.size()); - int status = CPXchgbds(_env, _prb, mindex.size(), mindex.data(), qbtype.data(), bnd.data()); - zero_status_check(status, "change bounds"); -} - -void SolverCplex::chg_col_type(const std::vector &mindex, const std::vector &qctype) -{ - assert(qctype.size() == mindex.size()); - int status = CPXchgctype(_env, _prb, mindex.size(), mindex.data(), qctype.data()); - zero_status_check(status, "change col type"); - if (get_n_integer_vars() == 0) - { - int status = CPXchgprobtype(_env, _prb, CPXPROB_LP); - zero_status_check(status, "change prob type after change col type"); - } -} - -void SolverCplex::chg_rhs(int id_row, double val) -{ - int ids[1]; - ids[0] = id_row; - double vals[1]; - vals[0] = val; - int status = CPXchgrhs(_env, _prb, 1, ids, vals); - zero_status_check(status, "change rhs"); -} - -void SolverCplex::chg_coef(int id_row, int id_col, double val) -{ - int status = CPXchgcoef(_env, _prb, id_row, id_col, val); - zero_status_check(status, "change coef"); -} - -void SolverCplex::chg_row_name(int id_row, std::string const &name) -{ - const std::vector indices(1, id_row); - - std::vector nameVec(1); - char nameToChar[100]; - memset(nameToChar, 0, sizeof(nameToChar)); - for (int i(0); i < name.size(); i++) - { - nameToChar[i] = name[i]; - } - nameVec[0] = nameToChar; - - int status = CPXchgrowname(_env, _prb, 1, indices.data(), nameVec.data()); - zero_status_check(status, "Set row name"); -} - -void SolverCplex::chg_col_name(int id_col, std::string const &name) -{ - const std::vector indices(1, id_col); - - std::vector nameVec(1); - char nameToChar[100]; - memset(nameToChar, 0, sizeof(nameToChar)); - for (int i(0); i < name.size(); i++) - { - nameToChar[i] = name[i]; - } - nameVec[0] = nameToChar; - int status = CPXchgcolname(_env, _prb, 1, indices.data(), nameVec.data()); - zero_status_check(status, "Set col name"); +void SolverCplex::del_rows(int first, int last) { + int status = CPXdelrows(_env, _prb, first, last); + zero_status_check(status, "delete rows"); +} + +void SolverCplex::add_rows(int newrows, int newnz, const char *qrtype, + const double *rhs, const double *range, + const int *mstart, const int *mclind, + const double *dmatval) { + int status = CPXaddrows(_env, _prb, 0, newrows, newnz, rhs, qrtype, mstart, + mclind, dmatval, NULL, NULL); + zero_status_check(status, "add rows"); +} + +void SolverCplex::add_cols(int newcol, int newnz, const double *objx, + const int *mstart, const int *mrwind, + const double *dmatval, const double *bdl, + const double *bdu) { + int status = CPXaddcols(_env, _prb, newcol, newnz, objx, mstart, mrwind, + dmatval, bdl, bdu, NULL); + zero_status_check(status, "add cols"); +} + +void SolverCplex::add_name(int type, const char *cnames, int indice) { + if (type == 1) { + // ROW + type = 'r'; + } else if (type == 2) { + // COLUMN + type = 'c'; + } else { + std::stringstream buffer; + buffer << "ERROR : wrong type sent to add_name"; + throw GenericSolverException(buffer.str()); + } + int status = CPXchgname(_env, _prb, type, indice, cnames); + zero_status_check(status, "add name"); +} + +void SolverCplex::chg_obj(const std::vector &mindex, + const std::vector &obj) { + assert(obj.size() == mindex.size()); + int status = CPXchgobj(_env, _prb, obj.size(), mindex.data(), obj.data()); + zero_status_check(status, "change obj"); +} + +void SolverCplex::chg_bounds(const std::vector &mindex, + const std::vector &qbtype, + const std::vector &bnd) { + assert(qbtype.size() == mindex.size()); + assert(bnd.size() == mindex.size()); + int status = CPXchgbds(_env, _prb, mindex.size(), mindex.data(), + qbtype.data(), bnd.data()); + zero_status_check(status, "change bounds"); +} + +void SolverCplex::chg_col_type(const std::vector &mindex, + const std::vector &qctype) { + assert(qctype.size() == mindex.size()); + int status = + CPXchgctype(_env, _prb, mindex.size(), mindex.data(), qctype.data()); + zero_status_check(status, "change col type"); + if (get_n_integer_vars() == 0) { + int status = CPXchgprobtype(_env, _prb, CPXPROB_LP); + zero_status_check(status, "change prob type after change col type"); + } +} + +void SolverCplex::chg_rhs(int id_row, double val) { + int ids[1]; + ids[0] = id_row; + double vals[1]; + vals[0] = val; + int status = CPXchgrhs(_env, _prb, 1, ids, vals); + zero_status_check(status, "change rhs"); +} + +void SolverCplex::chg_coef(int id_row, int id_col, double val) { + int status = CPXchgcoef(_env, _prb, id_row, id_col, val); + zero_status_check(status, "change coef"); +} + +void SolverCplex::chg_row_name(int id_row, std::string const &name) { + const std::vector indices(1, id_row); + + std::vector nameVec(1); + char nameToChar[100]; + memset(nameToChar, 0, sizeof(nameToChar)); + for (int i(0); i < name.size(); i++) { + nameToChar[i] = name[i]; + } + nameVec[0] = nameToChar; + + int status = CPXchgrowname(_env, _prb, 1, indices.data(), nameVec.data()); + zero_status_check(status, "Set row name"); +} + +void SolverCplex::chg_col_name(int id_col, std::string const &name) { + const std::vector indices(1, id_col); + + std::vector nameVec(1); + char nameToChar[100]; + memset(nameToChar, 0, sizeof(nameToChar)); + for (int i(0); i < name.size(); i++) { + nameToChar[i] = name[i]; + } + nameVec[0] = nameToChar; + int status = CPXchgcolname(_env, _prb, 1, indices.data(), nameVec.data()); + zero_status_check(status, "Set col name"); } /************************************************************************************************* ------------------------------ Methods to solve the problem --------------------------------- +----------------------------- Methods to solve the problem +--------------------------------- *************************************************************************************************/ -int SolverCplex::solve_lp() -{ - int lp_status; - int status = CPXlpopt(_env, _prb); - zero_status_check(status, "solve prb as lp"); - - int cpx_status(0); - cpx_status = CPXgetstat(_env, _prb); - - if (cpx_status == CPX_STAT_OPTIMAL) - { - lp_status = OPTIMAL; - } - else if (cpx_status == CPX_STAT_INFEASIBLE) - { - lp_status = INFEASIBLE; - } - else if (cpx_status == CPX_STAT_UNBOUNDED) - { - lp_status = UNBOUNDED; - } - else if (cpx_status == CPX_STAT_INForUNBD) - { - lp_status = INForUNBOUND; - } - else if (cpx_status == CPX_STAT_OPTIMAL_INFEAS) - { - std::cout << "WARNING: Code CPX_STAT_OPTIMAL_INFEAS treated as optimal" << std::endl; - lp_status = OPTIMAL; - } - else if (cpx_status == CPX_STAT_ABORT_IT_LIM) - { - lp_status = OPTIMAL; - } - else - { - lp_status = UNKNOWN; - std::cout << "UNKNOWN CPLEX STATUS: " << cpx_status << std::endl; - } - return lp_status; -} - -int SolverCplex::solve_mip() -{ - int lp_status; - if (get_n_integer_vars() == 0) - { - lp_status = solve_lp(); - } - else - { - int status = CPXmipopt(_env, _prb); - zero_status_check(status, "solve prb as MIP"); - - int cpx_status(0); - cpx_status = CPXgetstat(_env, _prb); - if (cpx_status == CPXMIP_OPTIMAL) - { - lp_status = OPTIMAL; - } - else if (cpx_status == CPXMIP_INFEASIBLE) - { - lp_status = INFEASIBLE; - } - else if (cpx_status == CPXMIP_UNBOUNDED) - { - lp_status = UNBOUNDED; - } - else if (cpx_status == CPXMIP_INForUNBD) - { - lp_status = INForUNBOUND; - } - else if (cpx_status == CPXMIP_OPTIMAL_TOL) - { - lp_status = OPTIMAL; - } - else - { - lp_status = UNKNOWN; - std::cout << "UNKNOWN CPLEX STATUS: " << cpx_status << std::endl; - } - } - return lp_status; +int SolverCplex::solve_lp() { + int lp_status; + int status = CPXlpopt(_env, _prb); + zero_status_check(status, "solve prb as lp"); + + int cpx_status(0); + cpx_status = CPXgetstat(_env, _prb); + + if (cpx_status == CPX_STAT_OPTIMAL) { + lp_status = OPTIMAL; + } else if (cpx_status == CPX_STAT_INFEASIBLE) { + lp_status = INFEASIBLE; + } else if (cpx_status == CPX_STAT_UNBOUNDED) { + lp_status = UNBOUNDED; + } else if (cpx_status == CPX_STAT_INForUNBD) { + lp_status = INForUNBOUND; + } else if (cpx_status == CPX_STAT_OPTIMAL_INFEAS) { + std::cout << "WARNING: Code CPX_STAT_OPTIMAL_INFEAS treated as optimal" + << std::endl; + lp_status = OPTIMAL; + } else if (cpx_status == CPX_STAT_ABORT_IT_LIM) { + lp_status = OPTIMAL; + } else { + lp_status = UNKNOWN; + std::cout << "UNKNOWN CPLEX STATUS: " << cpx_status << std::endl; + } + return lp_status; +} + +int SolverCplex::solve_mip() { + int lp_status; + if (get_n_integer_vars() == 0) { + lp_status = solve_lp(); + } else { + int status = CPXmipopt(_env, _prb); + zero_status_check(status, "solve prb as MIP"); + + int cpx_status(0); + cpx_status = CPXgetstat(_env, _prb); + if (cpx_status == CPXMIP_OPTIMAL) { + lp_status = OPTIMAL; + } else if (cpx_status == CPXMIP_INFEASIBLE) { + lp_status = INFEASIBLE; + } else if (cpx_status == CPXMIP_UNBOUNDED) { + lp_status = UNBOUNDED; + } else if (cpx_status == CPXMIP_INForUNBD) { + lp_status = INForUNBOUND; + } else if (cpx_status == CPXMIP_OPTIMAL_TOL) { + lp_status = OPTIMAL; + } else { + lp_status = UNKNOWN; + std::cout << "UNKNOWN CPLEX STATUS: " << cpx_status << std::endl; + } + } + return lp_status; } /************************************************************************************************* -------------------------- Methods to get solutions information ----------------------------- +------------------------- Methods to get solutions information +----------------------------- *************************************************************************************************/ -void SolverCplex::get_basis(int *rstatus, int *cstatus) const -{ - CPXgetbase(_env, _prb, cstatus, rstatus); +void SolverCplex::get_basis(int *rstatus, int *cstatus) const { + CPXgetbase(_env, _prb, cstatus, rstatus); } -double SolverCplex::get_mip_value() const -{ - double val; - CPXgetobjval(_env, _prb, &val); - return val; +double SolverCplex::get_mip_value() const { + double val; + CPXgetobjval(_env, _prb, &val); + return val; } -double SolverCplex::get_lp_value() const -{ - double val; - CPXgetobjval(_env, _prb, &val); - return val; +double SolverCplex::get_lp_value() const { + double val; + CPXgetobjval(_env, _prb, &val); + return val; } -int SolverCplex::get_splex_num_of_ite_last() const -{ - return CPXgetitcnt(_env, _prb); +int SolverCplex::get_splex_num_of_ite_last() const { + return CPXgetitcnt(_env, _prb); } void SolverCplex::get_lp_sol(double *primals, double *duals, - double *reduced_costs) -{ - CPXsolution(_env, _prb, NULL, NULL, primals, duals, NULL, reduced_costs); + double *reduced_costs) { + CPXsolution(_env, _prb, NULL, NULL, primals, duals, NULL, reduced_costs); } -void SolverCplex::get_mip_sol(double *primals) -{ - CPXsolution(_env, _prb, NULL, NULL, primals, NULL, NULL, NULL); +void SolverCplex::get_mip_sol(double *primals) { + CPXsolution(_env, _prb, NULL, NULL, primals, NULL, NULL, NULL); } /************************************************************************************************* ------------------------- Methods to set algorithm or logs levels --------------------------- +------------------------ Methods to set algorithm or logs levels +--------------------------- *************************************************************************************************/ -void SolverCplex::set_output_log_level(int loglevel) -{ - if (loglevel > 0) - { - int status = CPXsetintparam(_env, CPXPARAM_ScreenOutput, CPX_ON); - zero_status_check(status, "set solver log level"); - } - else - { - int status = CPXsetintparam(_env, CPXPARAM_ScreenOutput, CPX_OFF); - zero_status_check(status, "set solver log level"); - } -} - -void SolverCplex::set_algorithm(std::string const &algo) -{ - int status(0); - if (algo == "BARRIER") - { - status = CPXsetintparam(_env, CPXPARAM_LPMethod, CPX_ALG_BARRIER); - zero_status_check(status, "set barrier algorithm"); - } - else if (algo == "BARRIER_WO_CROSSOVER") - { - status = CPXsetintparam(_env, CPXPARAM_LPMethod, CPX_ALG_BARRIER); - zero_status_check(status, "set barrier algorithm"); - status = CPXsetintparam(_env, CPXPARAM_Barrier_Crossover, CPX_ALG_NONE); - zero_status_check(status, "set crossover param to 0 in barrier"); - } - else if (algo == "DUAL") - { - status = CPXsetintparam(_env, CPXPARAM_LPMethod, CPX_ALG_DUAL); - zero_status_check(status, "set dual simplex algorithm"); - } - else - { - throw InvalidSolverOptionException("set_algorithm : " + algo); - } -} - -void SolverCplex::set_threads(int n_threads) -{ - int status = CPXsetintparam(_env, CPXPARAM_Threads, n_threads); - zero_status_check(status, "set threads number"); -} - -void SolverCplex::set_optimality_gap(double gap) -{ - int status = CPXsetdblparam(_env, CPXPARAM_Simplex_Tolerances_Optimality, gap); - zero_status_check(status, "set optimality tol for simplex"); - - status = CPXsetdblparam(_env, CPXPARAM_Barrier_ConvergeTol, gap); - zero_status_check(status, "set optimality gap for barrier"); -} - -void SolverCplex::set_simplex_iter(int iter) -{ - int status = CPXsetintparam(_env, CPXPARAM_Simplex_Limits_Iterations, iter); - zero_status_check(status, "set maximum number of simplex iterations"); +void SolverCplex::set_output_log_level(int loglevel) { + if (loglevel > 0) { + int status = CPXsetintparam(_env, CPXPARAM_ScreenOutput, CPX_ON); + zero_status_check(status, "set solver log level"); + } else { + int status = CPXsetintparam(_env, CPXPARAM_ScreenOutput, CPX_OFF); + zero_status_check(status, "set solver log level"); + } +} + +void SolverCplex::set_algorithm(std::string const &algo) { + int status(0); + if (algo == "BARRIER") { + status = CPXsetintparam(_env, CPXPARAM_LPMethod, CPX_ALG_BARRIER); + zero_status_check(status, "set barrier algorithm"); + } else if (algo == "BARRIER_WO_CROSSOVER") { + status = CPXsetintparam(_env, CPXPARAM_LPMethod, CPX_ALG_BARRIER); + zero_status_check(status, "set barrier algorithm"); + status = CPXsetintparam(_env, CPXPARAM_Barrier_Crossover, CPX_ALG_NONE); + zero_status_check(status, "set crossover param to 0 in barrier"); + } else if (algo == "DUAL") { + status = CPXsetintparam(_env, CPXPARAM_LPMethod, CPX_ALG_DUAL); + zero_status_check(status, "set dual simplex algorithm"); + } else { + throw InvalidSolverOptionException("set_algorithm : " + algo); + } +} + +void SolverCplex::set_threads(int n_threads) { + int status = CPXsetintparam(_env, CPXPARAM_Threads, n_threads); + zero_status_check(status, "set threads number"); +} + +void SolverCplex::set_optimality_gap(double gap) { + int status = + CPXsetdblparam(_env, CPXPARAM_Simplex_Tolerances_Optimality, gap); + zero_status_check(status, "set optimality tol for simplex"); + + status = CPXsetdblparam(_env, CPXPARAM_Barrier_ConvergeTol, gap); + zero_status_check(status, "set optimality gap for barrier"); +} + +void SolverCplex::set_simplex_iter(int iter) { + int status = CPXsetintparam(_env, CPXPARAM_Simplex_Limits_Iterations, iter); + zero_status_check(status, "set maximum number of simplex iterations"); } \ No newline at end of file diff --git a/src/cpp/multisolver_interface/SolverCplex.h b/src/cpp/multisolver_interface/SolverCplex.h index 676a95ce5..91157a92f 100644 --- a/src/cpp/multisolver_interface/SolverCplex.h +++ b/src/cpp/multisolver_interface/SolverCplex.h @@ -1,161 +1,174 @@ #pragma once -#include "multisolver_interface/SolverAbstract.h" #include "cplex.h" +#include "multisolver_interface/SolverAbstract.h" /*! * \class class SolverCplex * \brief Daughter class of AsbtractSolver implementing solver IBM ILOG CPLEX */ -class SolverCplex : public SolverAbstract -{ - - /************************************************************************************************* - ---------------------------------------- ATTRIBUTES --------------------------------------- - *************************************************************************************************/ - static int _NumberOfProblems; /*!< Counter of the total number of Cplex problems - declared to set or end the environment */ -public: - CPXENVptr _env; /*!< Ptr to the CPLEX environment */ - CPXLPptr _prb; /*!< Ptr to the CPLEX problem */ - - /************************************************************************************************* - ----------------------------------- Constructor/Desctructor -------------------------------- - *************************************************************************************************/ -public: - /** - * @brief Default constructor of a CPLEX solver, as a name is needed by CPLEX, the name - is set to DefaultProblem_$(_NumberOfProblems+1) - */ - SolverCplex(); - - /** - * @brief Constructor of a CPLEX solver named "name" - * - * @param name : Name of the solver, used in memory by CPLEX - */ - SolverCplex(const std::string &name); - - /** - * @brief Copy constructor of CPLEX, copy the problem "fictif" in memory and name it "name" - * - * @param fictif : Pointer to an AbstractSolver object, containing a CPLEX solver to copy - */ - SolverCplex(const SolverAbstract::Ptr fictif); - virtual ~SolverCplex(); - virtual int get_number_of_instances() override; - - virtual std::string get_solver_name() const override { return "CPLEX"; } - - /************************************************************************************************* - --------------------------------- Output and stream management ----------------------------- - *************************************************************************************************/ - - /************************************************************************************************* - ------ Destruction or creation of inner strctures and datas, closing environments ---------- - *************************************************************************************************/ -public: - virtual void init() override; - virtual void free() override; - - /************************************************************************************************* - ------------------------------- Reading & Writing problems ------------------------------- - *************************************************************************************************/ -public: - virtual void write_prob_mps(const std::string &filename) override; - virtual void write_prob_lp(const std::string &filename) override; - - virtual void read_prob_mps(const std::string &filename) override; - virtual void read_prob_lp(const std::string &filename) override; - virtual void write_prob(const char *name, const char *flags) override; - virtual void read_prob(const char *prob_name, const char *flags) override; - virtual void copy_prob(const SolverAbstract::Ptr fictif_solv) override; - - /************************************************************************************************* - ----------------------- Get general informations about problem ---------------------------- - *************************************************************************************************/ -public: - virtual int get_ncols() const override; - virtual int get_nrows() const override; - virtual int get_nelems() const override; - virtual int get_n_integer_vars() const override; - virtual void get_obj(double *obj, int first, int last) const override; - virtual void get_rows(int *mstart, int *mclind, double *dmatval, int size, int *nels, - int first, int last) const override; - virtual void get_row_type(char *qrtype, int first, int last) const override; - virtual void get_rhs(double *rhs, int first, int last) const override; - virtual void get_rhs_range(double *range, int first, int last) const override; - virtual void get_col_type(char *coltype, int first, int last) const override; - virtual void get_lb(double *lb, int fisrt, int last) const override; - virtual void get_ub(double *ub, int fisrt, int last) const override; - - virtual int get_row_index(std::string const &name) const override; - virtual int get_col_index(std::string const &name) const override; - virtual std::vector get_row_names(int first, int last) override; - virtual std::vector get_col_names(int first, int last) override; - - /************************************************************************************************* - ------------------------------ Methods to modify problem ---------------------------------- - *************************************************************************************************/ -public: - virtual void del_rows(int first, int last); - virtual void add_rows(int newrows, int newnz, const char *qrtype, const double *rhs, - const double *range, const int *mstart, const int *mclind, - const double *dmatval) override; - virtual void add_cols(int newcol, int newnz, const double *objx, const int *mstart, - const int *mrwind, const double *dmatval, const double *bdl, - const double *bdu) override; - virtual void add_name(int type, const char *cnames, int indice) override; - virtual void chg_obj(const std::vector &mindex, const std::vector &obj) override; - virtual void chg_bounds(const std::vector &mindex, const std::vector &qbtype, const std::vector &bnd) override; - virtual void chg_col_type(const std::vector &mindex, const std::vector &qctype) override; - virtual void chg_rhs(int id_row, double val) override; - virtual void chg_coef(int id_row, int id_col, double val) override; - virtual void chg_row_name(int id_row, std::string const &name) override; - virtual void chg_col_name(int id_col, std::string const &name) override; - - /************************************************************************************************* - ----------------------------- Methods to solve the problem --------------------------------- - *************************************************************************************************/ -public: - virtual int solve_lp() override; - virtual int solve_mip() override; - - /************************************************************************************************* - ------------------------- Methods to get solutions information ----------------------------- - *************************************************************************************************/ -public: - /** - * @brief Returns the current basis into the user’s data arrays. - * - * @param rstatus : Integer array of length ROWS to the basis status of the slack, surplus or - artifficial variable associated with each row. The status will be one of: - 0 slack, surplus or artifficial is non-basic; - 1 slack, surplus or artifficial is basic;. - May be NULL if not required. - * @param cstatus : Integer array of length COLS to hold the basis status of the columns - in the constraint matrix. The status will be one of: - 0 variable is non-basic at lower bound; - 1 variable is basic; - 2 variable is non-basic at upper bound; - 3 variable is free and non-basic - May be NULL if not required. - */ - virtual void get_basis(int *rstatus, int *cstatus) const override; - virtual double get_mip_value() const override; - virtual double get_lp_value() const override; - virtual int get_splex_num_of_ite_last() const override; - virtual void get_lp_sol(double *primals, double *duals, - double *reduced_costs) override; - virtual void get_mip_sol(double *primals) override; - - /************************************************************************************************* - ------------------------ Methods to set algorithm or logs levels --------------------------- - *************************************************************************************************/ -public: - virtual void set_output_log_level(int loglevel) override; - 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; - virtual void set_simplex_iter(int iter) override; +class SolverCplex : public SolverAbstract { + /************************************************************************************************* + ---------------------------------------- ATTRIBUTES + --------------------------------------- + *************************************************************************************************/ + static int + _NumberOfProblems; /*!< Counter of the total number of Cplex problems + declared to set or end the environment */ + public: + CPXENVptr _env; /*!< Ptr to the CPLEX environment */ + CPXLPptr _prb; /*!< Ptr to the CPLEX problem */ + + /************************************************************************************************* + ----------------------------------- Constructor/Desctructor + -------------------------------- + *************************************************************************************************/ + public: + /** + * @brief Default constructor of a CPLEX solver, as a name is needed by CPLEX, + the name is set to DefaultProblem_$(_NumberOfProblems+1) + */ + SolverCplex(); + + /** + * @brief Constructor of a CPLEX solver named "name" + * + * @param name : Name of the solver, used in memory by CPLEX + */ + SolverCplex(const std::string &name); + + /** + * @brief Copy constructor of CPLEX, copy the problem "fictif" in memory and + * name it "name" + * + * @param fictif : Pointer to an AbstractSolver object, containing a CPLEX + * solver to copy + */ + SolverCplex(const SolverAbstract::Ptr fictif); + virtual ~SolverCplex(); + virtual int get_number_of_instances() override; + + virtual std::string get_solver_name() const override { return "CPLEX"; } + + /************************************************************************************************* + --------------------------------- Output and stream management + ----------------------------- + *************************************************************************************************/ + + /************************************************************************************************* + ------ Destruction or creation of inner strctures and datas, closing + environments ---------- + *************************************************************************************************/ + public: + virtual void init() override; + virtual void free() override; + + /************************************************************************************************* + ------------------------------- Reading & Writing problems + ------------------------------- + *************************************************************************************************/ + public: + virtual void write_prob_mps(const std::string &filename) override; + virtual void write_prob_lp(const std::string &filename) override; + + virtual void read_prob_mps(const std::string &filename) override; + virtual void read_prob_lp(const std::string &filename) override; + virtual void write_prob(const char *name, const char *flags) override; + virtual void read_prob(const char *prob_name, const char *flags) override; + virtual void copy_prob(const SolverAbstract::Ptr fictif_solv) override; + + /************************************************************************************************* + ----------------------- Get general informations about problem + ---------------------------- + *************************************************************************************************/ + public: + virtual int get_ncols() const override; + virtual int get_nrows() const override; + virtual int get_nelems() const override; + virtual int get_n_integer_vars() const override; + virtual void get_obj(double *obj, int first, int last) const override; + virtual void get_rows(int *mstart, int *mclind, double *dmatval, int size, + int *nels, int first, int last) const override; + virtual void get_row_type(char *qrtype, int first, int last) const override; + virtual void get_rhs(double *rhs, int first, int last) const override; + virtual void get_rhs_range(double *range, int first, int last) const override; + virtual void get_col_type(char *coltype, int first, int last) const override; + virtual void get_lb(double *lb, int fisrt, int last) const override; + virtual void get_ub(double *ub, int fisrt, int last) const override; + + virtual int get_row_index(std::string const &name) const override; + virtual int get_col_index(std::string const &name) const override; + virtual std::vector get_row_names(int first, int last) override; + virtual std::vector get_col_names(int first, int last) override; + + /************************************************************************************************* + ------------------------------ Methods to modify problem + ---------------------------------- + *************************************************************************************************/ + public: + virtual void del_rows(int first, int last); + virtual void add_rows(int newrows, int newnz, const char *qrtype, + const double *rhs, const double *range, + const int *mstart, const int *mclind, + const double *dmatval) override; + virtual void add_cols(int newcol, int newnz, const double *objx, + const int *mstart, const int *mrwind, + const double *dmatval, const double *bdl, + const double *bdu) override; + virtual void add_name(int type, const char *cnames, int indice) override; + virtual void chg_obj(const std::vector &mindex, + const std::vector &obj) override; + virtual void chg_bounds(const std::vector &mindex, + const std::vector &qbtype, + const std::vector &bnd) override; + virtual void chg_col_type(const std::vector &mindex, + const std::vector &qctype) override; + virtual void chg_rhs(int id_row, double val) override; + virtual void chg_coef(int id_row, int id_col, double val) override; + virtual void chg_row_name(int id_row, std::string const &name) override; + virtual void chg_col_name(int id_col, std::string const &name) override; + + /************************************************************************************************* + ----------------------------- Methods to solve the problem + --------------------------------- + *************************************************************************************************/ + public: + virtual int solve_lp() override; + virtual int solve_mip() override; + + /************************************************************************************************* + ------------------------- Methods to get solutions information + ----------------------------- + *************************************************************************************************/ + public: + /** + * @brief Returns the current basis into the user’s data arrays. + * + * @param rstatus : Integer array of length ROWS to the basis status of the + slack, surplus or artifficial variable associated with each row. The status + will be one of: 0 slack, surplus or artifficial is non-basic; 1 slack, surplus + or artifficial is basic;. May be NULL if not required. + * @param cstatus : Integer array of length COLS to hold the basis status of + the columns in the constraint matrix. The status will be one of: 0 variable is + non-basic at lower bound; 1 variable is basic; 2 variable is non-basic at + upper bound; 3 variable is free and non-basic May be NULL if not required. + */ + virtual void get_basis(int *rstatus, int *cstatus) const override; + virtual double get_mip_value() const override; + virtual double get_lp_value() const override; + virtual int get_splex_num_of_ite_last() const override; + virtual void get_lp_sol(double *primals, double *duals, + double *reduced_costs) override; + virtual void get_mip_sol(double *primals) override; + + /************************************************************************************************* + ------------------------ Methods to set algorithm or logs levels + --------------------------- + *************************************************************************************************/ + public: + virtual void set_output_log_level(int loglevel) override; + 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; + virtual void set_simplex_iter(int iter) override; }; \ No newline at end of file diff --git a/src/cpp/multisolver_interface/SolverFactory.cpp b/src/cpp/multisolver_interface/SolverFactory.cpp index a6c778df5..a6b2f0225 100644 --- a/src/cpp/multisolver_interface/SolverFactory.cpp +++ b/src/cpp/multisolver_interface/SolverFactory.cpp @@ -11,109 +11,87 @@ #include "multisolver_interface/SolverFactory.h" -SolverFactory::SolverFactory() -{ - _available_solvers.clear(); +SolverFactory::SolverFactory() { + _available_solvers.clear(); #ifdef CPLEX - _available_solvers.push_back(CPLEX_STR); + _available_solvers.push_back(CPLEX_STR); #endif #ifdef XPRESS - _available_solvers.push_back(XPRESS_STR); + _available_solvers.push_back(XPRESS_STR); #endif #ifdef COIN_OR - _available_solvers.push_back(CLP_STR); - _available_solvers.push_back(CBC_STR); + _available_solvers.push_back(CLP_STR); + _available_solvers.push_back(CBC_STR); #endif } -SolverAbstract::Ptr SolverFactory::create_solver(const std::string &solver_name, const SOLVER_TYPE solver_type) const -{ - +SolverAbstract::Ptr SolverFactory::create_solver( + const std::string &solver_name, const SOLVER_TYPE solver_type) const { #ifdef COIN_OR - if (solver_name == COIN_STR && solver_type == SOLVER_TYPE::CONTINUOUS) - { - return std::make_shared(); - } - else if (solver_name == COIN_STR && solver_type == SOLVER_TYPE::INTEGER) - { - return std::make_shared(); - } + if (solver_name == COIN_STR && solver_type == SOLVER_TYPE::CONTINUOUS) { + return std::make_shared(); + } else if (solver_name == COIN_STR && solver_type == SOLVER_TYPE::INTEGER) { + return std::make_shared(); + } #endif - return create_solver(solver_name); + return create_solver(solver_name); } -SolverAbstract::Ptr SolverFactory::create_solver(const std::string &solver_name) const -{ - - if (solver_name == "") - { - throw InvalidSolverNameException(solver_name); - } +SolverAbstract::Ptr SolverFactory::create_solver( + const std::string &solver_name) const { + if (solver_name == "") { + throw InvalidSolverNameException(solver_name); + } #ifdef CPLEX - else if (solver_name == CPLEX_STR) - { - return std::make_shared(); - } + else if (solver_name == CPLEX_STR) { + return std::make_shared(); + } #endif #ifdef XPRESS - else if (solver_name == XPRESS_STR) - { - return std::make_shared(); - } + else if (solver_name == XPRESS_STR) { + return std::make_shared(); + } #endif #ifdef COIN_OR - else if (solver_name == CLP_STR) - { - return std::make_shared(); - } - else if (solver_name == CBC_STR) - { - return std::make_shared(); - } + else if (solver_name == CLP_STR) { + return std::make_shared(); + } else if (solver_name == CBC_STR) { + return std::make_shared(); + } #endif - else - { - throw InvalidSolverNameException(solver_name); - } + else { + throw InvalidSolverNameException(solver_name); + } } -SolverAbstract::Ptr SolverFactory::create_solver(SolverAbstract::Ptr to_copy) -{ - std::string solver_name = to_copy->get_solver_name(); +SolverAbstract::Ptr SolverFactory::create_solver(SolverAbstract::Ptr to_copy) { + std::string solver_name = to_copy->get_solver_name(); - if (solver_name == "") - { - throw InvalidSolverNameException(solver_name); - } + if (solver_name == "") { + throw InvalidSolverNameException(solver_name); + } #ifdef CPLEX - else if (solver_name == CPLEX_STR) - { - return std::make_shared(to_copy); - } + else if (solver_name == CPLEX_STR) { + return std::make_shared(to_copy); + } #endif #ifdef XPRESS - else if (solver_name == XPRESS_STR) - { - return std::make_shared(to_copy); - } + else if (solver_name == XPRESS_STR) { + return std::make_shared(to_copy); + } #endif #ifdef COIN_OR - else if (solver_name == CLP_STR) - { - return std::make_shared(to_copy); - } - else if (solver_name == CBC_STR) - { - return std::make_shared(to_copy); - } + else if (solver_name == CLP_STR) { + return std::make_shared(to_copy); + } else if (solver_name == CBC_STR) { + return std::make_shared(to_copy); + } #endif - else - { - throw InvalidSolverNameException(solver_name); - } + else { + throw InvalidSolverNameException(solver_name); + } } -const std::vector &SolverFactory::get_solvers_list() const -{ - return _available_solvers; +const std::vector &SolverFactory::get_solvers_list() const { + return _available_solvers; } \ No newline at end of file diff --git a/src/cpp/multisolver_interface/SolverXpress.cpp b/src/cpp/multisolver_interface/SolverXpress.cpp index d7f66c19f..8c1bcbec0 100644 --- a/src/cpp/multisolver_interface/SolverXpress.cpp +++ b/src/cpp/multisolver_interface/SolverXpress.cpp @@ -1,600 +1,528 @@ +#include "SolverXpress.h" + #include #include -#include "SolverXpress.h" - /************************************************************************************************* ------------------------------------ Constructor/Desctructor -------------------------------- +----------------------------------- Constructor/Desctructor +-------------------------------- *************************************************************************************************/ int SolverXpress::_NumberOfProblems = 0; -SolverXpress::SolverXpress() -{ - int status = 0; - if (_NumberOfProblems == 0) - { - status = XPRSinit(NULL); - zero_status_check(status, "intialize XPRESS environment"); - } +SolverXpress::SolverXpress() { + int status = 0; + if (_NumberOfProblems == 0) { + status = XPRSinit(NULL); + zero_status_check(status, "intialize XPRESS environment"); + } - _NumberOfProblems += 1; + _NumberOfProblems += 1; - _xprs = NULL; - add_stream(std::cout); + _xprs = NULL; + add_stream(std::cout); } -SolverXpress::SolverXpress(const SolverAbstract::Ptr toCopy) : SolverXpress() -{ - SolverXpress::init(); - int status = 0; +SolverXpress::SolverXpress(const SolverAbstract::Ptr toCopy) : SolverXpress() { + SolverXpress::init(); + int status = 0; - // Try to cast the solver in fictif to a SolverCPLEX - if (SolverXpress *xpSolv = dynamic_cast(toCopy.get())) - { - status = XPRScopyprob(_xprs, xpSolv->_xprs, ""); - zero_status_check(status, "create problem"); - } - else - { - _NumberOfProblems -= 1; - SolverXpress::free(); - throw InvalidSolverForCopyException(toCopy->get_solver_name(), SolverXpress::get_solver_name()); - } + // Try to cast the solver in fictif to a SolverCPLEX + if (SolverXpress *xpSolv = dynamic_cast(toCopy.get())) { + status = XPRScopyprob(_xprs, xpSolv->_xprs, ""); + zero_status_check(status, "create problem"); + } else { + _NumberOfProblems -= 1; + SolverXpress::free(); + throw InvalidSolverForCopyException(toCopy->get_solver_name(), + SolverXpress::get_solver_name()); + } } -SolverXpress::~SolverXpress() -{ - _NumberOfProblems -= 1; - SolverXpress::free(); +SolverXpress::~SolverXpress() { + _NumberOfProblems -= 1; + SolverXpress::free(); - if (_NumberOfProblems == 0) - { - int status = XPRSfree(); - zero_status_check(status, "free XPRESS environment"); - } + if (_NumberOfProblems == 0) { + int status = XPRSfree(); + zero_status_check(status, "free XPRESS environment"); + } } -int SolverXpress::get_number_of_instances() -{ - return _NumberOfProblems; -} +int SolverXpress::get_number_of_instances() { return _NumberOfProblems; } /************************************************************************************************* ------------------------------------ Output stream management ------------------------------ +----------------------------------- Output stream management +------------------------------ *************************************************************************************************/ /************************************************************************************************* ------------- Destruction of inner strctures and datas, closing environments --------------- +------------ Destruction of inner strctures and datas, closing environments +--------------- *************************************************************************************************/ -void SolverXpress::init() -{ - int status = XPRScreateprob(&_xprs); - zero_status_check(status, "create XPRESS problem"); +void SolverXpress::init() { + int status = XPRScreateprob(&_xprs); + zero_status_check(status, "create XPRESS problem"); - SolverXpress::set_output_log_level(0); - status = XPRSloadlp(_xprs, "empty", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - zero_status_check(status, "generate empty prob in XPRS interface init method"); + SolverXpress::set_output_log_level(0); + status = XPRSloadlp(_xprs, "empty", 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + zero_status_check(status, + "generate empty prob in XPRS interface init method"); } -void SolverXpress::free() -{ - int status = XPRSdestroyprob(_xprs); - _xprs = NULL; - zero_status_check(status, "destroy XPRESS problem"); +void SolverXpress::free() { + int status = XPRSdestroyprob(_xprs); + _xprs = NULL; + zero_status_check(status, "destroy XPRESS problem"); } /************************************************************************************************* -------------------------------- Reading & Writing problems ------------------------------- +------------------------------- Reading & Writing problems +------------------------------- *************************************************************************************************/ -void SolverXpress::write_prob_mps(const std::string &filename) -{ - std::string nFlags = ""; - int status = XPRSwriteprob(_xprs, filename.c_str(), nFlags.c_str()); - zero_status_check(status, "write problem"); +void SolverXpress::write_prob_mps(const std::string &filename) { + std::string nFlags = ""; + int status = XPRSwriteprob(_xprs, filename.c_str(), nFlags.c_str()); + zero_status_check(status, "write problem"); } -void SolverXpress::write_prob_lp(const std::string &filename) -{ - std::string nFlags = "l"; - int status = XPRSwriteprob(_xprs, filename.c_str(), nFlags.c_str()); - zero_status_check(status, "write problem"); +void SolverXpress::write_prob_lp(const std::string &filename) { + std::string nFlags = "l"; + int status = XPRSwriteprob(_xprs, filename.c_str(), nFlags.c_str()); + zero_status_check(status, "write problem"); } -void SolverXpress::read_prob_mps(const std::string &filename) -{ - std::string nFlags = ""; - read_prob(filename.c_str(), nFlags.c_str()); +void SolverXpress::read_prob_mps(const std::string &filename) { + std::string nFlags = ""; + read_prob(filename.c_str(), nFlags.c_str()); } -void SolverXpress::read_prob_lp(const std::string &filename) -{ - std::string nFlags = "l"; - read_prob(filename.c_str(), nFlags.c_str()); +void SolverXpress::read_prob_lp(const std::string &filename) { + std::string nFlags = "l"; + read_prob(filename.c_str(), nFlags.c_str()); } -void SolverXpress::read_prob(const char *prob_name, const char *flags) -{ - // To delete obj from rows when reading prob - int keeprows(0); - int status = XPRSgetintcontrol(_xprs, XPRS_KEEPNROWS, &keeprows); - zero_status_check(status, "get XPRS_KEEPNROWS"); +void SolverXpress::read_prob(const char *prob_name, const char *flags) { + // To delete obj from rows when reading prob + int keeprows(0); + int status = XPRSgetintcontrol(_xprs, XPRS_KEEPNROWS, &keeprows); + zero_status_check(status, "get XPRS_KEEPNROWS"); - /* - * This part of the code requires XPRESS version 8.8.5 or higher - * For previous versions, the param KEEPNROWS deletes row names - * when reading. - * In order to bypass that without modifying the code, - * the first row, which is the objective function - * is deleted after read - * - */ + /* + * This part of the code requires XPRESS version 8.8.5 or higher + * For previous versions, the param KEEPNROWS deletes row names + * when reading. + * In order to bypass that without modifying the code, + * the first row, which is the objective function + * is deleted after read + * + */ - /* - if (keeprows != -1) { - status = XPRSsetintcontrol(_xprs, XPRS_KEEPNROWS, -1); - zero_status_check(status, "set XPRS_KEEPNROWS to -1"); - } - */ + /* + if (keeprows != -1) { + status = XPRSsetintcontrol(_xprs, XPRS_KEEPNROWS, -1); + zero_status_check(status, "set XPRS_KEEPNROWS to -1"); + } + */ - status = XPRSreadprob(_xprs, prob_name, flags); - zero_status_check(status, "read problem"); + status = XPRSreadprob(_xprs, prob_name, flags); + zero_status_check(status, "read problem"); - // If param KEEPNROWS not -1 remove first row which is the objective function - if (keeprows != -1) - { - del_rows(0, 0); - } + // If param KEEPNROWS not -1 remove first row which is the objective function + if (keeprows != -1) { + del_rows(0, 0); + } } -void SolverXpress::copy_prob(const SolverAbstract::Ptr fictif_solv) -{ - - std::string error = "Copy XPRESS problem : TO DO WHEN NEEDED"; - throw NotImplementedFeatureSolverException(error); +void SolverXpress::copy_prob(const SolverAbstract::Ptr fictif_solv) { + std::string error = "Copy XPRESS problem : TO DO WHEN NEEDED"; + throw NotImplementedFeatureSolverException(error); } /************************************************************************************************* ------------------------ Get general informations about problem ---------------------------- +----------------------- Get general informations about problem +---------------------------- *************************************************************************************************/ -int SolverXpress::get_ncols() const -{ - int cols(0); - int status = XPRSgetintattrib(_xprs, XPRS_COLS, &cols); - zero_status_check(status, "get number of columns"); - return cols; +int SolverXpress::get_ncols() const { + int cols(0); + int status = XPRSgetintattrib(_xprs, XPRS_COLS, &cols); + zero_status_check(status, "get number of columns"); + return cols; } -int SolverXpress::get_nrows() const -{ - int rows(0); - int status = XPRSgetintattrib(_xprs, XPRS_ROWS, &rows); - zero_status_check(status, "get number of rows"); - return rows; +int SolverXpress::get_nrows() const { + int rows(0); + int status = XPRSgetintattrib(_xprs, XPRS_ROWS, &rows); + zero_status_check(status, "get number of rows"); + return rows; } -int SolverXpress::get_nelems() const -{ - int elems(0); - int status = XPRSgetintattrib(_xprs, XPRS_ELEMS, &elems); - zero_status_check(status, "get number of non zero elements"); +int SolverXpress::get_nelems() const { + int elems(0); + int status = XPRSgetintattrib(_xprs, XPRS_ELEMS, &elems); + zero_status_check(status, "get number of non zero elements"); - return elems; + return elems; } -int SolverXpress::get_n_integer_vars() const -{ - int n_int_vars(0); - int status = XPRSgetintattrib(_xprs, XPRS_MIPENTS, &n_int_vars); - zero_status_check(status, "get number of integer variables"); - return n_int_vars; +int SolverXpress::get_n_integer_vars() const { + int n_int_vars(0); + int status = XPRSgetintattrib(_xprs, XPRS_MIPENTS, &n_int_vars); + zero_status_check(status, "get number of integer variables"); + return n_int_vars; } -void SolverXpress::get_obj(double *obj, int first, int last) const -{ - int status = XPRSgetobj(_xprs, obj, first, last); - zero_status_check(status, "get objective function"); +void SolverXpress::get_obj(double *obj, int first, int last) const { + int status = XPRSgetobj(_xprs, obj, first, last); + zero_status_check(status, "get objective function"); } -void SolverXpress::get_rows(int *mstart, int *mclind, double *dmatval, int size, int *nels, - int first, int last) const -{ - int status = XPRSgetrows(_xprs, mstart, mclind, dmatval, size, nels, first, last); - zero_status_check(status, "get rows"); +void SolverXpress::get_rows(int *mstart, int *mclind, double *dmatval, int size, + int *nels, int first, int last) const { + int status = + XPRSgetrows(_xprs, mstart, mclind, dmatval, size, nels, first, last); + zero_status_check(status, "get rows"); } -void SolverXpress::get_row_type(char *qrtype, int first, int last) const -{ - int status = XPRSgetrowtype(_xprs, qrtype, first, last); - zero_status_check(status, "get rows types"); +void SolverXpress::get_row_type(char *qrtype, int first, int last) const { + int status = XPRSgetrowtype(_xprs, qrtype, first, last); + zero_status_check(status, "get rows types"); } -void SolverXpress::get_rhs(double *rhs, int first, int last) const -{ - int status = XPRSgetrhs(_xprs, rhs, first, last); - zero_status_check(status, "get RHS"); +void SolverXpress::get_rhs(double *rhs, int first, int last) const { + int status = XPRSgetrhs(_xprs, rhs, first, last); + zero_status_check(status, "get RHS"); } -void SolverXpress::get_rhs_range(double *range, int first, int last) const -{ - int status = XPRSgetrhsrange(_xprs, range, first, last); - zero_status_check(status, "get RHS of range rows"); +void SolverXpress::get_rhs_range(double *range, int first, int last) const { + int status = XPRSgetrhsrange(_xprs, range, first, last); + zero_status_check(status, "get RHS of range rows"); } -void SolverXpress::get_col_type(char *coltype, int first, int last) const -{ - int status = XPRSgetcoltype(_xprs, coltype, first, last); - zero_status_check(status, "get type of columns"); +void SolverXpress::get_col_type(char *coltype, int first, int last) const { + int status = XPRSgetcoltype(_xprs, coltype, first, last); + zero_status_check(status, "get type of columns"); } -void SolverXpress::get_lb(double *lb, int first, int last) const -{ - int status = XPRSgetlb(_xprs, lb, first, last); - zero_status_check(status, "get lower bounds of variables"); +void SolverXpress::get_lb(double *lb, int first, int last) const { + int status = XPRSgetlb(_xprs, lb, first, last); + zero_status_check(status, "get lower bounds of variables"); } -void SolverXpress::get_ub(double *ub, int first, int last) const -{ - int status = XPRSgetub(_xprs, ub, first, last); - zero_status_check(status, "get upper bounds of variables"); +void SolverXpress::get_ub(double *ub, int first, int last) const { + int status = XPRSgetub(_xprs, ub, first, last); + zero_status_check(status, "get upper bounds of variables"); } -int SolverXpress::get_row_index(std::string const &name) const -{ - int id = 0; - int status = XPRSgetindex(_xprs, 1, name.c_str(), &id); - zero_status_check(status, "get row index. Name does not exist."); - return id; +int SolverXpress::get_row_index(std::string const &name) const { + int id = 0; + int status = XPRSgetindex(_xprs, 1, name.c_str(), &id); + zero_status_check(status, "get row index. Name does not exist."); + return id; } -int SolverXpress::get_col_index(std::string const &name) const -{ - int id = 0; - int status = XPRSgetindex(_xprs, 2, name.c_str(), &id); - zero_status_check(status, "get column index. Name does not exist."); - return id; +int SolverXpress::get_col_index(std::string const &name) const { + int id = 0; + int status = XPRSgetindex(_xprs, 2, name.c_str(), &id); + zero_status_check(status, "get column index. Name does not exist."); + return id; } -std::vector SolverXpress::get_row_names(int first, int last) -{ - std::vector names; - names.reserve(1 + last - first); - char cur_name[100]; - for (int i = 0; i < last - first + 1; i++) - { - int status = XPRSgetnames(_xprs, 1, cur_name, i + first, i + first); - zero_status_check(status, "get row names."); - names.push_back(cur_name); - memset(cur_name, 0, 100); - } +std::vector SolverXpress::get_row_names(int first, int last) { + std::vector names; + names.reserve(1 + last - first); + char cur_name[100]; + for (int i = 0; i < last - first + 1; i++) { + int status = XPRSgetnames(_xprs, 1, cur_name, i + first, i + first); + zero_status_check(status, "get row names."); + names.push_back(cur_name); + memset(cur_name, 0, 100); + } - return names; + return names; } -std::vector SolverXpress::get_col_names(int first, int last) -{ - std::vector names; - names.reserve(1 + last - first); - char cur_name[100]; - for (int i = 0; i < last - first + 1; i++) - { - int status = XPRSgetnames(_xprs, 2, cur_name, i + first, i + first); - zero_status_check(status, "get column names."); - names.push_back(cur_name); - memset(cur_name, 0, 100); - } +std::vector SolverXpress::get_col_names(int first, int last) { + std::vector names; + names.reserve(1 + last - first); + char cur_name[100]; + for (int i = 0; i < last - first + 1; i++) { + int status = XPRSgetnames(_xprs, 2, cur_name, i + first, i + first); + zero_status_check(status, "get column names."); + names.push_back(cur_name); + memset(cur_name, 0, 100); + } - return names; + return names; } /************************************************************************************************* ------------------------------- Methods to modify problem ---------------------------------- +------------------------------ Methods to modify problem +---------------------------------- *************************************************************************************************/ -void SolverXpress::del_rows(int first, int last) -{ - std::vector mindex(last - first + 1); - for (int i = 0; i < last - first + 1; i++) - { - mindex[i] = first + i; - } - int status = XPRSdelrows(_xprs, last - first + 1, mindex.data()); - zero_status_check(status, "delete rows"); +void SolverXpress::del_rows(int first, int last) { + std::vector mindex(last - first + 1); + for (int i = 0; i < last - first + 1; i++) { + mindex[i] = first + i; + } + int status = XPRSdelrows(_xprs, last - first + 1, mindex.data()); + zero_status_check(status, "delete rows"); } -void SolverXpress::add_rows(int newrows, int newnz, const char *qrtype, const double *rhs, - const double *range, const int *mstart, const int *mclind, - const double *dmatval) -{ - int status = XPRSaddrows(_xprs, newrows, newnz, qrtype, rhs, range, mstart, mclind, dmatval); - zero_status_check(status, "add rows"); +void SolverXpress::add_rows(int newrows, int newnz, const char *qrtype, + const double *rhs, const double *range, + const int *mstart, const int *mclind, + const double *dmatval) { + int status = XPRSaddrows(_xprs, newrows, newnz, qrtype, rhs, range, mstart, + mclind, dmatval); + zero_status_check(status, "add rows"); } -void SolverXpress::add_cols(int newcol, int newnz, const double *objx, const int *mstart, - const int *mrwind, const double *dmatval, const double *bdl, - const double *bdu) -{ - int status = XPRSaddcols(_xprs, newcol, newnz, objx, mstart, mrwind, dmatval, bdl, bdu); - zero_status_check(status, "add columns"); +void SolverXpress::add_cols(int newcol, int newnz, const double *objx, + const int *mstart, const int *mrwind, + const double *dmatval, const double *bdl, + const double *bdu) { + int status = XPRSaddcols(_xprs, newcol, newnz, objx, mstart, mrwind, dmatval, + bdl, bdu); + zero_status_check(status, "add columns"); } -void SolverXpress::add_name(int type, const char *cnames, int indice) -{ - int status = XPRSaddnames(_xprs, type, cnames, indice, indice); - zero_status_check(status, "add names"); +void SolverXpress::add_name(int type, const char *cnames, int indice) { + int status = XPRSaddnames(_xprs, type, cnames, indice, indice); + zero_status_check(status, "add names"); } -void SolverXpress::chg_obj(const std::vector &mindex, const std::vector &obj) -{ - assert(obj.size() == mindex.size()); - int status = XPRSchgobj(_xprs, obj.size(), mindex.data(), obj.data()); - zero_status_check(status, "change objective"); +void SolverXpress::chg_obj(const std::vector &mindex, + const std::vector &obj) { + assert(obj.size() == mindex.size()); + int status = XPRSchgobj(_xprs, obj.size(), mindex.data(), obj.data()); + zero_status_check(status, "change objective"); } -void SolverXpress::chg_bounds(const std::vector &mindex, const std::vector &qbtype, const std::vector &bnd) -{ - assert(qbtype.size() == mindex.size()); - assert(bnd.size() == mindex.size()); - int status = XPRSchgbounds(_xprs, mindex.size(), mindex.data(), qbtype.data(), bnd.data()); - zero_status_check(status, "change bounds"); +void SolverXpress::chg_bounds(const std::vector &mindex, + const std::vector &qbtype, + const std::vector &bnd) { + assert(qbtype.size() == mindex.size()); + assert(bnd.size() == mindex.size()); + int status = XPRSchgbounds(_xprs, mindex.size(), mindex.data(), qbtype.data(), + bnd.data()); + zero_status_check(status, "change bounds"); } -void SolverXpress::chg_col_type(const std::vector &mindex, const std::vector &qctype) -{ - assert(qctype.size() == mindex.size()); - int status = XPRSchgcoltype(_xprs, mindex.size(), mindex.data(), qctype.data()); - zero_status_check(status, "change column types"); +void SolverXpress::chg_col_type(const std::vector &mindex, + const std::vector &qctype) { + assert(qctype.size() == mindex.size()); + int status = + XPRSchgcoltype(_xprs, mindex.size(), mindex.data(), qctype.data()); + zero_status_check(status, "change column types"); } -void SolverXpress::chg_rhs(int id_row, double val) -{ - int status = XPRSchgrhs(_xprs, 1, std::vector(1, id_row).data(), - std::vector(1, val).data()); - zero_status_check(status, "change rhs"); +void SolverXpress::chg_rhs(int id_row, double val) { + int status = XPRSchgrhs(_xprs, 1, std::vector(1, id_row).data(), + std::vector(1, val).data()); + zero_status_check(status, "change rhs"); } -void SolverXpress::chg_coef(int id_row, int id_col, double val) -{ - int status = XPRSchgcoef(_xprs, id_row, id_col, val); - zero_status_check(status, "change matrix coefficient"); +void SolverXpress::chg_coef(int id_row, int id_col, double val) { + int status = XPRSchgcoef(_xprs, id_row, id_col, val); + zero_status_check(status, "change matrix coefficient"); } -void SolverXpress::chg_row_name(int id_row, std::string const &name) -{ - int status = XPRSaddnames(_xprs, 1, name.data(), id_row, id_row); - zero_status_check(status, "Set row name"); +void SolverXpress::chg_row_name(int id_row, std::string const &name) { + int status = XPRSaddnames(_xprs, 1, name.data(), id_row, id_row); + zero_status_check(status, "Set row name"); } -void SolverXpress::chg_col_name(int id_col, std::string const &name) -{ - int status = XPRSaddnames(_xprs, 2, name.data(), id_col, id_col); - zero_status_check(status, "Set col name"); +void SolverXpress::chg_col_name(int id_col, std::string const &name) { + int status = XPRSaddnames(_xprs, 2, name.data(), id_col, id_col); + zero_status_check(status, "Set col name"); } /************************************************************************************************* ------------------------------ Methods to solve the problem --------------------------------- +----------------------------- Methods to solve the problem +--------------------------------- *************************************************************************************************/ -int SolverXpress::solve_lp() -{ - int lp_status; - int status = XPRSlpoptimize(_xprs, ""); - zero_status_check(status, "solve problem as LP"); - - int xprs_status(0); - status = XPRSgetintattrib(_xprs, XPRS_LPSTATUS, &xprs_status); - zero_status_check(status, "get LP status after LP solve"); - - if (xprs_status == XPRS_LP_OPTIMAL) - { - lp_status = OPTIMAL; - } - else if (xprs_status == XPRS_LP_INFEAS) - { - lp_status = INFEASIBLE; - } - else if (xprs_status == XPRS_LP_UNBOUNDED) - { - lp_status = UNBOUNDED; - } - else - { - lp_status = UNKNOWN; - std::cout << "Error : UNKNOWN XPRESS STATUS IS : " << xprs_status << std::endl; - } - return lp_status; -} - -int SolverXpress::solve_mip() -{ - int lp_status; - int status(0); - status = XPRSmipoptimize(_xprs, ""); - zero_status_check(status, "solve problem as MIP"); - - int xprs_status(0); - status = XPRSgetintattrib(_xprs, XPRS_MIPSTATUS, &xprs_status); - zero_status_check(status, "get MIP status after MIP solve"); - - if (xprs_status == XPRS_MIP_OPTIMAL) - { - lp_status = OPTIMAL; - } - else if (xprs_status == XPRS_MIP_INFEAS) - { - lp_status = INFEASIBLE; - } - else if (xprs_status == XPRS_MIP_UNBOUNDED) - { - lp_status = UNBOUNDED; - } - else - { - lp_status = UNKNOWN; - std::cout << "XPRESS STATUS IS : " << xprs_status << std::endl; - } - return lp_status; +int SolverXpress::solve_lp() { + int lp_status; + int status = XPRSlpoptimize(_xprs, ""); + zero_status_check(status, "solve problem as LP"); + + int xprs_status(0); + status = XPRSgetintattrib(_xprs, XPRS_LPSTATUS, &xprs_status); + zero_status_check(status, "get LP status after LP solve"); + + if (xprs_status == XPRS_LP_OPTIMAL) { + lp_status = OPTIMAL; + } else if (xprs_status == XPRS_LP_INFEAS) { + lp_status = INFEASIBLE; + } else if (xprs_status == XPRS_LP_UNBOUNDED) { + lp_status = UNBOUNDED; + } else { + lp_status = UNKNOWN; + std::cout << "Error : UNKNOWN XPRESS STATUS IS : " << xprs_status + << std::endl; + } + return lp_status; +} + +int SolverXpress::solve_mip() { + int lp_status; + int status(0); + status = XPRSmipoptimize(_xprs, ""); + zero_status_check(status, "solve problem as MIP"); + + int xprs_status(0); + status = XPRSgetintattrib(_xprs, XPRS_MIPSTATUS, &xprs_status); + zero_status_check(status, "get MIP status after MIP solve"); + + if (xprs_status == XPRS_MIP_OPTIMAL) { + lp_status = OPTIMAL; + } else if (xprs_status == XPRS_MIP_INFEAS) { + lp_status = INFEASIBLE; + } else if (xprs_status == XPRS_MIP_UNBOUNDED) { + lp_status = UNBOUNDED; + } else { + lp_status = UNKNOWN; + std::cout << "XPRESS STATUS IS : " << xprs_status << std::endl; + } + return lp_status; } /************************************************************************************************* -------------------------- Methods to get solutions information ----------------------------- +------------------------- Methods to get solutions information +----------------------------- *************************************************************************************************/ -void SolverXpress::get_basis(int *rstatus, int *cstatus) const -{ - int status = XPRSgetbasis(_xprs, rstatus, cstatus); - zero_status_check(status, "get basis"); +void SolverXpress::get_basis(int *rstatus, int *cstatus) const { + int status = XPRSgetbasis(_xprs, rstatus, cstatus); + zero_status_check(status, "get basis"); } -double SolverXpress::get_mip_value() const -{ - double val; - int status = XPRSgetdblattrib(_xprs, XPRS_MIPOBJVAL, &val); - zero_status_check(status, "get MIP value"); - return val; +double SolverXpress::get_mip_value() const { + double val; + int status = XPRSgetdblattrib(_xprs, XPRS_MIPOBJVAL, &val); + zero_status_check(status, "get MIP value"); + return val; } -double SolverXpress::get_lp_value() const -{ - double val; - int status = XPRSgetdblattrib(_xprs, XPRS_LPOBJVAL, &val); - zero_status_check(status, "get LP value"); - return val; +double SolverXpress::get_lp_value() const { + double val; + int status = XPRSgetdblattrib(_xprs, XPRS_LPOBJVAL, &val); + zero_status_check(status, "get LP value"); + return val; } -int SolverXpress::get_splex_num_of_ite_last() const -{ - int result; - int status = XPRSgetintattrib(_xprs, XPRS_SIMPLEXITER, &result); - zero_status_check(status, "get simplex iterations"); - return result; +int SolverXpress::get_splex_num_of_ite_last() const { + int result; + int status = XPRSgetintattrib(_xprs, XPRS_SIMPLEXITER, &result); + zero_status_check(status, "get simplex iterations"); + return result; } void SolverXpress::get_lp_sol(double *primals, double *duals, - double *reduced_costs) -{ - int status = XPRSgetlpsol(_xprs, primals, NULL, duals, reduced_costs); - zero_status_check(status, "get LP sol"); + double *reduced_costs) { + int status = XPRSgetlpsol(_xprs, primals, NULL, duals, reduced_costs); + zero_status_check(status, "get LP sol"); } -void SolverXpress::get_mip_sol(double *primals) -{ - int status = XPRSgetmipsol(_xprs, primals, NULL); - zero_status_check(status, "get MIP sol"); +void SolverXpress::get_mip_sol(double *primals) { + int status = XPRSgetmipsol(_xprs, primals, NULL); + zero_status_check(status, "get MIP sol"); } /************************************************************************************************* ------------------------- Methods to set algorithm or logs levels --------------------------- +------------------------ Methods to set algorithm or logs levels +--------------------------- *************************************************************************************************/ -void SolverXpress::set_output_log_level(int loglevel) -{ - int status = XPRSsetcbmessage(_xprs, optimizermsg, &get_stream()); - zero_status_check(status, "set message stream to solver stream"); - - if (loglevel > 0) - { - int status = XPRSsetintcontrol(_xprs, XPRS_OUTPUTLOG, XPRS_OUTPUTLOG_FULL_OUTPUT); - zero_status_check(status, "set log level"); - } - else - { - int status = XPRSsetintcontrol(_xprs, XPRS_OUTPUTLOG, XPRS_OUTPUTLOG_NO_OUTPUT); - zero_status_check(status, "set log level"); - } -} - -void SolverXpress::set_algorithm(std::string const &algo) -{ - if (algo == "BARRIER") - { - int status = XPRSsetintcontrol(_xprs, XPRS_DEFAULTALG, 4); - zero_status_check(status, "set barrier algorithm"); - } - else if (algo == "BARRIER_WO_CROSSOVER") - { - int status = XPRSsetintcontrol(_xprs, XPRS_DEFAULTALG, 4); - zero_status_check(status, "set barrier algorithm"); - status = XPRSsetintcontrol(_xprs, XPRS_CROSSOVER, 0); - zero_status_check(status, "desactivate barrier crossover"); - } - else if (algo == "DUAL") - { - int status = XPRSsetintcontrol(_xprs, XPRS_DEFAULTALG, 2); - zero_status_check(status, "set dual simplex algorithm"); - } - else - { - throw InvalidSolverOptionException("set_algorithm : " + algo); - } -} - -void SolverXpress::set_threads(int n_threads) -{ - int status = XPRSsetintcontrol(_xprs, XPRS_THREADS, n_threads); - zero_status_check(status, "set threads"); -} - -void SolverXpress::set_optimality_gap(double gap) -{ - int status = XPRSsetdblcontrol(_xprs, XPRS_OPTIMALITYTOL, gap); - zero_status_check(status, "set optimality gap"); -} - -void SolverXpress::set_simplex_iter(int iter) -{ - int status = XPRSsetdblcontrol(_xprs, XPRS_BARITERLIMIT, iter); - zero_status_check(status, "set barrier max iter"); - - status = XPRSsetdblcontrol(_xprs, XPRS_LPITERLIMIT, iter); - zero_status_check(status, "set simplex max iter"); -} - -void XPRS_CC optimizermsg(XPRSprob prob, void *strPtr, const char *sMsg, int nLen, - int nMsglvl) -{ - std::list *ptr = NULL; - if (strPtr != NULL) - ptr = (std::list *)strPtr; - switch (nMsglvl) - { - - /* Print Optimizer error messages and warnings */ - case 4: /* error */ - case 3: /* warning */ - case 2: /* dialogue */ - case 1: /* information */ - if (ptr != NULL) - { - for (auto const &stream : *ptr) - *stream << sMsg << std::endl; - } - else - { - std::cout << sMsg << std::endl; - } - break; - /* Exit and flush buffers */ - default: - fflush(NULL); - break; - } -} - -void errormsg(XPRSprob &_xprs, const char *sSubName, int nLineNo, int nErrCode) -{ - int nErrNo; /* Optimizer error number */ - /* Print error message */ - printf("The subroutine %s has failed on line %d\n", sSubName, nLineNo); - - /* Append the error code if it exists */ - if (nErrCode != -1) - printf("with error code %d.\n\n", nErrCode); - - /* Append Optimizer error number, if available */ - if (nErrCode == 32) - { - XPRSgetintattrib(_xprs, XPRS_ERRORCODE, &nErrNo); - printf("The Optimizer eror number is: %d\n\n", nErrNo); - } - - /* Free memory close files and exit */ - XPRSdestroyprob(_xprs); - XPRSfree(); - exit(nErrCode); +void SolverXpress::set_output_log_level(int loglevel) { + int status = XPRSsetcbmessage(_xprs, optimizermsg, &get_stream()); + zero_status_check(status, "set message stream to solver stream"); + + if (loglevel > 0) { + int status = + XPRSsetintcontrol(_xprs, XPRS_OUTPUTLOG, XPRS_OUTPUTLOG_FULL_OUTPUT); + zero_status_check(status, "set log level"); + } else { + int status = + XPRSsetintcontrol(_xprs, XPRS_OUTPUTLOG, XPRS_OUTPUTLOG_NO_OUTPUT); + zero_status_check(status, "set log level"); + } +} + +void SolverXpress::set_algorithm(std::string const &algo) { + if (algo == "BARRIER") { + int status = XPRSsetintcontrol(_xprs, XPRS_DEFAULTALG, 4); + zero_status_check(status, "set barrier algorithm"); + } else if (algo == "BARRIER_WO_CROSSOVER") { + int status = XPRSsetintcontrol(_xprs, XPRS_DEFAULTALG, 4); + zero_status_check(status, "set barrier algorithm"); + status = XPRSsetintcontrol(_xprs, XPRS_CROSSOVER, 0); + zero_status_check(status, "desactivate barrier crossover"); + } else if (algo == "DUAL") { + int status = XPRSsetintcontrol(_xprs, XPRS_DEFAULTALG, 2); + zero_status_check(status, "set dual simplex algorithm"); + } else { + throw InvalidSolverOptionException("set_algorithm : " + algo); + } +} + +void SolverXpress::set_threads(int n_threads) { + int status = XPRSsetintcontrol(_xprs, XPRS_THREADS, n_threads); + zero_status_check(status, "set threads"); +} + +void SolverXpress::set_optimality_gap(double gap) { + int status = XPRSsetdblcontrol(_xprs, XPRS_OPTIMALITYTOL, gap); + zero_status_check(status, "set optimality gap"); +} + +void SolverXpress::set_simplex_iter(int iter) { + int status = XPRSsetdblcontrol(_xprs, XPRS_BARITERLIMIT, iter); + zero_status_check(status, "set barrier max iter"); + + status = XPRSsetdblcontrol(_xprs, XPRS_LPITERLIMIT, iter); + zero_status_check(status, "set simplex max iter"); +} + +void XPRS_CC optimizermsg(XPRSprob prob, void *strPtr, const char *sMsg, + int nLen, int nMsglvl) { + std::list *ptr = NULL; + if (strPtr != NULL) ptr = (std::list *)strPtr; + switch (nMsglvl) { + /* Print Optimizer error messages and warnings */ + case 4: /* error */ + case 3: /* warning */ + case 2: /* dialogue */ + case 1: /* information */ + if (ptr != NULL) { + for (auto const &stream : *ptr) *stream << sMsg << std::endl; + } else { + std::cout << sMsg << std::endl; + } + break; + /* Exit and flush buffers */ + default: + fflush(NULL); + break; + } +} + +void errormsg(XPRSprob &_xprs, const char *sSubName, int nLineNo, + int nErrCode) { + int nErrNo; /* Optimizer error number */ + /* Print error message */ + printf("The subroutine %s has failed on line %d\n", sSubName, nLineNo); + + /* Append the error code if it exists */ + if (nErrCode != -1) printf("with error code %d.\n\n", nErrCode); + + /* Append Optimizer error number, if available */ + if (nErrCode == 32) { + XPRSgetintattrib(_xprs, XPRS_ERRORCODE, &nErrNo); + printf("The Optimizer eror number is: %d\n\n", nErrNo); + } + + /* Free memory close files and exit */ + XPRSdestroyprob(_xprs); + XPRSfree(); + exit(nErrCode); } diff --git a/src/cpp/multisolver_interface/SolverXpress.h b/src/cpp/multisolver_interface/SolverXpress.h index dbf011b86..2da567f96 100644 --- a/src/cpp/multisolver_interface/SolverXpress.h +++ b/src/cpp/multisolver_interface/SolverXpress.h @@ -7,171 +7,186 @@ * \class class SolverXpress * \brief Daughter class of AsbtractSolver implementing solver XPRESS FICO */ -class SolverXpress : public SolverAbstract -{ - - /************************************************************************************************* - ---------------------------------------- ATTRIBUTES --------------------------------------- - *************************************************************************************************/ - static int _NumberOfProblems; /*!< Counter of the total number of Cplex problems - declared to set or end the environment */ -public: - XPRSprob _xprs; /*!< Problem in XPRESS */ - - /************************************************************************************************* - ----------------------------------- Constructor/Desctructor -------------------------------- - *************************************************************************************************/ -public: - /** - * @brief Default constructor of a XPRESS solver - */ - SolverXpress(); - - /** - * @brief Copy constructor of XPRESS, copy the problem toCopy in memory and name it "name" - * - * @param toCopy : Pointer to an AbstractSolver object, containing an XPRESS solver to copy - */ - SolverXpress(const SolverAbstract::Ptr toCopy); - - virtual ~SolverXpress(); - virtual int get_number_of_instances() override; - - virtual std::string get_solver_name() const override { return "XPRESS"; } - - /************************************************************************************************* - --------------------------------- Output and stream management ----------------------------- - *************************************************************************************************/ - - /************************************************************************************************* - ------ Destruction or creation of inner strctures and datas, closing environments ---------- - *************************************************************************************************/ -public: - virtual void init() override; - virtual void free() override; - - /************************************************************************************************* - ------------------------------- Reading & Writing problems ------------------------------- - *************************************************************************************************/ -public: - virtual void write_prob_mps(const std::string &filename) override; - virtual void write_prob_lp(const std::string &filename) override; - - virtual void read_prob_mps(const std::string &filename) override; - virtual void read_prob_lp(const std::string &filename) override; - virtual void copy_prob(const SolverAbstract::Ptr fictif_solv) override; - -private: - virtual void read_prob(const char *prob_name, const char *flags) override; - - /************************************************************************************************* - ----------------------- Get general informations about problem ---------------------------- - *************************************************************************************************/ -public: - virtual int get_ncols() const override; - virtual int get_nrows() const override; - virtual int get_nelems() const override; - virtual int get_n_integer_vars() const override; - virtual void get_obj(double *obj, int first, int last) const override; - virtual void get_rows(int *mstart, int *mclind, double *dmatval, int size, int *nels, - int first, int last) const override; - virtual void get_row_type(char *qrtype, int first, int last) const override; - virtual void get_rhs(double *rhs, int first, int last) const override; - virtual void get_rhs_range(double *range, int first, int last) const override; - virtual void get_col_type(char *coltype, int first, int last) const override; - virtual void get_lb(double *lb, int fisrt, int last) const override; - virtual void get_ub(double *ub, int fisrt, int last) const override; - - virtual int get_row_index(std::string const &name) const override; - virtual int get_col_index(std::string const &name) const override; - virtual std::vector get_row_names(int first, int last) override; - virtual std::vector get_col_names(int first, int last) override; - - /************************************************************************************************* - ------------------------------ Methods to modify problem ---------------------------------- - *************************************************************************************************/ -public: - virtual void del_rows(int first, int last) override; - virtual void add_rows(int newrows, int newnz, const char *qrtype, const double *rhs, - const double *range, const int *mstart, const int *mclind, - const double *dmatval) override; - virtual void add_cols(int newcol, int newnz, const double *objx, const int *mstart, - const int *mrwind, const double *dmatval, const double *bdl, - const double *bdu) override; - virtual void add_name(int type, const char *cnames, int indice) override; - virtual void chg_obj(const std::vector &mindex, const std::vector &obj) override; - virtual void chg_bounds(const std::vector &mindex, const std::vector &qbtype, const std::vector &bnd) override; - virtual void chg_col_type(const std::vector &mindex, const std::vector &qctype) override; - virtual void chg_rhs(int id_row, double val) override; - virtual void chg_coef(int id_row, int id_col, double val) override; - virtual void chg_row_name(int id_row, std::string const &name) override; - virtual void chg_col_name(int id_col, std::string const &name) override; - - /************************************************************************************************* - ----------------------------- Methods to solve the problem --------------------------------- - *************************************************************************************************/ -public: - virtual int solve_lp() override; - virtual int solve_mip() override; - - /************************************************************************************************* - ------------------------- Methods to get solutions information ----------------------------- - *************************************************************************************************/ -public: - /** - * @brief Returns the current basis into the user’s data arrays. - * - * @param rstatus : Integer array of length ROWS to the basis status of the slack, surplus or - artifficial variable associated with each row. The status will be one of: - 0 slack, surplus or artifficial is non-basic at lower bound; - 1 slack, surplus or artifficial is basic; - 2 slack or surplus is non-basic at upper bound. - 3 slack or surplus is super-basic. - May be NULL if not required. - * @param cstatus : Integer array of length COLS to hold the basis status of the columns - in the constraint matrix. The status will be one of: - 0 variable is non-basic at lower bound, or superbasic at zero if the - variable has no lower bound; - 1 variable is basic; - 2 variable is non-basic at upper bound; - 3 variable is super-basic. - May be NULL if not required. - */ - virtual void get_basis(int *rstatus, int *cstatus) const override; - virtual double get_mip_value() const override; - virtual double get_lp_value() const override; - virtual int get_splex_num_of_ite_last() const override; - virtual void get_lp_sol(double *primals, double *duals, - double *reduced_costs) override; - virtual void get_mip_sol(double *primals) override; - - /************************************************************************************************* - ------------------------ Methods to set algorithm or logs levels --------------------------- - *************************************************************************************************/ -public: - virtual void set_output_log_level(int loglevel) override; - 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; - virtual void set_simplex_iter(int iter) override; +class SolverXpress : public SolverAbstract { + /************************************************************************************************* + ---------------------------------------- ATTRIBUTES + --------------------------------------- + *************************************************************************************************/ + static int + _NumberOfProblems; /*!< Counter of the total number of Cplex problems + declared to set or end the environment */ + public: + XPRSprob _xprs; /*!< Problem in XPRESS */ + + /************************************************************************************************* + ----------------------------------- Constructor/Desctructor + -------------------------------- + *************************************************************************************************/ + public: + /** + * @brief Default constructor of a XPRESS solver + */ + SolverXpress(); + + /** + * @brief Copy constructor of XPRESS, copy the problem toCopy in memory and + * name it "name" + * + * @param toCopy : Pointer to an AbstractSolver object, containing an XPRESS + * solver to copy + */ + SolverXpress(const SolverAbstract::Ptr toCopy); + + virtual ~SolverXpress(); + virtual int get_number_of_instances() override; + + virtual std::string get_solver_name() const override { return "XPRESS"; } + + /************************************************************************************************* + --------------------------------- Output and stream management + ----------------------------- + *************************************************************************************************/ + + /************************************************************************************************* + ------ Destruction or creation of inner strctures and datas, closing + environments ---------- + *************************************************************************************************/ + public: + virtual void init() override; + virtual void free() override; + + /************************************************************************************************* + ------------------------------- Reading & Writing problems + ------------------------------- + *************************************************************************************************/ + public: + virtual void write_prob_mps(const std::string &filename) override; + virtual void write_prob_lp(const std::string &filename) override; + + virtual void read_prob_mps(const std::string &filename) override; + virtual void read_prob_lp(const std::string &filename) override; + virtual void copy_prob(const SolverAbstract::Ptr fictif_solv) override; + + private: + virtual void read_prob(const char *prob_name, const char *flags) override; + + /************************************************************************************************* + ----------------------- Get general informations about problem + ---------------------------- + *************************************************************************************************/ + public: + virtual int get_ncols() const override; + virtual int get_nrows() const override; + virtual int get_nelems() const override; + virtual int get_n_integer_vars() const override; + virtual void get_obj(double *obj, int first, int last) const override; + virtual void get_rows(int *mstart, int *mclind, double *dmatval, int size, + int *nels, int first, int last) const override; + virtual void get_row_type(char *qrtype, int first, int last) const override; + virtual void get_rhs(double *rhs, int first, int last) const override; + virtual void get_rhs_range(double *range, int first, int last) const override; + virtual void get_col_type(char *coltype, int first, int last) const override; + virtual void get_lb(double *lb, int fisrt, int last) const override; + virtual void get_ub(double *ub, int fisrt, int last) const override; + + virtual int get_row_index(std::string const &name) const override; + virtual int get_col_index(std::string const &name) const override; + virtual std::vector get_row_names(int first, int last) override; + virtual std::vector get_col_names(int first, int last) override; + + /************************************************************************************************* + ------------------------------ Methods to modify problem + ---------------------------------- + *************************************************************************************************/ + public: + virtual void del_rows(int first, int last) override; + virtual void add_rows(int newrows, int newnz, const char *qrtype, + const double *rhs, const double *range, + const int *mstart, const int *mclind, + const double *dmatval) override; + virtual void add_cols(int newcol, int newnz, const double *objx, + const int *mstart, const int *mrwind, + const double *dmatval, const double *bdl, + const double *bdu) override; + virtual void add_name(int type, const char *cnames, int indice) override; + virtual void chg_obj(const std::vector &mindex, + const std::vector &obj) override; + virtual void chg_bounds(const std::vector &mindex, + const std::vector &qbtype, + const std::vector &bnd) override; + virtual void chg_col_type(const std::vector &mindex, + const std::vector &qctype) override; + virtual void chg_rhs(int id_row, double val) override; + virtual void chg_coef(int id_row, int id_col, double val) override; + virtual void chg_row_name(int id_row, std::string const &name) override; + virtual void chg_col_name(int id_col, std::string const &name) override; + + /************************************************************************************************* + ----------------------------- Methods to solve the problem + --------------------------------- + *************************************************************************************************/ + public: + virtual int solve_lp() override; + virtual int solve_mip() override; + + /************************************************************************************************* + ------------------------- Methods to get solutions information + ----------------------------- + *************************************************************************************************/ + public: + /** + * @brief Returns the current basis into the user’s data arrays. + * + * @param rstatus : Integer array of length ROWS to the basis status of the + slack, surplus or artifficial variable associated with each row. The status + will be one of: 0 slack, surplus or artifficial is non-basic at lower bound; + 1 slack, surplus or artifficial is basic; + 2 slack or surplus is non-basic at upper bound. + 3 slack or surplus is super-basic. + May be NULL if not required. + * @param cstatus : Integer array of length COLS to hold the basis status of + the columns in the constraint matrix. The status will be one of: 0 variable is + non-basic at lower bound, or superbasic at zero if the variable has no lower + bound; 1 variable is basic; 2 variable is non-basic at upper bound; 3 variable + is super-basic. May be NULL if not required. + */ + virtual void get_basis(int *rstatus, int *cstatus) const override; + virtual double get_mip_value() const override; + virtual double get_lp_value() const override; + virtual int get_splex_num_of_ite_last() const override; + virtual void get_lp_sol(double *primals, double *duals, + double *reduced_costs) override; + virtual void get_mip_sol(double *primals) override; + + /************************************************************************************************* + ------------------------ Methods to set algorithm or logs levels + --------------------------- + *************************************************************************************************/ + public: + virtual void set_output_log_level(int loglevel) override; + 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; + virtual void set_simplex_iter(int iter) override; }; /************************************************************************************\ -* Name: optimizermsg * -* Purpose: Display Optimizer error messages and warnings. * -* Arguments: const char *sMsg Message string * -* int nLen Message length * -* int nMsgLvl Message type * -* Return Value: None. * +* Name: optimizermsg * +* Purpose: Display Optimizer error messages and warnings. * +* Arguments: const char *sMsg Message string * +* int nLen Message length * +* int nMsgLvl Message type * +* Return Value: None. * \************************************************************************************/ void errormsg(XPRSprob &xprs, const char *sSubName, int nLineNo, int nErrCode); /************************************************************************************\ -* Name: errormsg * -* Purpose: Display error information about failed subroutines. * -* Arguments: const char *sSubName Subroutine name * -* int nLineNo Line number * -* int nErrCode Error code * -* Return Value: None * +* Name: errormsg * +* Purpose: Display error information about failed subroutines. * +* Arguments: const char *sSubName Subroutine name * +* int nLineNo Line number * +* int nErrCode Error code * +* Return Value: None * \************************************************************************************/ -void optimizermsg(XPRSprob prob, void *stream, const char *sMsg, int nLen, int nMsglvl); \ No newline at end of file +void optimizermsg(XPRSprob prob, void *stream, const char *sMsg, int nLen, + int nMsglvl); \ No newline at end of file diff --git a/src/cpp/multisolver_interface/include/multisolver_interface/SolverAbstract.h b/src/cpp/multisolver_interface/include/multisolver_interface/SolverAbstract.h index 2bd07f507..d8df29487 100644 --- a/src/cpp/multisolver_interface/include/multisolver_interface/SolverAbstract.h +++ b/src/cpp/multisolver_interface/include/multisolver_interface/SolverAbstract.h @@ -1,617 +1,627 @@ #pragma once -#include -#include -#include #include -#include +#include #include +#include #include +#include +#include -class InvalidStatusException : public std::runtime_error -{ -public: - InvalidStatusException(int status, const std::string &action) - : std::runtime_error("Failed to " + action + ": invalid status " + std::to_string(status) + " (0 expected)") - { - } +class InvalidStatusException : public std::runtime_error { + public: + InvalidStatusException(int status, const std::string &action) + : std::runtime_error("Failed to " + action + ": invalid status " + + std::to_string(status) + " (0 expected)") {} }; -class InvalidRowSizeException : public std::runtime_error -{ -public: - InvalidRowSizeException(int expected_size, int actual_size) - : std::runtime_error("Invalid row size for solver. " + std::to_string(actual_size) + " rows available (" + std::to_string(expected_size) + " expected)") - { - } +class InvalidRowSizeException : public std::runtime_error { + public: + InvalidRowSizeException(int expected_size, int actual_size) + : std::runtime_error("Invalid row size for solver. " + + std::to_string(actual_size) + " rows available (" + + std::to_string(expected_size) + " expected)") {} }; -class InvalidColSizeException : public std::runtime_error -{ -public: - InvalidColSizeException(int expected_size, int actual_size) - : std::runtime_error("Invalid col size for solver. " + std::to_string(actual_size) + " cols available (" + std::to_string(expected_size) + " expected)") - { - } +class InvalidColSizeException : public std::runtime_error { + public: + InvalidColSizeException(int expected_size, int actual_size) + : std::runtime_error("Invalid col size for solver. " + + std::to_string(actual_size) + " cols available (" + + std::to_string(expected_size) + " expected)") {} }; -class InvalidBoundTypeException : public std::runtime_error -{ -public: - InvalidBoundTypeException(char qbtype) - : std::runtime_error(std::string("Invalid bound type ") + qbtype + std::string(" for solver.")) - { - } +class InvalidBoundTypeException : public std::runtime_error { + public: + InvalidBoundTypeException(char qbtype) + : std::runtime_error(std::string("Invalid bound type ") + qbtype + + std::string(" for solver.")) {} }; -class InvalidColTypeException : public std::runtime_error -{ -public: - InvalidColTypeException(char qctype) - : std::runtime_error(std::string("Invalid col type ") + qctype + std::string(" for solver.")) - { - } +class InvalidColTypeException : public std::runtime_error { + public: + InvalidColTypeException(char qctype) + : std::runtime_error(std::string("Invalid col type ") + qctype + + std::string(" for solver.")) {} }; -class InvalidSolverOptionException : public std::runtime_error -{ -public: - InvalidSolverOptionException(const std::string &option) - : std::runtime_error("Invalid option '" + option + "' for solver.") - { - } +class InvalidSolverOptionException : public std::runtime_error { + public: + InvalidSolverOptionException(const std::string &option) + : std::runtime_error("Invalid option '" + option + "' for solver.") {} }; -class InvalidSolverForCopyException : public std::runtime_error -{ -public: - InvalidSolverForCopyException(const std::string &from_solver, const std::string &to_solver) - : std::runtime_error("Can't copy " + from_solver + "solver from " + to_solver) - { - } +class InvalidSolverForCopyException : public std::runtime_error { + public: + InvalidSolverForCopyException(const std::string &from_solver, + const std::string &to_solver) + : std::runtime_error("Can't copy " + from_solver + "solver from " + + to_solver) {} }; -class InvalidSolverNameException : public std::runtime_error -{ -public: - InvalidSolverNameException(const std::string &solver_name) - : std::runtime_error("Solver '" + solver_name + "' not supported") - { - } +class InvalidSolverNameException : public std::runtime_error { + public: + InvalidSolverNameException(const std::string &solver_name) + : std::runtime_error("Solver '" + solver_name + "' not supported") {} }; -class GenericSolverException : public std::runtime_error -{ -public: - GenericSolverException(const std::string &message) - : std::runtime_error(message) - { - } +class GenericSolverException : public std::runtime_error { + public: + GenericSolverException(const std::string &message) + : std::runtime_error(message) {} }; -class NotImplementedFeatureSolverException : public std::runtime_error -{ -public: - NotImplementedFeatureSolverException(const std::string &message) - : std::runtime_error(message) - { - } +class NotImplementedFeatureSolverException : public std::runtime_error { + public: + NotImplementedFeatureSolverException(const std::string &message) + : std::runtime_error(message) {} }; // Definition of optimality codes -enum SOLVER_STATUS -{ - OPTIMAL, - INFEASIBLE, - UNBOUNDED, - INForUNBOUND, - UNKNOWN, +enum SOLVER_STATUS { + OPTIMAL, + INFEASIBLE, + UNBOUNDED, + INForUNBOUND, + UNKNOWN, }; /*! * \class class SolverAbstract * \brief Virtual class to implement solvers methods */ -class SolverAbstract -{ - -public: - std::vector SOLVER_STRING_STATUS = { - "OPTIMAL", - "INFEASIBLE", - "UNBOUNDED", - "INForUNBOUND", - "UNKNOWN"}; - - /************************************************************************************************* - ---------------------------------------- ATTRIBUTES --------------------------------------- - *************************************************************************************************/ -public: - std::string _name; /*!< Name of the problem */ - typedef std::shared_ptr Ptr; /*!< Ptr to the solver */ - std::list _streams; /*!< List of streams to print the output (default std::cout) */ - - /************************************************************************************************* - ----------------------------------- Constructor/Desctructor -------------------------------- - *************************************************************************************************/ -public: - /** - * @brief constructor of SolverAbstract class : does nothing - */ - SolverAbstract(){}; - - /** - * @brief Copy constructor, copy the problem "toCopy" in memory and name it "name" if possible - * - * @param name : Name to give to new problem - * @param toCopy : Pointer to an AbstractSolver object, containing a solver object to copy - */ - SolverAbstract(const std::string &name, const SolverAbstract::Ptr toCopy){}; - - /** - * @brief destructor of SolverAbstract class : does nothing - */ - virtual ~SolverAbstract(){}; - - /** - * @brief Returns number of instances of solver currently in memory - */ - virtual int get_number_of_instances() = 0; - - /** - * @brief Returns the solver used - */ - virtual std::string get_solver_name() const = 0; - - /************************************************************************************************* - ----------------------------------- Output stream management ------------------------------ - *************************************************************************************************/ -public: - /** - * @brief returns the list of streams used by the solver instance - */ - std::list &get_stream() { return _streams; }; - - /** - * @brief add a stream to the list of streams used by the solver instance - * - * @param stream : reference to a std::ostream object - */ - void add_stream(std::ostream &stream) { get_stream().push_back(&stream); }; - - /** - * @brief Check if a status code is different to 0, throw InvalidStatusException if it occurs - * - * @param status : status code to check - * @param action_failed : action which returned the non zero status code, - used to print the error message. - */ - void zero_status_check(int status, const std::string &action_failed) const - { - if (status != 0) - { - throw InvalidStatusException(status, action_failed); - } - }; - - /************************************************************************************************* - ------ Destruction or creation of inner strctures and datas, closing environments ---------- - *************************************************************************************************/ -public: - /** - * @brief Initializes a problem - */ - virtual void init() = 0; - - /** - * @brief Frees all the datas contained in the Solver environment - */ - virtual void free() = 0; - - /************************************************************************************************* - ------------------------------- Reading & Writing problems ------------------------------- - *************************************************************************************************/ -public: - /** - * @brief writes an optimization problem in a MPS file - * - * @param name : name of the file to write - */ - virtual void write_prob_mps(const std::string &filename) = 0; - - /** - * @brief writes an optimization problem in a LP file - * - * @param name : name of the file to write - */ - virtual void write_prob_lp(const std::string &filename) = 0; - - /** - * @brief reads an optimization problem contained in a MPS file - * - * @param name : name of the file to read - */ - virtual void read_prob_mps(const std::string &filename) = 0; - - /** - * @brief reads an optimization problem contained in a MPS file - * - * @param name : name of the file to read - */ - virtual void read_prob_lp(const std::string &filename) = 0; - - /** - * @brief copy an existing problem - * - * @param prb_to_copy : Ptr to the - */ - virtual void copy_prob(Ptr fictif_solv) = 0; - - /************************************************************************************************* - ----------------------- Get general informations about problem ---------------------------- - *************************************************************************************************/ -public: - /** - * @brief returns number of columns of the problem - */ - virtual int get_ncols() const = 0; - - /** - * @brief returns number of rows of the problem - */ - virtual int get_nrows() const = 0; - - /** - * @brief returns number of non zeros elements in the matrix, excluding objective - */ - virtual int get_nelems() const = 0; - - /** - * @brief returns number of integer variables in the problem - */ - virtual int get_n_integer_vars() const = 0; - - /** - * @brief returns number of non zeros elements in the matrix, excluding objective - */ - virtual void get_obj(double *obj, int first, int last) const = 0; - - /** - * @brief get coefficients of rows from index first to last - * - * @param mstart : Integer array which will be filled with the indices indicating the - starting offsets in the mrwind and dmatval arrays for each requested row. - * @param mclind : array containing the column indices of the elements contained in dmatval - * @param dmatval : array containing non zero elements of the rows - * @param size : maximum number of elements to be retrieved - * @param nels : array containing number of elements in dmatval and mclind - * @param first : first index of row to get - * @param last : last index of row to get - */ - virtual void get_rows(int *mstart, int *mclind, double *dmatval, int size, int *nels, - int first, int last) const = 0; - - /** - * @brief Returns the row types for the rows in a given range. - * - * @param qrtype : Character array of length last-first+1 characters where the row - types will be returned (N, E, L, G, R) - * @param first : first index of row to get - * @param last : last index of row to get - */ - virtual void get_row_type(char *qrtype, int first, int last) const = 0; - - /** - * @brief Returns the right-hand sides of the rows in a given range. - * - * @param qrtype : Character array of length last-first+1 characters where the rhs will be stored - * @param first : first index of row to get - * @param last : last index of row to get - */ - virtual void get_rhs(double *rhs, int first, int last) const = 0; - - /** - * @brief Returns the right hand side range values for the rows in a given range. - * - * @param range : Double array of length last-first+1 where the right hand side range - values are to be placed. - * @param first : first index of row to get - * @param last : last index of row to get - */ - virtual void get_rhs_range(double *range, int first, int last) const = 0; - - /** - * @brief Returns the column types for the columns in a given range. - * - * @param coltype : Character array of length last-first+1 where the column types will - be returned (C: continuous, I: integer, B: binary, S: semi-continuous, - R: semi-continuous integer, P: partial integer) - * @param first : first index of row to get - * @param last : last index of row to get - */ - virtual void get_col_type(char *coltype, int first, int last) const = 0; - - /** - * @brief Returns the lower bounds for variables in a given range. - * - * @param lb : Double array of length last-first+1 where the lower bounds are to be placed. - * @param first : First column in the range. - * @param last : Last column in the range. - */ - virtual void get_lb(double *lb, int fisrt, int last) const = 0; - - /** - * @brief Returns the upper bounds for variables in a given range. - * - * @param lb : Double array of length last-first+1 where the upper bounds are to be placed. - * @param first : First column in the range. - * @param last : Last column in the range. - */ - virtual void get_ub(double *ub, int fisrt, int last) const = 0; - - /** - * @brief Returns the index of row named "name" - * - * @param name : name of row to get the index - */ - virtual int get_row_index(std::string const &name) const = 0; - - /** - * @brief Returns the index of column named "name" - * - * @param name : name of column to get the index - */ - virtual int get_col_index(std::string const &name) const = 0; - - /** - * @brief Returns the names of row from index first to last - * cannot be declared as const because of some solver methods - * - * @param first : first index from which name has be returned - * @param last : last index from which name has be returned - * @return names : vector of names - */ - virtual std::vector get_row_names(int first, int last) = 0; - - /** - * @brief Returns the names of columns from index first to last - * cannot be declared as const because of some solver methods - * - * @param first : first index from which name has be returned - * @param last : last index from which name has be returned - * @return names : vector of names - */ - virtual std::vector get_col_names(int first, int last) = 0; - - /************************************************************************************************* - ------------------------------ Methods to modify problem ---------------------------------- - *************************************************************************************************/ -public: - /** - * @brief Deletes rows between index first and last - * - * @param first : first row index to delete - * @param last : last row index to delete - */ - virtual void del_rows(int first, int last) = 0; - - /** - * @brief Adds rows to the problem - * - * @param newrows : Number of new rows. - * @param newnz : Number of new nonzeros in the added rows. - * @param qrtype : Character array of length newrow containing the row types: - * @param rhs : Double array of length newrow containing the right hand side elements. - * @param range : Double array of length newrow containing the row range elements - (index read only for R type rows) - * @param mstart : Integer array of length newrow + 1 containing the offsets in the mclind - and dmatval arrays of the start of the elements for each row. - * @param mclind : Integer array of length newnz containing the (contiguous) column indices - for the elements in each row. - * @param dmatval : Double array of length newnz containing the (contiguous) element values. - */ - virtual void add_rows(int newrows, int newnz, const char *qrtype, const double *rhs, - const double *range, const int *mstart, const int *mclind, - const double *dmatval) = 0; - - /** - * @brief Adds new columns to the problem - * - * @param newcol : Number of new columns. - * @param newnz : Number of new nonzeros in the added columns. - * @param objx : Double array of length newcol containing the objective function - coefficients of the new columns. - * @param mstart : Integer array of length newcol containing the offsets in the mrwind and - dmatval arrays of the start of the elements for each column. - * @param mrwind : Integer array of length newnz containing the row indices for the elements 7 - in each column. - * @param dmatval : Double array of length newnz containing the element values. - * @param bdl : Double array of length newcol containing the lower bounds on the - added columns. - * @param bdu : Double array of length newcol containing the upper bounds on the added - columns. - */ - virtual void add_cols(int newcol, int newnz, const double *objx, const int *mstart, - const int *mrwind, const double *dmatval, const double *bdl, - const double *bdu) = 0; - - /** - * @brief Adds a name to a row or a column - * - * @param type : 1 for row, 2 for column. - * @param cnames : Character buffer containing the null-terminated string names. - * @param indice : index of the row or of the column. - */ - virtual void add_name(int type, const char *cnames, int indice) = 0; - - /** - * @brief Change coefficients in objective function - * - * @param mindex : indices of columns to modify - * @param obj : Values to set in objective function - */ - virtual void chg_obj(const std::vector &mindex, const std::vector &obj) = 0; - - /** - * @brief Change bounds of some variables - * - * @param nbds : number of bounds to change - * @param mindex : indices of columns to modify - * @param qbtype : types of the bounds to modify ('U' upper, 'L' lower, 'B' both) - * @param bnd : new values for the bounds - */ - virtual void chg_bounds(const std::vector &mindex, const std::vector &qbtype, const std::vector &bnd) = 0; - - /** - * @brief Change type of some columns - * - * @param nels : number of elements to change - * @param mindex : indices of columns to modify - * @param qctype : New types of columns - */ - virtual void chg_col_type(const std::vector &mindex, const std::vector &qctype) = 0; - - /** - * @brief Change rhs of a row - * - * @param id_row : index of the row - * @param val : new rhs value - */ - virtual void chg_rhs(int id_row, double val) = 0; - - /** - * @brief Change a coefficient in the matrix - * - * @param id_row : index of the row - * @param id_col : index of the column - * @param val : new value to set in the matrix - */ - virtual void chg_coef(int id_row, int id_col, double val) = 0; - - /** - * @brief Change the name of a constraint - * - * @param id_row : index of the row - * @param name : new name of the row - */ - virtual void chg_row_name(int id_row, std::string const &name) = 0; - - /** - * @brief Change the name of a variable - * - * @param id_col : index of the column - * @param name : new name of the column - */ - virtual void chg_col_name(int id_col, std::string const &name) = 0; - - /************************************************************************************************* - ----------------------------- Methods to solve the problem --------------------------------- - *************************************************************************************************/ -public: - /** - * @brief Solves a problem as LP - * - * @return lp_status : status of the problem after resolution - */ - virtual int solve_lp() = 0; - - /** - * @brief Solves a problem as MIP - * - * @return lp_status : status of the problem after resolution - */ - virtual int solve_mip() = 0; - - /************************************************************************************************* - ------------------------- Methods to get solutions information ----------------------------- - *************************************************************************************************/ -public: - /** - * @brief Returns the current basis into the user’s data arrays. - * - * @param rstatus : Integer array of length ROWS to the basis status of the slack, surplus or - artifficial variable associated with each row. The values depend on the - solver used.May be NULL if not required. - - * @param cstatus : Integer array of length COLS to hold the basis status of the columns - in the constraint matrix. The values depend on the - solver used.May be NULL if not required. - */ - virtual void get_basis(int *rstatus, int *cstatus) const = 0; - - /** - * @brief Get the optimal value of a MIP problem (available after method "solve_mip") - * - * @return lb : optimal value of a MIP problem - */ - virtual double get_mip_value() const = 0; - - /** - * @brief Get the optimal value of a LP problem (available after method "solve_lp" ) - * - * @return lb : optimal value of a LP problem - */ - virtual double get_lp_value() const = 0; - - /** - * @brief Get the number of simplex iterations done in the last resolution of the problem - * - * @return result : number of simplex iterations done in the last resolution of the problem - */ - virtual int get_splex_num_of_ite_last() const = 0; - - /** - * @brief Get LP solution of a problem (available after method "solve_lp") - * - * @param primals : values of primal variables - * @param duals : values of dual variables - * @param reduced_cost: reduced_cost in an optimal basis - */ - virtual void get_lp_sol(double *primals, double *duals, - double *reduced_costs) = 0; - - /** - * @brief Get MIP solution of a problem (available after method "solve_mip") - * - * @param primals : values of primal variables - */ - virtual void get_mip_sol(double *primals) = 0; - - /************************************************************************************************* - ------------------------ Methods to set algorithm or logs levels --------------------------- - *************************************************************************************************/ -public: - /** - * @brief Sets log level of the solver - * - * @param loglevel : level of log to set - */ - virtual void set_output_log_level(int loglevel) = 0; - - /** - * @brief Sets algorithm used by solver to solve LP's - * - * @param algo : string of the name of the algorithm - */ - virtual void set_algorithm(std::string const &algo) = 0; - - /** - * @brief Sets the maximum number of threads used to perform optimization - * - * @param n_threads: maximum number of threads - */ - virtual void set_threads(int n_threads) = 0; - - /** - * @brief Sets the optimality gap - * - * @param gap: double of the value of wanted gap - */ - virtual void set_optimality_gap(double gap) = 0; - - /** - * @brief Sets the maximum number of simplex iterations the solver can perform - * - * @param iter: maximum number of simplex iterations - */ - virtual void set_simplex_iter(int iter) = 0; +class SolverAbstract { + public: + std::vector SOLVER_STRING_STATUS = { + "OPTIMAL", "INFEASIBLE", "UNBOUNDED", "INForUNBOUND", "UNKNOWN"}; + + /************************************************************************************************* + ---------------------------------------- ATTRIBUTES + --------------------------------------- + *************************************************************************************************/ + public: + std::string _name; /*!< Name of the problem */ + typedef std::shared_ptr Ptr; /*!< Ptr to the solver */ + std::list + _streams; /*!< List of streams to print the output (default std::cout) */ + + /************************************************************************************************* + ----------------------------------- Constructor/Desctructor + -------------------------------- + *************************************************************************************************/ + public: + /** + * @brief constructor of SolverAbstract class : does nothing + */ + SolverAbstract(){}; + + /** + * @brief Copy constructor, copy the problem "toCopy" in memory and name it + * "name" if possible + * + * @param name : Name to give to new problem + * @param toCopy : Pointer to an AbstractSolver object, containing a solver + * object to copy + */ + SolverAbstract(const std::string &name, const SolverAbstract::Ptr toCopy){}; + + /** + * @brief destructor of SolverAbstract class : does nothing + */ + virtual ~SolverAbstract(){}; + + /** + * @brief Returns number of instances of solver currently in memory + */ + virtual int get_number_of_instances() = 0; + + /** + * @brief Returns the solver used + */ + virtual std::string get_solver_name() const = 0; + + /************************************************************************************************* + ----------------------------------- Output stream management + ------------------------------ + *************************************************************************************************/ + public: + /** + * @brief returns the list of streams used by the solver instance + */ + std::list &get_stream() { return _streams; }; + + /** + * @brief add a stream to the list of streams used by the solver instance + * + * @param stream : reference to a std::ostream object + */ + void add_stream(std::ostream &stream) { get_stream().push_back(&stream); }; + + /** + * @brief Check if a status code is different to 0, throw + InvalidStatusException if it occurs + * + * @param status : status code to check + * @param action_failed : action which returned the non zero status code, + used to print the error message. + */ + void zero_status_check(int status, const std::string &action_failed) const { + if (status != 0) { + throw InvalidStatusException(status, action_failed); + } + }; + + /************************************************************************************************* + ------ Destruction or creation of inner strctures and datas, closing + environments ---------- + *************************************************************************************************/ + public: + /** + * @brief Initializes a problem + */ + virtual void init() = 0; + + /** + * @brief Frees all the datas contained in the Solver environment + */ + virtual void free() = 0; + + /************************************************************************************************* + ------------------------------- Reading & Writing problems + ------------------------------- + *************************************************************************************************/ + public: + /** + * @brief writes an optimization problem in a MPS file + * + * @param name : name of the file to write + */ + virtual void write_prob_mps(const std::string &filename) = 0; + + /** + * @brief writes an optimization problem in a LP file + * + * @param name : name of the file to write + */ + virtual void write_prob_lp(const std::string &filename) = 0; + + /** + * @brief reads an optimization problem contained in a MPS file + * + * @param name : name of the file to read + */ + virtual void read_prob_mps(const std::string &filename) = 0; + + /** + * @brief reads an optimization problem contained in a MPS file + * + * @param name : name of the file to read + */ + virtual void read_prob_lp(const std::string &filename) = 0; + + /** + * @brief copy an existing problem + * + * @param prb_to_copy : Ptr to the + */ + virtual void copy_prob(Ptr fictif_solv) = 0; + + /************************************************************************************************* + ----------------------- Get general informations about problem + ---------------------------- + *************************************************************************************************/ + public: + /** + * @brief returns number of columns of the problem + */ + virtual int get_ncols() const = 0; + + /** + * @brief returns number of rows of the problem + */ + virtual int get_nrows() const = 0; + + /** + * @brief returns number of non zeros elements in the matrix, excluding + * objective + */ + virtual int get_nelems() const = 0; + + /** + * @brief returns number of integer variables in the problem + */ + virtual int get_n_integer_vars() const = 0; + + /** + * @brief returns number of non zeros elements in the matrix, excluding + * objective + */ + virtual void get_obj(double *obj, int first, int last) const = 0; + + /** + * @brief get coefficients of rows from index first to last + * + * @param mstart : Integer array which will be filled with the indices + indicating the starting offsets in the mrwind and dmatval arrays for each + requested row. + * @param mclind : array containing the column indices of the elements + contained in dmatval + * @param dmatval : array containing non zero elements of the rows + * @param size : maximum number of elements to be retrieved + * @param nels : array containing number of elements in dmatval and + mclind + * @param first : first index of row to get + * @param last : last index of row to get + */ + virtual void get_rows(int *mstart, int *mclind, double *dmatval, int size, + int *nels, int first, int last) const = 0; + + /** + * @brief Returns the row types for the rows in a given range. + * + * @param qrtype : Character array of length last-first+1 characters where the + row types will be returned (N, E, L, G, R) + * @param first : first index of row to get + * @param last : last index of row to get + */ + virtual void get_row_type(char *qrtype, int first, int last) const = 0; + + /** + * @brief Returns the right-hand sides of the rows in a given range. + * + * @param qrtype : Character array of length last-first+1 characters where the + * rhs will be stored + * @param first : first index of row to get + * @param last : last index of row to get + */ + virtual void get_rhs(double *rhs, int first, int last) const = 0; + + /** + * @brief Returns the right hand side range values for the rows in a given + range. + * + * @param range : Double array of length last-first+1 where the right hand + side range values are to be placed. + * @param first : first index of row to get + * @param last : last index of row to get + */ + virtual void get_rhs_range(double *range, int first, int last) const = 0; + + /** + * @brief Returns the column types for the columns in a given range. + * + * @param coltype : Character array of length last-first+1 where the column + types will be returned (C: continuous, I: integer, B: binary, S: + semi-continuous, R: semi-continuous integer, P: partial integer) + * @param first : first index of row to get + * @param last : last index of row to get + */ + virtual void get_col_type(char *coltype, int first, int last) const = 0; + + /** + * @brief Returns the lower bounds for variables in a given range. + * + * @param lb : Double array of length last-first+1 where the lower bounds + * are to be placed. + * @param first : First column in the range. + * @param last : Last column in the range. + */ + virtual void get_lb(double *lb, int fisrt, int last) const = 0; + + /** + * @brief Returns the upper bounds for variables in a given range. + * + * @param lb : Double array of length last-first+1 where the upper bounds + * are to be placed. + * @param first : First column in the range. + * @param last : Last column in the range. + */ + virtual void get_ub(double *ub, int fisrt, int last) const = 0; + + /** + * @brief Returns the index of row named "name" + * + * @param name : name of row to get the index + */ + virtual int get_row_index(std::string const &name) const = 0; + + /** + * @brief Returns the index of column named "name" + * + * @param name : name of column to get the index + */ + virtual int get_col_index(std::string const &name) const = 0; + + /** + * @brief Returns the names of row from index first to last + * cannot be declared as const because of some solver methods + * + * @param first : first index from which name has be returned + * @param last : last index from which name has be returned + * @return names : vector of names + */ + virtual std::vector get_row_names(int first, int last) = 0; + + /** + * @brief Returns the names of columns from index first to last + * cannot be declared as const because of some solver methods + * + * @param first : first index from which name has be returned + * @param last : last index from which name has be returned + * @return names : vector of names + */ + virtual std::vector get_col_names(int first, int last) = 0; + + /************************************************************************************************* + ------------------------------ Methods to modify problem + ---------------------------------- + *************************************************************************************************/ + public: + /** + * @brief Deletes rows between index first and last + * + * @param first : first row index to delete + * @param last : last row index to delete + */ + virtual void del_rows(int first, int last) = 0; + + /** + * @brief Adds rows to the problem + * + * @param newrows : Number of new rows. + * @param newnz : Number of new nonzeros in the added rows. + * @param qrtype : Character array of length newrow containing the row + types: + * @param rhs : Double array of length newrow containing the right hand + side elements. + * @param range : Double array of length newrow containing the row range + elements (index read only for R type rows) + * @param mstart : Integer array of length newrow + 1 containing the + offsets in the mclind and dmatval arrays of the start of the elements for each + row. + * @param mclind : Integer array of length newnz containing the + (contiguous) column indices for the elements in each row. + * @param dmatval : Double array of length newnz containing the (contiguous) + element values. + */ + virtual void add_rows(int newrows, int newnz, const char *qrtype, + const double *rhs, const double *range, + const int *mstart, const int *mclind, + const double *dmatval) = 0; + + /** + * @brief Adds new columns to the problem + * + * @param newcol : Number of new columns. + * @param newnz : Number of new nonzeros in the added columns. + * @param objx : Double array of length newcol containing the objective + function coefficients of the new columns. + * @param mstart : Integer array of length newcol containing the offsets in + the mrwind and dmatval arrays of the start of the elements for each column. + * @param mrwind : Integer array of length newnz containing the row indices + for the elements 7 in each column. + * @param dmatval : Double array of length newnz containing the element + values. + * @param bdl : Double array of length newcol containing the lower + bounds on the added columns. + * @param bdu : Double array of length newcol containing the upper + bounds on the added columns. + */ + virtual void add_cols(int newcol, int newnz, const double *objx, + const int *mstart, const int *mrwind, + const double *dmatval, const double *bdl, + const double *bdu) = 0; + + /** + * @brief Adds a name to a row or a column + * + * @param type : 1 for row, 2 for column. + * @param cnames : Character buffer containing the null-terminated string + * names. + * @param indice : index of the row or of the column. + */ + virtual void add_name(int type, const char *cnames, int indice) = 0; + + /** + * @brief Change coefficients in objective function + * + * @param mindex : indices of columns to modify + * @param obj : Values to set in objective function + */ + virtual void chg_obj(const std::vector &mindex, + const std::vector &obj) = 0; + + /** + * @brief Change bounds of some variables + * + * @param nbds : number of bounds to change + * @param mindex : indices of columns to modify + * @param qbtype : types of the bounds to modify ('U' upper, 'L' lower, 'B' + * both) + * @param bnd : new values for the bounds + */ + virtual void chg_bounds(const std::vector &mindex, + const std::vector &qbtype, + const std::vector &bnd) = 0; + + /** + * @brief Change type of some columns + * + * @param nels : number of elements to change + * @param mindex : indices of columns to modify + * @param qctype : New types of columns + */ + virtual void chg_col_type(const std::vector &mindex, + const std::vector &qctype) = 0; + + /** + * @brief Change rhs of a row + * + * @param id_row : index of the row + * @param val : new rhs value + */ + virtual void chg_rhs(int id_row, double val) = 0; + + /** + * @brief Change a coefficient in the matrix + * + * @param id_row : index of the row + * @param id_col : index of the column + * @param val : new value to set in the matrix + */ + virtual void chg_coef(int id_row, int id_col, double val) = 0; + + /** + * @brief Change the name of a constraint + * + * @param id_row : index of the row + * @param name : new name of the row + */ + virtual void chg_row_name(int id_row, std::string const &name) = 0; + + /** + * @brief Change the name of a variable + * + * @param id_col : index of the column + * @param name : new name of the column + */ + virtual void chg_col_name(int id_col, std::string const &name) = 0; + + /************************************************************************************************* + ----------------------------- Methods to solve the problem + --------------------------------- + *************************************************************************************************/ + public: + /** + * @brief Solves a problem as LP + * + * @return lp_status : status of the problem after resolution + */ + virtual int solve_lp() = 0; + + /** + * @brief Solves a problem as MIP + * + * @return lp_status : status of the problem after resolution + */ + virtual int solve_mip() = 0; + + /************************************************************************************************* + ------------------------- Methods to get solutions information + ----------------------------- + *************************************************************************************************/ + public: + /** + * @brief Returns the current basis into the user’s data arrays. + * + * @param rstatus : Integer array of length ROWS to the basis status of the + slack, surplus or artifficial variable associated with each row. The values + depend on the solver used.May be NULL if not required. + + * @param cstatus : Integer array of length COLS to hold the basis status of + the columns in the constraint matrix. The values depend on the solver used.May + be NULL if not required. + */ + virtual void get_basis(int *rstatus, int *cstatus) const = 0; + + /** + * @brief Get the optimal value of a MIP problem (available after method + * "solve_mip") + * + * @return lb : optimal value of a MIP problem + */ + virtual double get_mip_value() const = 0; + + /** + * @brief Get the optimal value of a LP problem (available after method + * "solve_lp" ) + * + * @return lb : optimal value of a LP problem + */ + virtual double get_lp_value() const = 0; + + /** + * @brief Get the number of simplex iterations done in the last resolution of + * the problem + * + * @return result : number of simplex iterations done in the last resolution + * of the problem + */ + virtual int get_splex_num_of_ite_last() const = 0; + + /** + * @brief Get LP solution of a problem (available after method "solve_lp") + * + * @param primals : values of primal variables + * @param duals : values of dual variables + * @param reduced_cost: reduced_cost in an optimal basis + */ + virtual void get_lp_sol(double *primals, double *duals, + double *reduced_costs) = 0; + + /** + * @brief Get MIP solution of a problem (available after method "solve_mip") + * + * @param primals : values of primal variables + */ + virtual void get_mip_sol(double *primals) = 0; + + /************************************************************************************************* + ------------------------ Methods to set algorithm or logs levels + --------------------------- + *************************************************************************************************/ + public: + /** + * @brief Sets log level of the solver + * + * @param loglevel : level of log to set + */ + virtual void set_output_log_level(int loglevel) = 0; + + /** + * @brief Sets algorithm used by solver to solve LP's + * + * @param algo : string of the name of the algorithm + */ + virtual void set_algorithm(std::string const &algo) = 0; + + /** + * @brief Sets the maximum number of threads used to perform optimization + * + * @param n_threads: maximum number of threads + */ + virtual void set_threads(int n_threads) = 0; + + /** + * @brief Sets the optimality gap + * + * @param gap: double of the value of wanted gap + */ + virtual void set_optimality_gap(double gap) = 0; + + /** + * @brief Sets the maximum number of simplex iterations the solver can perform + * + * @param iter: maximum number of simplex iterations + */ + virtual void set_simplex_iter(int iter) = 0; }; diff --git a/src/cpp/multisolver_interface/include/multisolver_interface/SolverFactory.h b/src/cpp/multisolver_interface/include/multisolver_interface/SolverFactory.h index 38547e6b1..cbb0ec5d8 100644 --- a/src/cpp/multisolver_interface/include/multisolver_interface/SolverFactory.h +++ b/src/cpp/multisolver_interface/include/multisolver_interface/SolverFactory.h @@ -1,62 +1,57 @@ #pragma once -#include "multisolver_interface/SolverAbstract.h" #include -enum class SOLVER_TYPE -{ - INTEGER, - CONTINUOUS -}; -const std::string - UNKNOWN_STR("UNKNOWN"), - COIN_STR("COIN"), - CBC_STR("CBC"), - CLP_STR("CLP"), - XPRESS_STR("XPRESS"), - CPLEX_STR("CPLEX"); +#include "multisolver_interface/SolverAbstract.h" + +enum class SOLVER_TYPE { INTEGER, CONTINUOUS }; +const std::string UNKNOWN_STR("UNKNOWN"), COIN_STR("COIN"), CBC_STR("CBC"), + CLP_STR("CLP"), XPRESS_STR("XPRESS"), CPLEX_STR("CPLEX"); /*! * \class class SolverFactory - * \brief Class to manage the creation of solvers from the different implementations + * \brief Class to manage the creation of solvers from the different + * implementations */ -class SolverFactory -{ -private: - std::vector _available_solvers; - -public: - /** - * @brief Constructor of SolverFactory, fills the list of available solvers - */ - SolverFactory(); - -public: - /** - * @brief Creates and returns to an object solver from the wanted implementation - * - * @param solver_name : Name of the solver to use - */ - SolverAbstract::Ptr create_solver(const std::string &solver_name) const; - - /** - * @brief Creates and returns to an object solver from the wanted implementation - * - * @param solver_name : Name of the solver to use - * @param solver_type : Name of the solver to use - */ - SolverAbstract::Ptr create_solver(const std::string &solver_name, const SOLVER_TYPE solver_type) const; - - /** - * @brief Copy constructor : Creates and returns to an object solver from the wanted - * implementation by copying datas from same solver implementation - * - * @param to_copy : solver to copy - */ - SolverAbstract::Ptr create_solver(SolverAbstract::Ptr to_copy); - - /** - * @brief Returns a reference to the list of available solvers - */ - const std::vector &get_solvers_list() const; +class SolverFactory { + private: + std::vector _available_solvers; + + public: + /** + * @brief Constructor of SolverFactory, fills the list of available solvers + */ + SolverFactory(); + + public: + /** + * @brief Creates and returns to an object solver from the wanted + * implementation + * + * @param solver_name : Name of the solver to use + */ + SolverAbstract::Ptr create_solver(const std::string &solver_name) const; + + /** + * @brief Creates and returns to an object solver from the wanted + * implementation + * + * @param solver_name : Name of the solver to use + * @param solver_type : Name of the solver to use + */ + SolverAbstract::Ptr create_solver(const std::string &solver_name, + const SOLVER_TYPE solver_type) const; + + /** + * @brief Copy constructor : Creates and returns to an object solver from the + * wanted implementation by copying datas from same solver implementation + * + * @param to_copy : solver to copy + */ + SolverAbstract::Ptr create_solver(SolverAbstract::Ptr to_copy); + + /** + * @brief Returns a reference to the list of available solvers + */ + const std::vector &get_solvers_list() const; }; \ No newline at end of file diff --git a/tests/cpp/json_output_writer/output_writer_test.cpp b/tests/cpp/json_output_writer/output_writer_test.cpp index 9a71be8da..aa503f61c 100644 --- a/tests/cpp/json_output_writer/output_writer_test.cpp +++ b/tests/cpp/json_output_writer/output_writer_test.cpp @@ -1,206 +1,202 @@ -#include - -#include "gtest/gtest.h" +#include +#include -#include "JsonWriter.h" -#include #include -#include -#include #include +#include +#include + +#include "JsonWriter.h" +#include "gtest/gtest.h" using namespace Output; time_t time_from_date(int year, int month, int day, int hour, int min, int sec); -const std::string - CRIT_ABSOLUTE_GAP_C("absolute gap"), - CRIT_RELATIVE_GAP_C("relative gap"), - CRIT_MAX_ITER_C("maximum iterations"), - CRIT_TIMELIMIT_C("timelimit"), - STOP_ERROR_C("error"); -class ClockMock : public Clock -{ -private: - std::time_t _time; - -public: - std::time_t getTime() override - { - return _time; - } - void set_time(std::time_t time) - { - _time = time; - } +const std::string CRIT_ABSOLUTE_GAP_C("absolute gap"), + CRIT_RELATIVE_GAP_C("relative gap"), CRIT_MAX_ITER_C("maximum iterations"), + CRIT_TIMELIMIT_C("timelimit"), STOP_ERROR_C("error"); +class ClockMock : public Clock { + private: + std::time_t _time; + + public: + std::time_t getTime() override { return _time; } + void set_time(std::time_t time) { _time = time; } }; -class JsonWriterTest : public ::testing::Test -{ -public: - void SetUp() override - { - _fileName = std::tmpnam(nullptr); - } - - void TearDown() override - { - std::remove(_fileName.c_str()); - } - - std::string _fileName; - std::shared_ptr my_clock = std::make_shared(); +class JsonWriterTest : public ::testing::Test { + public: + void SetUp() override { _fileName = std::tmpnam(nullptr); } + + void TearDown() override { std::remove(_fileName.c_str()); } + + std::string _fileName; + std::shared_ptr my_clock = std::make_shared(); }; -TEST_F(JsonWriterTest, GenerateAValideFile) -{ - auto writer = JsonWriter(my_clock, _fileName); - writer.initialize(); +TEST_F(JsonWriterTest, GenerateAValideFile) { + auto writer = JsonWriter(my_clock, _fileName); + writer.initialize(); - std::ifstream fileStream(_fileName); - fileStream.close(); - ASSERT_TRUE(fileStream.good()); + std::ifstream fileStream(_fileName); + fileStream.close(); + ASSERT_TRUE(fileStream.good()); } -Json::Value get_value_from_json(const std::string &file_name) -{ - Json::Value _input; - std::ifstream input_file_l(file_name, std::ifstream::binary); - Json::CharReaderBuilder builder_l; - std::string errs; - if (!parseFromStream(builder_l, input_file_l, &_input, &errs)) - { - throw std::runtime_error(""); - } - return _input; +Json::Value get_value_from_json(const std::string &file_name) { + Json::Value _input; + std::ifstream input_file_l(file_name, std::ifstream::binary); + Json::CharReaderBuilder builder_l; + std::string errs; + if (!parseFromStream(builder_l, input_file_l, &_input, &errs)) { + throw std::runtime_error(""); + } + return _input; } -TEST_F(JsonWriterTest, InitialiseShouldPrintBeginTimeAndOptions) -{ - // given - my_clock->set_time(time_from_date(2020, 1, 1, 12, 10, 30)); - auto writer = JsonWriter(my_clock, _fileName); - // when - writer.initialize(); - // then - Json::Value json_content = get_value_from_json(_fileName); - ASSERT_EQ("01-01-2020 12:10:30", json_content[BEGIN_C].asString()); +TEST_F(JsonWriterTest, InitialiseShouldPrintBeginTimeAndOptions) { + // given + my_clock->set_time(time_from_date(2020, 1, 1, 12, 10, 30)); + auto writer = JsonWriter(my_clock, _fileName); + // when + writer.initialize(); + // then + Json::Value json_content = get_value_from_json(_fileName); + ASSERT_EQ("01-01-2020 12:10:30", json_content[BEGIN_C].asString()); } -TEST_F(JsonWriterTest, EndWritingShouldPrintEndTimeAndSimuationResults) -{ - my_clock->set_time(time_from_date(2020, 1, 1, 12, 10, 30)); - auto writer = JsonWriter(my_clock, _fileName); +TEST_F(JsonWriterTest, EndWritingShouldPrintEndTimeAndSimuationResults) { + my_clock->set_time(time_from_date(2020, 1, 1, 12, 10, 30)); + auto writer = JsonWriter(my_clock, _fileName); - IterationsData iterations_data; - writer.end_writing(iterations_data); + IterationsData iterations_data; + writer.end_writing(iterations_data); - Json::Value json_content = get_value_from_json(_fileName); - ASSERT_EQ("01-01-2020 12:10:30", json_content[END_C].asString()); + Json::Value json_content = get_value_from_json(_fileName); + ASSERT_EQ("01-01-2020 12:10:30", json_content[END_C].asString()); } -TEST_F(JsonWriterTest, EndWritingShouldPrintIterationsData) -{ - auto writer = JsonWriter(my_clock, _fileName); - - CandidateData c1, c2; - c1.name = "c1"; - c1.invest = 55; - c1.min = 0.55; - c1.max = 555; - c2.name = "c2"; - c2.invest = 66; - c2.min = 0.66; - c2.max = 666; - CandidatesVec cdVec = {c1, c2}; - - Iteration iter1; - iter1.time = 15; - iter1.lb = 1.2; - iter1.best_ub = 12; - iter1.optimality_gap = 1e-10; - iter1.relative_gap = 1e-12; - iter1.investment_cost = 1; - iter1.operational_cost = 17; - iter1.overall_cost = 20; - iter1.candidates = cdVec; - - CandidateData c3, c4; - c3.name = "c3"; - c3.invest = 33; - c3.min = 0.33; - c3.max = 5553; - c4.name = "c4"; - c4.invest = 656; - c4.min = 0.4566; - c4.max = 545666; - CandidatesVec cdVec2 = {c3, c4}; - - Iteration iter2; - iter2.time = 105; - iter2.lb = 12; - iter2.best_ub = 212; - iter2.optimality_gap = 1e-1; - iter2.relative_gap = 1e-10; - iter2.investment_cost = 12; - iter2.operational_cost = 67; - iter2.overall_cost = 620; - iter2.candidates = cdVec2; - - Iterations itersVec = {iter1, iter2}; - - SolutionData solution_data; - solution_data.solution = iter2; - solution_data.nbWeeks_p = 5; - solution_data.best_it = 2; - solution_data.problem_status = STATUS_OPTIMAL_C; - solution_data.stopping_criterion = CRIT_MAX_ITER_C; - - IterationsData iterations_data; - iterations_data.nbWeeks_p = 5; - iterations_data.elapsed_time = 55; - iterations_data.iters = itersVec; - iterations_data.solution_data = solution_data; - - writer.end_writing(iterations_data); - - Json::Value json_content = get_value_from_json(_fileName); - - ASSERT_EQ(iter1.best_ub, json_content[ITERATIONS_C]["1"][BEST_UB_C].asDouble()); - ASSERT_EQ(iter1.time, json_content[ITERATIONS_C]["1"][DURATION_C].asDouble()); - ASSERT_EQ(iter1.investment_cost, json_content[ITERATIONS_C]["1"][INVESTMENT_COST_C].asDouble()); - ASSERT_EQ(iter1.lb, json_content[ITERATIONS_C]["1"][LB_C].asDouble()); - ASSERT_EQ(iter1.operational_cost, json_content[ITERATIONS_C]["1"][OPERATIONAL_COST_C].asDouble()); - ASSERT_EQ(iter1.optimality_gap, json_content[ITERATIONS_C]["1"][OPTIMALITY_GAP_C].asDouble()); - ASSERT_EQ(iter1.relative_gap, json_content[ITERATIONS_C]["1"][RELATIVE_GAP_C].asDouble()); - ASSERT_EQ(iter1.ub, json_content[ITERATIONS_C]["1"][UB_C].asDouble()); - - ASSERT_EQ(c1.name, json_content[ITERATIONS_C]["1"][CANDIDATES_C][0][NAME_C].asString()); - ASSERT_EQ(c1.invest, json_content[ITERATIONS_C]["1"][CANDIDATES_C][0][INVEST_C].asDouble()); - ASSERT_EQ(c1.min, json_content[ITERATIONS_C]["1"][CANDIDATES_C][0][MIN_C].asDouble()); - ASSERT_EQ(c1.max, json_content[ITERATIONS_C]["1"][CANDIDATES_C][0][MAX_C].asDouble()); - - ASSERT_EQ(solution_data.solution.investment_cost, json_content[SOLUTION_C][INVESTMENT_COST_C].asDouble()); - ASSERT_EQ(solution_data.solution.operational_cost, json_content[SOLUTION_C][OPERATIONAL_COST_C].asDouble()); - ASSERT_EQ(solution_data.solution.optimality_gap, json_content[SOLUTION_C][OPTIMALITY_GAP_C].asDouble()); - ASSERT_EQ(solution_data.solution.overall_cost, json_content[SOLUTION_C][OVERALL_COST_C].asDouble()); - ASSERT_EQ(solution_data.solution.relative_gap, json_content[SOLUTION_C][RELATIVE_GAP_C].asDouble()); - ASSERT_EQ(solution_data.best_it, json_content[SOLUTION_C][ITERATION_C].asInt()); - ASSERT_EQ(solution_data.problem_status, json_content[SOLUTION_C][PROBLEM_STATUS_C].asString()); - ASSERT_EQ(solution_data.stopping_criterion, json_content[SOLUTION_C][STOPPING_CRITERION_C].asString()); +TEST_F(JsonWriterTest, EndWritingShouldPrintIterationsData) { + auto writer = JsonWriter(my_clock, _fileName); + + CandidateData c1, c2; + c1.name = "c1"; + c1.invest = 55; + c1.min = 0.55; + c1.max = 555; + c2.name = "c2"; + c2.invest = 66; + c2.min = 0.66; + c2.max = 666; + CandidatesVec cdVec = {c1, c2}; + + Iteration iter1; + iter1.time = 15; + iter1.lb = 1.2; + iter1.best_ub = 12; + iter1.optimality_gap = 1e-10; + iter1.relative_gap = 1e-12; + iter1.investment_cost = 1; + iter1.operational_cost = 17; + iter1.overall_cost = 20; + iter1.candidates = cdVec; + + CandidateData c3, c4; + c3.name = "c3"; + c3.invest = 33; + c3.min = 0.33; + c3.max = 5553; + c4.name = "c4"; + c4.invest = 656; + c4.min = 0.4566; + c4.max = 545666; + CandidatesVec cdVec2 = {c3, c4}; + + Iteration iter2; + iter2.time = 105; + iter2.lb = 12; + iter2.best_ub = 212; + iter2.optimality_gap = 1e-1; + iter2.relative_gap = 1e-10; + iter2.investment_cost = 12; + iter2.operational_cost = 67; + iter2.overall_cost = 620; + iter2.candidates = cdVec2; + + Iterations itersVec = {iter1, iter2}; + + SolutionData solution_data; + solution_data.solution = iter2; + solution_data.nbWeeks_p = 5; + solution_data.best_it = 2; + solution_data.problem_status = STATUS_OPTIMAL_C; + solution_data.stopping_criterion = CRIT_MAX_ITER_C; + + IterationsData iterations_data; + iterations_data.nbWeeks_p = 5; + iterations_data.elapsed_time = 55; + iterations_data.iters = itersVec; + iterations_data.solution_data = solution_data; + + writer.end_writing(iterations_data); + + Json::Value json_content = get_value_from_json(_fileName); + + ASSERT_EQ(iter1.best_ub, + json_content[ITERATIONS_C]["1"][BEST_UB_C].asDouble()); + ASSERT_EQ(iter1.time, json_content[ITERATIONS_C]["1"][DURATION_C].asDouble()); + ASSERT_EQ(iter1.investment_cost, + json_content[ITERATIONS_C]["1"][INVESTMENT_COST_C].asDouble()); + ASSERT_EQ(iter1.lb, json_content[ITERATIONS_C]["1"][LB_C].asDouble()); + ASSERT_EQ(iter1.operational_cost, + json_content[ITERATIONS_C]["1"][OPERATIONAL_COST_C].asDouble()); + ASSERT_EQ(iter1.optimality_gap, + json_content[ITERATIONS_C]["1"][OPTIMALITY_GAP_C].asDouble()); + ASSERT_EQ(iter1.relative_gap, + json_content[ITERATIONS_C]["1"][RELATIVE_GAP_C].asDouble()); + ASSERT_EQ(iter1.ub, json_content[ITERATIONS_C]["1"][UB_C].asDouble()); + + ASSERT_EQ( + c1.name, + json_content[ITERATIONS_C]["1"][CANDIDATES_C][0][NAME_C].asString()); + ASSERT_EQ( + c1.invest, + json_content[ITERATIONS_C]["1"][CANDIDATES_C][0][INVEST_C].asDouble()); + ASSERT_EQ(c1.min, + json_content[ITERATIONS_C]["1"][CANDIDATES_C][0][MIN_C].asDouble()); + ASSERT_EQ(c1.max, + json_content[ITERATIONS_C]["1"][CANDIDATES_C][0][MAX_C].asDouble()); + + ASSERT_EQ(solution_data.solution.investment_cost, + json_content[SOLUTION_C][INVESTMENT_COST_C].asDouble()); + ASSERT_EQ(solution_data.solution.operational_cost, + json_content[SOLUTION_C][OPERATIONAL_COST_C].asDouble()); + ASSERT_EQ(solution_data.solution.optimality_gap, + json_content[SOLUTION_C][OPTIMALITY_GAP_C].asDouble()); + ASSERT_EQ(solution_data.solution.overall_cost, + json_content[SOLUTION_C][OVERALL_COST_C].asDouble()); + ASSERT_EQ(solution_data.solution.relative_gap, + json_content[SOLUTION_C][RELATIVE_GAP_C].asDouble()); + ASSERT_EQ(solution_data.best_it, + json_content[SOLUTION_C][ITERATION_C].asInt()); + ASSERT_EQ(solution_data.problem_status, + json_content[SOLUTION_C][PROBLEM_STATUS_C].asString()); + ASSERT_EQ(solution_data.stopping_criterion, + json_content[SOLUTION_C][STOPPING_CRITERION_C].asString()); } -time_t time_from_date(int year, int month, int day, int hour, int min, int sec) -{ - time_t current_time; - struct tm time_info; - time(¤t_time); - localtime_platform(current_time, time_info); - time_info.tm_hour = hour; - time_info.tm_min = min; - time_info.tm_sec = sec; - time_info.tm_mday = day; - time_info.tm_mon = month - 1; // january = 0 - time_info.tm_year = year - 1900; - time_t my_time_t = mktime(&time_info); - return my_time_t; +time_t time_from_date(int year, int month, int day, int hour, int min, + int sec) { + time_t current_time; + struct tm time_info; + time(¤t_time); + localtime_platform(current_time, time_info); + time_info.tm_hour = hour; + time_info.tm_min = min; + time_info.tm_sec = sec; + time_info.tm_mday = day; + time_info.tm_mon = month - 1; // january = 0 + time_info.tm_year = year - 1900; + time_t my_time_t = mktime(&time_info); + return my_time_t; } diff --git a/tests/cpp/logger/logger_test.cpp b/tests/cpp/logger/logger_test.cpp index ee41962a2..4f8bd1a2f 100644 --- a/tests/cpp/logger/logger_test.cpp +++ b/tests/cpp/logger/logger_test.cpp @@ -1,472 +1,489 @@ +#include +#include #include -#include "gtest/gtest.h" - #include "core/ILogger.h" -#include "logger/User.h" +#include "gtest/gtest.h" #include "logger/Master.h" +#include "logger/User.h" #include "logger/UserFile.h" -#include -#include using namespace xpansion::logger; -class FileLoggerTest : public ::testing::Test -{ -public: - - void SetUp() - { - _fileName = std::tmpnam(nullptr); - } - - void TearDown() - { - std::remove(_fileName.c_str()); - } +class FileLoggerTest : public ::testing::Test { + public: + void SetUp() { _fileName = std::tmpnam(nullptr); } + void TearDown() { std::remove(_fileName.c_str()); } - std::string _fileName; - + std::string _fileName; }; TEST_F(FileLoggerTest, InvalidFileNotified) { + const std::string& expectedErrorString = + "Invalid file name passed as parameter"; + std::stringstream redirectedErrorStream; + std::streambuf* initialBufferCerr = + std::cerr.rdbuf(redirectedErrorStream.rdbuf()); - const std::string& expectedErrorString = "Invalid file name passed as parameter"; - std::stringstream redirectedErrorStream; - std::streambuf* initialBufferCerr = std::cerr.rdbuf(redirectedErrorStream.rdbuf()); - - UserFile userFileLogger(""); - std::cerr.rdbuf(initialBufferCerr); + UserFile userFileLogger(""); + std::cerr.rdbuf(initialBufferCerr); - ASSERT_TRUE(redirectedErrorStream.str().find(expectedErrorString) != std::string::npos); + ASSERT_TRUE(redirectedErrorStream.str().find(expectedErrorString) != + std::string::npos); } TEST_F(FileLoggerTest, EmptyFileCreatedAtInit) { - UserFile fileLog(_fileName); + UserFile fileLog(_fileName); + + std::ifstream fileStream(_fileName); + std::stringstream stringStreamFromFile; - std::ifstream fileStream(_fileName); - std::stringstream stringStreamFromFile; - - stringStreamFromFile << fileStream.rdbuf(); - fileStream.close(); + stringStreamFromFile << fileStream.rdbuf(); + fileStream.close(); - ASSERT_TRUE(fileStream.good() && stringStreamFromFile.str().empty()); + ASSERT_TRUE(fileStream.good() && stringStreamFromFile.str().empty()); } TEST_F(FileLoggerTest, FileHasBeenWritten) { - UserFile fileLog(_fileName); - const std::string& displayMessage = "Writing test"; - std::stringstream expected; - expected << displayMessage << std::endl; + UserFile fileLog(_fileName); + const std::string& displayMessage = "Writing test"; + std::stringstream expected; + expected << displayMessage << std::endl; - fileLog.display_message(displayMessage); + fileLog.display_message(displayMessage); - std::ifstream fileStream(_fileName); - std::stringstream stringStringFromFile; - - stringStringFromFile << fileStream.rdbuf(); - fileStream.close(); + std::ifstream fileStream(_fileName); + std::stringstream stringStringFromFile; - ASSERT_EQ(stringStringFromFile.str(), expected.str()); -} - -class UserLoggerTest : public ::testing::Test -{ + stringStringFromFile << fileStream.rdbuf(); + fileStream.close(); -public : + ASSERT_EQ(stringStringFromFile.str(), expected.str()); +} - const std::string indent_0 = "\t\t"; - const std::string indent_1 = "\t"; +class UserLoggerTest : public ::testing::Test { + public: + const std::string indent_0 = "\t\t"; + const std::string indent_1 = "\t"; - UserLoggerTest(): - _logger(_stream) - { - } + UserLoggerTest() : _logger(_stream) {} - void addCandidate(LogData& logData, std::string candidate, double invest, double minInvest, double maxInvest) - { - logData.x0[candidate] = invest; - logData.min_invest[candidate] = minInvest; - logData.max_invest[candidate] = maxInvest; - } + void addCandidate(LogData& logData, std::string candidate, double invest, + double minInvest, double maxInvest) { + logData.x0[candidate] = invest; + logData.min_invest[candidate] = minInvest; + logData.max_invest[candidate] = maxInvest; + } - std::stringstream _stream; - User _logger; + std::stringstream _stream; + User _logger; }; TEST_F(UserLoggerTest, EmptyStreamAtInit) { - ASSERT_EQ( _stream.str().size() ,0 ); + ASSERT_EQ(_stream.str().size(), 0); } TEST_F(UserLoggerTest, InvalidStreamNotified) { + const std::string expectedErrorString = + "Invalid stream passed as parameter\n"; - const std::string expectedErrorString = "Invalid stream passed as parameter\n"; + std::stringstream redirectedErrorStream; + std::streambuf* initialBufferCerr = + std::cerr.rdbuf(redirectedErrorStream.rdbuf()); + std::ofstream invalidStream(""); - std::stringstream redirectedErrorStream; - std::streambuf* initialBufferCerr = std::cerr.rdbuf(redirectedErrorStream.rdbuf()); - std::ofstream invalidStream(""); + User userLogger(invalidStream); - User userLogger(invalidStream); + std::cerr.rdbuf(initialBufferCerr); - std::cerr.rdbuf(initialBufferCerr); - - ASSERT_EQ(redirectedErrorStream.str(), expectedErrorString); + ASSERT_EQ(redirectedErrorStream.str(), expectedErrorString); } TEST_F(UserLoggerTest, InitLog) { - LogData logData; - logData.it = 1; - std::stringstream expected; - expected << "ITERATION 1:" << std::endl; + LogData logData; + logData.it = 1; + std::stringstream expected; + expected << "ITERATION 1:" << std::endl; - _logger.log_at_initialization(logData); - ASSERT_EQ( _stream.str() ,expected.str() ); + _logger.log_at_initialization(logData); + ASSERT_EQ(_stream.str(), expected.str()); } TEST_F(UserLoggerTest, IterationStartLogCandidateOrder) { - LogData logData; - addCandidate(logData,"z", 50.0 , 0.0, 100.0); - addCandidate(logData,"a", 10.0 , 0.0, 50.0); - addCandidate(logData,"c", 50.0 , 0.0, 100.0); - - std::stringstream expected; - expected << indent_0 << "Candidates:" << std::endl; - expected << indent_0 << indent_1 << "a = 10.00 invested MW -- possible interval [0.00; 50.00] MW" << std::endl; - expected << indent_0 << indent_1 << "c = 50.00 invested MW -- possible interval [0.00; 100.00] MW" << std::endl; - expected << indent_0 << indent_1 << "z = 50.00 invested MW -- possible interval [0.00; 100.00] MW" << std::endl; - - _logger.log_iteration_candidates(logData); - ASSERT_EQ( _stream.str() ,expected.str() ); + LogData logData; + addCandidate(logData, "z", 50.0, 0.0, 100.0); + addCandidate(logData, "a", 10.0, 0.0, 50.0); + addCandidate(logData, "c", 50.0, 0.0, 100.0); + + std::stringstream expected; + expected << indent_0 << "Candidates:" << std::endl; + expected << indent_0 << indent_1 + << "a = 10.00 invested MW -- possible interval [0.00; 50.00] MW" + << std::endl; + expected << indent_0 << indent_1 + << "c = 50.00 invested MW -- possible interval [0.00; 100.00] MW" + << std::endl; + expected << indent_0 << indent_1 + << "z = 50.00 invested MW -- possible interval [0.00; 100.00] MW" + << std::endl; + + _logger.log_iteration_candidates(logData); + ASSERT_EQ(_stream.str(), expected.str()); } TEST_F(UserLoggerTest, IterationStartLogCandidateLongInvestment) { - LogData logData; - addCandidate(logData,"z", 5000000.0 , 0.0, 10000000.0); - addCandidate(logData,"a", 10.0 , 200.0, 50.0); - addCandidate(logData,"b", 20.0 , 0.0, 200.0); - - std::stringstream expected; - expected << indent_0 <<"Candidates:" << std::endl; - expected << indent_0 << indent_1 << "a = 10.00 invested MW -- possible interval [200.00; 50.00] MW" << std::endl; - expected << indent_0 << indent_1 << "b = 20.00 invested MW -- possible interval [ 0.00; 200.00] MW" << std::endl; - expected << indent_0 << indent_1 << "z = 5000000.00 invested MW -- possible interval [ 0.00; 10000000.00] MW" << std::endl; - - _logger.log_iteration_candidates(logData); - ASSERT_EQ( _stream.str() ,expected.str() ); + LogData logData; + addCandidate(logData, "z", 5000000.0, 0.0, 10000000.0); + addCandidate(logData, "a", 10.0, 200.0, 50.0); + addCandidate(logData, "b", 20.0, 0.0, 200.0); + + std::stringstream expected; + expected << indent_0 << "Candidates:" << std::endl; + expected << indent_0 << indent_1 + << "a = 10.00 invested MW -- possible interval [200.00; " + "50.00] MW" + << std::endl; + expected << indent_0 << indent_1 + << "b = 20.00 invested MW -- possible interval [ 0.00; " + "200.00] MW" + << std::endl; + expected << indent_0 << indent_1 + << "z = 5000000.00 invested MW -- possible interval [ 0.00; " + "10000000.00] MW" + << std::endl; + + _logger.log_iteration_candidates(logData); + ASSERT_EQ(_stream.str(), expected.str()); } TEST_F(UserLoggerTest, IterationStartLogCandidateNameLenght) { - LogData logData; - addCandidate(logData,"z", 50.0 , 0.0, 100.0); - addCandidate(logData,"a", 10.0 , 0.0, 50.0); - addCandidate(logData,"very long name of investment", 50.0 , 0.0, 100.0); - - std::stringstream expected; - expected << indent_0 <<"Candidates:" << std::endl; - expected << indent_0 << indent_1 << " a = 10.00 invested MW -- possible interval [0.00; 50.00] MW" << std::endl; - expected << indent_0 << indent_1 << "very long name of investment = 50.00 invested MW -- possible interval [0.00; 100.00] MW" << std::endl; - expected << indent_0 << indent_1 << " z = 50.00 invested MW -- possible interval [0.00; 100.00] MW" << std::endl; - - _logger.log_iteration_candidates(logData); - ASSERT_EQ( _stream.str() ,expected.str() ); + LogData logData; + addCandidate(logData, "z", 50.0, 0.0, 100.0); + addCandidate(logData, "a", 10.0, 0.0, 50.0); + addCandidate(logData, "very long name of investment", 50.0, 0.0, 100.0); + + std::stringstream expected; + expected << indent_0 << "Candidates:" << std::endl; + expected << indent_0 << indent_1 + << " a = 10.00 invested MW -- possible " + "interval [0.00; 50.00] MW" + << std::endl; + expected << indent_0 << indent_1 + << "very long name of investment = 50.00 invested MW -- possible " + "interval [0.00; 100.00] MW" + << std::endl; + expected << indent_0 << indent_1 + << " z = 50.00 invested MW -- possible " + "interval [0.00; 100.00] MW" + << std::endl; + + _logger.log_iteration_candidates(logData); + ASSERT_EQ(_stream.str(), expected.str()); } TEST_F(UserLoggerTest, IterationEndLog) { - LogData logData; - logData.slave_cost = 15.5e6; - logData.invest_cost = 20e6; - logData.best_ub = 3e6; - logData.lb = 2e6; - - std::stringstream expected; - expected << indent_0 << "Solution =" << std::endl; - expected << indent_0 << indent_1 << "Operational cost = 15.50 Me" << std::endl; - expected << indent_0 << indent_1 << " Investment cost = 20.00 Me" << std::endl; - expected << indent_0 << indent_1 << " Overall cost = 35.50 Me" << std::endl; - expected << indent_0 << indent_1 << " Best Solution = 3.00 Me" << std::endl; - expected << indent_0 << indent_1 << " Lower Bound = 2.00 Me" << std::endl; - expected << indent_0 << indent_1 << " Absolute gap = 1.00000e+06 e" << std::endl; - expected << indent_0 << indent_1 << " Relative gap = 3.33333e-01" << std::endl; - - _logger.log_at_iteration_end(logData); - ASSERT_EQ( _stream.str() ,expected.str() ); + LogData logData; + logData.slave_cost = 15.5e6; + logData.invest_cost = 20e6; + logData.best_ub = 3e6; + logData.lb = 2e6; + + std::stringstream expected; + expected << indent_0 << "Solution =" << std::endl; + expected << indent_0 << indent_1 << "Operational cost = 15.50 Me" + << std::endl; + expected << indent_0 << indent_1 << " Investment cost = 20.00 Me" + << std::endl; + expected << indent_0 << indent_1 << " Overall cost = 35.50 Me" + << std::endl; + expected << indent_0 << indent_1 << " Best Solution = 3.00 Me" + << std::endl; + expected << indent_0 << indent_1 << " Lower Bound = 2.00 Me" + << std::endl; + expected << indent_0 << indent_1 << " Absolute gap = 1.00000e+06 e" + << std::endl; + expected << indent_0 << indent_1 << " Relative gap = 3.33333e-01" + << std::endl; + + _logger.log_at_iteration_end(logData); + ASSERT_EQ(_stream.str(), expected.str()); } TEST_F(UserLoggerTest, IterationEndLogLongCost) { - LogData logData; - logData.slave_cost = 150000000.5e6; - logData.invest_cost = 200000000e6; - logData.best_ub = 100e6; - logData.lb = 3e6; - - std::stringstream expected; - expected << indent_0 << "Solution =" << std::endl; - expected << indent_0 << indent_1 << "Operational cost = 150000000.50 Me" << std::endl; - expected << indent_0 << indent_1 << " Investment cost = 200000000.00 Me" << std::endl; - expected << indent_0 << indent_1 << " Overall cost = 350000000.50 Me" << std::endl; - expected << indent_0 << indent_1 << " Best Solution = 100.00 Me" << std::endl; - expected << indent_0 << indent_1 << " Lower Bound = 3.00 Me" << std::endl; - expected << indent_0 << indent_1 << " Absolute gap = 9.70000e+07 e" << std::endl; - expected << indent_0 << indent_1 << " Relative gap = 9.70000e-01" << std::endl; - - _logger.log_at_iteration_end(logData); - ASSERT_EQ( _stream.str() ,expected.str() ); + LogData logData; + logData.slave_cost = 150000000.5e6; + logData.invest_cost = 200000000e6; + logData.best_ub = 100e6; + logData.lb = 3e6; + + std::stringstream expected; + expected << indent_0 << "Solution =" << std::endl; + expected << indent_0 << indent_1 << "Operational cost = 150000000.50 Me" + << std::endl; + expected << indent_0 << indent_1 << " Investment cost = 200000000.00 Me" + << std::endl; + expected << indent_0 << indent_1 << " Overall cost = 350000000.50 Me" + << std::endl; + expected << indent_0 << indent_1 << " Best Solution = 100.00 Me" + << std::endl; + expected << indent_0 << indent_1 << " Lower Bound = 3.00 Me" + << std::endl; + expected << indent_0 << indent_1 << " Absolute gap = 9.70000e+07 e" + << std::endl; + expected << indent_0 << indent_1 << " Relative gap = 9.70000e-01" + << std::endl; + + _logger.log_at_iteration_end(logData); + ASSERT_EQ(_stream.str(), expected.str()); } -TEST_F(UserLoggerTest, MaxIterationsReached) -{ - std::stringstream expected; - expected << "--- Run completed: maximum iterations reached" << std::endl; - StoppingCriterion criterion = StoppingCriterion::max_iteration; - _logger.log_stop_criterion_reached(criterion); - ASSERT_EQ(_stream.str(), expected.str()); +TEST_F(UserLoggerTest, MaxIterationsReached) { + std::stringstream expected; + expected << "--- Run completed: maximum iterations reached" << std::endl; + StoppingCriterion criterion = StoppingCriterion::max_iteration; + _logger.log_stop_criterion_reached(criterion); + ASSERT_EQ(_stream.str(), expected.str()); } -TEST_F(UserLoggerTest, TimeLimitReached) -{ - std::stringstream expected; - expected << "--- Run completed: timelimit reached" << std::endl; - StoppingCriterion criterion = StoppingCriterion::timelimit; - _logger.log_stop_criterion_reached(criterion); - ASSERT_EQ(_stream.str(), expected.str()); +TEST_F(UserLoggerTest, TimeLimitReached) { + std::stringstream expected; + expected << "--- Run completed: timelimit reached" << std::endl; + StoppingCriterion criterion = StoppingCriterion::timelimit; + _logger.log_stop_criterion_reached(criterion); + ASSERT_EQ(_stream.str(), expected.str()); } -TEST_F(UserLoggerTest, AbsoluteGapReached) -{ - std::stringstream expected; - expected << "--- Run completed: absolute gap reached" << std::endl; - StoppingCriterion criterion = StoppingCriterion::absolute_gap; - _logger.log_stop_criterion_reached(criterion); - ASSERT_EQ(_stream.str(), expected.str()); +TEST_F(UserLoggerTest, AbsoluteGapReached) { + std::stringstream expected; + expected << "--- Run completed: absolute gap reached" << std::endl; + StoppingCriterion criterion = StoppingCriterion::absolute_gap; + _logger.log_stop_criterion_reached(criterion); + ASSERT_EQ(_stream.str(), expected.str()); } -TEST_F(UserLoggerTest, RelativeGapReached) -{ - std::stringstream expected; - expected << "--- Run completed: relative gap reached" << std::endl; - StoppingCriterion criterion = StoppingCriterion::relative_gap; - _logger.log_stop_criterion_reached(criterion); - ASSERT_EQ(_stream.str(), expected.str()); +TEST_F(UserLoggerTest, RelativeGapReached) { + std::stringstream expected; + expected << "--- Run completed: relative gap reached" << std::endl; + StoppingCriterion criterion = StoppingCriterion::relative_gap; + _logger.log_stop_criterion_reached(criterion); + ASSERT_EQ(_stream.str(), expected.str()); } TEST_F(UserLoggerTest, EndLog) { - LogData logData; - logData.best_it = 1; - logData.best_ub = 20; - logData.lb = 19.5; - logData.slave_cost = 1e6; - logData.invest_cost = 10e6; - logData.optimality_gap = 1; - logData.relative_gap = 1e-6; - logData.it = 2; - logData.max_iterations = 10; - std::stringstream expected; - expected << indent_1 << "Best solution = it 1" << std::endl; - expected << indent_1 << " Overall cost = 11.00 Me" << std::endl; - - _logger.log_at_ending(logData); - ASSERT_EQ( _stream.str() ,expected.str() ); + LogData logData; + logData.best_it = 1; + logData.best_ub = 20; + logData.lb = 19.5; + logData.slave_cost = 1e6; + logData.invest_cost = 10e6; + logData.optimality_gap = 1; + logData.relative_gap = 1e-6; + logData.it = 2; + logData.max_iterations = 10; + std::stringstream expected; + expected << indent_1 << "Best solution = it 1" << std::endl; + expected << indent_1 << " Overall cost = 11.00 Me" << std::endl; + + _logger.log_at_ending(logData); + ASSERT_EQ(_stream.str(), expected.str()); } TEST_F(UserLoggerTest, DifferentCallsAddToTheSamStream) { - LogData logData1; - logData1.it = 1; - addCandidate(logData1, "z", 5000000.0 , 0.0, 10000000.0); - addCandidate(logData1, "a", 10.0 , 200.0, 50.0); - - std::stringstream expected; - expected << indent_0 <<"Candidates:" << std::endl; - expected << indent_0 << indent_1 << "a = 10.00 invested MW -- possible interval [200.00; 50.00] MW" << std::endl; - expected << indent_0 << indent_1 << "z = 5000000.00 invested MW -- possible interval [ 0.00; 10000000.00] MW" << std::endl; - - LogData logData2; - logData2.it = 2; - addCandidate(logData2, "b", 6000000.0 , 0.0, 10000000.0); - addCandidate(logData2, "a", 200.0 , 200.0, 50.0); - - expected << indent_0 <<"Candidates:" << std::endl; - expected << indent_0 << indent_1 << "a = 200.00 invested MW -- possible interval [200.00; 50.00] MW" << std::endl; - expected << indent_0 << indent_1 << "b = 6000000.00 invested MW -- possible interval [ 0.00; 10000000.00] MW" << std::endl; - _logger.log_iteration_candidates(logData1); - _logger.log_iteration_candidates(logData2); - ASSERT_EQ( _stream.str() ,expected.str() ); + LogData logData1; + logData1.it = 1; + addCandidate(logData1, "z", 5000000.0, 0.0, 10000000.0); + addCandidate(logData1, "a", 10.0, 200.0, 50.0); + + std::stringstream expected; + expected << indent_0 << "Candidates:" << std::endl; + expected << indent_0 << indent_1 + << "a = 10.00 invested MW -- possible interval [200.00; " + "50.00] MW" + << std::endl; + expected << indent_0 << indent_1 + << "z = 5000000.00 invested MW -- possible interval [ 0.00; " + "10000000.00] MW" + << std::endl; + + LogData logData2; + logData2.it = 2; + addCandidate(logData2, "b", 6000000.0, 0.0, 10000000.0); + addCandidate(logData2, "a", 200.0, 200.0, 50.0); + + expected << indent_0 << "Candidates:" << std::endl; + expected << indent_0 << indent_1 + << "a = 200.00 invested MW -- possible interval [200.00; " + "50.00] MW" + << std::endl; + expected << indent_0 << indent_1 + << "b = 6000000.00 invested MW -- possible interval [ 0.00; " + "10000000.00] MW" + << std::endl; + _logger.log_iteration_candidates(logData1); + _logger.log_iteration_candidates(logData2); + ASSERT_EQ(_stream.str(), expected.str()); } TEST_F(UserLoggerTest, DisplayMessage) { - std::stringstream expected; - expected << "Message" << std::endl; + std::stringstream expected; + expected << "Message" << std::endl; - _logger.display_message("Message"); - ASSERT_EQ( _stream.str() ,expected.str() ); + _logger.display_message("Message"); + ASSERT_EQ(_stream.str(), expected.str()); } TEST_F(UserLoggerTest, LogMasterDuration) { - std::stringstream expected; - expected << indent_1 << "Master solved in 3 s" << std::endl; - _logger.log_master_solving_duration(3.000000); - ASSERT_EQ( _stream.str() ,expected.str() ); + std::stringstream expected; + expected << indent_1 << "Master solved in 3 s" << std::endl; + _logger.log_master_solving_duration(3.000000); + ASSERT_EQ(_stream.str(), expected.str()); } TEST_F(UserLoggerTest, LogSubProblemDuration) { - std::stringstream expected; - expected << indent_1 << "Subproblems solved in 3 s" << std::endl; - _logger.log_subproblems_solving_duration(3.000000); - ASSERT_EQ( _stream.str() ,expected.str() ); + std::stringstream expected; + expected << indent_1 << "Subproblems solved in 3 s" << std::endl; + _logger.log_subproblems_solving_duration(3.000000); + ASSERT_EQ(_stream.str(), expected.str()); } TEST_F(UserLoggerTest, LogTotalDuration) { - std::stringstream expected; - expected << "Problem ran in 3 s" << std::endl; - _logger.log_total_duration(3.000000); - ASSERT_EQ( _stream.str() ,expected.str() ); + std::stringstream expected; + expected << "Problem ran in 3 s" << std::endl; + _logger.log_total_duration(3.000000); + ASSERT_EQ(_stream.str(), expected.str()); } -class SimpleLoggerMock : public ILogger -{ -public: +class SimpleLoggerMock : public ILogger { + public: + SimpleLoggerMock() { + _initCall = false; + _iterationStartCall = false; + _iterationEndCall = false; + _endingCall = false; - SimpleLoggerMock() - { - _initCall = false; - _iterationStartCall = false; - _iterationEndCall = false; - _endingCall = false; + _stopping_criterion = StoppingCriterion::empty; - _stopping_criterion = StoppingCriterion::empty; + _durationMaster = 0.0; + _durationSubproblem = 0.0; + _durationTotal = 0.0; + } - _durationMaster = 0.0; - _durationSubproblem = 0.0; - _durationTotal = 0.0; - } + void display_message(const std::string& str) { _displaymessage = str; } - void display_message(const std::string& str) { - _displaymessage = str; - } + void log_at_initialization(const LogData& d) override { _initCall = true; } - void log_at_initialization(const LogData &d) override { - _initCall = true; - } + void log_iteration_candidates(const LogData& d) override { + _iterationStartCall = true; + } - void log_iteration_candidates(const LogData &d) override { - _iterationStartCall = true; - } + void log_master_solving_duration(double durationInSeconds) { + _durationMaster = durationInSeconds; + } - void log_master_solving_duration(double durationInSeconds) { - _durationMaster = durationInSeconds; - } + void log_subproblems_solving_duration(double durationInSeconds) { + _durationSubproblem = durationInSeconds; + } - void log_subproblems_solving_duration(double durationInSeconds) { - _durationSubproblem = durationInSeconds; - } + void log_at_iteration_end(const LogData& d) override { + _iterationEndCall = true; + } - void log_at_iteration_end(const LogData &d) override { - _iterationEndCall = true; - } + void log_at_ending(const LogData& d) override { _endingCall = true; } + void log_total_duration(double durationInSeconds) { + _durationTotal = durationInSeconds; + } - void log_at_ending(const LogData &d) override { - _endingCall = true; - } - void log_total_duration(double durationInSeconds) { - _durationTotal = durationInSeconds; - } + void log_stop_criterion_reached( + const StoppingCriterion stopping_criterion) override { + _stopping_criterion = stopping_criterion; + } - void log_stop_criterion_reached(const StoppingCriterion stopping_criterion) override{ - _stopping_criterion = stopping_criterion; - } - - bool _initCall; - bool _iterationStartCall; - bool _iterationEndCall; - bool _endingCall; - StoppingCriterion _stopping_criterion; - - std::string _displaymessage; - - double _durationMaster; - double _durationSubproblem; - double _durationTotal; + bool _initCall; + bool _iterationStartCall; + bool _iterationEndCall; + bool _endingCall; + StoppingCriterion _stopping_criterion; + std::string _displaymessage; + double _durationMaster; + double _durationSubproblem; + double _durationTotal; }; -class MasterLoggerTest : public ::testing::Test -{ -public : - - MasterLoggerTest() - { - _logger = std::make_shared(); - _logger2 = std::make_shared(); - _master.addLogger(_logger); - _master.addLogger(_logger2); - } - Master _master; - std::shared_ptr _logger; - std::shared_ptr _logger2; +class MasterLoggerTest : public ::testing::Test { + public: + MasterLoggerTest() { + _logger = std::make_shared(); + _logger2 = std::make_shared(); + _master.addLogger(_logger); + _master.addLogger(_logger2); + } + Master _master; + std::shared_ptr _logger; + std::shared_ptr _logger2; }; TEST_F(MasterLoggerTest, InitLog) { - LogData logData; - _master.log_at_initialization(logData); - ASSERT_TRUE( _logger->_initCall); - ASSERT_TRUE( _logger2->_initCall); + LogData logData; + _master.log_at_initialization(logData); + ASSERT_TRUE(_logger->_initCall); + ASSERT_TRUE(_logger2->_initCall); } TEST_F(MasterLoggerTest, IterationStartLog) { - LogData logData; - _master.log_iteration_candidates(logData); - ASSERT_TRUE( _logger->_iterationStartCall); - ASSERT_TRUE( _logger2->_iterationStartCall); + LogData logData; + _master.log_iteration_candidates(logData); + ASSERT_TRUE(_logger->_iterationStartCall); + ASSERT_TRUE(_logger2->_iterationStartCall); } TEST_F(MasterLoggerTest, IterationEndLog) { - LogData logData; - _master.log_at_iteration_end(logData); - ASSERT_TRUE( _logger->_iterationEndCall); - ASSERT_TRUE( _logger2->_iterationEndCall); + LogData logData; + _master.log_at_iteration_end(logData); + ASSERT_TRUE(_logger->_iterationEndCall); + ASSERT_TRUE(_logger2->_iterationEndCall); } TEST_F(MasterLoggerTest, EndLog) { - LogData logData; - _master.log_at_ending(logData); - ASSERT_TRUE( _logger->_endingCall); - ASSERT_TRUE( _logger2->_endingCall); + LogData logData; + _master.log_at_ending(logData); + ASSERT_TRUE(_logger->_endingCall); + ASSERT_TRUE(_logger2->_endingCall); } TEST_F(MasterLoggerTest, DisplayMessage) { - std::string message = "message"; - _master.display_message(message); - ASSERT_EQ( _logger->_displaymessage ,message ); - ASSERT_EQ( _logger2->_displaymessage ,message ); + std::string message = "message"; + _master.display_message(message); + ASSERT_EQ(_logger->_displaymessage, message); + ASSERT_EQ(_logger2->_displaymessage, message); } TEST_F(MasterLoggerTest, LogMasterDuration) { - double duration = 3.0; - _master.log_master_solving_duration(duration); - ASSERT_EQ( _logger->_durationMaster ,duration ); - ASSERT_EQ( _logger2->_durationMaster ,duration ); + double duration = 3.0; + _master.log_master_solving_duration(duration); + ASSERT_EQ(_logger->_durationMaster, duration); + ASSERT_EQ(_logger2->_durationMaster, duration); } TEST_F(MasterLoggerTest, LogSubProblemDuration) { - double duration = 3.0; - _master.log_subproblems_solving_duration(duration); - ASSERT_EQ( _logger->_durationSubproblem ,duration ); - ASSERT_EQ( _logger2->_durationSubproblem ,duration ); + double duration = 3.0; + _master.log_subproblems_solving_duration(duration); + ASSERT_EQ(_logger->_durationSubproblem, duration); + ASSERT_EQ(_logger2->_durationSubproblem, duration); } TEST_F(MasterLoggerTest, LogTotalDuration) { - double duration = 3.0; - _master.log_total_duration(duration); - ASSERT_EQ( _logger->_durationTotal ,duration ); - ASSERT_EQ( _logger2->_durationTotal ,duration ); + double duration = 3.0; + _master.log_total_duration(duration); + ASSERT_EQ(_logger->_durationTotal, duration); + ASSERT_EQ(_logger2->_durationTotal, duration); } TEST_F(MasterLoggerTest, LogStoppingCriterion) { - StoppingCriterion criterion= StoppingCriterion::absolute_gap; - _master.log_stop_criterion_reached(criterion); - ASSERT_EQ( _logger->_stopping_criterion ,StoppingCriterion::absolute_gap ); - ASSERT_EQ( _logger2->_stopping_criterion ,StoppingCriterion::absolute_gap ); + StoppingCriterion criterion = StoppingCriterion::absolute_gap; + _master.log_stop_criterion_reached(criterion); + ASSERT_EQ(_logger->_stopping_criterion, StoppingCriterion::absolute_gap); + ASSERT_EQ(_logger2->_stopping_criterion, StoppingCriterion::absolute_gap); } - - diff --git a/tests/cpp/lp_namer/ActiveLinkTest.cpp b/tests/cpp/lp_namer/ActiveLinkTest.cpp index ce6f474a1..c33aa5532 100644 --- a/tests/cpp/lp_namer/ActiveLinkTest.cpp +++ b/tests/cpp/lp_namer/ActiveLinkTest.cpp @@ -1,450 +1,430 @@ -#include "gtest/gtest.h" #include "ActiveLinks.h" +#include "gtest/gtest.h" const double DEFAULT_CAPACITY = 0; const double DEFAULT_PROFILE_VALUE = 1; -LinkProfile createProfile(std::vector& directAlreadyInstalledLinkprofile_l, std::vector& indirectAlreadyInstalledLinkprofile_l) -{ - LinkProfile profile; - profile._directLinkProfile = directAlreadyInstalledLinkprofile_l; - profile._indirectLinkProfile = indirectAlreadyInstalledLinkprofile_l; - return profile; +LinkProfile createProfile( + std::vector& directAlreadyInstalledLinkprofile_l, + std::vector& indirectAlreadyInstalledLinkprofile_l) { + LinkProfile profile; + profile._directLinkProfile = directAlreadyInstalledLinkprofile_l; + profile._indirectLinkProfile = indirectAlreadyInstalledLinkprofile_l; + return profile; } -TEST(LinkBuilderTest, one_valid_candidate_no_profile_no_capacity) -{ - CandidateData cand1; - cand1.link_id =1; - cand1.name = "transmission_line_1"; - cand1.link_name = "area1 - area2"; - cand1.already_installed_capacity = 0; - - std::vector cand_data_list = {cand1}; - - std::map profile_map; - - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - const std::vector& links = linkBuilder.getLinks(); - - ASSERT_EQ(links.size(), 1); - ASSERT_EQ(links[0].get_idLink(), 1); - ASSERT_EQ(links[0].get_LinkName(), "area1 - area2"); - ASSERT_DOUBLE_EQ(links[0].get_already_installed_capacity(), DEFAULT_CAPACITY); - for (int timeStep = 0; timeStep < 8760; timeStep++) - { - ASSERT_DOUBLE_EQ(links[0].already_installed_direct_profile(timeStep), 1); - ASSERT_DOUBLE_EQ(links[0].already_installed_indirect_profile(timeStep), 1); - } - - const auto& candidates = links[0].getCandidates(); - ASSERT_EQ(candidates.size(), 1); - ASSERT_EQ(candidates[0].get_name(), "transmission_line_1"); - for (int timeStep = 0; timeStep < 8760; timeStep++) - { - ASSERT_DOUBLE_EQ(candidates[0].direct_profile(timeStep), 1); - ASSERT_DOUBLE_EQ(candidates[0].indirect_profile(timeStep), 1); - } +TEST(LinkBuilderTest, one_valid_candidate_no_profile_no_capacity) { + CandidateData cand1; + cand1.link_id = 1; + cand1.name = "transmission_line_1"; + cand1.link_name = "area1 - area2"; + cand1.already_installed_capacity = 0; + + std::vector cand_data_list = {cand1}; + + std::map profile_map; + + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + const std::vector& links = linkBuilder.getLinks(); + + ASSERT_EQ(links.size(), 1); + ASSERT_EQ(links[0].get_idLink(), 1); + ASSERT_EQ(links[0].get_LinkName(), "area1 - area2"); + ASSERT_DOUBLE_EQ(links[0].get_already_installed_capacity(), DEFAULT_CAPACITY); + for (int timeStep = 0; timeStep < 8760; timeStep++) { + ASSERT_DOUBLE_EQ(links[0].already_installed_direct_profile(timeStep), 1); + ASSERT_DOUBLE_EQ(links[0].already_installed_indirect_profile(timeStep), 1); + } + + const auto& candidates = links[0].getCandidates(); + ASSERT_EQ(candidates.size(), 1); + ASSERT_EQ(candidates[0].get_name(), "transmission_line_1"); + for (int timeStep = 0; timeStep < 8760; timeStep++) { + ASSERT_DOUBLE_EQ(candidates[0].direct_profile(timeStep), 1); + ASSERT_DOUBLE_EQ(candidates[0].indirect_profile(timeStep), 1); + } } -TEST(LinkBuilderTest, one_valid_candidate_no_profile_with_capacity) -{ - CandidateData cand1; - cand1.link_id = 1; - cand1.name = "transmission_line_1"; - cand1.link_name = "area1 - area2"; - cand1.already_installed_capacity = 20; +TEST(LinkBuilderTest, one_valid_candidate_no_profile_with_capacity) { + CandidateData cand1; + cand1.link_id = 1; + cand1.name = "transmission_line_1"; + cand1.link_name = "area1 - area2"; + cand1.already_installed_capacity = 20; - std::vector cand_data_list = { cand1 }; + std::vector cand_data_list = {cand1}; - std::map profile_map; + std::map profile_map; - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - const std::vector& links = linkBuilder.getLinks(); - - ASSERT_DOUBLE_EQ(links[0].get_already_installed_capacity(), 20); + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + const std::vector& links = linkBuilder.getLinks(); + ASSERT_DOUBLE_EQ(links[0].get_already_installed_capacity(), 20); } -TEST(LinkBuilderTest, one_valid_candidate_with_profile_no_capacity) -{ - std::string link_profile_cand1 = "link_profile_cand1.txt"; - - CandidateData cand1; - cand1.link_id = 1; - cand1.name = "transmission_line_1"; - cand1.link_name = "area1 - area2"; - cand1.link_profile = link_profile_cand1; - cand1.already_installed_capacity = 0; - - std::vector cand_data_list = { cand1 }; - - std::map profile_map; - - std::vector directLinkprofile_l(8760, 1); - std::vector indirectLinkprofile_l(8760, 1); - - directLinkprofile_l[0] = 0; - directLinkprofile_l[1] = 0.5; - indirectLinkprofile_l[0] = 0.25; - indirectLinkprofile_l[1] = 0.75; - - const auto linkProfileCandidat1 = createProfile(directLinkprofile_l, indirectLinkprofile_l); - - profile_map[link_profile_cand1] = linkProfileCandidat1; - - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - const std::vector& links = linkBuilder.getLinks(); - - ASSERT_EQ(links.size(), 1); - ASSERT_EQ(links[0].get_idLink(), 1); - ASSERT_EQ(links[0].get_LinkName(), "area1 - area2"); - ASSERT_DOUBLE_EQ(links[0].get_already_installed_capacity(), DEFAULT_CAPACITY); - for (int timeStep = 0; timeStep < 8760; timeStep++) - { - ASSERT_DOUBLE_EQ(links[0].already_installed_direct_profile(timeStep), 1); - ASSERT_DOUBLE_EQ(links[0].already_installed_indirect_profile(timeStep), 1); - } - - const auto& candidates = links[0].getCandidates(); - ASSERT_EQ(candidates.size(), 1); - ASSERT_EQ(candidates[0].get_name(), "transmission_line_1"); - ASSERT_EQ(candidates[0].direct_profile(0), 0); - ASSERT_EQ(candidates[0].direct_profile(1), 0.5); - ASSERT_EQ(candidates[0].indirect_profile(0), 0.25); - ASSERT_EQ(candidates[0].indirect_profile(1), 0.75); - for (int timeStep = 2; timeStep < 8760; timeStep++) - { - ASSERT_DOUBLE_EQ(candidates[0].direct_profile(timeStep), 1); - ASSERT_DOUBLE_EQ(candidates[0].indirect_profile(timeStep), 1); - } +TEST(LinkBuilderTest, one_valid_candidate_with_profile_no_capacity) { + std::string link_profile_cand1 = "link_profile_cand1.txt"; + + CandidateData cand1; + cand1.link_id = 1; + cand1.name = "transmission_line_1"; + cand1.link_name = "area1 - area2"; + cand1.link_profile = link_profile_cand1; + cand1.already_installed_capacity = 0; + + std::vector cand_data_list = {cand1}; + + std::map profile_map; + + std::vector directLinkprofile_l(8760, 1); + std::vector indirectLinkprofile_l(8760, 1); + + directLinkprofile_l[0] = 0; + directLinkprofile_l[1] = 0.5; + indirectLinkprofile_l[0] = 0.25; + indirectLinkprofile_l[1] = 0.75; + + const auto linkProfileCandidat1 = + createProfile(directLinkprofile_l, indirectLinkprofile_l); + + profile_map[link_profile_cand1] = linkProfileCandidat1; + + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + const std::vector& links = linkBuilder.getLinks(); + + ASSERT_EQ(links.size(), 1); + ASSERT_EQ(links[0].get_idLink(), 1); + ASSERT_EQ(links[0].get_LinkName(), "area1 - area2"); + ASSERT_DOUBLE_EQ(links[0].get_already_installed_capacity(), DEFAULT_CAPACITY); + for (int timeStep = 0; timeStep < 8760; timeStep++) { + ASSERT_DOUBLE_EQ(links[0].already_installed_direct_profile(timeStep), 1); + ASSERT_DOUBLE_EQ(links[0].already_installed_indirect_profile(timeStep), 1); + } + + const auto& candidates = links[0].getCandidates(); + ASSERT_EQ(candidates.size(), 1); + ASSERT_EQ(candidates[0].get_name(), "transmission_line_1"); + ASSERT_EQ(candidates[0].direct_profile(0), 0); + ASSERT_EQ(candidates[0].direct_profile(1), 0.5); + ASSERT_EQ(candidates[0].indirect_profile(0), 0.25); + ASSERT_EQ(candidates[0].indirect_profile(1), 0.75); + for (int timeStep = 2; timeStep < 8760; timeStep++) { + ASSERT_DOUBLE_EQ(candidates[0].direct_profile(timeStep), 1); + ASSERT_DOUBLE_EQ(candidates[0].indirect_profile(timeStep), 1); + } } -TEST(LinkBuilderTest, two_valid_candidate_no_profile_with_capacity) -{ - CandidateData cand1; - cand1.link_id = 1; - cand1.name = "transmission_line_1"; - cand1.link_name = "area1 - area2"; - cand1.already_installed_capacity = 20; - - CandidateData cand2; - cand2.link_id = 1; - cand2.name = "transmission_line_2"; - cand2.link_name = "area1 - area2"; - cand2.already_installed_capacity = 20; - - std::vector cand_data_list = { cand1, cand2 }; - - std::map profile_map; - - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - const std::vector& links = linkBuilder.getLinks(); - - ASSERT_EQ(links.size(), 1); - ASSERT_EQ(links[0].get_idLink(), 1); - ASSERT_EQ(links[0].get_LinkName(), "area1 - area2"); - ASSERT_DOUBLE_EQ(links[0].get_already_installed_capacity(), 20); - for (int timeStep = 0; timeStep < 8760; timeStep++) - { - ASSERT_DOUBLE_EQ(links[0].already_installed_direct_profile(timeStep), 1); - ASSERT_DOUBLE_EQ(links[0].already_installed_indirect_profile(timeStep), 1); - } - - const auto& candidates = links[0].getCandidates(); - ASSERT_EQ(candidates.size(), 2); - - ASSERT_EQ(candidates[0].get_name(), "transmission_line_1"); - for (int timeStep = 0; timeStep < 8760; timeStep++) - { - ASSERT_DOUBLE_EQ(candidates[0].direct_profile(timeStep), 1); - ASSERT_DOUBLE_EQ(candidates[0].indirect_profile(timeStep), 1); - } - - ASSERT_EQ(candidates[1].get_name(), "transmission_line_2"); - for (int timeStep = 0; timeStep < 8760; timeStep++) - { - ASSERT_DOUBLE_EQ(candidates[1].direct_profile(timeStep), 1); - ASSERT_DOUBLE_EQ(candidates[1].indirect_profile(timeStep), 1); - } - +TEST(LinkBuilderTest, two_valid_candidate_no_profile_with_capacity) { + CandidateData cand1; + cand1.link_id = 1; + cand1.name = "transmission_line_1"; + cand1.link_name = "area1 - area2"; + cand1.already_installed_capacity = 20; + + CandidateData cand2; + cand2.link_id = 1; + cand2.name = "transmission_line_2"; + cand2.link_name = "area1 - area2"; + cand2.already_installed_capacity = 20; + + std::vector cand_data_list = {cand1, cand2}; + + std::map profile_map; + + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + const std::vector& links = linkBuilder.getLinks(); + + ASSERT_EQ(links.size(), 1); + ASSERT_EQ(links[0].get_idLink(), 1); + ASSERT_EQ(links[0].get_LinkName(), "area1 - area2"); + ASSERT_DOUBLE_EQ(links[0].get_already_installed_capacity(), 20); + for (int timeStep = 0; timeStep < 8760; timeStep++) { + ASSERT_DOUBLE_EQ(links[0].already_installed_direct_profile(timeStep), 1); + ASSERT_DOUBLE_EQ(links[0].already_installed_indirect_profile(timeStep), 1); + } + + const auto& candidates = links[0].getCandidates(); + ASSERT_EQ(candidates.size(), 2); + + ASSERT_EQ(candidates[0].get_name(), "transmission_line_1"); + for (int timeStep = 0; timeStep < 8760; timeStep++) { + ASSERT_DOUBLE_EQ(candidates[0].direct_profile(timeStep), 1); + ASSERT_DOUBLE_EQ(candidates[0].indirect_profile(timeStep), 1); + } + + ASSERT_EQ(candidates[1].get_name(), "transmission_line_2"); + for (int timeStep = 0; timeStep < 8760; timeStep++) { + ASSERT_DOUBLE_EQ(candidates[1].direct_profile(timeStep), 1); + ASSERT_DOUBLE_EQ(candidates[1].indirect_profile(timeStep), 1); + } } - -TEST(LinkBuilderTest, two_valid_candidates_data_on_two_different_link_no_profile_no_capacity) -{ - const double installed_capacity_link_0 = 0; - const double installed_capacity_link_1 = 0; - - CandidateData cand1; - cand1.link_id = 11; - cand1.name = "transmission_line_1"; - cand1.link_name = "area1 - area2"; - cand1.already_installed_capacity = installed_capacity_link_0; - - CandidateData cand2; - cand2.link_id = 12; - cand2.name = "pv"; - cand2.link_name = "area1 - pv"; - cand2.already_installed_capacity = installed_capacity_link_1; - - std::vector cand_data_list; - cand_data_list.push_back(cand1); - cand_data_list.push_back(cand2); - - std::map profile_map; - - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - const std::vector& links = linkBuilder.getLinks(); - - ASSERT_EQ(links.size(), 2); - ASSERT_EQ(links[0].get_idLink(), 11); - ASSERT_EQ(links[0].get_LinkName(), "area1 - area2"); - ASSERT_DOUBLE_EQ(links[0].get_already_installed_capacity(), installed_capacity_link_0); - for (int timeStep = 0; timeStep < 8760; timeStep++) - { - ASSERT_DOUBLE_EQ(links[0].already_installed_direct_profile(timeStep), 1); - ASSERT_DOUBLE_EQ(links[0].already_installed_indirect_profile(timeStep), 1); - } - - const auto& candidatesLink0 = links[0].getCandidates(); - ASSERT_EQ(candidatesLink0.size(), 1); - - ASSERT_EQ(candidatesLink0[0].get_name(), "transmission_line_1"); - for (int timeStep = 0; timeStep < 8760; timeStep++) - { - ASSERT_DOUBLE_EQ(candidatesLink0[0].direct_profile(timeStep), 1); - ASSERT_DOUBLE_EQ(candidatesLink0[0].indirect_profile(timeStep), 1); - } - - ASSERT_EQ(links[1].get_idLink(), 12); - ASSERT_EQ(links[1].get_LinkName(), "area1 - pv"); - ASSERT_DOUBLE_EQ(links[1].get_already_installed_capacity(), installed_capacity_link_1); - for (int timeStep = 0; timeStep < 8760; timeStep++) - { - ASSERT_DOUBLE_EQ(links[1].already_installed_direct_profile(timeStep), 1); - ASSERT_DOUBLE_EQ(links[1].already_installed_indirect_profile(timeStep), 1); - } - - const auto& candidatesLink1 = links[1].getCandidates(); - ASSERT_EQ(candidatesLink1.size(), 1); - - ASSERT_EQ(candidatesLink1[0].get_name(), "pv"); - for (int timeStep = 0; timeStep < 8760; timeStep++) - { - ASSERT_DOUBLE_EQ(candidatesLink1[0].direct_profile(timeStep), 1); - ASSERT_DOUBLE_EQ(candidatesLink1[0].indirect_profile(timeStep), 1); - } - +TEST(LinkBuilderTest, + two_valid_candidates_data_on_two_different_link_no_profile_no_capacity) { + const double installed_capacity_link_0 = 0; + const double installed_capacity_link_1 = 0; + + CandidateData cand1; + cand1.link_id = 11; + cand1.name = "transmission_line_1"; + cand1.link_name = "area1 - area2"; + cand1.already_installed_capacity = installed_capacity_link_0; + + CandidateData cand2; + cand2.link_id = 12; + cand2.name = "pv"; + cand2.link_name = "area1 - pv"; + cand2.already_installed_capacity = installed_capacity_link_1; + + std::vector cand_data_list; + cand_data_list.push_back(cand1); + cand_data_list.push_back(cand2); + + std::map profile_map; + + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + const std::vector& links = linkBuilder.getLinks(); + + ASSERT_EQ(links.size(), 2); + ASSERT_EQ(links[0].get_idLink(), 11); + ASSERT_EQ(links[0].get_LinkName(), "area1 - area2"); + ASSERT_DOUBLE_EQ(links[0].get_already_installed_capacity(), + installed_capacity_link_0); + for (int timeStep = 0; timeStep < 8760; timeStep++) { + ASSERT_DOUBLE_EQ(links[0].already_installed_direct_profile(timeStep), 1); + ASSERT_DOUBLE_EQ(links[0].already_installed_indirect_profile(timeStep), 1); + } + + const auto& candidatesLink0 = links[0].getCandidates(); + ASSERT_EQ(candidatesLink0.size(), 1); + + ASSERT_EQ(candidatesLink0[0].get_name(), "transmission_line_1"); + for (int timeStep = 0; timeStep < 8760; timeStep++) { + ASSERT_DOUBLE_EQ(candidatesLink0[0].direct_profile(timeStep), 1); + ASSERT_DOUBLE_EQ(candidatesLink0[0].indirect_profile(timeStep), 1); + } + + ASSERT_EQ(links[1].get_idLink(), 12); + ASSERT_EQ(links[1].get_LinkName(), "area1 - pv"); + ASSERT_DOUBLE_EQ(links[1].get_already_installed_capacity(), + installed_capacity_link_1); + for (int timeStep = 0; timeStep < 8760; timeStep++) { + ASSERT_DOUBLE_EQ(links[1].already_installed_direct_profile(timeStep), 1); + ASSERT_DOUBLE_EQ(links[1].already_installed_indirect_profile(timeStep), 1); + } + + const auto& candidatesLink1 = links[1].getCandidates(); + ASSERT_EQ(candidatesLink1.size(), 1); + + ASSERT_EQ(candidatesLink1[0].get_name(), "pv"); + for (int timeStep = 0; timeStep < 8760; timeStep++) { + ASSERT_DOUBLE_EQ(candidatesLink1[0].direct_profile(timeStep), 1); + ASSERT_DOUBLE_EQ(candidatesLink1[0].indirect_profile(timeStep), 1); + } } - -TEST(LinkBuilderTest, error_if_two_candidates_on_same_link_only_one_with_installed_profile) -{ - CandidateData cand1; - cand1.link_id = 1; - cand1.name = "transmission_line_1"; - cand1.link_name = "area1 - area2"; - - CandidateData cand2; - cand2.link_id = 1; - cand2.name = "transmission_line_2"; - cand2.link_name = "area1 - area2"; - cand2.installed_link_profile_name = "dummy"; - - std::vector cand_data_list; - cand_data_list.push_back(cand1); - cand_data_list.push_back(cand2); - std::map profile_map = {{"dummy", LinkProfile()}}; - - try { - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - FAIL() << "duplicate not detected"; - } - catch (const std::runtime_error& err) { - ASSERT_STREQ(err.what(), "Multiple already_installed_profile detected for link area1 - area2"); - } - +TEST(LinkBuilderTest, + error_if_two_candidates_on_same_link_only_one_with_installed_profile) { + CandidateData cand1; + cand1.link_id = 1; + cand1.name = "transmission_line_1"; + cand1.link_name = "area1 - area2"; + + CandidateData cand2; + cand2.link_id = 1; + cand2.name = "transmission_line_2"; + cand2.link_name = "area1 - area2"; + cand2.installed_link_profile_name = "dummy"; + + std::vector cand_data_list; + cand_data_list.push_back(cand1); + cand_data_list.push_back(cand2); + std::map profile_map = {{"dummy", LinkProfile()}}; + + try { + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + FAIL() << "duplicate not detected"; + } catch (const std::runtime_error& err) { + ASSERT_STREQ( + err.what(), + "Multiple already_installed_profile detected for link area1 - area2"); + } } -TEST(LinkBuilderTest, error_if_two_candidates_on_same_link_with_different_linkid) -{ - CandidateData cand1; - cand1.link_id = 1; - cand1.name = "transmission_line_1"; - cand1.link_name = "area1 - area2"; - - CandidateData cand2; - cand2.link_id = 2; - cand2.name = "transmission_line_2"; - cand2.link_name = "area1 - area2"; - - std::vector cand_data_list; - cand_data_list.push_back(cand1); - cand_data_list.push_back(cand2); - std::map profile_map ; - - try { - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - FAIL() << "incompatibility of link_id not detected"; - } - catch (const std::runtime_error& err) { - ASSERT_STREQ(err.what(), "Multiple link_id detected for link area1 - area2"); - } - +TEST(LinkBuilderTest, + error_if_two_candidates_on_same_link_with_different_linkid) { + CandidateData cand1; + cand1.link_id = 1; + cand1.name = "transmission_line_1"; + cand1.link_name = "area1 - area2"; + + CandidateData cand2; + cand2.link_id = 2; + cand2.name = "transmission_line_2"; + cand2.link_name = "area1 - area2"; + + std::vector cand_data_list; + cand_data_list.push_back(cand1); + cand_data_list.push_back(cand2); + std::map profile_map; + + try { + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + FAIL() << "incompatibility of link_id not detected"; + } catch (const std::runtime_error& err) { + ASSERT_STREQ(err.what(), + "Multiple link_id detected for link area1 - area2"); + } } - -TEST(LinkBuilderTest, two_candidates_same_name) -{ - CandidateData cand1; - cand1.link_id = 1; - cand1.name = "transmission_line_1"; - cand1.link_name = "area1 - area2"; - - CandidateData cand2; - cand2.link_id = 2; - cand2.name = "transmission_line_1"; - cand2.link_name = "area1 - area3"; - - std::vector cand_data_list; - cand_data_list.push_back(cand1); - cand_data_list.push_back(cand2); - std::map profile_map; - - try { - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - FAIL() << "duplicate not detected"; - } - catch (const std::runtime_error& err) { - ASSERT_STREQ(err.what(), "Candidate transmission_line_1 duplication detected"); - } - +TEST(LinkBuilderTest, two_candidates_same_name) { + CandidateData cand1; + cand1.link_id = 1; + cand1.name = "transmission_line_1"; + cand1.link_name = "area1 - area2"; + + CandidateData cand2; + cand2.link_id = 2; + cand2.name = "transmission_line_1"; + cand2.link_name = "area1 - area3"; + + std::vector cand_data_list; + cand_data_list.push_back(cand1); + cand_data_list.push_back(cand2); + std::map profile_map; + + try { + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + FAIL() << "duplicate not detected"; + } catch (const std::runtime_error& err) { + ASSERT_STREQ(err.what(), + "Candidate transmission_line_1 duplication detected"); + } } -TEST(LinkBuilderTest, one_link_two_already_installed_profile) -{ - std::string temp_already_installed_profile1_name = "temp_already_installed_profile1.txt"; - std::string temp_already_installed_profile2_name = "temp_already_installed_profile2.txt"; - - CandidateData cand1; - cand1.link_id = 1; - cand1.name = "transmission_line_1"; - cand1.link_name = "area1 - area2"; - cand1.already_installed_capacity = 0; - cand1.installed_link_profile_name = temp_already_installed_profile1_name; - - CandidateData cand2; - cand2.link_id = 1; - cand2.name = "transmission_line_2"; - cand2.link_name = "area1 - area2"; - cand2.already_installed_capacity = 0; - cand2.installed_link_profile_name = temp_already_installed_profile2_name; - - std::vector cand_data_list; - cand_data_list.push_back(cand1); - cand_data_list.push_back(cand2); - - std::vector directLinkprofile_l(8760, 1); - std::vector indirectLinkprofile_l(8760, 1); - - directLinkprofile_l[0] = 0; - directLinkprofile_l[1] = 0.5; - indirectLinkprofile_l[0] = 0.25; - indirectLinkprofile_l[1] = 0.75; - - const auto alreadyInstalledProfile = createProfile(directLinkprofile_l, indirectLinkprofile_l); - - std::map profile_map; - - profile_map[temp_already_installed_profile1_name] = alreadyInstalledProfile; - profile_map[temp_already_installed_profile2_name] = alreadyInstalledProfile; - - try { - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - FAIL() << "Candidate of the same links have different already_installed_links_profile and it's not detected"; - } - catch (const std::runtime_error& err) { - ASSERT_STREQ(err.what(), "Multiple already_installed_profile detected for link area1 - area2"); - } - +TEST(LinkBuilderTest, one_link_two_already_installed_profile) { + std::string temp_already_installed_profile1_name = + "temp_already_installed_profile1.txt"; + std::string temp_already_installed_profile2_name = + "temp_already_installed_profile2.txt"; + + CandidateData cand1; + cand1.link_id = 1; + cand1.name = "transmission_line_1"; + cand1.link_name = "area1 - area2"; + cand1.already_installed_capacity = 0; + cand1.installed_link_profile_name = temp_already_installed_profile1_name; + + CandidateData cand2; + cand2.link_id = 1; + cand2.name = "transmission_line_2"; + cand2.link_name = "area1 - area2"; + cand2.already_installed_capacity = 0; + cand2.installed_link_profile_name = temp_already_installed_profile2_name; + + std::vector cand_data_list; + cand_data_list.push_back(cand1); + cand_data_list.push_back(cand2); + + std::vector directLinkprofile_l(8760, 1); + std::vector indirectLinkprofile_l(8760, 1); + + directLinkprofile_l[0] = 0; + directLinkprofile_l[1] = 0.5; + indirectLinkprofile_l[0] = 0.25; + indirectLinkprofile_l[1] = 0.75; + + const auto alreadyInstalledProfile = + createProfile(directLinkprofile_l, indirectLinkprofile_l); + + std::map profile_map; + + profile_map[temp_already_installed_profile1_name] = alreadyInstalledProfile; + profile_map[temp_already_installed_profile2_name] = alreadyInstalledProfile; + + try { + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + FAIL() << "Candidate of the same links have different " + "already_installed_links_profile and it's not detected"; + } catch (const std::runtime_error& err) { + ASSERT_STREQ( + err.what(), + "Multiple already_installed_profile detected for link area1 - area2"); + } } - -TEST(LinkBuilderTest, one_link_with_two_different_already_installed_capacity) -{ - CandidateData cand1; - cand1.link_id = 1; - cand1.name = "transmission_line_1"; - cand1.link_name = "area1 - area2"; - cand1.already_installed_capacity = 20; - - CandidateData cand2; - cand2.link_id = 1; - cand2.name = "transmission_line_2"; - cand2.link_name = "area1 - area2"; - cand2.already_installed_capacity = 30; - - std::vector cand_data_list; - cand_data_list.push_back(cand1); - cand_data_list.push_back(cand2); - - std::map profile_map; - - try { - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - FAIL() << "Same alreadyInstalledCapacity : not detected"; - } - catch (const std::runtime_error& err) { - ASSERT_STREQ(err.what(), "Multiple already installed capacity detected for link area1 - area2"); - } +TEST(LinkBuilderTest, one_link_with_two_different_already_installed_capacity) { + CandidateData cand1; + cand1.link_id = 1; + cand1.name = "transmission_line_1"; + cand1.link_name = "area1 - area2"; + cand1.already_installed_capacity = 20; + + CandidateData cand2; + cand2.link_id = 1; + cand2.name = "transmission_line_2"; + cand2.link_name = "area1 - area2"; + cand2.already_installed_capacity = 30; + + std::vector cand_data_list; + cand_data_list.push_back(cand1); + cand_data_list.push_back(cand2); + + std::map profile_map; + + try { + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + FAIL() << "Same alreadyInstalledCapacity : not detected"; + } catch (const std::runtime_error& err) { + ASSERT_STREQ( + err.what(), + "Multiple already installed capacity detected for link area1 - area2"); + } } -TEST(LinkBuilderTest, missing_link_profile_in_profile_map) -{ - std::string cand_profile1_name = "cand1Profile.txt"; - CandidateData cand1; - cand1.link_id = 1; - cand1.name = "transmission_line_1"; - cand1.link_name = "area1 - area2"; - cand1.link_profile = cand_profile1_name; - cand1.already_installed_capacity = 20; - - std::vector cand_data_list; - cand_data_list.push_back(cand1); - - std::map profile_map; - - try { - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - FAIL() << "Missing link profile : not detected"; - } - catch (const std::runtime_error& err) { - ASSERT_STREQ(err.what(), "There is no linkProfile associated with cand1Profile.txt"); - } +TEST(LinkBuilderTest, missing_link_profile_in_profile_map) { + std::string cand_profile1_name = "cand1Profile.txt"; + CandidateData cand1; + cand1.link_id = 1; + cand1.name = "transmission_line_1"; + cand1.link_name = "area1 - area2"; + cand1.link_profile = cand_profile1_name; + cand1.already_installed_capacity = 20; + + std::vector cand_data_list; + cand_data_list.push_back(cand1); + + std::map profile_map; + + try { + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + FAIL() << "Missing link profile : not detected"; + } catch (const std::runtime_error& err) { + ASSERT_STREQ(err.what(), + "There is no linkProfile associated with cand1Profile.txt"); + } } -TEST(LinkBuilderTest, candidate_not_enable) -{ - CandidateData cand1; - cand1.link_id = 1; - cand1.name = "transmission_line_1"; - cand1.link_name = "area1 - area2"; - cand1.enable = true; - - CandidateData cand2; - cand2.link_id = 1; - cand2.name = "transmission_line_2"; - cand2.link_name = "area1 - area2"; - cand2.enable = false; - - std::vector cand_data_list; - cand_data_list.push_back(cand1); - cand_data_list.push_back(cand2); - std::map profile_map ; - - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - const std::vector& links = linkBuilder.getLinks(); - const auto& candidates = links[0].getCandidates(); - ASSERT_EQ(candidates.size(), 1); +TEST(LinkBuilderTest, candidate_not_enable) { + CandidateData cand1; + cand1.link_id = 1; + cand1.name = "transmission_line_1"; + cand1.link_name = "area1 - area2"; + cand1.enable = true; + + CandidateData cand2; + cand2.link_id = 1; + cand2.name = "transmission_line_2"; + cand2.link_name = "area1 - area2"; + cand2.enable = false; + + std::vector cand_data_list; + cand_data_list.push_back(cand1); + cand_data_list.push_back(cand2); + std::map profile_map; + + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + const std::vector& links = linkBuilder.getLinks(); + const auto& candidates = links[0].getCandidates(); + ASSERT_EQ(candidates.size(), 1); } diff --git a/tests/cpp/lp_namer/CandidatesINIReaderTest.cpp b/tests/cpp/lp_namer/CandidatesINIReaderTest.cpp index 8fca9ff9a..ca3c4927b 100644 --- a/tests/cpp/lp_namer/CandidatesINIReaderTest.cpp +++ b/tests/cpp/lp_namer/CandidatesINIReaderTest.cpp @@ -1,129 +1,126 @@ -#include "gtest/gtest.h" - #include #include "CandidatesINIReader.h" +#include "gtest/gtest.h" -class CandidatesINIReaderTest : public ::testing::Test -{ -protected: - static void SetUpTestCase() - { - // called before 1st test - std::string interco_content_l = "0 0 1\n" - "1 0 3\n" - "2 0 5\n" - "3 1 2\n" - "4 1 4"; - - // dummy interco tmp file name - std::ofstream file_interco("temp_interco.txt"); - file_interco << interco_content_l; - file_interco.close(); - - std::string area_content_l = "area1\n" - "area2\n" - "flex\n" - "peak\n" - "pv\n" - "semibase"; - - // dummy area tmp file name - std::ofstream file_area("temp_area.txt"); - file_area << area_content_l; - file_area.close(); - - std::string candidate_content_l = "[1]\n" - "name = semibase\n" - "link = area1 - semibase\n" - "annual-cost-per-mw = 126000\n" - "unit-size = 200\n" - "max-units = 10\n" - "enable = true\n" - "\n" - "[2]\n" - "name = peak\n" - "link = area1 - peak\n" - "annual-cost-per-mw = 60000\n" - "unit-size = 100\n" - "max-units = 20\n" - "enable = false\n" - "\n" - "[3]\n" - "name = peak2\n" - "link = area1 - peak\n" - "annual-cost-per-mw = 30000\n" - "unit-size = 100\n" - "max-units = 20"; - - // dummy area tmp file name - std::ofstream file_candidate("temp_candidate.ini"); - file_candidate << candidate_content_l; - file_candidate.close(); - } - - static void TearDownTestCase() - { - // called after last test - - //delete the created tmp file - std::remove("temp_interco.txt"); - std::remove("temp_area.txt"); - std::remove("temp_candidate.ini"); - } - - void SetUp() - { - // called before each test - } - - void TearDown() - { - // called after each test - } +class CandidatesINIReaderTest : public ::testing::Test { + protected: + static void SetUpTestCase() { + // called before 1st test + std::string interco_content_l = + "0 0 1\n" + "1 0 3\n" + "2 0 5\n" + "3 1 2\n" + "4 1 4"; + + // dummy interco tmp file name + std::ofstream file_interco("temp_interco.txt"); + file_interco << interco_content_l; + file_interco.close(); + + std::string area_content_l = + "area1\n" + "area2\n" + "flex\n" + "peak\n" + "pv\n" + "semibase"; + + // dummy area tmp file name + std::ofstream file_area("temp_area.txt"); + file_area << area_content_l; + file_area.close(); + + std::string candidate_content_l = + "[1]\n" + "name = semibase\n" + "link = area1 - semibase\n" + "annual-cost-per-mw = 126000\n" + "unit-size = 200\n" + "max-units = 10\n" + "enable = true\n" + "\n" + "[2]\n" + "name = peak\n" + "link = area1 - peak\n" + "annual-cost-per-mw = 60000\n" + "unit-size = 100\n" + "max-units = 20\n" + "enable = false\n" + "\n" + "[3]\n" + "name = peak2\n" + "link = area1 - peak\n" + "annual-cost-per-mw = 30000\n" + "unit-size = 100\n" + "max-units = 20"; + + // dummy area tmp file name + std::ofstream file_candidate("temp_candidate.ini"); + file_candidate << candidate_content_l; + file_candidate.close(); + } + + static void TearDownTestCase() { + // called after last test + + // delete the created tmp file + std::remove("temp_interco.txt"); + std::remove("temp_area.txt"); + std::remove("temp_candidate.ini"); + } + + void SetUp() { + // called before each test + } + + void TearDown() { + // called after each test + } }; TEST_F(CandidatesINIReaderTest, testReadIntero) { + std::vector intercoDataList = + CandidatesINIReader::ReadAntaresIntercoFile("temp_interco.txt"); - std::vector intercoDataList = CandidatesINIReader::ReadAntaresIntercoFile("temp_interco.txt"); - - ASSERT_EQ(intercoDataList[0].index_interco, 0); - ASSERT_EQ(intercoDataList[0].index_pays_origine, 0); - ASSERT_EQ(intercoDataList[0].index_pays_extremite, 1); + ASSERT_EQ(intercoDataList[0].index_interco, 0); + ASSERT_EQ(intercoDataList[0].index_pays_origine, 0); + ASSERT_EQ(intercoDataList[0].index_pays_extremite, 1); } TEST_F(CandidatesINIReaderTest, testReadArea) { + std::vector areaList = + CandidatesINIReader::ReadAreaFile("temp_area.txt"); - std::vector areaList = CandidatesINIReader::ReadAreaFile("temp_area.txt"); - - ASSERT_EQ(areaList[0], "area1"); - ASSERT_EQ(areaList[1], "area2"); - ASSERT_EQ(areaList[2], "flex"); + ASSERT_EQ(areaList[0], "area1"); + ASSERT_EQ(areaList[1], "area2"); + ASSERT_EQ(areaList[2], "flex"); } -TEST_F(CandidatesINIReaderTest, testReadCandidate) -{ - CandidatesINIReader reader("temp_interco.txt","temp_area.txt"); +TEST_F(CandidatesINIReaderTest, testReadCandidate) { + CandidatesINIReader reader("temp_interco.txt", "temp_area.txt"); - std::vector candidates_data = reader.readCandidateData("temp_candidate.ini"); + std::vector candidates_data = + reader.readCandidateData("temp_candidate.ini"); - ASSERT_EQ(candidates_data.size(), 3); + ASSERT_EQ(candidates_data.size(), 3); - ASSERT_EQ(candidates_data[0].name, "semibase"); - ASSERT_EQ(candidates_data[0].link_name, "area1 - semibase"); - ASSERT_EQ(candidates_data[0].link_id, 2); - ASSERT_EQ(candidates_data[0].enable, true); - ASSERT_DOUBLE_EQ(candidates_data[0].annual_cost_per_mw, 126000); + ASSERT_EQ(candidates_data[0].name, "semibase"); + ASSERT_EQ(candidates_data[0].link_name, "area1 - semibase"); + ASSERT_EQ(candidates_data[0].link_id, 2); + ASSERT_EQ(candidates_data[0].enable, true); + ASSERT_DOUBLE_EQ(candidates_data[0].annual_cost_per_mw, 126000); - ASSERT_EQ(candidates_data[1].name, "peak"); - ASSERT_EQ(candidates_data[1].link_name, "area1 - peak"); - ASSERT_EQ(candidates_data[1].link_id, 1); - ASSERT_EQ(candidates_data[1].enable, false); - ASSERT_DOUBLE_EQ(candidates_data[1].annual_cost_per_mw, 60000); + ASSERT_EQ(candidates_data[1].name, "peak"); + ASSERT_EQ(candidates_data[1].link_name, "area1 - peak"); + ASSERT_EQ(candidates_data[1].link_id, 1); + ASSERT_EQ(candidates_data[1].enable, false); + ASSERT_DOUBLE_EQ(candidates_data[1].annual_cost_per_mw, 60000); - ASSERT_EQ(candidates_data[2].name, "peak2"); - ASSERT_EQ(candidates_data[2].link_name, "area1 - peak"); - ASSERT_EQ(candidates_data[2].link_id, 1); - ASSERT_EQ(candidates_data[2].enable, true); - ASSERT_DOUBLE_EQ(candidates_data[2].annual_cost_per_mw, 30000); + ASSERT_EQ(candidates_data[2].name, "peak2"); + ASSERT_EQ(candidates_data[2].link_name, "area1 - peak"); + ASSERT_EQ(candidates_data[2].link_id, 1); + ASSERT_EQ(candidates_data[2].enable, true); + ASSERT_DOUBLE_EQ(candidates_data[2].annual_cost_per_mw, 30000); } diff --git a/tests/cpp/lp_namer/LinkProfileReaderTest.cpp b/tests/cpp/lp_namer/LinkProfileReaderTest.cpp index ca12c415f..577cef3fb 100644 --- a/tests/cpp/lp_namer/LinkProfileReaderTest.cpp +++ b/tests/cpp/lp_namer/LinkProfileReaderTest.cpp @@ -1,106 +1,99 @@ -#include "gtest/gtest.h" - #include + #include "LinkProfileReader.h" +#include "gtest/gtest.h" -const char* VALID_PROFILE_NAME= "temp_profile.txt"; +const char* VALID_PROFILE_NAME = "temp_profile.txt"; const char* INVALID_PROFILE_NAME = "temp_invalid_profile.txt"; +class LinkProfileReaderTest : public ::testing::Test { + protected: + static void createProfileFile(const std::string& temp_profile_name, + std::vector& directLinkprofile_l, + std::vector& indirectLinkprofile_l) { + std::ofstream file_profile(temp_profile_name); -class LinkProfileReaderTest : public ::testing::Test -{ -protected: - - static void createProfileFile(const std::string &temp_profile_name, std::vector &directLinkprofile_l, - std::vector &indirectLinkprofile_l) { - std::ofstream file_profile(temp_profile_name); - - for(auto cnt_l = 0; cnt_l < directLinkprofile_l.size()-1 ; ++cnt_l) - { - file_profile << directLinkprofile_l[cnt_l] << "\t" << indirectLinkprofile_l[cnt_l] << "\n"; - } - file_profile << directLinkprofile_l.back() << "\t" << indirectLinkprofile_l.back(); - file_profile.close(); - } - - static void SetUpTestCase() - { - - std::vector directLinkprofile_l(8760, 1); - std::vector indirectLinkprofile_l(8760, 1); - - directLinkprofile_l[0] = 0; - directLinkprofile_l[1] = 0.5; - indirectLinkprofile_l[0] = 0.25; - indirectLinkprofile_l[1] = 0.75; - - createProfileFile(VALID_PROFILE_NAME, directLinkprofile_l, indirectLinkprofile_l); - - std::vector invalid_directLinkprofile_l(100, 1); - std::vector invalid_indirectLinkprofile_l(100, 1); - createProfileFile(INVALID_PROFILE_NAME, invalid_directLinkprofile_l, invalid_directLinkprofile_l); - } - - static void TearDownTestCase() - { - // called after last test - - //delete the created tmp file - std::remove(VALID_PROFILE_NAME); - std::remove(INVALID_PROFILE_NAME); - } - - void SetUp() - { - // called before each test - } - - void TearDown() - { - // called after each test + for (auto cnt_l = 0; cnt_l < directLinkprofile_l.size() - 1; ++cnt_l) { + file_profile << directLinkprofile_l[cnt_l] << "\t" + << indirectLinkprofile_l[cnt_l] << "\n"; } + file_profile << directLinkprofile_l.back() << "\t" + << indirectLinkprofile_l.back(); + file_profile.close(); + } + + static void SetUpTestCase() { + std::vector directLinkprofile_l(8760, 1); + std::vector indirectLinkprofile_l(8760, 1); + + directLinkprofile_l[0] = 0; + directLinkprofile_l[1] = 0.5; + indirectLinkprofile_l[0] = 0.25; + indirectLinkprofile_l[1] = 0.75; + + createProfileFile(VALID_PROFILE_NAME, directLinkprofile_l, + indirectLinkprofile_l); + + std::vector invalid_directLinkprofile_l(100, 1); + std::vector invalid_indirectLinkprofile_l(100, 1); + createProfileFile(INVALID_PROFILE_NAME, invalid_directLinkprofile_l, + invalid_directLinkprofile_l); + } + + static void TearDownTestCase() { + // called after last test + + // delete the created tmp file + std::remove(VALID_PROFILE_NAME); + std::remove(INVALID_PROFILE_NAME); + } + + void SetUp() { + // called before each test + } + + void TearDown() { + // called after each test + } }; TEST_F(LinkProfileReaderTest, ReadValidProfile) { + LinkProfile profile = LinkProfileReader::ReadLinkProfile(VALID_PROFILE_NAME); - LinkProfile profile = LinkProfileReader::ReadLinkProfile(VALID_PROFILE_NAME); - - ASSERT_EQ(profile.getDirectProfile(0), 0); - ASSERT_EQ(profile.getIndirectProfile(0), 0.25); - ASSERT_EQ(profile.getDirectProfile(1), 0.5); - ASSERT_EQ(profile.getIndirectProfile(1), 0.75); + ASSERT_EQ(profile.getDirectProfile(0), 0); + ASSERT_EQ(profile.getIndirectProfile(0), 0.25); + ASSERT_EQ(profile.getDirectProfile(1), 0.5); + ASSERT_EQ(profile.getIndirectProfile(1), 0.75); } TEST_F(LinkProfileReaderTest, ReadInvalidProfile) { - - try { - LinkProfile profile = LinkProfileReader::ReadLinkProfile(INVALID_PROFILE_NAME); - FAIL(); - } - catch(const std::runtime_error& expected) { - ASSERT_STREQ(expected.what(), "error not enough line in link-profile temp_invalid_profile.txt"); - } + try { + LinkProfile profile = + LinkProfileReader::ReadLinkProfile(INVALID_PROFILE_NAME); + FAIL(); + } catch (const std::runtime_error& expected) { + ASSERT_STREQ( + expected.what(), + "error not enough line in link-profile temp_invalid_profile.txt"); + } } TEST_F(LinkProfileReaderTest, GetTimeStepLargerThan8760) { - - LinkProfile profile = LinkProfileReader::ReadLinkProfile(VALID_PROFILE_NAME); - - try { - profile.getDirectProfile(8790); - FAIL(); - } - catch(const std::runtime_error& expected) { - ASSERT_STREQ(expected.what(), "Link profiles can be requested between point 0 and 8759."); - } - - try { - profile.getIndirectProfile(8790); - FAIL(); - } - catch(const std::runtime_error& expected) { - ASSERT_STREQ(expected.what(), "Link profiles can be requested between point 0 and 8759."); - } + LinkProfile profile = LinkProfileReader::ReadLinkProfile(VALID_PROFILE_NAME); + + try { + profile.getDirectProfile(8790); + FAIL(); + } catch (const std::runtime_error& expected) { + ASSERT_STREQ(expected.what(), + "Link profiles can be requested between point 0 and 8759."); + } + + try { + profile.getIndirectProfile(8790); + FAIL(); + } catch (const std::runtime_error& expected) { + ASSERT_STREQ(expected.what(), + "Link profiles can be requested between point 0 and 8759."); + } } - - diff --git a/tests/cpp/lp_namer/MasterProblemBuilderTest.cpp b/tests/cpp/lp_namer/MasterProblemBuilderTest.cpp index 0eb6906c3..a63bd4a5b 100644 --- a/tests/cpp/lp_namer/MasterProblemBuilderTest.cpp +++ b/tests/cpp/lp_namer/MasterProblemBuilderTest.cpp @@ -1,163 +1,167 @@ // // Created by s90365 on 23/08/2021. // -#include "MasterProblemBuilder.h" #include -#include "gtest/gtest.h" -TEST(MasterProblemBuilderTest, test_one_candidate_not_integer) -{ - std::string solver_name = "CBC"; - std::string master_formulation = "integer"; +#include "MasterProblemBuilder.h" +#include "gtest/gtest.h" - CandidateData cand1; - cand1.link_id = 1; - cand1.name = "transmission_line_1"; - cand1.link_name = "area1 - area2"; - cand1.already_installed_capacity = 0; +TEST(MasterProblemBuilderTest, test_one_candidate_not_integer) { + std::string solver_name = "CBC"; + std::string master_formulation = "integer"; - std::vector cand_data_list = { cand1 }; + CandidateData cand1; + cand1.link_id = 1; + cand1.name = "transmission_line_1"; + cand1.link_name = "area1 - area2"; + cand1.already_installed_capacity = 0; - std::map profile_map; + std::vector cand_data_list = {cand1}; - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - const std::vector& links = linkBuilder.getLinks(); + std::map profile_map; - std::vector candidates; + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + const std::vector& links = linkBuilder.getLinks(); - for (const auto& link : links) - { - const auto& candidateFromLink = link.getCandidates(); - candidates.insert(candidates.end(), candidateFromLink.begin(), candidateFromLink.end()); - } + std::vector 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], cand1.name); + for (const auto& link : links) { + const auto& candidateFromLink = link.getCandidates(); + candidates.insert(candidates.end(), candidateFromLink.begin(), + candidateFromLink.end()); + } - std::vector colTypeArray(master_problem->get_ncols()); - master_problem->get_col_type(colTypeArray.data(), 0, master_problem->get_ncols() - 1); + 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], + cand1.name); - ASSERT_EQ(colTypeArray[0], 'C'); + std::vector colTypeArray(master_problem->get_ncols()); + master_problem->get_col_type(colTypeArray.data(), 0, + master_problem->get_ncols() - 1); - std::vector varLbArray(master_problem->get_ncols()); - master_problem->get_lb(varLbArray.data(), 0, master_problem->get_ncols() - 1); + ASSERT_EQ(colTypeArray[0], 'C'); - ASSERT_EQ(varLbArray[0], 0); + std::vector varLbArray(master_problem->get_ncols()); + master_problem->get_lb(varLbArray.data(), 0, master_problem->get_ncols() - 1); - std::vector varUbArray(master_problem->get_ncols()); - master_problem->get_ub(varUbArray.data(), 0, master_problem->get_ncols() - 1); + ASSERT_EQ(varLbArray[0], 0); - ASSERT_EQ(varUbArray[0], 0); + std::vector varUbArray(master_problem->get_ncols()); + master_problem->get_ub(varUbArray.data(), 0, master_problem->get_ncols() - 1); - ASSERT_EQ(master_problem->get_nrows(), 0); + ASSERT_EQ(varUbArray[0], 0); + ASSERT_EQ(master_problem->get_nrows(), 0); } -TEST(MasterProblemBuilderTest, test_one_candidate_integer_problem_integer) -{ - std::string solver_name = "CBC"; - std::string master_formulation = "integer"; +TEST(MasterProblemBuilderTest, test_one_candidate_integer_problem_integer) { + std::string solver_name = "CBC"; + std::string master_formulation = "integer"; - CandidateData cand1; - cand1.link_id = 1; - cand1.name = "transmission_line_1"; - cand1.link_name = "area1 - area2"; - cand1.already_installed_capacity = 0; - cand1.unit_size = 4; - cand1.max_units = 17; + CandidateData cand1; + cand1.link_id = 1; + cand1.name = "transmission_line_1"; + cand1.link_name = "area1 - area2"; + cand1.already_installed_capacity = 0; + cand1.unit_size = 4; + cand1.max_units = 17; - std::vector cand_data_list = { cand1 }; + std::vector cand_data_list = {cand1}; - std::map profile_map; + std::map profile_map; - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - const std::vector& links = linkBuilder.getLinks(); + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + const std::vector& links = linkBuilder.getLinks(); - std::vector candidates; + std::vector candidates; - for (const auto& link : links) - { - const auto& candidateFromLink = link.getCandidates(); - candidates.insert(candidates.end(), candidateFromLink.begin(), candidateFromLink.end()); - } + for (const auto& link : links) { + const auto& candidateFromLink = link.getCandidates(); + candidates.insert(candidates.end(), candidateFromLink.begin(), + candidateFromLink.end()); + } - auto master_problem = MasterProblemBuilder(master_formulation).build(solver_name, candidates); - ASSERT_EQ(master_problem->get_ncols(), 2); + auto master_problem = + MasterProblemBuilder(master_formulation).build(solver_name, candidates); + ASSERT_EQ(master_problem->get_ncols(), 2); - std::vector colTypeArray(master_problem->get_ncols()); - master_problem->get_col_type(colTypeArray.data(), 0, master_problem->get_ncols() - 1); + std::vector colTypeArray(master_problem->get_ncols()); + master_problem->get_col_type(colTypeArray.data(), 0, + master_problem->get_ncols() - 1); - ASSERT_EQ(colTypeArray[1], 'I'); + ASSERT_EQ(colTypeArray[1], 'I'); - std::vector varLbArray(master_problem->get_ncols()); - master_problem->get_lb(varLbArray.data(), 0, master_problem->get_ncols() - 1); + std::vector varLbArray(master_problem->get_ncols()); + master_problem->get_lb(varLbArray.data(), 0, master_problem->get_ncols() - 1); - ASSERT_EQ(varLbArray[1], 0); + ASSERT_EQ(varLbArray[1], 0); - std::vector varUbArray(master_problem->get_ncols()); - master_problem->get_ub(varUbArray.data(), 0, master_problem->get_ncols() - 1); + std::vector varUbArray(master_problem->get_ncols()); + master_problem->get_ub(varUbArray.data(), 0, master_problem->get_ncols() - 1); - ASSERT_EQ(varUbArray[1], 17); + ASSERT_EQ(varUbArray[1], 17); - ASSERT_EQ(master_problem->get_nrows(), 1); + ASSERT_EQ(master_problem->get_nrows(), 1); - std::vector rowTypeArray(master_problem->get_nrows()); - master_problem->get_row_type(rowTypeArray.data(), 0, master_problem->get_nrows() - 1); - - ASSERT_EQ(rowTypeArray[0], 'E'); + std::vector rowTypeArray(master_problem->get_nrows()); + master_problem->get_row_type(rowTypeArray.data(), 0, + master_problem->get_nrows() - 1); + ASSERT_EQ(rowTypeArray[0], 'E'); } -TEST(MasterProblemBuilderTest, test_one_candidate_integer_problem_relaxed) -{ - std::string solver_name = "CBC"; - std::string master_formulation = "relaxed"; - - CandidateData cand1; - cand1.link_id = 1; - cand1.name = "transmission_line_1"; - cand1.link_name = "area1 - area2"; - cand1.already_installed_capacity = 0; - cand1.unit_size = 4; - cand1.max_units = 17; +TEST(MasterProblemBuilderTest, test_one_candidate_integer_problem_relaxed) { + std::string solver_name = "CBC"; + std::string master_formulation = "relaxed"; - std::vector cand_data_list = { cand1 }; + CandidateData cand1; + cand1.link_id = 1; + cand1.name = "transmission_line_1"; + cand1.link_name = "area1 - area2"; + cand1.already_installed_capacity = 0; + cand1.unit_size = 4; + cand1.max_units = 17; - std::map profile_map; + std::vector cand_data_list = {cand1}; - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - const std::vector& links = linkBuilder.getLinks(); + std::map profile_map; - std::vector candidates; + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + const std::vector& links = linkBuilder.getLinks(); - for (const auto& link : links) - { - const auto& candidateFromLink = link.getCandidates(); - candidates.insert(candidates.end(), candidateFromLink.begin(), candidateFromLink.end()); - } + std::vector 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], cand1.name); + for (const auto& link : links) { + const auto& candidateFromLink = link.getCandidates(); + candidates.insert(candidates.end(), candidateFromLink.begin(), + candidateFromLink.end()); + } - std::vector colTypeArray(master_problem->get_ncols()); - master_problem->get_col_type(colTypeArray.data(), 0, master_problem->get_ncols() - 1); + 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], + cand1.name); - ASSERT_EQ(colTypeArray[0], 'C'); + std::vector colTypeArray(master_problem->get_ncols()); + master_problem->get_col_type(colTypeArray.data(), 0, + master_problem->get_ncols() - 1); - std::vector varLbArray(master_problem->get_ncols()); - master_problem->get_lb(varLbArray.data(), 0, master_problem->get_ncols() - 1); + ASSERT_EQ(colTypeArray[0], 'C'); - ASSERT_EQ(varLbArray[0], 0); + std::vector varLbArray(master_problem->get_ncols()); + master_problem->get_lb(varLbArray.data(), 0, master_problem->get_ncols() - 1); - std::vector varUbArray(master_problem->get_ncols()); - master_problem->get_ub(varUbArray.data(), 0, master_problem->get_ncols() - 1); + ASSERT_EQ(varLbArray[0], 0); - ASSERT_EQ(varUbArray[0], 68); + std::vector varUbArray(master_problem->get_ncols()); + master_problem->get_ub(varUbArray.data(), 0, master_problem->get_ncols() - 1); - ASSERT_EQ(master_problem->get_nrows(), 0); - + ASSERT_EQ(varUbArray[0], 68); + ASSERT_EQ(master_problem->get_nrows(), 0); } - diff --git a/tests/cpp/lp_namer/ProblemModifierTest.cpp b/tests/cpp/lp_namer/ProblemModifierTest.cpp index 9a2868bef..c1b411ea4 100644 --- a/tests/cpp/lp_namer/ProblemModifierTest.cpp +++ b/tests/cpp/lp_namer/ProblemModifierTest.cpp @@ -1,9 +1,11 @@ -#include #include +#include #include -#include #include + +#include + #include "gtest/gtest.h" const std::string P_LINK = "p_link"; @@ -13,605 +15,600 @@ const double ZERO = 0.0; const double PLUS_INF = 1e20; const double MINUS_INF = -1e20; - -class ProblemModifierTest : public ::testing::Test -{ -public: - SolverAbstract::Ptr math_problem; - int n_cols=-1; - int n_rows=-1; - int n_elems=-1; - std::vector coltypes; - std::vector rowtypes; - std::vector objectives; - std::vector upper_bounds; - std::vector lower_bounds; - std::vector rhs; - std::vector mat_val; - std::vector col_indexes; - std::vector start_indexes; - std::vector> col_names; - - -protected: - void SetUp() +class ProblemModifierTest : public ::testing::Test { + public: + SolverAbstract::Ptr math_problem; + int n_cols = -1; + int n_rows = -1; + int n_elems = -1; + std::vector coltypes; + std::vector rowtypes; + std::vector objectives; + std::vector upper_bounds; + std::vector lower_bounds; + std::vector rhs; + std::vector mat_val; + std::vector col_indexes; + std::vector start_indexes; + std::vector> col_names; + + protected: + void SetUp() { + std::string solver_name = "CBC"; + SolverFactory factory; + math_problem = factory.create_solver(solver_name); + + // Add NTC variable column { - - std::string solver_name = "CBC"; - SolverFactory factory; - math_problem = factory.create_solver(solver_name); - - //Add NTC variable column - { - std::vector objectives(1, 1); - std::vector lb(1, -1000); - std::vector ub(1, 1000); - std::vector coltypes(1, 'C'); - std::vector mstart(1, 0); - std::vector candidates_colnames(1, P_LINK); - solver_addcols(math_problem, objectives, mstart, {}, {}, lb, ub, coltypes, candidates_colnames); - } - - //Add direct cost variable column - { - std::vector objectives(1, 1); - std::vector lb(1, 0); - std::vector ub(1, 1); - std::vector coltypes(1, 'C'); - std::vector mstart(1, 0); - std::vector candidates_colnames( 1, P_PLUS); - solver_addcols(math_problem, objectives, mstart, {}, {}, lb, ub, coltypes, candidates_colnames); - } - - //Add indirect cost variable column - { - std::vector objectives(1, 1); - std::vector lb(1, 0); - std::vector ub(1, 1); - std::vector coltypes(1, 'C'); - std::vector mstart(1, 0); - std::vector candidates_colnames(1, P_MINUS); - solver_addcols(math_problem, objectives, mstart, {}, {}, lb, ub, coltypes, candidates_colnames); - } + std::vector objectives(1, 1); + std::vector lb(1, -1000); + std::vector ub(1, 1000); + std::vector coltypes(1, 'C'); + std::vector mstart(1, 0); + std::vector candidates_colnames(1, P_LINK); + solver_addcols(math_problem, objectives, mstart, {}, {}, lb, ub, coltypes, + candidates_colnames); } - void TearDown() + // Add direct cost variable column { - n_cols=-1; - n_rows=-1; - n_elems=-1; - - } - - void update_n_cols(){ - if(n_cols==-1){ - n_cols = math_problem->get_ncols(); - } - } - void update_n_rows(){ - if(n_rows==-1){ - n_rows = math_problem->get_nrows(); - } - } - void update_n_elems(){ - if(n_elems==-1){ - n_elems = math_problem->get_nelems(); - } - } - void update_col_names(){ - update_n_cols(); - col_names = math_problem->get_col_names(0, n_cols-1); - } - void update_col_type(){ - update_n_cols(); - if(coltypes.size()!= n_cols){ - std::vector buffer(n_cols, '0'); - coltypes.insert(coltypes.begin(), buffer.begin(), buffer.end()); - math_problem->get_col_type(coltypes.data(), 0, n_cols-1); - } - } - void update_row_type(){ - update_n_rows(); - if(rowtypes.size()!= n_rows){ - std::vector buffer(n_rows, '0'); - rowtypes.insert(rowtypes.begin(), buffer.begin(), buffer.end()); - math_problem->get_row_type(rowtypes.data(), 0, n_rows-1); - } - } - void update_objectives(){ - update_n_cols(); - if(objectives.size()!=n_cols){ - std::vector buffer(n_cols, -777); - objectives.insert(objectives.begin(), buffer.begin(), buffer.end()); - math_problem->get_obj(objectives.data(), 0, n_cols-1); - } - } - void update_lower_bounds(){ - update_n_cols(); - if(lower_bounds.size()!=n_cols){ - std::vector buffer(n_cols, -777); - lower_bounds.insert(lower_bounds.begin(), buffer.begin(), buffer.end()); - math_problem->get_lb(lower_bounds.data(), 0, n_cols-1); - } - } - void update_upper_bounds(){ - update_n_cols(); - if(upper_bounds.size()!=n_cols){ - std::vector buffer(n_cols, -777); - upper_bounds.insert(upper_bounds.begin(), buffer.begin(), buffer.end()); - math_problem->get_ub(upper_bounds.data(), 0, n_cols-1); - } - } - void update_mat_val(){ - update_n_rows(); - update_n_elems(); - - if (mat_val.size() != n_elems){ - std::vector buffer(n_elems, -777); - mat_val.insert(mat_val.begin(), buffer.begin(), buffer.end()); - - start_indexes.clear(); - start_indexes = std::vector(n_rows+1); - col_indexes.clear(); - col_indexes = std::vector(n_elems); - int n_returned(0); - math_problem->get_rows(start_indexes.data(), col_indexes.data(), mat_val.data(), - n_elems, &n_returned, 0, n_rows - 1); - } + std::vector objectives(1, 1); + std::vector lb(1, 0); + std::vector ub(1, 1); + std::vector coltypes(1, 'C'); + std::vector mstart(1, 0); + std::vector candidates_colnames(1, P_PLUS); + solver_addcols(math_problem, objectives, mstart, {}, {}, lb, ub, coltypes, + candidates_colnames); } - std::vector getRowCoefficients(int index_row){ - update_mat_val(); - std::vector row; - row.insert(row.begin(), mat_val.begin() + start_indexes.at(index_row), mat_val.begin() + start_indexes.at(index_row+1)); - return row; + // Add indirect cost variable column + { + std::vector objectives(1, 1); + std::vector lb(1, 0); + std::vector ub(1, 1); + std::vector coltypes(1, 'C'); + std::vector mstart(1, 0); + std::vector candidates_colnames(1, P_MINUS); + solver_addcols(math_problem, objectives, mstart, {}, {}, lb, ub, coltypes, + candidates_colnames); } + } - std::vector getRowColIndexes(int index_row){ - update_mat_val(); - std::vector index; - index.insert(index.begin(), col_indexes.begin() + start_indexes.at(index_row), col_indexes.begin() + start_indexes.at(index_row+1)); - return index; - } + void TearDown() { + n_cols = -1; + n_rows = -1; + n_elems = -1; + } - void update_rhs_val(){ - update_n_rows(); - if (rhs.size() != n_rows){ - std::vector buffer(n_rows, -777); - rhs.insert(rhs.begin(), buffer.begin(), buffer.end()); - math_problem->get_rhs(rhs.data(),0, n_rows - 1); - } - } - void verify_columns_are(const int expected_n_cols){ - update_n_cols(); - ASSERT_EQ(n_cols, expected_n_cols); - } - void verify_rows_are(const int expected_n_rows){ - update_n_rows(); - ASSERT_EQ(n_rows, expected_n_rows); + void update_n_cols() { + if (n_cols == -1) { + n_cols = math_problem->get_ncols(); } - void verify_column_name_is(const int col_id, std::basic_string name){ - update_col_names(); - ASSERT_EQ(col_names.at(col_id), name); + } + void update_n_rows() { + if (n_rows == -1) { + n_rows = math_problem->get_nrows(); } - void verify_column_is_of_type(const int col_id, char type){ - update_col_type(); - ASSERT_EQ(coltypes.at(col_id), type); + } + void update_n_elems() { + if (n_elems == -1) { + n_elems = math_problem->get_nelems(); } - void verify_column_objective_is(const int col_id, double obj_value){ - update_objectives(); - ASSERT_DOUBLE_EQ(objectives.at(col_id), obj_value); + } + void update_col_names() { + update_n_cols(); + col_names = math_problem->get_col_names(0, n_cols - 1); + } + void update_col_type() { + update_n_cols(); + if (coltypes.size() != n_cols) { + std::vector buffer(n_cols, '0'); + coltypes.insert(coltypes.begin(), buffer.begin(), buffer.end()); + math_problem->get_col_type(coltypes.data(), 0, n_cols - 1); } - void verify_column_lower_bound_is(const int col_id, double lower_value){ - update_lower_bounds(); - ASSERT_DOUBLE_EQ(lower_bounds.at(col_id), lower_value); + } + void update_row_type() { + update_n_rows(); + if (rowtypes.size() != n_rows) { + std::vector buffer(n_rows, '0'); + rowtypes.insert(rowtypes.begin(), buffer.begin(), buffer.end()); + math_problem->get_row_type(rowtypes.data(), 0, n_rows - 1); } - void verify_column_upper_bound_is(const int col_id, double upper_value){ - update_upper_bounds(); - ASSERT_DOUBLE_EQ(upper_bounds.at(col_id), upper_value); + } + void update_objectives() { + update_n_cols(); + if (objectives.size() != n_cols) { + std::vector buffer(n_cols, -777); + objectives.insert(objectives.begin(), buffer.begin(), buffer.end()); + math_problem->get_obj(objectives.data(), 0, n_cols - 1); } - void verify_row_is_of_type(const int row_id, char type){ - update_row_type(); - ASSERT_EQ(rowtypes.at(row_id), type); + } + void update_lower_bounds() { + update_n_cols(); + if (lower_bounds.size() != n_cols) { + std::vector buffer(n_cols, -777); + lower_bounds.insert(lower_bounds.begin(), buffer.begin(), buffer.end()); + math_problem->get_lb(lower_bounds.data(), 0, n_cols - 1); } - void verify_rhs_is(const int rhs_id, double rhs_value){ - update_rhs_val(); - ASSERT_DOUBLE_EQ(rhs.at(rhs_id), rhs_value); + } + void update_upper_bounds() { + update_n_cols(); + if (upper_bounds.size() != n_cols) { + std::vector buffer(n_cols, -777); + upper_bounds.insert(upper_bounds.begin(), buffer.begin(), buffer.end()); + math_problem->get_ub(upper_bounds.data(), 0, n_cols - 1); } - void verify_column(const int col_id, std::basic_string name, char type,double obj_value,double lower_value,double upper_value ){ - verify_column_name_is(col_id, name); - verify_column_is_of_type(col_id, type); - verify_column_objective_is(col_id, obj_value); - verify_column_lower_bound_is(col_id, lower_value); - verify_column_upper_bound_is(col_id, upper_value); + } + void update_mat_val() { + update_n_rows(); + update_n_elems(); + + if (mat_val.size() != n_elems) { + std::vector buffer(n_elems, -777); + mat_val.insert(mat_val.begin(), buffer.begin(), buffer.end()); + + start_indexes.clear(); + start_indexes = std::vector(n_rows + 1); + col_indexes.clear(); + col_indexes = std::vector(n_elems); + int n_returned(0); + math_problem->get_rows(start_indexes.data(), col_indexes.data(), + mat_val.data(), n_elems, &n_returned, 0, + n_rows - 1); } - void verify_row(int row, char type, const std::vector& coeff,const std::vector& col_indexes, double rhs){ - verify_row_is_of_type(row, type); - ASSERT_EQ(getRowCoefficients(row), coeff); - ASSERT_EQ(getRowColIndexes(row), col_indexes); - verify_rhs_is(row, rhs); + } + + std::vector getRowCoefficients(int index_row) { + update_mat_val(); + std::vector row; + row.insert(row.begin(), mat_val.begin() + start_indexes.at(index_row), + mat_val.begin() + start_indexes.at(index_row + 1)); + return row; + } + + std::vector getRowColIndexes(int index_row) { + update_mat_val(); + std::vector index; + index.insert(index.begin(), + col_indexes.begin() + start_indexes.at(index_row), + col_indexes.begin() + start_indexes.at(index_row + 1)); + return index; + } + + void update_rhs_val() { + update_n_rows(); + if (rhs.size() != n_rows) { + std::vector buffer(n_rows, -777); + rhs.insert(rhs.begin(), buffer.begin(), buffer.end()); + math_problem->get_rhs(rhs.data(), 0, n_rows - 1); } + } + void verify_columns_are(const int expected_n_cols) { + update_n_cols(); + ASSERT_EQ(n_cols, expected_n_cols); + } + void verify_rows_are(const int expected_n_rows) { + update_n_rows(); + ASSERT_EQ(n_rows, expected_n_rows); + } + void verify_column_name_is(const int col_id, std::basic_string name) { + update_col_names(); + ASSERT_EQ(col_names.at(col_id), name); + } + void verify_column_is_of_type(const int col_id, char type) { + update_col_type(); + ASSERT_EQ(coltypes.at(col_id), type); + } + void verify_column_objective_is(const int col_id, double obj_value) { + update_objectives(); + ASSERT_DOUBLE_EQ(objectives.at(col_id), obj_value); + } + void verify_column_lower_bound_is(const int col_id, double lower_value) { + update_lower_bounds(); + ASSERT_DOUBLE_EQ(lower_bounds.at(col_id), lower_value); + } + void verify_column_upper_bound_is(const int col_id, double upper_value) { + update_upper_bounds(); + ASSERT_DOUBLE_EQ(upper_bounds.at(col_id), upper_value); + } + void verify_row_is_of_type(const int row_id, char type) { + update_row_type(); + ASSERT_EQ(rowtypes.at(row_id), type); + } + void verify_rhs_is(const int rhs_id, double rhs_value) { + update_rhs_val(); + ASSERT_DOUBLE_EQ(rhs.at(rhs_id), rhs_value); + } + void verify_column(const int col_id, std::basic_string name, char type, + double obj_value, double lower_value, double upper_value) { + verify_column_name_is(col_id, name); + verify_column_is_of_type(col_id, type); + verify_column_objective_is(col_id, obj_value); + verify_column_lower_bound_is(col_id, lower_value); + verify_column_upper_bound_is(col_id, upper_value); + } + void verify_row(int row, char type, const std::vector& coeff, + const std::vector& col_indexes, double rhs) { + verify_row_is_of_type(row, type); + ASSERT_EQ(getRowCoefficients(row), coeff); + ASSERT_EQ(getRowColIndexes(row), col_indexes); + verify_rhs_is(row, rhs); + } }; -TEST_F(ProblemModifierTest, empty_test_the_multisolver_interface) -{ - verify_columns_are(3); - verify_rows_are(0); +TEST_F(ProblemModifierTest, empty_test_the_multisolver_interface) { + verify_columns_are(3); + verify_rows_are(0); - verify_column(0,P_LINK,'C',1,-1000,1000); - verify_column(1,P_PLUS,'C',1,0,1); - verify_column(2,P_MINUS,'C',1,0,1); + verify_column(0, P_LINK, 'C', 1, -1000, 1000); + verify_column(1, P_PLUS, 'C', 1, 0, 1); + verify_column(2, P_MINUS, 'C', 1, 0, 1); } - -TEST_F(ProblemModifierTest, One_link_no_candidates_link_boundaries_are_removed) { - const int link_id = 0; - const std::map p_var_columns = {{link_id,{{0, 0}}}}; - const std::map p_direct_cost_columns= {{link_id,{{{1, 0}}}}}; - const std::map p_indirect_cost_columns= {{link_id,{{{2, 0}}}}}; - const std::vector active_links= {ActiveLink(link_id, "dummy_link", "from", "to", 0)}; - - auto problem_modifier = ProblemModifier(); - math_problem = problem_modifier.changeProblem(std::move(math_problem), active_links, p_var_columns,p_direct_cost_columns,p_indirect_cost_columns); - - verify_columns_are(3); - - verify_column(0,P_LINK,'C',1,MINUS_INF, PLUS_INF); - verify_column(1,P_PLUS,'C',1,ZERO, PLUS_INF); - verify_column(2,P_MINUS,'C',1,ZERO, PLUS_INF); - - try { - problem_modifier.get_candidate_col_id("invalid_cand_name"); - FAIL(); - } - catch(const std::runtime_error& expected) { - ASSERT_STREQ(expected.what(), "Candidate 'invalid_cand_name' not added in problem"); - } +TEST_F(ProblemModifierTest, + One_link_no_candidates_link_boundaries_are_removed) { + const int link_id = 0; + const std::map p_var_columns = {{link_id, {{0, 0}}}}; + const std::map p_direct_cost_columns = { + {link_id, {{{1, 0}}}}}; + const std::map p_indirect_cost_columns = { + {link_id, {{{2, 0}}}}}; + const std::vector active_links = { + ActiveLink(link_id, "dummy_link", "from", "to", 0)}; + + auto problem_modifier = ProblemModifier(); + math_problem = problem_modifier.changeProblem( + std::move(math_problem), active_links, p_var_columns, + p_direct_cost_columns, p_indirect_cost_columns); + + verify_columns_are(3); + + verify_column(0, P_LINK, 'C', 1, MINUS_INF, PLUS_INF); + verify_column(1, P_PLUS, 'C', 1, ZERO, PLUS_INF); + verify_column(2, P_MINUS, 'C', 1, ZERO, PLUS_INF); + + try { + problem_modifier.get_candidate_col_id("invalid_cand_name"); + FAIL(); + } catch (const std::runtime_error& expected) { + ASSERT_STREQ(expected.what(), + "Candidate 'invalid_cand_name' not added in problem"); + } } - TEST_F(ProblemModifierTest, One_link_two_candidates) { - const int link_id = 0; - std::vector time_steps = {0}; - const std::map p_var_columns = {{link_id,{{0, 0}}}}; - const std::map p_direct_cost_columns= {{link_id,{{1, 0}}}}; - const std::map p_indirect_cost_columns= {{link_id,{{2, 0}}}}; - - const double link_capacity = 1000.0; - CandidateData cand1; - cand1.link_id = link_id; - cand1.name = "candy1"; - cand1.link_name = "dummy_link"; - cand1.already_installed_capacity = link_capacity; - CandidateData cand2; - cand2.link_id = link_id; - cand2.name = "candy2"; - cand2.link_name = "dummy_link"; - cand2.already_installed_capacity = link_capacity; - - std::vector cand_data_list = { cand1, cand2 }; - std::map profile_map; - - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - const std::vector& links = linkBuilder.getLinks(); - - auto problem_modifier = ProblemModifier(); - math_problem = problem_modifier.changeProblem(std::move(math_problem), links, p_var_columns,p_direct_cost_columns,p_indirect_cost_columns); - - verify_columns_are(5); - - const int P_LINK_id = 0; - const int P_PLUS_id = 1; - const int P_MINUS_id = 2; - const int cand1_id= 3; - const int cand2_id= 4; - - verify_column(P_LINK_id,P_LINK,'C',1,MINUS_INF,PLUS_INF); - verify_column(P_PLUS_id,P_PLUS,'C',1,0,PLUS_INF); - verify_column(P_MINUS_id,P_MINUS,'C',1,0,PLUS_INF); - verify_column(cand1_id,cand1.name,'C',0,MINUS_INF,PLUS_INF); - verify_column(cand2_id,cand2.name,'C',0,MINUS_INF,PLUS_INF); - - ASSERT_EQ(problem_modifier.get_candidate_col_id(cand1.name) , cand1_id); - ASSERT_EQ(problem_modifier.get_candidate_col_id(cand2.name) , cand2_id); - - verify_rows_are(4); - verify_row(0, 'L', - {1,-1,-1}, - {P_LINK_id,cand1_id,cand2_id}, - link_capacity); - verify_row(1 , 'G', - {1,1,1}, - {P_LINK_id,cand1_id,cand2_id}, - -link_capacity); - verify_row(2, 'L', - {1,-1,-1}, - {P_PLUS_id,cand1_id,cand2_id}, - link_capacity); - verify_row(3, 'L', - {1,-1,-1}, - {P_MINUS_id,cand1_id,cand2_id}, - link_capacity); + const int link_id = 0; + std::vector time_steps = {0}; + const std::map p_var_columns = {{link_id, {{0, 0}}}}; + const std::map p_direct_cost_columns = { + {link_id, {{1, 0}}}}; + const std::map p_indirect_cost_columns = { + {link_id, {{2, 0}}}}; + + const double link_capacity = 1000.0; + CandidateData cand1; + cand1.link_id = link_id; + cand1.name = "candy1"; + cand1.link_name = "dummy_link"; + cand1.already_installed_capacity = link_capacity; + CandidateData cand2; + cand2.link_id = link_id; + cand2.name = "candy2"; + cand2.link_name = "dummy_link"; + cand2.already_installed_capacity = link_capacity; + + std::vector cand_data_list = {cand1, cand2}; + std::map profile_map; + + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + const std::vector& links = linkBuilder.getLinks(); + + auto problem_modifier = ProblemModifier(); + math_problem = problem_modifier.changeProblem( + std::move(math_problem), links, p_var_columns, p_direct_cost_columns, + p_indirect_cost_columns); + + verify_columns_are(5); + + const int P_LINK_id = 0; + const int P_PLUS_id = 1; + const int P_MINUS_id = 2; + const int cand1_id = 3; + const int cand2_id = 4; + + verify_column(P_LINK_id, P_LINK, 'C', 1, MINUS_INF, PLUS_INF); + verify_column(P_PLUS_id, P_PLUS, 'C', 1, 0, PLUS_INF); + verify_column(P_MINUS_id, P_MINUS, 'C', 1, 0, PLUS_INF); + verify_column(cand1_id, cand1.name, 'C', 0, MINUS_INF, PLUS_INF); + verify_column(cand2_id, cand2.name, 'C', 0, MINUS_INF, PLUS_INF); + + ASSERT_EQ(problem_modifier.get_candidate_col_id(cand1.name), cand1_id); + ASSERT_EQ(problem_modifier.get_candidate_col_id(cand2.name), cand2_id); + + verify_rows_are(4); + verify_row(0, 'L', {1, -1, -1}, {P_LINK_id, cand1_id, cand2_id}, + link_capacity); + verify_row(1, 'G', {1, 1, 1}, {P_LINK_id, cand1_id, cand2_id}, + -link_capacity); + verify_row(2, 'L', {1, -1, -1}, {P_PLUS_id, cand1_id, cand2_id}, + link_capacity); + verify_row(3, 'L', {1, -1, -1}, {P_MINUS_id, cand1_id, cand2_id}, + link_capacity); } TEST_F(ProblemModifierTest, One_link_two_candidates_two_timestep_no_profile) { - const int link_id = 0; - const std::map p_var_columns = {{link_id,{{0, 0},{0, 1}}}}; - const std::map p_direct_cost_columns= {{link_id,{{1, 0},{1, 1}}}}; - const std::map p_indirect_cost_columns= {{link_id,{{{2, 0},{2, 1}}}}}; - - const double link_capacity = 1000.0; - CandidateData cand1; - cand1.link_id = link_id; - cand1.name = "candy1"; - cand1.link_name = "dummy_link"; - cand1.already_installed_capacity = link_capacity; - CandidateData cand2; - cand2.link_id = link_id; - cand2.name = "candy2"; - cand2.link_name = "dummy_link"; - cand2.already_installed_capacity = link_capacity; - - std::vector cand_data_list = { cand1, cand2 }; - std::map profile_map; - - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - const std::vector& links = linkBuilder.getLinks(); - - auto problem_modifier = ProblemModifier(); - math_problem = problem_modifier.changeProblem(std::move(math_problem), links, p_var_columns,p_direct_cost_columns,p_indirect_cost_columns); - verify_columns_are(5); - - const int P_LINK_id = 0; - const int P_PLUS_id = 1; - const int P_MINUS_id = 2; - const int cand1_id= 3; - const int cand2_id= 4; - - verify_column(P_LINK_id,P_LINK,'C',1,MINUS_INF,PLUS_INF); - verify_column(P_PLUS_id,P_PLUS,'C',1,0,PLUS_INF); - verify_column(P_MINUS_id,P_MINUS,'C',1,0,PLUS_INF); - verify_column(cand1_id,cand1.name,'C',0,MINUS_INF,PLUS_INF); - verify_column(cand2_id,cand2.name,'C',0,MINUS_INF,PLUS_INF); - ASSERT_EQ(problem_modifier.get_candidate_col_id(cand1.name) , cand1_id); - ASSERT_EQ(problem_modifier.get_candidate_col_id(cand2.name) , cand2_id); - - verify_rows_are(8); - - verify_row(0, 'L', - {1,-1,-1}, - {P_LINK_id,cand1_id,cand2_id}, - link_capacity); - verify_row(1 , 'G', - {1,1,1}, - {P_LINK_id,cand1_id,cand2_id}, - -link_capacity); - verify_row(2, 'L', - {1,-1,-1}, - {P_LINK_id,cand1_id,cand2_id}, - link_capacity); - verify_row(3 , 'G', - {1,1,1}, - {P_LINK_id,cand1_id,cand2_id}, - -link_capacity); - verify_row(4, 'L', - {1,-1,-1}, - {P_PLUS_id,cand1_id,cand2_id}, - link_capacity); - verify_row(5, 'L', - {1,-1,-1}, - {P_PLUS_id,cand1_id,cand2_id}, - link_capacity); - verify_row(6, 'L', - {1,-1,-1}, - {P_MINUS_id,cand1_id,cand2_id}, - link_capacity); - verify_row(7, 'L', - {1,-1,-1}, - {P_MINUS_id,cand1_id,cand2_id}, - link_capacity); - + const int link_id = 0; + const std::map p_var_columns = { + {link_id, {{0, 0}, {0, 1}}}}; + const std::map p_direct_cost_columns = { + {link_id, {{1, 0}, {1, 1}}}}; + const std::map p_indirect_cost_columns = { + {link_id, {{{2, 0}, {2, 1}}}}}; + + const double link_capacity = 1000.0; + CandidateData cand1; + cand1.link_id = link_id; + cand1.name = "candy1"; + cand1.link_name = "dummy_link"; + cand1.already_installed_capacity = link_capacity; + CandidateData cand2; + cand2.link_id = link_id; + cand2.name = "candy2"; + cand2.link_name = "dummy_link"; + cand2.already_installed_capacity = link_capacity; + + std::vector cand_data_list = {cand1, cand2}; + std::map profile_map; + + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + const std::vector& links = linkBuilder.getLinks(); + + auto problem_modifier = ProblemModifier(); + math_problem = problem_modifier.changeProblem( + std::move(math_problem), links, p_var_columns, p_direct_cost_columns, + p_indirect_cost_columns); + verify_columns_are(5); + + const int P_LINK_id = 0; + const int P_PLUS_id = 1; + const int P_MINUS_id = 2; + const int cand1_id = 3; + const int cand2_id = 4; + + verify_column(P_LINK_id, P_LINK, 'C', 1, MINUS_INF, PLUS_INF); + verify_column(P_PLUS_id, P_PLUS, 'C', 1, 0, PLUS_INF); + verify_column(P_MINUS_id, P_MINUS, 'C', 1, 0, PLUS_INF); + verify_column(cand1_id, cand1.name, 'C', 0, MINUS_INF, PLUS_INF); + verify_column(cand2_id, cand2.name, 'C', 0, MINUS_INF, PLUS_INF); + ASSERT_EQ(problem_modifier.get_candidate_col_id(cand1.name), cand1_id); + ASSERT_EQ(problem_modifier.get_candidate_col_id(cand2.name), cand2_id); + + verify_rows_are(8); + + verify_row(0, 'L', {1, -1, -1}, {P_LINK_id, cand1_id, cand2_id}, + link_capacity); + verify_row(1, 'G', {1, 1, 1}, {P_LINK_id, cand1_id, cand2_id}, + -link_capacity); + verify_row(2, 'L', {1, -1, -1}, {P_LINK_id, cand1_id, cand2_id}, + link_capacity); + verify_row(3, 'G', {1, 1, 1}, {P_LINK_id, cand1_id, cand2_id}, + -link_capacity); + verify_row(4, 'L', {1, -1, -1}, {P_PLUS_id, cand1_id, cand2_id}, + link_capacity); + verify_row(5, 'L', {1, -1, -1}, {P_PLUS_id, cand1_id, cand2_id}, + link_capacity); + verify_row(6, 'L', {1, -1, -1}, {P_MINUS_id, cand1_id, cand2_id}, + link_capacity); + verify_row(7, 'L', {1, -1, -1}, {P_MINUS_id, cand1_id, cand2_id}, + link_capacity); } TEST_F(ProblemModifierTest, One_link_two_candidates_two_timestep_profile) { - const int link_id = 0; - const std::map p_var_columns = {{link_id,{{0, 0},{0, 1}}}}; - const std::map p_direct_cost_columns= {{link_id,{{1, 0},{1, 1}}}}; - const std::map p_indirect_cost_columns= {{link_id,{{{2, 0},{2, 1}}}}}; - - const double link_capacity = 2000.0; - CandidateData cand1; - cand1.link_id = link_id; - cand1.name = "candy1"; - cand1.link_name = "dummy_link"; - cand1.already_installed_capacity = link_capacity; - cand1.installed_link_profile_name = "install_link_profile"; - cand1.link_profile = "profile_cand1"; - CandidateData cand2; - cand2.link_id = link_id; - cand2.name = "candy2"; - cand2.link_name = "dummy_link"; - cand2.already_installed_capacity = link_capacity; - cand2.installed_link_profile_name = "install_link_profile"; - cand2.link_profile = "profile_cand2"; - - std::vector cand_data_list = { cand1, cand2 }; - std::map profile_map; - LinkProfile profile_link; - profile_link._directLinkProfile = {1,2}; - profile_link._indirectLinkProfile = {3,4}; - profile_map["install_link_profile"]=profile_link; - LinkProfile profile_cand1; - profile_cand1._directLinkProfile = {0.5, 1}; - profile_cand1._indirectLinkProfile = {0.8, 1.2}; - profile_map["profile_cand1"]=profile_cand1; - LinkProfile profile_cand2; - profile_cand2._directLinkProfile = {1.5, 1.7}; - profile_cand2._indirectLinkProfile = {2.6, 2.8}; - profile_map["profile_cand2"]=profile_cand2; - - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - const std::vector& links = linkBuilder.getLinks(); - - auto problem_modifier = ProblemModifier(); - math_problem = problem_modifier.changeProblem(std::move(math_problem), links, p_var_columns,p_direct_cost_columns,p_indirect_cost_columns); - - const int P_LINK_id = 0; - const int P_PLUS_id = 1; - const int P_MINUS_id = 2; - const int cand1_id = 3; - const int cand2_id = 4; - - verify_column(P_LINK_id,P_LINK,'C',1,MINUS_INF,PLUS_INF); - verify_column(P_PLUS_id,P_PLUS,'C',1,0,PLUS_INF); - verify_column(P_MINUS_id,P_MINUS,'C',1,0,PLUS_INF); - verify_column(cand1_id,cand1.name,'C',0,MINUS_INF,PLUS_INF); - verify_column(cand2_id,cand2.name,'C',0,MINUS_INF,PLUS_INF); - ASSERT_EQ(problem_modifier.get_candidate_col_id(cand1.name) , cand1_id); - ASSERT_EQ(problem_modifier.get_candidate_col_id(cand2.name) , cand2_id); - - verify_rows_are(8); - - verify_row(0,'L', - {1,-profile_cand1.getDirectProfile(0),-profile_cand2.getDirectProfile(0)}, - {P_LINK_id,cand1_id,cand2_id}, - link_capacity * profile_link.getDirectProfile(0)); - - verify_row(1 , 'G', - {1,profile_cand1.getIndirectProfile(0),profile_cand2.getIndirectProfile(0)}, - {P_LINK_id,cand1_id,cand2_id}, - -link_capacity * profile_link.getIndirectProfile(0)); - - verify_row(2,'L', - {1,-profile_cand1.getDirectProfile(1),-profile_cand2.getDirectProfile(1)}, - {P_LINK_id,cand1_id,cand2_id}, - link_capacity * profile_link.getDirectProfile(1)); - - verify_row(3 , 'G', - {1,profile_cand1.getIndirectProfile(1),profile_cand2.getIndirectProfile(1)}, - {P_LINK_id,cand1_id,cand2_id}, - -link_capacity * profile_link.getIndirectProfile(1)); - - verify_row(4, 'L', - {1,-profile_cand1.getDirectProfile(0),-profile_cand2.getDirectProfile(0)}, - {P_PLUS_id,cand1_id,cand2_id}, - link_capacity* profile_link.getDirectProfile(0)); - - verify_row(5, 'L', - {1,-profile_cand1.getDirectProfile(1),-profile_cand2.getDirectProfile(1)}, - {P_PLUS_id,cand1_id,cand2_id}, - link_capacity* profile_link.getDirectProfile(1)); - - verify_row(6, 'L', - {1,-profile_cand1.getIndirectProfile(0),-profile_cand2.getIndirectProfile(0)}, - {P_MINUS_id,cand1_id,cand2_id}, - link_capacity* profile_link.getIndirectProfile(0)); - - verify_row(7, 'L', - {1,-profile_cand1.getIndirectProfile(1),-profile_cand2.getIndirectProfile(1)}, - {P_MINUS_id,cand1_id,cand2_id}, - link_capacity* profile_link.getIndirectProfile(1)); - + const int link_id = 0; + const std::map p_var_columns = { + {link_id, {{0, 0}, {0, 1}}}}; + const std::map p_direct_cost_columns = { + {link_id, {{1, 0}, {1, 1}}}}; + const std::map p_indirect_cost_columns = { + {link_id, {{{2, 0}, {2, 1}}}}}; + + const double link_capacity = 2000.0; + CandidateData cand1; + cand1.link_id = link_id; + cand1.name = "candy1"; + cand1.link_name = "dummy_link"; + cand1.already_installed_capacity = link_capacity; + cand1.installed_link_profile_name = "install_link_profile"; + cand1.link_profile = "profile_cand1"; + CandidateData cand2; + cand2.link_id = link_id; + cand2.name = "candy2"; + cand2.link_name = "dummy_link"; + cand2.already_installed_capacity = link_capacity; + cand2.installed_link_profile_name = "install_link_profile"; + cand2.link_profile = "profile_cand2"; + + std::vector cand_data_list = {cand1, cand2}; + std::map profile_map; + LinkProfile profile_link; + profile_link._directLinkProfile = {1, 2}; + profile_link._indirectLinkProfile = {3, 4}; + profile_map["install_link_profile"] = profile_link; + LinkProfile profile_cand1; + profile_cand1._directLinkProfile = {0.5, 1}; + profile_cand1._indirectLinkProfile = {0.8, 1.2}; + profile_map["profile_cand1"] = profile_cand1; + LinkProfile profile_cand2; + profile_cand2._directLinkProfile = {1.5, 1.7}; + profile_cand2._indirectLinkProfile = {2.6, 2.8}; + profile_map["profile_cand2"] = profile_cand2; + + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + const std::vector& links = linkBuilder.getLinks(); + + auto problem_modifier = ProblemModifier(); + math_problem = problem_modifier.changeProblem( + std::move(math_problem), links, p_var_columns, p_direct_cost_columns, + p_indirect_cost_columns); + + const int P_LINK_id = 0; + const int P_PLUS_id = 1; + const int P_MINUS_id = 2; + const int cand1_id = 3; + const int cand2_id = 4; + + verify_column(P_LINK_id, P_LINK, 'C', 1, MINUS_INF, PLUS_INF); + verify_column(P_PLUS_id, P_PLUS, 'C', 1, 0, PLUS_INF); + verify_column(P_MINUS_id, P_MINUS, 'C', 1, 0, PLUS_INF); + verify_column(cand1_id, cand1.name, 'C', 0, MINUS_INF, PLUS_INF); + verify_column(cand2_id, cand2.name, 'C', 0, MINUS_INF, PLUS_INF); + ASSERT_EQ(problem_modifier.get_candidate_col_id(cand1.name), cand1_id); + ASSERT_EQ(problem_modifier.get_candidate_col_id(cand2.name), cand2_id); + + verify_rows_are(8); + + verify_row(0, 'L', + {1, -profile_cand1.getDirectProfile(0), + -profile_cand2.getDirectProfile(0)}, + {P_LINK_id, cand1_id, cand2_id}, + link_capacity * profile_link.getDirectProfile(0)); + + verify_row(1, 'G', + {1, profile_cand1.getIndirectProfile(0), + profile_cand2.getIndirectProfile(0)}, + {P_LINK_id, cand1_id, cand2_id}, + -link_capacity * profile_link.getIndirectProfile(0)); + + verify_row(2, 'L', + {1, -profile_cand1.getDirectProfile(1), + -profile_cand2.getDirectProfile(1)}, + {P_LINK_id, cand1_id, cand2_id}, + link_capacity * profile_link.getDirectProfile(1)); + + verify_row(3, 'G', + {1, profile_cand1.getIndirectProfile(1), + profile_cand2.getIndirectProfile(1)}, + {P_LINK_id, cand1_id, cand2_id}, + -link_capacity * profile_link.getIndirectProfile(1)); + + verify_row(4, 'L', + {1, -profile_cand1.getDirectProfile(0), + -profile_cand2.getDirectProfile(0)}, + {P_PLUS_id, cand1_id, cand2_id}, + link_capacity * profile_link.getDirectProfile(0)); + + verify_row(5, 'L', + {1, -profile_cand1.getDirectProfile(1), + -profile_cand2.getDirectProfile(1)}, + {P_PLUS_id, cand1_id, cand2_id}, + link_capacity * profile_link.getDirectProfile(1)); + + verify_row(6, 'L', + {1, -profile_cand1.getIndirectProfile(0), + -profile_cand2.getIndirectProfile(0)}, + {P_MINUS_id, cand1_id, cand2_id}, + link_capacity * profile_link.getIndirectProfile(0)); + + verify_row(7, 'L', + {1, -profile_cand1.getIndirectProfile(1), + -profile_cand2.getIndirectProfile(1)}, + {P_MINUS_id, cand1_id, cand2_id}, + link_capacity * profile_link.getIndirectProfile(1)); } - -TEST_F(ProblemModifierTest, One_link_two_candidates_one_candidate_with_empty_profile) { - const int link_id = 0; - const std::map p_var_columns = {{link_id,{{0, 0},{0, 1}}}}; - const std::map p_direct_cost_columns= {{link_id,{{1, 0},{1, 1}}}}; - const std::map p_indirect_cost_columns= {{link_id,{{{2, 0},{2, 1}}}}}; - - const double link_capacity = 2000.0; - CandidateData cand1; - cand1.link_id = link_id; - cand1.name = "candy1"; - cand1.link_name = "dummy_link"; - cand1.already_installed_capacity = link_capacity; - cand1.installed_link_profile_name = "install_link_profile"; - cand1.link_profile = "profile_cand1"; - CandidateData cand2; - cand2.link_id = link_id; - cand2.name = "candy2"; - cand2.link_name = "dummy_link"; - cand2.already_installed_capacity = link_capacity; - cand2.installed_link_profile_name = "install_link_profile"; - cand2.link_profile = "empty_profile"; - - std::vector cand_data_list = { cand1, cand2 }; - std::map profile_map; - LinkProfile profile_link; - profile_link._directLinkProfile = {1,2}; - profile_link._indirectLinkProfile = {3,4}; - profile_map["install_link_profile"]=profile_link; - LinkProfile profile_cand1; - profile_cand1._directLinkProfile = {0.5, 1}; - profile_cand1._indirectLinkProfile = {0.8, 1.2}; - profile_map["profile_cand1"]=profile_cand1; - LinkProfile empty_profile; - empty_profile._directLinkProfile = {0.0, 0.0}; - empty_profile._indirectLinkProfile = {0.0, 0.0}; - profile_map["empty_profile"]=empty_profile; - - ActiveLinksBuilder linkBuilder{ cand_data_list, profile_map }; - const std::vector& links = linkBuilder.getLinks(); - - auto problem_modifier = ProblemModifier(); - math_problem = problem_modifier.changeProblem(std::move(math_problem), links, p_var_columns,p_direct_cost_columns,p_indirect_cost_columns); - - const int P_LINK_id = 0; - const int P_PLUS_id = 1; - const int P_MINUS_id = 2; - const int cand1_id = 3; - - verify_column(P_LINK_id,P_LINK,'C',1,MINUS_INF,PLUS_INF); - verify_column(P_PLUS_id,P_PLUS,'C',1,0,PLUS_INF); - verify_column(P_MINUS_id,P_MINUS,'C',1,0,PLUS_INF); - verify_column(cand1_id,cand1.name,'C',0,MINUS_INF,PLUS_INF); - ASSERT_EQ(problem_modifier.get_candidate_col_id(cand1.name) , cand1_id); - EXPECT_FALSE(problem_modifier.has_candidate_col_id(cand2.name)); - - verify_rows_are(8); - - verify_row(0,'L', - {1,-profile_cand1.getDirectProfile(0)}, - {P_LINK_id,cand1_id}, - link_capacity * profile_link.getDirectProfile(0)); - - verify_row(1 , 'G', - {1,profile_cand1.getIndirectProfile(0)}, - {P_LINK_id,cand1_id}, - -link_capacity * profile_link.getIndirectProfile(0)); - - verify_row(2,'L', - {1,-profile_cand1.getDirectProfile(1)}, - {P_LINK_id,cand1_id}, - link_capacity * profile_link.getDirectProfile(1)); - - verify_row(3 , 'G', - {1,profile_cand1.getIndirectProfile(1)}, - {P_LINK_id,cand1_id}, - -link_capacity * profile_link.getIndirectProfile(1)); - - verify_row(4, 'L', - {1,-profile_cand1.getDirectProfile(0)}, - {P_PLUS_id,cand1_id}, - link_capacity* profile_link.getDirectProfile(0)); - - verify_row(5, 'L', - {1,-profile_cand1.getDirectProfile(1)}, - {P_PLUS_id,cand1_id}, - link_capacity* profile_link.getDirectProfile(1)); - - verify_row(6, 'L', - {1,-profile_cand1.getIndirectProfile(0)}, - {P_MINUS_id,cand1_id}, - link_capacity* profile_link.getIndirectProfile(0)); - - verify_row(7, 'L', - {1,-profile_cand1.getIndirectProfile(1)}, - {P_MINUS_id,cand1_id}, - link_capacity* profile_link.getIndirectProfile(1)); - +TEST_F(ProblemModifierTest, + One_link_two_candidates_one_candidate_with_empty_profile) { + const int link_id = 0; + const std::map p_var_columns = { + {link_id, {{0, 0}, {0, 1}}}}; + const std::map p_direct_cost_columns = { + {link_id, {{1, 0}, {1, 1}}}}; + const std::map p_indirect_cost_columns = { + {link_id, {{{2, 0}, {2, 1}}}}}; + + const double link_capacity = 2000.0; + CandidateData cand1; + cand1.link_id = link_id; + cand1.name = "candy1"; + cand1.link_name = "dummy_link"; + cand1.already_installed_capacity = link_capacity; + cand1.installed_link_profile_name = "install_link_profile"; + cand1.link_profile = "profile_cand1"; + CandidateData cand2; + cand2.link_id = link_id; + cand2.name = "candy2"; + cand2.link_name = "dummy_link"; + cand2.already_installed_capacity = link_capacity; + cand2.installed_link_profile_name = "install_link_profile"; + cand2.link_profile = "empty_profile"; + + std::vector cand_data_list = {cand1, cand2}; + std::map profile_map; + LinkProfile profile_link; + profile_link._directLinkProfile = {1, 2}; + profile_link._indirectLinkProfile = {3, 4}; + profile_map["install_link_profile"] = profile_link; + LinkProfile profile_cand1; + profile_cand1._directLinkProfile = {0.5, 1}; + profile_cand1._indirectLinkProfile = {0.8, 1.2}; + profile_map["profile_cand1"] = profile_cand1; + LinkProfile empty_profile; + empty_profile._directLinkProfile = {0.0, 0.0}; + empty_profile._indirectLinkProfile = {0.0, 0.0}; + profile_map["empty_profile"] = empty_profile; + + ActiveLinksBuilder linkBuilder{cand_data_list, profile_map}; + const std::vector& links = linkBuilder.getLinks(); + + auto problem_modifier = ProblemModifier(); + math_problem = problem_modifier.changeProblem( + std::move(math_problem), links, p_var_columns, p_direct_cost_columns, + p_indirect_cost_columns); + + const int P_LINK_id = 0; + const int P_PLUS_id = 1; + const int P_MINUS_id = 2; + const int cand1_id = 3; + + verify_column(P_LINK_id, P_LINK, 'C', 1, MINUS_INF, PLUS_INF); + verify_column(P_PLUS_id, P_PLUS, 'C', 1, 0, PLUS_INF); + verify_column(P_MINUS_id, P_MINUS, 'C', 1, 0, PLUS_INF); + verify_column(cand1_id, cand1.name, 'C', 0, MINUS_INF, PLUS_INF); + ASSERT_EQ(problem_modifier.get_candidate_col_id(cand1.name), cand1_id); + EXPECT_FALSE(problem_modifier.has_candidate_col_id(cand2.name)); + + verify_rows_are(8); + + verify_row(0, 'L', {1, -profile_cand1.getDirectProfile(0)}, + {P_LINK_id, cand1_id}, + link_capacity * profile_link.getDirectProfile(0)); + + verify_row(1, 'G', {1, profile_cand1.getIndirectProfile(0)}, + {P_LINK_id, cand1_id}, + -link_capacity * profile_link.getIndirectProfile(0)); + + verify_row(2, 'L', {1, -profile_cand1.getDirectProfile(1)}, + {P_LINK_id, cand1_id}, + link_capacity * profile_link.getDirectProfile(1)); + + verify_row(3, 'G', {1, profile_cand1.getIndirectProfile(1)}, + {P_LINK_id, cand1_id}, + -link_capacity * profile_link.getIndirectProfile(1)); + + verify_row(4, 'L', {1, -profile_cand1.getDirectProfile(0)}, + {P_PLUS_id, cand1_id}, + link_capacity * profile_link.getDirectProfile(0)); + + verify_row(5, 'L', {1, -profile_cand1.getDirectProfile(1)}, + {P_PLUS_id, cand1_id}, + link_capacity * profile_link.getDirectProfile(1)); + + verify_row(6, 'L', {1, -profile_cand1.getIndirectProfile(0)}, + {P_MINUS_id, cand1_id}, + link_capacity * profile_link.getIndirectProfile(0)); + + verify_row(7, 'L', {1, -profile_cand1.getIndirectProfile(1)}, + {P_MINUS_id, cand1_id}, + link_capacity * profile_link.getIndirectProfile(1)); } - - diff --git a/tests/cpp/lp_namer/VariableFileReaderTest.cpp b/tests/cpp/lp_namer/VariableFileReaderTest.cpp index e1bbb53a5..bc1c5edbb 100644 --- a/tests/cpp/lp_namer/VariableFileReaderTest.cpp +++ b/tests/cpp/lp_namer/VariableFileReaderTest.cpp @@ -1,248 +1,250 @@ -#include "gtest/gtest.h" - #include + #include "VariableFileReader.h" +#include "gtest/gtest.h" -const char* TEMP_FILE_NAME= "temp_variable.txt"; +const char* TEMP_FILE_NAME = "temp_variable.txt"; -struct VariableFileLine{ - int id; - std::string variable; - int id_pays; - int id_link; - int time_step; +struct VariableFileLine { + int id; + std::string variable; + int id_pays; + int id_link; + int time_step; }; -class VariableFileReaderTest : public ::testing::Test -{ -protected: - - static std::vector createVariableFileLineVec(const std::vector& ids, const std::vector& variable, - const std::vector& id_pays, - const std::vector& id_link, const std::vector& time_step){ - std::vector result; - result.reserve(ids.size()); - assert(ids.size() == variable.size()); - assert(variable.size() == id_pays.size()); - assert(id_pays.size() == id_link.size()); - assert(id_link.size() == time_step.size()); - - for (int i = 0; i< ids.size();i++) { - VariableFileLine line; - line.id = ids.at(i); - line.variable = variable.at(i); - line.id_pays = id_pays.at(i); - line.id_link = id_link.at(i); - line.time_step = time_step.at(i); - result.push_back(line); - } - - return result; +class VariableFileReaderTest : public ::testing::Test { + protected: + static std::vector createVariableFileLineVec( + const std::vector& ids, const std::vector& variable, + const std::vector& id_pays, const std::vector& id_link, + const std::vector& time_step) { + std::vector result; + result.reserve(ids.size()); + assert(ids.size() == variable.size()); + assert(variable.size() == id_pays.size()); + assert(id_pays.size() == id_link.size()); + assert(id_link.size() == time_step.size()); + + for (int i = 0; i < ids.size(); i++) { + VariableFileLine line; + line.id = ids.at(i); + line.variable = variable.at(i); + line.id_pays = id_pays.at(i); + line.id_link = id_link.at(i); + line.time_step = time_step.at(i); + result.push_back(line); } - static void createVariableFile(const std::string &temp_variable_name,const std::vector &variableFileLineVec) { - std::ofstream file(temp_variable_name); - - for (const auto& fileLine : variableFileLineVec) { - file << fileLine.id << " " << fileLine.variable; - if (fileLine.id_pays != -1) { - file << " " << fileLine.id_pays; - } - file <<" " <& ids, - const std::vector& variable, - const std::vector& id_pays, - const std::vector& id_link, - const std::vector& time_step) { - createVariableFile(temp_variable_name, createVariableFileLineVec(ids,variable,id_pays,id_link,time_step)); - } + static void createVariableFile( + const std::string& temp_variable_name, + const std::vector& variableFileLineVec) { + std::ofstream file(temp_variable_name); - static std::vector createExpectedVariableName(const std::vector& variable, - const std::vector& id_pays, - const std::vector& id_link, - const std::vector& time_step) { - - std::vector result; - result.reserve(variable.size()); - assert(variable.size() == id_pays.size()); - assert(id_pays.size() == id_link.size()); - assert(id_link.size() == time_step.size()); - - for (int i = 0; i< variable.size();i++) { - std::ostringstream name; - name << variable.at(i) << "_"; - if (id_pays.at(i) != -1) { - name << id_pays.at(i) << "_"; - } - name << id_link.at(i) << "_"; - name << time_step.at(i) << "_"; - result.push_back(name.str()); - } - return result; + for (const auto& fileLine : variableFileLineVec) { + file << fileLine.id << " " << fileLine.variable; + if (fileLine.id_pays != -1) { + file << " " << fileLine.id_pays; + } + file << " " << fileLine.id_link << " " << fileLine.time_step << "\n"; } - - static void SetUpTestCase() - { - + file.close(); + } + + static void createVariableFile(const std::string& temp_variable_name, + const std::vector& ids, + const std::vector& variable, + const std::vector& id_pays, + const std::vector& id_link, + const std::vector& time_step) { + createVariableFile( + temp_variable_name, + createVariableFileLineVec(ids, variable, id_pays, id_link, time_step)); + } + + static std::vector createExpectedVariableName( + const std::vector& variable, const std::vector& id_pays, + const std::vector& id_link, const std::vector& time_step) { + std::vector result; + result.reserve(variable.size()); + assert(variable.size() == id_pays.size()); + assert(id_pays.size() == id_link.size()); + assert(id_link.size() == time_step.size()); + + for (int i = 0; i < variable.size(); i++) { + std::ostringstream name; + name << variable.at(i) << "_"; + if (id_pays.at(i) != -1) { + name << id_pays.at(i) << "_"; + } + name << id_link.at(i) << "_"; + name << time_step.at(i) << "_"; + result.push_back(name.str()); } + return result; + } - static void TearDownTestCase() - { - // called after last test + static void SetUpTestCase() {} - //delete the created tmp file - std::remove(TEMP_FILE_NAME); - } + static void TearDownTestCase() { + // called after last test - void SetUp() - { - // called before each test - } + // delete the created tmp file + std::remove(TEMP_FILE_NAME); + } - void TearDown() - { - // called after each test - } + void SetUp() { + // called before each test + } - std::vector _ids; - std::vector _variable; - std::vector _id_pays; - std::vector _id_link; - std::vector _time_step; -}; + void TearDown() { + // called after each test + } + std::vector _ids; + std::vector _variable; + std::vector _id_pays; + std::vector _id_link; + std::vector _time_step; +}; TEST_F(VariableFileReaderTest, FileNotAvailable) { - try { - std::vector links; - VariableFileReadNameConfiguration variable_name_config; - VariableFileReader varReader("not_available_file.txt", links, variable_name_config); - FAIL(); - } - catch(const std::runtime_error& expected) { - ASSERT_STREQ(expected.what(), "Unable to open 'not_available_file.txt'"); - } -} - -TEST_F(VariableFileReaderTest, ReadVariable) { - - _ids = {0,1,2,3,4,5,6}; - _variable = {"var_1", "var_2", "var_3", "var_4", "var_5", "var_6", "var_7"}; - _id_pays = std::vector(_variable.size(), 0); - _id_link = {7,8,9,10,11,12,13}; - _time_step = {14,15,16,17,18,19,20}; - createVariableFile(TEMP_FILE_NAME, _ids,_variable,_id_pays,_id_link,_time_step); - + try { std::vector links; VariableFileReadNameConfiguration variable_name_config; - VariableFileReader varReader(TEMP_FILE_NAME, links, variable_name_config); - - std::vector expectedVariable = createExpectedVariableName(_variable,_id_pays, _id_link,_time_step); - std::vector variable = varReader.getVariables(); + VariableFileReader varReader("not_available_file.txt", links, + variable_name_config); + FAIL(); + } catch (const std::runtime_error& expected) { + ASSERT_STREQ(expected.what(), "Unable to open 'not_available_file.txt'"); + } +} - ASSERT_EQ(variable, expectedVariable); +TEST_F(VariableFileReaderTest, ReadVariable) { + _ids = {0, 1, 2, 3, 4, 5, 6}; + _variable = {"var_1", "var_2", "var_3", "var_4", "var_5", "var_6", "var_7"}; + _id_pays = std::vector(_variable.size(), 0); + _id_link = {7, 8, 9, 10, 11, 12, 13}; + _time_step = {14, 15, 16, 17, 18, 19, 20}; + createVariableFile(TEMP_FILE_NAME, _ids, _variable, _id_pays, _id_link, + _time_step); + + std::vector links; + VariableFileReadNameConfiguration variable_name_config; + VariableFileReader varReader(TEMP_FILE_NAME, links, variable_name_config); + + std::vector expectedVariable = + createExpectedVariableName(_variable, _id_pays, _id_link, _time_step); + std::vector variable = varReader.getVariables(); + + ASSERT_EQ(variable, expectedVariable); } TEST_F(VariableFileReaderTest, ReadNtcColumnsWithoutActiveLink) { - - _ids = {0,1,2,3,4,5,6}; - _variable = {"var_ntc", "var_ntc", "var_3", "var_4", "var_5", "var_6", "var_7"}; - _id_pays = std::vector(_variable.size(), 0); - _id_link = {7,8,9,10,11,12,13}; - _time_step = {14,15,16,17,18,19,20}; - createVariableFile(TEMP_FILE_NAME, _ids,_variable,_id_pays,_id_link,_time_step); - - VariableFileReadNameConfiguration variable_name_config; - variable_name_config.ntc_variable_name = "var_ntc"; - - std::vector links; - VariableFileReader varReader(TEMP_FILE_NAME, links,variable_name_config); - - std::map ntcVarColumns = varReader.getNtcVarColumns(); - ASSERT_EQ(ntcVarColumns.size(), 0); + _ids = {0, 1, 2, 3, 4, 5, 6}; + _variable = {"var_ntc", "var_ntc", "var_3", "var_4", + "var_5", "var_6", "var_7"}; + _id_pays = std::vector(_variable.size(), 0); + _id_link = {7, 8, 9, 10, 11, 12, 13}; + _time_step = {14, 15, 16, 17, 18, 19, 20}; + createVariableFile(TEMP_FILE_NAME, _ids, _variable, _id_pays, _id_link, + _time_step); + + VariableFileReadNameConfiguration variable_name_config; + variable_name_config.ntc_variable_name = "var_ntc"; + + std::vector links; + VariableFileReader varReader(TEMP_FILE_NAME, links, variable_name_config); + + std::map ntcVarColumns = + varReader.getNtcVarColumns(); + ASSERT_EQ(ntcVarColumns.size(), 0); } TEST_F(VariableFileReaderTest, ReadNtcColumnsWithOneActiveLink) { - - _ids = {0,1,2,3,4,5,6}; - _variable = {"var_ntc", "var_ntc", "var_3", "var_4", "var_5", "var_6", "var_7"}; - _id_pays = std::vector(_variable.size(), 0); - _id_link = {1,1,9,10,11,12,13}; - _time_step = {14,15,16,17,18,19,20}; - createVariableFile(TEMP_FILE_NAME, _ids,_variable,_id_pays,_id_link,_time_step); - - std::vector links; - links.push_back(ActiveLink(1, "link", "from", "to", 0)); - VariableFileReadNameConfiguration variable_name_config; - variable_name_config.ntc_variable_name = "var_ntc"; - VariableFileReader varReader(TEMP_FILE_NAME, links,variable_name_config); - - std::map ntcVarColumns = varReader.getNtcVarColumns(); - std::map expectedNtcVarColumns; - expectedNtcVarColumns[1] = { ColumnToChange(0,14), ColumnToChange(1,15)}; - - ASSERT_EQ(ntcVarColumns,expectedNtcVarColumns); + _ids = {0, 1, 2, 3, 4, 5, 6}; + _variable = {"var_ntc", "var_ntc", "var_3", "var_4", + "var_5", "var_6", "var_7"}; + _id_pays = std::vector(_variable.size(), 0); + _id_link = {1, 1, 9, 10, 11, 12, 13}; + _time_step = {14, 15, 16, 17, 18, 19, 20}; + createVariableFile(TEMP_FILE_NAME, _ids, _variable, _id_pays, _id_link, + _time_step); + + std::vector links; + links.push_back(ActiveLink(1, "link", "from", "to", 0)); + VariableFileReadNameConfiguration variable_name_config; + variable_name_config.ntc_variable_name = "var_ntc"; + VariableFileReader varReader(TEMP_FILE_NAME, links, variable_name_config); + + std::map ntcVarColumns = + varReader.getNtcVarColumns(); + std::map expectedNtcVarColumns; + expectedNtcVarColumns[1] = {ColumnToChange(0, 14), ColumnToChange(1, 15)}; + + ASSERT_EQ(ntcVarColumns, expectedNtcVarColumns); } TEST_F(VariableFileReaderTest, ReadNtcColumnsWithMultipleActiveLink) { - - _ids = {0,1,2,3,4,5,6}; - _variable = {"var_ntc", "var_ntc", "var_3", "var_4", "var_5", "var_ntc", "var_ntc"}; - _id_pays = std::vector(_variable.size(), 0); - _id_link = {1,1,9,10,11,2,2}; - _time_step = {14,15,16,17,18,19,20}; - createVariableFile(TEMP_FILE_NAME, _ids,_variable,_id_pays,_id_link,_time_step); - - std::vector links; - links.push_back(ActiveLink(1, "link", "from1", "to1", 0)); - links.push_back(ActiveLink(2, "link2", "from2", "to2", 0)); - VariableFileReadNameConfiguration variable_name_config; - variable_name_config.ntc_variable_name = "var_ntc"; - VariableFileReader varReader(TEMP_FILE_NAME, links,variable_name_config); - - std::map ntcVarColumns = varReader.getNtcVarColumns(); - std::map expectedNtcVarColumns; - expectedNtcVarColumns[1] = { ColumnToChange(0,14), ColumnToChange(1,15)}; - expectedNtcVarColumns[2] = { ColumnToChange(5,19), ColumnToChange(6,20)}; - - ASSERT_EQ(ntcVarColumns,expectedNtcVarColumns); + _ids = {0, 1, 2, 3, 4, 5, 6}; + _variable = {"var_ntc", "var_ntc", "var_3", "var_4", + "var_5", "var_ntc", "var_ntc"}; + _id_pays = std::vector(_variable.size(), 0); + _id_link = {1, 1, 9, 10, 11, 2, 2}; + _time_step = {14, 15, 16, 17, 18, 19, 20}; + createVariableFile(TEMP_FILE_NAME, _ids, _variable, _id_pays, _id_link, + _time_step); + + std::vector links; + links.push_back(ActiveLink(1, "link", "from1", "to1", 0)); + links.push_back(ActiveLink(2, "link2", "from2", "to2", 0)); + VariableFileReadNameConfiguration variable_name_config; + variable_name_config.ntc_variable_name = "var_ntc"; + VariableFileReader varReader(TEMP_FILE_NAME, links, variable_name_config); + + std::map ntcVarColumns = + varReader.getNtcVarColumns(); + std::map expectedNtcVarColumns; + expectedNtcVarColumns[1] = {ColumnToChange(0, 14), ColumnToChange(1, 15)}; + expectedNtcVarColumns[2] = {ColumnToChange(5, 19), ColumnToChange(6, 20)}; + + ASSERT_EQ(ntcVarColumns, expectedNtcVarColumns); } TEST_F(VariableFileReaderTest, ReadCostColumnsWithMultipleActiveLink) { - - _ids = {0,1,2,3,4,5,6}; - _variable = {"cost_ori", "cost_ori", "cost_ext", "var_4", "cost_ext", "cost_ori", "cost_ori"}; - _id_pays = std::vector(_variable.size(), -1); - _id_link = {1,1,1,10,2,2,2}; - _time_step = {14,15,16,17,18,19,20}; - createVariableFile(TEMP_FILE_NAME, _ids,_variable,_id_pays,_id_link,_time_step); - - std::vector links; - links.push_back(ActiveLink(1, "link", "from", "to", 0)); - links.push_back(ActiveLink(2, "link2", "from", "to", 0)); - - VariableFileReadNameConfiguration variable_name_config; - variable_name_config.cost_origin_variable_name = "cost_ori"; - variable_name_config.cost_extremite_variable_name = "cost_ext"; - VariableFileReader varReader(TEMP_FILE_NAME, links, variable_name_config); - - std::map directCostVarColumns = varReader.getDirectCostVarColumns(); - std::map expectedDirectCostVarColumns; - expectedDirectCostVarColumns[1] = {{0,14}, {1,15}}; - expectedDirectCostVarColumns[2] = {{5,19}, {6,20}}; - ASSERT_EQ(directCostVarColumns,expectedDirectCostVarColumns); - - std::map indirectCostVarColumns = varReader.getIndirectCostVarColumns(); - std::map expectedIndirectCostVarColumns; - - expectedIndirectCostVarColumns[1] = { {2,16}}; - expectedIndirectCostVarColumns[2] = {{4,18}}; - ASSERT_EQ(indirectCostVarColumns,expectedIndirectCostVarColumns); + _ids = {0, 1, 2, 3, 4, 5, 6}; + _variable = {"cost_ori", "cost_ori", "cost_ext", "var_4", + "cost_ext", "cost_ori", "cost_ori"}; + _id_pays = std::vector(_variable.size(), -1); + _id_link = {1, 1, 1, 10, 2, 2, 2}; + _time_step = {14, 15, 16, 17, 18, 19, 20}; + createVariableFile(TEMP_FILE_NAME, _ids, _variable, _id_pays, _id_link, + _time_step); + + std::vector links; + links.push_back(ActiveLink(1, "link", "from", "to", 0)); + links.push_back(ActiveLink(2, "link2", "from", "to", 0)); + + VariableFileReadNameConfiguration variable_name_config; + variable_name_config.cost_origin_variable_name = "cost_ori"; + variable_name_config.cost_extremite_variable_name = "cost_ext"; + VariableFileReader varReader(TEMP_FILE_NAME, links, variable_name_config); + + std::map directCostVarColumns = + varReader.getDirectCostVarColumns(); + std::map expectedDirectCostVarColumns; + expectedDirectCostVarColumns[1] = {{0, 14}, {1, 15}}; + expectedDirectCostVarColumns[2] = {{5, 19}, {6, 20}}; + ASSERT_EQ(directCostVarColumns, expectedDirectCostVarColumns); + + std::map indirectCostVarColumns = + varReader.getIndirectCostVarColumns(); + std::map expectedIndirectCostVarColumns; + + expectedIndirectCostVarColumns[1] = {{2, 16}}; + expectedIndirectCostVarColumns[2] = {{4, 18}}; + ASSERT_EQ(indirectCostVarColumns, expectedIndirectCostVarColumns); } - - diff --git a/tests/cpp/solvers_interface/catch2.hpp b/tests/cpp/solvers_interface/catch2.hpp index 9754a6547..7073a8136 100644 --- a/tests/cpp/solvers_interface/catch2.hpp +++ b/tests/cpp/solvers_interface/catch2.hpp @@ -2,8 +2,8 @@ * Catch v2.11.1 * Generated: 2019-12-28 21:22:11.930976 * ---------------------------------------------------------- - * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved. + * This file has been merged from multiple headers. Please don't edit it + * directly Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved. * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -12,88 +12,88 @@ #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED // start catch.hpp - #define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MINOR 11 #define CATCH_VERSION_PATCH 1 #ifdef __clang__ -# pragma clang system_header +#pragma clang system_header #elif defined __GNUC__ -# pragma GCC system_header +#pragma GCC system_header #endif // start catch_suppress_warnings.h #ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(push) -# pragma warning(disable: 161 1682) -# else // __ICC -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wswitch-enum" -# pragma clang diagnostic ignored "-Wcovered-switch-default" -# endif +#ifdef __ICC // icpc defines the __clang__ macro +#pragma warning(push) +#pragma warning(disable : 161 1682) +#else // __ICC +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#pragma clang diagnostic ignored "-Wswitch-enum" +#pragma clang diagnostic ignored "-Wcovered-switch-default" +#endif #elif defined __GNUC__ - // Because REQUIREs trigger GCC's -Wparentheses, and because still - // supported version of g++ have only buggy support for _Pragmas, - // Wparentheses have to be suppressed globally. -# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details - -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-variable" -# pragma GCC diagnostic ignored "-Wpadded" +// Because REQUIREs trigger GCC's -Wparentheses, and because still +// supported version of g++ have only buggy support for _Pragmas, +// Wparentheses have to be suppressed globally. +#pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wpadded" #endif // end catch_suppress_warnings.h #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) -# define CATCH_IMPL -# define CATCH_CONFIG_ALL_PARTS +#define CATCH_IMPL +#define CATCH_CONFIG_ALL_PARTS #endif // In the impl file, we want to have access to all parts of the headers // Can also be used to sanely support PCHs #if defined(CATCH_CONFIG_ALL_PARTS) -# define CATCH_CONFIG_EXTERNAL_INTERFACES -# if defined(CATCH_CONFIG_DISABLE_MATCHERS) -# undef CATCH_CONFIG_DISABLE_MATCHERS -# endif -# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) -# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER -# endif +#define CATCH_CONFIG_EXTERNAL_INTERFACES +#if defined(CATCH_CONFIG_DISABLE_MATCHERS) +#undef CATCH_CONFIG_DISABLE_MATCHERS +#endif +#if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +#endif #endif #if !defined(CATCH_CONFIG_IMPL_ONLY) // start catch_platform.h #ifdef __APPLE__ -# include -# if TARGET_OS_OSX == 1 -# define CATCH_PLATFORM_MAC -# elif TARGET_OS_IPHONE == 1 -# define CATCH_PLATFORM_IPHONE -# endif +#include +#if TARGET_OS_OSX == 1 +#define CATCH_PLATFORM_MAC +#elif TARGET_OS_IPHONE == 1 +#define CATCH_PLATFORM_IPHONE +#endif #elif defined(linux) || defined(__linux) || defined(__linux__) -# define CATCH_PLATFORM_LINUX +#define CATCH_PLATFORM_LINUX -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) -# define CATCH_PLATFORM_WINDOWS +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || \ + defined(_MSC_VER) || defined(__MINGW32__) +#define CATCH_PLATFORM_WINDOWS #endif // end catch_platform.h #ifdef CATCH_IMPL -# ifndef CLARA_CONFIG_MAIN -# define CLARA_CONFIG_MAIN_NOT_DEFINED -# define CLARA_CONFIG_MAIN -# endif +#ifndef CLARA_CONFIG_MAIN +#define CLARA_CONFIG_MAIN_NOT_DEFINED +#define CLARA_CONFIG_MAIN +#endif #endif // start catch_user_interfaces.h namespace Catch { - unsigned int rngSeed(); +unsigned int rngSeed(); } // end catch_user_interfaces.h @@ -122,84 +122,86 @@ namespace Catch { #ifdef __cplusplus -# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) -# define CATCH_CPP14_OR_GREATER -# endif +#if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) +#define CATCH_CPP14_OR_GREATER +#endif -# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) -# define CATCH_CPP17_OR_GREATER -# endif +#if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +#define CATCH_CPP17_OR_GREATER +#endif #endif #if defined(CATCH_CPP17_OR_GREATER) -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS #endif // We have to avoid both ICC and Clang, because they try to mask themselves // as gcc, and we want only GCC in this block #if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) +#define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma("GCC diagnostic push") +#define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma("GCC diagnostic pop") #endif #if defined(__clang__) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) +#define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + _Pragma("clang diagnostic push") +#define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma("clang diagnostic pop") -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ - _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") +#define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \ + _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) +#define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma("clang diagnostic ignored \"-Wparentheses\"") -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) +#define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + _Pragma("clang diagnostic ignored \"-Wunused-variable\"") -# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) +#define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + _Pragma("clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"") -# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) +#define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ + _Pragma("clang diagnostic ignored \"-Wunused-template\"") -#endif // __clang__ +#endif // __clang__ //////////////////////////////////////////////////////////////////////////////// // Assume that non-Windows platforms support posix signals by default #if !defined(CATCH_PLATFORM_WINDOWS) - #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS +#define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS #endif //////////////////////////////////////////////////////////////////////////////// // We know some environments not to support full POSIX signals -#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) - #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || \ + defined(__DJGPP__) +#define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS #endif #ifdef __OS400__ -# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -# define CATCH_CONFIG_COLOUR_NONE +#define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +#define CATCH_CONFIG_COLOUR_NONE #endif //////////////////////////////////////////////////////////////////////////////// // Android somehow still does not support std::to_string #if defined(__ANDROID__) -# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING -# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE +#define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +#define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE #endif //////////////////////////////////////////////////////////////////////////////// // Not all Windows environments support SEH properly #if defined(__MINGW32__) -# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH +#define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH #endif //////////////////////////////////////////////////////////////////////////////// // PS4 #if defined(__ORBIS__) -# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE +#define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE #endif //////////////////////////////////////////////////////////////////////////////// @@ -207,69 +209,74 @@ namespace Catch { #ifdef __CYGWIN__ // Required for some versions of Cygwin to declare gettimeofday -// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin -# define _BSD_SOURCE -// some versions of cygwin (most) do not support std::to_string. Use the libstd check. -// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 -# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ - && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) +// see: +// http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin +#define _BSD_SOURCE +// some versions of cygwin (most) do not support std::to_string. Use the libstd +// check. +// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html +// line 2812-2813 +#if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) && \ + !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) + +#define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING -# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING - -# endif -#endif // __CYGWIN__ +#endif +#endif // __CYGWIN__ //////////////////////////////////////////////////////////////////////////////// // Visual C++ #if defined(_MSC_VER) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) +#define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma(warning(push)) +#define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma(warning(pop)) -# if _MSC_VER >= 1900 // Visual Studio 2015 or newer -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -# endif +#if _MSC_VER >= 1900 // Visual Studio 2015 or newer +#define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif // Universal Windows platform does not support SEH // Or console colours (or console at all...) -# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) -# define CATCH_CONFIG_COLOUR_NONE -# else -# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH -# endif +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +#define CATCH_CONFIG_COLOUR_NONE +#else +#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +#endif // MSVC traditional preprocessor needs some workaround for __VA_ARGS__ // _MSVC_TRADITIONAL == 0 means new conformant preprocessor // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor -# if !defined(__clang__) // Handle Clang masquerading for msvc -# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) -# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -# endif // MSVC_TRADITIONAL -# endif // __clang__ +#if !defined(__clang__) // Handle Clang masquerading for msvc +#if !defined(_MSVC_TRADITIONAL) || \ + (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +#define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#endif // MSVC_TRADITIONAL +#endif // __clang__ -#endif // _MSC_VER +#endif // _MSC_VER #if defined(_REENTRANT) || defined(_MSC_VER) -// Enable async processing, as -pthread is specified or no additional linking is required -# define CATCH_INTERNAL_CONFIG_USE_ASYNC -#endif // _MSC_VER +// Enable async processing, as -pthread is specified or no additional linking is +// required +#define CATCH_INTERNAL_CONFIG_USE_ASYNC +#endif // _MSC_VER //////////////////////////////////////////////////////////////////////////////// // Check if we are compiled with -fno-exceptions or equivalent #if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) -# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED +#define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED #endif //////////////////////////////////////////////////////////////////////////////// // DJGPP #ifdef __DJGPP__ -# define CATCH_INTERNAL_CONFIG_NO_WCHAR -#endif // __DJGPP__ +#define CATCH_INTERNAL_CONFIG_NO_WCHAR +#endif // __DJGPP__ //////////////////////////////////////////////////////////////////////////////// // Embarcadero C++Build #if defined(__BORLANDC__) - #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN +#define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN #endif //////////////////////////////////////////////////////////////////////////////// @@ -279,8 +286,8 @@ namespace Catch { // handled by it. // Otherwise all supported compilers support COUNTER macro, // but user still might want to turn it off -#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) - #define CATCH_INTERNAL_CONFIG_COUNTER +#if (!defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L) +#define CATCH_INTERNAL_CONFIG_COUNTER #endif //////////////////////////////////////////////////////////////////////////////// @@ -289,9 +296,9 @@ namespace Catch { // This means that it is detected as Windows, but does not provide // the same set of capabilities as real Windows does. #if defined(UNDER_RTSS) || defined(RTX64_BUILD) - #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH - #define CATCH_INTERNAL_CONFIG_NO_ASYNC - #define CATCH_CONFIG_COLOUR_NONE +#define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH +#define CATCH_INTERNAL_CONFIG_NO_ASYNC +#define CATCH_CONFIG_COLOUR_NONE #endif #if defined(__UCLIBC__) @@ -300,134 +307,170 @@ namespace Catch { // Various stdlib support checks that require __has_include #if defined(__has_include) - // Check if string_view is available and usable - #if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW - #endif - - // Check if optional is available and usable - # if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL - # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) - - // Check if byte is available and usable - # if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # define CATCH_INTERNAL_CONFIG_CPP17_BYTE - # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) - - // Check if variant is available and usable - # if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # if defined(__clang__) && (__clang_major__ < 8) - // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 - // fix should be in clang 8, workaround in libstdc++ 8.2 - # include - # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) - # define CATCH_CONFIG_NO_CPP17_VARIANT - # else - # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT - # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) - # else - # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT - # endif // defined(__clang__) && (__clang_major__ < 8) - # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) -#endif // defined(__has_include) - -#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) -# define CATCH_CONFIG_COUNTER +// Check if string_view is available and usable +#if __has_include() && defined(CATCH_CPP17_OR_GREATER) +#define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW +#endif + +// Check if optional is available and usable +#if __has_include() && defined(CATCH_CPP17_OR_GREATER) +#define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL +#endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + +// Check if byte is available and usable +#if __has_include() && defined(CATCH_CPP17_OR_GREATER) +#define CATCH_INTERNAL_CONFIG_CPP17_BYTE +#endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) + +// Check if variant is available and usable +#if __has_include() && defined(CATCH_CPP17_OR_GREATER) +#if defined(__clang__) && (__clang_major__ < 8) +// work around clang bug with libstdc++ +// https://bugs.llvm.org/show_bug.cgi?id=31852 fix should be in clang 8, +// workaround in libstdc++ 8.2 +#include +#if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) +#define CATCH_CONFIG_NO_CPP17_VARIANT +#else +#define CATCH_INTERNAL_CONFIG_CPP17_VARIANT +#endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && + // (_GLIBCXX_RELEASE < 9) +#else +#define CATCH_INTERNAL_CONFIG_CPP17_VARIANT +#endif // defined(__clang__) && (__clang_major__ < 8) +#endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) +#endif // defined(__has_include) + +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && \ + !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +#define CATCH_CONFIG_COUNTER #endif -#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) -# define CATCH_CONFIG_WINDOWS_SEH +#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && \ + !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && \ + !defined(CATCH_CONFIG_WINDOWS_SEH) && \ + !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) +#define CATCH_CONFIG_WINDOWS_SEH #endif -// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. -#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) -# define CATCH_CONFIG_POSIX_SIGNALS +// This is set by default, because we assume that unix compilers are +// posix-signal-compatible by default. +#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && \ + !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && \ + !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && \ + !defined(CATCH_CONFIG_POSIX_SIGNALS) +#define CATCH_CONFIG_POSIX_SIGNALS #endif -// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. -#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) -# define CATCH_CONFIG_WCHAR +// This is set by default, because we assume that compilers with no wchar_t +// support are just rare exceptions. +#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && \ + !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) +#define CATCH_CONFIG_WCHAR #endif -#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) -# define CATCH_CONFIG_CPP11_TO_STRING +#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && \ + !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && \ + !defined(CATCH_CONFIG_CPP11_TO_STRING) +#define CATCH_CONFIG_CPP11_TO_STRING #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) -# define CATCH_CONFIG_CPP17_OPTIONAL +#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && \ + !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && \ + !defined(CATCH_CONFIG_CPP17_OPTIONAL) +#define CATCH_CONFIG_CPP17_OPTIONAL #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) -# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && \ + !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && \ + !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) +#define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) -# define CATCH_CONFIG_CPP17_STRING_VIEW +#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && \ + !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && \ + !defined(CATCH_CONFIG_CPP17_STRING_VIEW) +#define CATCH_CONFIG_CPP17_STRING_VIEW #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) -# define CATCH_CONFIG_CPP17_VARIANT +#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && \ + !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && \ + !defined(CATCH_CONFIG_CPP17_VARIANT) +#define CATCH_CONFIG_CPP17_VARIANT #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) -# define CATCH_CONFIG_CPP17_BYTE +#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && \ + !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) +#define CATCH_CONFIG_CPP17_BYTE #endif #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) -# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE +#define CATCH_INTERNAL_CONFIG_NEW_CAPTURE #endif -#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) -# define CATCH_CONFIG_NEW_CAPTURE +#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && \ + !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && \ + !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && \ + !defined(CATCH_CONFIG_NEW_CAPTURE) +#define CATCH_CONFIG_NEW_CAPTURE #endif -#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -# define CATCH_CONFIG_DISABLE_EXCEPTIONS +#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && \ + !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +#define CATCH_CONFIG_DISABLE_EXCEPTIONS #endif -#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) -# define CATCH_CONFIG_POLYFILL_ISNAN +#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && \ + !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && \ + !defined(CATCH_CONFIG_POLYFILL_ISNAN) +#define CATCH_CONFIG_POLYFILL_ISNAN #endif -#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) -# define CATCH_CONFIG_USE_ASYNC +#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && \ + !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && \ + !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) +#define CATCH_CONFIG_USE_ASYNC #endif -#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) -# define CATCH_CONFIG_ANDROID_LOGWRITE +#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && \ + !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && \ + !defined(CATCH_CONFIG_ANDROID_LOGWRITE) +#define CATCH_CONFIG_ANDROID_LOGWRITE #endif -#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) -# define CATCH_CONFIG_GLOBAL_NEXTAFTER +#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && \ + !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && \ + !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) +#define CATCH_CONFIG_GLOBAL_NEXTAFTER #endif // Even if we do not think the compiler has that warning, we still have // to provide a macro that can be used by the code. #if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION +#define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION #endif #if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION #endif #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +#define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS +#define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS +#define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS #endif -#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) -# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#if defined(__APPLE__) && defined(__apple_build_version__) && \ + (__clang_major__ < 10) +#undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS #elif defined(__clang__) && (__clang_major__ < 5) -# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS #endif #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS #endif #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) @@ -440,103 +483,109 @@ namespace Catch { #define CATCH_CATCH_ANON(type) catch (type) #endif -#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) +#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && \ + !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && \ + !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) #define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #endif // end catch_compiler_capabilities.h -#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line -#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2(name, line) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE(name, line) \ + INTERNAL_CATCH_UNIQUE_NAME_LINE2(name, line) #ifdef CATCH_CONFIG_COUNTER -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#define INTERNAL_CATCH_UNIQUE_NAME(name) \ + INTERNAL_CATCH_UNIQUE_NAME_LINE(name, __COUNTER__) #else -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#define INTERNAL_CATCH_UNIQUE_NAME(name) \ + INTERNAL_CATCH_UNIQUE_NAME_LINE(name, __LINE__) #endif +#include #include #include -#include -// We need a dummy global operator<< so we can bring it into Catch namespace later +// We need a dummy global operator<< so we can bring it into Catch namespace +// later struct Catch_global_namespace_dummy {}; std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); namespace Catch { - struct CaseSensitive { enum Choice { - Yes, - No - }; }; - - class NonCopyable { - NonCopyable( NonCopyable const& ) = delete; - NonCopyable( NonCopyable && ) = delete; - NonCopyable& operator = ( NonCopyable const& ) = delete; - NonCopyable& operator = ( NonCopyable && ) = delete; +struct CaseSensitive { + enum Choice { Yes, No }; +}; - protected: - NonCopyable(); - virtual ~NonCopyable(); - }; +class NonCopyable { + NonCopyable(NonCopyable const&) = delete; + NonCopyable(NonCopyable&&) = delete; + NonCopyable& operator=(NonCopyable const&) = delete; + NonCopyable& operator=(NonCopyable&&) = delete; - struct SourceLineInfo { + protected: + NonCopyable(); + virtual ~NonCopyable(); +}; - SourceLineInfo() = delete; - SourceLineInfo( char const* _file, std::size_t _line ) noexcept - : file( _file ), - line( _line ) - {} +struct SourceLineInfo { + SourceLineInfo() = delete; + SourceLineInfo(char const* _file, std::size_t _line) noexcept + : file(_file), line(_line) {} - SourceLineInfo( SourceLineInfo const& other ) = default; - SourceLineInfo& operator = ( SourceLineInfo const& ) = default; - SourceLineInfo( SourceLineInfo&& ) noexcept = default; - SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; + SourceLineInfo(SourceLineInfo const& other) = default; + SourceLineInfo& operator=(SourceLineInfo const&) = default; + SourceLineInfo(SourceLineInfo&&) noexcept = default; + SourceLineInfo& operator=(SourceLineInfo&&) noexcept = default; - bool empty() const noexcept { return file[0] == '\0'; } - bool operator == ( SourceLineInfo const& other ) const noexcept; - bool operator < ( SourceLineInfo const& other ) const noexcept; + bool empty() const noexcept { return file[0] == '\0'; } + bool operator==(SourceLineInfo const& other) const noexcept; + bool operator<(SourceLineInfo const& other) const noexcept; - char const* file; - std::size_t line; - }; + char const* file; + std::size_t line; +}; - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); +std::ostream& operator<<(std::ostream& os, SourceLineInfo const& info); - // Bring in operator<< from global namespace into Catch namespace - // This is necessary because the overload of operator<< above makes - // lookup stop at namespace Catch - using ::operator<<; +// Bring in operator<< from global namespace into Catch namespace +// This is necessary because the overload of operator<< above makes +// lookup stop at namespace Catch +using ::operator<<; - // Use this in variadic streaming macros to allow - // >> +StreamEndStop - // as well as - // >> stuff +StreamEndStop - struct StreamEndStop { - std::string operator+() const; - }; - template - T const& operator + ( T const& value, StreamEndStop ) { - return value; - } +// Use this in variadic streaming macros to allow +// >> +StreamEndStop +// as well as +// >> stuff +StreamEndStop +struct StreamEndStop { + std::string operator+() const; +}; +template +T const& operator+(T const& value, StreamEndStop) { + return value; } +} // namespace Catch #define CATCH_INTERNAL_LINEINFO \ - ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) + ::Catch::SourceLineInfo(__FILE__, static_cast(__LINE__)) // end catch_common.h namespace Catch { - struct RegistrarForTagAliases { - RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); - }; +struct RegistrarForTagAliases { + RegistrarForTagAliases(char const* alias, char const* tag, + SourceLineInfo const& lineInfo); +}; -} // end namespace Catch +} // end namespace Catch -#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#define CATCH_REGISTER_TAG_ALIAS(alias, spec) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace { \ + Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( \ + AutoRegisterTagAlias)(alias, spec, CATCH_INTERNAL_LINEINFO); \ + } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION // end catch_tag_alias_autoregistrar.h // start catch_test_registry.h @@ -547,143 +596,152 @@ namespace Catch { namespace Catch { - class TestSpec; +class TestSpec; - struct ITestInvoker { - virtual void invoke () const = 0; - virtual ~ITestInvoker(); - }; +struct ITestInvoker { + virtual void invoke() const = 0; + virtual ~ITestInvoker(); +}; - class TestCase; - struct IConfig; +class TestCase; +struct IConfig; - struct ITestCaseRegistry { - virtual ~ITestCaseRegistry(); - virtual std::vector const& getAllTests() const = 0; - virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; - }; +struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( + IConfig const& config) const = 0; +}; - bool isThrowSafe( TestCase const& testCase, IConfig const& config ); - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); - std::vector const& getAllTestCasesSorted( IConfig const& config ); +bool isThrowSafe(TestCase const& testCase, IConfig const& config); +bool matchTest(TestCase const& testCase, TestSpec const& testSpec, + IConfig const& config); +std::vector filterTests(std::vector const& testCases, + TestSpec const& testSpec, + IConfig const& config); +std::vector const& getAllTestCasesSorted(IConfig const& config); -} +} // namespace Catch // end catch_interfaces_testcase.h // start catch_stringref.h +#include #include -#include #include -#include +#include namespace Catch { - /// A non-owning string class (similar to the forthcoming std::string_view) - /// Note that, because a StringRef may be a substring of another string, - /// it may not be null terminated. - class StringRef { - public: - using size_type = std::size_t; - using const_iterator = const char*; +/// A non-owning string class (similar to the forthcoming std::string_view) +/// Note that, because a StringRef may be a substring of another string, +/// it may not be null terminated. +class StringRef { + public: + using size_type = std::size_t; + using const_iterator = const char*; - private: - static constexpr char const* const s_empty = ""; + private: + static constexpr char const* const s_empty = ""; - char const* m_start = s_empty; - size_type m_size = 0; + char const* m_start = s_empty; + size_type m_size = 0; - public: // construction - constexpr StringRef() noexcept = default; + public: // construction + constexpr StringRef() noexcept = default; - StringRef( char const* rawChars ) noexcept; + StringRef(char const* rawChars) noexcept; - constexpr StringRef( char const* rawChars, size_type size ) noexcept - : m_start( rawChars ), - m_size( size ) - {} + constexpr StringRef(char const* rawChars, size_type size) noexcept + : m_start(rawChars), m_size(size) {} - StringRef( std::string const& stdString ) noexcept - : m_start( stdString.c_str() ), - m_size( stdString.size() ) - {} + StringRef(std::string const& stdString) noexcept + : m_start(stdString.c_str()), m_size(stdString.size()) {} - explicit operator std::string() const { - return std::string(m_start, m_size); - } + explicit operator std::string() const { return std::string(m_start, m_size); } - public: // operators - auto operator == ( StringRef const& other ) const noexcept -> bool; - auto operator != (StringRef const& other) const noexcept -> bool { - return !(*this == other); - } + public: // operators + auto operator==(StringRef const& other) const noexcept -> bool; + auto operator!=(StringRef const& other) const noexcept -> bool { + return !(*this == other); + } - auto operator[] ( size_type index ) const noexcept -> char { - assert(index < m_size); - return m_start[index]; - } + auto operator[](size_type index) const noexcept -> char { + assert(index < m_size); + return m_start[index]; + } - public: // named queries - constexpr auto empty() const noexcept -> bool { - return m_size == 0; - } - constexpr auto size() const noexcept -> size_type { - return m_size; - } + public: // named queries + constexpr auto empty() const noexcept -> bool { return m_size == 0; } + constexpr auto size() const noexcept -> size_type { return m_size; } - // Returns the current start pointer. If the StringRef is not - // null-terminated, throws std::domain_exception - auto c_str() const -> char const*; + // Returns the current start pointer. If the StringRef is not + // null-terminated, throws std::domain_exception + auto c_str() const -> char const*; - public: // substrings and searches - // Returns a substring of [start, start + length). - // If start + length > size(), then the substring is [start, size()). - // If start > size(), then the substring is empty. - auto substr( size_type start, size_type length ) const noexcept -> StringRef; + public: // substrings and searches + // Returns a substring of [start, start + length). + // If start + length > size(), then the substring is [start, size()). + // If start > size(), then the substring is empty. + auto substr(size_type start, size_type length) const noexcept -> StringRef; - // Returns the current start pointer. May not be null-terminated. - auto data() const noexcept -> char const*; + // Returns the current start pointer. May not be null-terminated. + auto data() const noexcept -> char const*; - constexpr auto isNullTerminated() const noexcept -> bool { - return m_start[m_size] == '\0'; - } + constexpr auto isNullTerminated() const noexcept -> bool { + return m_start[m_size] == '\0'; + } - public: // iterators - constexpr const_iterator begin() const { return m_start; } - constexpr const_iterator end() const { return m_start + m_size; } - }; + public: // iterators + constexpr const_iterator begin() const { return m_start; } + constexpr const_iterator end() const { return m_start + m_size; } +}; - auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; - auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; +auto operator+=(std::string& lhs, StringRef const& sr) -> std::string&; +auto operator<<(std::ostream& os, StringRef const& sr) -> std::ostream&; - constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { - return StringRef( rawChars, size ); - } -} // namespace Catch +constexpr auto operator"" _sr(char const* rawChars, std::size_t size) noexcept + -> StringRef { + return StringRef(rawChars, size); +} +} // namespace Catch -constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { - return Catch::StringRef( rawChars, size ); +constexpr auto operator"" _catch_sr(char const* rawChars, + std::size_t size) noexcept + -> Catch::StringRef { + return Catch::StringRef(rawChars, size); } // end catch_stringref.h // start catch_preprocessor.hpp - #define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ -#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL1(...) \ + CATCH_RECURSION_LEVEL0( \ + CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL2(...) \ + CATCH_RECURSION_LEVEL1( \ + CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL3(...) \ + CATCH_RECURSION_LEVEL2( \ + CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL4(...) \ + CATCH_RECURSION_LEVEL3( \ + CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL5(...) \ + CATCH_RECURSION_LEVEL4( \ + CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) #ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ // MSVC needs more evaluations -#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) -#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) +#define CATCH_RECURSION_LEVEL6(...) \ + CATCH_RECURSION_LEVEL5( \ + CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) +#define CATCH_RECURSE(...) \ + CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) #else -#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) #endif #define CATCH_REC_END(...) @@ -696,627 +754,1152 @@ constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) n #define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 #define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 #define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT -#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) -#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) - -#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) - -#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) - -// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, -// and passes userdata as the first parameter to each invocation, -// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) -#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) - -#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) +#define CATCH_REC_NEXT1(test, next) CATCH_DEFER(CATCH_REC_NEXT0)(test, next, 0) +#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) + +#define CATCH_REC_LIST0(f, x, peek, ...) \ + , f(x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1))(f, peek, \ + __VA_ARGS__) +#define CATCH_REC_LIST1(f, x, peek, ...) \ + , f(x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST0))(f, peek, \ + __VA_ARGS__) +#define CATCH_REC_LIST2(f, x, peek, ...) \ + f(x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1))(f, peek, __VA_ARGS__) + +#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) \ + , f(userdata, x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD))( \ + f, userdata, peek, __VA_ARGS__) +#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) \ + , f(userdata, x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD))( \ + f, userdata, peek, __VA_ARGS__) +#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) \ + f(userdata, x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD))( \ + f, userdata, peek, __VA_ARGS__) + +// Applies the function macro `f` to each of the remaining parameters, inserts +// commas between the results, and passes userdata as the first parameter to +// each invocation, e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), +// f(x, b), f(x, c) +#define CATCH_REC_LIST_UD(f, userdata, ...) \ + CATCH_RECURSE( \ + CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define CATCH_REC_LIST(f, ...) \ + CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) #define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) -#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ +#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO##__VA_ARGS__ #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ #define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF #define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR #define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ -#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) \ + INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) #else -// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +// MSVC is adding extra space and needs another indirection to expand +// INTERNAL_CATCH_NOINTERNAL_CATCH_DEF #define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) #define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ -#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) \ + (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) #endif #define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ #define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) -#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) +#define INTERNAL_CATCH_REMOVE_PARENS(...) \ + INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper()) -#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) \ + decltype(get_wrapper()) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) \ + INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) #else -#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper())) -#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) \ + INTERNAL_CATCH_EXPAND_VARGS( \ + decltype(get_wrapper())) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) \ + INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2( \ + INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) #endif -#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ - CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) +#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...) \ + CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST, __VA_ARGS__) #define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) -#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) -#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) -#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) -#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) -#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) -#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _4, _5, _6) -#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) -#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) -#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) -#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) - -#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N - -#define INTERNAL_CATCH_TYPE_GEN\ - template struct TypeList {};\ - template\ - constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ - template class...> struct TemplateTypeList{};\ - template class...Cs>\ - constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\ - template\ - struct append;\ - template\ - struct rewrap;\ - template class, typename...>\ - struct create;\ - template class, typename>\ - struct convert;\ - \ - template \ - struct append { using type = T; };\ - template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ - struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\ - template< template class L1, typename...E1, typename...Rest>\ - struct append, TypeList, Rest...> { using type = L1; };\ - \ - template< template class Container, template class List, typename...elems>\ - struct rewrap, List> { using type = TypeList>; };\ - template< template class Container, template class List, class...Elems, typename...Elements>\ - struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\ - \ - template