The Simplex method
The Simplex method solves a linear program by walking along the edges of the feasible region, hopping from vertex to vertex so that the objective improves at every step. In lpviz, that walk is drawn right on the polytope you sketched.
The idea
A linear objective over a convex polytope always attains its maximum at a vertex (a basic feasible solution). So instead of searching the whole region, Simplex searches only vertices — and only ever moves to an adjacent vertex that improves the objective. Since a polytope has finitely many vertices and the objective strictly improves (with a suitable pivot rule), the method terminates at an optimal vertex, or proves along the way that the LP is unbounded or infeasible.
Invented by George Dantzig in 1947, Simplex remains a workhorse of practical optimization. Its geometry is exactly what lpviz shows: each iterate in the log is a vertex, and consecutive iterates share an edge.
How lpviz sets up the problem
Your drawing defines the LP maximize cᵀx s.t. Ax ≤ b, with one row per edge. Simplex operates on standard form (equality constraints, nonnegative variables), so lpviz converts first:
- Each coordinate is split as x = x⁺ − x⁻ with x⁺, x⁻ ≥ 0, since points on the canvas may have negative coordinates.
- Each inequality gains a slack variable: aiᵀx + si = bi, si ≥ 0. Geometrically, si is the distance-like margin to constraint i; a vertex of your polygon is exactly a point where enough slacks are zero.
A basis is a choice of m variables (one per constraint) allowed to be nonzero; solving the basis system yields the vertex it represents. The bit-string in the iteration log is this basis: one 0/1 per standard-form variable, with 1 marking a basic variable.
Two phases
Simplex needs a feasible vertex to start from, and finding one is itself an LP. lpviz uses the classic two-phase method:
- Phase 1 adds one artificial variable per constraint and maximizes minus their sum. Artificials measure constraint violation, so driving them to zero lands on a genuine vertex of your region. If the Phase 1 optimum is negative, no feasible point exists and the LP is declared infeasible. Any artificials still lingering in the basis at value zero are pivoted out before Phase 2.
- Phase 2 starts from that vertex and optimizes the true objective cᵀx.
Both phases are shown: the Phase 1 iterates are drawn in a different color than the Phase 2 path, and the sidebar log separates the two blocks. On many drawings Phase 1 is short — but tilt or translate your region and you can watch it grow.
The pivot loop
At each iteration, Simplex computes the reduced cost of every nonbasic variable — the rate at which the objective would improve per unit increase of that variable. Then:
- Entering variable: by default lpviz uses Bland's rule — pick the lowest-index variable with positive reduced cost (Bland (low) in the Simplex settings). Bland's rule is not the fastest pivot rule, but together with the lowest-index tie-break below it provably never cycles. Two alternatives are available: Dantzig picks the variable with the largest reduced cost — the classic textbook rule, which often needs fewer pivots — and Bland (high) picks the highest index. Neither of those guarantees termination on a degenerate drawing, so lpviz counts consecutive degenerate pivots and switches back to Bland's rule for the rest of the phase when a run of them looks like a cycle. Iterations pivoted under that fallback are marked with a
dafter their number in the log, like therthat marks PDHG restarts. - Leaving variable (ratio test): increase the entering variable until some basic variable hits zero; the minimum ratio decides which one leaves; ties are broken by index — lowest by default, or highest via the Leaving rule setting. Geometrically, this is sliding along an edge until the next constraint becomes tight.
- Unboundedness: if no basic variable ever hits zero, the edge is a ray on which the objective grows forever — the log reports LP is unbounded. You can trigger this by leaving the region open in the objective direction.
Degenerate pivots happen when the minimum ratio is zero: the basis changes but the vertex does not move. In the log you'll see consecutive iterations with identical coordinates but different basis strings — the algorithm is reindexing the same corner before it can leave it. Vertices where more than n constraints meet (easy to create by dragging edges) produce exactly this.
Dual simplex mode
Every LP has a dual: for max cᵀx s.t. Ax ≤ b, the dual is min bᵀy s.t. Aᵀy = c, y ≥ 0 — one dual variable per constraint, and equal optimal values (strong duality). With Dual simplex mode checked, lpviz runs the same two-phase primal algorithm on the dual problem, then maps every dual basis back into your picture: the basic dual variables select which constraints are tight, and the displayed point is the intersection of those constraint lines (complementary slackness in action).
The behavior looks completely different from primal simplex. The path hops between intersections of constraint lines that are usually outside the feasible region — "super-optimal" points that satisfy the optimality conditions but not feasibility — and only becomes feasible at the very last step, which is the optimum. The status logic flips accordingly: an infeasible dual means your (nonempty) primal is unbounded, and an unbounded dual means the primal is infeasible.
Reading the log
Iter x y Obj basis
1 -8.00 -5.00 -7.1e+1 10010…
2 8.00 -4.00 4.4e+1 10001…
- x, y (and z in 3-variable mode): the current vertex.
- Obj: the objective value cᵀx — non-decreasing across Phase 2 rows.
- basis: the 0/1 membership of every standard-form variable in the current basis. Hover any row to highlight its vertex on the canvas.
Behavior to watch for
- Pivot counts track geometry. The number of iterations is the number of edges walked. On the Many Facets preset (28 edges), click Rotate Objective: as the objective sweeps, the start-to-optimum walk length changes, and the path wraps different amounts of the boundary.
- Worst cases exist. Simplex is exponential in the worst case (the Klee–Minty cube), yet astonishingly fast in practice — a tension you can feel by comparing round regions with skewed ones like Slanted Strip or Tight Corner.
- Compare with IPM. Simplex cost per iteration is a basis update; IPM pays for a full Newton system but takes few iterations regardless of how many vertices the region has. On Many Facets, count iterations for both.
- Dual vs. primal. Enable Trace, run primal simplex, switch on dual mode, and run again: one path crawls the inside of the boundary, the other leaps around the exterior scaffolding of constraint intersections — both finish at the same vertex.