Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unfeasible problem analyzer : add a new check #1689

Merged
merged 40 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
b885cea
New log msg when solver not found in or-tools
guilpier-code Oct 6, 2023
f9e1645
New log msg when solver not found in or-tools : oops, correct an obli…
guilpier-code Oct 6, 2023
093477b
Add a check to unfeasible analyzer : just a renaming
guilpier-code Oct 6, 2023
44f0698
Add a check to unfeasible analyzer : remove exceptions + add a new ru…
guilpier-code Oct 6, 2023
4d1d1e8
Add a check to unfeasible analyzer : renaming slack variables
guilpier-code Oct 9, 2023
4b59b50
Add a check to unfeasible analyzer : merely change a unique pointer i…
guilpier-code Oct 9, 2023
f76e266
Add a check to unfeasible analyzer : add some analysis classes defini…
guilpier-code Oct 9, 2023
4a54f05
Add a check to unfeasible analyzer : clarify class InfeasibleProblemR…
guilpier-code Oct 9, 2023
83cc237
Add a check to unfeasible analyzer : clarify class InfeasibleProblemR…
guilpier-code Oct 9, 2023
6ad43bd
Add a check to unfeasible analyzer : adding a using namespace in repo…
guilpier-code Oct 9, 2023
e0675e2
Add a check to unfeasible analyzer : simplify analyzer interface + mo…
guilpier-code Oct 10, 2023
2e1982e
Add a check to unfeasible analyzer : remove a useless data member fro…
guilpier-code Oct 10, 2023
ddee96f
Add a check to unfeasible analyzer : adding an incomplete variables b…
guilpier-code Oct 10, 2023
73994aa
Add a check to unfeasible analyzer : class VariablesBoundsAnalysis - …
guilpier-code Oct 10, 2023
22dcde8
Add a check to unfeasible analyzer : add a title for every analysis, …
guilpier-code Oct 10, 2023
3659da0
Add a check to unfeasible analyzer : class VariablesBoundsAnalysis - …
guilpier-code Oct 10, 2023
465173f
[skip ci] Add a check to unfeasible analyzer : add comments in the co…
guilpier-code Oct 10, 2023
d73d33a
Add a check to unfeasible analyzer : improve logs + correct a shared …
guilpier-code Oct 10, 2023
0084fce
Add a check to unfeasible analyzer : correct a compilation error on U…
guilpier-code Oct 10, 2023
218b9cf
Add a check to unfeasible analyzer : correcting the analyzer after tests
guilpier-code Oct 10, 2023
f40a6dc
Add a check to unfeasible analyzer : make code a bit more clear
guilpier-code Oct 10, 2023
679b5de
[skip ci] Add a check to unfeasible analyzer : piece of cleaning
guilpier-code Oct 18, 2023
879b664
[skip ci] Add a check to unfeasible analyzer : renaming classes aroun…
guilpier-code Oct 18, 2023
c3f3fca
[skip ci] Add a check to unfeasible analyzer : still renaming
guilpier-code Oct 18, 2023
d85a03f
[skip ci] Add a check to unfeasible analyzer : renaming files + move …
guilpier-code Oct 18, 2023
81fe8cf
Add a check to unfeasible analyzer : move constraint slack analysis t…
guilpier-code Oct 18, 2023
273a6c6
Add a check to unfeasible analyzer : renaming file and classes
guilpier-code Oct 18, 2023
4b455fc
Add a check to unfeasible analyzer : renaming classes and source files
guilpier-code Oct 18, 2023
2691f18
Add a check to unfeasible analyzer : renaming class and related sourc…
guilpier-code Oct 18, 2023
7dc22fb
Add a check to unfeasible analyzer : correct compilation and CI errors
guilpier-code Oct 19, 2023
4bffb5f
Add a check to unfeasible analyzer : mainly extract class VariablesBo…
guilpier-code Oct 19, 2023
4564bc0
Add a check to unfeasible analyzer : removing PROBLEME_SIMPLEXE_NOMME…
guilpier-code Oct 20, 2023
7ee755a
Add a check to unfeasible analyzer : turning a shared_ptr into a raw …
guilpier-code Oct 20, 2023
7a1d0d5
Add a check to unfeasible analyzer : make problem an argument of the …
guilpier-code Oct 23, 2023
0499708
Add a check to unfeasible analyzer : make problem an argument of the …
guilpier-code Oct 23, 2023
1439a4d
Add a check to unfeasible analyzer : add a factory function to the un…
guilpier-code Oct 24, 2023
40cba9a
Add a check to unfeasible analyzer : in the analysis list, replace sh…
guilpier-code Oct 24, 2023
12c425c
Add a check to unfeasible analyzer : class VariableBounds > change a …
guilpier-code Oct 25, 2023
7590b48
Add a check to unfeasible analyzer : adding const identifiers to func…
guilpier-code Oct 25, 2023
a9c4ad7
Unit tests for unfeasible problem analyzer (#1716)
sylvlecl Nov 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/solver/infeasible-problem-analysis/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ set(SRC_INFEASIBLE_PROBLEM_ANALYSIS
report.cpp
constraint.h
constraint.cpp
exceptions.h
exceptions.cpp
)

add_library(infeasible_problem_analysis ${SRC_INFEASIBLE_PROBLEM_ANALYSIS})
Expand Down
18 changes: 0 additions & 18 deletions src/solver/infeasible-problem-analysis/exceptions.cpp

This file was deleted.

21 changes: 0 additions & 21 deletions src/solver/infeasible-problem-analysis/exceptions.h

This file was deleted.

36 changes: 22 additions & 14 deletions src/solver/infeasible-problem-analysis/problem.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "problem.h"
#include "exceptions.h"
#include <antares/logs/logs.h>

#include <fstream>
#include <regex>
Expand All @@ -13,8 +13,7 @@ namespace Optimization
{
InfeasibleProblemAnalysis::InfeasibleProblemAnalysis(const std::string& solverName, const PROBLEME_SIMPLEXE_NOMME* ProbSpx)
{
mSolver
= std::unique_ptr<MPSolver>(ProblemSimplexeNommeConverter(solverName, ProbSpx).Convert());
problem_ = std::unique_ptr<MPSolver>(ProblemSimplexeNommeConverter(solverName, ProbSpx).Convert());
}

void InfeasibleProblemAnalysis::addSlackVariables()
Expand All @@ -25,25 +24,25 @@ void InfeasibleProblemAnalysis::addSlackVariables()
This should not happen in most cases.
*/
const unsigned int selectedConstraintsInverseRatio = 3;
mSlackVariables.reserve(mSolver->NumConstraints() / selectedConstraintsInverseRatio);
mSlackVariables.reserve(problem_->NumConstraints() / selectedConstraintsInverseRatio);
std::regex rgx(constraint_name_pattern);
const double infinity = MPSolver::infinity();
for (MPConstraint* constraint : mSolver->constraints())
for (MPConstraint* constraint : problem_->constraints())
{
if (std::regex_search(constraint->name(), rgx))
{
if (constraint->lb() != -infinity)
{
const MPVariable* slack
= mSolver->MakeNumVar(0, infinity, constraint->name() + "::low");
= problem_->MakeNumVar(0, infinity, constraint->name() + "::low");
constraint->SetCoefficient(slack, 1.);
mSlackVariables.push_back(slack);
}

if (constraint->ub() != infinity)
{
const MPVariable* slack
= mSolver->MakeNumVar(0, infinity, constraint->name() + "::up");
= problem_->MakeNumVar(0, infinity, constraint->name() + "::up");
constraint->SetCoefficient(slack, -1.);
mSlackVariables.push_back(slack);
}
Expand All @@ -53,7 +52,7 @@ void InfeasibleProblemAnalysis::addSlackVariables()

void InfeasibleProblemAnalysis::buildObjective() const
{
MPObjective* objective = mSolver->MutableObjective();
MPObjective* objective = problem_->MutableObjective();
// Reset objective function
objective->Clear();
// Only slack variables have a non-zero cost
Expand All @@ -66,24 +65,33 @@ void InfeasibleProblemAnalysis::buildObjective() const

MPSolver::ResultStatus InfeasibleProblemAnalysis::Solve() const
{
return mSolver->Solve();
return problem_->Solve();
}

InfeasibleProblemReport InfeasibleProblemAnalysis::produceReport()
bool InfeasibleProblemAnalysis::run()
{
logs.notice() << " Solver: Starting infeasibility analysis...";
addSlackVariables();
if (mSlackVariables.empty())
{
throw SlackVariablesEmpty(
"Cannot generate infeasibility report: no constraints have been selected");
logs.error() << "Cannot generate infeasibility report: no constraints have been selected";
return false;
}

buildObjective();

const MPSolver::ResultStatus status = Solve();
if ((status != MPSolver::OPTIMAL) && (status != MPSolver::FEASIBLE))
{
throw ProblemResolutionFailed(
"Linear problem could not be solved, and infeasibility analysis could not help");
logs.error() << "Linear problem could not be solved, and infeasibility analysis could not help";
return false;
}

return true;
}

InfeasibleProblemReport InfeasibleProblemAnalysis::produceReport()
{
return InfeasibleProblemReport(mSlackVariables);
}
} // namespace Optimization
Expand Down
6 changes: 3 additions & 3 deletions src/solver/infeasible-problem-analysis/problem.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ class InfeasibleProblemAnalysis
public:
InfeasibleProblemAnalysis() = delete;
explicit InfeasibleProblemAnalysis(const std::string& solverName, const PROBLEME_SIMPLEXE_NOMME* ProbSpx);
bool run();
InfeasibleProblemReport produceReport();

private:
void buildObjective() const;
void addSlackVariables();
operations_research::MPSolver::ResultStatus Solve() const;

std::unique_ptr<operations_research::MPSolver> mSolver;
std::unique_ptr<operations_research::MPSolver> problem_;
std::vector<const operations_research::MPVariable*> mSlackVariables;
const std::string constraint_name_pattern = "^AreaHydroLevel::|::hourly::|::daily::|::weekly::|^FictiveLoads::";

const std::string constraint_name_pattern = "^AreaHydroLevel::|::hourly::|::daily::|::weekly::|^FictiveLoads::";
};
} // namespace Optimization
} // namespace Antares
12 changes: 1 addition & 11 deletions src/solver/optimisation/opt_appel_solveur_lineaire.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ extern "C"
#include "../utils/filename.h"

#include "../infeasible-problem-analysis/problem.h"
#include "../infeasible-problem-analysis/exceptions.h"

#include <chrono>

Expand Down Expand Up @@ -376,20 +375,11 @@ bool OPT_AppelDuSimplexe(const OptimizationOptions& options,

Probleme.SetUseNamedProblems(true);
Optimization::InfeasibleProblemAnalysis analysis(options.solverName, &Probleme);
logs.notice() << " Solver: Starting infeasibility analysis...";
try
if (analysis.run())
{
Optimization::InfeasibleProblemReport report = analysis.produceReport();
report.prettyPrint();
}
catch (const Optimization::SlackVariablesEmpty& ex)
{
logs.error() << ex.what();
}
catch (const Optimization::ProblemResolutionFailed& ex)
{
logs.error() << ex.what();
}

auto mps_writer_on_error = simplexResult.mps_writer_factory.createOnOptimizationError();
const std::string filename = createMPSfilename(optPeriodStringGenerator, optimizationNumber);
Expand Down
15 changes: 10 additions & 5 deletions src/solver/utils/ortools_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ namespace Antares
namespace Optimization
{
ProblemSimplexeNommeConverter::ProblemSimplexeNommeConverter(
const std::string& solverName,
const Antares::Optimization::PROBLEME_SIMPLEXE_NOMME* problemeSimplexe) :
solverName_(solverName), problemeSimplexe_(problemeSimplexe)
const std::string& solverName,
const Antares::Optimization::PROBLEME_SIMPLEXE_NOMME* problemeSimplexe)
: solverName_(solverName), problemeSimplexe_(problemeSimplexe)
{
if (problemeSimplexe_->UseNamedProblems())
{
Expand Down Expand Up @@ -364,11 +364,16 @@ MPSolver* MPSolverFactory(const Antares::Optimization::PROBLEME_SIMPLEXE_NOMME*
solver = MPSolver::CreateSolver((OrtoolsUtils::solverMap.at(solverName)).LPSolverName);

if (!solver)
throw Antares::Data::AssertionError("Solver not found: " + solverName);
{
std::string msg_to_throw = "Solver " + solverName + " not found. \n";
msg_to_throw += "Please make sure that your OR-Tools install supports solver " + solverName + ".";

throw Antares::Data::AssertionError(msg_to_throw);
}
}
catch (...)
{
Antares::logs.error() << "Solver creation failed";
Antares::logs.error() << "Solver creation failed.";
throw;
}

Expand Down
3 changes: 1 addition & 2 deletions src/tests/run-study-tests/test_unfeasible_problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,4 @@ def test_unfeasible_problem_01__warning_dry(study_path, check_runner):
checks.add(check = unfeasible_problem(study_path, new_behavior="warning-dry",
checks_on_weeks=warnings_on_weeks,
simulation=check_runner.get_simulation()))
check_runner.run(checks)

check_runner.run(checks)