SOCP
Solver: Clarabel
SOCWR is the second-order cone relaxation of AC OPF introduced by Jabr in 2006 — the most influential convex relaxation in the history of power-system optimization. By lifting the AC equations into a higher-dimensional space of squared voltage magnitudes and bilinear products, SOCWR replaces the non-convex coupling between magnitudes and phase angles with a rotated second-order cone — a convex constraint that any modern SOCP solver handles in polynomial time.
Use SOCWR when global optimality matters: it returns a provable lower bound on the AC optimal cost. On radial (tree) networks, the relaxation is exact under mild conditions (Lavaei–Low 2012, Bose et al. 2015), meaning SOCWR’s optimum is also the AC optimum. On meshed transmission networks the gap is typically below 1%, making SOCWR an excellent warm-start and a strong certificate of near-global optimality.
SOCWR introduces three sets of new variables per bus pair (i,k), called W-variables, that absorb the bilinear voltage products of AC:
The diagonal wii captures squared voltage magnitudes; the off-diagonals wikr and wiki package the magnitude-angle coupling that makes AC non-convex. Each W-variable is real-valued, removing all phasor algebra from the problem.
Substituting the W-variables into the AC power-flow equations gives expressions that are linear in W:
Power balance, voltage limits wii ∈ [V̲i², V̅i²], and branch flow constraints all become linear or convex quadratic in W. The non-convexity of AC has been quarantined into a single relationship — the coupling that defines W from the original V.
The W-variables satisfy a non-convex relationship. Using the trigonometric identity cos²θ + sin²θ = 1, we have (wikr)² + (wiki)² = (|Vi||Vk|)² = wii · wkk. This is a non-convex quadratic equality. SOCWR replaces equality with inequality:
This is a rotated second-order cone constraint — convex, smooth, and handled efficiently by interior-point SOCP solvers. The relaxation is tight (equality holds at the optimum) on radial networks; on meshed networks, the gap measures how much “magnitude-angle coupling” the relaxation loses.
The complete formulation reads:
Variable count grows compared to AC — one W-variable per bus, two per branch — but every constraint is linear or a rotated second-order cone. The problem is convex, with strong duality and provable global optimality of the solver’s output.
SOCWR solves an order of magnitude faster than AC on networks up to a few thousand buses, with the additional benefit of returning a certified lower bound on the AC optimal cost. Lirion defaults to Clarabel, an interior-point SOCP solver that handles the rotated cones natively; alternatives include Mosek, ECOS, and the SCS first-order solver for very large instances.
The exactness of the relaxation depends on network topology and operating conditions. On radial distribution networks, sufficient conditions (Lavaei–Low, Bose et al.) guarantee zero gap. On meshed transmission networks, the gap is typically 0.1–1%, and the W-space solution can be projected back to AC voltages V via post-processing — recovering phase angles consistently when the gap is small. When SOCWR is exact, its dual variables give locational marginal prices that are valid for the AC problem.
Solving SOCWR on a MATPOWER case file requires a single call to solve:
using Lirion
# Solve SOCWR — convex relaxation with global lower bound
out = solve("case118.m"; model = socwr(), algorithm = centralized())
# W-space solution
W_diag = out.solution["bus"]["w"] # squared voltage magnitudes
Wr = out.solution["branch"]["wr"] # real off-diagonal
Wi = out.solution["branch"]["wi"] # imaginary off-diagonal
# Reconstruct voltage magnitudes (always recoverable)
V_mag = sqrt.(W_diag)
# Check relaxation gap vs. AC
out_ac = solve("case118.m"; model = ac(), algorithm = centralized())
gap = (out_ac.objective - out.objective) / out_ac.objective * 100
println("SOCWR lower bound: \$", round(out.objective, digits=2))
println("AC optimal cost: \$", round(out_ac.objective, digits=2))
println("Relaxation gap: ", round(gap, digits=3), " %") The out object follows the PowerModels.jl result schema. Branch flows are available under out.solution["branch"]["pf"].