LP
Solver: OSQP
The Network-Flow Approximation is the simplest possible model in Lirion — the zero-physics baseline against which every other formulation should be compared. NFA strips OPF down to a capacity-constrained transshipment LP: each branch is a pipe with maximum throughput, each bus is a node where flow balance holds, and the only objective is routing generation to demand at minimum cost.
Use NFA as a sanity check (does the network have enough capacity at all?), for transmission expansion planning over thousands of scenarios where AC accuracy is prohibitive, or for teaching: it isolates the combinatorial structure of dispatch from electrical physics. The gap between NFA and DC cost quantifies how much “physics” the linearized AC adds beyond pure routing.
NFA discards everything in the AC power-flow equations except topology and capacity. There are no voltage magnitudes, no phase angles, no susceptances, no Kirchhoff voltage law — only Kirchhoff’s current law applied as bookkeeping. Each branch (i,j) carries a directed flow f_{ij}, and the model imposes flow balance at every bus:
The crucial property NFA loses compared to DC is the angle-flow coupling f_{ij} = (θ_i − θ_j)/x_{ij} — without it, flow is no longer determined by the network’s electrical structure. Two parallel branches with different reactances can carry arbitrary flow splits in NFA; in DC, the split is fixed by impedance ratios.
The complete formulation reads:
Three constraint families: flow balance at each bus, generator capability box, and branch capacity. No angle variable, no electrical relation between flows and voltages. The constraint matrix is the network’s signed incidence matrix — sparse, totally unimodular, the same problem class as min-cost flow on a transportation graph.
NFA solves orders of magnitude faster than any other model in Lirion, with solve times often dominated by file I/O rather than the optimization itself. Any modern LP solver handles the totally unimodular constraint matrix trivially.
The model’s value is comparative: by stripping electrical physics, NFA isolates “is the network topology sufficient?” from “are the impedances cooperating?” When NFA is feasible but DC is not, the bottleneck is electrical, not capacity-based. When NFA itself is infeasible, no amount of voltage control can fix the dispatch — the network needs new branches.
Solving the NFA on a MATPOWER case file requires a single call to solve:
using Lirion
# Solve the network-flow baseline
out = solve("case30.m"; model = nfa(), algorithm = centralized())
# Net dispatch and flows
Pg = out.solution["gen"]["pg"]
flows = out.solution["branch"]["pf"]
# Compare to DC cost gap
out_dc = solve("case30.m"; model = dc(), algorithm = centralized())
println("NFA cost: \$", round(out.objective, digits=2))
println("DC cost: \$", round(out_dc.objective, digits=2))
println("Gap: \$", round(out_dc.objective - out.objective, digits=2)) The out object follows the PowerModels.jl result schema. Branch flows are available under out.solution["branch"]["pf"].