The AC Optimal Power Flow problem (AC-OPF) is one of the most foundational optimization problems that arises in the design and operations of power networks.
Mathematically the AC-OPF is a large-scale, sparse, non-convex nonlinear continuous optimization problem.
The models make heavy use of scalar indexing in the definition of the nonlinear functions, and most operations are simple floating point operations (+
, *
, cos
, and sin
) applied to scalar data.
In practice AC-OPF is most often solved to local optimality conditions using interior point methods.
This project proposes AC-OPF as proxy-application for testing the viability of different nonlinear optimization frameworks, as performant solutions to AC-OPF has proven to be a necessary (but not always sufficient) condition for solving a wide range of industrial network optimization tasks.
x^2*y^3
, sin(x)*cos(y)
)At present this project is focused on comparing NLP modeling layers that are available in the Julia programming langue. However, other modeling layers may be considered in the future.
This work is not intended for comparing different nonlinear optimization algorithms, which are often independent of the NLP modeling layer. Consequently, the Ipopt solver is used as a standard NLP algorithm whenever it is accessible from the modeling layer.
All framework implementations use PowerModels.jl to read input .m
data files into non-concrete dictionaries, from which the objective and constraint functions are defined.
Reading the data into non-concrete dictionaries simulates a very common non-expert user of NLP tooling, but biases the performance results in favor of symbolic front-ends which perform additional optimizations on the objective and constraint functions before performing the optimization.
Moreover, the total time
reported by rosetta-opf
includes Julia's compilation time.
This biases performance against frameworks which generate large amounts of new code that requires compilation.
We do not attempt to remove the compilation overhead, for example, by using a tool like PackageCompiler.jl.
For a variation of rosetta-opf
that removes these factors to focus on core implementation differences of the numerical backends, see the SciMLBenchmarks adaptation.
This work adopts the mathematical model and data format that is used in the IEEE PES benchmark library for AC-OPF, PGLib-OPF. The Julia package PowerModels is used for parsing the problem data files and making standard data transformations.
In this formulation the equations encode the following properties: (1) minimization of generator fuel costs; (2) a voltage phase reference angle; (3) power balance (i.e. energy conservation); (4,5) Ohm's Law for the flow power; (6) power flow limits; and (7) angle difference limits.
AC-OPF is naturally modeled as continuous nonlinear optimization problem over complex data and variables. However, the implementations in this repository use the projection into real numbers to support the broadest possible set of optimization modeling frameworks.
In this formulation the complex voltage terms expand into the following expressions, |Vᵢ|^2 = (vᵢ)^2
, ∠Vᵢ = θᵢ
, Vᵢ * conj(Vⱼ) = vᵢ*vⱼ*cos(θᵢ-θⱼ) + im*vᵢ*vⱼ*sin(θᵢ-θⱼ)
, which is the source of the transcendental functions in the implementations.
Each of these files is designed to be stand-alone and can be tested with minimal package dependencies. Consequently, there is some code replication between implementations.
examodels.jl
: implementation using ExaModelsjump.jl
: implementation using JuMPnlpmodels.jl
: implementation using ADNLPModelsnonconvex.jl
: implementation using Nonconvexoptim.jl
: implementation using Optimoptimization.jl
: implementation using Optimizationdata/*
: small example datasetstest/*
: basic tests for the primary AC-OPF implementationsdebug/*
: scripts for debugging NLP modeling layersvariants/*
: additional variants of the AC-OPF problemBy convention each AC-OPF stand-alone file implements a function called solve_opf
that requires one argument, file_name
. The argument should be a path to an AC-OPF case file that is compatible with PowerModels' parse_file
function (usually a MATPOWER case file). The solve_opf
function parses the case file, builds the suitable AC-OPF optimization problem, solves it with Ipopt (or the next-best available algorithm) and returns a dictionary of basic information about the solution process. This dictionary includes items such as,
case
: the name of the file that was solvedfeasible
: if the modeling layer determined the solution at the competition of the solve process satisfies the model constraints cost
: evaluation of the objective function at the competition of the solve processtime_total
: the total wall-clock time of the solve_opf
function in secondsThe standard steps for testing the solve_opf
function on a specific AC-OPF data file are,
julia --project=. # Start Julia with the project environment provided with this repo
julia> include("jump.jl") # Load the solve_opf function from one of the example files
julia> solve_opf("data/pglib_opf_case5_pjm.m") # Run the solve_opf function on a specific AC-OPF case file
Note that due to Julia's JIT, it is very likely that the first call to solve_opf
will take significantly more time than the second call. The case file data/opf_warmup.m
can be used to remove the bulk of overheads related to Julia's JIT when collecting precise runtime data on one of the solve_opf
functions.
This code is provided under a BSD license as part of the Grid Optimization Competition Solvers project, C19076.