Skip to content

Commit

Permalink
Infeasibility anaylsis : make it more changeable (#2232)
Browse files Browse the repository at this point in the history
Create classes for each constraint type, with a common interface. Additional tests to come.

---------

Co-authored-by: Florian OMNES <26088210+flomnes@users.noreply.github.com>
Co-authored-by: Florian Omnès <florian.omnes@rte-france.com>
  • Loading branch information
3 people authored Jul 17, 2024
1 parent 8cc64f9 commit 89ac6c8
Show file tree
Hide file tree
Showing 10 changed files with 436 additions and 355 deletions.
4 changes: 2 additions & 2 deletions src/solver/infeasible-problem-analysis/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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/constraint.h
constraint.cpp
include/antares/solver/infeasible-problem-analysis/watched-constraints.h
watched-constraints.cpp
)

add_library(infeasible_problem_analysis ${SRC_INFEASIBLE_PROBLEM_ANALYSIS})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,23 @@

using namespace operations_research;

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
{

void ConstraintSlackAnalysis::run(MPSolver* problem)
{
addSlackVariables(problem);
selectConstraintsToWatch(problem);
addSlackVariablesToConstraints(problem);
if (slackVariables_.empty())
{
logs.error() << title() << " : no constraints have been selected";
Expand All @@ -53,9 +64,21 @@ void ConstraintSlackAnalysis::run(MPSolver* problem)
}

hasDetectedInfeasibilityCause_ = true;

sortSlackVariablesByValue();
trimSlackVariables();
}

void ConstraintSlackAnalysis::selectConstraintsToWatch(MPSolver* problem)
{
ConstraintsFactory factory;
std::regex rgx = factory.constraintsFilter();
std::ranges::copy_if(problem->constraints(),
std::back_inserter(constraintsToWatch_),
[&rgx](auto* c) { return std::regex_search(c->name(), rgx); });
}

void ConstraintSlackAnalysis::addSlackVariables(MPSolver* problem)
void ConstraintSlackAnalysis::addSlackVariablesToConstraints(MPSolver* problem)
{
/* Optimization:
We assess that less than 1 every 3 constraint will match
Expand All @@ -64,29 +87,21 @@ 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)
{
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() + "::low");
c->SetCoefficient(slack, 1.);
slackVariables_.push_back(slack);
}

if (c->ub() < infinity)
{
const MPVariable* slack = problem->MakeNumVar(0, infinity, c->name() + "::up");
c->SetCoefficient(slack, -1.);
slackVariables_.push_back(slack);
}
}
}
Expand All @@ -104,10 +119,22 @@ 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_);
report.prettyPrint();
report.logSuspiciousConstraints();
report.logInfeasibilityCauses();
}

} // namespace Antares::Optimization
160 changes: 0 additions & 160 deletions src/solver/infeasible-problem-analysis/constraint.cpp

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
#include <vector>

#include "unfeasibility-analysis.h"
#include "watched-constraints.h"

namespace operations_research
{
class MPConstraint;
class MPVariable;
class MPSolver;
} // namespace operations_research
Expand All @@ -40,7 +42,6 @@ namespace Antares::Optimization
class ConstraintSlackAnalysis: public UnfeasibilityAnalysis
{
public:
ConstraintSlackAnalysis() = default;
~ConstraintSlackAnalysis() override = default;

void run(operations_research::MPSolver* problem) override;
Expand All @@ -52,13 +53,14 @@ 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<operations_research::MPConstraint*> constraintsToWatch_;
std::vector<const operations_research::MPVariable*> slackVariables_;
const std::string constraint_name_pattern = "^AreaHydroLevel::|::hourly::|::daily::|::weekly::|"
"^FictiveLoads::|^Level::|"
"^HydroPower::";
};

} // namespace Antares::Optimization

This file was deleted.

Loading

0 comments on commit 89ac6c8

Please sign in to comment.