Skip to contents

Solves an interpolated scenario once per solver option set and returns runtime and objective for each, so back ends can be compared on the same linear programme.

Usage

benchmark_solvers(scen, solvers = NULL, tol = 1e-06, verbose = TRUE)

Arguments

scen

an interpolated scenario, from energyRt::interpolate_model().

solvers

character vector of names in energyRt::solver_options, or a named list of option sets. Defaults to the open solvers reported available by open_solvers().

tol

relative objective difference treated as agreement.

verbose

report each run as it completes.

Value

A data frame with solver, seconds, objective, status and agrees, ordered by runtime. The reference for agrees is the first successful run.

Details

Every run receives the same scenario, so the objectives are expected to agree to solver tolerance. A disagreement larger than tol is reported in the agrees column and is a signal to investigate the back end, not the model.

Solving is sequential. A back end that fails records the error and does not stop the remaining runs.

Solver choice by model size

Relative performance depends strongly on model size, and the ordering reverses across the range. Measured on one workstation; treat the ratios rather than the absolute times as transferable.

modelGLPKCBCHiGHS
5 regions, 168 h10 s19 s24-47 s
69 regions, 96 slices2158 s809 s79-82 s
1035 regions, 96 slices18.5 min

On the smallest models GLPK wins on start-up cost alone. From roughly a hundred thousand rows onward HiGHS dominates: at 69 regions it is 27 times faster than GLPK, and the gap widens with size.

At 1035 regions on a 96-slice sample the linear programme is 1.3 million rows after presolve, solved by HiGHS interior point in about 16 minutes. Extending the same model to 672 slices produces 9.4 million rows after presolve, at which point the interior-point method fails to return a solution; a first-order method (solver = "pdlp") or dual simplex is the route to test at that size.

Julia carries a fixed start-up cost of 20-30 seconds per invocation for just-in-time compilation, which dominates small models and is amortised across a session. Pyomo starts in a few seconds. For a single small solve Pyomo is therefore quicker end to end even where Julia's solver call is faster.

See also

Examples

if (FALSE) { # \dontrun{
scen <- energyRt::interpolate_model(pypsa_eur_5, name = "be")
benchmark_solvers(scen)
} # }