From 05803714caffbcd1ce6714d26bdee4c7be19758f Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 2 Jul 2024 17:21:42 +0200 Subject: [PATCH 01/78] Renaming infeasibility analyzer : renaming in class Constraint --- .../constraint.cpp | 44 +++++++++---------- .../infeasible-problem-analysis/constraint.h | 8 ++-- .../infeasible-problem-analysis/report.cpp | 2 +- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint.cpp b/src/solver/infeasible-problem-analysis/constraint.cpp index 0e95848ad9..c9aacb06aa 100644 --- a/src/solver/infeasible-problem-analysis/constraint.cpp +++ b/src/solver/infeasible-problem-analysis/constraint.cpp @@ -33,37 +33,37 @@ const std::string kUnknown = ""; namespace Antares::Optimization { Constraint::Constraint(const std::string& input, const double slackValue): - mInput(input), - mSlackValue(slackValue) + name_(input), + slackValue_(slackValue) { } -std::size_t Constraint::extractItems() +std::size_t Constraint::extractComponentsFromName() { - const auto beg = mInput.begin(); - const auto end = mInput.end(); + const auto beg = name_.begin(); + const auto end = name_.end(); std::size_t newPos = 0; const std::size_t sepSize = 2; - const std::size_t inputSize = mInput.size(); + const std::size_t inputSize = name_.size(); for (std::size_t pos = 0; pos < inputSize; pos = newPos + sepSize) { - newPos = mInput.find("::", pos); + newPos = name_.find("::", pos); if (newPos == std::string::npos) { - mItems.emplace_back(beg + pos, end); + nameComponents_.emplace_back(beg + pos, end); break; } if (newPos > pos) { - mItems.emplace_back(beg + pos, beg + newPos); + nameComponents_.emplace_back(beg + pos, beg + newPos); } } - return mItems.size(); + return nameComponents_.size(); } double Constraint::getSlackValue() const { - return mSlackValue; + return slackValue_; } class StringIsNotWellFormated: public std::runtime_error @@ -117,7 +117,7 @@ std::string Constraint::getAreaName() const { return ""; } - return StringBetweenAngleBrackets(mItems.at(1)); + return StringBetweenAngleBrackets(nameComponents_.at(1)); } std::string Constraint::getTimeStepInYear() const @@ -129,7 +129,7 @@ std::string Constraint::getTimeStepInYear() const case ConstraintType::fictitious_load: case ConstraintType::hydro_reservoir_level: case ConstraintType::short_term_storage_level: - return StringBetweenAngleBrackets(mItems.at(mItems.size() - 2)); + return StringBetweenAngleBrackets(nameComponents_.at(nameComponents_.size() - 2)); default: return kUnknown; } @@ -137,28 +137,28 @@ std::string Constraint::getTimeStepInYear() const ConstraintType Constraint::getType() const { - assert(mItems.size() > 1); - if (mItems.at(1) == "hourly") + assert(nameComponents_.size() > 1); + if (nameComponents_.at(1) == "hourly") { return ConstraintType::binding_constraint_hourly; } - if (mItems.at(1) == "daily") + if (nameComponents_.at(1) == "daily") { return ConstraintType::binding_constraint_daily; } - if (mItems.at(1) == "weekly") + if (nameComponents_.at(1) == "weekly") { return ConstraintType::binding_constraint_weekly; } - if (mItems.at(0) == "FictiveLoads") + if (nameComponents_.at(0) == "FictiveLoads") { return ConstraintType::fictitious_load; } - if (mItems.at(0) == "AreaHydroLevel") + if (nameComponents_.at(0) == "AreaHydroLevel") { return ConstraintType::hydro_reservoir_level; } - if (mItems.at(0) == "Level") + if (nameComponents_.at(0) == "Level") { return ConstraintType::short_term_storage_level; } @@ -172,7 +172,7 @@ std::string Constraint::getBindingConstraintName() const case ConstraintType::binding_constraint_hourly: case ConstraintType::binding_constraint_daily: case ConstraintType::binding_constraint_weekly: - return mItems.at(0); + return nameComponents_.at(0); default: return kUnknown; } @@ -182,7 +182,7 @@ std::string Constraint::getSTSName() const { if (getType() == ConstraintType::short_term_storage_level) { - return StringBetweenAngleBrackets(mItems.at(2)); + return StringBetweenAngleBrackets(nameComponents_.at(2)); } else { diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h index aba82e7f21..c5443f951c 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h @@ -47,14 +47,14 @@ class Constraint double getSlackValue() const; // Extract items, check consistency - std::size_t extractItems(); + std::size_t extractComponentsFromName(); std::string prettyPrint() const; ConstraintType getType() const; private: - std::string mInput; - std::vector mItems; - double mSlackValue; + std::string name_; + std::vector nameComponents_; + double slackValue_; // Get specific items std::string getAreaName() const; diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 28e72109bf..c3c66f5674 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -73,7 +73,7 @@ void InfeasibleProblemReport::extractItems() { for (auto& c: mConstraints) { - if (c.extractItems() == 0) + if (c.extractComponentsFromName() == 0) { return; } From e46bc1fadf7c759e4bc9baa7c54abba6cdad42a1 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 2 Jul 2024 17:32:16 +0200 Subject: [PATCH 02/78] Renaming infeasibility analyzer : renaming in class InfeasibleProblemReport --- .../infeasible-problem-analysis/report.h | 8 ++--- .../infeasible-problem-analysis/report.cpp | 34 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h index 6ebb919fb1..334e09c979 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h @@ -46,11 +46,11 @@ class InfeasibleProblemReport const std::vector& slackVariables); void sortConstraints(); void trimConstraints(); - void extractItems(); + void sortConstraintsByType(); void logSuspiciousConstraints(); - std::vector mConstraints; - std::map mTypes; - const unsigned int nbVariables = 10; + std::vector constraints_; + std::map nbConstraintsByType_; + const unsigned int nbMaxVariables = 10; }; } // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index c3c66f5674..58b1f4b757 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -40,7 +40,7 @@ static bool compareSlackSolutions(const Antares::Optimization::Constraint& a, namespace Antares::Optimization { InfeasibleProblemReport::InfeasibleProblemReport( - const std::vector& slackVariables) + const std::vector& slackVariables) { turnSlackVarsIntoConstraints(slackVariables); sortConstraints(); @@ -48,66 +48,66 @@ InfeasibleProblemReport::InfeasibleProblemReport( } void InfeasibleProblemReport::turnSlackVarsIntoConstraints( - const std::vector& slackVariables) + const std::vector& slackVariables) { for (const MPVariable* slack: slackVariables) { - mConstraints.emplace_back(slack->name(), slack->solution_value()); + constraints_.emplace_back(slack->name(), slack->solution_value()); } } void InfeasibleProblemReport::sortConstraints() { - std::sort(std::begin(mConstraints), std::end(mConstraints), ::compareSlackSolutions); + std::sort(std::begin(constraints_), std::end(constraints_), ::compareSlackSolutions); } void InfeasibleProblemReport::trimConstraints() { - if (nbVariables <= mConstraints.size()) + if (nbMaxVariables <= constraints_.size()) { - mConstraints.resize(nbVariables); + constraints_.resize(nbMaxVariables); } } -void InfeasibleProblemReport::extractItems() +void InfeasibleProblemReport::sortConstraintsByType() { - for (auto& c: mConstraints) + for (auto& c: constraints_) { if (c.extractComponentsFromName() == 0) { return; } - mTypes[c.getType()]++; + nbConstraintsByType_[c.getType()]++; } } void InfeasibleProblemReport::logSuspiciousConstraints() { Antares::logs.error() << "The following constraints are suspicious (first = most suspicious)"; - for (const auto& c: mConstraints) + for (const auto& c: constraints_) { Antares::logs.error() << c.prettyPrint(); } Antares::logs.error() << "Possible causes of infeasibility:"; - if (mTypes[ConstraintType::hydro_reservoir_level] > 0) + if (nbConstraintsByType_[ConstraintType::hydro_reservoir_level] > 0) { Antares::logs.error() << "* Hydro reservoir impossible to manage with cumulative options " "\"hard bounds without heuristic\""; } - if (mTypes[ConstraintType::fictitious_load] > 0) + if (nbConstraintsByType_[ConstraintType::fictitious_load] > 0) { Antares::logs.error() << "* Last resort shedding status,"; } - if (mTypes[ConstraintType::short_term_storage_level] > 0) + if (nbConstraintsByType_[ConstraintType::short_term_storage_level] > 0) { Antares::logs.error() << "* Short-term storage reservoir level impossible to manage. Please check inflows, " "lower & upper curves and initial level (if prescribed),"; } - const unsigned int bcCount = mTypes[ConstraintType::binding_constraint_hourly] - + mTypes[ConstraintType::binding_constraint_daily] - + mTypes[ConstraintType::binding_constraint_weekly]; + const unsigned int bcCount = nbConstraintsByType_[ConstraintType::binding_constraint_hourly] + + nbConstraintsByType_[ConstraintType::binding_constraint_daily] + + nbConstraintsByType_[ConstraintType::binding_constraint_weekly]; if (bcCount > 0) { Antares::logs.error() << "* Binding constraints,"; @@ -118,7 +118,7 @@ void InfeasibleProblemReport::logSuspiciousConstraints() void InfeasibleProblemReport::prettyPrint() { - extractItems(); + sortConstraintsByType(); logSuspiciousConstraints(); } From eec4b4fe0315abd87025f746b892753fbdfb9265 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 2 Jul 2024 17:39:51 +0200 Subject: [PATCH 03/78] Simplifying infeasibility analyzer --- .../constraint.cpp | 25 ++++--------------- .../infeasible-problem-analysis/report.cpp | 6 ++--- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint.cpp b/src/solver/infeasible-problem-analysis/constraint.cpp index c9aacb06aa..0ac031184a 100644 --- a/src/solver/infeasible-problem-analysis/constraint.cpp +++ b/src/solver/infeasible-problem-analysis/constraint.cpp @@ -18,12 +18,14 @@ * You should have received a copy of the Mozilla Public Licence 2.0 * along with Antares_Simulator. If not, see . */ -#include "antares/solver/infeasible-problem-analysis/constraint.h" - #include #include #include #include +#include +#include + +#include "antares/solver/infeasible-problem-analysis/constraint.h" namespace { @@ -40,24 +42,7 @@ Constraint::Constraint(const std::string& input, const double slackValue): std::size_t Constraint::extractComponentsFromName() { - const auto beg = name_.begin(); - const auto end = name_.end(); - std::size_t newPos = 0; - const std::size_t sepSize = 2; - const std::size_t inputSize = name_.size(); - for (std::size_t pos = 0; pos < inputSize; pos = newPos + sepSize) - { - newPos = name_.find("::", pos); - if (newPos == std::string::npos) - { - nameComponents_.emplace_back(beg + pos, end); - break; - } - if (newPos > pos) - { - nameComponents_.emplace_back(beg + pos, beg + newPos); - } - } + boost::algorithm::split_regex(nameComponents_, name_, boost::regex("::")); return nameComponents_.size(); } diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 58b1f4b757..f0a515c4bb 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -63,10 +63,8 @@ void InfeasibleProblemReport::sortConstraints() void InfeasibleProblemReport::trimConstraints() { - if (nbMaxVariables <= constraints_.size()) - { - constraints_.resize(nbMaxVariables); - } + unsigned int nbConstraints = constraints_.size(); + constraints_.resize(std::min(nbMaxVariables, nbConstraints)); } void InfeasibleProblemReport::sortConstraintsByType() From f10c53a822d04cd470dd57108c8476fb59d703e0 Mon Sep 17 00:00:00 2001 From: Florian OMNES <26088210+flomnes@users.noreply.github.com> Date: Wed, 3 Jul 2024 10:46:02 +0200 Subject: [PATCH 04/78] format --- src/solver/infeasible-problem-analysis/constraint.cpp | 7 ++++--- src/solver/infeasible-problem-analysis/report.cpp | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint.cpp b/src/solver/infeasible-problem-analysis/constraint.cpp index 0ac031184a..b43dc7dd95 100644 --- a/src/solver/infeasible-problem-analysis/constraint.cpp +++ b/src/solver/infeasible-problem-analysis/constraint.cpp @@ -18,14 +18,15 @@ * You should have received a copy of the Mozilla Public Licence 2.0 * along with Antares_Simulator. If not, see . */ +#include "antares/solver/infeasible-problem-analysis/constraint.h" + #include #include #include #include -#include -#include -#include "antares/solver/infeasible-problem-analysis/constraint.h" +#include +#include namespace { diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index f0a515c4bb..0964c251ab 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -40,7 +40,7 @@ static bool compareSlackSolutions(const Antares::Optimization::Constraint& a, namespace Antares::Optimization { InfeasibleProblemReport::InfeasibleProblemReport( - const std::vector& slackVariables) + const std::vector& slackVariables) { turnSlackVarsIntoConstraints(slackVariables); sortConstraints(); @@ -48,7 +48,7 @@ InfeasibleProblemReport::InfeasibleProblemReport( } void InfeasibleProblemReport::turnSlackVarsIntoConstraints( - const std::vector& slackVariables) + const std::vector& slackVariables) { for (const MPVariable* slack: slackVariables) { From 644335b760edb9e46678a346fcf854bcfcd3363d Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 2 Jul 2024 17:48:50 +0200 Subject: [PATCH 05/78] New constraint to detect by infeasibility analyzer --- src/solver/infeasible-problem-analysis/constraint.cpp | 6 ++++++ .../infeasible-problem-analysis/constraint-slack-analysis.h | 3 ++- .../antares/solver/infeasible-problem-analysis/constraint.h | 1 + src/solver/infeasible-problem-analysis/report.cpp | 4 ++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/solver/infeasible-problem-analysis/constraint.cpp b/src/solver/infeasible-problem-analysis/constraint.cpp index b43dc7dd95..8d9491695e 100644 --- a/src/solver/infeasible-problem-analysis/constraint.cpp +++ b/src/solver/infeasible-problem-analysis/constraint.cpp @@ -144,6 +144,10 @@ ConstraintType Constraint::getType() const { return ConstraintType::hydro_reservoir_level; } + if (nameComponents_.at(0) == "HydroPower") + { + return ConstraintType::hydro_production_weekly; + } if (nameComponents_.at(0) == "Level") { return ConstraintType::short_term_storage_level; @@ -195,6 +199,8 @@ std::string Constraint::prettyPrint() const case ConstraintType::hydro_reservoir_level: return "Hydro reservoir constraint at area '" + getAreaName() + "' at hour " + getTimeStepInYear(); + case ConstraintType::hydro_production_weekly: + return "Hydro weekly production at area '" + getAreaName() + "'"; case ConstraintType::short_term_storage_level: return "Short-term-storage reservoir constraint at area '" + getAreaName() + "' in STS '" + getSTSName() + "' at hour " + getTimeStepInYear(); diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h index a298b6b026..bb56228b2f 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h @@ -57,7 +57,8 @@ class ConstraintSlackAnalysis: public UnfeasibilityAnalysis std::vector slackVariables_; const std::string constraint_name_pattern = "^AreaHydroLevel::|::hourly::|::daily::|::weekly::|" - "^FictiveLoads::|^Level::"; + "^FictiveLoads::|^Level::|" + "^HydroPower::"; }; } // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h index c5443f951c..92bab3c87b 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h @@ -32,6 +32,7 @@ enum class ConstraintType binding_constraint_weekly, fictitious_load, hydro_reservoir_level, + hydro_production_weekly, short_term_storage_level, none }; diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 0964c251ab..2022bfbfd6 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -92,6 +92,10 @@ void InfeasibleProblemReport::logSuspiciousConstraints() Antares::logs.error() << "* Hydro reservoir impossible to manage with cumulative options " "\"hard bounds without heuristic\""; } + if (nbConstraintsByType_[ConstraintType::hydro_production_weekly] > 0) + { + Antares::logs.error() << "* impossible to generate exactly the weekly hydro target"; + } if (nbConstraintsByType_[ConstraintType::fictitious_load] > 0) { Antares::logs.error() << "* Last resort shedding status,"; From b94dfc0df98836eed17d535c21ef5abb69159956 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 3 Jul 2024 11:02:09 +0200 Subject: [PATCH 06/78] Infeasibility - to more changeability : simplification + renaming --- .../constraint.cpp | 46 ++++++++----------- .../infeasible-problem-analysis/constraint.h | 10 ++-- .../infeasible-problem-analysis/report.cpp | 2 - 3 files changed, 24 insertions(+), 34 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint.cpp b/src/solver/infeasible-problem-analysis/constraint.cpp index 8d9491695e..2dad52f4ac 100644 --- a/src/solver/infeasible-problem-analysis/constraint.cpp +++ b/src/solver/infeasible-problem-analysis/constraint.cpp @@ -35,8 +35,8 @@ const std::string kUnknown = ""; namespace Antares::Optimization { -Constraint::Constraint(const std::string& input, const double slackValue): - name_(input), +Constraint::Constraint(const std::string& name, const double slackValue): + name_(name), slackValue_(slackValue) { } @@ -95,7 +95,7 @@ std::string StringBetweenAngleBrackets(const std::string& str) return std::string(left + 1, right); } -std::string Constraint::getAreaName() const +std::string Constraint::areaName() const { if ((getType() == ConstraintType::binding_constraint_hourly) || (getType() == ConstraintType::binding_constraint_daily) @@ -106,7 +106,7 @@ std::string Constraint::getAreaName() const return StringBetweenAngleBrackets(nameComponents_.at(1)); } -std::string Constraint::getTimeStepInYear() const +std::string Constraint::timeStep() const { switch (getType()) { @@ -155,20 +155,12 @@ ConstraintType Constraint::getType() const return ConstraintType::none; } -std::string Constraint::getBindingConstraintName() const +std::string Constraint::shortName() const { - switch (getType()) - { - case ConstraintType::binding_constraint_hourly: - case ConstraintType::binding_constraint_daily: - case ConstraintType::binding_constraint_weekly: - return nameComponents_.at(0); - default: - return kUnknown; - } + return nameComponents_.at(0); } -std::string Constraint::getSTSName() const +std::string Constraint::STSName() const { if (getType() == ConstraintType::short_term_storage_level) { @@ -185,25 +177,25 @@ std::string Constraint::prettyPrint() const switch (getType()) { case ConstraintType::binding_constraint_hourly: - return "Hourly binding constraint '" + getBindingConstraintName() + "' at hour " - + getTimeStepInYear(); + return "Hourly binding constraint '" + shortName() + "' at hour " + + timeStep(); case ConstraintType::binding_constraint_daily: - return "Daily binding constraint '" + getBindingConstraintName() + "' at day " - + getTimeStepInYear(); + return "Daily binding constraint '" + shortName() + "' at day " + + timeStep(); case ConstraintType::binding_constraint_weekly: - return "Weekly binding constraint '" + getBindingConstraintName(); + return "Weekly binding constraint '" + shortName(); case ConstraintType::fictitious_load: - return "Last resort shedding status at area '" + getAreaName() + "' at hour " - + getTimeStepInYear(); + return "Last resort shedding status at area '" + areaName() + "' at hour " + + timeStep(); case ConstraintType::hydro_reservoir_level: - return "Hydro reservoir constraint at area '" + getAreaName() + "' at hour " - + getTimeStepInYear(); + return "Hydro reservoir constraint at area '" + areaName() + "' at hour " + + timeStep(); case ConstraintType::hydro_production_weekly: - return "Hydro weekly production at area '" + getAreaName() + "'"; + return "Hydro weekly production at area '" + areaName() + "'"; case ConstraintType::short_term_storage_level: - return "Short-term-storage reservoir constraint at area '" + getAreaName() + "' in STS '" - + getSTSName() + "' at hour " + getTimeStepInYear(); + return "Short-term-storage reservoir constraint at area '" + areaName() + "' in STS '" + + STSName() + "' at hour " + timeStep(); default: return kUnknown; diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h index 92bab3c87b..604385ad11 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h @@ -42,7 +42,7 @@ class Constraint public: // Construct object Constraint() = default; - Constraint(const std::string& input, const double slackValue); + Constraint(const std::string& name, const double slackValue); // Raw members double getSlackValue() const; @@ -58,9 +58,9 @@ class Constraint double slackValue_; // Get specific items - std::string getAreaName() const; - std::string getSTSName() const; - std::string getTimeStepInYear() const; - std::string getBindingConstraintName() const; + std::string areaName() const; + std::string STSName() const; + std::string timeStep() const; + std::string shortName() const; }; } // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 2022bfbfd6..c0e1e05dbe 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -114,8 +114,6 @@ void InfeasibleProblemReport::logSuspiciousConstraints() { Antares::logs.error() << "* Binding constraints,"; } - - Antares::logs.error() << "* Negative hurdle costs on lines with infinite capacity (rare)."; } void InfeasibleProblemReport::prettyPrint() From f408ecd214e53d613cbb3a4352327275d7fda665 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 3 Jul 2024 12:51:48 +0200 Subject: [PATCH 07/78] Infeasibility - to more changeability : simplifying function StringBetweenAngleBrackets --- .../constraint.cpp | 38 ++++++------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint.cpp b/src/solver/infeasible-problem-analysis/constraint.cpp index 2dad52f4ac..b48b10f84a 100644 --- a/src/solver/infeasible-problem-analysis/constraint.cpp +++ b/src/solver/infeasible-problem-analysis/constraint.cpp @@ -27,6 +27,7 @@ #include #include +#include namespace { @@ -61,38 +62,23 @@ class StringIsNotWellFormated: public std::runtime_error } }; -std::string StringBetweenAngleBrackets(const std::string& str) +std::string StringBetweenAngleBrackets(const std::string& constraintName) { - const auto& begin = str.begin(); - const auto& end = str.end(); + std::vector split_name; + boost::split(split_name, constraintName, boost::is_any_of("<>")); - auto left = std::find(begin, end, '<'); - - if (left == end) + std::string err_msg = "Error: "; + if (split_name.size() < 3) { - std::ostringstream stream; - stream << std::string("Error the string: ") << std::quoted(str) - << " does not contains the left angle bracket " << std::quoted("<"); - throw StringIsNotWellFormated(stream.str()); + err_msg += "constraint name '" + constraintName + "' misses '<' and/or '>' bracket"; + throw StringIsNotWellFormated(err_msg); } - - auto right = std::find(begin, end, '>'); - if (right == end) - { - std::ostringstream stream; - stream << std::string("Error the string: ") << std::quoted(str) - << " does not contains the right angle bracket " << std::quoted(">"); - throw StringIsNotWellFormated(stream.str()); - } - - if (std::distance(left, right) <= 1) + if (split_name[1].empty()) { - std::ostringstream stream; - stream << std::string("Error the string: ") << std::quoted(str) << " must be of format " - << std::quoted("**"); - throw StringIsNotWellFormated(stream.str()); + err_msg += "constraint name '" + constraintName + "' must be of format '**'"; + throw StringIsNotWellFormated(err_msg); } - return std::string(left + 1, right); + return split_name[1]; } std::string Constraint::areaName() const From bb55301af00efb5f817b92a07e0b4353a57d9d5c Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 3 Jul 2024 12:57:21 +0200 Subject: [PATCH 08/78] Infeasibility - to more changeability : simplifying functions areaName() and timeStep() --- .../infeasible-problem-analysis/constraint.cpp | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint.cpp b/src/solver/infeasible-problem-analysis/constraint.cpp index b48b10f84a..830bf04ace 100644 --- a/src/solver/infeasible-problem-analysis/constraint.cpp +++ b/src/solver/infeasible-problem-analysis/constraint.cpp @@ -83,28 +83,12 @@ std::string StringBetweenAngleBrackets(const std::string& constraintName) std::string Constraint::areaName() const { - if ((getType() == ConstraintType::binding_constraint_hourly) - || (getType() == ConstraintType::binding_constraint_daily) - || (getType() == ConstraintType::binding_constraint_weekly)) - { - return ""; - } return StringBetweenAngleBrackets(nameComponents_.at(1)); } std::string Constraint::timeStep() const { - switch (getType()) - { - case ConstraintType::binding_constraint_hourly: - case ConstraintType::binding_constraint_daily: - case ConstraintType::fictitious_load: - case ConstraintType::hydro_reservoir_level: - case ConstraintType::short_term_storage_level: - return StringBetweenAngleBrackets(nameComponents_.at(nameComponents_.size() - 2)); - default: - return kUnknown; - } + return StringBetweenAngleBrackets(nameComponents_.at(nameComponents_.size() - 2)); } ConstraintType Constraint::getType() const From 1d58402ed09fe35592d38067994eb87e205f6d82 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 3 Jul 2024 12:59:40 +0200 Subject: [PATCH 09/78] Infeasibility - to more changeability : renaming Constraint::getType() into type() --- src/solver/infeasible-problem-analysis/constraint.cpp | 4 ++-- .../antares/solver/infeasible-problem-analysis/constraint.h | 2 +- src/solver/infeasible-problem-analysis/report.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint.cpp b/src/solver/infeasible-problem-analysis/constraint.cpp index 830bf04ace..8f3d674baa 100644 --- a/src/solver/infeasible-problem-analysis/constraint.cpp +++ b/src/solver/infeasible-problem-analysis/constraint.cpp @@ -91,7 +91,7 @@ std::string Constraint::timeStep() const return StringBetweenAngleBrackets(nameComponents_.at(nameComponents_.size() - 2)); } -ConstraintType Constraint::getType() const +ConstraintType Constraint::type() const { assert(nameComponents_.size() > 1); if (nameComponents_.at(1) == "hourly") @@ -132,7 +132,7 @@ std::string Constraint::shortName() const std::string Constraint::STSName() const { - if (getType() == ConstraintType::short_term_storage_level) + if (type() == ConstraintType::short_term_storage_level) { return StringBetweenAngleBrackets(nameComponents_.at(2)); } diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h index 604385ad11..4a1e9062b1 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h @@ -50,7 +50,7 @@ class Constraint // Extract items, check consistency std::size_t extractComponentsFromName(); std::string prettyPrint() const; - ConstraintType getType() const; + ConstraintType type() const; private: std::string name_; diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index c0e1e05dbe..04d0a5eeae 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -75,7 +75,7 @@ void InfeasibleProblemReport::sortConstraintsByType() { return; } - nbConstraintsByType_[c.getType()]++; + nbConstraintsByType_[c.type()]++; } } From 666201d147a321aa03a2e659ae6caa08619dd1d9 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 3 Jul 2024 13:04:31 +0200 Subject: [PATCH 10/78] Infeasibility - to more changeability : function STSName() ==> simplified and renamed into STSname() --- .../infeasible-problem-analysis/constraint.cpp | 17 ++++------------- .../infeasible-problem-analysis/constraint.h | 2 +- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint.cpp b/src/solver/infeasible-problem-analysis/constraint.cpp index 8f3d674baa..8e96464922 100644 --- a/src/solver/infeasible-problem-analysis/constraint.cpp +++ b/src/solver/infeasible-problem-analysis/constraint.cpp @@ -130,21 +130,14 @@ std::string Constraint::shortName() const return nameComponents_.at(0); } -std::string Constraint::STSName() const +std::string Constraint::STSname() const { - if (type() == ConstraintType::short_term_storage_level) - { - return StringBetweenAngleBrackets(nameComponents_.at(2)); - } - else - { - return kUnknown; - } + return StringBetweenAngleBrackets(nameComponents_.at(2)); } std::string Constraint::prettyPrint() const { - switch (getType()) + switch (type()) { case ConstraintType::binding_constraint_hourly: return "Hourly binding constraint '" + shortName() + "' at hour " @@ -154,7 +147,6 @@ std::string Constraint::prettyPrint() const + timeStep(); case ConstraintType::binding_constraint_weekly: return "Weekly binding constraint '" + shortName(); - case ConstraintType::fictitious_load: return "Last resort shedding status at area '" + areaName() + "' at hour " + timeStep(); @@ -165,8 +157,7 @@ std::string Constraint::prettyPrint() const return "Hydro weekly production at area '" + areaName() + "'"; case ConstraintType::short_term_storage_level: return "Short-term-storage reservoir constraint at area '" + areaName() + "' in STS '" - + STSName() + "' at hour " + timeStep(); - + + STSname() + "' at hour " + timeStep(); default: return kUnknown; } diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h index 4a1e9062b1..59886055b3 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h @@ -59,7 +59,7 @@ class Constraint // Get specific items std::string areaName() const; - std::string STSName() const; + std::string STSname() const; std::string timeStep() const; std::string shortName() const; }; From 499619b40bc1f6379ccee632ba1c8c4e145cdd1f Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 3 Jul 2024 13:34:17 +0200 Subject: [PATCH 11/78] Infeasibility - to more changeability : remove unnecessary comments --- .../antares/solver/infeasible-problem-analysis/constraint.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h index 59886055b3..606e66af54 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h @@ -40,14 +40,11 @@ enum class ConstraintType class Constraint { public: - // Construct object Constraint() = default; Constraint(const std::string& name, const double slackValue); - // Raw members double getSlackValue() const; - // Extract items, check consistency std::size_t extractComponentsFromName(); std::string prettyPrint() const; ConstraintType type() const; @@ -57,7 +54,6 @@ class Constraint std::vector nameComponents_; double slackValue_; - // Get specific items std::string areaName() const; std::string STSname() const; std::string timeStep() const; From 25d34246465e368d96c6bbbcce15c79bba9efddb Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 3 Jul 2024 13:45:03 +0200 Subject: [PATCH 12/78] Infeasibility - to more changeability : simplifying function sortConstraintsByType() Check on the current constraint's name number of components is useless : it cannot be null. --- src/solver/infeasible-problem-analysis/constraint.cpp | 3 +-- .../antares/solver/infeasible-problem-analysis/constraint.h | 2 +- src/solver/infeasible-problem-analysis/report.cpp | 5 +---- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint.cpp b/src/solver/infeasible-problem-analysis/constraint.cpp index 8e96464922..71c67b31ac 100644 --- a/src/solver/infeasible-problem-analysis/constraint.cpp +++ b/src/solver/infeasible-problem-analysis/constraint.cpp @@ -42,10 +42,9 @@ Constraint::Constraint(const std::string& name, const double slackValue): { } -std::size_t Constraint::extractComponentsFromName() +void Constraint::extractComponentsFromName() { boost::algorithm::split_regex(nameComponents_, name_, boost::regex("::")); - return nameComponents_.size(); } double Constraint::getSlackValue() const diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h index 606e66af54..52fb799692 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h @@ -45,7 +45,7 @@ class Constraint double getSlackValue() const; - std::size_t extractComponentsFromName(); + void extractComponentsFromName(); std::string prettyPrint() const; ConstraintType type() const; diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 04d0a5eeae..7683e825fd 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -71,10 +71,7 @@ void InfeasibleProblemReport::sortConstraintsByType() { for (auto& c: constraints_) { - if (c.extractComponentsFromName() == 0) - { - return; - } + c.extractComponentsFromName(); nbConstraintsByType_[c.type()]++; } } From 3c040c0a6620ab77f6f4189064caff7dab1067b2 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 3 Jul 2024 16:00:13 +0200 Subject: [PATCH 13/78] Infeasibility - to more changeability : in unit tests, change misleading BC names --- .../test-unfeasible-problem-analyzer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index 321bd4b3e7..8d960f7381 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -171,9 +171,9 @@ std::unique_ptr createUnfeasibleProblem(const std::string& constraintN } static const std::string validConstraintNames[] = { - "BC::hourly::hour<36>", - "BC::daily::day<67>", - "BC::weekly::week<12>", + "BC-name-1::hourly::hour<36>", + "BC-name-2::daily::day<67>", + "BC-name-3::weekly::week<12>", "FictiveLoads::hour<25>", "AreaHydroLevel::hour<8>", }; From b3fc6f0fff42781219ede55cb38ec50b96193c3e Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 3 Jul 2024 16:04:46 +0200 Subject: [PATCH 14/78] Infeasibility - to more changeability : split constraints logs into 2 parts (suspicious constraints and infeasibility causes) --- .../antares/solver/infeasible-problem-analysis/report.h | 1 + src/solver/infeasible-problem-analysis/report.cpp | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h index 334e09c979..ea62adb347 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h @@ -48,6 +48,7 @@ class InfeasibleProblemReport void trimConstraints(); void sortConstraintsByType(); void logSuspiciousConstraints(); + void logInfeasibilityCauses(); std::vector constraints_; std::map nbConstraintsByType_; diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 7683e825fd..33c0b68491 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -83,6 +83,10 @@ void InfeasibleProblemReport::logSuspiciousConstraints() { Antares::logs.error() << c.prettyPrint(); } +} + +void InfeasibleProblemReport::logInfeasibilityCauses() +{ Antares::logs.error() << "Possible causes of infeasibility:"; if (nbConstraintsByType_[ConstraintType::hydro_reservoir_level] > 0) { @@ -100,8 +104,8 @@ void InfeasibleProblemReport::logSuspiciousConstraints() if (nbConstraintsByType_[ConstraintType::short_term_storage_level] > 0) { Antares::logs.error() - << "* Short-term storage reservoir level impossible to manage. Please check inflows, " - "lower & upper curves and initial level (if prescribed),"; + << "* Short-term storage reservoir level impossible to manage. Please check inflows, " + "lower & upper curves and initial level (if prescribed),"; } const unsigned int bcCount = nbConstraintsByType_[ConstraintType::binding_constraint_hourly] @@ -117,6 +121,7 @@ void InfeasibleProblemReport::prettyPrint() { sortConstraintsByType(); logSuspiciousConstraints(); + logInfeasibilityCauses(); } } // namespace Antares::Optimization From bbdc23015742ff9cd72231f9916a8969ff4d9aef Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 3 Jul 2024 16:31:47 +0200 Subject: [PATCH 15/78] Infeasibility - to more changeability : move call to sortConstraintsByType with his friends --- .../antares/solver/infeasible-problem-analysis/report.h | 2 +- src/solver/infeasible-problem-analysis/report.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h index ea62adb347..898f4df359 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h @@ -44,7 +44,7 @@ class InfeasibleProblemReport private: void turnSlackVarsIntoConstraints( const std::vector& slackVariables); - void sortConstraints(); + void sortConstraintsBySlackValue(); void trimConstraints(); void sortConstraintsByType(); void logSuspiciousConstraints(); diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 33c0b68491..b038aa8823 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -43,8 +43,9 @@ InfeasibleProblemReport::InfeasibleProblemReport( const std::vector& slackVariables) { turnSlackVarsIntoConstraints(slackVariables); - sortConstraints(); + sortConstraintsBySlackValue(); trimConstraints(); + sortConstraintsByType(); } void InfeasibleProblemReport::turnSlackVarsIntoConstraints( @@ -56,7 +57,7 @@ void InfeasibleProblemReport::turnSlackVarsIntoConstraints( } } -void InfeasibleProblemReport::sortConstraints() +void InfeasibleProblemReport::sortConstraintsBySlackValue() { std::sort(std::begin(constraints_), std::end(constraints_), ::compareSlackSolutions); } @@ -119,7 +120,6 @@ void InfeasibleProblemReport::logInfeasibilityCauses() void InfeasibleProblemReport::prettyPrint() { - sortConstraintsByType(); logSuspiciousConstraints(); logInfeasibilityCauses(); } From 331c1f5a5be3f1ba66c732b3e9c3cf0f946c94df Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Thu, 4 Jul 2024 08:16:54 +0200 Subject: [PATCH 16/78] Infeasibility - to more changeability : run clang-format --- .../infeasible-problem-analysis/constraint.cpp | 14 +++++--------- src/solver/infeasible-problem-analysis/report.cpp | 4 ++-- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint.cpp b/src/solver/infeasible-problem-analysis/constraint.cpp index 71c67b31ac..2c4fd6d085 100644 --- a/src/solver/infeasible-problem-analysis/constraint.cpp +++ b/src/solver/infeasible-problem-analysis/constraint.cpp @@ -25,9 +25,9 @@ #include #include +#include #include #include -#include namespace { @@ -139,19 +139,15 @@ std::string Constraint::prettyPrint() const switch (type()) { case ConstraintType::binding_constraint_hourly: - return "Hourly binding constraint '" + shortName() + "' at hour " - + timeStep(); + return "Hourly binding constraint '" + shortName() + "' at hour " + timeStep(); case ConstraintType::binding_constraint_daily: - return "Daily binding constraint '" + shortName() + "' at day " - + timeStep(); + return "Daily binding constraint '" + shortName() + "' at day " + timeStep(); case ConstraintType::binding_constraint_weekly: return "Weekly binding constraint '" + shortName(); case ConstraintType::fictitious_load: - return "Last resort shedding status at area '" + areaName() + "' at hour " - + timeStep(); + return "Last resort shedding status at area '" + areaName() + "' at hour " + timeStep(); case ConstraintType::hydro_reservoir_level: - return "Hydro reservoir constraint at area '" + areaName() + "' at hour " - + timeStep(); + return "Hydro reservoir constraint at area '" + areaName() + "' at hour " + timeStep(); case ConstraintType::hydro_production_weekly: return "Hydro weekly production at area '" + areaName() + "'"; case ConstraintType::short_term_storage_level: diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index b038aa8823..5154cffa0e 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -105,8 +105,8 @@ void InfeasibleProblemReport::logInfeasibilityCauses() if (nbConstraintsByType_[ConstraintType::short_term_storage_level] > 0) { Antares::logs.error() - << "* Short-term storage reservoir level impossible to manage. Please check inflows, " - "lower & upper curves and initial level (if prescribed),"; + << "* Short-term storage reservoir level impossible to manage. Please check inflows, " + "lower & upper curves and initial level (if prescribed),"; } const unsigned int bcCount = nbConstraintsByType_[ConstraintType::binding_constraint_hourly] From fe1c95218942f0135a363b1f95186d23cfd4bf77 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Thu, 4 Jul 2024 11:32:18 +0200 Subject: [PATCH 17/78] Make infeasibily more changeable : move sorting and trimming slack vars from report to analysis --- .../constraint-slack-analysis.cpp | 21 ++++++++++++++++++- .../constraint.cpp | 10 ++------- .../constraint-slack-analysis.h | 4 ++++ .../infeasible-problem-analysis/constraint.h | 5 +---- .../infeasible-problem-analysis/report.h | 2 -- .../infeasible-problem-analysis/report.cpp | 21 +------------------ 6 files changed, 28 insertions(+), 35 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index 785d4670f8..bddfbfceb3 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -31,9 +31,14 @@ using namespace operations_research; -namespace Antares::Optimization +static bool compareSlackSolutions(const MPVariable* a, + const MPVariable* b) { + return a->solution_value() > b->solution_value(); +} +namespace Antares::Optimization +{ void ConstraintSlackAnalysis::run(MPSolver* problem) { addSlackVariables(problem); @@ -53,6 +58,9 @@ void ConstraintSlackAnalysis::run(MPSolver* problem) } hasDetectedInfeasibilityCause_ = true; + + sortSlackVariablesByValue(); + trimSlackVariables(); } void ConstraintSlackAnalysis::addSlackVariables(MPSolver* problem) @@ -104,6 +112,17 @@ void ConstraintSlackAnalysis::buildObjective(MPSolver* problem) const objective->SetMinimization(); } +void ConstraintSlackAnalysis::sortSlackVariablesByValue() +{ + std::sort(std::begin(slackVariables_), std::end(slackVariables_), ::compareSlackSolutions); +} + +void ConstraintSlackAnalysis::trimSlackVariables() +{ + unsigned int nbSlackVars = slackVariables_.size(); + slackVariables_.resize(std::min(nbMaxSlackVarsToKeep, nbSlackVars)); +} + void ConstraintSlackAnalysis::printReport() const { InfeasibleProblemReport report(slackVariables_); diff --git a/src/solver/infeasible-problem-analysis/constraint.cpp b/src/solver/infeasible-problem-analysis/constraint.cpp index 2c4fd6d085..4f111914aa 100644 --- a/src/solver/infeasible-problem-analysis/constraint.cpp +++ b/src/solver/infeasible-problem-analysis/constraint.cpp @@ -36,9 +36,8 @@ const std::string kUnknown = ""; namespace Antares::Optimization { -Constraint::Constraint(const std::string& name, const double slackValue): - name_(name), - slackValue_(slackValue) +Constraint::Constraint(const std::string& name): + name_(name) { } @@ -47,11 +46,6 @@ void Constraint::extractComponentsFromName() boost::algorithm::split_regex(nameComponents_, name_, boost::regex("::")); } -double Constraint::getSlackValue() const -{ - return slackValue_; -} - class StringIsNotWellFormated: public std::runtime_error { public: diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h index bb56228b2f..edc84805c9 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h @@ -54,8 +54,12 @@ class ConstraintSlackAnalysis: public UnfeasibilityAnalysis private: void buildObjective(operations_research::MPSolver* problem) const; void addSlackVariables(operations_research::MPSolver* problem); + void sortSlackVariablesByValue(); + void trimSlackVariables(); std::vector slackVariables_; + const unsigned int nbMaxSlackVarsToKeep = 10; + const std::string constraint_name_pattern = "^AreaHydroLevel::|::hourly::|::daily::|::weekly::|" "^FictiveLoads::|^Level::|" "^HydroPower::"; diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h index 52fb799692..d2f4f2a692 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h @@ -41,9 +41,7 @@ class Constraint { public: Constraint() = default; - Constraint(const std::string& name, const double slackValue); - - double getSlackValue() const; + Constraint(const std::string& name); void extractComponentsFromName(); std::string prettyPrint() const; @@ -52,7 +50,6 @@ class Constraint private: std::string name_; std::vector nameComponents_; - double slackValue_; std::string areaName() const; std::string STSname() const; diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h index 898f4df359..f28683d7a6 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h @@ -44,8 +44,6 @@ class InfeasibleProblemReport private: void turnSlackVarsIntoConstraints( const std::vector& slackVariables); - void sortConstraintsBySlackValue(); - void trimConstraints(); void sortConstraintsByType(); void logSuspiciousConstraints(); void logInfeasibilityCauses(); diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 5154cffa0e..8260038eed 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -31,20 +31,12 @@ using namespace operations_research; -static bool compareSlackSolutions(const Antares::Optimization::Constraint& a, - const Antares::Optimization::Constraint& b) -{ - return a.getSlackValue() > b.getSlackValue(); -} - namespace Antares::Optimization { InfeasibleProblemReport::InfeasibleProblemReport( const std::vector& slackVariables) { turnSlackVarsIntoConstraints(slackVariables); - sortConstraintsBySlackValue(); - trimConstraints(); sortConstraintsByType(); } @@ -53,21 +45,10 @@ void InfeasibleProblemReport::turnSlackVarsIntoConstraints( { for (const MPVariable* slack: slackVariables) { - constraints_.emplace_back(slack->name(), slack->solution_value()); + constraints_.emplace_back(slack->name()); } } -void InfeasibleProblemReport::sortConstraintsBySlackValue() -{ - std::sort(std::begin(constraints_), std::end(constraints_), ::compareSlackSolutions); -} - -void InfeasibleProblemReport::trimConstraints() -{ - unsigned int nbConstraints = constraints_.size(); - constraints_.resize(std::min(nbMaxVariables, nbConstraints)); -} - void InfeasibleProblemReport::sortConstraintsByType() { for (auto& c: constraints_) From 82ef63c1f13ea53b9fae628b20df320d1512b16b Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Fri, 5 Jul 2024 10:48:49 +0200 Subject: [PATCH 18/78] Make infeasibily more changeable : introducing constraints list to be detected by slack analysis --- .../CMakeLists.txt | 2 + .../constraint-slack-analysis.cpp | 21 +- .../detected-infeasible-constraints.cpp | 201 ++++++++++++++++++ .../detected-infeasible-constraints.h | 79 +++++++ .../constraint-slack-analysis.h | 9 +- .../infeasible-problem-analysis/report.h | 5 +- .../infeasible-problem-analysis/report.cpp | 3 +- 7 files changed, 311 insertions(+), 9 deletions(-) create mode 100644 src/solver/infeasible-problem-analysis/detected-infeasible-constraints.cpp create mode 100644 src/solver/infeasible-problem-analysis/detected-infeasible-constraints.h diff --git a/src/solver/infeasible-problem-analysis/CMakeLists.txt b/src/solver/infeasible-problem-analysis/CMakeLists.txt index 720842fd6a..67d2462fec 100644 --- a/src/solver/infeasible-problem-analysis/CMakeLists.txt +++ b/src/solver/infeasible-problem-analysis/CMakeLists.txt @@ -12,6 +12,8 @@ set(SRC_INFEASIBLE_PROBLEM_ANALYSIS report.cpp include/antares/solver/infeasible-problem-analysis/constraint.h constraint.cpp + detected-infeasible-constraints.h + detected-infeasible-constraints.cpp ) add_library(infeasible_problem_analysis ${SRC_INFEASIBLE_PROBLEM_ANALYSIS}) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index bddfbfceb3..aa1d75b6c0 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -21,6 +21,7 @@ #include "antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h" #include +#include #include #include "antares/solver/infeasible-problem-analysis/report.h" @@ -39,6 +40,22 @@ static bool compareSlackSolutions(const MPVariable* a, namespace Antares::Optimization { +ConstraintSlackAnalysis::ConstraintSlackAnalysis() +{ + detectedConstraints_.push_back(std::make_shared()); + detectedConstraints_.push_back(std::make_shared()); + detectedConstraints_.push_back(std::make_shared()); + detectedConstraints_.push_back(std::make_shared()); + detectedConstraints_.push_back(std::make_shared()); + detectedConstraints_.push_back(std::make_shared()); + detectedConstraints_.push_back(std::make_shared()); + + std::vector patterns; + std::for_each(detectedConstraints_.begin(), detectedConstraints_.end(), + [&](auto& c) { patterns.push_back(c->regexId()); }); + constraint_name_pattern_ = boost::algorithm::join(patterns, "|"); +} + void ConstraintSlackAnalysis::run(MPSolver* problem) { addSlackVariables(problem); @@ -72,7 +89,7 @@ void ConstraintSlackAnalysis::addSlackVariables(MPSolver* problem) */ const unsigned int selectedConstraintsInverseRatio = 3; slackVariables_.reserve(problem->NumConstraints() / selectedConstraintsInverseRatio); - std::regex rgx(constraint_name_pattern); + std::regex rgx(constraint_name_pattern_); const double infinity = MPSolver::infinity(); for (MPConstraint* constraint: problem->constraints()) { @@ -125,7 +142,7 @@ void ConstraintSlackAnalysis::trimSlackVariables() void ConstraintSlackAnalysis::printReport() const { - InfeasibleProblemReport report(slackVariables_); + InfeasibleProblemReport report(slackVariables_, detectedConstraints_); report.prettyPrint(); } diff --git a/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.cpp b/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.cpp new file mode 100644 index 0000000000..f76e077015 --- /dev/null +++ b/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.cpp @@ -0,0 +1,201 @@ + +#include "detected-infeasible-constraints.h" + +#include +#include +#include + +class StringIsNotWellFormated: public std::runtime_error +{ +public: + StringIsNotWellFormated(const std::string& error_message): + std::runtime_error(error_message) + { + } +}; + +std::string StringBetweenAngleBrackets(const std::string& constraintName) +{ + std::vector split_name; + boost::split(split_name, constraintName, boost::is_any_of("<>")); + + std::string err_msg = "Error: "; + if (split_name.size() < 3) + { + err_msg += "constraint name '" + constraintName + "' misses '<' and/or '>' bracket"; + throw StringIsNotWellFormated(err_msg); + } + if (split_name[1].empty()) + { + err_msg += "constraint name '" + constraintName + "' must be of format '**'"; + throw StringIsNotWellFormated(err_msg); + } + return split_name[1]; +} + +std::string timeStep(std::vector splitName) +{ + return StringBetweenAngleBrackets(splitName.at(splitName.size() - 2)); +} + +std::string shortName(std::vector splitName) +{ + return splitName.at(0); +} + +std::string areaName(std::vector splitName) +{ + return StringBetweenAngleBrackets(splitName.at(1)); +} + +std::string STSname(std::vector splitName) +{ + return StringBetweenAngleBrackets(splitName.at(2)); +} + +namespace Antares::Optimization +{ + +// ======================================= +// Generic constraint logger +// ======================================= +void DetectedConstraint::setConstraintName(std::string name) +{ + name_ = name; + boost::algorithm::split_regex(splitName_, name_, boost::regex("::")); +} + +std::string DetectedConstraint::regexId() +{ + return regexId_; +} + +// ======================================= +// Hourly BC logger +// ======================================= +HourlyBC::HourlyBC() +{ + regexId_ = "::hourly::"; +} + +std::string HourlyBC::infeasisibity() +{ + return "Hourly BC '" + shortName(splitName_) + "' at hour " + timeStep(splitName_); +} + +std::string HourlyBC::infeasisibityCause() +{ + return "* Hourly binding constraints."; +} + +// ======================================= +// Daily BC logger +// ======================================= +DailyBC::DailyBC() +{ + regexId_ = "::daily::"; +} + +std::string DailyBC::infeasisibity() +{ + return "Daily BC '" + shortName(splitName_) + "' at day " + timeStep(splitName_); +} + +std::string DailyBC::infeasisibityCause() +{ + return "* Daily binding constraints,"; +} + +// ======================================= +// Weekly BC constraint +// ======================================= +WeeklyBC::WeeklyBC() +{ + regexId_ = "::weekly::"; +} + +std::string WeeklyBC::infeasisibity() +{ + return "Weekly BC '" + shortName(splitName_); +} + +std::string WeeklyBC::infeasisibityCause() +{ + return "* Weekly binding constraints."; +} + +// ======================================= +// Fictitious load constraint +// ======================================= +FictitiousLoad::FictitiousLoad() +{ + regexId_ = "^FictiveLoads::"; +} + +std::string FictitiousLoad::infeasisibity() +{ + return "Last resort shedding status at area '" + areaName(splitName_) + "' at hour " + timeStep(splitName_); +} + +std::string FictitiousLoad::infeasisibityCause() +{ + return "* Last resort shedding status."; +} + +// ======================================= +// Hydro level constraint +// ======================================= +HydroLevel::HydroLevel() +{ + regexId_ = "^AreaHydroLevel::"; +} + +std::string HydroLevel::infeasisibity() +{ + return "Hydro level constraint at area '" + areaName(splitName_) + "' at hour " + timeStep(splitName_); +} + +std::string HydroLevel::infeasisibityCause() +{ + return "* Hydro reservoir impossible to manage with cumulative options " + "\"hard bounds without heuristic\""; +} + +// ======================================= +// Short term storage constraint +// ======================================= +STS::STS() +{ + regexId_ = "^Level::"; +} + +std::string STS::infeasisibity() +{ + return "Short-term-storage reservoir constraint at area '" + areaName(splitName_) + "' in STS '" + + STSname(splitName_) + "' at hour " + timeStep(splitName_); +} + +std::string STS::infeasisibityCause() +{ + return "* Short-term storage reservoir level impossible to manage. Please check inflows, " + "lower & upper curves and initial level (if prescribed),"; +} + +// ======================================= +// Hydro production constraint +// ======================================= +HydroProduction::HydroProduction() +{ + regexId_ = "^HydroPower::"; +} + +std::string HydroProduction::infeasisibity() +{ + return "Hydro weekly production at area '" + areaName(splitName_) + "'"; +} + +std::string HydroProduction::infeasisibityCause() +{ + return "* impossible to generate exactly the weekly hydro target"; +} +} \ No newline at end of file diff --git a/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.h b/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.h new file mode 100644 index 0000000000..5ed846ed17 --- /dev/null +++ b/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.h @@ -0,0 +1,79 @@ + +#pragma once + +#include +#include + +namespace Antares::Optimization +{ +class DetectedConstraint +{ +public: + void setConstraintName(std::string constraintName); + std::string regexId(); + virtual std::string infeasisibity() = 0; + virtual std::string infeasisibityCause() = 0; + +protected: + std::string name_; + std::string regexId_; + std::vector splitName_; +}; + +class HourlyBC : public DetectedConstraint +{ +public: + HourlyBC(); + std::string infeasisibity() override; + std::string infeasisibityCause() override; +}; + +class DailyBC : public DetectedConstraint +{ +public: + DailyBC(); + std::string infeasisibity() override; + std::string infeasisibityCause() override; +}; + +class WeeklyBC : public DetectedConstraint +{ +public: + WeeklyBC(); + std::string infeasisibity() override; + std::string infeasisibityCause() override; +}; + +class FictitiousLoad : public DetectedConstraint +{ +public: + FictitiousLoad(); + std::string infeasisibity() override; + std::string infeasisibityCause() override; +}; + +class HydroLevel : public DetectedConstraint +{ +public: + HydroLevel(); + std::string infeasisibity() override; + std::string infeasisibityCause() override; +}; + +class STS : public DetectedConstraint +{ +public: + STS(); + std::string infeasisibity() override; + std::string infeasisibityCause() override; +}; + +class HydroProduction : public DetectedConstraint +{ +public: + HydroProduction(); + std::string infeasisibity() override; + std::string infeasisibityCause() override; +}; +} + diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h index edc84805c9..96e01f8136 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h @@ -23,6 +23,7 @@ #include #include "unfeasibility-analysis.h" +#include "detected-infeasible-constraints.h" namespace operations_research { @@ -40,7 +41,7 @@ namespace Antares::Optimization class ConstraintSlackAnalysis: public UnfeasibilityAnalysis { public: - ConstraintSlackAnalysis() = default; + ConstraintSlackAnalysis(); ~ConstraintSlackAnalysis() override = default; void run(operations_research::MPSolver* problem) override; @@ -59,10 +60,8 @@ class ConstraintSlackAnalysis: public UnfeasibilityAnalysis std::vector slackVariables_; const unsigned int nbMaxSlackVarsToKeep = 10; - - const std::string constraint_name_pattern = "^AreaHydroLevel::|::hourly::|::daily::|::weekly::|" - "^FictiveLoads::|^Level::|" - "^HydroPower::"; + std::vector> detectedConstraints_; + std::string constraint_name_pattern_; }; } // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h index f28683d7a6..c734304bdd 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h @@ -23,8 +23,10 @@ #include #include #include +#include #include "constraint.h" +#include "detected-infeasible-constraints.h" namespace operations_research { @@ -38,7 +40,8 @@ class InfeasibleProblemReport public: InfeasibleProblemReport() = delete; explicit InfeasibleProblemReport( - const std::vector& slackVariables); + const std::vector& slackVariables, + const std::vector>&); void prettyPrint(); private: diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 8260038eed..528f23901e 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -34,7 +34,8 @@ using namespace operations_research; namespace Antares::Optimization { InfeasibleProblemReport::InfeasibleProblemReport( - const std::vector& slackVariables) + const std::vector& slackVariables, + const std::vector>& loggers) { turnSlackVarsIntoConstraints(slackVariables); sortConstraintsByType(); From b73f98562553e9f105400564304009537ef606ac Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Fri, 5 Jul 2024 13:31:19 +0200 Subject: [PATCH 19/78] Make infeasibily more changeable : use new list of constraint and remove old style --- .../constraint-slack-analysis.cpp | 21 +++--- .../detected-infeasible-constraints.cpp | 35 +++++++++ .../detected-infeasible-constraints.h | 9 +++ .../constraint-slack-analysis.h | 2 +- .../infeasible-problem-analysis/report.h | 21 +++--- .../infeasible-problem-analysis/report.cpp | 74 +++++++------------ 6 files changed, 94 insertions(+), 68 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index aa1d75b6c0..2c2ee0b459 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -42,16 +42,16 @@ namespace Antares::Optimization { ConstraintSlackAnalysis::ConstraintSlackAnalysis() { - detectedConstraints_.push_back(std::make_shared()); - detectedConstraints_.push_back(std::make_shared()); - detectedConstraints_.push_back(std::make_shared()); - detectedConstraints_.push_back(std::make_shared()); - detectedConstraints_.push_back(std::make_shared()); - detectedConstraints_.push_back(std::make_shared()); - detectedConstraints_.push_back(std::make_shared()); + detectedConstraintTypes_.push_back(std::make_shared()); + detectedConstraintTypes_.push_back(std::make_shared()); + detectedConstraintTypes_.push_back(std::make_shared()); + detectedConstraintTypes_.push_back(std::make_shared()); + detectedConstraintTypes_.push_back(std::make_shared()); + detectedConstraintTypes_.push_back(std::make_shared()); + detectedConstraintTypes_.push_back(std::make_shared()); std::vector patterns; - std::for_each(detectedConstraints_.begin(), detectedConstraints_.end(), + std::for_each(detectedConstraintTypes_.begin(), detectedConstraintTypes_.end(), [&](auto& c) { patterns.push_back(c->regexId()); }); constraint_name_pattern_ = boost::algorithm::join(patterns, "|"); } @@ -142,8 +142,9 @@ void ConstraintSlackAnalysis::trimSlackVariables() void ConstraintSlackAnalysis::printReport() const { - InfeasibleProblemReport report(slackVariables_, detectedConstraints_); - report.prettyPrint(); + InfeasibleProblemReport report(slackVariables_, detectedConstraintTypes_); + report.logSuspiciousConstraints(); + report.logInfeasibilityCauses(); } } // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.cpp b/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.cpp index f76e077015..79e0e0d752 100644 --- a/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.cpp @@ -78,6 +78,11 @@ HourlyBC::HourlyBC() regexId_ = "::hourly::"; } +std::shared_ptr HourlyBC::clone() const +{ + return std::make_shared(*this); +} + std::string HourlyBC::infeasisibity() { return "Hourly BC '" + shortName(splitName_) + "' at hour " + timeStep(splitName_); @@ -96,6 +101,11 @@ DailyBC::DailyBC() regexId_ = "::daily::"; } +std::shared_ptr DailyBC::clone() const +{ + return std::make_shared(*this); +} + std::string DailyBC::infeasisibity() { return "Daily BC '" + shortName(splitName_) + "' at day " + timeStep(splitName_); @@ -114,6 +124,11 @@ WeeklyBC::WeeklyBC() regexId_ = "::weekly::"; } +std::shared_ptr WeeklyBC::clone() const +{ + return std::make_shared(*this); +} + std::string WeeklyBC::infeasisibity() { return "Weekly BC '" + shortName(splitName_); @@ -132,6 +147,11 @@ FictitiousLoad::FictitiousLoad() regexId_ = "^FictiveLoads::"; } +std::shared_ptr FictitiousLoad::clone() const +{ + return std::make_shared(*this); +} + std::string FictitiousLoad::infeasisibity() { return "Last resort shedding status at area '" + areaName(splitName_) + "' at hour " + timeStep(splitName_); @@ -150,6 +170,11 @@ HydroLevel::HydroLevel() regexId_ = "^AreaHydroLevel::"; } +std::shared_ptr HydroLevel::clone() const +{ + return std::make_shared(*this); +} + std::string HydroLevel::infeasisibity() { return "Hydro level constraint at area '" + areaName(splitName_) + "' at hour " + timeStep(splitName_); @@ -169,6 +194,11 @@ STS::STS() regexId_ = "^Level::"; } +std::shared_ptr STS::clone() const +{ + return std::make_shared(*this); +} + std::string STS::infeasisibity() { return "Short-term-storage reservoir constraint at area '" + areaName(splitName_) + "' in STS '" @@ -189,6 +219,11 @@ HydroProduction::HydroProduction() regexId_ = "^HydroPower::"; } +std::shared_ptr HydroProduction::clone() const +{ + return std::make_shared(*this); +} + std::string HydroProduction::infeasisibity() { return "Hydro weekly production at area '" + areaName(splitName_) + "'"; diff --git a/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.h b/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.h index 5ed846ed17..ae1b0c4756 100644 --- a/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.h +++ b/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.h @@ -3,6 +3,7 @@ #include #include +#include namespace Antares::Optimization { @@ -11,6 +12,7 @@ class DetectedConstraint public: void setConstraintName(std::string constraintName); std::string regexId(); + virtual std::shared_ptr clone() const = 0; virtual std::string infeasisibity() = 0; virtual std::string infeasisibityCause() = 0; @@ -24,6 +26,7 @@ class HourlyBC : public DetectedConstraint { public: HourlyBC(); + std::shared_ptr clone() const override; std::string infeasisibity() override; std::string infeasisibityCause() override; }; @@ -32,6 +35,7 @@ class DailyBC : public DetectedConstraint { public: DailyBC(); + std::shared_ptr clone() const override; std::string infeasisibity() override; std::string infeasisibityCause() override; }; @@ -40,6 +44,7 @@ class WeeklyBC : public DetectedConstraint { public: WeeklyBC(); + std::shared_ptr clone() const override; std::string infeasisibity() override; std::string infeasisibityCause() override; }; @@ -48,6 +53,7 @@ class FictitiousLoad : public DetectedConstraint { public: FictitiousLoad(); + std::shared_ptr clone() const override; std::string infeasisibity() override; std::string infeasisibityCause() override; }; @@ -56,6 +62,7 @@ class HydroLevel : public DetectedConstraint { public: HydroLevel(); + std::shared_ptr clone() const override; std::string infeasisibity() override; std::string infeasisibityCause() override; }; @@ -64,6 +71,7 @@ class STS : public DetectedConstraint { public: STS(); + std::shared_ptr clone() const override; std::string infeasisibity() override; std::string infeasisibityCause() override; }; @@ -71,6 +79,7 @@ class STS : public DetectedConstraint class HydroProduction : public DetectedConstraint { public: + std::shared_ptr clone() const override; HydroProduction(); std::string infeasisibity() override; std::string infeasisibityCause() override; diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h index 96e01f8136..49d7d03dad 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h @@ -60,7 +60,7 @@ class ConstraintSlackAnalysis: public UnfeasibilityAnalysis std::vector slackVariables_; const unsigned int nbMaxSlackVarsToKeep = 10; - std::vector> detectedConstraints_; + std::vector> detectedConstraintTypes_; std::string constraint_name_pattern_; }; diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h index c734304bdd..d57ccf58a4 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h @@ -25,8 +25,10 @@ #include #include -#include "constraint.h" #include "detected-infeasible-constraints.h" +#include "ortools/linear_solver/linear_solver.h" + +using namespace operations_research; namespace operations_research { @@ -42,17 +44,16 @@ class InfeasibleProblemReport explicit InfeasibleProblemReport( const std::vector& slackVariables, const std::vector>&); - void prettyPrint(); - -private: - void turnSlackVarsIntoConstraints( - const std::vector& slackVariables); - void sortConstraintsByType(); void logSuspiciousConstraints(); void logInfeasibilityCauses(); - std::vector constraints_; - std::map nbConstraintsByType_; - const unsigned int nbMaxVariables = 10; +private: + void buildConstraintsFromSlackVars(); + void filterConstraintsToOneByType(); + + const std::vector>& constraintTypes_; + const std::vector& slackVariables_; + std::vector> constraints_; + std::vector> uniqueConstraintByType_; }; } // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 528f23901e..8a1d15fa8e 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -21,89 +21,69 @@ #include "antares/solver/infeasible-problem-analysis/report.h" #include +#include #include #include "antares/solver/infeasible-problem-analysis/constraint.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" -#include "ortools/linear_solver/linear_solver.h" #pragma GCC diagnostic pop -using namespace operations_research; - namespace Antares::Optimization { InfeasibleProblemReport::InfeasibleProblemReport( const std::vector& slackVariables, - const std::vector>& loggers) + const std::vector>& constraintTypes) : + slackVariables_(slackVariables), + constraintTypes_(constraintTypes) { - turnSlackVarsIntoConstraints(slackVariables); - sortConstraintsByType(); + buildConstraintsFromSlackVars(); + filterConstraintsToOneByType(); } -void InfeasibleProblemReport::turnSlackVarsIntoConstraints( - const std::vector& slackVariables) +void InfeasibleProblemReport::buildConstraintsFromSlackVars() { - for (const MPVariable* slack: slackVariables) + for (const auto& slackVar : slackVariables_) { - constraints_.emplace_back(slack->name()); + for (const auto& cType : constraintTypes_) + { + if (std::regex_search(slackVar->name(), std::regex(cType->regexId()))) + { + constraints_.push_back(cType->clone()); + constraints_.back()->setConstraintName(slackVar->name()); + } + } } } -void InfeasibleProblemReport::sortConstraintsByType() +void InfeasibleProblemReport::filterConstraintsToOneByType() { - for (auto& c: constraints_) + std::vector typesPicked; + for (const auto& c: constraints_) { - c.extractComponentsFromName(); - nbConstraintsByType_[c.type()]++; + if (std::find(typesPicked.begin(), typesPicked.end(), c->regexId()) == typesPicked.end()) + { + uniqueConstraintByType_.push_back(c); + typesPicked.push_back(c->regexId()); + } } } void InfeasibleProblemReport::logSuspiciousConstraints() { - Antares::logs.error() << "The following constraints are suspicious (first = most suspicious)"; for (const auto& c: constraints_) { - Antares::logs.error() << c.prettyPrint(); + Antares::logs.error() << c->infeasisibity(); } } void InfeasibleProblemReport::logInfeasibilityCauses() { Antares::logs.error() << "Possible causes of infeasibility:"; - if (nbConstraintsByType_[ConstraintType::hydro_reservoir_level] > 0) - { - Antares::logs.error() << "* Hydro reservoir impossible to manage with cumulative options " - "\"hard bounds without heuristic\""; - } - if (nbConstraintsByType_[ConstraintType::hydro_production_weekly] > 0) - { - Antares::logs.error() << "* impossible to generate exactly the weekly hydro target"; - } - if (nbConstraintsByType_[ConstraintType::fictitious_load] > 0) - { - Antares::logs.error() << "* Last resort shedding status,"; - } - if (nbConstraintsByType_[ConstraintType::short_term_storage_level] > 0) - { - Antares::logs.error() - << "* Short-term storage reservoir level impossible to manage. Please check inflows, " - "lower & upper curves and initial level (if prescribed),"; - } - - const unsigned int bcCount = nbConstraintsByType_[ConstraintType::binding_constraint_hourly] - + nbConstraintsByType_[ConstraintType::binding_constraint_daily] - + nbConstraintsByType_[ConstraintType::binding_constraint_weekly]; - if (bcCount > 0) + for (const auto& c: uniqueConstraintByType_) { - Antares::logs.error() << "* Binding constraints,"; + Antares::logs.error() << c->infeasisibityCause(); } } -void InfeasibleProblemReport::prettyPrint() -{ - logSuspiciousConstraints(); - logInfeasibilityCauses(); -} - } // namespace Antares::Optimization From ef34f664ab68f2f4f075312c8ec5b807a4ec3351 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Fri, 5 Jul 2024 15:21:53 +0200 Subject: [PATCH 20/78] Make infeasibily more changeable : remove old class Constraint (now useless) + move a header to the right location --- .../CMakeLists.txt | 4 +- .../constraint.cpp | 154 ------------------ .../detected-infeasible-constraints.cpp | 2 +- .../infeasible-problem-analysis/constraint.h | 59 ------- .../detected-infeasible-constraints.h | 0 .../infeasible-problem-analysis/report.cpp | 1 - 6 files changed, 2 insertions(+), 218 deletions(-) delete mode 100644 src/solver/infeasible-problem-analysis/constraint.cpp delete mode 100644 src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h rename src/solver/infeasible-problem-analysis/{ => include/antares/solver/infeasible-problem-analysis}/detected-infeasible-constraints.h (100%) diff --git a/src/solver/infeasible-problem-analysis/CMakeLists.txt b/src/solver/infeasible-problem-analysis/CMakeLists.txt index 67d2462fec..1b474cc624 100644 --- a/src/solver/infeasible-problem-analysis/CMakeLists.txt +++ b/src/solver/infeasible-problem-analysis/CMakeLists.txt @@ -10,9 +10,7 @@ set(SRC_INFEASIBLE_PROBLEM_ANALYSIS include/antares/solver/infeasible-problem-analysis/unfeasible-pb-analyzer.h include/antares/solver/infeasible-problem-analysis/report.h report.cpp - include/antares/solver/infeasible-problem-analysis/constraint.h - constraint.cpp - detected-infeasible-constraints.h + include/antares/solver/infeasible-problem-analysis/detected-infeasible-constraints.h detected-infeasible-constraints.cpp ) diff --git a/src/solver/infeasible-problem-analysis/constraint.cpp b/src/solver/infeasible-problem-analysis/constraint.cpp deleted file mode 100644 index 4f111914aa..0000000000 --- a/src/solver/infeasible-problem-analysis/constraint.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2007-2024, RTE (https://www.rte-france.com) - * See AUTHORS.txt - * SPDX-License-Identifier: MPL-2.0 - * This file is part of Antares-Simulator, - * Adequacy and Performance assessment for interconnected energy networks. - * - * Antares_Simulator is free software: you can redistribute it and/or modify - * it under the terms of the Mozilla Public Licence 2.0 as published by - * the Mozilla Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Antares_Simulator is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * Mozilla Public Licence 2.0 for more details. - * - * You should have received a copy of the Mozilla Public Licence 2.0 - * along with Antares_Simulator. If not, see . - */ -#include "antares/solver/infeasible-problem-analysis/constraint.h" - -#include -#include -#include -#include - -#include -#include -#include - -namespace -{ -const std::string kUnknown = ""; -} - -namespace Antares::Optimization -{ -Constraint::Constraint(const std::string& name): - name_(name) -{ -} - -void Constraint::extractComponentsFromName() -{ - boost::algorithm::split_regex(nameComponents_, name_, boost::regex("::")); -} - -class StringIsNotWellFormated: public std::runtime_error -{ -public: - StringIsNotWellFormated(const std::string& error_message): - std::runtime_error(error_message) - { - } -}; - -std::string StringBetweenAngleBrackets(const std::string& constraintName) -{ - std::vector split_name; - boost::split(split_name, constraintName, boost::is_any_of("<>")); - - std::string err_msg = "Error: "; - if (split_name.size() < 3) - { - err_msg += "constraint name '" + constraintName + "' misses '<' and/or '>' bracket"; - throw StringIsNotWellFormated(err_msg); - } - if (split_name[1].empty()) - { - err_msg += "constraint name '" + constraintName + "' must be of format '**'"; - throw StringIsNotWellFormated(err_msg); - } - return split_name[1]; -} - -std::string Constraint::areaName() const -{ - return StringBetweenAngleBrackets(nameComponents_.at(1)); -} - -std::string Constraint::timeStep() const -{ - return StringBetweenAngleBrackets(nameComponents_.at(nameComponents_.size() - 2)); -} - -ConstraintType Constraint::type() const -{ - assert(nameComponents_.size() > 1); - if (nameComponents_.at(1) == "hourly") - { - return ConstraintType::binding_constraint_hourly; - } - if (nameComponents_.at(1) == "daily") - { - return ConstraintType::binding_constraint_daily; - } - if (nameComponents_.at(1) == "weekly") - { - return ConstraintType::binding_constraint_weekly; - } - if (nameComponents_.at(0) == "FictiveLoads") - { - return ConstraintType::fictitious_load; - } - if (nameComponents_.at(0) == "AreaHydroLevel") - { - return ConstraintType::hydro_reservoir_level; - } - if (nameComponents_.at(0) == "HydroPower") - { - return ConstraintType::hydro_production_weekly; - } - if (nameComponents_.at(0) == "Level") - { - return ConstraintType::short_term_storage_level; - } - return ConstraintType::none; -} - -std::string Constraint::shortName() const -{ - return nameComponents_.at(0); -} - -std::string Constraint::STSname() const -{ - return StringBetweenAngleBrackets(nameComponents_.at(2)); -} - -std::string Constraint::prettyPrint() const -{ - switch (type()) - { - case ConstraintType::binding_constraint_hourly: - return "Hourly binding constraint '" + shortName() + "' at hour " + timeStep(); - case ConstraintType::binding_constraint_daily: - return "Daily binding constraint '" + shortName() + "' at day " + timeStep(); - case ConstraintType::binding_constraint_weekly: - return "Weekly binding constraint '" + shortName(); - case ConstraintType::fictitious_load: - return "Last resort shedding status at area '" + areaName() + "' at hour " + timeStep(); - case ConstraintType::hydro_reservoir_level: - return "Hydro reservoir constraint at area '" + areaName() + "' at hour " + timeStep(); - case ConstraintType::hydro_production_weekly: - return "Hydro weekly production at area '" + areaName() + "'"; - case ConstraintType::short_term_storage_level: - return "Short-term-storage reservoir constraint at area '" + areaName() + "' in STS '" - + STSname() + "' at hour " + timeStep(); - default: - return kUnknown; - } -} -} // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.cpp b/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.cpp index 79e0e0d752..a30d9fefa6 100644 --- a/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.cpp @@ -1,5 +1,5 @@ -#include "detected-infeasible-constraints.h" +#include "antares/solver/infeasible-problem-analysis/detected-infeasible-constraints.h" #include #include diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h deleted file mode 100644 index d2f4f2a692..0000000000 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2007-2024, RTE (https://www.rte-france.com) - * See AUTHORS.txt - * SPDX-License-Identifier: MPL-2.0 - * This file is part of Antares-Simulator, - * Adequacy and Performance assessment for interconnected energy networks. - * - * Antares_Simulator is free software: you can redistribute it and/or modify - * it under the terms of the Mozilla Public Licence 2.0 as published by - * the Mozilla Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Antares_Simulator is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * Mozilla Public Licence 2.0 for more details. - * - * You should have received a copy of the Mozilla Public Licence 2.0 - * along with Antares_Simulator. If not, see . - */ -#pragma once - -#include -#include - -namespace Antares::Optimization -{ -enum class ConstraintType -{ - binding_constraint_hourly, - binding_constraint_daily, - binding_constraint_weekly, - fictitious_load, - hydro_reservoir_level, - hydro_production_weekly, - short_term_storage_level, - none -}; - -class Constraint -{ -public: - Constraint() = default; - Constraint(const std::string& name); - - void extractComponentsFromName(); - std::string prettyPrint() const; - ConstraintType type() const; - -private: - std::string name_; - std::vector nameComponents_; - - std::string areaName() const; - std::string STSname() const; - std::string timeStep() const; - std::string shortName() const; -}; -} // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/detected-infeasible-constraints.h similarity index 100% rename from src/solver/infeasible-problem-analysis/detected-infeasible-constraints.h rename to src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/detected-infeasible-constraints.h diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 8a1d15fa8e..ac11359c5f 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -24,7 +24,6 @@ #include #include -#include "antares/solver/infeasible-problem-analysis/constraint.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic pop From c998d5f1220bbc38e0ce6244ad55eca2f5b009d0 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Fri, 5 Jul 2024 15:48:24 +0200 Subject: [PATCH 21/78] Make infeasibily more changeable : renaming - detected ==> watched (for variables, classes, files) --- .../CMakeLists.txt | 4 +-- .../constraint-slack-analysis.cpp | 21 ++++++------ .../constraint-slack-analysis.h | 4 +-- .../infeasible-problem-analysis/report.h | 10 +++--- ...le-constraints.h => watched-constraints.h} | 32 +++++++++---------- .../infeasible-problem-analysis/report.cpp | 5 +-- ...onstraints.cpp => watched-constraints.cpp} | 20 ++++++------ 7 files changed, 46 insertions(+), 50 deletions(-) rename src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/{detected-infeasible-constraints.h => watched-constraints.h} (59%) rename src/solver/infeasible-problem-analysis/{detected-infeasible-constraints.cpp => watched-constraints.cpp} (89%) diff --git a/src/solver/infeasible-problem-analysis/CMakeLists.txt b/src/solver/infeasible-problem-analysis/CMakeLists.txt index 1b474cc624..0043f59dce 100644 --- a/src/solver/infeasible-problem-analysis/CMakeLists.txt +++ b/src/solver/infeasible-problem-analysis/CMakeLists.txt @@ -10,8 +10,8 @@ set(SRC_INFEASIBLE_PROBLEM_ANALYSIS include/antares/solver/infeasible-problem-analysis/unfeasible-pb-analyzer.h include/antares/solver/infeasible-problem-analysis/report.h report.cpp - include/antares/solver/infeasible-problem-analysis/detected-infeasible-constraints.h - detected-infeasible-constraints.cpp + include/antares/solver/infeasible-problem-analysis/watched-constraints.h + watched-constraints.cpp ) add_library(infeasible_problem_analysis ${SRC_INFEASIBLE_PROBLEM_ANALYSIS}) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index 2c2ee0b459..c499e9850f 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -18,12 +18,11 @@ * You should have received a copy of the Mozilla Public Licence 2.0 * along with Antares_Simulator. If not, see . */ -#include "antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h" - #include #include #include +#include "antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h" #include "antares/solver/infeasible-problem-analysis/report.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" @@ -42,16 +41,16 @@ namespace Antares::Optimization { ConstraintSlackAnalysis::ConstraintSlackAnalysis() { - detectedConstraintTypes_.push_back(std::make_shared()); - detectedConstraintTypes_.push_back(std::make_shared()); - detectedConstraintTypes_.push_back(std::make_shared()); - detectedConstraintTypes_.push_back(std::make_shared()); - detectedConstraintTypes_.push_back(std::make_shared()); - detectedConstraintTypes_.push_back(std::make_shared()); - detectedConstraintTypes_.push_back(std::make_shared()); + watchedConstraintTypes_.push_back(std::make_shared()); + watchedConstraintTypes_.push_back(std::make_shared()); + watchedConstraintTypes_.push_back(std::make_shared()); + watchedConstraintTypes_.push_back(std::make_shared()); + watchedConstraintTypes_.push_back(std::make_shared()); + watchedConstraintTypes_.push_back(std::make_shared()); + watchedConstraintTypes_.push_back(std::make_shared()); std::vector patterns; - std::for_each(detectedConstraintTypes_.begin(), detectedConstraintTypes_.end(), + std::for_each(watchedConstraintTypes_.begin(), watchedConstraintTypes_.end(), [&](auto& c) { patterns.push_back(c->regexId()); }); constraint_name_pattern_ = boost::algorithm::join(patterns, "|"); } @@ -142,7 +141,7 @@ void ConstraintSlackAnalysis::trimSlackVariables() void ConstraintSlackAnalysis::printReport() const { - InfeasibleProblemReport report(slackVariables_, detectedConstraintTypes_); + InfeasibleProblemReport report(slackVariables_, watchedConstraintTypes_); report.logSuspiciousConstraints(); report.logInfeasibilityCauses(); } diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h index 49d7d03dad..7ce70e6efd 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h @@ -23,7 +23,7 @@ #include #include "unfeasibility-analysis.h" -#include "detected-infeasible-constraints.h" +#include "watched-constraints.h" namespace operations_research { @@ -59,8 +59,8 @@ class ConstraintSlackAnalysis: public UnfeasibilityAnalysis void trimSlackVariables(); std::vector slackVariables_; + std::vector> watchedConstraintTypes_; const unsigned int nbMaxSlackVarsToKeep = 10; - std::vector> detectedConstraintTypes_; std::string constraint_name_pattern_; }; diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h index d57ccf58a4..96bfe8f568 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h @@ -25,7 +25,7 @@ #include #include -#include "detected-infeasible-constraints.h" +#include "watched-constraints.h" #include "ortools/linear_solver/linear_solver.h" using namespace operations_research; @@ -43,7 +43,7 @@ class InfeasibleProblemReport InfeasibleProblemReport() = delete; explicit InfeasibleProblemReport( const std::vector& slackVariables, - const std::vector>&); + const std::vector>&); void logSuspiciousConstraints(); void logInfeasibilityCauses(); @@ -51,9 +51,9 @@ class InfeasibleProblemReport void buildConstraintsFromSlackVars(); void filterConstraintsToOneByType(); - const std::vector>& constraintTypes_; + const std::vector>& constraintTypes_; const std::vector& slackVariables_; - std::vector> constraints_; - std::vector> uniqueConstraintByType_; + std::vector> constraints_; + std::vector> uniqueConstraintByType_; }; } // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/detected-infeasible-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h similarity index 59% rename from src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/detected-infeasible-constraints.h rename to src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index ae1b0c4756..74ed65beab 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/detected-infeasible-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -7,12 +7,12 @@ namespace Antares::Optimization { -class DetectedConstraint +class WatchedConstraint { public: void setConstraintName(std::string constraintName); std::string regexId(); - virtual std::shared_ptr clone() const = 0; + virtual std::shared_ptr clone() const = 0; virtual std::string infeasisibity() = 0; virtual std::string infeasisibityCause() = 0; @@ -22,64 +22,64 @@ class DetectedConstraint std::vector splitName_; }; -class HourlyBC : public DetectedConstraint +class HourlyBC : public WatchedConstraint { public: HourlyBC(); - std::shared_ptr clone() const override; + std::shared_ptr clone() const override; std::string infeasisibity() override; std::string infeasisibityCause() override; }; -class DailyBC : public DetectedConstraint +class DailyBC : public WatchedConstraint { public: DailyBC(); - std::shared_ptr clone() const override; + std::shared_ptr clone() const override; std::string infeasisibity() override; std::string infeasisibityCause() override; }; -class WeeklyBC : public DetectedConstraint +class WeeklyBC : public WatchedConstraint { public: WeeklyBC(); - std::shared_ptr clone() const override; + std::shared_ptr clone() const override; std::string infeasisibity() override; std::string infeasisibityCause() override; }; -class FictitiousLoad : public DetectedConstraint +class FictitiousLoad : public WatchedConstraint { public: FictitiousLoad(); - std::shared_ptr clone() const override; + std::shared_ptr clone() const override; std::string infeasisibity() override; std::string infeasisibityCause() override; }; -class HydroLevel : public DetectedConstraint +class HydroLevel : public WatchedConstraint { public: HydroLevel(); - std::shared_ptr clone() const override; + std::shared_ptr clone() const override; std::string infeasisibity() override; std::string infeasisibityCause() override; }; -class STS : public DetectedConstraint +class STS : public WatchedConstraint { public: STS(); - std::shared_ptr clone() const override; + std::shared_ptr clone() const override; std::string infeasisibity() override; std::string infeasisibityCause() override; }; -class HydroProduction : public DetectedConstraint +class HydroProduction : public WatchedConstraint { public: - std::shared_ptr clone() const override; + std::shared_ptr clone() const override; HydroProduction(); std::string infeasisibity() override; std::string infeasisibityCause() override; diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index ac11359c5f..6e5218d9a4 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -24,15 +24,12 @@ #include #include -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#pragma GCC diagnostic pop namespace Antares::Optimization { InfeasibleProblemReport::InfeasibleProblemReport( const std::vector& slackVariables, - const std::vector>& constraintTypes) : + const std::vector>& constraintTypes) : slackVariables_(slackVariables), constraintTypes_(constraintTypes) { diff --git a/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp similarity index 89% rename from src/solver/infeasible-problem-analysis/detected-infeasible-constraints.cpp rename to src/solver/infeasible-problem-analysis/watched-constraints.cpp index a30d9fefa6..22ae4bcca0 100644 --- a/src/solver/infeasible-problem-analysis/detected-infeasible-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -1,5 +1,5 @@ -#include "antares/solver/infeasible-problem-analysis/detected-infeasible-constraints.h" +#include "antares/solver/infeasible-problem-analysis/watched-constraints.h" #include #include @@ -59,13 +59,13 @@ namespace Antares::Optimization // ======================================= // Generic constraint logger // ======================================= -void DetectedConstraint::setConstraintName(std::string name) +void WatchedConstraint::setConstraintName(std::string name) { name_ = name; boost::algorithm::split_regex(splitName_, name_, boost::regex("::")); } -std::string DetectedConstraint::regexId() +std::string WatchedConstraint::regexId() { return regexId_; } @@ -78,7 +78,7 @@ HourlyBC::HourlyBC() regexId_ = "::hourly::"; } -std::shared_ptr HourlyBC::clone() const +std::shared_ptr HourlyBC::clone() const { return std::make_shared(*this); } @@ -101,7 +101,7 @@ DailyBC::DailyBC() regexId_ = "::daily::"; } -std::shared_ptr DailyBC::clone() const +std::shared_ptr DailyBC::clone() const { return std::make_shared(*this); } @@ -124,7 +124,7 @@ WeeklyBC::WeeklyBC() regexId_ = "::weekly::"; } -std::shared_ptr WeeklyBC::clone() const +std::shared_ptr WeeklyBC::clone() const { return std::make_shared(*this); } @@ -147,7 +147,7 @@ FictitiousLoad::FictitiousLoad() regexId_ = "^FictiveLoads::"; } -std::shared_ptr FictitiousLoad::clone() const +std::shared_ptr FictitiousLoad::clone() const { return std::make_shared(*this); } @@ -170,7 +170,7 @@ HydroLevel::HydroLevel() regexId_ = "^AreaHydroLevel::"; } -std::shared_ptr HydroLevel::clone() const +std::shared_ptr HydroLevel::clone() const { return std::make_shared(*this); } @@ -194,7 +194,7 @@ STS::STS() regexId_ = "^Level::"; } -std::shared_ptr STS::clone() const +std::shared_ptr STS::clone() const { return std::make_shared(*this); } @@ -219,7 +219,7 @@ HydroProduction::HydroProduction() regexId_ = "^HydroPower::"; } -std::shared_ptr HydroProduction::clone() const +std::shared_ptr HydroProduction::clone() const { return std::make_shared(*this); } From 294b10ee64ff2395814c05bc482ccf9ba1b04f68 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Fri, 5 Jul 2024 16:23:15 +0200 Subject: [PATCH 22/78] Make infeasibily more changeable : split function addSlackVariables into 2 functions --- .../constraint-slack-analysis.cpp | 63 +++++++++++-------- .../constraint-slack-analysis.h | 6 +- 2 files changed, 40 insertions(+), 29 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index c499e9850f..05320ca473 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -48,16 +48,12 @@ ConstraintSlackAnalysis::ConstraintSlackAnalysis() watchedConstraintTypes_.push_back(std::make_shared()); watchedConstraintTypes_.push_back(std::make_shared()); watchedConstraintTypes_.push_back(std::make_shared()); - - std::vector patterns; - std::for_each(watchedConstraintTypes_.begin(), watchedConstraintTypes_.end(), - [&](auto& c) { patterns.push_back(c->regexId()); }); - constraint_name_pattern_ = boost::algorithm::join(patterns, "|"); } void ConstraintSlackAnalysis::run(MPSolver* problem) { - addSlackVariables(problem); + selectConstraintsToWatch(problem); + addSlackVariablesToConstraints(problem); if (slackVariables_.empty()) { logs.error() << title() << " : no constraints have been selected"; @@ -79,7 +75,24 @@ void ConstraintSlackAnalysis::run(MPSolver* problem) trimSlackVariables(); } -void ConstraintSlackAnalysis::addSlackVariables(MPSolver* problem) +void ConstraintSlackAnalysis::selectConstraintsToWatch(MPSolver* problem) +{ + std::vector patterns; + std::for_each(watchedConstraintTypes_.begin(), watchedConstraintTypes_.end(), + [&](auto& c) { patterns.push_back(c->regexId()); }); + std::string constraint_name_pattern { boost::algorithm::join(patterns, "|") }; + + std::regex rgx(constraint_name_pattern); + for (MPConstraint* c: problem->constraints()) + { + if (std::regex_search(c->name(), rgx)) + { + constraintsToWatch_.push_back(c); + } + } +} + +void ConstraintSlackAnalysis::addSlackVariablesToConstraints(MPSolver* problem) { /* Optimization: We assess that less than 1 every 3 constraint will match @@ -88,29 +101,25 @@ void ConstraintSlackAnalysis::addSlackVariables(MPSolver* problem) */ const unsigned int selectedConstraintsInverseRatio = 3; slackVariables_.reserve(problem->NumConstraints() / selectedConstraintsInverseRatio); - std::regex rgx(constraint_name_pattern_); const double infinity = MPSolver::infinity(); - for (MPConstraint* constraint: problem->constraints()) + for (MPConstraint* c: constraintsToWatch_) { - if (std::regex_search(constraint->name(), rgx)) + if (c->lb() != -infinity) + { + const MPVariable* slack = problem->MakeNumVar(0, + infinity, + c->name() + "::low"); + c->SetCoefficient(slack, 1.); + slackVariables_.push_back(slack); + } + + if (c->ub() != infinity) { - if (constraint->lb() != -infinity) - { - const MPVariable* slack = problem->MakeNumVar(0, - infinity, - constraint->name() + "::low"); - constraint->SetCoefficient(slack, 1.); - slackVariables_.push_back(slack); - } - - if (constraint->ub() != infinity) - { - const MPVariable* slack = problem->MakeNumVar(0, - infinity, - constraint->name() + "::up"); - constraint->SetCoefficient(slack, -1.); - slackVariables_.push_back(slack); - } + const MPVariable* slack = problem->MakeNumVar(0, + infinity, + c->name() + "::up"); + c->SetCoefficient(slack, -1.); + slackVariables_.push_back(slack); } } } diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h index 7ce70e6efd..ac4d1a9bd8 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h @@ -27,6 +27,7 @@ namespace operations_research { +class MPConstraint; class MPVariable; class MPSolver; } // namespace operations_research @@ -53,15 +54,16 @@ class ConstraintSlackAnalysis: public UnfeasibilityAnalysis } private: + void selectConstraintsToWatch(operations_research::MPSolver* problem); + void addSlackVariablesToConstraints(operations_research::MPSolver* problem); void buildObjective(operations_research::MPSolver* problem) const; - void addSlackVariables(operations_research::MPSolver* problem); void sortSlackVariablesByValue(); void trimSlackVariables(); + std::vector constraintsToWatch_; std::vector slackVariables_; std::vector> watchedConstraintTypes_; const unsigned int nbMaxSlackVarsToKeep = 10; - std::string constraint_name_pattern_; }; } // namespace Antares::Optimization From 2b94176366569b1441143216fd20562e84acaa37 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Fri, 5 Jul 2024 16:28:58 +0200 Subject: [PATCH 23/78] Make infeasibily more changeable : clang format --- .../constraint-slack-analysis.cpp | 20 ++++++++---------- .../infeasible-problem-analysis/report.h | 4 ++-- .../watched-constraints.h | 21 +++++++++---------- .../infeasible-problem-analysis/report.cpp | 6 +++--- .../watched-constraints.cpp | 10 +++++---- 5 files changed, 30 insertions(+), 31 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index 05320ca473..af8edc3c23 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -18,11 +18,13 @@ * You should have received a copy of the Mozilla Public Licence 2.0 * along with Antares_Simulator. If not, see . */ +#include "antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h" + #include + #include #include -#include "antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h" #include "antares/solver/infeasible-problem-analysis/report.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" @@ -31,8 +33,7 @@ using namespace operations_research; -static bool compareSlackSolutions(const MPVariable* a, - const MPVariable* b) +static bool compareSlackSolutions(const MPVariable* a, const MPVariable* b) { return a->solution_value() > b->solution_value(); } @@ -78,9 +79,10 @@ void ConstraintSlackAnalysis::run(MPSolver* problem) void ConstraintSlackAnalysis::selectConstraintsToWatch(MPSolver* problem) { std::vector patterns; - std::for_each(watchedConstraintTypes_.begin(), watchedConstraintTypes_.end(), + std::for_each(watchedConstraintTypes_.begin(), + watchedConstraintTypes_.end(), [&](auto& c) { patterns.push_back(c->regexId()); }); - std::string constraint_name_pattern { boost::algorithm::join(patterns, "|") }; + std::string constraint_name_pattern{boost::algorithm::join(patterns, "|")}; std::regex rgx(constraint_name_pattern); for (MPConstraint* c: problem->constraints()) @@ -106,18 +108,14 @@ void ConstraintSlackAnalysis::addSlackVariablesToConstraints(MPSolver* problem) { if (c->lb() != -infinity) { - const MPVariable* slack = problem->MakeNumVar(0, - infinity, - c->name() + "::low"); + const MPVariable* slack = problem->MakeNumVar(0, infinity, c->name() + "::low"); c->SetCoefficient(slack, 1.); slackVariables_.push_back(slack); } if (c->ub() != infinity) { - const MPVariable* slack = problem->MakeNumVar(0, - infinity, - c->name() + "::up"); + const MPVariable* slack = problem->MakeNumVar(0, infinity, c->name() + "::up"); c->SetCoefficient(slack, -1.); slackVariables_.push_back(slack); } diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h index 96bfe8f568..1d243700a1 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h @@ -21,12 +21,12 @@ #pragma once #include +#include #include #include -#include -#include "watched-constraints.h" #include "ortools/linear_solver/linear_solver.h" +#include "watched-constraints.h" using namespace operations_research; diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index 74ed65beab..76163f5204 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -1,9 +1,9 @@ #pragma once +#include #include #include -#include namespace Antares::Optimization { @@ -22,7 +22,7 @@ class WatchedConstraint std::vector splitName_; }; -class HourlyBC : public WatchedConstraint +class HourlyBC: public WatchedConstraint { public: HourlyBC(); @@ -31,7 +31,7 @@ class HourlyBC : public WatchedConstraint std::string infeasisibityCause() override; }; -class DailyBC : public WatchedConstraint +class DailyBC: public WatchedConstraint { public: DailyBC(); @@ -40,16 +40,16 @@ class DailyBC : public WatchedConstraint std::string infeasisibityCause() override; }; -class WeeklyBC : public WatchedConstraint +class WeeklyBC: public WatchedConstraint { public: WeeklyBC(); - std::shared_ptr clone() const override; + std::shared_ptr clone() const override; std::string infeasisibity() override; std::string infeasisibityCause() override; }; -class FictitiousLoad : public WatchedConstraint +class FictitiousLoad: public WatchedConstraint { public: FictitiousLoad(); @@ -58,7 +58,7 @@ class FictitiousLoad : public WatchedConstraint std::string infeasisibityCause() override; }; -class HydroLevel : public WatchedConstraint +class HydroLevel: public WatchedConstraint { public: HydroLevel(); @@ -67,7 +67,7 @@ class HydroLevel : public WatchedConstraint std::string infeasisibityCause() override; }; -class STS : public WatchedConstraint +class STS: public WatchedConstraint { public: STS(); @@ -76,7 +76,7 @@ class STS : public WatchedConstraint std::string infeasisibityCause() override; }; -class HydroProduction : public WatchedConstraint +class HydroProduction: public WatchedConstraint { public: std::shared_ptr clone() const override; @@ -84,5 +84,4 @@ class HydroProduction : public WatchedConstraint std::string infeasisibity() override; std::string infeasisibityCause() override; }; -} - +} // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 6e5218d9a4..35fc283000 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -29,7 +29,7 @@ namespace Antares::Optimization { InfeasibleProblemReport::InfeasibleProblemReport( const std::vector& slackVariables, - const std::vector>& constraintTypes) : + const std::vector>& constraintTypes): slackVariables_(slackVariables), constraintTypes_(constraintTypes) { @@ -39,9 +39,9 @@ InfeasibleProblemReport::InfeasibleProblemReport( void InfeasibleProblemReport::buildConstraintsFromSlackVars() { - for (const auto& slackVar : slackVariables_) + for (const auto& slackVar: slackVariables_) { - for (const auto& cType : constraintTypes_) + for (const auto& cType: constraintTypes_) { if (std::regex_search(slackVar->name(), std::regex(cType->regexId()))) { diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index 22ae4bcca0..15795a2e65 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -9,7 +9,7 @@ class StringIsNotWellFormated: public std::runtime_error { public: StringIsNotWellFormated(const std::string& error_message): - std::runtime_error(error_message) + std::runtime_error(error_message) { } }; @@ -154,7 +154,8 @@ std::shared_ptr FictitiousLoad::clone() const std::string FictitiousLoad::infeasisibity() { - return "Last resort shedding status at area '" + areaName(splitName_) + "' at hour " + timeStep(splitName_); + return "Last resort shedding status at area '" + areaName(splitName_) + "' at hour " + + timeStep(splitName_); } std::string FictitiousLoad::infeasisibityCause() @@ -177,7 +178,8 @@ std::shared_ptr HydroLevel::clone() const std::string HydroLevel::infeasisibity() { - return "Hydro level constraint at area '" + areaName(splitName_) + "' at hour " + timeStep(splitName_); + return "Hydro level constraint at area '" + areaName(splitName_) + "' at hour " + + timeStep(splitName_); } std::string HydroLevel::infeasisibityCause() @@ -233,4 +235,4 @@ std::string HydroProduction::infeasisibityCause() { return "* impossible to generate exactly the weekly hydro target"; } -} \ No newline at end of file +} // namespace Antares::Optimization From 64f94d8b0211e8ba68288a5001587176646b7287 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Fri, 5 Jul 2024 16:54:10 +0200 Subject: [PATCH 24/78] Make infeasibily more changeable : correction due to review --- .../watched-constraints.h | 6 ++- .../watched-constraints.cpp | 46 +++++++++++-------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index 76163f5204..95f5363abd 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -11,12 +11,16 @@ class WatchedConstraint { public: void setConstraintName(std::string constraintName); - std::string regexId(); + std::string regexId() const; virtual std::shared_ptr clone() const = 0; virtual std::string infeasisibity() = 0; virtual std::string infeasisibityCause() = 0; protected: + void setRegexId(std::string name); + const std::vector& splitName() const; + +private: std::string name_; std::string regexId_; std::vector splitName_; diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index 15795a2e65..c24c2a399e 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -65,17 +65,27 @@ void WatchedConstraint::setConstraintName(std::string name) boost::algorithm::split_regex(splitName_, name_, boost::regex("::")); } -std::string WatchedConstraint::regexId() +std::string WatchedConstraint::regexId() const { return regexId_; } +void WatchedConstraint::setRegexId(std::string regexId) +{ + regexId_ = regexId; +} + +const std::vector& WatchedConstraint::splitName() const +{ + return splitName_; +} + // ======================================= // Hourly BC logger // ======================================= HourlyBC::HourlyBC() { - regexId_ = "::hourly::"; + setRegexId("::hourly::"); } std::shared_ptr HourlyBC::clone() const @@ -85,7 +95,7 @@ std::shared_ptr HourlyBC::clone() const std::string HourlyBC::infeasisibity() { - return "Hourly BC '" + shortName(splitName_) + "' at hour " + timeStep(splitName_); + return "Hourly BC '" + shortName(splitName()) + "' at hour " + timeStep(splitName()); } std::string HourlyBC::infeasisibityCause() @@ -98,7 +108,7 @@ std::string HourlyBC::infeasisibityCause() // ======================================= DailyBC::DailyBC() { - regexId_ = "::daily::"; + setRegexId("::daily::"); } std::shared_ptr DailyBC::clone() const @@ -108,7 +118,7 @@ std::shared_ptr DailyBC::clone() const std::string DailyBC::infeasisibity() { - return "Daily BC '" + shortName(splitName_) + "' at day " + timeStep(splitName_); + return "Daily BC '" + shortName(splitName()) + "' at day " + timeStep(splitName()); } std::string DailyBC::infeasisibityCause() @@ -121,7 +131,7 @@ std::string DailyBC::infeasisibityCause() // ======================================= WeeklyBC::WeeklyBC() { - regexId_ = "::weekly::"; + setRegexId("::weekly::"); } std::shared_ptr WeeklyBC::clone() const @@ -131,7 +141,7 @@ std::shared_ptr WeeklyBC::clone() const std::string WeeklyBC::infeasisibity() { - return "Weekly BC '" + shortName(splitName_); + return "Weekly BC '" + shortName(splitName()); } std::string WeeklyBC::infeasisibityCause() @@ -144,7 +154,7 @@ std::string WeeklyBC::infeasisibityCause() // ======================================= FictitiousLoad::FictitiousLoad() { - regexId_ = "^FictiveLoads::"; + setRegexId("^FictiveLoads::"); } std::shared_ptr FictitiousLoad::clone() const @@ -154,8 +164,8 @@ std::shared_ptr FictitiousLoad::clone() const std::string FictitiousLoad::infeasisibity() { - return "Last resort shedding status at area '" + areaName(splitName_) + "' at hour " - + timeStep(splitName_); + return "Last resort shedding status at area '" + areaName(splitName()) + "' at hour " + + timeStep(splitName()); } std::string FictitiousLoad::infeasisibityCause() @@ -168,7 +178,7 @@ std::string FictitiousLoad::infeasisibityCause() // ======================================= HydroLevel::HydroLevel() { - regexId_ = "^AreaHydroLevel::"; + setRegexId("^AreaHydroLevel::"); } std::shared_ptr HydroLevel::clone() const @@ -178,8 +188,8 @@ std::shared_ptr HydroLevel::clone() const std::string HydroLevel::infeasisibity() { - return "Hydro level constraint at area '" + areaName(splitName_) + "' at hour " - + timeStep(splitName_); + return "Hydro level constraint at area '" + areaName(splitName()) + "' at hour " + + timeStep(splitName()); } std::string HydroLevel::infeasisibityCause() @@ -193,7 +203,7 @@ std::string HydroLevel::infeasisibityCause() // ======================================= STS::STS() { - regexId_ = "^Level::"; + setRegexId("^Level::"); } std::shared_ptr STS::clone() const @@ -203,8 +213,8 @@ std::shared_ptr STS::clone() const std::string STS::infeasisibity() { - return "Short-term-storage reservoir constraint at area '" + areaName(splitName_) + "' in STS '" - + STSname(splitName_) + "' at hour " + timeStep(splitName_); + return "Short-term-storage reservoir constraint at area '" + areaName(splitName()) + "' in STS '" + + STSname(splitName()) + "' at hour " + timeStep(splitName()); } std::string STS::infeasisibityCause() @@ -218,7 +228,7 @@ std::string STS::infeasisibityCause() // ======================================= HydroProduction::HydroProduction() { - regexId_ = "^HydroPower::"; + setRegexId("^HydroPower::"); } std::shared_ptr HydroProduction::clone() const @@ -228,7 +238,7 @@ std::shared_ptr HydroProduction::clone() const std::string HydroProduction::infeasisibity() { - return "Hydro weekly production at area '" + areaName(splitName_) + "'"; + return "Hydro weekly production at area '" + areaName(splitName()) + "'"; } std::string HydroProduction::infeasisibityCause() From d83e5922f6539f150f4d7b348d3df92a9919b39e Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Mon, 8 Jul 2024 17:52:59 +0200 Subject: [PATCH 25/78] Make infeasibily more changeable : add use of a factory and remove the clone function --- .../constraint-slack-analysis.cpp | 20 +--- .../constraint-slack-analysis.h | 3 +- .../infeasible-problem-analysis/report.h | 4 +- .../watched-constraints.h | 41 +++---- .../infeasible-problem-analysis/report.cpp | 13 +-- .../watched-constraints.cpp | 102 ++++++++---------- 6 files changed, 75 insertions(+), 108 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index af8edc3c23..8778b1df14 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -40,16 +40,6 @@ static bool compareSlackSolutions(const MPVariable* a, const MPVariable* b) namespace Antares::Optimization { -ConstraintSlackAnalysis::ConstraintSlackAnalysis() -{ - watchedConstraintTypes_.push_back(std::make_shared()); - watchedConstraintTypes_.push_back(std::make_shared()); - watchedConstraintTypes_.push_back(std::make_shared()); - watchedConstraintTypes_.push_back(std::make_shared()); - watchedConstraintTypes_.push_back(std::make_shared()); - watchedConstraintTypes_.push_back(std::make_shared()); - watchedConstraintTypes_.push_back(std::make_shared()); -} void ConstraintSlackAnalysis::run(MPSolver* problem) { @@ -78,13 +68,7 @@ void ConstraintSlackAnalysis::run(MPSolver* problem) void ConstraintSlackAnalysis::selectConstraintsToWatch(MPSolver* problem) { - std::vector patterns; - std::for_each(watchedConstraintTypes_.begin(), - watchedConstraintTypes_.end(), - [&](auto& c) { patterns.push_back(c->regexId()); }); - std::string constraint_name_pattern{boost::algorithm::join(patterns, "|")}; - - std::regex rgx(constraint_name_pattern); + std::regex rgx = constraintFactory_.regexFilter(); for (MPConstraint* c: problem->constraints()) { if (std::regex_search(c->name(), rgx)) @@ -148,7 +132,7 @@ void ConstraintSlackAnalysis::trimSlackVariables() void ConstraintSlackAnalysis::printReport() const { - InfeasibleProblemReport report(slackVariables_, watchedConstraintTypes_); + InfeasibleProblemReport report(slackVariables_, constraintFactory_); report.logSuspiciousConstraints(); report.logInfeasibilityCauses(); } diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h index ac4d1a9bd8..f2bb19b493 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h @@ -42,7 +42,6 @@ namespace Antares::Optimization class ConstraintSlackAnalysis: public UnfeasibilityAnalysis { public: - ConstraintSlackAnalysis(); ~ConstraintSlackAnalysis() override = default; void run(operations_research::MPSolver* problem) override; @@ -62,7 +61,7 @@ class ConstraintSlackAnalysis: public UnfeasibilityAnalysis std::vector constraintsToWatch_; std::vector slackVariables_; - std::vector> watchedConstraintTypes_; + ConstraintsFactory constraintFactory_; const unsigned int nbMaxSlackVarsToKeep = 10; }; diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h index 1d243700a1..43d54a1509 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h @@ -43,7 +43,7 @@ class InfeasibleProblemReport InfeasibleProblemReport() = delete; explicit InfeasibleProblemReport( const std::vector& slackVariables, - const std::vector>&); + const ConstraintsFactory&); void logSuspiciousConstraints(); void logInfeasibilityCauses(); @@ -51,7 +51,7 @@ class InfeasibleProblemReport void buildConstraintsFromSlackVars(); void filterConstraintsToOneByType(); - const std::vector>& constraintTypes_; + const ConstraintsFactory& constraintsFactory_; const std::vector& slackVariables_; std::vector> constraints_; std::vector> uniqueConstraintByType_; diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index 95f5363abd..7641e5c616 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -4,24 +4,23 @@ #include #include #include +#include namespace Antares::Optimization { class WatchedConstraint { public: - void setConstraintName(std::string constraintName); + WatchedConstraint(std::string constraintName); std::string regexId() const; - virtual std::shared_ptr clone() const = 0; virtual std::string infeasisibity() = 0; virtual std::string infeasisibityCause() = 0; protected: - void setRegexId(std::string name); const std::vector& splitName() const; -private: - std::string name_; +protected: + std::string constraintName_; std::string regexId_; std::vector splitName_; }; @@ -29,8 +28,7 @@ class WatchedConstraint class HourlyBC: public WatchedConstraint { public: - HourlyBC(); - std::shared_ptr clone() const override; + HourlyBC(std::string constraintName); std::string infeasisibity() override; std::string infeasisibityCause() override; }; @@ -38,8 +36,7 @@ class HourlyBC: public WatchedConstraint class DailyBC: public WatchedConstraint { public: - DailyBC(); - std::shared_ptr clone() const override; + DailyBC(std::string constraintName); std::string infeasisibity() override; std::string infeasisibityCause() override; }; @@ -47,8 +44,7 @@ class DailyBC: public WatchedConstraint class WeeklyBC: public WatchedConstraint { public: - WeeklyBC(); - std::shared_ptr clone() const override; + WeeklyBC(std::string constraintName); std::string infeasisibity() override; std::string infeasisibityCause() override; }; @@ -56,8 +52,7 @@ class WeeklyBC: public WatchedConstraint class FictitiousLoad: public WatchedConstraint { public: - FictitiousLoad(); - std::shared_ptr clone() const override; + FictitiousLoad(std::string constraintName); std::string infeasisibity() override; std::string infeasisibityCause() override; }; @@ -65,8 +60,7 @@ class FictitiousLoad: public WatchedConstraint class HydroLevel: public WatchedConstraint { public: - HydroLevel(); - std::shared_ptr clone() const override; + HydroLevel(std::string constraintName); std::string infeasisibity() override; std::string infeasisibityCause() override; }; @@ -74,8 +68,7 @@ class HydroLevel: public WatchedConstraint class STS: public WatchedConstraint { public: - STS(); - std::shared_ptr clone() const override; + STS(std::string constraintName); std::string infeasisibity() override; std::string infeasisibityCause() override; }; @@ -83,9 +76,19 @@ class STS: public WatchedConstraint class HydroProduction: public WatchedConstraint { public: - std::shared_ptr clone() const override; - HydroProduction(); + HydroProduction(std::string constraintName); std::string infeasisibity() override; std::string infeasisibityCause() override; }; + +class ConstraintsFactory +{ +public: + std::shared_ptr create(std::string regexId) const; + std::regex regexFilter(); +private: + const std::vector regex_ids_ = {"::hourly::", "::daily::", "::weekly::", "^FictiveLoads::", + "^AreaHydroLevel::", "^Level::", "^HydroPower::"}; +}; + } // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 35fc283000..8ab7148541 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -29,9 +29,9 @@ namespace Antares::Optimization { InfeasibleProblemReport::InfeasibleProblemReport( const std::vector& slackVariables, - const std::vector>& constraintTypes): + const ConstraintsFactory& factory): slackVariables_(slackVariables), - constraintTypes_(constraintTypes) + constraintsFactory_(factory) { buildConstraintsFromSlackVars(); filterConstraintsToOneByType(); @@ -41,14 +41,7 @@ void InfeasibleProblemReport::buildConstraintsFromSlackVars() { for (const auto& slackVar: slackVariables_) { - for (const auto& cType: constraintTypes_) - { - if (std::regex_search(slackVar->name(), std::regex(cType->regexId()))) - { - constraints_.push_back(cType->clone()); - constraints_.back()->setConstraintName(slackVar->name()); - } - } + constraints_.push_back(constraintsFactory_.create(slackVar->name())); } } diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index c24c2a399e..4b66fda631 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -4,6 +4,7 @@ #include #include #include +#include class StringIsNotWellFormated: public std::runtime_error { @@ -59,10 +60,9 @@ namespace Antares::Optimization // ======================================= // Generic constraint logger // ======================================= -void WatchedConstraint::setConstraintName(std::string name) +WatchedConstraint::WatchedConstraint(std::string name) : constraintName_(name) { - name_ = name; - boost::algorithm::split_regex(splitName_, name_, boost::regex("::")); + boost::algorithm::split_regex(splitName_, constraintName_, boost::regex("::")); } std::string WatchedConstraint::regexId() const @@ -70,11 +70,6 @@ std::string WatchedConstraint::regexId() const return regexId_; } -void WatchedConstraint::setRegexId(std::string regexId) -{ - regexId_ = regexId; -} - const std::vector& WatchedConstraint::splitName() const { return splitName_; @@ -83,14 +78,9 @@ const std::vector& WatchedConstraint::splitName() const // ======================================= // Hourly BC logger // ======================================= -HourlyBC::HourlyBC() +HourlyBC::HourlyBC(std::string constraintName) : WatchedConstraint(constraintName) { - setRegexId("::hourly::"); -} - -std::shared_ptr HourlyBC::clone() const -{ - return std::make_shared(*this); + regexId_ = "::hourly::"; } std::string HourlyBC::infeasisibity() @@ -106,14 +96,9 @@ std::string HourlyBC::infeasisibityCause() // ======================================= // Daily BC logger // ======================================= -DailyBC::DailyBC() -{ - setRegexId("::daily::"); -} - -std::shared_ptr DailyBC::clone() const +DailyBC::DailyBC(std::string constraintName) : WatchedConstraint(constraintName) { - return std::make_shared(*this); + regexId_ = "::daily::"; } std::string DailyBC::infeasisibity() @@ -129,14 +114,9 @@ std::string DailyBC::infeasisibityCause() // ======================================= // Weekly BC constraint // ======================================= -WeeklyBC::WeeklyBC() +WeeklyBC::WeeklyBC(std::string constraintName) : WatchedConstraint(constraintName) { - setRegexId("::weekly::"); -} - -std::shared_ptr WeeklyBC::clone() const -{ - return std::make_shared(*this); + regexId_ = "::weekly::"; } std::string WeeklyBC::infeasisibity() @@ -152,14 +132,9 @@ std::string WeeklyBC::infeasisibityCause() // ======================================= // Fictitious load constraint // ======================================= -FictitiousLoad::FictitiousLoad() -{ - setRegexId("^FictiveLoads::"); -} - -std::shared_ptr FictitiousLoad::clone() const +FictitiousLoad::FictitiousLoad(std::string constraintName) : WatchedConstraint(constraintName) { - return std::make_shared(*this); + regexId_ = "^FictiveLoads::"; } std::string FictitiousLoad::infeasisibity() @@ -176,14 +151,9 @@ std::string FictitiousLoad::infeasisibityCause() // ======================================= // Hydro level constraint // ======================================= -HydroLevel::HydroLevel() +HydroLevel::HydroLevel(std::string constraintName) : WatchedConstraint(constraintName) { - setRegexId("^AreaHydroLevel::"); -} - -std::shared_ptr HydroLevel::clone() const -{ - return std::make_shared(*this); + regexId_ = "^AreaHydroLevel::"; } std::string HydroLevel::infeasisibity() @@ -201,14 +171,9 @@ std::string HydroLevel::infeasisibityCause() // ======================================= // Short term storage constraint // ======================================= -STS::STS() -{ - setRegexId("^Level::"); -} - -std::shared_ptr STS::clone() const +STS::STS(std::string constraintName) : WatchedConstraint(constraintName) { - return std::make_shared(*this); + regexId_ = "^Level::"; } std::string STS::infeasisibity() @@ -226,14 +191,9 @@ std::string STS::infeasisibityCause() // ======================================= // Hydro production constraint // ======================================= -HydroProduction::HydroProduction() +HydroProduction::HydroProduction(std::string constraintName) : WatchedConstraint(constraintName) { - setRegexId("^HydroPower::"); -} - -std::shared_ptr HydroProduction::clone() const -{ - return std::make_shared(*this); + regexId_ = "^HydroPower::"; } std::string HydroProduction::infeasisibity() @@ -245,4 +205,32 @@ std::string HydroProduction::infeasisibityCause() { return "* impossible to generate exactly the weekly hydro target"; } + +// ======================================= +// Constraints factory +// ======================================= +std::shared_ptr ConstraintsFactory::create(std::string varName) const +{ + if (std::regex_search(varName, std::regex("::hourly::"))) + return std::make_shared(varName); + if (std::regex_search(varName, std::regex("::daily::"))) + return std::make_shared(varName); + if (std::regex_search(varName, std::regex("::weekly::"))) + return std::make_shared(varName); + if (std::regex_search(varName, std::regex("^FictiveLoads::"))) + return std::make_shared(varName); + if (std::regex_search(varName, std::regex("^AreaHydroLevel::"))) + return std::make_shared(varName); + if (std::regex_search(varName, std::regex("^Level::"))) + return std::make_shared(varName); + if (std::regex_search(varName, std::regex("^HydroPower::"))) + return std::make_shared(varName); + return nullptr; +} + +std::regex ConstraintsFactory::regexFilter() +{ + return std::regex(boost::algorithm::join(regex_ids_, "|")); +} + } // namespace Antares::Optimization From f8f59b61e217d271c15074a6aaa8e73e23d2b3c8 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Mon, 8 Jul 2024 18:10:18 +0200 Subject: [PATCH 26/78] [skip ci] Make infeasibily more changeable : renaming --- src/solver/infeasible-problem-analysis/report.cpp | 6 +++--- .../infeasible-problem-analysis/watched-constraints.cpp | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 8ab7148541..8344e2ac05 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -47,13 +47,13 @@ void InfeasibleProblemReport::buildConstraintsFromSlackVars() void InfeasibleProblemReport::filterConstraintsToOneByType() { - std::vector typesPicked; + std::vector pickedTypes; for (const auto& c: constraints_) { - if (std::find(typesPicked.begin(), typesPicked.end(), c->regexId()) == typesPicked.end()) + if (std::find(pickedTypes.begin(), pickedTypes.end(), c->regexId()) == pickedTypes.end()) { uniqueConstraintByType_.push_back(c); - typesPicked.push_back(c->regexId()); + pickedTypes.push_back(c->regexId()); } } } diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index 4b66fda631..b609768451 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -4,7 +4,6 @@ #include #include #include -#include class StringIsNotWellFormated: public std::runtime_error { From e1d9e64b36eca629e837144214aaf969ca337af0 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Mon, 8 Jul 2024 18:19:18 +0200 Subject: [PATCH 27/78] Make infeasibily more changeable : clang format --- .../watched-constraints.h | 12 ++++-- .../watched-constraints.cpp | 42 ++++++++++++++----- 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index 7641e5c616..83ec89dba0 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -2,9 +2,9 @@ #pragma once #include +#include #include #include -#include namespace Antares::Optimization { @@ -86,9 +86,15 @@ class ConstraintsFactory public: std::shared_ptr create(std::string regexId) const; std::regex regexFilter(); + private: - const std::vector regex_ids_ = {"::hourly::", "::daily::", "::weekly::", "^FictiveLoads::", - "^AreaHydroLevel::", "^Level::", "^HydroPower::"}; + const std::vector regex_ids_ = {"::hourly::", + "::daily::", + "::weekly::", + "^FictiveLoads::", + "^AreaHydroLevel::", + "^Level::", + "^HydroPower::"}; }; } // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index b609768451..978f995f31 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -59,7 +59,8 @@ namespace Antares::Optimization // ======================================= // Generic constraint logger // ======================================= -WatchedConstraint::WatchedConstraint(std::string name) : constraintName_(name) +WatchedConstraint::WatchedConstraint(std::string name): + constraintName_(name) { boost::algorithm::split_regex(splitName_, constraintName_, boost::regex("::")); } @@ -77,7 +78,8 @@ const std::vector& WatchedConstraint::splitName() const // ======================================= // Hourly BC logger // ======================================= -HourlyBC::HourlyBC(std::string constraintName) : WatchedConstraint(constraintName) +HourlyBC::HourlyBC(std::string constraintName): + WatchedConstraint(constraintName) { regexId_ = "::hourly::"; } @@ -95,7 +97,8 @@ std::string HourlyBC::infeasisibityCause() // ======================================= // Daily BC logger // ======================================= -DailyBC::DailyBC(std::string constraintName) : WatchedConstraint(constraintName) +DailyBC::DailyBC(std::string constraintName): + WatchedConstraint(constraintName) { regexId_ = "::daily::"; } @@ -113,7 +116,8 @@ std::string DailyBC::infeasisibityCause() // ======================================= // Weekly BC constraint // ======================================= -WeeklyBC::WeeklyBC(std::string constraintName) : WatchedConstraint(constraintName) +WeeklyBC::WeeklyBC(std::string constraintName): + WatchedConstraint(constraintName) { regexId_ = "::weekly::"; } @@ -131,7 +135,8 @@ std::string WeeklyBC::infeasisibityCause() // ======================================= // Fictitious load constraint // ======================================= -FictitiousLoad::FictitiousLoad(std::string constraintName) : WatchedConstraint(constraintName) +FictitiousLoad::FictitiousLoad(std::string constraintName): + WatchedConstraint(constraintName) { regexId_ = "^FictiveLoads::"; } @@ -150,7 +155,8 @@ std::string FictitiousLoad::infeasisibityCause() // ======================================= // Hydro level constraint // ======================================= -HydroLevel::HydroLevel(std::string constraintName) : WatchedConstraint(constraintName) +HydroLevel::HydroLevel(std::string constraintName): + WatchedConstraint(constraintName) { regexId_ = "^AreaHydroLevel::"; } @@ -170,15 +176,16 @@ std::string HydroLevel::infeasisibityCause() // ======================================= // Short term storage constraint // ======================================= -STS::STS(std::string constraintName) : WatchedConstraint(constraintName) +STS::STS(std::string constraintName): + WatchedConstraint(constraintName) { regexId_ = "^Level::"; } std::string STS::infeasisibity() { - return "Short-term-storage reservoir constraint at area '" + areaName(splitName()) + "' in STS '" - + STSname(splitName()) + "' at hour " + timeStep(splitName()); + return "Short-term-storage reservoir constraint at area '" + areaName(splitName()) + + "' in STS '" + STSname(splitName()) + "' at hour " + timeStep(splitName()); } std::string STS::infeasisibityCause() @@ -190,7 +197,8 @@ std::string STS::infeasisibityCause() // ======================================= // Hydro production constraint // ======================================= -HydroProduction::HydroProduction(std::string constraintName) : WatchedConstraint(constraintName) +HydroProduction::HydroProduction(std::string constraintName): + WatchedConstraint(constraintName) { regexId_ = "^HydroPower::"; } @@ -211,19 +219,33 @@ std::string HydroProduction::infeasisibityCause() std::shared_ptr ConstraintsFactory::create(std::string varName) const { if (std::regex_search(varName, std::regex("::hourly::"))) + { return std::make_shared(varName); + } if (std::regex_search(varName, std::regex("::daily::"))) + { return std::make_shared(varName); + } if (std::regex_search(varName, std::regex("::weekly::"))) + { return std::make_shared(varName); + } if (std::regex_search(varName, std::regex("^FictiveLoads::"))) + { return std::make_shared(varName); + } if (std::regex_search(varName, std::regex("^AreaHydroLevel::"))) + { return std::make_shared(varName); + } if (std::regex_search(varName, std::regex("^Level::"))) + { return std::make_shared(varName); + } if (std::regex_search(varName, std::regex("^HydroPower::"))) + { return std::make_shared(varName); + } return nullptr; } From cda782ac626ae44dd84b242aeba1bc6743f22dcd Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 9 Jul 2024 09:56:16 +0200 Subject: [PATCH 28/78] Make infeasibily more changeable : avoid useless data member + avoid passing constraint factory --- .../constraint-slack-analysis.cpp | 5 +++-- .../constraint-slack-analysis.h | 1 - .../solver/infeasible-problem-analysis/report.h | 7 ++----- .../watched-constraints.h | 2 +- src/solver/infeasible-problem-analysis/report.cpp | 14 ++++++-------- .../watched-constraints.cpp | 2 +- 6 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index 8778b1df14..d962af17aa 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -68,7 +68,8 @@ void ConstraintSlackAnalysis::run(MPSolver* problem) void ConstraintSlackAnalysis::selectConstraintsToWatch(MPSolver* problem) { - std::regex rgx = constraintFactory_.regexFilter(); + ConstraintsFactory factory; + std::regex rgx = factory.constraintsFilter(); for (MPConstraint* c: problem->constraints()) { if (std::regex_search(c->name(), rgx)) @@ -132,7 +133,7 @@ void ConstraintSlackAnalysis::trimSlackVariables() void ConstraintSlackAnalysis::printReport() const { - InfeasibleProblemReport report(slackVariables_, constraintFactory_); + InfeasibleProblemReport report(slackVariables_); report.logSuspiciousConstraints(); report.logInfeasibilityCauses(); } diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h index f2bb19b493..cfb6fccdf4 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h @@ -61,7 +61,6 @@ class ConstraintSlackAnalysis: public UnfeasibilityAnalysis std::vector constraintsToWatch_; std::vector slackVariables_; - ConstraintsFactory constraintFactory_; const unsigned int nbMaxSlackVarsToKeep = 10; }; diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h index 43d54a1509..5152037523 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h @@ -42,17 +42,14 @@ class InfeasibleProblemReport public: InfeasibleProblemReport() = delete; explicit InfeasibleProblemReport( - const std::vector& slackVariables, - const ConstraintsFactory&); + const std::vector&); void logSuspiciousConstraints(); void logInfeasibilityCauses(); private: - void buildConstraintsFromSlackVars(); + void buildConstraintsFromSlackVars(const std::vector&); void filterConstraintsToOneByType(); - const ConstraintsFactory& constraintsFactory_; - const std::vector& slackVariables_; std::vector> constraints_; std::vector> uniqueConstraintByType_; }; diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index 83ec89dba0..77a393ab3c 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -85,7 +85,7 @@ class ConstraintsFactory { public: std::shared_ptr create(std::string regexId) const; - std::regex regexFilter(); + std::regex constraintsFilter(); private: const std::vector regex_ids_ = {"::hourly::", diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 8344e2ac05..a2724ae143 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -28,20 +28,18 @@ namespace Antares::Optimization { InfeasibleProblemReport::InfeasibleProblemReport( - const std::vector& slackVariables, - const ConstraintsFactory& factory): - slackVariables_(slackVariables), - constraintsFactory_(factory) + const std::vector& slackVariables) { - buildConstraintsFromSlackVars(); + buildConstraintsFromSlackVars(slackVariables); filterConstraintsToOneByType(); } -void InfeasibleProblemReport::buildConstraintsFromSlackVars() +void InfeasibleProblemReport::buildConstraintsFromSlackVars(const std::vector& slackVariables) { - for (const auto& slackVar: slackVariables_) + const ConstraintsFactory constraintsFactory; + for (const auto& slackVar: slackVariables) { - constraints_.push_back(constraintsFactory_.create(slackVar->name())); + constraints_.push_back(constraintsFactory.create(slackVar->name())); } } diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index 978f995f31..94e3bec3aa 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -249,7 +249,7 @@ std::shared_ptr ConstraintsFactory::create(std::string varNam return nullptr; } -std::regex ConstraintsFactory::regexFilter() +std::regex ConstraintsFactory::constraintsFilter() { return std::regex(boost::algorithm::join(regex_ids_, "|")); } From 436da64429ed9ea3873e3bb62d0ce82d0eb72516 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 9 Jul 2024 10:01:48 +0200 Subject: [PATCH 29/78] [skip ci] Make infeasibily more changeable : correct function naming --- .../watched-constraints.h | 32 +++++++++---------- .../infeasible-problem-analysis/report.cpp | 4 +-- .../watched-constraints.cpp | 28 ++++++++-------- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index 77a393ab3c..f3280e8ca2 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -13,8 +13,8 @@ class WatchedConstraint public: WatchedConstraint(std::string constraintName); std::string regexId() const; - virtual std::string infeasisibity() = 0; - virtual std::string infeasisibityCause() = 0; + virtual std::string infeasibility() = 0; + virtual std::string infeasibilityCause() = 0; protected: const std::vector& splitName() const; @@ -29,56 +29,56 @@ class HourlyBC: public WatchedConstraint { public: HourlyBC(std::string constraintName); - std::string infeasisibity() override; - std::string infeasisibityCause() override; + std::string infeasibility() override; + std::string infeasibilityCause() override; }; class DailyBC: public WatchedConstraint { public: DailyBC(std::string constraintName); - std::string infeasisibity() override; - std::string infeasisibityCause() override; + std::string infeasibility() override; + std::string infeasibilityCause() override; }; class WeeklyBC: public WatchedConstraint { public: WeeklyBC(std::string constraintName); - std::string infeasisibity() override; - std::string infeasisibityCause() override; + std::string infeasibility() override; + std::string infeasibilityCause() override; }; class FictitiousLoad: public WatchedConstraint { public: FictitiousLoad(std::string constraintName); - std::string infeasisibity() override; - std::string infeasisibityCause() override; + std::string infeasibility() override; + std::string infeasibilityCause() override; }; class HydroLevel: public WatchedConstraint { public: HydroLevel(std::string constraintName); - std::string infeasisibity() override; - std::string infeasisibityCause() override; + std::string infeasibility() override; + std::string infeasibilityCause() override; }; class STS: public WatchedConstraint { public: STS(std::string constraintName); - std::string infeasisibity() override; - std::string infeasisibityCause() override; + std::string infeasibility() override; + std::string infeasibilityCause() override; }; class HydroProduction: public WatchedConstraint { public: HydroProduction(std::string constraintName); - std::string infeasisibity() override; - std::string infeasisibityCause() override; + std::string infeasibility() override; + std::string infeasibilityCause() override; }; class ConstraintsFactory diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index a2724ae143..1a593ba41e 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -60,7 +60,7 @@ void InfeasibleProblemReport::logSuspiciousConstraints() { for (const auto& c: constraints_) { - Antares::logs.error() << c->infeasisibity(); + Antares::logs.error() << c->infeasibility(); } } @@ -69,7 +69,7 @@ void InfeasibleProblemReport::logInfeasibilityCauses() Antares::logs.error() << "Possible causes of infeasibility:"; for (const auto& c: uniqueConstraintByType_) { - Antares::logs.error() << c->infeasisibityCause(); + Antares::logs.error() << c->infeasibilityCause(); } } diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index 94e3bec3aa..9edf0210f8 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -84,12 +84,12 @@ HourlyBC::HourlyBC(std::string constraintName): regexId_ = "::hourly::"; } -std::string HourlyBC::infeasisibity() +std::string HourlyBC::infeasibility() { return "Hourly BC '" + shortName(splitName()) + "' at hour " + timeStep(splitName()); } -std::string HourlyBC::infeasisibityCause() +std::string HourlyBC::infeasibilityCause() { return "* Hourly binding constraints."; } @@ -103,12 +103,12 @@ DailyBC::DailyBC(std::string constraintName): regexId_ = "::daily::"; } -std::string DailyBC::infeasisibity() +std::string DailyBC::infeasibility() { return "Daily BC '" + shortName(splitName()) + "' at day " + timeStep(splitName()); } -std::string DailyBC::infeasisibityCause() +std::string DailyBC::infeasibilityCause() { return "* Daily binding constraints,"; } @@ -122,12 +122,12 @@ WeeklyBC::WeeklyBC(std::string constraintName): regexId_ = "::weekly::"; } -std::string WeeklyBC::infeasisibity() +std::string WeeklyBC::infeasibility() { return "Weekly BC '" + shortName(splitName()); } -std::string WeeklyBC::infeasisibityCause() +std::string WeeklyBC::infeasibilityCause() { return "* Weekly binding constraints."; } @@ -141,13 +141,13 @@ FictitiousLoad::FictitiousLoad(std::string constraintName): regexId_ = "^FictiveLoads::"; } -std::string FictitiousLoad::infeasisibity() +std::string FictitiousLoad::infeasibility() { return "Last resort shedding status at area '" + areaName(splitName()) + "' at hour " + timeStep(splitName()); } -std::string FictitiousLoad::infeasisibityCause() +std::string FictitiousLoad::infeasibilityCause() { return "* Last resort shedding status."; } @@ -161,13 +161,13 @@ HydroLevel::HydroLevel(std::string constraintName): regexId_ = "^AreaHydroLevel::"; } -std::string HydroLevel::infeasisibity() +std::string HydroLevel::infeasibility() { return "Hydro level constraint at area '" + areaName(splitName()) + "' at hour " + timeStep(splitName()); } -std::string HydroLevel::infeasisibityCause() +std::string HydroLevel::infeasibilityCause() { return "* Hydro reservoir impossible to manage with cumulative options " "\"hard bounds without heuristic\""; @@ -182,13 +182,13 @@ STS::STS(std::string constraintName): regexId_ = "^Level::"; } -std::string STS::infeasisibity() +std::string STS::infeasibility() { return "Short-term-storage reservoir constraint at area '" + areaName(splitName()) + "' in STS '" + STSname(splitName()) + "' at hour " + timeStep(splitName()); } -std::string STS::infeasisibityCause() +std::string STS::infeasibilityCause() { return "* Short-term storage reservoir level impossible to manage. Please check inflows, " "lower & upper curves and initial level (if prescribed),"; @@ -203,12 +203,12 @@ HydroProduction::HydroProduction(std::string constraintName): regexId_ = "^HydroPower::"; } -std::string HydroProduction::infeasisibity() +std::string HydroProduction::infeasibility() { return "Hydro weekly production at area '" + areaName(splitName()) + "'"; } -std::string HydroProduction::infeasisibityCause() +std::string HydroProduction::infeasibilityCause() { return "* impossible to generate exactly the weekly hydro target"; } From 10491bc967654a4d123716ec27519f51b77bd5a1 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 9 Jul 2024 11:42:42 +0200 Subject: [PATCH 30/78] Make infeasibility more changeable : simplify constraint factory --- .../watched-constraints.h | 12 ++- .../watched-constraints.cpp | 77 ++++++++++++------- 2 files changed, 55 insertions(+), 34 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index f3280e8ca2..858b811467 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -5,6 +5,8 @@ #include #include #include +#include +#include namespace Antares::Optimization { @@ -84,17 +86,13 @@ class HydroProduction: public WatchedConstraint class ConstraintsFactory { public: + ConstraintsFactory(); std::shared_ptr create(std::string regexId) const; std::regex constraintsFilter(); private: - const std::vector regex_ids_ = {"::hourly::", - "::daily::", - "::weekly::", - "^FictiveLoads::", - "^AreaHydroLevel::", - "^Level::", - "^HydroPower::"}; + std::map(std::string)>> regex_to_constraints_; + std::vector regex_ids_; }; } // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index 9edf0210f8..aca7c4eba8 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -4,6 +4,7 @@ #include #include #include +#include class StringIsNotWellFormated: public std::runtime_error { @@ -216,37 +217,59 @@ std::string HydroProduction::infeasibilityCause() // ======================================= // Constraints factory // ======================================= +std::shared_ptr createHourlyBC(std::string varName) +{ + return std::make_shared(varName); +} +std::shared_ptr createDailyBC(std::string varName) +{ + return std::make_shared(varName); +} +std::shared_ptr createWeeklyBC(std::string varName) +{ + return std::make_shared(varName); +} +std::shared_ptr createFictitiousLoad(std::string varName) +{ + return std::make_shared(varName); +} +std::shared_ptr createHydroLevel(std::string varName) +{ + return std::make_shared(varName); +} +std::shared_ptr createSTS(std::string varName) +{ + return std::make_shared(varName); +} +std::shared_ptr createHydroProduction(std::string varName) +{ + return std::make_shared(varName); +} + + +ConstraintsFactory::ConstraintsFactory() +{ + regex_to_constraints_["::hourly::"] = createHourlyBC; + regex_to_constraints_["::daily::"] = createDailyBC; + regex_to_constraints_["::weekly::"] = createWeeklyBC; + regex_to_constraints_["^FictiveLoads::"] = createFictitiousLoad; + regex_to_constraints_["^AreaHydroLevel::"] = createHydroLevel; + regex_to_constraints_["^Level::"] = createSTS; + regex_to_constraints_["^HydroPower::"] = createHydroProduction; + + auto keyView = std::views::keys(regex_to_constraints_); + regex_ids_ = { keyView.begin(), keyView.end() }; +} + std::shared_ptr ConstraintsFactory::create(std::string varName) const { - if (std::regex_search(varName, std::regex("::hourly::"))) - { - return std::make_shared(varName); - } - if (std::regex_search(varName, std::regex("::daily::"))) - { - return std::make_shared(varName); - } - if (std::regex_search(varName, std::regex("::weekly::"))) - { - return std::make_shared(varName); - } - if (std::regex_search(varName, std::regex("^FictiveLoads::"))) - { - return std::make_shared(varName); - } - if (std::regex_search(varName, std::regex("^AreaHydroLevel::"))) - { - return std::make_shared(varName); - } - if (std::regex_search(varName, std::regex("^Level::"))) - { - return std::make_shared(varName); - } - if (std::regex_search(varName, std::regex("^HydroPower::"))) + for (auto& [pattern, createFunction]: regex_to_constraints_) { - return std::make_shared(varName); + if (std::regex_search(varName, std::regex(pattern))) + { + return createFunction(varName); + } } - return nullptr; } std::regex ConstraintsFactory::constraintsFilter() From d74212d0ff7dcc9363a67d00a5bebbd41b85df9f Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 9 Jul 2024 11:59:00 +0200 Subject: [PATCH 31/78] Make infeasibility more changeable : simplifying constraint classes --- .../watched-constraints.h | 2 -- src/solver/infeasible-problem-analysis/report.cpp | 4 ++-- .../watched-constraints.cpp | 12 ------------ 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index 858b811467..671299acec 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -14,7 +14,6 @@ class WatchedConstraint { public: WatchedConstraint(std::string constraintName); - std::string regexId() const; virtual std::string infeasibility() = 0; virtual std::string infeasibilityCause() = 0; @@ -23,7 +22,6 @@ class WatchedConstraint protected: std::string constraintName_; - std::string regexId_; std::vector splitName_; }; diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 1a593ba41e..fe1a196f04 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -48,10 +48,10 @@ void InfeasibleProblemReport::filterConstraintsToOneByType() std::vector pickedTypes; for (const auto& c: constraints_) { - if (std::find(pickedTypes.begin(), pickedTypes.end(), c->regexId()) == pickedTypes.end()) + if (std::find(pickedTypes.begin(), pickedTypes.end(), typeid(c).name()) == pickedTypes.end()) { uniqueConstraintByType_.push_back(c); - pickedTypes.push_back(c->regexId()); + pickedTypes.push_back(typeid(c).name()); } } } diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index aca7c4eba8..eecd8bf8eb 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -66,11 +66,6 @@ WatchedConstraint::WatchedConstraint(std::string name): boost::algorithm::split_regex(splitName_, constraintName_, boost::regex("::")); } -std::string WatchedConstraint::regexId() const -{ - return regexId_; -} - const std::vector& WatchedConstraint::splitName() const { return splitName_; @@ -82,7 +77,6 @@ const std::vector& WatchedConstraint::splitName() const HourlyBC::HourlyBC(std::string constraintName): WatchedConstraint(constraintName) { - regexId_ = "::hourly::"; } std::string HourlyBC::infeasibility() @@ -101,7 +95,6 @@ std::string HourlyBC::infeasibilityCause() DailyBC::DailyBC(std::string constraintName): WatchedConstraint(constraintName) { - regexId_ = "::daily::"; } std::string DailyBC::infeasibility() @@ -120,7 +113,6 @@ std::string DailyBC::infeasibilityCause() WeeklyBC::WeeklyBC(std::string constraintName): WatchedConstraint(constraintName) { - regexId_ = "::weekly::"; } std::string WeeklyBC::infeasibility() @@ -139,7 +131,6 @@ std::string WeeklyBC::infeasibilityCause() FictitiousLoad::FictitiousLoad(std::string constraintName): WatchedConstraint(constraintName) { - regexId_ = "^FictiveLoads::"; } std::string FictitiousLoad::infeasibility() @@ -159,7 +150,6 @@ std::string FictitiousLoad::infeasibilityCause() HydroLevel::HydroLevel(std::string constraintName): WatchedConstraint(constraintName) { - regexId_ = "^AreaHydroLevel::"; } std::string HydroLevel::infeasibility() @@ -180,7 +170,6 @@ std::string HydroLevel::infeasibilityCause() STS::STS(std::string constraintName): WatchedConstraint(constraintName) { - regexId_ = "^Level::"; } std::string STS::infeasibility() @@ -201,7 +190,6 @@ std::string STS::infeasibilityCause() HydroProduction::HydroProduction(std::string constraintName): WatchedConstraint(constraintName) { - regexId_ = "^HydroPower::"; } std::string HydroProduction::infeasibility() From fb6b7c0911bb2892dc60eaccaf43db0857340805 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 9 Jul 2024 12:12:16 +0200 Subject: [PATCH 32/78] Make infeasibility more changeable : fix compilation error on Linux + clang format --- .../solver/infeasible-problem-analysis/report.h | 3 +-- .../watched-constraints.h | 7 ++++--- src/solver/infeasible-problem-analysis/report.cpp | 8 +++++--- .../watched-constraints.cpp | 13 ++++++++++--- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h index 5152037523..bf9dc27025 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h @@ -41,8 +41,7 @@ class InfeasibleProblemReport { public: InfeasibleProblemReport() = delete; - explicit InfeasibleProblemReport( - const std::vector&); + explicit InfeasibleProblemReport(const std::vector&); void logSuspiciousConstraints(); void logInfeasibilityCauses(); diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index 671299acec..9368217961 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -1,12 +1,12 @@ #pragma once +#include +#include #include #include #include #include -#include -#include namespace Antares::Optimization { @@ -89,7 +89,8 @@ class ConstraintsFactory std::regex constraintsFilter(); private: - std::map(std::string)>> regex_to_constraints_; + std::map(std::string)>> + regex_to_constraints_; std::vector regex_ids_; }; diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index fe1a196f04..c06d372901 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -34,7 +34,8 @@ InfeasibleProblemReport::InfeasibleProblemReport( filterConstraintsToOneByType(); } -void InfeasibleProblemReport::buildConstraintsFromSlackVars(const std::vector& slackVariables) +void InfeasibleProblemReport::buildConstraintsFromSlackVars( + const std::vector& slackVariables) { const ConstraintsFactory constraintsFactory; for (const auto& slackVar: slackVariables) @@ -48,10 +49,11 @@ void InfeasibleProblemReport::filterConstraintsToOneByType() std::vector pickedTypes; for (const auto& c: constraints_) { - if (std::find(pickedTypes.begin(), pickedTypes.end(), typeid(c).name()) == pickedTypes.end()) + std::string cType = typeid(*c).name(); + if (std::find(pickedTypes.begin(), pickedTypes.end(), cType) == pickedTypes.end()) { uniqueConstraintByType_.push_back(c); - pickedTypes.push_back(typeid(c).name()); + pickedTypes.push_back(cType); } } } diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index eecd8bf8eb..70f95577a0 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -1,10 +1,11 @@ #include "antares/solver/infeasible-problem-analysis/watched-constraints.h" +#include + #include #include #include -#include class StringIsNotWellFormated: public std::runtime_error { @@ -209,32 +210,37 @@ std::shared_ptr createHourlyBC(std::string varName) { return std::make_shared(varName); } + std::shared_ptr createDailyBC(std::string varName) { return std::make_shared(varName); } + std::shared_ptr createWeeklyBC(std::string varName) { return std::make_shared(varName); } + std::shared_ptr createFictitiousLoad(std::string varName) { return std::make_shared(varName); } + std::shared_ptr createHydroLevel(std::string varName) { return std::make_shared(varName); } + std::shared_ptr createSTS(std::string varName) { return std::make_shared(varName); } + std::shared_ptr createHydroProduction(std::string varName) { return std::make_shared(varName); } - ConstraintsFactory::ConstraintsFactory() { regex_to_constraints_["::hourly::"] = createHourlyBC; @@ -246,7 +252,7 @@ ConstraintsFactory::ConstraintsFactory() regex_to_constraints_["^HydroPower::"] = createHydroProduction; auto keyView = std::views::keys(regex_to_constraints_); - regex_ids_ = { keyView.begin(), keyView.end() }; + regex_ids_ = {keyView.begin(), keyView.end()}; } std::shared_ptr ConstraintsFactory::create(std::string varName) const @@ -258,6 +264,7 @@ std::shared_ptr ConstraintsFactory::create(std::string varNam return createFunction(varName); } } + return nullptr; // Cannot happen } std::regex ConstraintsFactory::constraintsFilter() From 288b85e14b6abd6bb39ca9e875eb81bf2bc00260 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 9 Jul 2024 12:18:04 +0200 Subject: [PATCH 33/78] [skip ci] Make infeasibility more changeable ; very small change --- src/solver/infeasible-problem-analysis/watched-constraints.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index 70f95577a0..bfa5111b37 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -2,7 +2,6 @@ #include "antares/solver/infeasible-problem-analysis/watched-constraints.h" #include - #include #include #include From ddc6b1dd1769ccc855861410409a881704c91eb4 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 9 Jul 2024 14:49:39 +0200 Subject: [PATCH 34/78] Make infeasibility more changeable : use a std algorithm instead of a for loop --- .../watched-constraints.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index bfa5111b37..d44703c485 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -256,14 +256,11 @@ ConstraintsFactory::ConstraintsFactory() std::shared_ptr ConstraintsFactory::create(std::string varName) const { - for (auto& [pattern, createFunction]: regex_to_constraints_) - { - if (std::regex_search(varName, std::regex(pattern))) - { - return createFunction(varName); - } - } - return nullptr; // Cannot happen + return std::find_if(regex_to_constraints_.begin(), + regex_to_constraints_.end(), + [&varName](auto& p) + { return std::regex_search(varName, std::regex(p.first)); }) + ->second(varName); } std::regex ConstraintsFactory::constraintsFilter() From 304836e514daae3c98a3d63272fa05f483b48a6e Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 9 Jul 2024 14:53:47 +0200 Subject: [PATCH 35/78] [skip ci] Make infeasibility more changeable : renaming --- .../watched-constraints.h | 2 +- .../watched-constraints.cpp | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index 9368217961..60c6ed01ec 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -90,7 +90,7 @@ class ConstraintsFactory private: std::map(std::string)>> - regex_to_constraints_; + regex_to_ctypes_; std::vector regex_ids_; }; diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index d44703c485..18239adf07 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -242,22 +242,22 @@ std::shared_ptr createHydroProduction(std::string varName) ConstraintsFactory::ConstraintsFactory() { - regex_to_constraints_["::hourly::"] = createHourlyBC; - regex_to_constraints_["::daily::"] = createDailyBC; - regex_to_constraints_["::weekly::"] = createWeeklyBC; - regex_to_constraints_["^FictiveLoads::"] = createFictitiousLoad; - regex_to_constraints_["^AreaHydroLevel::"] = createHydroLevel; - regex_to_constraints_["^Level::"] = createSTS; - regex_to_constraints_["^HydroPower::"] = createHydroProduction; - - auto keyView = std::views::keys(regex_to_constraints_); + regex_to_ctypes_["::hourly::"] = createHourlyBC; + regex_to_ctypes_["::daily::"] = createDailyBC; + regex_to_ctypes_["::weekly::"] = createWeeklyBC; + regex_to_ctypes_["^FictiveLoads::"] = createFictitiousLoad; + regex_to_ctypes_["^AreaHydroLevel::"] = createHydroLevel; + regex_to_ctypes_["^Level::"] = createSTS; + regex_to_ctypes_["^HydroPower::"] = createHydroProduction; + + auto keyView = std::views::keys(regex_to_ctypes_); regex_ids_ = {keyView.begin(), keyView.end()}; } std::shared_ptr ConstraintsFactory::create(std::string varName) const { - return std::find_if(regex_to_constraints_.begin(), - regex_to_constraints_.end(), + return std::find_if(regex_to_ctypes_.begin(), + regex_to_ctypes_.end(), [&varName](auto& p) { return std::regex_search(varName, std::regex(p.first)); }) ->second(varName); From 45b778c584e7fdf69c5edd7fd94c4b766c799947 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 9 Jul 2024 17:24:13 +0200 Subject: [PATCH 36/78] Make infeasibility more changeable : simplify constraint classes yet again --- .../watched-constraints.h | 14 ++-- .../watched-constraints.cpp | 70 +++---------------- .../test-unfeasible-problem-analyzer.cpp | 33 +++++---- 3 files changed, 33 insertions(+), 84 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index 60c6ed01ec..868de701c2 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -27,56 +27,56 @@ class WatchedConstraint class HourlyBC: public WatchedConstraint { + using WatchedConstraint::WatchedConstraint; public: - HourlyBC(std::string constraintName); std::string infeasibility() override; std::string infeasibilityCause() override; }; class DailyBC: public WatchedConstraint { + using WatchedConstraint::WatchedConstraint; public: - DailyBC(std::string constraintName); std::string infeasibility() override; std::string infeasibilityCause() override; }; class WeeklyBC: public WatchedConstraint { + using WatchedConstraint::WatchedConstraint; public: - WeeklyBC(std::string constraintName); std::string infeasibility() override; std::string infeasibilityCause() override; }; class FictitiousLoad: public WatchedConstraint { + using WatchedConstraint::WatchedConstraint; public: - FictitiousLoad(std::string constraintName); std::string infeasibility() override; std::string infeasibilityCause() override; }; class HydroLevel: public WatchedConstraint { + using WatchedConstraint::WatchedConstraint; public: - HydroLevel(std::string constraintName); std::string infeasibility() override; std::string infeasibilityCause() override; }; class STS: public WatchedConstraint { + using WatchedConstraint::WatchedConstraint; public: - STS(std::string constraintName); std::string infeasibility() override; std::string infeasibilityCause() override; }; class HydroProduction: public WatchedConstraint { + using WatchedConstraint::WatchedConstraint; public: - HydroProduction(std::string constraintName); std::string infeasibility() override; std::string infeasibilityCause() override; }; diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index 18239adf07..a6000a2328 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -57,9 +57,7 @@ std::string STSname(std::vector splitName) namespace Antares::Optimization { -// ======================================= -// Generic constraint logger -// ======================================= +// --- Generic constraint --- WatchedConstraint::WatchedConstraint(std::string name): constraintName_(name) { @@ -71,14 +69,6 @@ const std::vector& WatchedConstraint::splitName() const return splitName_; } -// ======================================= -// Hourly BC logger -// ======================================= -HourlyBC::HourlyBC(std::string constraintName): - WatchedConstraint(constraintName) -{ -} - std::string HourlyBC::infeasibility() { return "Hourly BC '" + shortName(splitName()) + "' at hour " + timeStep(splitName()); @@ -89,14 +79,7 @@ std::string HourlyBC::infeasibilityCause() return "* Hourly binding constraints."; } -// ======================================= -// Daily BC logger -// ======================================= -DailyBC::DailyBC(std::string constraintName): - WatchedConstraint(constraintName) -{ -} - +// --- Daily BC constraint --- std::string DailyBC::infeasibility() { return "Daily BC '" + shortName(splitName()) + "' at day " + timeStep(splitName()); @@ -107,14 +90,7 @@ std::string DailyBC::infeasibilityCause() return "* Daily binding constraints,"; } -// ======================================= -// Weekly BC constraint -// ======================================= -WeeklyBC::WeeklyBC(std::string constraintName): - WatchedConstraint(constraintName) -{ -} - +// --- Weekly BC constraint --- std::string WeeklyBC::infeasibility() { return "Weekly BC '" + shortName(splitName()); @@ -125,14 +101,7 @@ std::string WeeklyBC::infeasibilityCause() return "* Weekly binding constraints."; } -// ======================================= -// Fictitious load constraint -// ======================================= -FictitiousLoad::FictitiousLoad(std::string constraintName): - WatchedConstraint(constraintName) -{ -} - +// --- Fictitious load constraint --- std::string FictitiousLoad::infeasibility() { return "Last resort shedding status at area '" + areaName(splitName()) + "' at hour " @@ -144,14 +113,7 @@ std::string FictitiousLoad::infeasibilityCause() return "* Last resort shedding status."; } -// ======================================= -// Hydro level constraint -// ======================================= -HydroLevel::HydroLevel(std::string constraintName): - WatchedConstraint(constraintName) -{ -} - +// --- Hydro level constraint --- std::string HydroLevel::infeasibility() { return "Hydro level constraint at area '" + areaName(splitName()) + "' at hour " @@ -164,14 +126,7 @@ std::string HydroLevel::infeasibilityCause() "\"hard bounds without heuristic\""; } -// ======================================= -// Short term storage constraint -// ======================================= -STS::STS(std::string constraintName): - WatchedConstraint(constraintName) -{ -} - +// --- Short term storage constraint --- std::string STS::infeasibility() { return "Short-term-storage reservoir constraint at area '" + areaName(splitName()) @@ -184,14 +139,7 @@ std::string STS::infeasibilityCause() "lower & upper curves and initial level (if prescribed),"; } -// ======================================= -// Hydro production constraint -// ======================================= -HydroProduction::HydroProduction(std::string constraintName): - WatchedConstraint(constraintName) -{ -} - +// --- Hydro production constraint --- std::string HydroProduction::infeasibility() { return "Hydro weekly production at area '" + areaName(splitName()) + "'"; @@ -202,9 +150,7 @@ std::string HydroProduction::infeasibilityCause() return "* impossible to generate exactly the weekly hydro target"; } -// ======================================= -// Constraints factory -// ======================================= +// --- Constraints factory --- std::shared_ptr createHourlyBC(std::string varName) { return std::make_shared(varName); diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index 8d960f7381..6b132cba79 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -135,11 +135,12 @@ BOOST_AUTO_TEST_CASE(analysis_should_detect_inconsistent_variable_bounds) /*! * Creates a problem with 2 variables linked by 1 constraint: * - Variable 1 must be greater than 1 - * - Variable 2 must be lesser than -1 + * - Variable 2 must be smaller than -1 * - but if feasible is false, constraint enforces that variable 2 is greater than variable 1 --> * infeasible */ -std::unique_ptr createProblem(const std::string& constraintName, bool feasible) + +std::unique_ptr createProblem(const std::string& constraintName) { std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); const double infinity = problem->infinity(); @@ -147,27 +148,29 @@ std::unique_ptr createProblem(const std::string& constraintName, bool auto var2 = problem->MakeNumVar(-infinity, -1, "var2"); auto constraint = problem->MakeRowConstraint(constraintName); constraint->SetBounds(0, infinity); - if (feasible) - { - constraint->SetCoefficient(var1, 1); - constraint->SetCoefficient(var2, -1); - } - else - { - constraint->SetCoefficient(var1, -1); - constraint->SetCoefficient(var2, 1); - } return problem; } std::unique_ptr createFeasibleProblem(const std::string& constraintName) { - return createProblem(constraintName, true); + auto problem = createProblem(constraintName); + auto constraint = problem->LookupConstraintOrNull(constraintName); + auto var1 = problem->LookupVariableOrNull("var1"); + auto var2 = problem->LookupVariableOrNull("var2"); + constraint->SetCoefficient(var1, 1); + constraint->SetCoefficient(var2, -1); + return problem; } std::unique_ptr createUnfeasibleProblem(const std::string& constraintName) { - return createProblem(constraintName, false); + auto problem = createProblem(constraintName); + auto constraint = problem->LookupConstraintOrNull(constraintName); + auto var1 = problem->LookupVariableOrNull("var1"); + auto var2 = problem->LookupVariableOrNull("var2"); + constraint->SetCoefficient(var1, -1); + constraint->SetCoefficient(var2, 1); + return problem; } static const std::string validConstraintNames[] = { @@ -212,4 +215,4 @@ BOOST_AUTO_TEST_CASE(analysis_should_ignore_feasible_constraints) BOOST_CHECK(analysis.hasDetectedInfeasibilityCause()); // Would expect false here instead? } -BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file From 45e53dbaf76b4833ab0468b8f0f6c0cece642723 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 9 Jul 2024 18:22:59 +0200 Subject: [PATCH 37/78] Make infeasibility more changeable : replace a loop with the use of std::copy_if --- .../constraint-slack-analysis.cpp | 11 ++++------- .../test-unfeasible-problem-analyzer.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index d962af17aa..cd4016aa16 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -70,13 +70,10 @@ void ConstraintSlackAnalysis::selectConstraintsToWatch(MPSolver* problem) { ConstraintsFactory factory; std::regex rgx = factory.constraintsFilter(); - for (MPConstraint* c: problem->constraints()) - { - if (std::regex_search(c->name(), rgx)) - { - constraintsToWatch_.push_back(c); - } - } + std::copy_if(problem->constraints().begin(), + problem->constraints().end(), + std::back_inserter(constraintsToWatch_), + [&rgx](auto* c) { return std::regex_search(c->name(), rgx); }); } void ConstraintSlackAnalysis::addSlackVariablesToConstraints(MPSolver* problem) diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index 6b132cba79..1efae947f8 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -177,8 +177,10 @@ static const std::string validConstraintNames[] = { "BC-name-1::hourly::hour<36>", "BC-name-2::daily::day<67>", "BC-name-3::weekly::week<12>", - "FictiveLoads::hour<25>", - "AreaHydroLevel::hour<8>", + "FictiveLoads::area::hour<25>", + "AreaHydroLevel::area::hour<8>", + "Level::area::hour<28>", + "HydroPower::area::week<45>" }; BOOST_DATA_TEST_CASE(analysis_should_detect_unfeasible_constraint, From e52703f86668760cfdf129c902379fff857ce881 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 9 Jul 2024 18:28:36 +0200 Subject: [PATCH 38/78] [skip ci] Make infeasibility more changeable : remove useless include --- .../infeasible-problem-analysis/constraint-slack-analysis.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index cd4016aa16..dc473d5920 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -22,8 +22,6 @@ #include -#include - #include #include "antares/solver/infeasible-problem-analysis/report.h" #pragma GCC diagnostic push From 599b20c00ca8eba5c44fdce6b084888794f8aee7 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 10 Jul 2024 10:13:31 +0200 Subject: [PATCH 39/78] Make infeasibility more changeable : use of ranges algorithm instead of classic std algorithm --- .../constraint-slack-analysis.cpp | 7 +++---- .../infeasible-problem-analysis/watched-constraints.cpp | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index dc473d5920..742e08163d 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -68,10 +68,9 @@ void ConstraintSlackAnalysis::selectConstraintsToWatch(MPSolver* problem) { ConstraintsFactory factory; std::regex rgx = factory.constraintsFilter(); - std::copy_if(problem->constraints().begin(), - problem->constraints().end(), - std::back_inserter(constraintsToWatch_), - [&rgx](auto* c) { return std::regex_search(c->name(), rgx); }); + std::ranges::copy_if(problem->constraints(), + std::back_inserter(constraintsToWatch_), + [&rgx](auto* c) { return std::regex_search(c->name(), rgx); }); } void ConstraintSlackAnalysis::addSlackVariablesToConstraints(MPSolver* problem) diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index a6000a2328..87341c69a7 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -202,10 +202,9 @@ ConstraintsFactory::ConstraintsFactory() std::shared_ptr ConstraintsFactory::create(std::string varName) const { - return std::find_if(regex_to_ctypes_.begin(), - regex_to_ctypes_.end(), - [&varName](auto& p) - { return std::regex_search(varName, std::regex(p.first)); }) + return std::ranges::find_if(regex_to_ctypes_, + [&varName](auto& p) + { return std::regex_search(varName, std::regex(p.first)); }) ->second(varName); } From bb493cb94b5622e63dd20ffc21e5518204547bc7 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 10 Jul 2024 10:18:34 +0200 Subject: [PATCH 40/78] [skip ci] Make infeasibility more changeable : clang format --- .../watched-constraints.h | 7 +++++++ .../watched-constraints.cpp | 1 + .../test-unfeasible-problem-analyzer.cpp | 18 ++++++++---------- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index 868de701c2..b73c4b3dfb 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -28,6 +28,7 @@ class WatchedConstraint class HourlyBC: public WatchedConstraint { using WatchedConstraint::WatchedConstraint; + public: std::string infeasibility() override; std::string infeasibilityCause() override; @@ -36,6 +37,7 @@ class HourlyBC: public WatchedConstraint class DailyBC: public WatchedConstraint { using WatchedConstraint::WatchedConstraint; + public: std::string infeasibility() override; std::string infeasibilityCause() override; @@ -44,6 +46,7 @@ class DailyBC: public WatchedConstraint class WeeklyBC: public WatchedConstraint { using WatchedConstraint::WatchedConstraint; + public: std::string infeasibility() override; std::string infeasibilityCause() override; @@ -52,6 +55,7 @@ class WeeklyBC: public WatchedConstraint class FictitiousLoad: public WatchedConstraint { using WatchedConstraint::WatchedConstraint; + public: std::string infeasibility() override; std::string infeasibilityCause() override; @@ -60,6 +64,7 @@ class FictitiousLoad: public WatchedConstraint class HydroLevel: public WatchedConstraint { using WatchedConstraint::WatchedConstraint; + public: std::string infeasibility() override; std::string infeasibilityCause() override; @@ -68,6 +73,7 @@ class HydroLevel: public WatchedConstraint class STS: public WatchedConstraint { using WatchedConstraint::WatchedConstraint; + public: std::string infeasibility() override; std::string infeasibilityCause() override; @@ -76,6 +82,7 @@ class STS: public WatchedConstraint class HydroProduction: public WatchedConstraint { using WatchedConstraint::WatchedConstraint; + public: std::string infeasibility() override; std::string infeasibilityCause() override; diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index 87341c69a7..41e121ffa5 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -2,6 +2,7 @@ #include "antares/solver/infeasible-problem-analysis/watched-constraints.h" #include + #include #include #include diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index 1efae947f8..94237e37ca 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -173,15 +173,13 @@ std::unique_ptr createUnfeasibleProblem(const std::string& constraintN return problem; } -static const std::string validConstraintNames[] = { - "BC-name-1::hourly::hour<36>", - "BC-name-2::daily::day<67>", - "BC-name-3::weekly::week<12>", - "FictiveLoads::area::hour<25>", - "AreaHydroLevel::area::hour<8>", - "Level::area::hour<28>", - "HydroPower::area::week<45>" -}; +static const std::string validConstraintNames[] = {"BC-name-1::hourly::hour<36>", + "BC-name-2::daily::day<67>", + "BC-name-3::weekly::week<12>", + "FictiveLoads::area::hour<25>", + "AreaHydroLevel::area::hour<8>", + "Level::area::hour<28>", + "HydroPower::area::week<45>"}; BOOST_DATA_TEST_CASE(analysis_should_detect_unfeasible_constraint, bdata::make(validConstraintNames), @@ -217,4 +215,4 @@ BOOST_AUTO_TEST_CASE(analysis_should_ignore_feasible_constraints) BOOST_CHECK(analysis.hasDetectedInfeasibilityCause()); // Would expect false here instead? } -BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file +BOOST_AUTO_TEST_SUITE_END() From 6454550aca4cc636b83e5b8d9224950882b011db Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Thu, 11 Jul 2024 10:01:52 +0200 Subject: [PATCH 41/78] Make infeasibility more changeable : simplifying constraint factory --- .../watched-constraints.cpp | 50 +++---------------- 1 file changed, 8 insertions(+), 42 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index 41e121ffa5..f382747987 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -152,50 +152,16 @@ std::string HydroProduction::infeasibilityCause() } // --- Constraints factory --- -std::shared_ptr createHourlyBC(std::string varName) -{ - return std::make_shared(varName); -} - -std::shared_ptr createDailyBC(std::string varName) -{ - return std::make_shared(varName); -} - -std::shared_ptr createWeeklyBC(std::string varName) -{ - return std::make_shared(varName); -} - -std::shared_ptr createFictitiousLoad(std::string varName) -{ - return std::make_shared(varName); -} - -std::shared_ptr createHydroLevel(std::string varName) -{ - return std::make_shared(varName); -} - -std::shared_ptr createSTS(std::string varName) -{ - return std::make_shared(varName); -} - -std::shared_ptr createHydroProduction(std::string varName) -{ - return std::make_shared(varName); -} - ConstraintsFactory::ConstraintsFactory() { - regex_to_ctypes_["::hourly::"] = createHourlyBC; - regex_to_ctypes_["::daily::"] = createDailyBC; - regex_to_ctypes_["::weekly::"] = createWeeklyBC; - regex_to_ctypes_["^FictiveLoads::"] = createFictitiousLoad; - regex_to_ctypes_["^AreaHydroLevel::"] = createHydroLevel; - regex_to_ctypes_["^Level::"] = createSTS; - regex_to_ctypes_["^HydroPower::"] = createHydroProduction; + regex_to_ctypes_ = { + {"::hourly::", [](std::string name) { return std::make_shared(name); }}, + {"::daily::", [](std::string name) { return std::make_shared(name); }}, + {"::weekly::", [](std::string name) { return std::make_shared(name); }}, + {"^FictiveLoads::", [](std::string name) { return std::make_shared(name); }}, + {"^AreaHydroLevel::", [](std::string name) { return std::make_shared(name); }}, + {"^Level::", [](std::string name) { return std::make_shared(name); }}, + {"^HydroPower::", [](std::string name) { return std::make_shared(name); }}}; auto keyView = std::views::keys(regex_to_ctypes_); regex_ids_ = {keyView.begin(), keyView.end()}; From 827bd55e291b32592dae5c54dae974733079265c Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Thu, 11 Jul 2024 10:36:36 +0200 Subject: [PATCH 42/78] Make infeasibility more changeable : corrections due to review --- .../watched-constraints.h | 7 +++---- .../watched-constraints.cpp | 21 +++++++++---------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index b73c4b3dfb..11d827f546 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -13,7 +13,7 @@ namespace Antares::Optimization class WatchedConstraint { public: - WatchedConstraint(std::string constraintName); + WatchedConstraint(const std::string& name); virtual std::string infeasibility() = 0; virtual std::string infeasibilityCause() = 0; @@ -21,7 +21,7 @@ class WatchedConstraint const std::vector& splitName() const; protected: - std::string constraintName_; + std::string fullName_; std::vector splitName_; }; @@ -92,13 +92,12 @@ class ConstraintsFactory { public: ConstraintsFactory(); - std::shared_ptr create(std::string regexId) const; + std::shared_ptr create(std::string pair) const; std::regex constraintsFilter(); private: std::map(std::string)>> regex_to_ctypes_; - std::vector regex_ids_; }; } // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index f382747987..5250a8ce3c 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -59,10 +59,10 @@ namespace Antares::Optimization { // --- Generic constraint --- -WatchedConstraint::WatchedConstraint(std::string name): - constraintName_(name) +WatchedConstraint::WatchedConstraint(const std::string& name): + fullName_(std::move(name)) { - boost::algorithm::split_regex(splitName_, constraintName_, boost::regex("::")); + boost::algorithm::split_regex(splitName_, fullName_, boost::regex("::")); } const std::vector& WatchedConstraint::splitName() const @@ -162,22 +162,21 @@ ConstraintsFactory::ConstraintsFactory() {"^AreaHydroLevel::", [](std::string name) { return std::make_shared(name); }}, {"^Level::", [](std::string name) { return std::make_shared(name); }}, {"^HydroPower::", [](std::string name) { return std::make_shared(name); }}}; - - auto keyView = std::views::keys(regex_to_ctypes_); - regex_ids_ = {keyView.begin(), keyView.end()}; } -std::shared_ptr ConstraintsFactory::create(std::string varName) const +std::shared_ptr ConstraintsFactory::create(std::string name) const { return std::ranges::find_if(regex_to_ctypes_, - [&varName](auto& p) - { return std::regex_search(varName, std::regex(p.first)); }) - ->second(varName); + [&name](auto& pair) + { return std::regex_search(name, std::regex(pair.first)); }) + ->second(name); } std::regex ConstraintsFactory::constraintsFilter() { - return std::regex(boost::algorithm::join(regex_ids_, "|")); + auto keyView = std::views::keys(regex_to_ctypes_); + std::vector regex_ids = {keyView.begin(), keyView.end()}; + return std::regex(boost::algorithm::join(regex_ids, "|")); } } // namespace Antares::Optimization From c1326b8dca1c080a0d50b91a7584c5bfe214bfbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Thu, 11 Jul 2024 15:07:55 +0200 Subject: [PATCH 43/78] Fix Sonar issues on #2232 (#2257) Fix Sonar issues on #2232 --- .../constraint-slack-analysis.cpp | 4 ++-- .../solver/infeasible-problem-analysis/report.h | 4 +--- .../watched-constraints.h | 15 +++++++++++---- src/solver/infeasible-problem-analysis/report.cpp | 6 +++--- .../watched-constraints.cpp | 5 ++--- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index 742e08163d..6b433dcf8e 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -85,14 +85,14 @@ void ConstraintSlackAnalysis::addSlackVariablesToConstraints(MPSolver* problem) const double infinity = MPSolver::infinity(); for (MPConstraint* c: constraintsToWatch_) { - if (c->lb() != -infinity) + if (c->lb() > -infinity) { const MPVariable* slack = problem->MakeNumVar(0, infinity, c->name() + "::low"); c->SetCoefficient(slack, 1.); slackVariables_.push_back(slack); } - if (c->ub() != infinity) + if (c->ub() < infinity) { const MPVariable* slack = problem->MakeNumVar(0, infinity, c->name() + "::up"); c->SetCoefficient(slack, -1.); diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h index bf9dc27025..c90565649e 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h @@ -28,8 +28,6 @@ #include "ortools/linear_solver/linear_solver.h" #include "watched-constraints.h" -using namespace operations_research; - namespace operations_research { class MPVariable; @@ -46,7 +44,7 @@ class InfeasibleProblemReport void logInfeasibilityCauses(); private: - void buildConstraintsFromSlackVars(const std::vector&); + void buildConstraintsFromSlackVars(const std::vector&); void filterConstraintsToOneByType(); std::vector> constraints_; diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index 11d827f546..d814102d63 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -13,15 +13,15 @@ namespace Antares::Optimization class WatchedConstraint { public: - WatchedConstraint(const std::string& name); + explicit WatchedConstraint(const std::string& name); + virtual ~WatchedConstraint() = default; virtual std::string infeasibility() = 0; virtual std::string infeasibilityCause() = 0; protected: const std::vector& splitName() const; -protected: - std::string fullName_; +private: std::vector splitName_; }; @@ -30,6 +30,7 @@ class HourlyBC: public WatchedConstraint using WatchedConstraint::WatchedConstraint; public: + ~HourlyBC() override = default; std::string infeasibility() override; std::string infeasibilityCause() override; }; @@ -39,6 +40,7 @@ class DailyBC: public WatchedConstraint using WatchedConstraint::WatchedConstraint; public: + ~DailyBC() override = default; std::string infeasibility() override; std::string infeasibilityCause() override; }; @@ -48,6 +50,7 @@ class WeeklyBC: public WatchedConstraint using WatchedConstraint::WatchedConstraint; public: + ~WeeklyBC() override = default; std::string infeasibility() override; std::string infeasibilityCause() override; }; @@ -57,6 +60,7 @@ class FictitiousLoad: public WatchedConstraint using WatchedConstraint::WatchedConstraint; public: + ~FictitiousLoad() override = default; std::string infeasibility() override; std::string infeasibilityCause() override; }; @@ -66,6 +70,7 @@ class HydroLevel: public WatchedConstraint using WatchedConstraint::WatchedConstraint; public: + ~HydroLevel() override = default; std::string infeasibility() override; std::string infeasibilityCause() override; }; @@ -75,6 +80,7 @@ class STS: public WatchedConstraint using WatchedConstraint::WatchedConstraint; public: + ~STS() override = default; std::string infeasibility() override; std::string infeasibilityCause() override; }; @@ -84,6 +90,7 @@ class HydroProduction: public WatchedConstraint using WatchedConstraint::WatchedConstraint; public: + ~HydroProduction() override = default; std::string infeasibility() override; std::string infeasibilityCause() override; }; @@ -91,7 +98,7 @@ class HydroProduction: public WatchedConstraint class ConstraintsFactory { public: - ConstraintsFactory(); + explicit ConstraintsFactory(); std::shared_ptr create(std::string pair) const; std::regex constraintsFilter(); diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index c06d372901..c1df567e4e 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -28,17 +28,17 @@ namespace Antares::Optimization { InfeasibleProblemReport::InfeasibleProblemReport( - const std::vector& slackVariables) + const std::vector& slackVariables) { buildConstraintsFromSlackVars(slackVariables); filterConstraintsToOneByType(); } void InfeasibleProblemReport::buildConstraintsFromSlackVars( - const std::vector& slackVariables) + const std::vector& slackVariables) { const ConstraintsFactory constraintsFactory; - for (const auto& slackVar: slackVariables) + for (const auto* slackVar: slackVariables) { constraints_.push_back(constraintsFactory.create(slackVar->name())); } diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index 5250a8ce3c..531a69a27c 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -59,10 +59,9 @@ namespace Antares::Optimization { // --- Generic constraint --- -WatchedConstraint::WatchedConstraint(const std::string& name): - fullName_(std::move(name)) +WatchedConstraint::WatchedConstraint(const std::string& name) { - boost::algorithm::split_regex(splitName_, fullName_, boost::regex("::")); + boost::algorithm::split_regex(splitName_, name, boost::regex("::")); } const std::vector& WatchedConstraint::splitName() const From 9873fc65681c78b00c91a9e05083a1190c94c86a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Thu, 11 Jul 2024 17:18:48 +0200 Subject: [PATCH 44/78] Minor fixes, use std::unique_ptr, add safety (#2256) - Use `std::unique_ptr` since we don't share objects - Remove lambda functions (see https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique) - Use `const std::string&` - Make check on `create`, add safety on no result found - Remove unused variables in tests --- .../watched-constraints.h | 4 +-- .../infeasible-problem-analysis/report.cpp | 6 +++- .../watched-constraints.cpp | 35 ++++++++++--------- .../test-unfeasible-problem-analyzer.cpp | 4 +-- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index d814102d63..87413dae37 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -99,11 +99,11 @@ class ConstraintsFactory { public: explicit ConstraintsFactory(); - std::shared_ptr create(std::string pair) const; + std::unique_ptr create(const std::string& pair) const; std::regex constraintsFilter(); private: - std::map(std::string)>> + std::map(const std::string&)>> regex_to_ctypes_; }; diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index c1df567e4e..cce9851f22 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -40,7 +40,11 @@ void InfeasibleProblemReport::buildConstraintsFromSlackVars( const ConstraintsFactory constraintsFactory; for (const auto* slackVar: slackVariables) { - constraints_.push_back(constraintsFactory.create(slackVar->name())); + auto constraint = constraintsFactory.create(slackVar->name()); + if (constraint) + { + constraints_.push_back(std::move(constraint)); + } } } diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index 531a69a27c..886451d160 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -153,22 +153,25 @@ std::string HydroProduction::infeasibilityCause() // --- Constraints factory --- ConstraintsFactory::ConstraintsFactory() { - regex_to_ctypes_ = { - {"::hourly::", [](std::string name) { return std::make_shared(name); }}, - {"::daily::", [](std::string name) { return std::make_shared(name); }}, - {"::weekly::", [](std::string name) { return std::make_shared(name); }}, - {"^FictiveLoads::", [](std::string name) { return std::make_shared(name); }}, - {"^AreaHydroLevel::", [](std::string name) { return std::make_shared(name); }}, - {"^Level::", [](std::string name) { return std::make_shared(name); }}, - {"^HydroPower::", [](std::string name) { return std::make_shared(name); }}}; -} - -std::shared_ptr ConstraintsFactory::create(std::string name) const -{ - return std::ranges::find_if(regex_to_ctypes_, - [&name](auto& pair) - { return std::regex_search(name, std::regex(pair.first)); }) - ->second(name); + regex_to_ctypes_ = {{"::hourly::", std::make_unique}, + {"::daily::", std::make_unique}, + {"::weekly::", std::make_unique}, + {"^FictiveLoads::", std::make_unique}, + {"^AreaHydroLevel::", std::make_unique}, + {"^Level::", std::make_unique}, + {"^HydroPower::", std::make_unique}}; +} + +std::unique_ptr ConstraintsFactory::create(const std::string& name) const +{ + auto it = std::ranges::find_if(regex_to_ctypes_, + [&name](auto& pair) + { return std::regex_search(name, std::regex(pair.first)); }); + if (it != regex_to_ctypes_.end()) + { + return it->second(name); + } + return nullptr; } std::regex ConstraintsFactory::constraintsFilter() diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index 94237e37ca..20086d505f 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -144,8 +144,8 @@ std::unique_ptr createProblem(const std::string& constraintName) { std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); const double infinity = problem->infinity(); - auto var1 = problem->MakeNumVar(1, infinity, "var1"); - auto var2 = problem->MakeNumVar(-infinity, -1, "var2"); + problem->MakeNumVar(1, infinity, "var1"); + problem->MakeNumVar(-infinity, -1, "var2"); auto constraint = problem->MakeRowConstraint(constraintName); constraint->SetBounds(0, infinity); return problem; From be8101d608fd693d4a4a2e9ce77e01d2df5a0276 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Mon, 15 Jul 2024 13:25:58 +0200 Subject: [PATCH 45/78] Make infeasibility more changeable : changing inner class constant into a static const --- .../infeasible-problem-analysis/constraint-slack-analysis.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h index cfb6fccdf4..81e8d831c7 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h @@ -61,7 +61,7 @@ class ConstraintSlackAnalysis: public UnfeasibilityAnalysis std::vector constraintsToWatch_; std::vector slackVariables_; - const unsigned int nbMaxSlackVarsToKeep = 10; + static const unsigned int nbMaxSlackVarsToKeep = 10; }; } // namespace Antares::Optimization From 23d06d6d46d9191d2355d370a7bb9699e5b17194 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Mon, 15 Jul 2024 15:28:25 +0200 Subject: [PATCH 46/78] Make infeasibility more changeable : trial to simplify method InfeasibleProblemReport :: filterConstraintsToOneByType() --- .../infeasible-problem-analysis/report.h | 1 - .../watched-constraints.h | 8 +++--- .../infeasible-problem-analysis/report.cpp | 27 ++++++++++--------- .../watched-constraints.cpp | 26 +++++++++++------- 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h index c90565649e..ef242b1f36 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h @@ -48,6 +48,5 @@ class InfeasibleProblemReport void filterConstraintsToOneByType(); std::vector> constraints_; - std::vector> uniqueConstraintByType_; }; } // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index 87413dae37..dd8f8c6f6c 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -13,16 +13,18 @@ namespace Antares::Optimization class WatchedConstraint { public: - explicit WatchedConstraint(const std::string& name); + explicit WatchedConstraint(const std::string& name, const double slackValue); virtual ~WatchedConstraint() = default; virtual std::string infeasibility() = 0; virtual std::string infeasibilityCause() = 0; + double slackValue() const; protected: const std::vector& splitName() const; private: std::vector splitName_; + double slack_value_; }; class HourlyBC: public WatchedConstraint @@ -99,11 +101,11 @@ class ConstraintsFactory { public: explicit ConstraintsFactory(); - std::unique_ptr create(const std::string& pair) const; + std::unique_ptr create(const std::string&, const double) const; std::regex constraintsFilter(); private: - std::map(const std::string&)>> + std::map(const std::string&, const double)>> regex_to_ctypes_; }; diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index cce9851f22..bd26e785e0 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -40,7 +40,7 @@ void InfeasibleProblemReport::buildConstraintsFromSlackVars( const ConstraintsFactory constraintsFactory; for (const auto* slackVar: slackVariables) { - auto constraint = constraintsFactory.create(slackVar->name()); + auto constraint = constraintsFactory.create(slackVar->name(), slackVar->solution_value()); if (constraint) { constraints_.push_back(std::move(constraint)); @@ -48,18 +48,21 @@ void InfeasibleProblemReport::buildConstraintsFromSlackVars( } } +bool compTypeName(const std::shared_ptr a, const std::shared_ptr b) +{ + return typeid(*a).name() < typeid(*b).name(); +} + +bool compValue(const std::shared_ptr a, std::shared_ptr b) +{ + return a->slackValue() < b->slackValue(); +} + void InfeasibleProblemReport::filterConstraintsToOneByType() { - std::vector pickedTypes; - for (const auto& c: constraints_) - { - std::string cType = typeid(*c).name(); - if (std::find(pickedTypes.begin(), pickedTypes.end(), cType) == pickedTypes.end()) - { - uniqueConstraintByType_.push_back(c); - pickedTypes.push_back(cType); - } - } + std::sort(constraints_.begin(), constraints_.end(), compTypeName); + std::unique(constraints_.begin(), constraints_.end(), compValue); + std::sort(constraints_.begin(), constraints_.end(), compValue); } void InfeasibleProblemReport::logSuspiciousConstraints() @@ -73,7 +76,7 @@ void InfeasibleProblemReport::logSuspiciousConstraints() void InfeasibleProblemReport::logInfeasibilityCauses() { Antares::logs.error() << "Possible causes of infeasibility:"; - for (const auto& c: uniqueConstraintByType_) + for (const auto& c: constraints_) { Antares::logs.error() << c->infeasibilityCause(); } diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index 886451d160..7fd34f7abc 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -59,7 +59,8 @@ namespace Antares::Optimization { // --- Generic constraint --- -WatchedConstraint::WatchedConstraint(const std::string& name) +WatchedConstraint::WatchedConstraint(const std::string& name, const double slackValue) : + slack_value_(slackValue) { boost::algorithm::split_regex(splitName_, name, boost::regex("::")); } @@ -69,6 +70,11 @@ const std::vector& WatchedConstraint::splitName() const return splitName_; } +double WatchedConstraint::slackValue() const +{ + return slack_value_; +} + std::string HourlyBC::infeasibility() { return "Hourly BC '" + shortName(splitName()) + "' at hour " + timeStep(splitName()); @@ -153,23 +159,23 @@ std::string HydroProduction::infeasibilityCause() // --- Constraints factory --- ConstraintsFactory::ConstraintsFactory() { - regex_to_ctypes_ = {{"::hourly::", std::make_unique}, - {"::daily::", std::make_unique}, - {"::weekly::", std::make_unique}, - {"^FictiveLoads::", std::make_unique}, - {"^AreaHydroLevel::", std::make_unique}, - {"^Level::", std::make_unique}, - {"^HydroPower::", std::make_unique}}; + regex_to_ctypes_ = {{"::hourly::", std::make_unique}, + {"::daily::", std::make_unique}, + {"::weekly::", std::make_unique}, + {"^FictiveLoads::", std::make_unique}, + {"^AreaHydroLevel::", std::make_unique}, + {"^Level::", std::make_unique}, + {"^HydroPower::", std::make_unique}}; } -std::unique_ptr ConstraintsFactory::create(const std::string& name) const +std::unique_ptr ConstraintsFactory::create(const std::string& name, const double value) const { auto it = std::ranges::find_if(regex_to_ctypes_, [&name](auto& pair) { return std::regex_search(name, std::regex(pair.first)); }); if (it != regex_to_ctypes_.end()) { - return it->second(name); + return it->second(name, value); } return nullptr; } From ea5e282d239057831556585028f5c9d791f13ca5 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Mon, 15 Jul 2024 17:08:53 +0200 Subject: [PATCH 47/78] Make infeasibility more changeable : fix filterConstraintsToOneByType (used to fail on unit tests) --- src/solver/infeasible-problem-analysis/report.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index bd26e785e0..4c9acbf356 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -31,7 +31,6 @@ InfeasibleProblemReport::InfeasibleProblemReport( const std::vector& slackVariables) { buildConstraintsFromSlackVars(slackVariables); - filterConstraintsToOneByType(); } void InfeasibleProblemReport::buildConstraintsFromSlackVars( @@ -53,6 +52,11 @@ bool compTypeName(const std::shared_ptr a, const std::shared_ return typeid(*a).name() < typeid(*b).name(); } +bool sameType(const std::shared_ptr a, const std::shared_ptr b) +{ + return typeid(*a).name() == typeid(*b).name(); +} + bool compValue(const std::shared_ptr a, std::shared_ptr b) { return a->slackValue() < b->slackValue(); @@ -60,8 +64,9 @@ bool compValue(const std::shared_ptr a, std::shared_ptrinfeasibilityCause(); From c63d0892a69771ac219be2978f6899a0df43d5b2 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Mon, 15 Jul 2024 17:28:42 +0200 Subject: [PATCH 48/78] Make infeasibility more changeable : simplify filterConstraintsToOneByType --- src/solver/infeasible-problem-analysis/report.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 4c9acbf356..ccb2fc15d2 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -64,10 +64,10 @@ bool compValue(const std::shared_ptr a, std::shared_ptr Date: Mon, 15 Jul 2024 18:02:06 +0200 Subject: [PATCH 49/78] Make infeasibility more changeable : fix compilation error --- src/solver/infeasible-problem-analysis/report.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index ccb2fc15d2..a4e8dfc1ff 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -81,7 +81,7 @@ void InfeasibleProblemReport::logSuspiciousConstraints() void InfeasibleProblemReport::logInfeasibilityCauses() { filterConstraintsToOneByType(); - report_.push_back("Possible causes of infeasibility:"); + Antares::logs.error() << "Possible causes of infeasibility:"; for (const auto& c: constraints_) { Antares::logs.error() << c->infeasibilityCause(); From 2b4769e79f54341688c6b7fdb21cec054b83949f Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 16 Jul 2024 10:12:56 +0200 Subject: [PATCH 50/78] Make infeasibility more changeable : add comments to make code more understandable --- src/solver/infeasible-problem-analysis/report.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index a4e8dfc1ff..f9b222e93d 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -64,9 +64,13 @@ bool compValue(const std::shared_ptr a, std::shared_ptr Date: Tue, 16 Jul 2024 11:39:21 +0200 Subject: [PATCH 51/78] Use std::type_index (#2264) --- .../watched-constraints.h | 3 ++- .../infeasible-problem-analysis/report.cpp | 11 ++++++---- .../watched-constraints.cpp | 21 ++++++++++--------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h index dd8f8c6f6c..1c1c533d71 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/watched-constraints.h @@ -105,7 +105,8 @@ class ConstraintsFactory std::regex constraintsFilter(); private: - std::map(const std::string&, const double)>> + std::map(const std::string&, const double)>> regex_to_ctypes_; }; diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index f9b222e93d..7329d2c314 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -22,6 +22,7 @@ #include #include +#include #include @@ -47,14 +48,16 @@ void InfeasibleProblemReport::buildConstraintsFromSlackVars( } } -bool compTypeName(const std::shared_ptr a, const std::shared_ptr b) +bool compTypeName(const std::shared_ptr a, + const std::shared_ptr b) { - return typeid(*a).name() < typeid(*b).name(); + return std::type_index(typeid(*a)) < std::type_index(typeid(*b)); } -bool sameType(const std::shared_ptr a, const std::shared_ptr b) +bool sameType(const std::shared_ptr a, + const std::shared_ptr b) { - return typeid(*a).name() == typeid(*b).name(); + return std::type_index(typeid(*a)) == std::type_index(typeid(*b)); } bool compValue(const std::shared_ptr a, std::shared_ptr b) diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index 7fd34f7abc..e054f49f03 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -1,4 +1,3 @@ - #include "antares/solver/infeasible-problem-analysis/watched-constraints.h" #include @@ -59,7 +58,7 @@ namespace Antares::Optimization { // --- Generic constraint --- -WatchedConstraint::WatchedConstraint(const std::string& name, const double slackValue) : +WatchedConstraint::WatchedConstraint(const std::string& name, const double slackValue): slack_value_(slackValue) { boost::algorithm::split_regex(splitName_, name, boost::regex("::")); @@ -159,16 +158,18 @@ std::string HydroProduction::infeasibilityCause() // --- Constraints factory --- ConstraintsFactory::ConstraintsFactory() { - regex_to_ctypes_ = {{"::hourly::", std::make_unique}, - {"::daily::", std::make_unique}, - {"::weekly::", std::make_unique}, - {"^FictiveLoads::", std::make_unique}, - {"^AreaHydroLevel::", std::make_unique}, - {"^Level::", std::make_unique}, - {"^HydroPower::", std::make_unique}}; + regex_to_ctypes_ = { + {"::hourly::", std::make_unique}, + {"::daily::", std::make_unique}, + {"::weekly::", std::make_unique}, + {"^FictiveLoads::", std::make_unique}, + {"^AreaHydroLevel::", std::make_unique}, + {"^Level::", std::make_unique}, + {"^HydroPower::", std::make_unique}}; } -std::unique_ptr ConstraintsFactory::create(const std::string& name, const double value) const +std::unique_ptr ConstraintsFactory::create(const std::string& name, + const double value) const { auto it = std::ranges::find_if(regex_to_ctypes_, [&name](auto& pair) From b0181850d9a00749f4cb727a640985fa942369eb Mon Sep 17 00:00:00 2001 From: Florian OMNES <26088210+flomnes@users.noreply.github.com> Date: Tue, 16 Jul 2024 11:40:44 +0200 Subject: [PATCH 52/78] Formatting --- src/solver/infeasible-problem-analysis/report.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 7329d2c314..640715c8de 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -69,7 +69,8 @@ void InfeasibleProblemReport::filterConstraintsToOneByType() { // 1. Grouping constraints by C++ type (inside a group, order of instances remains unchanged) std::ranges::stable_sort(constraints_, compTypeName); - // 2. Keeping the first instances of each group, and rejecting others (= duplicates) to the end of vector + // 2. Keeping the first instances of each group, and rejecting others (= duplicates) to the end + // of vector auto duplicates = std::ranges::unique(constraints_, sameType); // 3. Removing trailing duplicates constraints_.erase(duplicates.begin(), duplicates.end()); From 3bbae2ad6510c2c2c011b7a374f65b28ed4ff313 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 16 Jul 2024 15:24:45 +0200 Subject: [PATCH 53/78] Make infeasibility more changeable : fix an error in infeasibility causes order in he report --- src/solver/infeasible-problem-analysis/report.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index 640715c8de..dc43da140a 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -48,7 +48,7 @@ void InfeasibleProblemReport::buildConstraintsFromSlackVars( } } -bool compTypeName(const std::shared_ptr a, +bool lessTypeName(const std::shared_ptr a, const std::shared_ptr b) { return std::type_index(typeid(*a)) < std::type_index(typeid(*b)); @@ -60,22 +60,22 @@ bool sameType(const std::shared_ptr a, return std::type_index(typeid(*a)) == std::type_index(typeid(*b)); } -bool compValue(const std::shared_ptr a, std::shared_ptr b) +bool greaterValue(const std::shared_ptr a, std::shared_ptr b) { - return a->slackValue() < b->slackValue(); + return a->slackValue() > b->slackValue(); } void InfeasibleProblemReport::filterConstraintsToOneByType() { // 1. Grouping constraints by C++ type (inside a group, order of instances remains unchanged) - std::ranges::stable_sort(constraints_, compTypeName); + std::ranges::stable_sort(constraints_, lessTypeName); // 2. Keeping the first instances of each group, and rejecting others (= duplicates) to the end // of vector auto duplicates = std::ranges::unique(constraints_, sameType); // 3. Removing trailing duplicates constraints_.erase(duplicates.begin(), duplicates.end()); - // 4. Sorting remaining constraints by slack value - std::ranges::sort(constraints_, compValue); + // 4. Sorting remaining constraints by slack value (in descending order) + std::ranges::sort(constraints_, greaterValue); } void InfeasibleProblemReport::logSuspiciousConstraints() From e67167a584de30caa607b6633f80f0eecfd942d8 Mon Sep 17 00:00:00 2001 From: Florian OMNES <26088210+flomnes@users.noreply.github.com> Date: Tue, 16 Jul 2024 14:55:25 +0200 Subject: [PATCH 54/78] Fix linking --- .../constraint-slack-analysis.cpp | 7 ++++++- .../constraint-slack-analysis.h | 1 - 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index 6b433dcf8e..099ac70db6 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -31,11 +31,16 @@ using namespace operations_research; -static bool compareSlackSolutions(const MPVariable* a, const MPVariable* b) +namespace +{ +bool compareSlackSolutions(const MPVariable* a, const MPVariable* b) { return a->solution_value() > b->solution_value(); } +constexpr unsigned int nbMaxSlackVarsToKeep = 10; +} // namespace + namespace Antares::Optimization { diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h index 81e8d831c7..462d5f965f 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h @@ -61,7 +61,6 @@ class ConstraintSlackAnalysis: public UnfeasibilityAnalysis std::vector constraintsToWatch_; std::vector slackVariables_; - static const unsigned int nbMaxSlackVarsToKeep = 10; }; } // namespace Antares::Optimization From 5bda935de471b4afc99316cc9e00dc2cf9adc95b Mon Sep 17 00:00:00 2001 From: Florian OMNES <26088210+flomnes@users.noreply.github.com> Date: Thu, 11 Jul 2024 11:19:17 +0200 Subject: [PATCH 55/78] Minor fixes, use std::unique_ptr From af62a603fca9198e176d1a6a9c54b5d7e8f19f44 Mon Sep 17 00:00:00 2001 From: Florian OMNES <26088210+flomnes@users.noreply.github.com> Date: Thu, 11 Jul 2024 11:22:23 +0200 Subject: [PATCH 56/78] Caller safer From 8496fe8d89e414577ebf0f8645f1d9c670c93ac0 Mon Sep 17 00:00:00 2001 From: Florian OMNES <26088210+flomnes@users.noreply.github.com> Date: Thu, 11 Jul 2024 11:39:04 +0200 Subject: [PATCH 57/78] Revert From 1d15b624164456abeb913c0559123316f96ab180 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 10 Jul 2024 13:20:28 +0200 Subject: [PATCH 58/78] Improve infeasible pb test : improve constraint violation detection --- .../constraint-slack-analysis.cpp | 11 ++++++++--- .../constraint-slack-analysis.h | 2 ++ .../test-unfeasible-problem-analyzer.cpp | 4 +--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index 099ac70db6..ea9c8aa856 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -50,7 +50,7 @@ void ConstraintSlackAnalysis::run(MPSolver* problem) addSlackVariablesToConstraints(problem); if (slackVariables_.empty()) { - logs.error() << title() << " : no constraints have been selected"; + logs.warning() << title() << " : no constraints have been selected"; return; } @@ -63,10 +63,9 @@ void ConstraintSlackAnalysis::run(MPSolver* problem) return; } - hasDetectedInfeasibilityCause_ = true; - sortSlackVariablesByValue(); trimSlackVariables(); + hasDetectedInfeasibilityCause_ = anySlackVariableNonZero(); } void ConstraintSlackAnalysis::selectConstraintsToWatch(MPSolver* problem) @@ -130,6 +129,12 @@ void ConstraintSlackAnalysis::trimSlackVariables() slackVariables_.resize(std::min(nbMaxSlackVarsToKeep, nbSlackVars)); } +bool ConstraintSlackAnalysis::anySlackVariableNonZero() +{ + return std::ranges::any_of(slackVariables_, + [&](auto& v) {return v->solution_value() > thresholdNonZero;}); +} + void ConstraintSlackAnalysis::printReport() const { InfeasibleProblemReport report(slackVariables_); diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h index 462d5f965f..ccb3f55acd 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h @@ -58,9 +58,11 @@ class ConstraintSlackAnalysis: public UnfeasibilityAnalysis void buildObjective(operations_research::MPSolver* problem) const; void sortSlackVariablesByValue(); void trimSlackVariables(); + bool anySlackVariableNonZero(); std::vector constraintsToWatch_; std::vector slackVariables_; + const double thresholdNonZero = 1e-06; }; } // namespace Antares::Optimization diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index 20086d505f..221445a9d8 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -203,8 +203,6 @@ BOOST_AUTO_TEST_CASE(analysis_should_ignore_ill_named_constraint) BOOST_CHECK(!analysis.hasDetectedInfeasibilityCause()); } -// TODO: this test should be improved by changing the API, the current interface does not allow -// to check that no constraint was identified... BOOST_AUTO_TEST_CASE(analysis_should_ignore_feasible_constraints) { std::unique_ptr feasibleProblem = createFeasibleProblem("BC::hourly::hour<36>"); @@ -212,7 +210,7 @@ BOOST_AUTO_TEST_CASE(analysis_should_ignore_feasible_constraints) ConstraintSlackAnalysis analysis; analysis.run(feasibleProblem.get()); - BOOST_CHECK(analysis.hasDetectedInfeasibilityCause()); // Would expect false here instead? + BOOST_CHECK(!analysis.hasDetectedInfeasibilityCause()); } BOOST_AUTO_TEST_SUITE_END() From f1991c4f28a8949fe93511e8ddc024f70b126e95 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 10 Jul 2024 14:30:18 +0200 Subject: [PATCH 59/78] Improve infeasible pb test : fix detection error detection + change report messages printings --- .../constraint-slack-analysis.cpp | 12 ++++++++---- .../solver/infeasible-problem-analysis/report.h | 6 ++++-- src/solver/infeasible-problem-analysis/report.cpp | 14 ++++++++++---- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index ea9c8aa856..c2e4d02ffc 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -65,7 +65,10 @@ void ConstraintSlackAnalysis::run(MPSolver* problem) sortSlackVariablesByValue(); trimSlackVariables(); - hasDetectedInfeasibilityCause_ = anySlackVariableNonZero(); + if (hasDetectedInfeasibilityCause_ = anySlackVariableNonZero(); !hasDetectedInfeasibilityCause_) + { + logs.warning() << title() << " : no violation detected for selected constraints."; + } } void ConstraintSlackAnalysis::selectConstraintsToWatch(MPSolver* problem) @@ -132,14 +135,15 @@ void ConstraintSlackAnalysis::trimSlackVariables() bool ConstraintSlackAnalysis::anySlackVariableNonZero() { return std::ranges::any_of(slackVariables_, - [&](auto& v) {return v->solution_value() > thresholdNonZero;}); + [&](auto& v) { return v->solution_value() > thresholdNonZero; }); } void ConstraintSlackAnalysis::printReport() const { InfeasibleProblemReport report(slackVariables_); - report.logSuspiciousConstraints(); - report.logInfeasibilityCauses(); + report.storeSuspiciousConstraints(); + report.storeInfeasibilityCauses(); + std::ranges::for_each(report.get(), [](auto& line) { logs.error() << line; }); } } // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h index ef242b1f36..a5a8d521cc 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h @@ -40,13 +40,15 @@ class InfeasibleProblemReport public: InfeasibleProblemReport() = delete; explicit InfeasibleProblemReport(const std::vector&); - void logSuspiciousConstraints(); - void logInfeasibilityCauses(); + void storeSuspiciousConstraints(); + void storeInfeasibilityCauses(); + std::vector get(); private: void buildConstraintsFromSlackVars(const std::vector&); void filterConstraintsToOneByType(); std::vector> constraints_; + std::vector report_; }; } // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index dc43da140a..ab521acf72 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -78,22 +78,28 @@ void InfeasibleProblemReport::filterConstraintsToOneByType() std::ranges::sort(constraints_, greaterValue); } -void InfeasibleProblemReport::logSuspiciousConstraints() +void InfeasibleProblemReport::storeSuspiciousConstraints() { + report_.push_back("Violated constraints:"); for (const auto& c: constraints_) { - Antares::logs.error() << c->infeasibility(); + report_.push_back(c->infeasibility()); } } -void InfeasibleProblemReport::logInfeasibilityCauses() +void InfeasibleProblemReport::storeInfeasibilityCauses() { filterConstraintsToOneByType(); Antares::logs.error() << "Possible causes of infeasibility:"; for (const auto& c: constraints_) { - Antares::logs.error() << c->infeasibilityCause(); + report_.push_back(c->infeasibilityCause()); } } +std::vector InfeasibleProblemReport::get() +{ + return report_; +} + } // namespace Antares::Optimization From 47341e7801d090a451b4e291454a8d4eac134fcf Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 10 Jul 2024 16:12:48 +0200 Subject: [PATCH 60/78] Improve infeasible pb test : fix bug in logging violated variables + add tests on report slack analysis --- .../constraint-slack-analysis.cpp | 2 +- .../infeasible-problem-analysis/report.h | 2 +- .../infeasible-problem-analysis/report.cpp | 2 +- .../watched-constraints.cpp | 2 +- .../test-unfeasible-problem-analyzer.cpp | 66 +++++++++++++++++-- 5 files changed, 63 insertions(+), 11 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index c2e4d02ffc..d1fc9c383e 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -143,7 +143,7 @@ void ConstraintSlackAnalysis::printReport() const InfeasibleProblemReport report(slackVariables_); report.storeSuspiciousConstraints(); report.storeInfeasibilityCauses(); - std::ranges::for_each(report.get(), [](auto& line) { logs.error() << line; }); + std::ranges::for_each(report.getLogs(), [](auto& line) { logs.error() << line; }); } } // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h index a5a8d521cc..1d498eb653 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h @@ -42,7 +42,7 @@ class InfeasibleProblemReport explicit InfeasibleProblemReport(const std::vector&); void storeSuspiciousConstraints(); void storeInfeasibilityCauses(); - std::vector get(); + std::vector getLogs(); private: void buildConstraintsFromSlackVars(const std::vector&); diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index ab521acf72..e6789f728a 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -97,7 +97,7 @@ void InfeasibleProblemReport::storeInfeasibilityCauses() } } -std::vector InfeasibleProblemReport::get() +std::vector InfeasibleProblemReport::getLogs() { return report_; } diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index e054f49f03..0584b469d4 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -36,7 +36,7 @@ std::string StringBetweenAngleBrackets(const std::string& constraintName) std::string timeStep(std::vector splitName) { - return StringBetweenAngleBrackets(splitName.at(splitName.size() - 2)); + return StringBetweenAngleBrackets(splitName.back()); } std::string shortName(std::vector splitName) diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index 221445a9d8..748fa5e14f 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -30,6 +30,7 @@ #include "antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h" #include "antares/solver/infeasible-problem-analysis/unfeasible-pb-analyzer.h" #include "antares/solver/infeasible-problem-analysis/variables-bounds-consistency.h" +#include "antares/solver/infeasible-problem-analysis/report.h" namespace bdata = boost::unit_test::data; @@ -40,6 +41,7 @@ using Antares::Optimization::UnfeasibilityAnalysis; using Antares::Optimization::UnfeasiblePbAnalyzer; using Antares::Optimization::VariableBounds; using Antares::Optimization::VariablesBoundsConsistency; +using Antares::Optimization::InfeasibleProblemReport; bool variableEquals(const VariableBounds& lhs, const VariableBounds& rhs) { @@ -83,7 +85,7 @@ class AnalysisMock: public UnfeasibilityAnalysis bool& hasPrinted_; }; -BOOST_AUTO_TEST_SUITE(unfeasible_problem_analyzer) +BOOST_AUTO_TEST_SUITE(general_unfeasible_problem_analyzer) BOOST_AUTO_TEST_CASE(analyzer_should_call_analysis_and_print_detected_issues) { @@ -116,6 +118,9 @@ BOOST_AUTO_TEST_CASE(analyzer_should_call_analysis_and_print_detected_issues) BOOST_CHECK(hasRun2); BOOST_CHECK(hasPrinted2); } +BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE(variable_bounds_consistency_analyzer) BOOST_AUTO_TEST_CASE(analysis_should_detect_inconsistent_variable_bounds) { @@ -131,15 +136,16 @@ BOOST_AUTO_TEST_CASE(analysis_should_detect_inconsistent_variable_bounds) auto expected = VariableBounds("not-ok-var", 1, -1); BOOST_CHECK(variableEquals(incorrectVars[0], expected)); } +BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_SUITE(slack_variables_analyzer) /*! - * Creates a problem with 2 variables linked by 1 constraint: + * Creates a 2 problems (feasible and infeasible) with 2 variables linked by 1 constraint: * - Variable 1 must be greater than 1 * - Variable 2 must be smaller than -1 - * - but if feasible is false, constraint enforces that variable 2 is greater than variable 1 --> - * infeasible + * - For infeasible problem, constraint enforces that variable 2 is greater than variable 1 */ - std::unique_ptr createProblem(const std::string& constraintName) { std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); @@ -205,12 +211,58 @@ BOOST_AUTO_TEST_CASE(analysis_should_ignore_ill_named_constraint) BOOST_AUTO_TEST_CASE(analysis_should_ignore_feasible_constraints) { - std::unique_ptr feasibleProblem = createFeasibleProblem("BC::hourly::hour<36>"); + std::unique_ptr feasibleProblem = createFeasibleProblem("BC-name::hourly::hour<36>"); BOOST_CHECK(feasibleProblem->Solve() == MPSolver::OPTIMAL); ConstraintSlackAnalysis analysis; analysis.run(feasibleProblem.get()); BOOST_CHECK(!analysis.hasDetectedInfeasibilityCause()); } - BOOST_AUTO_TEST_SUITE_END() + + +BOOST_AUTO_TEST_SUITE(slack_variables_report) + +BOOST_AUTO_TEST_CASE(constraints_associated_to_all_incoming_slack_vars_are_reported) +{ + // The problem is needed only to create variables, impossible otherwise. + std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); + + std::vector slackVariables; + slackVariables.push_back(problem->MakeNumVar(0, 1, "BC-1::hourly::hour<36>")); + slackVariables.push_back(problem->MakeNumVar(0, 1, "BC-2::hourly::hour<65>")); + slackVariables.push_back(problem->MakeNumVar(0, 1, "FictiveLoads::area::hour<25>")); + slackVariables.push_back(problem->MakeNumVar(0, 1, "HydroPower::area::week<45>")); + + InfeasibleProblemReport report(slackVariables); + report.storeSuspiciousConstraints(); + auto reportLogs = report.getLogs(); + + BOOST_CHECK_EQUAL(reportLogs.size(), 5); // Expecting 5 lines in the report + BOOST_CHECK_EQUAL(reportLogs[1], "Hourly BC 'BC-1' at hour 36"); + BOOST_CHECK_EQUAL(reportLogs[2], "Hourly BC 'BC-2' at hour 65"); + BOOST_CHECK_EQUAL(reportLogs[3], "Last resort shedding status at area 'some-area' at hour 25"); + BOOST_CHECK_EQUAL(reportLogs[4], "Hydro weekly production at area 'some-area'"); +} + +BOOST_AUTO_TEST_CASE(infeasibility_cause__only_one_constraint_of_type) +{ + // The problem is needed only to create variables, impossible otherwise. + std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); + + std::vector slackVariables; + slackVariables.push_back(problem->MakeNumVar(0, 1, "BC-1::hourly::hour<36>")); + slackVariables.push_back(problem->MakeNumVar(0, 1, "BC-2::hourly::hour<65>")); + slackVariables.push_back(problem->MakeNumVar(0, 1, "FictiveLoads::area::hour<25>")); + slackVariables.push_back(problem->MakeNumVar(0, 1, "FictiveLoads::area::hour<56>")); + + InfeasibleProblemReport report(slackVariables); + report.storeInfeasibilityCauses(); + auto reportLogs = report.getLogs(); + + BOOST_CHECK_EQUAL(reportLogs.size(), 3); // Expecting 3 lines in the report + BOOST_CHECK_EQUAL(reportLogs[1], "* Hourly binding constraints."); + BOOST_CHECK_EQUAL(reportLogs[2], "* Last resort shedding status."); +} + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file From 4666c564de2d3e9f4815bbe981ba3b15422ca705 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 10 Jul 2024 17:47:19 +0200 Subject: [PATCH 61/78] Improve infeasible pb test : test slack analysis results (list of slack variables, ordered and trimmed) --- .../constraint-slack-analysis.cpp | 7 ++- .../constraint-slack-analysis.h | 2 + .../watched-constraints.cpp | 2 +- .../test-unfeasible-problem-analyzer.cpp | 48 +++++++++++++++++-- 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index d1fc9c383e..d794a6d73f 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -138,12 +138,17 @@ bool ConstraintSlackAnalysis::anySlackVariableNonZero() [&](auto& v) { return v->solution_value() > thresholdNonZero; }); } +std::vector& ConstraintSlackAnalysis::largestSlackVariables() +{ + return slackVariables_; +} + void ConstraintSlackAnalysis::printReport() const { InfeasibleProblemReport report(slackVariables_); report.storeSuspiciousConstraints(); report.storeInfeasibilityCauses(); - std::ranges::for_each(report.getLogs(), [](auto& line) { logs.error() << line; }); + std::ranges::for_each(report.getLogs(), [](auto& line) { logs.notice() << line; }); } } // namespace Antares::Optimization diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h index ccb3f55acd..d00c395958 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h @@ -52,6 +52,8 @@ class ConstraintSlackAnalysis: public UnfeasibilityAnalysis return "Slack variables analysis"; } + std::vector& largestSlackVariables(); + private: void selectConstraintsToWatch(operations_research::MPSolver* problem); void addSlackVariablesToConstraints(operations_research::MPSolver* problem); diff --git a/src/solver/infeasible-problem-analysis/watched-constraints.cpp b/src/solver/infeasible-problem-analysis/watched-constraints.cpp index 0584b469d4..3404dc06d2 100644 --- a/src/solver/infeasible-problem-analysis/watched-constraints.cpp +++ b/src/solver/infeasible-problem-analysis/watched-constraints.cpp @@ -36,7 +36,7 @@ std::string StringBetweenAngleBrackets(const std::string& constraintName) std::string timeStep(std::vector splitName) { - return StringBetweenAngleBrackets(splitName.back()); + return StringBetweenAngleBrackets(splitName.rbegin()[1]); } std::string shortName(std::vector splitName) diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index 748fa5e14f..a8e062efcf 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -179,6 +179,29 @@ std::unique_ptr createUnfeasibleProblem(const std::string& constraintN return problem; } +std::unique_ptr create_3_constraintsViolationsProblem() +{ + std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); + const double infinity = problem->infinity(); + + auto* var1 = problem->MakeNumVar(0, 1, "var1"); + auto* constr1 = problem->MakeRowConstraint("BC-name-1::hourly::hour<5>"); + constr1->SetBounds(2, infinity); + constr1->SetCoefficient(var1, 1); + + auto* var2 = problem->MakeNumVar(0, 1, "var2"); + auto* constr2 = problem->MakeRowConstraint("BC-name-2::hourly::hour<10>"); + constr2->SetBounds(4, infinity); + constr2->SetCoefficient(var2, 1); + + auto* var3 = problem->MakeNumVar(0, 1, "var3"); + auto* constr3 = problem->MakeRowConstraint("BC-name-3::hourly::hour<15>"); + constr3->SetBounds(8, infinity); + constr3->SetCoefficient(var3, 1); + + return problem; +} + static const std::string validConstraintNames[] = {"BC-name-1::hourly::hour<36>", "BC-name-2::daily::day<67>", "BC-name-3::weekly::week<12>", @@ -218,6 +241,23 @@ BOOST_AUTO_TEST_CASE(analysis_should_ignore_feasible_constraints) analysis.run(feasibleProblem.get()); BOOST_CHECK(!analysis.hasDetectedInfeasibilityCause()); } + +BOOST_AUTO_TEST_CASE(analysis_resulting_slack_variables_are_ordered_and_trimmed) +{ + std::unique_ptr problem = create_3_constraintsViolationsProblem(); + BOOST_CHECK(problem->Solve() == MPSolver::INFEASIBLE); + + ConstraintSlackAnalysis analysis; + analysis.run(problem.get()); + BOOST_CHECK(analysis.hasDetectedInfeasibilityCause()); + + auto& violatedConstraints = analysis.largestSlackVariables(); + BOOST_CHECK_EQUAL(violatedConstraints.size(), 3); + BOOST_CHECK_EQUAL(violatedConstraints[0]->name(), "BC-name-3::hourly::hour<15>::low"); + BOOST_CHECK_EQUAL(violatedConstraints[1]->name(), "BC-name-2::hourly::hour<10>::low"); + BOOST_CHECK_EQUAL(violatedConstraints[2]->name(), "BC-name-1::hourly::hour<5>::low"); +} + BOOST_AUTO_TEST_SUITE_END() @@ -229,10 +269,10 @@ BOOST_AUTO_TEST_CASE(constraints_associated_to_all_incoming_slack_vars_are_repor std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); std::vector slackVariables; - slackVariables.push_back(problem->MakeNumVar(0, 1, "BC-1::hourly::hour<36>")); - slackVariables.push_back(problem->MakeNumVar(0, 1, "BC-2::hourly::hour<65>")); - slackVariables.push_back(problem->MakeNumVar(0, 1, "FictiveLoads::area::hour<25>")); - slackVariables.push_back(problem->MakeNumVar(0, 1, "HydroPower::area::week<45>")); + slackVariables.push_back(problem->MakeNumVar(0, 1, "BC-1::hourly::hour<36>::low")); + slackVariables.push_back(problem->MakeNumVar(0, 1, "BC-2::hourly::hour<65>::up")); + slackVariables.push_back(problem->MakeNumVar(0, 1, "FictiveLoads::area::hour<25>::low")); + slackVariables.push_back(problem->MakeNumVar(0, 1, "HydroPower::area::week<45>::up")); InfeasibleProblemReport report(slackVariables); report.storeSuspiciousConstraints(); From 424269abc611671cfb70bb9043cfd5f995881bea Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Thu, 11 Jul 2024 18:44:10 +0200 Subject: [PATCH 62/78] Improve infeasible pb test : make creation of a problem with infeasible constraints more generic --- .../test-unfeasible-problem-analyzer.cpp | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index a8e062efcf..ae50cca3bb 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -23,6 +23,7 @@ #include +#include #include #include #include @@ -179,26 +180,25 @@ std::unique_ptr createUnfeasibleProblem(const std::string& constraintN return problem; } -std::unique_ptr create_3_constraintsViolationsProblem() +void addInfeasibleConstraintToProblem(MPSolver* problem, const std::string& name, unsigned int numId) { - std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); - const double infinity = problem->infinity(); - - auto* var1 = problem->MakeNumVar(0, 1, "var1"); - auto* constr1 = problem->MakeRowConstraint("BC-name-1::hourly::hour<5>"); - constr1->SetBounds(2, infinity); - constr1->SetCoefficient(var1, 1); - - auto* var2 = problem->MakeNumVar(0, 1, "var2"); - auto* constr2 = problem->MakeRowConstraint("BC-name-2::hourly::hour<10>"); - constr2->SetBounds(4, infinity); - constr2->SetCoefficient(var2, 1); - - auto* var3 = problem->MakeNumVar(0, 1, "var3"); - auto* constr3 = problem->MakeRowConstraint("BC-name-3::hourly::hour<15>"); - constr3->SetBounds(8, infinity); - constr3->SetCoefficient(var3, 1); + // Make a constraint that can never be satisfied, of type : var > A, + // where : bound_inf(var) = 0, bound_sup(var) = 1 and A > 1. + std::string varName = "var" + std::to_string(numId); + auto* var = problem->MakeNumVar(0, 1, varName); // var in [0, 1] + auto* constraint = problem->MakeRowConstraint(name); + constraint->SetCoefficient(var, 1); + constraint->SetBounds(numId + 2, problem->infinity()); // A = numId + 2 > 1 necessarily +} +std::unique_ptr create_n_constraintsViolationsProblem(const unsigned int n) +{ + std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); + for (int i = 1; i <= n; i++) + { + std::string name = std::format("BC-name-{}::hourly::hour<{}>", i, 5*i); + addInfeasibleConstraintToProblem(problem.get(), name, i); + } return problem; } @@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(analysis_should_ignore_feasible_constraints) BOOST_AUTO_TEST_CASE(analysis_resulting_slack_variables_are_ordered_and_trimmed) { - std::unique_ptr problem = create_3_constraintsViolationsProblem(); + std::unique_ptr problem = create_n_constraintsViolationsProblem(3); BOOST_CHECK(problem->Solve() == MPSolver::INFEASIBLE); ConstraintSlackAnalysis analysis; @@ -285,7 +285,7 @@ BOOST_AUTO_TEST_CASE(constraints_associated_to_all_incoming_slack_vars_are_repor BOOST_CHECK_EQUAL(reportLogs[4], "Hydro weekly production at area 'some-area'"); } -BOOST_AUTO_TEST_CASE(infeasibility_cause__only_one_constraint_of_type) +BOOST_AUTO_TEST_CASE(_4_constraints_but_only_2_infeasibility_causes_reported) { // The problem is needed only to create variables, impossible otherwise. std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); From fd439560f4820f244c0d6f1c896041466118dab2 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Mon, 15 Jul 2024 10:36:35 +0200 Subject: [PATCH 63/78] Improve infeasible pb test : adding a test on limit of 10 to detected numbers of constraints --- .../test-unfeasible-problem-analyzer.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index ae50cca3bb..b3b48e3b13 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -242,7 +242,7 @@ BOOST_AUTO_TEST_CASE(analysis_should_ignore_feasible_constraints) BOOST_CHECK(!analysis.hasDetectedInfeasibilityCause()); } -BOOST_AUTO_TEST_CASE(analysis_resulting_slack_variables_are_ordered_and_trimmed) +BOOST_AUTO_TEST_CASE(analysis_slack_variables_are_ordered) { std::unique_ptr problem = create_n_constraintsViolationsProblem(3); BOOST_CHECK(problem->Solve() == MPSolver::INFEASIBLE); @@ -258,6 +258,21 @@ BOOST_AUTO_TEST_CASE(analysis_resulting_slack_variables_are_ordered_and_trimmed) BOOST_CHECK_EQUAL(violatedConstraints[2]->name(), "BC-name-1::hourly::hour<5>::low"); } +BOOST_AUTO_TEST_CASE(analysis_slack_variables_are_ordered_and_limited_to_10) +{ + std::unique_ptr problem = create_n_constraintsViolationsProblem(15); + BOOST_CHECK(problem->Solve() == MPSolver::INFEASIBLE); + + ConstraintSlackAnalysis analysis; + analysis.run(problem.get()); + BOOST_CHECK(analysis.hasDetectedInfeasibilityCause()); + + auto& violatedConstraints = analysis.largestSlackVariables(); + BOOST_CHECK_EQUAL(violatedConstraints.size(), 10); + BOOST_CHECK_EQUAL(violatedConstraints[0]->name(), "BC-name-15::hourly::hour<75>::low"); + BOOST_CHECK_EQUAL(violatedConstraints[9]->name(), "BC-name-6::hourly::hour<30>::low"); +} + BOOST_AUTO_TEST_SUITE_END() From 64516a174211b19cf86c18d8b6320ae5a398c285 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Mon, 15 Jul 2024 11:20:22 +0200 Subject: [PATCH 64/78] Improve infeasible pb test : replace a simple loop on integers with a loop involving std::ranges::iota_view(...) --- .../test-unfeasible-problem-analyzer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index b3b48e3b13..2f980b465b 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -191,10 +192,10 @@ void addInfeasibleConstraintToProblem(MPSolver* problem, const std::string& name constraint->SetBounds(numId + 2, problem->infinity()); // A = numId + 2 > 1 necessarily } -std::unique_ptr create_n_constraintsViolationsProblem(const unsigned int n) +std::unique_ptr create_n_constraintsViolationsProblem(const int n) { std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); - for (int i = 1; i <= n; i++) + for (auto i : std::ranges::iota_view(1, n + 1)) // From 1 to n included { std::string name = std::format("BC-name-{}::hourly::hour<{}>", i, 5*i); addInfeasibleConstraintToProblem(problem.get(), name, i); From 6e40b520268adaa733a2d16d2154178ac0dcdd49 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Mon, 15 Jul 2024 11:57:34 +0200 Subject: [PATCH 65/78] Improve infeasible pb test : fixing a compilation error on Linux ( not available) --- .../test-unfeasible-problem-analyzer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index 2f980b465b..ec8477e8a8 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -23,7 +23,7 @@ #include -#include +#include #include #include #include @@ -197,7 +197,8 @@ std::unique_ptr create_n_constraintsViolationsProblem(const int n) std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); for (auto i : std::ranges::iota_view(1, n + 1)) // From 1 to n included { - std::string name = std::format("BC-name-{}::hourly::hour<{}>", i, 5*i); + char name[32]; + std::sprintf(name, "BC-name-%d::hourly::hour<%d>", i, 5*i); addInfeasibleConstraintToProblem(problem.get(), name, i); } return problem; From e7e1cb096048eccb80f482594b115879695b356f Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Mon, 15 Jul 2024 17:36:56 +0200 Subject: [PATCH 66/78] Improve infeasible pb test : small improvements on unit tests --- .../test-unfeasible-problem-analyzer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index ec8477e8a8..485b2533d9 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -318,8 +318,8 @@ BOOST_AUTO_TEST_CASE(_4_constraints_but_only_2_infeasibility_causes_reported) auto reportLogs = report.getLogs(); BOOST_CHECK_EQUAL(reportLogs.size(), 3); // Expecting 3 lines in the report - BOOST_CHECK_EQUAL(reportLogs[1], "* Hourly binding constraints."); - BOOST_CHECK_EQUAL(reportLogs[2], "* Last resort shedding status."); + BOOST_CHECK(std::ranges::find(reportLogs, "* Hourly binding constraints.") != reportLogs.end()); + BOOST_CHECK(std::ranges::find(reportLogs, "* Last resort shedding status.") != reportLogs.end()); } BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file From 6087b6b84fe75bf20ae27b85f9d27872c0159780 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Mon, 15 Jul 2024 18:08:01 +0200 Subject: [PATCH 67/78] Improve infeasible pb test : restore a wrong removal --- src/solver/infeasible-problem-analysis/report.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index e6789f728a..dc42dce073 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -24,8 +24,6 @@ #include #include -#include - namespace Antares::Optimization { InfeasibleProblemReport::InfeasibleProblemReport( @@ -90,7 +88,7 @@ void InfeasibleProblemReport::storeSuspiciousConstraints() void InfeasibleProblemReport::storeInfeasibilityCauses() { filterConstraintsToOneByType(); - Antares::logs.error() << "Possible causes of infeasibility:"; + report_.push_back("Possible causes of infeasibility:"); for (const auto& c: constraints_) { report_.push_back(c->infeasibilityCause()); From b23ca90d6852a6898d75898f54be6ae9b473c210 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 16 Jul 2024 15:15:40 +0200 Subject: [PATCH 68/78] Improve infeasible pb test : add a new test on reporting infeasibility causes + preliminary work --- .../test-unfeasible-problem-analyzer.cpp | 160 +++++++++++------- 1 file changed, 96 insertions(+), 64 deletions(-) diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index 485b2533d9..dfb135a89b 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -87,6 +87,72 @@ class AnalysisMock: public UnfeasibilityAnalysis bool& hasPrinted_; }; +/*! + * Creates a 2 problems (feasible and infeasible) with 2 variables linked by 1 constraint: + * - Variable 1 must be greater than 1 + * - Variable 2 must be smaller than -1 + * - For infeasible problem, constraint enforces that variable 2 is greater than variable 1 + */ +std::unique_ptr createProblem(const std::string& constraintName) +{ + std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); + const double infinity = problem->infinity(); + problem->MakeNumVar(1, infinity, "var1"); + problem->MakeNumVar(-infinity, -1, "var2"); + auto constraint = problem->MakeRowConstraint(constraintName); + constraint->SetBounds(0, infinity); + return problem; +} + +std::unique_ptr createFeasibleProblem(const std::string& constraintName) +{ + auto problem = createProblem(constraintName); + auto constraint = problem->LookupConstraintOrNull(constraintName); + auto var1 = problem->LookupVariableOrNull("var1"); + auto var2 = problem->LookupVariableOrNull("var2"); + constraint->SetCoefficient(var1, 1); + constraint->SetCoefficient(var2, -1); + return problem; +} + +std::unique_ptr createUnfeasibleProblem(const std::string& constraintName) +{ + auto problem = createProblem(constraintName); + auto constraint = problem->LookupConstraintOrNull(constraintName); + auto var1 = problem->LookupVariableOrNull("var1"); + auto var2 = problem->LookupVariableOrNull("var2"); + constraint->SetCoefficient(var1, -1); + constraint->SetCoefficient(var2, 1); + return problem; +} + +void addOneVarConstraintToProblem(MPSolver* problem, + const std::string& name, + const double& varLowBnd, + const double& varUpBnd, + const double& ConstLowBnd) +{ + std::string varName = "slack-for-" + name; + auto* var = problem->MakeNumVar(varLowBnd, varUpBnd, varName); + auto* constraint = problem->MakeRowConstraint(name); + constraint->SetCoefficient(var, 1); + constraint->SetBounds(ConstLowBnd, problem->infinity()); +} + +std::unique_ptr createProblemWith_n_violatedConstraints(const int n) +{ + std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); + for (auto i : std::ranges::iota_view(1, n + 1)) // From 1 to n included + { + char name[32]; + std::sprintf(name, "BC-name-%d::hourly::hour<%d>", i, 5*i); + // Make a constraint that can never be satisfied, of type : var > A, + // where : bound_inf(var) = 0, bound_sup(var) = 1 and A > 1. + addOneVarConstraintToProblem(problem.get(), name, 0, 1, i + 2); + } + return problem; +} + BOOST_AUTO_TEST_SUITE(general_unfeasible_problem_analyzer) BOOST_AUTO_TEST_CASE(analyzer_should_call_analysis_and_print_detected_issues) @@ -142,68 +208,6 @@ BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE(slack_variables_analyzer) -/*! - * Creates a 2 problems (feasible and infeasible) with 2 variables linked by 1 constraint: - * - Variable 1 must be greater than 1 - * - Variable 2 must be smaller than -1 - * - For infeasible problem, constraint enforces that variable 2 is greater than variable 1 - */ -std::unique_ptr createProblem(const std::string& constraintName) -{ - std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); - const double infinity = problem->infinity(); - problem->MakeNumVar(1, infinity, "var1"); - problem->MakeNumVar(-infinity, -1, "var2"); - auto constraint = problem->MakeRowConstraint(constraintName); - constraint->SetBounds(0, infinity); - return problem; -} - -std::unique_ptr createFeasibleProblem(const std::string& constraintName) -{ - auto problem = createProblem(constraintName); - auto constraint = problem->LookupConstraintOrNull(constraintName); - auto var1 = problem->LookupVariableOrNull("var1"); - auto var2 = problem->LookupVariableOrNull("var2"); - constraint->SetCoefficient(var1, 1); - constraint->SetCoefficient(var2, -1); - return problem; -} - -std::unique_ptr createUnfeasibleProblem(const std::string& constraintName) -{ - auto problem = createProblem(constraintName); - auto constraint = problem->LookupConstraintOrNull(constraintName); - auto var1 = problem->LookupVariableOrNull("var1"); - auto var2 = problem->LookupVariableOrNull("var2"); - constraint->SetCoefficient(var1, -1); - constraint->SetCoefficient(var2, 1); - return problem; -} - -void addInfeasibleConstraintToProblem(MPSolver* problem, const std::string& name, unsigned int numId) -{ - // Make a constraint that can never be satisfied, of type : var > A, - // where : bound_inf(var) = 0, bound_sup(var) = 1 and A > 1. - std::string varName = "var" + std::to_string(numId); - auto* var = problem->MakeNumVar(0, 1, varName); // var in [0, 1] - auto* constraint = problem->MakeRowConstraint(name); - constraint->SetCoefficient(var, 1); - constraint->SetBounds(numId + 2, problem->infinity()); // A = numId + 2 > 1 necessarily -} - -std::unique_ptr create_n_constraintsViolationsProblem(const int n) -{ - std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); - for (auto i : std::ranges::iota_view(1, n + 1)) // From 1 to n included - { - char name[32]; - std::sprintf(name, "BC-name-%d::hourly::hour<%d>", i, 5*i); - addInfeasibleConstraintToProblem(problem.get(), name, i); - } - return problem; -} - static const std::string validConstraintNames[] = {"BC-name-1::hourly::hour<36>", "BC-name-2::daily::day<67>", "BC-name-3::weekly::week<12>", @@ -246,7 +250,7 @@ BOOST_AUTO_TEST_CASE(analysis_should_ignore_feasible_constraints) BOOST_AUTO_TEST_CASE(analysis_slack_variables_are_ordered) { - std::unique_ptr problem = create_n_constraintsViolationsProblem(3); + std::unique_ptr problem = createProblemWith_n_violatedConstraints(3); BOOST_CHECK(problem->Solve() == MPSolver::INFEASIBLE); ConstraintSlackAnalysis analysis; @@ -262,7 +266,7 @@ BOOST_AUTO_TEST_CASE(analysis_slack_variables_are_ordered) BOOST_AUTO_TEST_CASE(analysis_slack_variables_are_ordered_and_limited_to_10) { - std::unique_ptr problem = create_n_constraintsViolationsProblem(15); + std::unique_ptr problem = createProblemWith_n_violatedConstraints(15); BOOST_CHECK(problem->Solve() == MPSolver::INFEASIBLE); ConstraintSlackAnalysis analysis; @@ -322,4 +326,32 @@ BOOST_AUTO_TEST_CASE(_4_constraints_but_only_2_infeasibility_causes_reported) BOOST_CHECK(std::ranges::find(reportLogs, "* Last resort shedding status.") != reportLogs.end()); } + BOOST_AUTO_TEST_CASE(Infeasibility_causes_are_unique_and_sorted_by_salck_value) + { + // The problem is needed only to create variables, impossible otherwise. + std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); + + addOneVarConstraintToProblem(problem.get(), "HydroPower::area::week<0>", 0., 1., 2.); + addOneVarConstraintToProblem(problem.get(), "BC-1::hourly::hour<36>", 0., 1., 3.); + addOneVarConstraintToProblem(problem.get(), "FictiveLoads::area::hour<25>", 0., 1., 4.); + addOneVarConstraintToProblem(problem.get(), "BC-2::hourly::hour<65>", 0., 1., 5.); + addOneVarConstraintToProblem(problem.get(), "FictiveLoads::area::hour<56>", 0., 1., 6.); + + BOOST_CHECK(problem->Solve() == MPSolver::INFEASIBLE); + + ConstraintSlackAnalysis analysis; + analysis.run(problem.get()); + BOOST_CHECK(analysis.hasDetectedInfeasibilityCause()); + + InfeasibleProblemReport report(analysis.largestSlackVariables()); + report.storeInfeasibilityCauses(); + auto reportLogs = report.getLogs(); + + BOOST_CHECK_EQUAL(reportLogs.size(), 4); // Expecting 4 lines in the report + BOOST_CHECK_EQUAL(reportLogs[0], "Possible causes of infeasibility:"); + BOOST_CHECK_EQUAL(reportLogs[1], "* Last resort shedding status."); + BOOST_CHECK_EQUAL(reportLogs[2], "* Hourly binding constraints."); + BOOST_CHECK_EQUAL(reportLogs[3], "* impossible to generate exactly the weekly hydro target"); + } + BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file From 059645fd4505ec482865bd9c7b9cd08ac4065245 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 16 Jul 2024 15:41:32 +0200 Subject: [PATCH 69/78] Improve infeasible pb test : removing a useless test --- .../test-unfeasible-problem-analyzer.cpp | 56 ++++++------------- 1 file changed, 18 insertions(+), 38 deletions(-) diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index dfb135a89b..f44f008516 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -306,52 +306,32 @@ BOOST_AUTO_TEST_CASE(constraints_associated_to_all_incoming_slack_vars_are_repor BOOST_CHECK_EQUAL(reportLogs[4], "Hydro weekly production at area 'some-area'"); } -BOOST_AUTO_TEST_CASE(_4_constraints_but_only_2_infeasibility_causes_reported) +BOOST_AUTO_TEST_CASE(Infeasibility_causes_are_unique_and_sorted_by_salck_value) { // The problem is needed only to create variables, impossible otherwise. std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); - std::vector slackVariables; - slackVariables.push_back(problem->MakeNumVar(0, 1, "BC-1::hourly::hour<36>")); - slackVariables.push_back(problem->MakeNumVar(0, 1, "BC-2::hourly::hour<65>")); - slackVariables.push_back(problem->MakeNumVar(0, 1, "FictiveLoads::area::hour<25>")); - slackVariables.push_back(problem->MakeNumVar(0, 1, "FictiveLoads::area::hour<56>")); + addOneVarConstraintToProblem(problem.get(), "HydroPower::area::week<0>", 0., 1., 2.); + addOneVarConstraintToProblem(problem.get(), "BC-1::hourly::hour<36>", 0., 1., 3.); + addOneVarConstraintToProblem(problem.get(), "FictiveLoads::area::hour<25>", 0., 1., 4.); + addOneVarConstraintToProblem(problem.get(), "BC-2::hourly::hour<65>", 0., 1., 5.); + addOneVarConstraintToProblem(problem.get(), "FictiveLoads::area::hour<56>", 0., 1., 6.); - InfeasibleProblemReport report(slackVariables); + BOOST_CHECK(problem->Solve() == MPSolver::INFEASIBLE); + + ConstraintSlackAnalysis analysis; + analysis.run(problem.get()); + BOOST_CHECK(analysis.hasDetectedInfeasibilityCause()); + + InfeasibleProblemReport report(analysis.largestSlackVariables()); report.storeInfeasibilityCauses(); auto reportLogs = report.getLogs(); - BOOST_CHECK_EQUAL(reportLogs.size(), 3); // Expecting 3 lines in the report - BOOST_CHECK(std::ranges::find(reportLogs, "* Hourly binding constraints.") != reportLogs.end()); - BOOST_CHECK(std::ranges::find(reportLogs, "* Last resort shedding status.") != reportLogs.end()); + BOOST_CHECK_EQUAL(reportLogs.size(), 4); // Expecting 4 lines in the report + BOOST_CHECK_EQUAL(reportLogs[0], "Possible causes of infeasibility:"); + BOOST_CHECK_EQUAL(reportLogs[1], "* Last resort shedding status."); + BOOST_CHECK_EQUAL(reportLogs[2], "* Hourly binding constraints."); + BOOST_CHECK_EQUAL(reportLogs[3], "* impossible to generate exactly the weekly hydro target"); } - BOOST_AUTO_TEST_CASE(Infeasibility_causes_are_unique_and_sorted_by_salck_value) - { - // The problem is needed only to create variables, impossible otherwise. - std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); - - addOneVarConstraintToProblem(problem.get(), "HydroPower::area::week<0>", 0., 1., 2.); - addOneVarConstraintToProblem(problem.get(), "BC-1::hourly::hour<36>", 0., 1., 3.); - addOneVarConstraintToProblem(problem.get(), "FictiveLoads::area::hour<25>", 0., 1., 4.); - addOneVarConstraintToProblem(problem.get(), "BC-2::hourly::hour<65>", 0., 1., 5.); - addOneVarConstraintToProblem(problem.get(), "FictiveLoads::area::hour<56>", 0., 1., 6.); - - BOOST_CHECK(problem->Solve() == MPSolver::INFEASIBLE); - - ConstraintSlackAnalysis analysis; - analysis.run(problem.get()); - BOOST_CHECK(analysis.hasDetectedInfeasibilityCause()); - - InfeasibleProblemReport report(analysis.largestSlackVariables()); - report.storeInfeasibilityCauses(); - auto reportLogs = report.getLogs(); - - BOOST_CHECK_EQUAL(reportLogs.size(), 4); // Expecting 4 lines in the report - BOOST_CHECK_EQUAL(reportLogs[0], "Possible causes of infeasibility:"); - BOOST_CHECK_EQUAL(reportLogs[1], "* Last resort shedding status."); - BOOST_CHECK_EQUAL(reportLogs[2], "* Hourly binding constraints."); - BOOST_CHECK_EQUAL(reportLogs[3], "* impossible to generate exactly the weekly hydro target"); - } - BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file From 17fecd66937352c14477bc22d5f7b0361c01eb51 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 16 Jul 2024 16:46:24 +0200 Subject: [PATCH 70/78] Format --- .../constraint-slack-analysis.cpp | 3 +- .../test-unfeasible-problem-analyzer.cpp | 33 ++++++++++++------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index d794a6d73f..662b12c2dc 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -138,7 +138,8 @@ bool ConstraintSlackAnalysis::anySlackVariableNonZero() [&](auto& v) { return v->solution_value() > thresholdNonZero; }); } -std::vector& ConstraintSlackAnalysis::largestSlackVariables() +std::vector& +ConstraintSlackAnalysis::largestSlackVariables() { return slackVariables_; } diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index f44f008516..85fb8fcc37 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -21,29 +21,29 @@ #define WIN32_LEAN_AND_MEAN #define BOOST_TEST_MODULE unfeasible_problem_analyzer -#include - #include +#include #include + #include #include #include #include "antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h" +#include "antares/solver/infeasible-problem-analysis/report.h" #include "antares/solver/infeasible-problem-analysis/unfeasible-pb-analyzer.h" #include "antares/solver/infeasible-problem-analysis/variables-bounds-consistency.h" -#include "antares/solver/infeasible-problem-analysis/report.h" namespace bdata = boost::unit_test::data; using namespace operations_research; using Antares::Optimization::ConstraintSlackAnalysis; +using Antares::Optimization::InfeasibleProblemReport; using Antares::Optimization::UnfeasibilityAnalysis; using Antares::Optimization::UnfeasiblePbAnalyzer; using Antares::Optimization::VariableBounds; using Antares::Optimization::VariablesBoundsConsistency; -using Antares::Optimization::InfeasibleProblemReport; bool variableEquals(const VariableBounds& lhs, const VariableBounds& rhs) { @@ -142,10 +142,10 @@ void addOneVarConstraintToProblem(MPSolver* problem, std::unique_ptr createProblemWith_n_violatedConstraints(const int n) { std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); - for (auto i : std::ranges::iota_view(1, n + 1)) // From 1 to n included + for (auto i: std::ranges::iota_view(1, n + 1)) // From 1 to n included { char name[32]; - std::sprintf(name, "BC-name-%d::hourly::hour<%d>", i, 5*i); + std::sprintf(name, "BC-name-%d::hourly::hour<%d>", i, 5 * i); // Make a constraint that can never be satisfied, of type : var > A, // where : bound_inf(var) = 0, bound_sup(var) = 1 and A > 1. addOneVarConstraintToProblem(problem.get(), name, 0, 1, i + 2); @@ -281,7 +281,6 @@ BOOST_AUTO_TEST_CASE(analysis_slack_variables_are_ordered_and_limited_to_10) BOOST_AUTO_TEST_SUITE_END() - BOOST_AUTO_TEST_SUITE(slack_variables_report) BOOST_AUTO_TEST_CASE(constraints_associated_to_all_incoming_slack_vars_are_reported) @@ -292,8 +291,10 @@ BOOST_AUTO_TEST_CASE(constraints_associated_to_all_incoming_slack_vars_are_repor std::vector slackVariables; slackVariables.push_back(problem->MakeNumVar(0, 1, "BC-1::hourly::hour<36>::low")); slackVariables.push_back(problem->MakeNumVar(0, 1, "BC-2::hourly::hour<65>::up")); - slackVariables.push_back(problem->MakeNumVar(0, 1, "FictiveLoads::area::hour<25>::low")); - slackVariables.push_back(problem->MakeNumVar(0, 1, "HydroPower::area::week<45>::up")); + slackVariables.push_back( + problem->MakeNumVar(0, 1, "FictiveLoads::area::hour<25>::low")); + slackVariables.push_back( + problem->MakeNumVar(0, 1, "HydroPower::area::week<45>::up")); InfeasibleProblemReport report(slackVariables); report.storeSuspiciousConstraints(); @@ -313,9 +314,17 @@ BOOST_AUTO_TEST_CASE(Infeasibility_causes_are_unique_and_sorted_by_salck_value) addOneVarConstraintToProblem(problem.get(), "HydroPower::area::week<0>", 0., 1., 2.); addOneVarConstraintToProblem(problem.get(), "BC-1::hourly::hour<36>", 0., 1., 3.); - addOneVarConstraintToProblem(problem.get(), "FictiveLoads::area::hour<25>", 0., 1., 4.); + addOneVarConstraintToProblem(problem.get(), + "FictiveLoads::area::hour<25>", + 0., + 1., + 4.); addOneVarConstraintToProblem(problem.get(), "BC-2::hourly::hour<65>", 0., 1., 5.); - addOneVarConstraintToProblem(problem.get(), "FictiveLoads::area::hour<56>", 0., 1., 6.); + addOneVarConstraintToProblem(problem.get(), + "FictiveLoads::area::hour<56>", + 0., + 1., + 6.); BOOST_CHECK(problem->Solve() == MPSolver::INFEASIBLE); @@ -334,4 +343,4 @@ BOOST_AUTO_TEST_CASE(Infeasibility_causes_are_unique_and_sorted_by_salck_value) BOOST_CHECK_EQUAL(reportLogs[3], "* impossible to generate exactly the weekly hydro target"); } -BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file +BOOST_AUTO_TEST_SUITE_END() From 72db8421c2363b74e898be66e32306df7f95e1e9 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Tue, 16 Jul 2024 17:57:13 +0200 Subject: [PATCH 71/78] [skip ci] Improve infeasible pb test : very small fix --- .../test-unfeasible-problem-analyzer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index 85fb8fcc37..aacb9e0b37 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -307,7 +307,7 @@ BOOST_AUTO_TEST_CASE(constraints_associated_to_all_incoming_slack_vars_are_repor BOOST_CHECK_EQUAL(reportLogs[4], "Hydro weekly production at area 'some-area'"); } -BOOST_AUTO_TEST_CASE(Infeasibility_causes_are_unique_and_sorted_by_salck_value) +BOOST_AUTO_TEST_CASE(Infeasibility_causes_are_unique_and_sorted_by_slack_value) { // The problem is needed only to create variables, impossible otherwise. std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); From 6c3646b19459ce23cf41c8b40989fc30e2a877b0 Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Wed, 17 Jul 2024 15:06:15 +0200 Subject: [PATCH 72/78] Remove manual dynamic memory usage (#2254) Replaced new[] with vectors Made RunTimeInfos static --- src/api/API.cpp | 2 +- src/libs/antares/study/CMakeLists.txt | 1 - .../antares/study/progression/progression.h | 10 +-- .../include/antares/study/runtime/runtime.h | 12 ++- .../include/antares/study/runtime/runtime.hxx | 37 --------- .../study/include/antares/study/study.h | 4 +- .../antares/study/progression/progression.cpp | 2 +- src/libs/antares/study/runtime/runtime.cpp | 1 + src/libs/antares/study/study.cpp | 43 +++++----- src/libs/antares/study/study.importprepro.cpp | 2 +- .../application/ScenarioBuilderOwner.cpp | 2 +- src/solver/application/application.cpp | 3 +- src/solver/simulation/adequacy.cpp | 4 +- src/solver/simulation/common-eco-adq.cpp | 16 ++-- src/solver/simulation/economy.cpp | 2 +- .../solver/simulation/common-eco-adq.h | 2 +- .../antares/solver/simulation/solver.hxx | 49 ++++++----- .../antares/solver/simulation/solver_utils.h | 81 +++++-------------- .../simulation/sim_alloc_probleme_hebdo.cpp | 26 +++--- .../simulation/sim_allocation_tableaux.cpp | 4 +- .../simulation/sim_calcul_economique.cpp | 12 +-- src/solver/simulation/timeseries-numbers.cpp | 23 +++--- src/solver/ts-generator/hydro.cpp | 18 ++--- .../antares/solver/ts-generator/generator.hxx | 8 +- .../solver/variable/adequacy/overallCost.h | 2 +- .../variable/commons/spatial-aggregate.h | 2 +- .../solver/variable/economy/links/flowQuad.h | 2 +- .../variable/economy/nbOfDispatchedUnits.h | 4 +- .../economy/nbOfDispatchedUnitsByPlant.h | 6 +- .../variable/economy/nonProportionalCost.h | 4 +- .../economy/npCostByDispatchablePlant.h | 4 +- .../solver/variable/economy/operatingCost.h | 4 +- .../solver/variable/economy/overallCost.h | 4 +- .../economy/productionByDispatchablePlant.h | 2 +- .../antares/solver/variable/storage/average.h | 2 +- .../solver/variable/storage/averagedata.h | 2 +- .../antares/solver/variable/storage/raw.h | 2 +- .../antares/solver/variable/storage/rawdata.h | 2 +- src/solver/variable/state.cpp | 12 +-- src/solver/variable/storage/averagedata.cpp | 8 +- src/solver/variable/storage/intermediate.cpp | 4 +- src/solver/variable/storage/rawdata.cpp | 8 +- .../variable/surveyresults/surveyresults.cpp | 20 ++--- src/tests/inmemory-study/in-memory-study.cpp | 2 +- src/tests/src/api_internal/test_api.cpp | 2 +- .../src/libs/antares/study/test_study.cpp | 2 +- .../test-store-timeseries-number.cpp | 7 +- .../solver/simulation/test-time_series.cpp | 7 +- .../solver/simulation/tests-ts-numbers.cpp | 39 +++++---- src/tools/ts-generator/linksTSgenerator.cpp | 2 +- 50 files changed, 209 insertions(+), 310 deletions(-) delete mode 100644 src/libs/antares/study/include/antares/study/runtime/runtime.hxx diff --git a/src/api/API.cpp b/src/api/API.cpp index 38e9778eab..a76eb934ec 100644 --- a/src/api/API.cpp +++ b/src/api/API.cpp @@ -78,7 +78,7 @@ SimulationResults APIInternal::execute() const study_->parameters.resultFormat, study_->folderOutput, ioQueueService, durationCollector); SimulationObserver simulationObserver; // Run the simulation - switch (study_->runtime->mode) + switch (study_->runtime.mode) { case Data::SimulationMode::Economy: case Data::SimulationMode::Expansion: diff --git a/src/libs/antares/study/CMakeLists.txt b/src/libs/antares/study/CMakeLists.txt index 3ec77caaed..e9a05827ac 100644 --- a/src/libs/antares/study/CMakeLists.txt +++ b/src/libs/antares/study/CMakeLists.txt @@ -208,7 +208,6 @@ set(SRC_STUDY include/antares/study/load-options.h load-options.cpp include/antares/study/runtime/runtime.h - include/antares/study/runtime/runtime.hxx runtime/runtime.cpp include/antares/study/runtime.h include/antares/study/study.h diff --git a/src/libs/antares/study/include/antares/study/progression/progression.h b/src/libs/antares/study/include/antares/study/progression/progression.h index bcdeca82ac..5e013df957 100644 --- a/src/libs/antares/study/include/antares/study/progression/progression.h +++ b/src/libs/antares/study/include/antares/study/progression/progression.h @@ -76,11 +76,11 @@ class Progression final public: //! The total number of ticks to achieve - int maxTickCount; + unsigned maxTickCount; //! The current number of ticks - std::atomic tickCount; + std::atomic tickCount; //! The last number of ticks, to reduce the log verbosity - int lastTickCount; + unsigned lastTickCount; // Caption to use when displaying logs // Example: 'year: 10000, task: thermal' Yuni::CString<40, false> caption; @@ -104,7 +104,7 @@ class Progression final return *this; } - Task& operator+=(int value) + Task& operator+=(unsigned value) { pPart.tickCount += value; return *this; @@ -138,7 +138,7 @@ class Progression final ** \internal The number of ticks should remain an `int` because ** we can not use unsigned atomic integer */ - void add(uint year, Section section, int nbTicks); + void add(uint year, Section section, unsigned nbTicks); void add(Section section, int nbTicks); diff --git a/src/libs/antares/study/include/antares/study/runtime/runtime.h b/src/libs/antares/study/include/antares/study/runtime/runtime.h index 0ea07ce3bc..d87761674f 100644 --- a/src/libs/antares/study/include/antares/study/runtime/runtime.h +++ b/src/libs/antares/study/include/antares/study/runtime/runtime.h @@ -25,11 +25,13 @@ #include #include -#include "antares/study/study.h" +#include namespace Antares::Data { +class Study; + enum RangeLimitsIndex { rangeBegin = 0, @@ -139,8 +141,12 @@ class StudyRuntimeInfos void checkThermalTSGeneration(Study& study); }; // struct StudyRuntimeInfos -} // namespace Antares::Data +#ifdef NDEBUG +inline void StudyRangeLimits::checkIntegrity() const +{ +} +#endif -#include "runtime.hxx" +} // namespace Antares::Data #endif // __ANTARES_LIBS_STUDY_RUNTIME_RUNTIME_INFOS_H__ diff --git a/src/libs/antares/study/include/antares/study/runtime/runtime.hxx b/src/libs/antares/study/include/antares/study/runtime/runtime.hxx deleted file mode 100644 index 0e04ed3b93..0000000000 --- a/src/libs/antares/study/include/antares/study/runtime/runtime.hxx +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2007-2024, RTE (https://www.rte-france.com) - * See AUTHORS.txt - * SPDX-License-Identifier: MPL-2.0 - * This file is part of Antares-Simulator, - * Adequacy and Performance assessment for interconnected energy networks. - * - * Antares_Simulator is free software: you can redistribute it and/or modify - * it under the terms of the Mozilla Public Licence 2.0 as published by - * the Mozilla Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * Antares_Simulator is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * Mozilla Public Licence 2.0 for more details. - * - * You should have received a copy of the Mozilla Public Licence 2.0 - * along with Antares_Simulator. If not, see . - */ -#ifndef __ANTARES_LIBS_STUDY_RUNTIME_RUNTIME_INFOS_HXX__ -#define __ANTARES_LIBS_STUDY_RUNTIME_RUNTIME_INFOS_HXX__ - -namespace Antares -{ -namespace Data -{ -#ifdef NDEBUG -inline void StudyRangeLimits::checkIntegrity() const -{ -} -#endif - -} // namespace Data -} // namespace Antares - -#endif // __ANTARES_LIBS_STUDY_RUNTIME_RUNTIME_INFOS_HXX__ diff --git a/src/libs/antares/study/include/antares/study/study.h b/src/libs/antares/study/include/antares/study/study.h index 03e2df8bed..65f8f531fd 100644 --- a/src/libs/antares/study/include/antares/study/study.h +++ b/src/libs/antares/study/include/antares/study/study.h @@ -31,6 +31,7 @@ #include #include +#include #include #include "antares/antares/antares.h" #include "antares/study/binding_constraint/BindingConstraintGroupRepository.h" @@ -596,7 +597,7 @@ class Study: public Yuni::NonCopyable, public LayerData ** ** These informations are only needed when a study is processed. */ - StudyRuntimeInfos* runtime = nullptr; + StudyRuntimeInfos runtime; // Antares::Solver::Variable::State* state; @@ -690,7 +691,6 @@ YString StudyCreateOutputPath(SimulationMode mode, int64_t startTime); } // namespace Antares::Data -#include "runtime.h" #include "study.hxx" #endif /* __ANTARES_LIBS_STUDY_STUDY_H__ */ diff --git a/src/libs/antares/study/progression/progression.cpp b/src/libs/antares/study/progression/progression.cpp index a78c86959f..28c1d3288e 100644 --- a/src/libs/antares/study/progression/progression.cpp +++ b/src/libs/antares/study/progression/progression.cpp @@ -42,7 +42,7 @@ Progression::Task::Task(const Antares::Data::Study& study, uint year, Section se assert(&pProgression); } -void Progression::add(uint year, Section section, int nbTicks) +void Progression::add(uint year, Section section, unsigned nbTicks) { // This section is not thread-safe because always called before really launching // the simulation diff --git a/src/libs/antares/study/runtime/runtime.cpp b/src/libs/antares/study/runtime/runtime.cpp index 1bb7e46386..61be13d6cf 100644 --- a/src/libs/antares/study/runtime/runtime.cpp +++ b/src/libs/antares/study/runtime/runtime.cpp @@ -21,6 +21,7 @@ #include "antares/study/runtime/runtime.h" +#include #include #include "antares/antares/fatal-error.h" #include "antares/study/area/scratchpad.h" diff --git a/src/libs/antares/study/study.cpp b/src/libs/antares/study/study.cpp index 5b1dde8c5f..01d91b3abb 100644 --- a/src/libs/antares/study/study.cpp +++ b/src/libs/antares/study/study.cpp @@ -104,8 +104,6 @@ Study::~Study() void Study::clear() { - // Releasing runtime infos - FreeAndNil(runtime); FreeAndNil(scenarioRules); FreeAndNil(uiinfo); @@ -504,9 +502,7 @@ void Study::getNumberOfCores(const bool forceParallel, const uint nbYearsParalle bool Study::initializeRuntimeInfos() { - delete runtime; - runtime = new StudyRuntimeInfos(); - return runtime->loadFromStudy(*this); + return runtime.loadFromStudy(*this); } void Study::performTransformationsBeforeLaunchingSimulation() @@ -1164,25 +1160,24 @@ struct TS final void Study::initializeProgressMeter(bool tsGeneratorOnly) { - uint years = tsGeneratorOnly ? 1 : (runtime->rangeLimits.year[rangeEnd] + 1); - assert(runtime); + uint years = tsGeneratorOnly ? 1 : (runtime.rangeLimits.year[rangeEnd] + 1); - int ticksPerYear = 0; - int ticksPerOutput = 0; + unsigned ticksPerYear = 0; + unsigned ticksPerOutput = 0; if (not tsGeneratorOnly) { // One tick at the begining and 2 at the end of the year // Output - Areas - ticksPerOutput += (int)areas.size(); + ticksPerOutput += areas.size(); // Output - Links - ticksPerOutput += (int)runtime->interconnectionsCount(); + ticksPerOutput += runtime.interconnectionsCount(); // Output - digest ticksPerOutput += 1; ticksPerYear = 1; } - int n; + unsigned n; for (uint y = 0; y != years; ++y) { @@ -1191,7 +1186,7 @@ void Study::initializeProgressMeter(bool tsGeneratorOnly) n = parameters.nbTimeSeriesLoad * areas.size() * 365; if (0 != (timeSeriesLoad & parameters.timeSeriesToArchive)) { - n += (int)areas.size(); + n += areas.size(); } progression.add(y, Solver::Progression::sectTSGLoad, n); } @@ -1200,7 +1195,7 @@ void Study::initializeProgressMeter(bool tsGeneratorOnly) n = parameters.nbTimeSeriesSolar * areas.size() * 365; if (0 != (timeSeriesSolar & parameters.timeSeriesToArchive)) { - n += (int)areas.size(); + n += areas.size(); } progression.add(y, Solver::Progression::sectTSGSolar, n); } @@ -1209,7 +1204,7 @@ void Study::initializeProgressMeter(bool tsGeneratorOnly) n = parameters.nbTimeSeriesWind * areas.size() * 365; if (0 != (timeSeriesWind & parameters.timeSeriesToArchive)) { - n += (int)areas.size(); + n += areas.size(); } progression.add(y, Solver::Progression::sectTSGWind, n); } @@ -1219,17 +1214,17 @@ void Study::initializeProgressMeter(bool tsGeneratorOnly) n = parameters.nbTimeSeriesHydro; if (0 != (timeSeriesHydro & parameters.timeSeriesToArchive)) { - n += (int)areas.size(); + n += areas.size(); } progression.add(y, Solver::Progression::sectTSGHydro, n); } if (TS::IsNeeded(*this, y)) { - n = runtime->thermalPlantTotalCount; + n = runtime.thermalPlantTotalCount; if (0 != (timeSeriesThermal & parameters.timeSeriesToArchive)) { - n += (int)runtime->thermalPlantTotalCount; - n += (int)runtime->thermalPlantTotalCountMustRun; + n += runtime.thermalPlantTotalCount; + n += runtime.thermalPlantTotalCountMustRun; } progression.add(y, Solver::Progression::sectTSGThermal, n); } @@ -1249,23 +1244,23 @@ void Study::initializeProgressMeter(bool tsGeneratorOnly) n = 0; if (0 != (timeSeriesLoad & parameters.exportTimeSeriesInInput)) { - n += (int)areas.size(); + n += areas.size(); } if (0 != (timeSeriesSolar & parameters.exportTimeSeriesInInput)) { - n += (int)areas.size(); + n += areas.size(); } if (0 != (timeSeriesWind & parameters.exportTimeSeriesInInput)) { - n += (int)areas.size(); + n += areas.size(); } if (0 != (timeSeriesHydro & parameters.exportTimeSeriesInInput)) { - n += (int)areas.size(); + n += areas.size(); } if (0 != (timeSeriesThermal & parameters.exportTimeSeriesInInput)) { - n += (int)areas.size(); + n += areas.size(); } if (n) { diff --git a/src/libs/antares/study/study.importprepro.cpp b/src/libs/antares/study/study.importprepro.cpp index f7c8082050..69a0fe058b 100644 --- a/src/libs/antares/study/study.importprepro.cpp +++ b/src/libs/antares/study/study.importprepro.cpp @@ -33,7 +33,7 @@ bool Study::importTimeseriesIntoInput() { // Special case: some thermal clusters may force TS generation const bool importThermal = parameters.haveToImport(timeSeriesThermal) - && runtime->thermalTSRefresh; + && runtime.thermalTSRefresh; // Something to import ? if ((parameters.exportTimeSeriesInInput && parameters.timeSeriesToGenerate) || importThermal) { diff --git a/src/solver/application/ScenarioBuilderOwner.cpp b/src/solver/application/ScenarioBuilderOwner.cpp index 69f9d11799..f2f0c90c7e 100644 --- a/src/solver/application/ScenarioBuilderOwner.cpp +++ b/src/solver/application/ScenarioBuilderOwner.cpp @@ -39,7 +39,7 @@ void Antares::Solver::ScenarioBuilderOwner::callScenarioBuilder() // We will resize all matrix related to the time-series numbers // This operation can be done once since the number of years is constant // for a single simulation - study_.resizeAllTimeseriesNumbers(1 + study_.runtime->rangeLimits.year[Data::rangeEnd]); + study_.resizeAllTimeseriesNumbers(1 + study_.runtime.rangeLimits.year[Data::rangeEnd]); if (not TimeSeriesNumbers::CheckNumberOfColumns(study_.areas)) { throw FatalError( diff --git a/src/solver/application/application.cpp b/src/solver/application/application.cpp index c65e849a15..334e8f86d7 100644 --- a/src/solver/application/application.cpp +++ b/src/solver/application/application.cpp @@ -224,7 +224,6 @@ void Application::readDataForTheStudy(Data::StudyLoadOptions& options) writeComment(study); } - // Runtime data dedicated for the solver if (!study.initializeRuntimeInfos()) { throw Error::RuntimeInfoInitialization(); @@ -391,7 +390,7 @@ void Application::execute() pStudy->computePThetaInfForThermalClusters(); // Run the simulation - switch (pStudy->runtime->mode) + switch (pStudy->runtime.mode) { case Data::SimulationMode::Economy: case Data::SimulationMode::Expansion: diff --git a/src/solver/simulation/adequacy.cpp b/src/solver/simulation/adequacy.cpp index f4759a0ab1..eed49029e8 100644 --- a/src/solver/simulation/adequacy.cpp +++ b/src/solver/simulation/adequacy.cpp @@ -258,7 +258,7 @@ bool Adequacy::year(Progression::Task& progression, state.resSpilled.zero(); auto nbAreas = study.areas.size(); - auto& runtime = *(study.runtime); + auto& runtime = study.runtime; for (uint i = 0; i != nbHoursInAWeek; ++i) { @@ -399,7 +399,7 @@ static std::vector retrieveBalance( void Adequacy::simulationEnd() { - if (!preproOnly && study.runtime->interconnectionsCount() > 0) + if (!preproOnly && study.runtime.interconnectionsCount() > 0) { auto balance = retrieveBalance(study, variables); ComputeFlowQuad(study, pProblemesHebdo[0], balance, pNbWeeks); diff --git a/src/solver/simulation/common-eco-adq.cpp b/src/solver/simulation/common-eco-adq.cpp index 27d2cdae6c..bfc697372a 100644 --- a/src/solver/simulation/common-eco-adq.cpp +++ b/src/solver/simulation/common-eco-adq.cpp @@ -60,9 +60,9 @@ static void RecalculDesEchangesMoyens(Data::Study& study, std::vector avgDirect; std::vector avgIndirect; - for (uint j = 0; j < study.runtime->interconnectionsCount(); ++j) + for (uint j = 0; j < study.runtime.interconnectionsCount(); ++j) { - auto* link = study.runtime->areaLink[j]; + auto* link = study.runtime.areaLink[j]; int ret = retrieveAverageNTC(study, link->directCapacities.timeSeries, link->timeseriesNumbers, @@ -100,7 +100,7 @@ static void RecalculDesEchangesMoyens(Data::Study& study, } catch (Data::UnfeasibleProblemError&) { - study.runtime->quadraticOptimizationHasFailed = true; + study.runtime.quadraticOptimizationHasFailed = true; } for (uint i = 0; i < (uint)problem.NombreDePasDeTemps; ++i) @@ -108,7 +108,7 @@ static void RecalculDesEchangesMoyens(Data::Study& study, const uint indx = i + PasDeTempsDebut; auto& ntcValues = problem.ValeursDeNTC[i]; - for (uint j = 0; j < study.runtime->interconnectionsCount(); ++j) + for (uint j = 0; j < study.runtime.interconnectionsCount(); ++j) { transitMoyenInterconnexionsRecalculQuadratique[j][indx] = ntcValues.ValeurDuFlux[j]; } @@ -123,9 +123,9 @@ bool ShouldUseQuadraticOptimisation(const Data::Study& study) return false; } - for (uint j = 0; j < study.runtime->interconnectionsCount(); ++j) + for (uint j = 0; j < study.runtime.interconnectionsCount(); ++j) { - auto& lnk = *(study.runtime->areaLink[j]); + auto& lnk = *(study.runtime.areaLink[j]); auto& impedances = lnk.parameters[Data::fhlImpedances]; for (uint hour = 0; hour < HOURS_PER_YEAR; ++hour) @@ -162,7 +162,7 @@ void ComputeFlowQuad(Data::Study& study, { logs.info() << " The quadratic optimisation has been skipped"; - for (uint j = 0; j < study.runtime->interconnectionsCount(); ++j) + for (uint j = 0; j < study.runtime.interconnectionsCount(); ++j) { for (uint w = 0; w != nbWeeks; ++w) { @@ -360,7 +360,7 @@ void SetInitialHydroLevel(Data::Study& study, void BuildThermalPartOfWeeklyProblem(Data::Study& study, PROBLEME_HEBDO& problem, const int PasDeTempsDebut, - double** thermalNoises, + std::vector>& thermalNoises, unsigned int year) { int hourInYear = PasDeTempsDebut; diff --git a/src/solver/simulation/economy.cpp b/src/solver/simulation/economy.cpp index f14d4cabf0..269fcd26ff 100644 --- a/src/solver/simulation/economy.cpp +++ b/src/solver/simulation/economy.cpp @@ -263,7 +263,7 @@ static std::vector retrieveBalance( void Economy::simulationEnd() { - if (!preproOnly && study.runtime->interconnectionsCount() > 0) + if (!preproOnly && study.runtime.interconnectionsCount() > 0) { auto balance = retrieveBalance(study, variables); ComputeFlowQuad(study, pProblemesHebdo[0], balance, pNbWeeks); diff --git a/src/solver/simulation/include/antares/solver/simulation/common-eco-adq.h b/src/solver/simulation/include/antares/solver/simulation/common-eco-adq.h index 0bf24cd71d..1139bb9ff9 100644 --- a/src/solver/simulation/include/antares/solver/simulation/common-eco-adq.h +++ b/src/solver/simulation/include/antares/solver/simulation/common-eco-adq.h @@ -63,7 +63,7 @@ void SetInitialHydroLevel(Data::Study& study, void BuildThermalPartOfWeeklyProblem(Data::Study& study, PROBLEME_HEBDO& problem, const int PasDeTempsDebut, - double** thermalNoises, + std::vector>& thermalNoises, unsigned int year); /*! diff --git a/src/solver/simulation/include/antares/solver/simulation/solver.hxx b/src/solver/simulation/include/antares/solver/simulation/solver.hxx index 1aa04cb38f..539c1d298e 100644 --- a/src/solver/simulation/include/antares/solver/simulation/solver.hxx +++ b/src/solver/simulation/include/antares/solver/simulation/solver.hxx @@ -146,10 +146,9 @@ public: // Getting random tables for this year yearRandomNumbers& randomForCurrentYear = randomForParallelYears.pYears[indexYear]; - double* randomReservoirLevel = nullptr; // 1 - Applying random levels for current year - randomReservoirLevel = randomForCurrentYear.pReservoirLevels; + auto randomReservoirLevel = randomForCurrentYear.pReservoirLevels; // 2 - Preparing the Time-series numbers // removed @@ -159,7 +158,7 @@ public: // 4 - Hydraulic ventilation pDurationCollector("hydro_ventilation") << [this, &randomReservoirLevel] - { hydroManagement.makeVentilation(randomReservoirLevel, y, scratchmap); }; + { hydroManagement.makeVentilation(randomReservoirLevel.data(), y, scratchmap); }; // Updating the state state.year = y; @@ -326,9 +325,9 @@ void ISimulation::run() logs.info(); // Launching the simulation for all years - logs.info() << "MC-Years : [" << (study.runtime->rangeLimits.year[Data::rangeBegin] + 1) - << " .. " << (1 + study.runtime->rangeLimits.year[Data::rangeEnd]) - << "], total: " << study.runtime->rangeLimits.year[Data::rangeCount]; + logs.info() << "MC-Years : [" << (study.runtime.rangeLimits.year[Data::rangeBegin] + 1) + << " .. " << (1 + study.runtime.rangeLimits.year[Data::rangeEnd]) + << "], total: " << study.runtime.rangeLimits.year[Data::rangeCount]; // Current state std::vector state(pNbMaxPerformedYearsInParallel, Variable::State(study)); @@ -338,7 +337,7 @@ void ISimulation::run() ImplementationType::initializeState(state[numSpace], numSpace); } - uint finalYear = 1 + study.runtime->rangeLimits.year[Data::rangeEnd]; + uint finalYear = 1 + study.runtime.rangeLimits.year[Data::rangeEnd]; { pDurationCollector("mc_years") << [finalYear, &state, this] { loopThroughYears(0, finalYear, state); }; @@ -456,7 +455,7 @@ void ISimulation::regenerateTimeSeries(uint year) auto clusters = getAllClustersToGen(study.areas, pData.haveToRefreshTSThermal); generateThermalTimeSeries(study, clusters, - study.runtime->random[Data::seedTsGenThermal]); + study.runtime.random[Data::seedTsGenThermal]); bool archive = study.parameters.timeSeriesToArchive & Data::timeSeriesThermal; bool doWeWrite = archive && !study.parameters.noOutput; @@ -512,7 +511,7 @@ uint ISimulation::buildSetsOfParallelYears( // Some thermal clusters may override the global parameter. // Therefore, we may want to refresh TS even if pData.haveToRefreshTSThermal == false bool haveToRefreshTSThermal = pData.haveToRefreshTSThermal - || study.runtime->thermalTSRefresh; + || study.runtime.thermalTSRefresh; refreshing = refreshing || (haveToRefreshTSThermal && (y % pData.refreshIntervalThermal == 0)); @@ -606,43 +605,43 @@ void ISimulation::allocateMemoryForRandomNumbers( { // General : randomForParallelYears.pYears[y].setNbAreas(nbAreas); - randomForParallelYears.pYears[y].pNbClustersByArea = new size_t[nbAreas]; + randomForParallelYears.pYears[y].pNbClustersByArea.resize(nbAreas); // Thermal noises : - randomForParallelYears.pYears[y].pThermalNoisesByArea = new double*[nbAreas]; + randomForParallelYears.pYears[y].pThermalNoisesByArea.resize(nbAreas); for (uint a = 0; a != nbAreas; ++a) { // logs.info() << " area : " << a << " :"; auto& area = *(study.areas.byIndex[a]); size_t nbClusters = area.thermal.list.allClustersCount(); - randomForParallelYears.pYears[y].pThermalNoisesByArea[a] = new double[nbClusters]; + randomForParallelYears.pYears[y].pThermalNoisesByArea[a].resize(nbClusters); randomForParallelYears.pYears[y].pNbClustersByArea[a] = nbClusters; } // Reservoir levels - randomForParallelYears.pYears[y].pReservoirLevels = new double[nbAreas]; + randomForParallelYears.pYears[y].pReservoirLevels.resize(nbAreas); // Noises on unsupplied and spilled energy - randomForParallelYears.pYears[y].pUnsuppliedEnergy = new double[nbAreas]; - randomForParallelYears.pYears[y].pSpilledEnergy = new double[nbAreas]; + randomForParallelYears.pYears[y].pUnsuppliedEnergy.resize(nbAreas); + randomForParallelYears.pYears[y].pSpilledEnergy.resize(nbAreas); // Hydro costs noises switch (study.parameters.power.fluctuations) { case Data::lssFreeModulations: { - randomForParallelYears.pYears[y].pHydroCostsByArea_freeMod = new double*[nbAreas]; + randomForParallelYears.pYears[y].pHydroCostsByArea_freeMod.resize(nbAreas); for (uint a = 0; a != nbAreas; ++a) { - randomForParallelYears.pYears[y].pHydroCostsByArea_freeMod[a] = new double[8784]; + randomForParallelYears.pYears[y].pHydroCostsByArea_freeMod[a].resize(8784); } break; } case Data::lssMinimizeRamping: case Data::lssMinimizeExcursions: { - randomForParallelYears.pYears[y].pHydroCosts_rampingOrExcursion = new double[nbAreas]; + randomForParallelYears.pYears[y].pHydroCosts_rampingOrExcursion.resize(nbAreas); break; } case Data::lssUnknown: @@ -661,8 +660,6 @@ void ISimulation::computeRandomNumbers( std::map& isYearPerformed, MersenneTwister& randomHydroGenerator) { - auto& runtime = *study.runtime; - uint indexYear = 0; std::vector::iterator ity; @@ -687,7 +684,7 @@ void ISimulation::computeRandomNumbers( for (auto& cluster: area.thermal.list.all()) { uint clusterIndex = cluster->areaWideIndex; - double thermalNoise = runtime.random[Data::seedThermalCosts].next(); + double thermalNoise = study.runtime.random[Data::seedThermalCosts].next(); if (isPerformed) { randomForYears.pYears[indexYear].pThermalNoisesByArea[a][clusterIndex] @@ -746,8 +743,8 @@ void ISimulation::computeRandomNumbers( // ... Unsupplied and spilled energy costs noises (french : bruits sur la defaillance // positive et negatives) ... references to the random number generators - auto& randomUnsupplied = study.runtime->random[Data::seedUnsuppliedEnergyCosts]; - auto& randomSpilled = study.runtime->random[Data::seedSpilledEnergyCosts]; + auto& randomUnsupplied = study.runtime.random[Data::seedUnsuppliedEnergyCosts]; + auto& randomSpilled = study.runtime.random[Data::seedSpilledEnergyCosts]; int currentSpilledEnergySeed = study.parameters.seed[Data::seedSpilledEnergyCosts]; int defaultSpilledEnergySeed = Data::antaresSeedDefaultValue @@ -787,7 +784,7 @@ void ISimulation::computeRandomNumbers( }); // each area // ... Hydro costs noises ... - auto& randomHydro = study.runtime->random[Data::seedHydroCosts]; + auto& randomHydro = study.runtime.random[Data::seedHydroCosts]; Data::PowerFluctuations powerFluctuations = study.parameters.power.fluctuations; switch (powerFluctuations) @@ -803,8 +800,8 @@ void ISimulation::computeRandomNumbers( { for (auto i = study.areas.begin(); i != end; ++i) { - double* noise = randomForYears.pYears[indexYear] - .pHydroCostsByArea_freeMod[areaIndex]; + auto& noise = randomForYears.pYears[indexYear] + .pHydroCostsByArea_freeMod[areaIndex]; std::set setHydroCostsNoises; for (uint j = 0; j != 8784; ++j) { diff --git a/src/solver/simulation/include/antares/solver/simulation/solver_utils.h b/src/solver/simulation/include/antares/solver/simulation/solver_utils.h index 363b7839f8..d0d8748034 100644 --- a/src/solver/simulation/include/antares/solver/simulation/solver_utils.h +++ b/src/solver/simulation/include/antares/solver/simulation/solver_utils.h @@ -118,52 +118,10 @@ class yearRandomNumbers public: yearRandomNumbers() { - pThermalNoisesByArea = nullptr; - pNbClustersByArea = nullptr; pNbAreas = 0; } - ~yearRandomNumbers() - { - // General - delete[] pNbClustersByArea; - - // Thermal noises - for (uint a = 0; a != pNbAreas; a++) - { - delete[] pThermalNoisesByArea[a]; - } - delete[] pThermalNoisesByArea; - - // Reservoir levels, spilled and unsupplied energy - delete[] pReservoirLevels; - delete[] pUnsuppliedEnergy; - delete[] pSpilledEnergy; - - // Hydro costs noises - switch (pPowerFluctuations) - { - case Data::lssFreeModulations: - { - for (uint a = 0; a != pNbAreas; a++) - { - delete[] pHydroCostsByArea_freeMod[a]; - } - delete[] pHydroCostsByArea_freeMod; - break; - } - - case Data::lssMinimizeRamping: - case Data::lssMinimizeExcursions: - { - delete[] pHydroCosts_rampingOrExcursion; - break; - } - - case Data::lssUnknown: - break; - } - } + ~yearRandomNumbers() = default; void setNbAreas(uint nbAreas) { @@ -178,18 +136,18 @@ class yearRandomNumbers void reset() { // General - memset(pNbClustersByArea, 0, pNbAreas * sizeof(size_t)); + pNbClustersByArea.assign(pNbAreas, 0); // Thermal noises for (uint a = 0; a != pNbAreas; a++) { - memset(pThermalNoisesByArea[a], 0, pNbClustersByArea[a] * sizeof(double)); + pThermalNoisesByArea[a].assign(pNbClustersByArea[a], 0); } // Reservoir levels, spilled and unsupplied energy costs - memset(pReservoirLevels, 0, pNbAreas * sizeof(double)); - memset(pUnsuppliedEnergy, 0, pNbAreas * sizeof(double)); - memset(pSpilledEnergy, 0, pNbAreas * sizeof(double)); + pReservoirLevels.assign(pNbAreas, 0); + pUnsuppliedEnergy.assign(pNbAreas, 0); + pSpilledEnergy.assign(pNbAreas, 0); // Hydro costs noises switch (pPowerFluctuations) @@ -198,7 +156,7 @@ class yearRandomNumbers { for (uint a = 0; a != pNbAreas; a++) { - memset(pHydroCostsByArea_freeMod[a], 0, 8784 * sizeof(double)); + pHydroCostsByArea_freeMod[a].assign(8784, 0); } break; } @@ -206,7 +164,7 @@ class yearRandomNumbers case Data::lssMinimizeRamping: case Data::lssMinimizeExcursions: { - memset(pHydroCosts_rampingOrExcursion, 0, pNbAreas * sizeof(double)); + pHydroCosts_rampingOrExcursion.assign(pNbAreas, 0); break; } @@ -220,19 +178,19 @@ class yearRandomNumbers Data::PowerFluctuations pPowerFluctuations; // Data for thermal noises - double** pThermalNoisesByArea; - size_t* pNbClustersByArea; + std::vector> pThermalNoisesByArea; + std::vector pNbClustersByArea; // Data for reservoir levels - double* pReservoirLevels; + std::vector pReservoirLevels; // Data for unsupplied and spilled energy costs - double* pUnsuppliedEnergy; - double* pSpilledEnergy; + std::vector pUnsuppliedEnergy; + std::vector pSpilledEnergy; // Hydro costs noises - double** pHydroCostsByArea_freeMod; - double* pHydroCosts_rampingOrExcursion; + std::vector> pHydroCostsByArea_freeMod; + std::vector pHydroCosts_rampingOrExcursion; }; class randomNumbers @@ -242,7 +200,7 @@ class randomNumbers pMaxNbPerformedYears(maxNbPerformedYearsInAset) { // Allocate a table of parallel years structures - pYears = new yearRandomNumbers[maxNbPerformedYearsInAset]; + pYears.resize(maxNbPerformedYearsInAset); // Tells these structures their power fluctuations mode for (uint y = 0; y < maxNbPerformedYearsInAset; ++y) @@ -251,10 +209,7 @@ class randomNumbers } } - ~randomNumbers() - { - delete[] pYears; - } + ~randomNumbers() = default; void reset() { @@ -267,7 +222,7 @@ class randomNumbers } uint pMaxNbPerformedYears; - yearRandomNumbers* pYears; + std::vector pYears; // Associates : // year number (0, ..., total nb of years to compute - 1) --> index of the year's space diff --git a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp index 03126fa752..936a8e5ac0 100644 --- a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp +++ b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp @@ -39,7 +39,7 @@ void SIM_AllocationProblemeHebdo(const Data::Study& study, { SIM_AllocationProblemeDonneesGenerales(problem, study, NombreDePasDeTemps); SIM_AllocationProblemePasDeTemps(problem, study, NombreDePasDeTemps); - SIM_AllocationLinks(problem, study.runtime->interconnectionsCount(), NombreDePasDeTemps); + SIM_AllocationLinks(problem, study.runtime.interconnectionsCount(), NombreDePasDeTemps); SIM_AllocationConstraints(problem, study, NombreDePasDeTemps); SIM_AllocateAreas(problem, study, NombreDePasDeTemps); } @@ -55,7 +55,7 @@ void SIM_AllocationProblemeDonneesGenerales(PROBLEME_HEBDO& problem, { uint nbPays = study.areas.size(); - const uint linkCount = study.runtime->interconnectionsCount(); + const uint linkCount = study.runtime.interconnectionsCount(); problem.DefaillanceNegativeUtiliserPMinThermique.assign(nbPays, false); problem.DefaillanceNegativeUtiliserHydro.assign(nbPays, false); @@ -132,8 +132,8 @@ void SIM_AllocationProblemePasDeTemps(PROBLEME_HEBDO& problem, { uint nbPays = study.areas.size(); - const uint linkCount = study.runtime->interconnectionsCount(); - const uint shortTermStorageCount = study.runtime->shortTermStorageCount; + const uint linkCount = study.runtime.interconnectionsCount(); + const uint shortTermStorageCount = study.runtime.shortTermStorageCount; auto activeConstraints = study.bindingConstraints.activeConstraints(); @@ -159,7 +159,7 @@ void SIM_AllocationProblemePasDeTemps(PROBLEME_HEBDO& problem, 0); variablesMapping.NumeroDeVariableDuPalierThermique - .assign(study.runtime->thermalPlantTotalCount, 0); + .assign(study.runtime.thermalPlantTotalCount, 0); variablesMapping.NumeroDeVariablesDeLaProdHyd.assign(nbPays, 0); variablesMapping.NumeroDeVariablesDePompage.assign(nbPays, 0); variablesMapping.NumeroDeVariablesDeNiveau.assign(nbPays, 0); @@ -172,13 +172,13 @@ void SIM_AllocationProblemePasDeTemps(PROBLEME_HEBDO& problem, variablesMapping.NumeroDeVariablesVariationHydALaHausse.assign(nbPays, 0); variablesMapping.NumeroDeVariableDuNombreDeGroupesEnMarcheDuPalierThermique - .assign(study.runtime->thermalPlantTotalCount, 0); + .assign(study.runtime.thermalPlantTotalCount, 0); variablesMapping.NumeroDeVariableDuNombreDeGroupesQuiDemarrentDuPalierThermique - .assign(study.runtime->thermalPlantTotalCount, 0); + .assign(study.runtime.thermalPlantTotalCount, 0); variablesMapping.NumeroDeVariableDuNombreDeGroupesQuiSArretentDuPalierThermique - .assign(study.runtime->thermalPlantTotalCount, 0); + .assign(study.runtime.thermalPlantTotalCount, 0); variablesMapping.NumeroDeVariableDuNombreDeGroupesQuiTombentEnPanneDuPalierThermique - .assign(study.runtime->thermalPlantTotalCount, 0); + .assign(study.runtime.thermalPlantTotalCount, 0); variablesMapping.SIM_ShortTermStorage.InjectionVariable.assign(shortTermStorageCount, 0); variablesMapping.SIM_ShortTermStorage.WithdrawalVariable.assign(shortTermStorageCount, 0); @@ -205,14 +205,14 @@ void SIM_AllocationProblemePasDeTemps(PROBLEME_HEBDO& problem, problem.CorrespondanceCntNativesCntOptim[k] .NumeroDeContrainteDesContraintesDeDureeMinDeMarche - .assign(study.runtime->thermalPlantTotalCount, 0); + .assign(study.runtime.thermalPlantTotalCount, 0); problem.CorrespondanceCntNativesCntOptim[k] .NumeroDeContrainteDesContraintesDeDureeMinDArret - .assign(study.runtime->thermalPlantTotalCount, 0); + .assign(study.runtime.thermalPlantTotalCount, 0); problem.CorrespondanceCntNativesCntOptim[k] .NumeroDeLaDeuxiemeContrainteDesContraintesDesGroupesQuiTombentEnPanne - .assign(study.runtime->thermalPlantTotalCount, 0); + .assign(study.runtime.thermalPlantTotalCount, 0); problem.VariablesDualesDesContraintesDeNTC[k] .VariableDualeParInterconnexion.assign(linkCount, 0.); @@ -278,7 +278,7 @@ void SIM_AllocationConstraints(PROBLEME_HEBDO& problem, problem.MatriceDesContraintesCouplantes[constraintIndex] .PaysDuPalierDispatch.assign(bc->clusterCount(), 0); - // TODO : create a numberOfTimeSteps method in class of runtime->bindingConstraint + // TODO : create a numberOfTimeSteps method in class of runtime.bindingConstraint unsigned int nbTimeSteps; switch (bc->type()) { diff --git a/src/solver/simulation/sim_allocation_tableaux.cpp b/src/solver/simulation/sim_allocation_tableaux.cpp index 4b8674639d..ef788dfedd 100644 --- a/src/solver/simulation/sim_allocation_tableaux.cpp +++ b/src/solver/simulation/sim_allocation_tableaux.cpp @@ -29,9 +29,9 @@ using namespace Antares; void SIM_AllocationTableaux(const Data::Study& study) { - transitMoyenInterconnexionsRecalculQuadratique.resize(study.runtime->interconnectionsCount()); + transitMoyenInterconnexionsRecalculQuadratique.resize(study.runtime.interconnectionsCount()); - for (uint i = 0; i != study.runtime->interconnectionsCount(); i++) + for (uint i = 0; i != study.runtime.interconnectionsCount(); i++) { transitMoyenInterconnexionsRecalculQuadratique[i].assign(HOURS_PER_YEAR, 0.); } diff --git a/src/solver/simulation/sim_calcul_economique.cpp b/src/solver/simulation/sim_calcul_economique.cpp index 2402ddd548..9fd210f1fd 100644 --- a/src/solver/simulation/sim_calcul_economique.cpp +++ b/src/solver/simulation/sim_calcul_economique.cpp @@ -87,7 +87,7 @@ void SIM_InitialisationProblemeHebdo(Data::Study& study, { problem.adequacyPatchRuntimeData = std::make_shared( study.areas, - study.runtime->areaLink); + study.runtime.areaLink); } problem.WaterValueAccurate = (study.parameters.hydroPricing.hpMode @@ -101,9 +101,9 @@ void SIM_InitialisationProblemeHebdo(Data::Study& study, problem.NombreDePays = study.areas.size(); - problem.NombreDInterconnexions = study.runtime->interconnectionsCount(); + problem.NombreDInterconnexions = study.runtime.interconnectionsCount(); - problem.NumberOfShortTermStorages = study.runtime->shortTermStorageCount; + problem.NumberOfShortTermStorages = study.runtime.shortTermStorageCount; auto activeConstraints = study.bindingConstraints.activeConstraints(); problem.NombreDeContraintesCouplantes = activeConstraints.size(); @@ -219,9 +219,9 @@ void SIM_InitialisationProblemeHebdo(Data::Study& study, importShortTermStorages(study.areas, problem.ShortTermStorage); - for (uint i = 0; i < study.runtime->interconnectionsCount(); ++i) + for (uint i = 0; i < study.runtime.interconnectionsCount(); ++i) { - auto& link = *(study.runtime->areaLink[i]); + auto& link = *(study.runtime.areaLink[i]); problem.PaysOrigineDeLInterconnexion[i] = link.from->index; problem.PaysExtremiteDeLInterconnexion[i] = link.with->index; } @@ -411,7 +411,7 @@ void SIM_RenseignementProblemeHebdo(const Study& study, { const auto& parameters = study.parameters; - auto& studyruntime = *study.runtime; + auto& studyruntime = study.runtime; const uint nbPays = study.areas.size(); const size_t pasDeTempsSizeDouble = problem.NombreDePasDeTemps * sizeof(double); diff --git a/src/solver/simulation/timeseries-numbers.cpp b/src/solver/simulation/timeseries-numbers.cpp index 446a0efa08..fecb8ba4eb 100644 --- a/src/solver/simulation/timeseries-numbers.cpp +++ b/src/solver/simulation/timeseries-numbers.cpp @@ -475,7 +475,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i if (!isTSintramodal[indexTS]) { area.load.series.timeseriesNumbers[year] = (uint32_t)(floor( - study.runtime->random[seedTimeseriesNumbers].next() + study.runtime.random[seedTimeseriesNumbers].next() * area.load.series.timeSeries.width)); } @@ -487,7 +487,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i if (!isTSintramodal[indexTS]) { area.solar.series.timeseriesNumbers[year] = (uint32_t)(floor( - study.runtime->random[seedTimeseriesNumbers].next() + study.runtime.random[seedTimeseriesNumbers].next() * area.solar.series.timeSeries.width)); } @@ -499,7 +499,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i if (!isTSintramodal[indexTS]) { area.wind.series.timeseriesNumbers[year] = (uint32_t)(floor( - study.runtime->random[seedTimeseriesNumbers].next() + study.runtime.random[seedTimeseriesNumbers].next() * area.wind.series.timeSeries.width)); } @@ -511,8 +511,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i if (!isTSintramodal[indexTS]) { area.hydro.series->timeseriesNumbers[year] = (uint32_t)(floor( - study.runtime->random[seedTimeseriesNumbers].next() - * area.hydro.series->TScount())); + study.runtime.random[seedTimeseriesNumbers].next() * area.hydro.series->TScount())); } // ------------- @@ -524,14 +523,14 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i { if (!cluster->enabled) { - study.runtime->random[seedTimeseriesNumbers].next(); + study.runtime.random[seedTimeseriesNumbers].next(); } else { if (!isTSintramodal[indexTS]) { cluster->series.timeseriesNumbers[year] = (uint32_t)(floor( - study.runtime->random[seedTimeseriesNumbers].next() + study.runtime.random[seedTimeseriesNumbers].next() * cluster->series.timeSeries.width)); } } @@ -549,7 +548,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i // There is no TS generation for renewable clusters uint nbTimeSeries = cluster->series.timeSeries.width; cluster->series.timeseriesNumbers[year] = (uint32_t)(floor( - study.runtime->random[seedTimeseriesNumbers].next() * nbTimeSeries)); + study.runtime.random[seedTimeseriesNumbers].next() * nbTimeSeries)); } } @@ -567,7 +566,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i if (nbTimeSeries > 1) { link.timeseriesNumbers[year] = (uint32_t)(floor( - study.runtime->random[seedTimeseriesNumbers].next() * nbTimeSeries)); + study.runtime.random[seedTimeseriesNumbers].next() * nbTimeSeries)); } } } @@ -579,7 +578,7 @@ void drawAndStoreTSnumbersForNOTintraModal(const array& i auto& groupTsNumber = group->timeseriesNumbers[year]; if (nbTimeSeries > 1) { - groupTsNumber = (uint32_t)(floor(study.runtime->random[seedTimeseriesNumbers].next() + groupTsNumber = (uint32_t)(floor(study.runtime.random[seedTimeseriesNumbers].next() * nbTimeSeries)); } } @@ -753,7 +752,7 @@ bool TimeSeriesNumbers::Generate(Study& study) return GenerateDeratedMode(study); } - const uint years = 1 + study.runtime->rangeLimits.year[rangeEnd]; + const uint years = 1 + study.runtime.rangeLimits.year[rangeEnd]; const array isTSintramodal = { (bool)(timeSeriesLoad & parameters.intraModal), @@ -783,7 +782,7 @@ bool TimeSeriesNumbers::Generate(Study& study) drawTSnumbersForIntraModal(intramodal_draws, isTSintramodal, nbTimeseriesByMode, - study.runtime->random); + study.runtime.random); storeTSnumbersForIntraModal(intramodal_draws, isTSintramodal, year, study.areas); // NOT intra-modal TS : draw and store TS numbers diff --git a/src/solver/ts-generator/hydro.cpp b/src/solver/ts-generator/hydro.cpp index 2d31f08b22..168b290dfb 100644 --- a/src/solver/ts-generator/hydro.cpp +++ b/src/solver/ts-generator/hydro.cpp @@ -63,7 +63,7 @@ bool GenerateHydroTimeSeries(Data::Study& study, uint currentYear, Solver::IResu Solver::Progression::Task progression(study, currentYear, Solver::Progression::sectTSGHydro); - auto& studyRTI = *(study.runtime); + auto& studyRTI = study.runtime; auto& calendar = study.calendar; uint DIM = MONTHS_PER_YEAR * study.areas.size(); @@ -72,7 +72,7 @@ bool GenerateHydroTimeSeries(Data::Study& study, uint currentYear, Solver::IResu Matrix CHSKY; CHSKY.reset(DIM, DIM); - double* QCHOLTemp = new double[DIM]; + std::vector QCHOLTemp(DIM); Matrix B; B.reset(DIM, DIM); @@ -84,7 +84,7 @@ bool GenerateHydroTimeSeries(Data::Study& study, uint currentYear, Solver::IResu B.entry, nullmatrx, study.areas.size(), - QCHOLTemp, + QCHOLTemp.data(), true)) { throw FatalError("TS Generator: Hydro: Invalid correlation matrix"); @@ -122,7 +122,7 @@ bool GenerateHydroTimeSeries(Data::Study& study, uint currentYear, Solver::IResu B.entry, nullmatrx, DIM, - QCHOLTemp, + QCHOLTemp.data(), true); if (r < 1.) { @@ -134,15 +134,13 @@ bool GenerateHydroTimeSeries(Data::Study& study, uint currentYear, Solver::IResu } } - Solver::Cholesky(CHSKY.entry, B.entry, DIM, QCHOLTemp); + Solver::Cholesky(CHSKY.entry, B.entry, DIM, QCHOLTemp.data()); B.clear(); CORRE.clear(); + QCHOLTemp.clear(); - delete[] QCHOLTemp; - QCHOLTemp = nullptr; - - double* NORM = new double[DIM]; + std::vector NORM(DIM); for (uint i = 0; i != DIM; ++i) { NORM[i] = 0.; @@ -308,8 +306,6 @@ bool GenerateHydroTimeSeries(Data::Study& study, uint currentYear, Solver::IResu } } - delete[] NORM; - return true; } diff --git a/src/solver/ts-generator/include/antares/solver/ts-generator/generator.hxx b/src/solver/ts-generator/include/antares/solver/ts-generator/generator.hxx index 6596a4f7ab..7455c1accc 100644 --- a/src/solver/ts-generator/include/antares/solver/ts-generator/generator.hxx +++ b/src/solver/ts-generator/include/antares/solver/ts-generator/generator.hxx @@ -58,16 +58,16 @@ bool GenerateTimeSeries(Data::Study& study, uint year, IResultWriter& writer) switch (T) { case Data::timeSeriesLoad: - xcast->random = &(study.runtime->random[Data::seedTsGenLoad]); + xcast->random = &(study.runtime.random[Data::seedTsGenLoad]); break; case Data::timeSeriesSolar: - xcast->random = &(study.runtime->random[Data::seedTsGenSolar]); + xcast->random = &(study.runtime.random[Data::seedTsGenSolar]); break; case Data::timeSeriesWind: - xcast->random = &(study.runtime->random[Data::seedTsGenWind]); + xcast->random = &(study.runtime.random[Data::seedTsGenWind]); break; case Data::timeSeriesHydro: - xcast->random = &(study.runtime->random[Data::seedTsGenHydro]); + xcast->random = &(study.runtime.random[Data::seedTsGenHydro]); break; default: xcast->random = nullptr; diff --git a/src/solver/variable/include/antares/solver/variable/adequacy/overallCost.h b/src/solver/variable/include/antares/solver/variable/adequacy/overallCost.h index f730a3d865..3bdcee903b 100644 --- a/src/solver/variable/include/antares/solver/variable/adequacy/overallCost.h +++ b/src/solver/variable/include/antares/solver/variable/adequacy/overallCost.h @@ -194,7 +194,7 @@ class OverallCost: public Variable::IVariable, NextT, VCardOv void yearEndBuildForEachThermalCluster(State& state, uint year, unsigned int numSpace) { // Get end year calculations - for (unsigned int i = 0; i < state.study.runtime->rangeLimits.hour[Data::rangeCount]; ++i) + for (unsigned int i = 0; i < state.study.runtime.rangeLimits.hour[Data::rangeCount]; ++i) { pValuesForTheCurrentYear[numSpace][i] += state.thermalClusterOperatingCostForYear[i]; } diff --git a/src/solver/variable/include/antares/solver/variable/commons/spatial-aggregate.h b/src/solver/variable/include/antares/solver/variable/commons/spatial-aggregate.h index ea966c4977..851dbb9999 100644 --- a/src/solver/variable/include/antares/solver/variable/commons/spatial-aggregate.h +++ b/src/solver/variable/include/antares/solver/variable/commons/spatial-aggregate.h @@ -221,7 +221,7 @@ class SpatialAggregate VariableAccessorType::InitializeAndReset(pValuesForTheCurrentYear[numSpace], study); } - auto& limits = study.runtime->rangeLimits; + auto& limits = study.runtime.rangeLimits; pRatioYear = 100. / (double)limits.year[Data::rangeCount]; pRatioDay = 100. / (double)limits.day[Data::rangeCount]; diff --git a/src/solver/variable/include/antares/solver/variable/economy/links/flowQuad.h b/src/solver/variable/include/antares/solver/variable/economy/links/flowQuad.h index b7d00a3fb8..b6de8329ae 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/links/flowQuad.h +++ b/src/solver/variable/include/antares/solver/variable/economy/links/flowQuad.h @@ -129,7 +129,7 @@ class FlowQuad: public Variable::IVariable, NextT, VCardFlowQuad void initializeFromStudy(Data::Study& study) { // Average on all years - pNbHours = study.runtime->rangeLimits.hour[Data::rangeEnd] + 1; + pNbHours = study.runtime.rangeLimits.hour[Data::rangeEnd] + 1; AncestorType::pResults.initializeFromStudy(study); AncestorType::pResults.reset(); diff --git a/src/solver/variable/include/antares/solver/variable/economy/nbOfDispatchedUnits.h b/src/solver/variable/include/antares/solver/variable/economy/nbOfDispatchedUnits.h index a2af682a67..173343f61f 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/nbOfDispatchedUnits.h +++ b/src/solver/variable/include/antares/solver/variable/economy/nbOfDispatchedUnits.h @@ -198,8 +198,8 @@ class NbOfDispatchedUnits void yearEndBuildForEachThermalCluster(State& state, uint year, unsigned int numSpace) { // Get end year calculations - for (unsigned int i = state.study.runtime->rangeLimits.hour[Data::rangeBegin]; - i <= state.study.runtime->rangeLimits.hour[Data::rangeEnd]; + for (unsigned int i = state.study.runtime.rangeLimits.hour[Data::rangeBegin]; + i <= state.study.runtime.rangeLimits.hour[Data::rangeEnd]; ++i) { pValuesForTheCurrentYear[numSpace][i] += state.thermalClusterDispatchedUnitsCountForYear diff --git a/src/solver/variable/include/antares/solver/variable/economy/nbOfDispatchedUnitsByPlant.h b/src/solver/variable/include/antares/solver/variable/economy/nbOfDispatchedUnitsByPlant.h index 2bc519a94c..37f19ea3d6 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/nbOfDispatchedUnitsByPlant.h +++ b/src/solver/variable/include/antares/solver/variable/economy/nbOfDispatchedUnitsByPlant.h @@ -234,7 +234,7 @@ class NbOfDispatchedUnitsByPlant: public Variable::IVariablerangeLimits.hour[Data::rangeEnd]; ++i) + for (unsigned int i = 0; i <= state.study.runtime.rangeLimits.hour[Data::rangeEnd]; ++i) { state.thermalClusterDispatchedUnitsCountForYear[i] += static_cast( pValuesForTheCurrentYear[numSpace][state.thermalCluster->areaWideIndex].hour[i]); @@ -247,8 +247,8 @@ class NbOfDispatchedUnitsByPlant: public Variable::IVariablerangeLimits.hour[Data::rangeBegin]; - i <= state.study.runtime->rangeLimits.hour[Data::rangeEnd]; + for (unsigned int i = state.study.runtime.rangeLimits.hour[Data::rangeBegin]; + i <= state.study.runtime.rangeLimits.hour[Data::rangeEnd]; ++i) { pValuesForTheCurrentYear[numSpace][state.thermalCluster->areaWideIndex].hour[i] diff --git a/src/solver/variable/include/antares/solver/variable/economy/nonProportionalCost.h b/src/solver/variable/include/antares/solver/variable/economy/nonProportionalCost.h index be8436d29a..8d26594739 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/nonProportionalCost.h +++ b/src/solver/variable/include/antares/solver/variable/economy/nonProportionalCost.h @@ -198,8 +198,8 @@ class NonProportionalCost void yearEndBuildForEachThermalCluster(State& state, uint year, unsigned int numSpace) { // Get end year calculations - for (unsigned int i = state.study.runtime->rangeLimits.hour[Data::rangeBegin]; - i <= state.study.runtime->rangeLimits.hour[Data::rangeEnd]; + for (unsigned int i = state.study.runtime.rangeLimits.hour[Data::rangeBegin]; + i <= state.study.runtime.rangeLimits.hour[Data::rangeEnd]; ++i) { pValuesForTheCurrentYear[numSpace][i] += state diff --git a/src/solver/variable/include/antares/solver/variable/economy/npCostByDispatchablePlant.h b/src/solver/variable/include/antares/solver/variable/economy/npCostByDispatchablePlant.h index b0587d51a2..79304684b3 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/npCostByDispatchablePlant.h +++ b/src/solver/variable/include/antares/solver/variable/economy/npCostByDispatchablePlant.h @@ -236,8 +236,8 @@ class NonProportionalCostByDispatchablePlant void yearEndBuildForEachThermalCluster(State& state, uint year, unsigned int numSpace) { // Get end year calculations - for (unsigned int i = state.study.runtime->rangeLimits.hour[Data::rangeBegin]; - i <= state.study.runtime->rangeLimits.hour[Data::rangeEnd]; + for (unsigned int i = state.study.runtime.rangeLimits.hour[Data::rangeBegin]; + i <= state.study.runtime.rangeLimits.hour[Data::rangeEnd]; ++i) { pValuesForTheCurrentYear[numSpace][state.thermalCluster->areaWideIndex].hour[i] diff --git a/src/solver/variable/include/antares/solver/variable/economy/operatingCost.h b/src/solver/variable/include/antares/solver/variable/economy/operatingCost.h index 0df88e6711..df95f6d65c 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/operatingCost.h +++ b/src/solver/variable/include/antares/solver/variable/economy/operatingCost.h @@ -196,8 +196,8 @@ class OperatingCost: public Variable::IVariable, NextT, VCa void yearEndBuildForEachThermalCluster(State& state, uint year, unsigned int numSpace) { // Get end year calculations - for (unsigned int i = state.study.runtime->rangeLimits.hour[Data::rangeBegin]; - i <= state.study.runtime->rangeLimits.hour[Data::rangeEnd]; + for (unsigned int i = state.study.runtime.rangeLimits.hour[Data::rangeBegin]; + i <= state.study.runtime.rangeLimits.hour[Data::rangeEnd]; ++i) { pValuesForTheCurrentYear[numSpace][i] += state.thermalClusterOperatingCostForYear[i]; diff --git a/src/solver/variable/include/antares/solver/variable/economy/overallCost.h b/src/solver/variable/include/antares/solver/variable/economy/overallCost.h index 43c13f6620..ccb6632e9e 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/overallCost.h +++ b/src/solver/variable/include/antares/solver/variable/economy/overallCost.h @@ -194,8 +194,8 @@ class OverallCost: public Variable::IVariable, NextT, VCardOv void yearEndBuildForEachThermalCluster(State& state, uint year, unsigned int numSpace) { // Get end year calculations - for (unsigned int i = state.study.runtime->rangeLimits.hour[Data::rangeBegin]; - i <= state.study.runtime->rangeLimits.hour[Data::rangeEnd]; + for (unsigned int i = state.study.runtime.rangeLimits.hour[Data::rangeBegin]; + i <= state.study.runtime.rangeLimits.hour[Data::rangeEnd]; ++i) { pValuesForTheCurrentYear[numSpace][i] += state.thermalClusterOperatingCostForYear[i]; diff --git a/src/solver/variable/include/antares/solver/variable/economy/productionByDispatchablePlant.h b/src/solver/variable/include/antares/solver/variable/economy/productionByDispatchablePlant.h index 2e401844eb..b54245b644 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/productionByDispatchablePlant.h +++ b/src/solver/variable/include/antares/solver/variable/economy/productionByDispatchablePlant.h @@ -255,7 +255,7 @@ class ProductionByDispatchablePlant uint year, unsigned int numSpace) { - for (unsigned int i = 0; i <= state.study.runtime->rangeLimits.hour[Data::rangeEnd]; ++i) + for (unsigned int i = 0; i <= state.study.runtime.rangeLimits.hour[Data::rangeEnd]; ++i) { state.thermalClusterProductionForYear[i] += pValuesForTheCurrentYear [numSpace] diff --git a/src/solver/variable/include/antares/solver/variable/storage/average.h b/src/solver/variable/include/antares/solver/variable/storage/average.h index 380915e284..fbeaf16a5b 100644 --- a/src/solver/variable/include/antares/solver/variable/storage/average.h +++ b/src/solver/variable/include/antares/solver/variable/storage/average.h @@ -116,7 +116,7 @@ struct Average: public NextT avgdata.monthly); break; case Category::annual: - InternalExportValues<1, VCardT, Category::annual>(report, avgdata.year); + InternalExportValues<1, VCardT, Category::annual>(report, avgdata.year.data()); break; } } diff --git a/src/solver/variable/include/antares/solver/variable/storage/averagedata.h b/src/solver/variable/include/antares/solver/variable/storage/averagedata.h index 0ed11ae239..132b70317d 100644 --- a/src/solver/variable/include/antares/solver/variable/storage/averagedata.h +++ b/src/solver/variable/include/antares/solver/variable/storage/averagedata.h @@ -62,7 +62,7 @@ class AverageData double weekly[WEEKS_PER_YEAR]; double daily[DAYS_PER_YEAR]; Antares::Memory::Stored::Type hourly; - double* year; + std::vector year; unsigned int nbYearsCapacity; mutable double allYears; // FIX MEEE - Remove the mutable as soon as possible std::vector yearsWeight; diff --git a/src/solver/variable/include/antares/solver/variable/storage/raw.h b/src/solver/variable/include/antares/solver/variable/storage/raw.h index e71356953f..fe6c444840 100644 --- a/src/solver/variable/include/antares/solver/variable/storage/raw.h +++ b/src/solver/variable/include/antares/solver/variable/storage/raw.h @@ -120,7 +120,7 @@ struct Raw: public NextT rawdata.monthly); break; case Category::annual: - InternalExportValues(report, rawdata.year); + InternalExportValues(report, rawdata.year.data()); break; } } diff --git a/src/solver/variable/include/antares/solver/variable/storage/rawdata.h b/src/solver/variable/include/antares/solver/variable/storage/rawdata.h index 6a2c118c05..a0c60cc89d 100644 --- a/src/solver/variable/include/antares/solver/variable/storage/rawdata.h +++ b/src/solver/variable/include/antares/solver/variable/storage/rawdata.h @@ -60,7 +60,7 @@ class RawData double weekly[WEEKS_PER_YEAR]; double daily[DAYS_PER_YEAR]; Antares::Memory::Stored::Type hourly; - double* year; + std::vector year; mutable double allYears; unsigned int nbYearsCapacity; diff --git a/src/solver/variable/state.cpp b/src/solver/variable/state.cpp index ca8d5b2677..6657a5a23b 100644 --- a/src/solver/variable/state.cpp +++ b/src/solver/variable/state.cpp @@ -230,9 +230,9 @@ void State::yearEndBuildFromThermalClusterIndex(const uint clusterAreaWideIndex) uint maxDurationON; // nombre d'heures de fonctionnement d'un groupe au delà duquel un // arrêt/redémarrage est préférable uint maxUnitNeeded = 0; - uint startHourForCurrentYear = study.runtime->rangeLimits.hour[Data::rangeBegin]; + uint startHourForCurrentYear = study.runtime.rangeLimits.hour[Data::rangeBegin]; uint endHourForCurrentYear = startHourForCurrentYear - + study.runtime->rangeLimits.hour[Data::rangeCount]; + + study.runtime.rangeLimits.hour[Data::rangeCount]; assert(endHourForCurrentYear <= HOURS_PER_YEAR); @@ -377,9 +377,9 @@ void State::yearEndBuildThermalClusterCalculateStartupCosts( const std::array& ON_opt, const Data::ThermalCluster* currentCluster) { - uint startHourForCurrentYear = study.runtime->rangeLimits.hour[Data::rangeBegin]; + uint startHourForCurrentYear = study.runtime.rangeLimits.hour[Data::rangeBegin]; uint endHourForCurrentYear = startHourForCurrentYear - + study.runtime->rangeLimits.hour[Data::rangeCount]; + + study.runtime.rangeLimits.hour[Data::rangeCount]; for (uint hour = startHourForCurrentYear; hour < endHourForCurrentYear; ++hour) { @@ -427,9 +427,9 @@ std::array State::computeEconomicallyOptimalNbClustersONfo const std::array& ON_min, const std::array& ON_max) const { - uint startHourForCurrentYear = study.runtime->rangeLimits.hour[Data::rangeBegin]; + uint startHourForCurrentYear = study.runtime.rangeLimits.hour[Data::rangeBegin]; uint endHourForCurrentYear = startHourForCurrentYear - + study.runtime->rangeLimits.hour[Data::rangeCount]; + + study.runtime.rangeLimits.hour[Data::rangeCount]; // Nombre de groupes économiquement optimal en fonctionnement à l'heure h std::array ON_opt; diff --git a/src/solver/variable/storage/averagedata.cpp b/src/solver/variable/storage/averagedata.cpp index 4a88945bb6..fac0080bf1 100644 --- a/src/solver/variable/storage/averagedata.cpp +++ b/src/solver/variable/storage/averagedata.cpp @@ -31,7 +31,6 @@ namespace Antares::Solver::Variable::R::AllYears { AverageData::AverageData(): hourly(nullptr), - year(nullptr), nbYearsCapacity(0), allYears(0.) { @@ -40,7 +39,6 @@ AverageData::AverageData(): AverageData::~AverageData() { Antares::Memory::Release(hourly); - delete[] year; } void AverageData::reset() @@ -49,14 +47,14 @@ void AverageData::reset() (void)::memset(monthly, 0, sizeof(double) * MONTHS_PER_YEAR); (void)::memset(weekly, 0, sizeof(double) * WEEKS_PER_YEAR); (void)::memset(daily, 0, sizeof(double) * DAYS_PER_YEAR); - (void)::memset(year, 0, sizeof(double) * nbYearsCapacity); + year.assign(nbYearsCapacity, 0); } void AverageData::initializeFromStudy(Data::Study& study) { Antares::Memory::Allocate(hourly, HOURS_PER_YEAR); - nbYearsCapacity = study.runtime->rangeLimits.year[Data::rangeEnd] + 1; - year = new double[nbYearsCapacity]; + nbYearsCapacity = study.runtime.rangeLimits.year[Data::rangeEnd] + 1; + year.resize(nbYearsCapacity); yearsWeight = study.parameters.getYearsWeight(); yearsWeightSum = study.parameters.getYearsWeightSum(); diff --git a/src/solver/variable/storage/intermediate.cpp b/src/solver/variable/storage/intermediate.cpp index 4799085aaf..a796b9676d 100644 --- a/src/solver/variable/storage/intermediate.cpp +++ b/src/solver/variable/storage/intermediate.cpp @@ -44,9 +44,9 @@ IntermediateValues::IntermediateValues(): void IntermediateValues::initializeFromStudy(Data::Study& study) { - pRange = &study.runtime->rangeLimits; + pRange = &study.runtime.rangeLimits; calendar = &study.calendarOutput; - pRuntimeInfo = study.runtime; + pRuntimeInfo = &study.runtime; } void IntermediateValues::computeStatisticsAdequacyForTheCurrentYear() diff --git a/src/solver/variable/storage/rawdata.cpp b/src/solver/variable/storage/rawdata.cpp index 4baf8531bd..a1b4c2fecf 100644 --- a/src/solver/variable/storage/rawdata.cpp +++ b/src/solver/variable/storage/rawdata.cpp @@ -29,7 +29,6 @@ namespace Antares::Solver::Variable::R::AllYears { RawData::RawData(): hourly(nullptr), - year(nullptr), allYears(0.) { } @@ -37,14 +36,13 @@ RawData::RawData(): RawData::~RawData() { Antares::Memory::Release(hourly); - delete[] year; } void RawData::initializeFromStudy(const Data::Study& study) { Antares::Memory::Allocate(hourly, HOURS_PER_YEAR); - nbYearsCapacity = study.runtime->rangeLimits.year[Data::rangeEnd] + 1; - year = new double[nbYearsCapacity]; + nbYearsCapacity = study.runtime.rangeLimits.year[Data::rangeEnd] + 1; + year.resize(nbYearsCapacity); } void RawData::reset() @@ -54,7 +52,7 @@ void RawData::reset() (void)::memset(monthly, 0, sizeof(double) * MONTHS_PER_YEAR); (void)::memset(weekly, 0, sizeof(double) * WEEKS_PER_YEAR); (void)::memset(daily, 0, sizeof(double) * DAYS_PER_YEAR); - (void)::memset(year, 0, sizeof(double) * nbYearsCapacity); + year.assign(nbYearsCapacity, 0); } void RawData::merge(unsigned int y, const IntermediateValues& rhs) diff --git a/src/solver/variable/surveyresults/surveyresults.cpp b/src/solver/variable/surveyresults/surveyresults.cpp index bb763a1b80..8df87678e4 100644 --- a/src/solver/variable/surveyresults/surveyresults.cpp +++ b/src/solver/variable/surveyresults/surveyresults.cpp @@ -231,17 +231,16 @@ namespace Variable { static inline uint GetRangeLimit(const Data::Study& study, int precisionLevel, int index) { - assert(study.runtime && "invalid runtime data"); switch (precisionLevel) { case Category::hourly: - return study.runtime->rangeLimits.hour[index]; + return study.runtime.rangeLimits.hour[index]; case Category::daily: - return study.runtime->rangeLimits.day[index]; + return study.runtime.rangeLimits.day[index]; case Category::weekly: - return study.runtime->rangeLimits.week[index]; + return study.runtime.rangeLimits.week[index]; case Category::monthly: - return study.runtime->rangeLimits.month[index]; + return study.runtime.rangeLimits.month[index]; case Category::annual: return 0; default: @@ -357,13 +356,10 @@ inline void SurveyResults::AppendDoubleValue(uint& error, if (std::isnan(v)) { buffer.append("\tNaN", 4); - if (++error == 1) + // We should disabled errors on NaN if the quadratic optimization has failed + if (++error == 1 && !data.study.runtime.quadraticOptimizationHasFailed) { - // We should disabled errors on NaN if the quadratic optimization has failed - if (not data.study.runtime->quadraticOptimizationHasFailed) - { - logs.error() << "'NaN' value detected"; - } + logs.error() << "'NaN' value detected"; } } else @@ -608,7 +604,7 @@ void SurveyResults::exportDigestAllYears(std::string& buffer) { // Main Header { - const unsigned int nbLinks = data.study.runtime->interconnectionsCount(); + const unsigned int nbLinks = data.study.runtime.interconnectionsCount(); buffer.append("\tdigest\n\tVARIABLES\tAREAS\tLINKS\n") .append("\t") .append(std::to_string(data.columnIndex)) diff --git a/src/tests/inmemory-study/in-memory-study.cpp b/src/tests/inmemory-study/in-memory-study.cpp index 30efd246bf..1f3f78c194 100644 --- a/src/tests/inmemory-study/in-memory-study.cpp +++ b/src/tests/inmemory-study/in-memory-study.cpp @@ -56,7 +56,7 @@ void addScratchpadToEachArea(Study& study) { for (unsigned int i = 0; i < study.maxNbYearsInParallel; ++i) { - area->scratchpad.emplace_back(*study.runtime, *area); + area->scratchpad.emplace_back(study.runtime, *area); } } } diff --git a/src/tests/src/api_internal/test_api.cpp b/src/tests/src/api_internal/test_api.cpp index d60f6315d5..fe006c9bd6 100644 --- a/src/tests/src/api_internal/test_api.cpp +++ b/src/tests/src/api_internal/test_api.cpp @@ -44,8 +44,8 @@ class InMemoryStudyLoader: public Antares::IStudyLoader StudyBuilder builder; builder.addAreaToStudy("area1"); builder.addAreaToStudy("area2"); - builder.setNumberMCyears(1); builder.study->initializeRuntimeInfos(); + builder.setNumberMCyears(1); builder.study->parameters.resultFormat = ResultFormat::inMemory; builder.study->prepareOutput(); return std::move(builder.study); diff --git a/src/tests/src/libs/antares/study/test_study.cpp b/src/tests/src/libs/antares/study/test_study.cpp index 104b304c0e..0ecb082cd1 100644 --- a/src/tests/src/libs/antares/study/test_study.cpp +++ b/src/tests/src/libs/antares/study/test_study.cpp @@ -139,7 +139,7 @@ BOOST_FIXTURE_TEST_CASE(short_term_storage_delete, OneAreaStudy) BOOST_CHECK(findDisabledCluster("Cluster1") != sts.end()); BOOST_CHECK(findDisabledCluster("Cluster2") != sts.end()); - study->initializeRuntimeInfos(); // This should remove all disabled short-term storages + study->initializeRuntimeInfos(); // Check that only "Cluster1" is found BOOST_CHECK(findDisabledCluster("Cluster1") != sts.end()); diff --git a/src/tests/src/solver/simulation/test-store-timeseries-number.cpp b/src/tests/src/solver/simulation/test-store-timeseries-number.cpp index 16cbb59fc2..1e68ef95be 100644 --- a/src/tests/src/solver/simulation/test-store-timeseries-number.cpp +++ b/src/tests/src/solver/simulation/test-store-timeseries-number.cpp @@ -44,10 +44,9 @@ void initializeStudy(Study& study) { study.parameters.derated = false; - study.runtime = new StudyRuntimeInfos(); - study.runtime->rangeLimits.year[rangeBegin] = 0; - study.runtime->rangeLimits.year[rangeEnd] = 0; - study.runtime->rangeLimits.year[rangeCount] = 1; + study.runtime.rangeLimits.year[rangeBegin] = 0; + study.runtime.rangeLimits.year[rangeEnd] = 0; + study.runtime.rangeLimits.year[rangeCount] = 1; study.parameters.renewableGeneration.toAggregated(); // Default diff --git a/src/tests/src/solver/simulation/test-time_series.cpp b/src/tests/src/solver/simulation/test-time_series.cpp index 42f1fbddf4..b999c17b48 100644 --- a/src/tests/src/solver/simulation/test-time_series.cpp +++ b/src/tests/src/solver/simulation/test-time_series.cpp @@ -40,10 +40,9 @@ void initializeStudy(Study& study) { study.parameters.derated = false; - study.runtime = new StudyRuntimeInfos(); - study.runtime->rangeLimits.year[rangeBegin] = 0; - study.runtime->rangeLimits.year[rangeEnd] = 0; - study.runtime->rangeLimits.year[rangeCount] = 1; + study.runtime.rangeLimits.year[rangeBegin] = 0; + study.runtime.rangeLimits.year[rangeEnd] = 0; + study.runtime.rangeLimits.year[rangeCount] = 1; study.parameters.renewableGeneration.toAggregated(); // Default diff --git a/src/tests/src/solver/simulation/tests-ts-numbers.cpp b/src/tests/src/solver/simulation/tests-ts-numbers.cpp index 9767cbe525..8dbd450d53 100644 --- a/src/tests/src/solver/simulation/tests-ts-numbers.cpp +++ b/src/tests/src/solver/simulation/tests-ts-numbers.cpp @@ -38,9 +38,8 @@ void initializeStudy(Study::Ptr study, unsigned int nbYears = 1) { study->parameters.derated = false; - study->runtime = new StudyRuntimeInfos(); - study->runtime->rangeLimits.year[rangeBegin] = 0; - study->runtime->rangeLimits.year[rangeEnd] = nbYears - 1; + study->runtime.rangeLimits.year[rangeBegin] = 0; + study->runtime.rangeLimits.year[rangeEnd] = nbYears - 1; study->parameters.renewableGeneration.toAggregated(); // Default @@ -130,7 +129,7 @@ BOOST_AUTO_TEST_CASE(two_areas_with_5_ready_made_ts_on_load___check_intra_modal_ Area* area_1 = addAreaToStudy(study, "Area 1"); Area* area_2 = addAreaToStudy(study, "Area 2"); - study->areas.resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); + study->areas.resizeAllTimeseriesNumbers(1 + study->runtime.rangeLimits.year[rangeEnd]); area_1->load.series.timeSeries.resize(5, 1); area_2->load.series.timeSeries.resize(5, 1); @@ -157,7 +156,7 @@ static bool intramodal_load_two_areas(unsigned width_area_1, unsigned width_area Area* area_1 = addAreaToStudy(study, "Area 1"); Area* area_2 = addAreaToStudy(study, "Area 2"); - study->areas.resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); + study->areas.resizeAllTimeseriesNumbers(1 + study->runtime.rangeLimits.year[rangeEnd]); area_1->load.series.timeSeries.resize(width_area_1, 1); area_2->load.series.timeSeries.resize(width_area_2, 1); @@ -199,7 +198,7 @@ BOOST_AUTO_TEST_CASE( auto thCluster_21 = addClusterToArea(area_2, "th-cluster-21"); thCluster_21->series.timeSeries.resize(4, 1); - study->areas.resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); + study->areas.resizeAllTimeseriesNumbers(1 + study->runtime.rangeLimits.year[rangeEnd]); BOOST_CHECK(Generate(*study)); @@ -231,7 +230,7 @@ BOOST_AUTO_TEST_CASE( auto thCluster_21 = addClusterToArea(area_2, "th-cluster-21"); thCluster_21->series.timeSeries.resize(4, 1); - study->areas.resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); + study->areas.resizeAllTimeseriesNumbers(1 + study->runtime.rangeLimits.year[rangeEnd]); BOOST_CHECK(Generate(*study)); @@ -263,7 +262,7 @@ BOOST_AUTO_TEST_CASE( auto thCluster_21 = addClusterToArea(area_2, "th-cluster-21"); thCluster_21->series.timeSeries.resize(3, 1); - study->areas.resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); + study->areas.resizeAllTimeseriesNumbers(1 + study->runtime.rangeLimits.year[rangeEnd]); BOOST_CHECK(not Generate(*study)); } @@ -291,7 +290,7 @@ BOOST_AUTO_TEST_CASE( auto rnCluster_21 = addClusterToArea(area_2, "rn-cluster-21"); rnCluster_21->series.timeSeries.resize(4, 1); - study->areas.resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); + study->areas.resizeAllTimeseriesNumbers(1 + study->runtime.rangeLimits.year[rangeEnd]); BOOST_CHECK(Generate(*study)); @@ -323,7 +322,7 @@ BOOST_AUTO_TEST_CASE( auto rnCluster_21 = addClusterToArea(area_2, "rn-cluster-21"); rnCluster_21->series.timeSeries.resize(4, 1); - study->areas.resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); + study->areas.resizeAllTimeseriesNumbers(1 + study->runtime.rangeLimits.year[rangeEnd]); BOOST_CHECK(Generate(*study)); @@ -357,7 +356,7 @@ BOOST_AUTO_TEST_CASE( auto rnCluster_21 = addClusterToArea(area_2, "rn-cluster-21"); rnCluster_21->series.timeSeries.resize(4, 1); - study->areas.resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); + study->areas.resizeAllTimeseriesNumbers(1 + study->runtime.rangeLimits.year[rangeEnd]); BOOST_CHECK(not Generate(*study)); } @@ -389,7 +388,7 @@ BOOST_AUTO_TEST_CASE( auto thCluster_1 = addClusterToArea(area, "th-cluster-1"); auto thCluster_2 = addClusterToArea(area, "th-cluster-2"); - area->resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); + area->resizeAllTimeseriesNumbers(1 + study->runtime.rangeLimits.year[rangeEnd]); TSGenerator::ResizeGeneratedTimeSeries(study->areas, study->parameters); BOOST_CHECK(Generate(*study)); @@ -425,7 +424,7 @@ BOOST_AUTO_TEST_CASE( auto thCluster_1 = addClusterToArea(area, "th-cluster-1"); auto thCluster_2 = addClusterToArea(area, "th-cluster-2"); - area->resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); + area->resizeAllTimeseriesNumbers(1 + study->runtime.rangeLimits.year[rangeEnd]); TSGenerator::ResizeGeneratedTimeSeries(study->areas, study->parameters); BOOST_CHECK(Generate(*study)); @@ -461,7 +460,7 @@ BOOST_AUTO_TEST_CASE( auto thCluster_1 = addClusterToArea(area, "th-cluster-1"); auto thCluster_2 = addClusterToArea(area, "th-cluster-2"); - area->resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); + area->resizeAllTimeseriesNumbers(1 + study->runtime.rangeLimits.year[rangeEnd]); TSGenerator::ResizeGeneratedTimeSeries(study->areas, study->parameters); BOOST_CHECK(not Generate(*study)); @@ -486,7 +485,7 @@ BOOST_AUTO_TEST_CASE( auto rnCluster_1 = addClusterToArea(area, "rn-cluster-1"); rnCluster_1->series.timeSeries.resize(5, 1); - area->resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); + area->resizeAllTimeseriesNumbers(1 + study->runtime.rangeLimits.year[rangeEnd]); BOOST_CHECK(Generate(*study)); @@ -515,7 +514,7 @@ BOOST_AUTO_TEST_CASE( auto rnCluster_1 = addClusterToArea(area, "rn-cluster-1"); rnCluster_1->series.timeSeries.resize(4, 1); - area->resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); + area->resizeAllTimeseriesNumbers(1 + study->runtime.rangeLimits.year[rangeEnd]); BOOST_CHECK(not Generate(*study)); } @@ -539,7 +538,7 @@ BOOST_AUTO_TEST_CASE( auto rnCluster_1 = addClusterToArea(area, "rn-cluster-1"); rnCluster_1->series.timeSeries.resize(1, 1); - area->resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); + area->resizeAllTimeseriesNumbers(1 + study->runtime.rangeLimits.year[rangeEnd]); BOOST_CHECK(Generate(*study)); } @@ -581,7 +580,7 @@ BOOST_AUTO_TEST_CASE(load_wind_thermal_in_intra_and_inter_modal____check_all_ts_ area_2->wind.series.timeSeries.resize(5, 1); // Ready made TS for wind auto thCluster_area_2 = addClusterToArea(area_2, "th-cluster-area-2"); - study->areas.resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); + study->areas.resizeAllTimeseriesNumbers(1 + study->runtime.rangeLimits.year[rangeEnd]); TSGenerator::ResizeGeneratedTimeSeries(study->areas, study->parameters); BOOST_CHECK(Generate(*study)); @@ -629,14 +628,14 @@ BOOST_AUTO_TEST_CASE(check_all_drawn_ts_numbers_are_bounded_between_0_and_nb_of_ auto thCluster = addClusterToArea(area, "th-cluster"); - area->resizeAllTimeseriesNumbers(1 + study->runtime->rangeLimits.year[rangeEnd]); + area->resizeAllTimeseriesNumbers(1 + study->runtime.rangeLimits.year[rangeEnd]); auto bc = study->bindingConstraints.add("dummy"); bc->group("dummy"); study->bindingConstraintsGroups.add(bc->group()); bc->RHSTimeSeries().resize(42, 1); study->bindingConstraintsGroups.resizeAllTimeseriesNumbers( - 1 + study->runtime->rangeLimits.year[rangeEnd]); + 1 + study->runtime.rangeLimits.year[rangeEnd]); TSGenerator::ResizeGeneratedTimeSeries(study->areas, study->parameters); BOOST_CHECK(Generate(*study)); diff --git a/src/tools/ts-generator/linksTSgenerator.cpp b/src/tools/ts-generator/linksTSgenerator.cpp index 7ad893194a..a200386a7e 100644 --- a/src/tools/ts-generator/linksTSgenerator.cpp +++ b/src/tools/ts-generator/linksTSgenerator.cpp @@ -237,8 +237,8 @@ void readPreproTimeSeries(std::vector& linkList, fs::pat // Class methods // ================== LinksTSgenerator::LinksTSgenerator(Settings& settings): - studyFolder_(settings.studyFolder), linksFromCmdLineOptions_(settings.linksListToGen), + studyFolder_(settings.studyFolder), generateTSforAllLinks_(settings.allLinks) { } From f25b2607213c0003c62eccd7b47dcc0459ab90cc Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Wed, 17 Jul 2024 15:49:03 +0200 Subject: [PATCH 73/78] Improve infeasible pb test : simplify tests by simplifying infeasible problem construction --- .../test-unfeasible-problem-analyzer.cpp | 54 ++++++------------- 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index aacb9e0b37..0ba7ad866b 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -87,58 +87,34 @@ class AnalysisMock: public UnfeasibilityAnalysis bool& hasPrinted_; }; -/*! - * Creates a 2 problems (feasible and infeasible) with 2 variables linked by 1 constraint: - * - Variable 1 must be greater than 1 - * - Variable 2 must be smaller than -1 - * - For infeasible problem, constraint enforces that variable 2 is greater than variable 1 - */ -std::unique_ptr createProblem(const std::string& constraintName) +void addOneVarConstraintToProblem(MPSolver* problem, + const std::string& varName, + const double& varLowBnd, + const double& varUpBnd, + const double& ConstLowBnd) { - std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); - const double infinity = problem->infinity(); - problem->MakeNumVar(1, infinity, "var1"); - problem->MakeNumVar(-infinity, -1, "var2"); - auto constraint = problem->MakeRowConstraint(constraintName); - constraint->SetBounds(0, infinity); - return problem; + auto* var = problem->MakeNumVar(varLowBnd, varUpBnd, varName); + auto* constraint = problem->MakeRowConstraint(varName); + constraint->SetCoefficient(var, 1); + constraint->SetBounds(ConstLowBnd, problem->infinity()); } std::unique_ptr createFeasibleProblem(const std::string& constraintName) { - auto problem = createProblem(constraintName); - auto constraint = problem->LookupConstraintOrNull(constraintName); - auto var1 = problem->LookupVariableOrNull("var1"); - auto var2 = problem->LookupVariableOrNull("var2"); - constraint->SetCoefficient(var1, 1); - constraint->SetCoefficient(var2, -1); + std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); + // Following constraint is easily satisfied + addOneVarConstraintToProblem(problem.get(), constraintName, 0., 1., 0.); return problem; } std::unique_ptr createUnfeasibleProblem(const std::string& constraintName) { - auto problem = createProblem(constraintName); - auto constraint = problem->LookupConstraintOrNull(constraintName); - auto var1 = problem->LookupVariableOrNull("var1"); - auto var2 = problem->LookupVariableOrNull("var2"); - constraint->SetCoefficient(var1, -1); - constraint->SetCoefficient(var2, 1); + std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); + // Following constraint cannot be satisfied + addOneVarConstraintToProblem(problem.get(), constraintName, 0., 1., 2.); return problem; } -void addOneVarConstraintToProblem(MPSolver* problem, - const std::string& name, - const double& varLowBnd, - const double& varUpBnd, - const double& ConstLowBnd) -{ - std::string varName = "slack-for-" + name; - auto* var = problem->MakeNumVar(varLowBnd, varUpBnd, varName); - auto* constraint = problem->MakeRowConstraint(name); - constraint->SetCoefficient(var, 1); - constraint->SetBounds(ConstLowBnd, problem->infinity()); -} - std::unique_ptr createProblemWith_n_violatedConstraints(const int n) { std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); From beb39da598c295aa9f9b8e269e8c14306539e438 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Thu, 18 Jul 2024 10:59:34 +0200 Subject: [PATCH 74/78] Improve infeasible pb test : give a name to the (only) var of constraints we build for tests Unlike what was done, the only var in the constraint should a name on its own : a name different from the constraint' name --- .../test-unfeasible-problem-analyzer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index 0ba7ad866b..47c4254892 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -88,13 +88,14 @@ class AnalysisMock: public UnfeasibilityAnalysis }; void addOneVarConstraintToProblem(MPSolver* problem, - const std::string& varName, + const std::string& constraintName, const double& varLowBnd, const double& varUpBnd, const double& ConstLowBnd) { + std::string varName = "lonely-var-in-" + constraintName; auto* var = problem->MakeNumVar(varLowBnd, varUpBnd, varName); - auto* constraint = problem->MakeRowConstraint(varName); + auto* constraint = problem->MakeRowConstraint(constraintName); constraint->SetCoefficient(var, 1); constraint->SetBounds(ConstLowBnd, problem->infinity()); } From 3fe3d72dcc8db147b1f7d6a8c6c7733fe70a80eb Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Thu, 18 Jul 2024 11:33:39 +0200 Subject: [PATCH 75/78] Improve infeasible pb test : cleaning due to review --- .../constraint-slack-analysis.cpp | 2 +- .../constraint-slack-analysis.h | 2 +- .../test-unfeasible-problem-analyzer.cpp | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index 662b12c2dc..f771e011a5 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -138,7 +138,7 @@ bool ConstraintSlackAnalysis::anySlackVariableNonZero() [&](auto& v) { return v->solution_value() > thresholdNonZero; }); } -std::vector& +const std::vector& ConstraintSlackAnalysis::largestSlackVariables() { return slackVariables_; diff --git a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h index d00c395958..352176a41e 100644 --- a/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h +++ b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/constraint-slack-analysis.h @@ -52,7 +52,7 @@ class ConstraintSlackAnalysis: public UnfeasibilityAnalysis return "Slack variables analysis"; } - std::vector& largestSlackVariables(); + const std::vector& largestSlackVariables(); private: void selectConstraintsToWatch(operations_research::MPSolver* problem); diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index 47c4254892..060b525b91 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -89,9 +89,9 @@ class AnalysisMock: public UnfeasibilityAnalysis void addOneVarConstraintToProblem(MPSolver* problem, const std::string& constraintName, - const double& varLowBnd, - const double& varUpBnd, - const double& ConstLowBnd) + double varLowBnd, + double varUpBnd, + double ConstLowBnd) { std::string varName = "lonely-var-in-" + constraintName; auto* var = problem->MakeNumVar(varLowBnd, varUpBnd, varName); @@ -121,11 +121,11 @@ std::unique_ptr createProblemWith_n_violatedConstraints(const int n) std::unique_ptr problem(MPSolver::CreateSolver("GLOP")); for (auto i: std::ranges::iota_view(1, n + 1)) // From 1 to n included { - char name[32]; - std::sprintf(name, "BC-name-%d::hourly::hour<%d>", i, 5 * i); + std::stringstream name; + name << "BC-name-" << i << "::hourly::hour<" << 5 * i << ">"; // Make a constraint that can never be satisfied, of type : var > A, // where : bound_inf(var) = 0, bound_sup(var) = 1 and A > 1. - addOneVarConstraintToProblem(problem.get(), name, 0, 1, i + 2); + addOneVarConstraintToProblem(problem.get(), name.str(), 0., 1., double(i + 2)); } return problem; } From 768680f6a64bbca0e3bf1a6f5fbfd4d617dfeca0 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Thu, 18 Jul 2024 11:42:04 +0200 Subject: [PATCH 76/78] Improve infeasible pb test : renaming --- .../infeasible-problem-analysis/constraint-slack-analysis.cpp | 4 ++-- src/solver/infeasible-problem-analysis/report.cpp | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp index f771e011a5..68c11ff003 100644 --- a/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp +++ b/src/solver/infeasible-problem-analysis/constraint-slack-analysis.cpp @@ -33,7 +33,7 @@ using namespace operations_research; namespace { -bool compareSlackSolutions(const MPVariable* a, const MPVariable* b) +bool greaterSlackSolutions(const MPVariable* a, const MPVariable* b) { return a->solution_value() > b->solution_value(); } @@ -123,7 +123,7 @@ void ConstraintSlackAnalysis::buildObjective(MPSolver* problem) const void ConstraintSlackAnalysis::sortSlackVariablesByValue() { - std::sort(std::begin(slackVariables_), std::end(slackVariables_), ::compareSlackSolutions); + std::sort(std::begin(slackVariables_), std::end(slackVariables_), ::greaterSlackSolutions); } void ConstraintSlackAnalysis::trimSlackVariables() diff --git a/src/solver/infeasible-problem-analysis/report.cpp b/src/solver/infeasible-problem-analysis/report.cpp index dc42dce073..4be4463400 100644 --- a/src/solver/infeasible-problem-analysis/report.cpp +++ b/src/solver/infeasible-problem-analysis/report.cpp @@ -67,8 +67,7 @@ void InfeasibleProblemReport::filterConstraintsToOneByType() { // 1. Grouping constraints by C++ type (inside a group, order of instances remains unchanged) std::ranges::stable_sort(constraints_, lessTypeName); - // 2. Keeping the first instances of each group, and rejecting others (= duplicates) to the end - // of vector + // 2. Keeping the first instances of each group, and rejecting others (= duplicates) to the end. auto duplicates = std::ranges::unique(constraints_, sameType); // 3. Removing trailing duplicates constraints_.erase(duplicates.begin(), duplicates.end()); From 79df835b12355ee12138490b87aabb36f7dccfef Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Thu, 18 Jul 2024 11:46:34 +0200 Subject: [PATCH 77/78] [skip ci] Improve infeasible pb test : remove useless include --- .../test-unfeasible-problem-analyzer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp index 060b525b91..2155fd48c4 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp +++ b/src/tests/src/solver/infeasible-problem-analysis/test-unfeasible-problem-analyzer.cpp @@ -21,7 +21,6 @@ #define WIN32_LEAN_AND_MEAN #define BOOST_TEST_MODULE unfeasible_problem_analyzer -#include #include #include From 67f31e4e1295d4ebf9ba0d8fc54740eeb88b67d7 Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Fri, 19 Jul 2024 15:54:45 +0200 Subject: [PATCH 78/78] Remove manual dynamic allocations in Xcast (#2270) #2244 --- src/libs/antares/study/area/list.cpp | 44 ++-- .../study/include/antares/study/area/area.h | 2 +- .../include/antares/solver/misc/cholesky.hxx | 6 +- .../antares/solver/ts-generator/xcast/xcast.h | 90 +++---- src/solver/ts-generator/xcast/core.cpp | 13 +- src/solver/ts-generator/xcast/xcast.cpp | 221 +++++------------- 6 files changed, 130 insertions(+), 246 deletions(-) diff --git a/src/libs/antares/study/area/list.cpp b/src/libs/antares/study/area/list.cpp index de3c2e9b1f..46a2e98c6f 100644 --- a/src/libs/antares/study/area/list.cpp +++ b/src/libs/antares/study/area/list.cpp @@ -449,43 +449,31 @@ const AreaLink* AreaList::findLink(const AreaName& area, const AreaName& with) c void AreaList::clear() { - delete[] byIndex; - byIndex = nullptr; + byIndex.clear(); - if (!areas.empty()) - { - Area::Map copy; - copy.swap(areas); + Area::Map copy; + copy.swap(areas); - auto end = copy.end(); - for (auto i = copy.begin(); i != end; ++i) - { - delete i->second; - } + auto end = copy.end(); + for (auto i = copy.begin(); i != end; ++i) + { + delete i->second; } } void AreaList::rebuildIndexes() { - delete[] byIndex; + byIndex.clear(); - if (areas.empty()) - { - byIndex = nullptr; - } - else - { - using AreaWeakPtr = Area*; - byIndex = new AreaWeakPtr[areas.size()]; + byIndex.resize(areas.size()); - uint indx = 0; - auto end = areas.end(); - for (auto i = areas.begin(); i != end; ++i, ++indx) - { - Area* area = i->second; - byIndex[indx] = area; - area->index = indx; - } + uint indx = 0; + auto end = areas.end(); + for (auto i = areas.begin(); i != end; ++i, ++indx) + { + Area* area = i->second; + byIndex[indx] = area; + area->index = indx; } } diff --git a/src/libs/antares/study/include/antares/study/area/area.h b/src/libs/antares/study/include/antares/study/area/area.h index 6661ab8556..7550d9840f 100644 --- a/src/libs/antares/study/include/antares/study/area/area.h +++ b/src/libs/antares/study/include/antares/study/area/area.h @@ -689,7 +689,7 @@ class AreaList final: public Yuni::NonCopyable public: //! All areas by their index - Area** byIndex = nullptr; + std::vector byIndex; //! All areas in the list Area::Map areas; diff --git a/src/solver/misc/include/antares/solver/misc/cholesky.hxx b/src/solver/misc/include/antares/solver/misc/cholesky.hxx index 26c333d785..90418c17b2 100644 --- a/src/solver/misc/include/antares/solver/misc/cholesky.hxx +++ b/src/solver/misc/include/antares/solver/misc/cholesky.hxx @@ -42,7 +42,7 @@ bool Cholesky(U1& L, U2& A, uint size, T* temp) for (uint i = 0; i < size; ++i) { - typename MatrixSubColumn::Type Li = L[i]; + auto& Li = L[i]; // on calcule d'abord L[i][i] som = A[i][i]; @@ -58,8 +58,8 @@ bool Cholesky(U1& L, U2& A, uint size, T* temp) // maintenant on cherche L[k][i], k > i. for (uint k = i + 1; k < size; ++k) { - typename MatrixSubColumn::Type Lk = L[k]; - typename MatrixSubColumn::Type Ak = A[k]; + auto& Lk = L[k]; + auto& Ak = A[k]; if (temp[k] == Ak[k]) { diff --git a/src/solver/ts-generator/include/antares/solver/ts-generator/xcast/xcast.h b/src/solver/ts-generator/include/antares/solver/ts-generator/xcast/xcast.h index 55bb128e85..34b588b972 100644 --- a/src/solver/ts-generator/include/antares/solver/ts-generator/xcast/xcast.h +++ b/src/solver/ts-generator/include/antares/solver/ts-generator/xcast/xcast.h @@ -74,7 +74,7 @@ class XCast final: private Yuni::NonCopyable /*! ** \brief Destructor */ - ~XCast(); + ~XCast() = default; //@} //! \name Loading @@ -105,7 +105,6 @@ class XCast final: private Yuni::NonCopyable private: void allocateTemporaryData(); - void destroyTemporaryData(); template void updateMissingCoefficients(PredicateT& predicate); @@ -180,7 +179,7 @@ class XCast final: private Yuni::NonCopyable //! The correlation matrix for the current month const Matrix* pCorrMonth; - bool pNeverInitialized; + bool pNeverInitialized = true; uint Nombre_points_intermediaire; //! True when starting a new month (some data may have to be reinitialized) @@ -192,57 +191,58 @@ class XCast final: private Yuni::NonCopyable uint pNDPMatrixCount; uint pLevellingCount; - bool pAccuracyOnCorrelation; + bool pAccuracyOnCorrelation = false; bool All_normal; // all processes are Normal - float* A; // les variables de A à CO sont des vues de ALPH à CORR pour un mois particulier - float* B; - float* G; - float* D; - int* M; - float* T; - Data::XCast::Distribution* L; - bool* BO; - float* MA; - float* MI; - float** FO; // contrainte : FO >=0 + // les variables de A à CO sont des vues de ALPH à CORR pour un mois particulier + std::vector A; + std::vector B; + std::vector G; + std::vector D; + std::vector M; + std::vector T; + std::vector L; + std::vector BO; + std::vector MA; + std::vector MI; + std::vector> FO; // contrainte : FO >=0 float STEP; float SQST; - float* POSI; - float** CORR; - float* MAXI; - float* MINI; - float* Presque_maxi; - float* Presque_mini; - float* ESPE; - float* STDE; - float** LISS; - float** DATL; - - float* DIFF; - float* TREN; - float* WIEN; - float* BROW; - - float* BASI; // used only if all processes are Normal - float* ALPH; // used only if all processes are Normal - float* BETA; // used only if all processes are Normal - - float** Triangle_reference; - float** Triangle_courant; - float** Carre_reference; - float** Carre_courant; - - float* D_COPIE; - - float** DATA; + std::vector POSI; + std::vector> CORR; + std::vector MAXI; + std::vector MINI; + std::vector Presque_maxi; + std::vector Presque_mini; + std::vector ESPE; + std::vector STDE; + std::vector> LISS; + std::vector> DATL; + + std::vector DIFF; + std::vector TREN; + std::vector WIEN; + std::vector BROW; + + std::vector BASI; // used only if all processes are Normal + std::vector ALPH; // used only if all processes are Normal + std::vector BETA; // used only if all processes are Normal + + std::vector> Triangle_reference; + std::vector> Triangle_courant; + std::vector> Carre_reference; + std::vector> Carre_courant; + + std::vector D_COPIE; + + std::vector> DATA; // cholesky temporary data - float* pQCHOLTotal; + std::vector pQCHOLTotal; //! - bool* pUseConversion; + std::vector pUseConversion; //! Name of the current timeseries Yuni::CString<32, false> pTSName; diff --git a/src/solver/ts-generator/xcast/core.cpp b/src/solver/ts-generator/xcast/core.cpp index a3d373e2c1..1eab73d534 100644 --- a/src/solver/ts-generator/xcast/core.cpp +++ b/src/solver/ts-generator/xcast/core.cpp @@ -93,7 +93,7 @@ bool XCast::generateValuesForTheCurrentDay() // si les parametres ont change on reinitialise certaines variables intermediaires if (pNewMonth) { - if (Cholesky(Triangle_courant, pCorrMonth->entry, processCount, pQCHOLTotal)) + if (Cholesky(Triangle_courant, pCorrMonth->entry, processCount, pQCHOLTotal.data())) { // C n'est pas sdp, mais peut-etre proche de sdp // on tente un abattement de 0.999 @@ -107,7 +107,10 @@ bool XCast::generateValuesForTheCurrentDay() } } - if (Cholesky(Triangle_courant, pCorrMonth->entry, processCount, pQCHOLTotal)) + if (Cholesky(Triangle_courant, + pCorrMonth->entry, + processCount, + pQCHOLTotal.data())) { // la matrice C n'est pas admissible, on abandonne logs.error() << "TS " << pTSName << " generator: invalid correlation matrix"; @@ -227,7 +230,7 @@ bool XCast::generateValuesForTheCurrentDay() Carre_reference, pCorrMonth->entry, processCount, - pQCHOLTotal); + pQCHOLTotal.data()); if (shrink == -1.f) { // sortie impossible car on a v�rifi� que C est d.p @@ -414,7 +417,7 @@ bool XCast::generateValuesForTheCurrentDay() for (uint s = 0; s != processCount; ++s) { - float* corr_s = CORR[s]; + auto& corr_s = CORR[s]; auto& userMonthlyCorr = pCorrMonth->column(s); for (uint t = 0; t < s; ++t) { @@ -453,7 +456,7 @@ bool XCast::generateValuesForTheCurrentDay() Carre_courant, Carre_reference, processCount, - pQCHOLTotal); + pQCHOLTotal.data()); if (shrink <= 1.f) { if (shrink == -1.f) diff --git a/src/solver/ts-generator/xcast/xcast.cpp b/src/solver/ts-generator/xcast/xcast.cpp index 56f7234119..b431e8d8ff 100644 --- a/src/solver/ts-generator/xcast/xcast.cpp +++ b/src/solver/ts-generator/xcast/xcast.cpp @@ -52,17 +52,10 @@ enum XCast::XCast(Data::Study& study, Data::TimeSeriesType ts, IResultWriter& writer): study(study), timeSeriesType(ts), - pNeverInitialized(true), - pAccuracyOnCorrelation(false), pWriter(writer) { } -XCast::~XCast() -{ - destroyTemporaryData(); -} - template void XCast::exportTimeSeriesToTheOutput(Progression::Task& progression, PredicateT& predicate) { @@ -114,8 +107,6 @@ void XCast::applyTransferFunction(PredicateT& predicate) float a[maxPoints]; float b[maxPoints]; - float* dailyResults; - const uint processCount = (uint)pData.localareas.size(); for (uint s = 0; s != processCount; ++s) @@ -145,7 +136,7 @@ void XCast::applyTransferFunction(PredicateT& predicate) b[i] = (p0[y] * p1[x] - p1[y] * p0[x]) / (p1[x] - p0[x]); } - dailyResults = DATA[s]; + auto& dailyResults = DATA[s]; for (h = 0; h != HOURS_PER_DAY; ++h) { for (i = 0; i != tf.width; ++i) @@ -200,162 +191,64 @@ void XCast::updateMissingCoefficients(PredicateT& predicate) } } -namespace -{ -template -class Allocator -{ -public: - Allocator(): - allocated(0) - { - } - - ~Allocator() - { - logs.debug() << " allocated " << (allocated / 1024) << "Ko"; - } - - template - inline T* allocate(const size_t s) - { - allocated += sizeof(T) * s; - return new T[s]; - } - -public: - size_t allocated; -}; - -template<> -class Allocator<0> -{ -public: - template - inline T* allocate(const size_t s) const - { - return new T[s]; - } -}; - -} // namespace - void XCast::allocateTemporaryData() { uint p = (uint)pData.localareas.size(); - Allocator m; - - A = m.allocate(p); - B = m.allocate(p); - G = m.allocate(p); - D = m.allocate(p); - M = m.allocate(p); - T = m.allocate(p); - BO = m.allocate(p); - MA = m.allocate(p); - MI = m.allocate(p); - L = m.allocate(p); - POSI = m.allocate(p); - MAXI = m.allocate(p); - MINI = m.allocate(p); - ESPE = m.allocate(p); - STDE = m.allocate(p); - DIFF = m.allocate(p); - TREN = m.allocate(p); - WIEN = m.allocate(p + 1); - BROW = m.allocate(p); - - BASI = m.allocate(p); - ALPH = m.allocate(p); - BETA = m.allocate(p); - - D_COPIE = m.allocate(p); - - pUseConversion = m.allocate(p); - - Presque_maxi = m.allocate(p); - Presque_mini = m.allocate(p); - pQCHOLTotal = m.allocate(p); - - CORR = m.allocate(p); - Triangle_reference = m.allocate(p); - Triangle_courant = m.allocate(p); - FO = m.allocate(p); - LISS = m.allocate(p); - DATL = m.allocate(p); - DATA = m.allocate(p); - Carre_courant = m.allocate(p); - Carre_reference = m.allocate(p); + A.resize(p); + B.resize(p); + G.resize(p); + D.resize(p); + M.resize(p); + T.resize(p); + BO.resize(p); + MA.resize(p); + MI.resize(p); + L.resize(p); + POSI.resize(p); + MAXI.resize(p); + MINI.resize(p); + ESPE.resize(p); + STDE.resize(p); + DIFF.resize(p); + TREN.resize(p); + WIEN.resize(p + 1); + BROW.resize(p); + + BASI.resize(p); + ALPH.resize(p); + BETA.resize(p); + + D_COPIE.resize(p); + + pUseConversion.resize(p); + + Presque_maxi.resize(p); + Presque_mini.resize(p); + pQCHOLTotal.resize(p); + + CORR.resize(p); + Triangle_reference.resize(p); + Triangle_courant.resize(p); + FO.resize(p); + LISS.resize(p); + DATL.resize(p); + DATA.resize(p); + Carre_courant.resize(p); + Carre_reference.resize(p); for (uint i = 0; i != p; ++i) { - Triangle_reference[i] = m.allocate(p); - Triangle_courant[i] = m.allocate(p); - Carre_courant[i] = m.allocate(p); - Carre_reference[i] = m.allocate(p); - - CORR[i] = m.allocate(p); - FO[i] = m.allocate(24); - LISS[i] = m.allocate(24); - DATL[i] = m.allocate(24); - DATA[i] = m.allocate(24); - } -} - -void XCast::destroyTemporaryData() -{ - if (!pNeverInitialized) - { - uint p = (uint)pData.localareas.size(); - for (uint i = 0; i != p; ++i) - { - delete[] CORR[i]; - delete[] FO[i]; - delete[] LISS[i]; - delete[] DATL[i]; - delete[] Triangle_reference[i]; - delete[] Triangle_courant[i]; - delete[] DATA[i]; - delete[] Carre_courant[i]; - delete[] Carre_reference[i]; - } - delete[] Carre_courant; - delete[] Carre_reference; - delete[] D_COPIE; - delete[] DATA; - delete[] Triangle_reference; - delete[] Triangle_courant; - delete[] LISS; - delete[] DATL; - delete[] CORR; - delete[] FO; - delete[] A; - delete[] B; - delete[] G; - delete[] D; - delete[] M; - delete[] T; - delete[] L; - delete[] BO; - delete[] MA; - delete[] MI; - delete[] POSI; - delete[] MAXI; - delete[] MINI; - delete[] Presque_maxi; - delete[] Presque_mini; - delete[] ESPE; - delete[] STDE; - delete[] DIFF; - delete[] TREN; - delete[] WIEN; - delete[] BROW; - delete[] BASI; - delete[] ALPH; - delete[] BETA; - delete[] pQCHOLTotal; - delete[] pUseConversion; + Triangle_reference[i].resize(p); + Triangle_courant[i].resize(p); + Carre_courant[i].resize(p); + Carre_reference[i].resize(p); + + CORR[i].resize(p); + FO[i].resize(24); + LISS[i].resize(24); + DATL[i].resize(24); + DATA[i].resize(24); } } @@ -476,7 +369,7 @@ bool XCast::runWithPredicate(PredicateT& predicate, Progression::Task& progressi MA[s] = +std::numeric_limits::max(); } } - memcpy(FO[s], xcastdata.K[realmonth], sizeof(float) * HOURS_PER_DAY); + memcpy(FO[s].data(), xcastdata.K[realmonth], sizeof(float) * HOURS_PER_DAY); } uint nbDaysPerMonth = study.calendar.months[month].days; @@ -491,7 +384,7 @@ bool XCast::runWithPredicate(PredicateT& predicate, Progression::Task& progressi for (uint s = 0; s != processCount; ++s) { - float* dailyResults = DATA[s]; + auto& dailyResults = DATA[s]; for (uint h = 0; h != HOURS_PER_DAY; ++h) { @@ -512,7 +405,7 @@ bool XCast::runWithPredicate(PredicateT& predicate, Progression::Task& progressi } auto& column = srcData.translation[0]; - float* dailyResults = DATA[s]; + auto& dailyResults = DATA[s]; assert(hourInTheYear + HOURS_PER_DAY <= srcData.translation.height && "Bound checking"); @@ -529,7 +422,7 @@ bool XCast::runWithPredicate(PredicateT& predicate, Progression::Task& progressi for (uint s = 0; s != processCount; ++s) { - float* dailyResults = DATA[s]; + auto& dailyResults = DATA[s]; for (uint h = 0; h != HOURS_PER_DAY; ++h) { @@ -548,7 +441,7 @@ bool XCast::runWithPredicate(PredicateT& predicate, Progression::Task& progressi auto& series = predicate.matrix(currentArea); assert(tsIndex < series.width); auto& column = series.column(tsIndex); - float* dailyResults = DATA[s]; + auto& dailyResults = DATA[s]; for (uint h = 0; h != HOURS_PER_DAY; ++h) {