PDHG: primal-dual hybrid gradient

PDHG solves a linear program using nothing but matrix–vector products and projections — no factorizations, no linear systems. That simplicity is why it powers modern GPU-scale solvers like Google's PDLP. In lpviz you can watch its signature behavior up close: iterates that spiral into the optimum.

A trajectory spiraling in decreasing loops toward the optimal vertex of a polygon.
Primal-dual dynamics behave like a damped oscillator around the saddle point: the primal shadow of the iterates spirals inward.

The idea

Instead of attacking maximize cᵀx s.t. Ax ≤ b directly, PDHG works on its saddle-point (Lagrangian) formulation with a dual price yi ≥ 0 per constraint. The primal player nudges x uphill on the objective minus what the current prices charge for constraint violation; the dual player raises the price of any constraint that is violated. In lpviz's default inequality mode, one iteration is:

yk+1 = [yk + τ(Axk − b)]₊
ȳ = 2yk+1 − yk  (extrapolation)
xk+1 = xk + η(c − Aᵀȳ)

where [·]₊ clips negatives to zero (prices can't go negative). The extrapolation step — using the reflected dual 2yk+1 − yk rather than yk+1 itself — is what makes the scheme convergent (this is the Chambolle–Pock method, 2011). Each iteration costs exactly one multiply by A and one by Aᵀ, which is why PDHG scales to LPs with billions of nonzeros where factorization-based methods (Simplex, IPM) run out of memory.

Unchecking Inequality mode switches to the textbook standard-form variant: the problem is rewritten with split variables and slacks (x = x⁺ − x⁻, Ax + s = b, all variables ≥ 0), the projection moves to the primal update, and the extrapolation moves to the primal side. The LP is the same, but the splitting geometry — and therefore the trajectory you see — is different.

Two block diagrams. In inequality mode the primal variable is free and the dual is projected and extrapolated; in standard form the split primal variables and slacks are projected and extrapolated while the dual is free. Inequality mode (on) x ∈ ℝⁿ — free y ≥ 0 — projected and extrapolated Standard form (off) x⁺, x⁻, s ≥ 0 — projected and extrapolated y ∈ ℝᵐ — free the projection, and the extrapolation, swap sides
The bold box is the side that gets clipped back into its cone each iteration. Which variables are constrained decides where the projection lives, and the projection is what bends the trajectory.

Step sizes and divergence

The sliders η (primal) and τ (dual) are the two step sizes, 0.25 by default. PDHG converges when η·τ·‖A‖² < 1; beyond that the spiral stops contracting and the iterates fly apart. lpviz doesn't hide this — push both sliders toward 0.75 on a region with many facets and you can watch the divergence live (the run halts once the residuals overflow). Divergence from too-aggressive step sizes is a real failure mode first-order methods must manage; production solvers pick and adapt these step sizes automatically.

A plot with the primal step size on the horizontal axis and the dual step size on the vertical axis. A shaded region bounded by a hyperbola marks the step sizes guaranteed to converge on a 28-edge region; a second hyperbola higher up is the looser limit for a 5-edge region. The default of 0.25, 0.25 sits just inside the shaded region. η τ 0 0.8 0.8 guaranteed to converge m = 28 edges m = 5 edges default slider maximum
The stability condition is a hyperbola in the two step sizes, and it tightens as the region gains edges.

The shape of that condition is worth knowing before you drag the sliders. lpviz normalizes every constraint to a unit normal, so ‖A‖ depends only on how many edges your region has and how their normals are spread: for m normals pointing in evenly spread directions, ‖A‖² is exactly m/2, and the condition becomes η·τ < 2/m. The default η = τ = 0.25 gives η·τ = 0.0625, which clears that bar for regions up to 32 edges — so the defaults are safe on essentially every preset, and the way to leave the safe zone is to draw a region with many facets and then push both sliders up. Past the bar convergence is no longer guaranteed rather than immediately impossible: the condition is sufficient, not necessary, and on a small region you will often still converge — faster, in fact — while on a many-faceted one the iterates run away.

Convergence and termination

PDHG is a first-order method: cheap iterations, but many of them. The average iterate converges at a sublinear O(1/k) rate, and you'll see the signature long tail — early iterations cover most of the distance, then the spiral tightens excruciatingly slowly. lpviz stops when the scaled KKT error

ε = max( primal infeasibility, dual infeasibility, duality gap )

drops below 10⁻⁵ (each term relative-scaled) or when the iteration cap is hit. The eps column of the log tracks ε, and Infeas shows the raw constraint violation of the current point — unlike Simplex, PDHG iterates are only feasible in the limit.

Halpern acceleration and restarts

The Halpern checkbox enables the acceleration scheme used by recent PDLP-family research (restarted Halpern PDHG). Instead of taking the raw PDHG step T(zk), the iterate is blended with a fixed anchor point:

zk+1 = k⁄k+1 · T(zk) + 1⁄k+1 · zanchor

The pull toward the anchor damps the spiraling, and periodically the anchor is restarted to the current iterate. lpviz restarts adaptively, when the fixed-point residual has dropped to 20% of its value at the last restart, when it has dropped below 50% and begins rising again, or after a fixed fraction of the total iteration budget. Restart iterations are marked with an r in the log and highlighted along the path. With restarts, the convergence rate on LPs improves from sublinear to linear — flip Halpern on and off with Trace enabled and compare both the shape of the path (straighter, punctuated segments vs. a smooth spiral) and the final iteration counts.

A polygon with two trajectories from the same start: a pale spiral that loops several times, and a Halpern path made of near-straight segments joined at square restart markers. plain PDHG orbits the saddle Halpern with restarts sprints between restarts (▪)
The anchor damps the rotation, and each restart re-aims at the current iterate — so the path advances in near-straight segments instead of orbiting.

Color by basis

A spiralling trajectory drawn in three colours, one per active set. The colour changes twice near the start and then stays the same for the rest of the spiral. each colour is one active set rings mark where it changes — then it stops
The fingerprint changes a handful of times early, then stops — while the point is still visibly spiralling, and long before the residuals are small.

Color by basis colors each iterate by a fingerprint of its active set — which constraints currently have a positive dual price (inequality mode) or which variables sit at zero (standard-form mode). The color typically flickers early, then locks in well before the numbers converge: the iterates have identified which constraints will be tight at the optimum — the optimal basis — even though the point itself is still spiraling. This "basis identification" behavior is exactly what advanced implementations exploit to jump to an exact solution early.

The controls

ControlDefaultWhat it does
η (primal step size)0.25How far x moves per iteration. Larger is faster until η·τ·‖A‖² ≥ 1, then divergence.
τ (dual step size)0.25How fast constraint prices react. Interacts with η via the same stability product.
Maximum iterations1,000Iteration cap (log scale, up to 100k). PDHG routinely needs thousands on hard geometry.
Inequality modeonRun directly on Ax ≤ b; off = standard-form reformulation with split variables and slacks.
HalpernoffAnchored acceleration with adaptive restarts (r rows in the log).
Color by basisoffColor iterates by active-set fingerprint to watch basis identification.

Behavior to watch for