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

Support more quadratic solvers #2574

Open
wants to merge 18 commits into
base: develop
Choose a base branch
from
3 changes: 2 additions & 1 deletion docs/developer-guide/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ toc_depth: 2
* Short term storage costs [ANT-1854] (#2302)
* Add ts-generation for links [ANT-1084] (#1986)
* Make it possible to specify the final hydro reservoir level [ANT-1084] (#1521)
* Add support for more QP solvers [ANT-2546] (#2574)
Copy link
Contributor

@guilpier-code guilpier-code Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About QP : don't hesitate to be more explicit and indicate quadratic problem as in the PR's title


#### Removed features
* Remove hydro hotstart (#2131)
Expand Down Expand Up @@ -69,7 +70,7 @@ toc_depth: 2
#### Build
* vcpkg (linux, sirius) (#2078) (#2090) (#2145)
* Remove src/antares-deps (#2182)
* Use OR-Tools v9.11-rte1.1 (#2437)
* Use OR-Tools v9.11-rte1.2 (#2574)
* Fix or-tools integration (#2402)
* Better dependencies with cmake, antares matrix (#2369)

Expand Down
6 changes: 4 additions & 2 deletions docs/user-guide/solver/02-command-line.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ hide:
| --adequacy | Force the simulation in [adequacy](static-modeler/04-parameters.md#mode) mode |
| --parallel | Enable [parallel](optional-features/multi-threading.md) computation of MC years |
| --force-parallel=VALUE | Override the max number of years computed [simultaneously](optional-features/multi-threading.md) |
| --solver=VALUE | The optimization solver to use. Possible values are: `sirius` (default), `coin`, `xpress`, `scip` |
| --linear-solver=VALUE | The optimization solver to use for linear problems. Possible values are: `sirius` (default), `coin`, `xpress`, `scip` |
| --quadratic-solver=VALUE | The optimization solver to use for quadratic problems. Possible values are: `sirius` (default), `pdlp` |

## Parameters

Expand All @@ -43,7 +44,8 @@ hide:
| -m, --mps-export | Export anonymous MPS, weekly or daily optimal UC+dispatch linear (MPS will be named if the problem is infeasible) |
| -s, --named-mps-problems | Export named MPS, weekly or daily optimal UC+dispatch linear |
| --solver-logs | Print solver logs |
| --solver-parameters | Set solver-specific parameters, for instance `--solver-parameters="THREADS 1 PRESOLVE 1"` for XPRESS or `--solver-parameters="parallel/maxnthreads 1, lp/presolving TRUE"` for SCIP. Syntax is solver-dependent, and only supported for SCIP & XPRESS. |
| --linear-solver-parameters | Set solver-specific parameters for linear problems, for instance `--solver-parameters="THREADS 1 PRESOLVE 1"` for XPRESS or `--solver-parameters="parallel/maxnthreads 1, lp/presolving TRUE"` for SCIP. Syntax is solver-dependent, and only supported for SCIP & XPRESS. |
| --quadratic-solver-parameters | Set solver-specific parameters for quadratic problems. |

## Misc.

Expand Down
20 changes: 13 additions & 7 deletions docs/user-guide/solver/static-modeler/04-parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -483,14 +483,20 @@ _**This section is under construction**_
> _**Note:**_ You can find more information on this parameter [here](../03-appendix.md#details-on-the-include-unfeasible-problem-behavior-parameter).

---
#### solver-parameters
[//]: # (TODO: document this parameter)
_**This section is under construction**_
#### linear-solver-parameters
- **Expected value:** a string
- **Required:** **no**
- **Default value:** empty
- **Usage:** Set solver-specific parameters for linear problems, for instance `--solver-parameters="THREADS 1 PRESOLVE 1"`
for XPRESS or `--solver-parameters="parallel/maxnthreads 1, lp/presolving TRUE"` for SCIP. Syntax is solver-dependent, and only supported for SCIP & XPRESS.

- **Expected value:**
- **Required:** **yes**
- **Default value:**
- **Usage:**
---
#### quadratic-solver-parameters
- **Expected value:** a string
- **Required:** **no**
- **Default value:** empty
- **Usage:** Set solver-specific parameters for quadratic problems, for instance `--solver-parameters="THREADS 1 PRESOLVE 1"`
for XPRESS or `--solver-parameters="parallel/maxnthreads 1, lp/presolving TRUE"` for SCIP. Syntax is solver-dependent, and only supported for SCIP & XPRESS.

---
## Adequacy-patch parameters
Expand Down
2 changes: 1 addition & 1 deletion ortools_tag
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v9.11-rte1.1
v9.11-rte1.2
7 changes: 5 additions & 2 deletions src/libs/antares/InfoCollection/StudyInfoCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,11 @@ void StudyInfoCollector::solverVersionToFileContent(FileContent& file_content)

void StudyInfoCollector::ORToolsSolver(FileContent& file_content)
{
std::string solverName = study_.parameters.optOptions.ortoolsSolver;
file_content.addItemToSection("study", "ortools solver", solverName);
std::string linearSolverName = study_.parameters.optOptions.linearSolver;
file_content.addItemToSection("study", "linear solver", linearSolverName);

std::string quadraticSolverName = study_.parameters.optOptions.linearSolver;
Copy link
Contributor

@guilpier-code guilpier-code Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About line :

std::string quadraticSolverName = study_.parameters.optOptions.linearSolver;

By any chance, would you mean (instead) :

std::string quadraticSolverName = study_.parameters.optOptions.quadraticSolver;

?

file_content.addItemToSection("study", "quadratic solver", quadraticSolverName);
}

// Collecting data optimization problem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ namespace Antares::Solver::Optimization
struct OptimizationOptions
{
//! The solver name, sirius is the default
std::string ortoolsSolver = "sirius";
std::string linearSolver = "sirius";
std::string quadraticSolver = "sirius";
std::string linearSolverParameters;
std::string quadraticSolverParameters;
bool solverLogs = false;
std::string solverParameters;
};
} // namespace Antares::Solver::Optimization
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class StudyLoadOptions
//! A non-zero value if the data will be used for a simulation
bool usedByTheSolver;

//! All options related to optimization
//! All options related to linear & quadratic optimization
Antares::Solver::Optimization::OptimizationOptions optOptions;

//! Temporary string for passing log message
Expand Down
2 changes: 1 addition & 1 deletion src/libs/antares/study/include/antares/study/parameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ class Parameters final
// Naming constraints and variables in problems
bool namedProblems;

// All options related to optimization
// All options related to linear & quadratic optimization
Antares::Solver::Optimization::OptimizationOptions optOptions;

private:
Expand Down
13 changes: 9 additions & 4 deletions src/libs/antares/study/parameters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1283,8 +1283,10 @@ bool Parameters::loadFromINI(const IniFile& ini, const StudyVersion& version)
void Parameters::handleOptimizationOptions(const StudyLoadOptions& options)
{
// Options only set from the command-line
optOptions.ortoolsSolver = options.optOptions.ortoolsSolver;
optOptions.solverParameters = options.optOptions.solverParameters;
optOptions.linearSolver = options.optOptions.linearSolver;
optOptions.linearSolverParameters = options.optOptions.linearSolverParameters;
optOptions.quadraticSolver = options.optOptions.quadraticSolver;
optOptions.quadraticSolverParameters = options.optOptions.quadraticSolverParameters;

// Options that can be set both in command-line and file
optOptions.solverLogs = options.optOptions.solverLogs || optOptions.solverLogs;
Comment on lines +1286 to 1292
Copy link
Contributor

@guilpier-code guilpier-code Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of these 5 lines, it would be better to have :

optOptions = options.optOptions;

But because of the last line, it seems we can't do that.
But we may if we define an overloading operator in struct OptimizationOptions, with a special treatment for attribute solverLogs.
This operator could be "=" or "<<"

Expand Down Expand Up @@ -1780,8 +1782,11 @@ void Parameters::prepareForSimulation(const StudyLoadOptions& options)
logs.info() << " :: ignoring solution export";
}

logs.info() << " :: solver " << options.optOptions.ortoolsSolver
<< " is used for problem resolution";
logs.info() << " :: solver " << options.optOptions.linearSolver
<< " is used for linear problem resolution";

logs.info() << " :: solver " << options.optOptions.quadraticSolver
<< " is used for quadratic problem resolution";

// indicated that Problems will be named
if (namedProblems)
Expand Down
7 changes: 5 additions & 2 deletions src/solver/application/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ namespace
{
void printSolvers()
Copy link
Contributor

@guilpier-code guilpier-code Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the scope of this PR ? (not sure)

printSolvers() :

  • Should be renamed into : logAllAvailableSolvers()
  • why do we print to std::cout and not in usual logs ? Does it even make sense ?

Moreover printSolvers is called from handleOptions which has a very non expressive and probably wrong name and, besides printing, does very strange things.

{
std::cout << "Available solvers: " << availableOrToolsSolversString() << std::endl;
std::cout << "Available linear solvers: " // NOSONAR
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// NOSONAR : what do we mean by that ?

<< availableOrToolsSolversString(SolverClass::LINEAR) << std::endl; // NOSONAR
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

availableOrToolsSolversString(...) ==> availableSolversList(...), shorter and clearer.

std::cout << "Available quadratic solvers: " // NOSONAR
<< availableOrToolsSolversString(SolverClass::QUADRATIC) << std::endl; // NOSONAR
}
} // namespace

Expand Down Expand Up @@ -275,7 +278,7 @@ void Application::postParametersChecks() const
{ // Some more checks require the existence of pParameters, hence of a study.
// Their execution is delayed up to this point.
checkSolverMILPincompatibility(pParameters->unitCommitment.ucMode,
pParameters->optOptions.ortoolsSolver);
pParameters->optOptions.linearSolver);

checkSimplexRangeHydroPricing(pParameters->simplexOptimizationRange,
pParameters->hydroPricing.hpMode);
Expand Down
2 changes: 1 addition & 1 deletion src/solver/misc/include/antares/solver/misc/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,5 @@ std::unique_ptr<Yuni::GetOpt::Parser> CreateParser(Settings& settings,

void checkAndCorrectSettingsAndOptions(Settings& settings, Data::StudyLoadOptions& options);

void checkOrtoolsSolver(const Antares::Solver::Optimization::OptimizationOptions& optOptions);
void checkSolvers(Data::StudyLoadOptions& options);
#endif /* __SOLVER_MISC_GETOPT_H__ */
66 changes: 52 additions & 14 deletions src/solver/misc/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include <limits>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many headers inclusion unnecessary here :

  • algorithm,
  • cassert,
  • limits,
  • antares/study/study.h (already included in options.h)
  • yuni/yuni.h (already included in options.h)
  • string (already included in options.h)
  • antares/logs/logs.h
  • and maybe more

#include <string.h>

#include <boost/algorithm/string/join.hpp>

#include <yuni/yuni.h>

#include <antares/antares/constants.h>
Expand Down Expand Up @@ -75,22 +77,53 @@ std::unique_ptr<Yuni::GetOpt::Parser> CreateParser(Settings& settings, StudyLoad
"force-parallel",
"Override the max number of years computed simultaneously");

//--linear-solver
parser->add(options.optOptions.linearSolver,
' ',
"linear-solver",
"Solver used for linear optimizations during simulation\nAvailable solver list : "
+ availableOrToolsSolversString(SolverClass::LINEAR));

//--solver
parser->add(options.optOptions.ortoolsSolver,
parser->add(options.optOptions.linearSolver,
' ',
"solver",
"Solver used for simulation\nAvailable solver list : "
+ availableOrToolsSolversString());
"Deprecated, use linear-solver instead.");

//--solver-parameters
//--linear-solver-parameters
parser->add(
options.optOptions.solverParameters,
options.optOptions.linearSolverParameters,
' ',
"solver-parameters",
"Set solver-specific parameters, for instance --solver-parameters=\"THREADS 1 PRESOLVE 1\""
"linear-solver-parameters",
"Set linear solver-specific parameters, for instance --linear-solver-parameters=\"THREADS 1 "
"PRESOLVE 1\""
"for XPRESS or --solver-parameters=\"parallel/maxnthreads 1, lp/presolving TRUE\" for SCIP."
"Syntax is solver-dependent, and only supported for SCIP & XPRESS.");

//--solver-parameters
parser->add(options.optOptions.linearSolverParameters,
' ',
"solver-parameters",
"Deprecated, use linear-solver-parameters instead.");

//--quadratic-solver
parser->add(
options.optOptions.quadraticSolver,
' ',
"quadratic-solver",
"Solver used for quadratic optimizations during simulation\nAvailable solver list : "
+ availableOrToolsSolversString(SolverClass::QUADRATIC));

//--quadratic-solver-parameters
parser->add(
options.optOptions.quadraticSolverParameters,
' ',
"quadratic-solver-parameters",
"Set quadratic solver-specific parameters, for instance "
"--quadratic-solver-parameters=\"THREADS 1 PRESOLVE 1\""
"for XPRESS or --solver-parameters=\"parallel/maxnthreads 1, lp/presolving TRUE\" for SCIP."
"Syntax is solver-dependent.");

parser->addParagraph("\nParameters");
// --name
parser->add(settings.simulationName,
Expand Down Expand Up @@ -246,7 +279,7 @@ void checkAndCorrectSettingsAndOptions(Settings& settings, Data::StudyLoadOption
}

options.checkForceSimulationMode();
checkOrtoolsSolver(options.optOptions);
checkSolvers(options);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should rename options.optOptions into options.solverOptions, and
call :

checkSolvers(options.solverOptions);

(indeed, options.optOptions is about solver options).
It would be more clear.


// no-output and force-zip-output
if (settings.noOutput && settings.forceZipOutput)
Expand All @@ -255,19 +288,24 @@ void checkAndCorrectSettingsAndOptions(Settings& settings, Data::StudyLoadOption
}
}

void checkOrtoolsSolver(const Antares::Solver::Optimization::OptimizationOptions& optOptions)
void checkSolverExists(std::string solverName, const std::list<std::string> availableSolversList)
{
const std::string& solverName = optOptions.ortoolsSolver;
const std::list<std::string> availableSolverList = getAvailableOrtoolsSolverName();

// Check if solver is available
bool found = (std::ranges::find(availableSolverList, solverName) != availableSolverList.end());
bool found = std::ranges::find(availableSolversList, solverName) != availableSolversList.end();
if (!found)
{
throw Error::InvalidSolver(optOptions.ortoolsSolver, availableOrToolsSolversString());
throw Error::InvalidSolver(solverName, boost::algorithm::join(availableSolversList, ","));
}
}

void checkSolvers(StudyLoadOptions& options)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checkSolvers(...) could be renamed into checkForSolversExistence(...)

{
checkSolverExists(options.optOptions.linearSolver,
getAvailableSolverNames(SolverClass::LINEAR));
checkSolverExists(options.optOptions.quadraticSolver,
getAvailableSolverNames(SolverClass::QUADRATIC));
}

void Settings::checkAndSetStudyFolder(const std::string& folder)
{
// The study folder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,18 +198,18 @@ void HourlyCSRProblem::setProblemCost()
}
}

void HourlyCSRProblem::solveProblem(uint week, int year)
void HourlyCSRProblem::solveProblem(uint week, int year, const OptimizationOptions& options)
{
Comment on lines +201 to 202
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const OptimizationOptions& options ==> const SolversOptions& solversOptions ?

ADQ_PATCH_CSR(problemeAResoudre_, *this, adqPatchParams_, week, year);
ADQ_PATCH_CSR(options, problemeAResoudre_, *this, adqPatchParams_, week, year);
Copy link
Contributor

@guilpier-code guilpier-code Jan 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not strictly related to the current PR
ADQ_PATCH_CSR seems useless : we should move this free function's body into HourlyCSRProblem::solveProblem(...), and have one fewer level in the call stack.

}

void HourlyCSRProblem::run(uint week, uint year)
void HourlyCSRProblem::run(uint week, uint year, const OptimizationOptions& options)
{
calculateCsrParameters();
buildProblemVariables();
buildProblemConstraintsLHS();
setVariableBounds();
buildProblemConstraintsRHS();
setProblemCost();
solveProblem(week, year);
solveProblem(week, year, options);
}
Loading
Loading