diff --git a/src/solver/infeasible-problem-analysis/constraint.cpp b/src/solver/infeasible-problem-analysis/constraint.cpp index 8d9491695e..2c4fd6d085 100644 --- a/src/solver/infeasible-problem-analysis/constraint.cpp +++ b/src/solver/infeasible-problem-analysis/constraint.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -35,16 +36,15 @@ 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) { } -std::size_t Constraint::extractComponentsFromName() +void Constraint::extractComponentsFromName() { boost::algorithm::split_regex(nameComponents_, name_, boost::regex("::")); - return nameComponents_.size(); } double Constraint::getSlackValue() const @@ -61,67 +61,36 @@ 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::ostringstream stream; - stream << std::string("Error the string: ") << std::quoted(str) - << " does not contains the left angle bracket " << std::quoted("<"); - throw StringIsNotWellFormated(stream.str()); - } - - auto right = std::find(begin, end, '>'); - if (right == 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 right angle bracket " << std::quoted(">"); - throw StringIsNotWellFormated(stream.str()); + err_msg += "constraint name '" + constraintName + "' misses '<' and/or '>' bracket"; + throw StringIsNotWellFormated(err_msg); } - - 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::getAreaName() const +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::getTimeStepInYear() const +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 +ConstraintType Constraint::type() const { assert(nameComponents_.size() > 1); if (nameComponents_.at(1) == "hourly") @@ -155,56 +124,35 @@ 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) - { - 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 '" + 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..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 @@ -40,27 +40,23 @@ enum class ConstraintType 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; - // Extract items, check consistency - std::size_t extractComponentsFromName(); + void extractComponentsFromName(); std::string prettyPrint() const; - ConstraintType getType() const; + ConstraintType type() const; private: std::string name_; std::vector nameComponents_; 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/include/antares/solver/infeasible-problem-analysis/report.h b/src/solver/infeasible-problem-analysis/include/antares/solver/infeasible-problem-analysis/report.h index 334e09c979..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,10 +44,11 @@ class InfeasibleProblemReport private: void turnSlackVarsIntoConstraints( const std::vector& slackVariables); - void sortConstraints(); + void sortConstraintsBySlackValue(); 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 2022bfbfd6..5154cffa0e 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); } @@ -71,11 +72,8 @@ void InfeasibleProblemReport::sortConstraintsByType() { for (auto& c: constraints_) { - if (c.extractComponentsFromName() == 0) - { - return; - } - nbConstraintsByType_[c.getType()]++; + c.extractComponentsFromName(); + nbConstraintsByType_[c.type()]++; } } @@ -86,6 +84,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) { @@ -114,14 +116,12 @@ void InfeasibleProblemReport::logSuspiciousConstraints() { Antares::logs.error() << "* Binding constraints,"; } - - Antares::logs.error() << "* Negative hurdle costs on lines with infinite capacity (rare)."; } void InfeasibleProblemReport::prettyPrint() { - sortConstraintsByType(); logSuspiciousConstraints(); + logInfeasibilityCauses(); } } // 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 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>", };