Skip to content

Commit

Permalink
Fix infeasible analyzer : several corrections
Browse files Browse the repository at this point in the history
  • Loading branch information
guilpier-code committed Jul 2, 2024
1 parent 54954cd commit dea29db
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 44 deletions.
27 changes: 9 additions & 18 deletions src/solver/infeasible-problem-analysis/constraint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include <cassert>
#include <iomanip>
#include <sstream>
#include <boost/regex.hpp>
#include <boost/algorithm/string/regex.hpp>

namespace
{
Expand All @@ -40,24 +42,7 @@ Constraint::Constraint(const std::string& input, const double slackValue):

std::size_t Constraint::extractItems()
{
const auto beg = mInput.begin();
const auto end = mInput.end();
std::size_t newPos = 0;
const std::size_t sepSize = 2;
const std::size_t inputSize = mInput.size();
for (std::size_t pos = 0; pos < inputSize; pos = newPos + sepSize)
{
newPos = mInput.find("::", pos);
if (newPos == std::string::npos)
{
mItems.emplace_back(beg + pos, end);
break;
}
if (newPos > pos)
{
mItems.emplace_back(beg + pos, beg + newPos);
}
}
boost::algorithm::split_regex(mItems, mInput, boost::regex("::"));
return mItems.size();
}

Expand Down Expand Up @@ -158,6 +143,10 @@ ConstraintType Constraint::getType() const
{
return ConstraintType::hydro_reservoir_level;
}
if (mItems.at(0) == "HydroPower")
{
return ConstraintType::hydro_production_weekly;
}
if (mItems.at(0) == "Level")
{
return ConstraintType::short_term_storage_level;
Expand Down Expand Up @@ -209,6 +198,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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ class ConstraintSlackAnalysis: public UnfeasibilityAnalysis

std::vector<const operations_research::MPVariable*> slackVariables_;
const std::string constraint_name_pattern = "^AreaHydroLevel::|::hourly::|::daily::|::weekly::|"
"^FictiveLoads::|^Level::";
"^FictiveLoads::|^Level::|"
"^HydroPower::";
};

} // namespace Antares::Optimization
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ enum class ConstraintType
binding_constraint_weekly,
fictitious_load,
hydro_reservoir_level,
hydro_production_weekly,
short_term_storage_level,
none
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ class InfeasibleProblemReport
void extractItems();
void logSuspiciousConstraints();

std::vector<Constraint> mConstraints;
std::map<ConstraintType, unsigned int> mTypes;
const unsigned int nbVariables = 10;
std::vector<Constraint> constraints_;
std::map<ConstraintType, unsigned int> nbConstraintsByType_;
const unsigned int nbMaxVariables = 10;
};
} // namespace Antares::Optimization
38 changes: 19 additions & 19 deletions src/solver/infeasible-problem-analysis/report.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,80 +40,80 @@ static bool compareSlackSolutions(const Antares::Optimization::Constraint& a,
namespace Antares::Optimization
{
InfeasibleProblemReport::InfeasibleProblemReport(
const std::vector<const MPVariable*>& slackVariables)
const std::vector<const MPVariable*>& slackVariables)
{
turnSlackVarsIntoConstraints(slackVariables);
sortConstraints();
trimConstraints();
}

void InfeasibleProblemReport::turnSlackVarsIntoConstraints(
const std::vector<const MPVariable*>& slackVariables)
const std::vector<const MPVariable*>& 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())
{
mConstraints.resize(nbVariables);
}
unsigned int nbConstraints = constraints_.size();
constraints_.resize(std::min(nbMaxVariables, nbConstraints));
}

void InfeasibleProblemReport::extractItems()
{
for (auto& c: mConstraints)
for (auto& c: constraints_)
{
if (c.extractItems() == 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::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 (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,";
}

Antares::logs.error() << "* Negative hurdle costs on lines with infinite capacity (rare).";
}

void InfeasibleProblemReport::prettyPrint()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ void ISimulation<ImplementationType>::run()
}
else
{
// Export ts-numbers into output
TimeSeriesNumbers::StoreTimeSeriesNumbersIntoOuput(study, pResultWriter);

if (not ImplementationType::simulationBegin())
{
return;
Expand Down Expand Up @@ -358,9 +361,6 @@ void ISimulation<ImplementationType>::run()

ImplementationType::variables.simulationEnd();

// Export ts-numbers into output
TimeSeriesNumbers::StoreTimeSeriesNumbersIntoOuput(study, pResultWriter);

// Spatial clusters
// Notifying all variables to perform the final spatial clusters.
// This must be done only when all variables have finished to compute their
Expand Down

0 comments on commit dea29db

Please sign in to comment.