Skip to content
The Lumenary
Advanced undergraduateUndergraduate 120 min

Optimisation

Finding the best. Linear programs and the shadow prices hidden in their duals, why convexity turns every local minimum into a global one, Lagrange multipliers and the KKT conditions, and gradient descent with a proof of how fast it converges.

Formally verified · 9 LeanComputationally tested · 2 PythonAI-drafted · awaiting human reviewMathematically reviewed: Awaiting human review
MotivationH

The best possible

A furniture workshop in Kumasi makes two products. Each uses time in three workshops, each workshop has only so many hours a week, and each product earns a different profit. How many of each should it make? In 1939 Leonid Kantorovich, asked by a plywood trust in Leningrad how to allocate machines to materials, saw that such problems share one mathematical form, and that every solution comes with a set of hidden prices — what an extra hour of each scarce resource is worth. Today the same mathematics schedules airline crews, routes delivery vans through Jakarta, plans electricity generation and allocates vaccines.

A different kind of optimisation runs on every phone. Training a machine-learning model means choosing millions of numbers to make an error as small as possible. Nobody can search all choices. Instead the computer repeatedly takes a small step downhill — gradient descent, an idea Cauchy published in 1847. Does it reach the bottom? How fast? And how could we ever know that a valley we have found is the lowest one, rather than a hollow halfway up the mountain?

This lesson develops the core of the theory: linear programming and its duality, convexity (the property that makes "local" mean "global"), Lagrange multipliers and the KKT conditions for constraints, and gradient descent with a proof of its convergence rate.

IntuitionH

Landscapes, corners and slopes

Picture the function to be minimised as a landscape. A local minimum is the bottom of some hollow; a global minimum is the lowest point anywhere. In a rugged landscape a hiker who always walks downhill can get stuck in a hollow far above the sea. In a convex landscape — a single bowl, with no ridges or false valleys — that cannot happen: every hollow is the bottom.

A linear program maximises a linear function over a region cut out by linear inequalities, a convex polygon or polyhedron. The level sets of the objective are parallel lines; slide them in the direction of improvement, and the last point of the region they touch is a corner (or, in a tie, an edge). The simplex method walks from corner to corner along edges, always improving.

With constraints, a minimum need not be a point where the slope vanishes. A ball rolling in a bowl that hits a wall comes to rest against the wall: there the downhill force is balanced by the wall pushing back, perpendicular to it. The size of that push is a Lagrange multiplier; it measures how much the optimum would improve if the wall moved. That is exactly Kantorovich's hidden price.

DefinitionsH

Definitions

Definition— optimisation problem, local and global minimum

An optimisation problem asks for min⁡x∈Sf(x)\min_{x \in S} f(x), where f:Rn→Rf : \R^n \to \R is the objective and S⊆RnS \subseteq \R^n the feasible set (maximising ff is minimising −f-f). A point x∗∈Sx^* \in S is a global minimiser if f(x∗)≤f(x)f(x^*) \le f(x) for all x∈Sx \in S, and a local minimiser if this holds for all x∈Sx \in S in some ball around x∗x^*. The problem is infeasible if S=∅S = \varnothing and unbounded if inf⁡Sf=−∞\inf_S f = -\infty.

Definition— linear program and its dual

A linear program (LP) optimises a linear function subject to finitely many linear equations and inequalities. In inequality form, the primal problem and its dual are

(P)max⁡  cTx   s.t.   Ax≤b,  x≥0,(D)min⁡  bTy   s.t.   ATy≥c,  y≥0,\text{(P)}\quad \max\; c^{\mathsf T}x \;\text{ s.t. }\; Ax \le b,\; x \ge 0, \qquad\qquad \text{(D)}\quad \min\; b^{\mathsf T}y \;\text{ s.t. }\; A^{\mathsf T}y \ge c,\; y \ge 0,

with AA an m×nm \times n matrix and inequalities between vectors meant entry by entry. A vertex of the feasible polyhedron is a feasible point at which nn linearly independent constraints are tight.

Definition— convex set, convex function

A set C⊆RnC \subseteq \R^n is convex if tx+(1−t)y∈Ctx + (1 - t)y \in C whenever x,y∈Cx, y \in C and 0≤t≤10 \le t \le 1. A function ff on a convex set is convex if

f(tx+(1−t)y)≤tf(x)+(1−t)f(y)for all x,y and 0≤t≤1,f(tx + (1 - t)y) \le t f(x) + (1 - t) f(y) \qquad \text{for all } x, y \text{ and } 0 \le t \le 1,

strictly convex if the inequality is strict for x≠yx \neq y and 0<t<10 < t < 1, and μ\mu-strongly convex if f(x)−μ2∥x∥2f(x) - \frac\mu2\|x\|^2 is convex. A differentiable ff is LL-smooth if its gradient is LL-Lipschitz: ∥∇f(x)−∇f(y)∥≤L∥x−y∥\|\nabla f(x) - \nabla f(y)\| \le L\|x - y\|.

Definition— Lagrangian and KKT conditions

For the problem min⁡f(x)\min f(x) subject to gi(x)≤0g_i(x) \le 0 (i=1,…,mi = 1, \dots, m) and hj(x)=0h_j(x) = 0 (j=1,…,pj = 1, \dots, p), with differentiable functions, the Lagrangian is L(x,μ,λ)=f(x)+∑iμigi(x)+∑jλjhj(x)\mathcal L(x, \mu, \lambda) = f(x) + \sum_i \mu_i g_i(x) + \sum_j \lambda_j h_j(x). A point x∗x^* with multipliers μ,λ\mu, \lambda satisfies the Karush–Kuhn–Tucker (KKT) conditions if

∇f(x∗)+∑iμi∇gi(x∗)+∑jλj∇hj(x∗)=0,gi(x∗)≤0,hj(x∗)=0,μi≥0,μi gi(x∗)=0.\nabla f(x^*) + \sum_i \mu_i \nabla g_i(x^*) + \sum_j \lambda_j \nabla h_j(x^*) = 0, \quad g_i(x^*) \le 0, \quad h_j(x^*) = 0, \quad \mu_i \ge 0, \quad \mu_i\, g_i(x^*) = 0.

The last condition is complementary slackness: a multiplier can be non-zero only for a constraint that is tight.

Definition— gradient descent and Newton's method

Gradient descent with step size η>0\eta > 0 iterates xk+1=xk−η∇f(xk)x_{k+1} = x_k - \eta\nabla f(x_k). Newton's method iterates xk+1=xk−(∇2f(xk))−1∇f(xk)x_{k+1} = x_k - \big(\nabla^2 f(x_k)\big)^{-1}\nabla f(x_k), using the Hessian matrix ∇2f\nabla^2 f.

Worked examplesH

Examples and non-examples

Example— A production problem, solved by looking

The Kumasi workshop makes xx units of product 1 and yy of product 2, using 11 hour of workshop A and 33 of workshop C per unit of product 1, and 22 hours of B and 22 of C per unit of product 2. A, B and C have 44, 1212 and 1818 hours a week, and the profits are 33 and 55 per unit:

max⁡  3x+5ys.t.x≤4,2y≤12,3x+2y≤18,x,y≥0.\max\; 3x + 5y \quad \text{s.t.}\quad x \le 4,\quad 2y \le 12,\quad 3x + 2y \le 18,\quad x, y \ge 0.

The feasible region is a pentagon with vertices (0,0)(0, 0), (4,0)(4, 0), (4,3)(4, 3), (2,6)(2, 6), (0,6)(0, 6), where the objective takes the values 0,12,27,36,300, 12, 27, 36, 30. The optimum is (2,6)(2, 6), with profit 3636: workshops B and C are fully used, while A has 22 hours to spare. (The visualisation lets you slide the profit line.)

Example— LPs without optimal solutions

max⁡  x\max\; x subject to x≤0x \le 0 and x≥1x \ge 1 is infeasible. max⁡  x+y\max\; x + y subject to x−y≤1x - y \le 1, x,y≥0x, y \ge 0 is unbounded: (t+1,t)(t + 1, t) is feasible for every t≥0t \ge 0, with objective 2t+12t + 1. A feasible LP whose objective is bounded always has an optimal solution, and if its feasible region has a vertex, one optimal solution is a vertex.

Example— Convex and not convex

Convex functions: affine functions, x2x^2, exe^x, ∣x∣|x| and every norm, −log⁡x-\log x on (0,∞)(0, \infty), the maximum of finitely many convex functions, and ∥Aw−y∥2\|Aw - y\|^2. Convex sets: half-spaces {a⋅x≤b}\{a \cdot x \le b\}, balls, polyhedra (intersections of finitely many half-spaces), and sublevel sets {f≤r}\{f \le r\} of convex functions. Not convex: x3x^3, sin⁡x\sin x, the double well x4−x2x^4 - x^2 (with two global minima ±1/2\pm 1/\sqrt2 and a local maximum at 00), and the annulus 1≤∥x∥≤21 \le \|x\| \le 2. Note that ∣x∣|x| is convex but not differentiable at its minimum.

Example— A constrained minimum, by KKT

Minimise (x−2)2+(y−2)2(x - 2)^2 + (y - 2)^2 — the squared distance to (2,2)(2, 2) — subject to x+y≤2x + y \le 2. The unconstrained minimiser (2,2)(2, 2) is infeasible, so the constraint will be tight. KKT: (2(x−2),2(y−2))+μ(1,1)=0(2(x - 2), 2(y - 2)) + \mu(1, 1) = 0 gives x=y=2−μ/2x = y = 2 - \mu/2, and x+y=2x + y = 2 gives μ=2≥0\mu = 2 \ge 0, so x∗=(1,1)x^* = (1, 1) with minimum value 22. The multiplier μ=2\mu = 2 is the rate at which the optimal value would fall if the constraint were relaxed to x+y≤2+εx + y \le 2 + \varepsilon (it becomes 2−2ε+O(ε2)2 - 2\varepsilon + O(\varepsilon^2)).

ProofH

Linear programming and duality

Theorem— Theorem 1 (weak duality)

If xx is feasible for (P) and yy is feasible for (D), then cTx≤bTyc^{\mathsf T}x \le b^{\mathsf T}y.

Proof

Using x≥0x \ge 0 with c≤ATyc \le A^{\mathsf T}y, and then y≥0y \ge 0 with Ax≤bAx \le b:

cTx  ≤  (ATy)Tx  =  yT(Ax)  ≤  yTb.c^{\mathsf T}x \;\le\; (A^{\mathsf T}y)^{\mathsf T}x \;=\; y^{\mathsf T}(Ax) \;\le\; y^{\mathsf T}b.

∎

Theorem— Corollary 2 (certificates and complementary slackness)

(a) If feasible xx and yy have cTx=bTyc^{\mathsf T}x = b^{\mathsf T}y, both are optimal. (b) In that case yi (b−Ax)i=0y_i\,(b - Ax)_i = 0 for every ii and xj (ATy−c)j=0x_j\,(A^{\mathsf T}y - c)_j = 0 for every jj. (c) If (P) is unbounded, (D) is infeasible, and vice versa.

Proof

(a) Every feasible x′x' has cTx′≤bTy=cTxc^{\mathsf T}x' \le b^{\mathsf T}y = c^{\mathsf T}x, and symmetrically for yy. (b) Equality of the ends of the chain in Theorem 1 forces both inequalities to be equalities: yT(b−Ax)=0y^{\mathsf T}(b - Ax) = 0 and (ATy−c)Tx=0(A^{\mathsf T}y - c)^{\mathsf T}x = 0. These are sums of non-negative products, so every product vanishes. (c) A dual-feasible yy would bound every primal value by bTyb^{\mathsf T}y.

∎

Theorem— Theorem 3 (Farkas' lemma)

For a matrix AA and vector bb, exactly one of the following holds: (i) Ax=bAx = b for some x≥0x \ge 0; (ii) there is yy with ATy≥0A^{\mathsf T}y \ge 0 and bTy<0b^{\mathsf T}y < 0.

Proof

Not both: otherwise 0≤(ATy)Tx=yTb<00 \le (A^{\mathsf T}y)^{\mathsf T}x = y^{\mathsf T}b < 0. Suppose (i) fails, so b∉K={Ax:x≥0}b \notin K = \{Ax : x \ge 0\}. The cone KK is convex, and it is closed (a finitely generated cone is closed; this follows from Carathéodory's theorem, which writes each point of KK using linearly independent columns of AA). Let z0z_0 be the point of KK nearest to bb (it exists since KK is closed), and put y=z0−b≠0y = z_0 - b \ne 0. For z∈Kz \in K and 0<t≤10 < t \le 1, the point z0+t(z−z0)z_0 + t(z - z_0) is in KK and is no closer to bb; expanding ∥z0+t(z−z0)−b∥2≥∥y∥2\|z_0 + t(z - z_0) - b\|^2 \ge \|y\|^2 and letting t→0t \to 0 gives yT(z−z0)≥0y^{\mathsf T}(z - z_0) \ge 0. Taking z=0z = 0 and z=2z0z = 2z_0 gives yTz0=0y^{\mathsf T}z_0 = 0, so yTz≥0y^{\mathsf T}z \ge 0 for all z∈Kz \in K — in particular ATy≥0A^{\mathsf T}y \ge 0 — and yTb=yTz0−∥y∥2<0y^{\mathsf T}b = y^{\mathsf T}z_0 - \|y\|^2 < 0.

∎

Theorem— Theorem 4 (strong duality)

If (P) has an optimal solution, then so does (D), and the optimal values are equal. The same holds with the roles of (P) and (D) exchanged.

Proof

Sketch. Let p∗p^* be the optimal value of (P) and ε>0\varepsilon > 0. The system Ax≤bAx \le b, x≥0x \ge 0, cTx≥p∗+εc^{\mathsf T}x \ge p^* + \varepsilon has no solution. Adding slack variables and applying Farkas' lemma gives y≥0y \ge 0 and τ≥0\tau \ge 0 with ATy≥τcA^{\mathsf T}y \ge \tau c and bTy<τ(p∗+ε)b^{\mathsf T}y < \tau(p^* + \varepsilon). Here τ>0\tau > 0, since τ=0\tau = 0 would contradict the feasibility of (P) by Theorem 1. Then y/τy/\tau is dual feasible with value below p∗+εp^* + \varepsilon. Since ε\varepsilon was arbitrary and Theorem 1 gives the reverse inequality, inf⁡(D)=p∗\inf(D) = p^*; a feasible LP whose objective is bounded attains its optimum. Full details are in Matoušek and Gärtner, chapter 6.

∎

The dual as prices. In the workshop problem the dual solution is y=(0,32,1)y = (0, \tfrac32, 1): one more hour in workshop B would raise the maximum profit by 32\tfrac32, one more in C by 11, and one more in A by nothing, since A already has slack (complementary slackness). Check: bTy=4⋅0+12⋅32+18⋅1=36=cTx∗b^{\mathsf T}y = 4 \cdot 0 + 12 \cdot \tfrac32 + 18 \cdot 1 = 36 = c^{\mathsf T}x^*. These shadow prices are Kantorovich's "objectively determined valuations".

The simplex method. An LP in inequality form with b≥0b \ge 0 starts at the vertex x=0x = 0. At each step the method looks for a non-basic variable whose increase improves the objective (a positive reduced cost), increases it until the first constraint becomes tight (the ratio test), and pivots to that adjacent vertex. If no variable can improve the objective, the vertex is optimal, and the final tableau displays a dual solution satisfying Corollary 2(a). If an improving variable can be increased forever, the LP is unbounded. With Bland's smallest-index rule (1977) the method never cycles, so it terminates. Klee and Minty (1972) built LPs on which the classical rule visits exponentially many vertices, yet in practice the method is very fast, a phenomenon explained by Spielman and Teng's smoothed analysis (2004). Provably polynomial-time algorithms exist: Khachiyan's ellipsoid method (1979) and Karmarkar's interior-point method (1984). The first experiment runs the simplex method in exact arithmetic.

ProofH

Convexity: local is global

Theorem— Theorem 5 (local minima of convex functions are global)

Let ff be convex on a convex set CC. Every local minimiser of ff on CC is a global minimiser. The set of minimisers is convex, and if ff is strictly convex there is at most one.

Proof

Let xx be a local minimiser and y∈Cy \in C. For t∈(0,1]t \in (0, 1] the point x+t(y−x)=(1−t)x+tyx + t(y - x) = (1 - t)x + ty lies in CC, and for tt small enough it lies in the ball where xx is minimal. Then

f(x)≤f((1−t)x+ty)≤(1−t)f(x)+tf(y),f(x) \le f\big((1 - t)x + ty\big) \le (1 - t)f(x) + t f(y),

so tf(x)≤tf(y)t f(x) \le t f(y), and dividing by t>0t > 0 gives f(x)≤f(y)f(x) \le f(y). The minimisers form the sublevel set {f≤min⁡f}\{f \le \min f\}, which is convex. If x≠yx \ne y were both minimisers of a strictly convex ff, their midpoint would have f<min⁡ff < \min f.

∎

Theorem— Theorem 6 (first-order characterisation)

A differentiable ff on a convex open set is convex if and only if f(y)≥f(x)+∇f(x)⋅(y−x)f(y) \ge f(x) + \nabla f(x) \cdot (y - x) for all x,yx, y. Consequently, for convex differentiable ff on Rn\R^n, ∇f(x∗)=0\nabla f(x^*) = 0 if and only if x∗x^* is a global minimiser.

Proof

If ff is convex, f(x+t(y−x))−f(x)t≤f(y)−f(x)\frac{f(x + t(y - x)) - f(x)}{t} \le f(y) - f(x) for t∈(0,1]t \in (0, 1], by the definition with weights 1−t1 - t and tt; letting t→0t \to 0 the left side tends to ∇f(x)⋅(y−x)\nabla f(x) \cdot (y - x). Conversely, given the inequality, put z=tx+(1−t)yz = tx + (1 - t)y and add tt times the inequality at (z,x)(z, x) to 1−t1 - t times the inequality at (z,y)(z, y): the gradient terms cancel and leave tf(x)+(1−t)f(y)≥f(z)tf(x) + (1 - t)f(y) \ge f(z). The consequence: if ∇f(x∗)=0\nabla f(x^*) = 0 the inequality gives f(y)≥f(x∗)f(y) \ge f(x^*) for all yy.

∎

A twice-differentiable ff is convex exactly when its Hessian is positive semidefinite everywhere (by Theorem 6 applied along lines). Without convexity none of this holds: x3x^3 has f′(0)=0f'(0) = 0 but no minimum, and x2−y2x^2 - y^2 has a saddle at the origin.

ProofH

Lagrange multipliers and the KKT conditions

From multivariable calculus: if x∗x^* is a local minimiser of ff subject to h(x)=0h(x) = 0 and ∇h(x∗)≠0\nabla h(x^*) \ne 0, then ∇f(x∗)=λ∇h(x∗)\nabla f(x^*) = \lambda\nabla h(x^*) for some λ\lambda, because the gradient of ff must be perpendicular to the constraint surface. For example, the point of the plane ⟨a,x⟩=b\langle a, x \rangle = b closest to the origin satisfies 2x=λa2x = \lambda a, so x∗=b∥a∥2ax^* = \frac{b}{\|a\|^2}a. Convexity turns this necessary condition into a proof of optimality: x−x∗x - x^* is orthogonal to x∗x^* for every feasible xx, so ∥x∥2=∥x−x∗∥2+∥x∗∥2≥∥x∗∥2\|x\|^2 = \|x - x^*\|^2 + \|x^*\|^2 \ge \|x^*\|^2. (This is the Lean theorem least_norm.)

Theorem— Theorem 7 (KKT conditions)

Consider min⁡f(x)\min f(x) subject to gi(x)≤0g_i(x) \le 0 and hj(x)=0h_j(x) = 0, with continuously differentiable functions.

(a) Sufficiency. If ff and every gig_i are convex, every hjh_j is affine, and (x∗,μ,λ)(x^*, \mu, \lambda) satisfies the KKT conditions, then x∗x^* is a global minimiser.

(b) Necessity. If x∗x^* is a local minimiser and a constraint qualification holds at x∗x^* — for example, the gradients of the tight constraints are linearly independent, or (for convex problems) some point satisfies all gi<0g_i < 0 strictly (Slater's condition) — then there are multipliers making the KKT conditions hold.

Proof

(a) Let xx be feasible. By Theorem 6 for ff and the KKT equation,

f(x)≥f(x∗)+∇f(x∗)⋅(x−x∗)=f(x∗)−∑iμi∇gi(x∗)⋅(x−x∗)−∑jλj∇hj(x∗)⋅(x−x∗).f(x) \ge f(x^*) + \nabla f(x^*) \cdot (x - x^*) = f(x^*) - \sum_i \mu_i \nabla g_i(x^*) \cdot (x - x^*) - \sum_j \lambda_j \nabla h_j(x^*) \cdot (x - x^*).

Since hjh_j is affine, ∇hj(x∗)⋅(x−x∗)=hj(x)−hj(x∗)=0\nabla h_j(x^*) \cdot (x - x^*) = h_j(x) - h_j(x^*) = 0. By Theorem 6 for gig_i, ∇gi(x∗)⋅(x−x∗)≤gi(x)−gi(x∗)\nabla g_i(x^*) \cdot (x - x^*) \le g_i(x) - g_i(x^*), and with μi≥0\mu_i \ge 0 and μigi(x∗)=0\mu_i g_i(x^*) = 0 we get −μi∇gi(x∗)⋅(x−x∗)≥−μigi(x)≥0-\mu_i \nabla g_i(x^*) \cdot (x - x^*) \ge -\mu_i g_i(x) \ge 0. So f(x)≥f(x∗)f(x) \ge f(x^*).

(b) Sketch. Under linear independence of the active gradients, a first-order feasible direction dd that decreased ff could be followed along a curve of feasible points (implicit function theorem). So no such dd exists, and Farkas' lemma converts "no improving feasible direction" into the existence of μ≥0\mu \ge 0 and λ\lambda. See Nocedal and Wright, chapter 12, or Boyd and Vandenberghe, chapter 5.

∎

For a linear program, the KKT conditions are exactly primal feasibility, dual feasibility and complementary slackness (Corollary 2): the multipliers are the dual variables. Without a constraint qualification, necessity can fail: minimise xx subject to x2≤0x^2 \le 0. The only feasible point is 00, but ∇x=1≠−μ⋅0\nabla x = 1 \neq -\mu \cdot 0 for every μ\mu.

ProofH

Gradient descent: a convergence proof

Theorem— Lemma 8 (descent lemma)

If ∇f\nabla f is LL-Lipschitz, then f(y)≤f(x)+∇f(x)⋅(y−x)+L2∥y−x∥2f(y) \le f(x) + \nabla f(x) \cdot (y - x) + \frac L2\|y - x\|^2. In particular, the step x+=x−1L∇f(x)x^+ = x - \frac1L\nabla f(x) gives f(x+)≤f(x)−12L∥∇f(x)∥2f(x^+) \le f(x) - \frac{1}{2L}\|\nabla f(x)\|^2.

Proof

By the fundamental theorem of calculus along the segment and Cauchy–Schwarz,

f(y)−f(x)−∇f(x)⋅(y−x)=∫01(∇f(x+t(y−x))−∇f(x))⋅(y−x) dt≤∫01Lt∥y−x∥2 dt=L2∥y−x∥2.f(y) - f(x) - \nabla f(x) \cdot (y - x) = \int_0^1 \big(\nabla f(x + t(y - x)) - \nabla f(x)\big) \cdot (y - x)\,dt \le \int_0^1 Lt\|y - x\|^2\,dt = \frac L2 \|y - x\|^2.

For y=x+y = x^+, the right-hand side becomes f(x)−1L∥∇f(x)∥2+12L∥∇f(x)∥2f(x) - \frac1L\|\nabla f(x)\|^2 + \frac1{2L}\|\nabla f(x)\|^2.

∎

Theorem— Theorem 9 (rate of gradient descent)

Let ff be convex and LL-smooth with a minimiser x∗x^*, and let xk+1=xk−1L∇f(xk)x_{k+1} = x_k - \frac1L\nabla f(x_k). Then for every k≥1k \ge 1,

f(xk)−f(x∗)≤L ∥x0−x∗∥22k.f(x_k) - f(x^*) \le \frac{L\,\|x_0 - x^*\|^2}{2k}.

Proof

Write gk=∇f(xk)g_k = \nabla f(x_k). By Lemma 8, f(xk+1)≤f(xk)−12L∥gk∥2f(x_{k+1}) \le f(x_k) - \frac{1}{2L}\|g_k\|^2; in particular the values decrease. By Theorem 6, f(xk)−f(x∗)≤gk⋅(xk−x∗)f(x_k) - f(x^*) \le g_k \cdot (x_k - x^*). Combining,

f(xk+1)−f(x∗)≤gk⋅(xk−x∗)−12L∥gk∥2=L2(∥xk−x∗∥2−∥xk+1−x∗∥2),f(x_{k+1}) - f(x^*) \le g_k \cdot (x_k - x^*) - \frac{1}{2L}\|g_k\|^2 = \frac L2\Big(\|x_k - x^*\|^2 - \|x_{k+1} - x^*\|^2\Big),

where the equality is the expansion of ∥xk+1−x∗∥2=∥(xk−x∗)−1Lgk∥2\|x_{k+1} - x^*\|^2 = \|(x_k - x^*) - \frac1L g_k\|^2. Summing over k=0,…,n−1k = 0, \dots, n - 1, the right-hand side telescopes to at most L2∥x0−x∗∥2\frac L2\|x_0 - x^*\|^2. Since the values decrease, the left-hand sum is at least n (f(xn)−f(x∗))n\,(f(x_n) - f(x^*)).

∎

Three remarks. Step size. For f(x)=L2x2f(x) = \frac L2 x^2 the iteration is xk+1=(1−ηL)xkx_{k+1} = (1 - \eta L)x_k, which converges exactly when 0<η<2/L0 < \eta < 2/L. Larger steps overshoot and diverge, as the experiment and the cobweb diagram show. Strong convexity. If ff is also μ\mu-strongly convex, the gap shrinks geometrically, like (1−μ/L)k(1 - \mu/L)^k. The ratio L/μL/\mu, the condition number, governs the speed. Faster methods. Nesterov's accelerated gradient method (1983) achieves O(1/k2)O(1/k^2), which is optimal for first-order methods on this class. Newton's method minimises a quadratic in one step, since it jumps straight to the minimum of the local quadratic model, and converges quadratically near a minimiser with positive definite Hessian; but each step solves a linear system with the Hessian.

Data fitting. Fitting a model Aw≈yAw \approx y to data by least squares means minimising F(w)=∥Aw−y∥2F(w) = \|Aw - y\|^2, which is convex with gradient 2AT(Aw−y)2A^{\mathsf T}(Aw - y). By Theorem 6 its minimisers are exactly the solutions of the normal equations ATAw=ATyA^{\mathsf T}Aw = A^{\mathsf T}y, unique when AA has independent columns. Geometrically Aw∗Aw^* is the orthogonal projection of yy onto the column space of AA. For huge data sets one runs (stochastic) gradient descent on FF instead of solving the normal equations, and the second experiment checks that both give the same line.

Formal mathematicsF

Optimisation in Lean and Mathlib

Mathlib has convex sets and functions (Convex, ConvexOn), local and global minima (IsLocalMin, IsMinOn), the dot product ⬝ᵥ with the order lemmas needed for linear programming, and real inner product spaces. Weak duality and its corollaries, as in Theorem 1 and Corollary 2:

weak_dualityLean 4Proved here from basic factsFormally verified
/-- **Weak duality.** For the primal problem *maximise `c · x` subject to `A x ≤ b`, `x ≥ 0`*
and its dual *minimise `b · y` subject to `Aᵀ y ≥ c`, `y ≥ 0`*, every feasible `x` and `y` satisfy
`c · x ≤ b · y`. The proof is one line of inequalities:
`c · x ≤ (Aᵀ y) · x = y · (A x) ≤ y · b`, using `x ≥ 0` and then `y ≥ 0`. -/
theorem weak_duality {m n : Type*} [Fintype m] [Fintype n] (A : Matrix m n ℝ) (b : m → ℝ)
    (c : n → ℝ) (x : n → ℝ) (y : m → ℝ) (hx : 0 ≤ x) (hAx : A *ᵥ x ≤ b) (hy : 0 ≤ y)
    (hAy : c ≤ y ᵥ* A) : c ⬝ᵥ x ≤ b ⬝ᵥ y :=
  calc c ⬝ᵥ x ≤ (y ᵥ* A) ⬝ᵥ x := dotProduct_le_dotProduct_of_nonneg_right hAy hx
    _ = y ⬝ᵥ (A *ᵥ x) := (dotProduct_mulVec y A x).symm
    _ ≤ y ⬝ᵥ b := dotProduct_le_dotProduct_of_nonneg_left hAx hy
    _ = b ⬝ᵥ y := dotProduct_comm _ _
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Optimisation.leanTry it in the Lean web editor
optimality_certificateLean 4Proved here from basic factsFormally verified
/-- **A dual solution certifies optimality.** If a primal-feasible `x` and a dual-feasible `y`
have equal objective values, then `x` is optimal: no feasible `x'` does better, because
`c · x' ≤ b · y = c · x` by weak duality. -/
theorem optimality_certificate {m n : Type*} [Fintype m] [Fintype n] (A : Matrix m n ℝ)
    (b : m → ℝ) (c : n → ℝ) (x : n → ℝ) (y : m → ℝ) (hy : 0 ≤ y) (hAy : c ≤ y ᵥ* A)
    (heq : c ⬝ᵥ x = b ⬝ᵥ y) (x' : n → ℝ) (hx' : 0 ≤ x') (hAx' : A *ᵥ x' ≤ b) :
    c ⬝ᵥ x' ≤ c ⬝ᵥ x := by
  rw [heq]
  exact weak_duality A b c x' y hx' hAx' hy hAy
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Optimisation.leanTry it in the Lean web editor
complementary_slacknessLean 4Proved here from basic factsFormally verified
/-- **Complementary slackness.** If feasible `x` and `y` have equal objective values, then both
inequalities in the weak-duality chain are equalities: `y · (b − A x) = 0` (a dual variable is
zero unless its constraint is tight) and `(Aᵀ y − c) · x = 0` (a primal variable is zero unless
its dual constraint is tight). -/
theorem complementary_slackness {m n : Type*} [Fintype m] [Fintype n] (A : Matrix m n ℝ)
    (b : m → ℝ) (c : n → ℝ) (x : n → ℝ) (y : m → ℝ) (hx : 0 ≤ x) (hAx : A *ᵥ x ≤ b)
    (hy : 0 ≤ y) (hAy : c ≤ y ᵥ* A) (heq : c ⬝ᵥ x = b ⬝ᵥ y) :
    y ⬝ᵥ (b - A *ᵥ x) = 0 ∧ (y ᵥ* A - c) ⬝ᵥ x = 0 := by
  have h1 : c ⬝ᵥ x ≤ (y ᵥ* A) ⬝ᵥ x := dotProduct_le_dotProduct_of_nonneg_right hAy hx
  have h2 : y ⬝ᵥ (A *ᵥ x) ≤ y ⬝ᵥ b := dotProduct_le_dotProduct_of_nonneg_left hAx hy
  have h3 : y ⬝ᵥ (A *ᵥ x) = (y ᵥ* A) ⬝ᵥ x := dotProduct_mulVec y A x
  have h4 : b ⬝ᵥ y = y ⬝ᵥ b := dotProduct_comm _ _
  constructor
  · rw [dotProduct_sub]
    linarith
  · rw [sub_dotProduct]
    linarith
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Optimisation.leanTry it in the Lean web editor

Theorem 5, proved along the segment as above, then the one-line Mathlib version, and convexity of sublevel sets:

local_min_convex_globalLean 4Proved here from basic factsFormally verified
/-- **For a convex function, every local minimum is global.** Suppose `x` is a local minimum
and `y` is any point. For small `t > 0` the point `x + t (y − x) = (1 − t) x + t y` is near `x`,
so `f x ≤ f ((1 − t) x + t y) ≤ (1 − t) f x + t f y` by convexity; subtracting `(1 − t) f x`
and dividing by `t` gives `f x ≤ f y`. -/
theorem local_min_convex_global {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E]
    {f : E → ℝ} (hf : ConvexOn ℝ Set.univ f) {x : E} (hx : IsLocalMin f x) (y : E) :
    f x ≤ f y := by
  have hcont : Filter.Tendsto (fun t : ℝ => x + t • (y - x)) (nhds 0) (nhds x) := by
    have hc : Continuous (fun t : ℝ => x + t • (y - x)) := by fun_prop
    simpa using hc.tendsto 0
  obtain ⟨ε, hε, hball⟩ := Metric.eventually_nhds_iff.mp (hcont.eventually hx)
  set t : ℝ := min (ε / 2) (1 / 2) with ht
  have ht0 : 0 < t := lt_min (half_pos hε) (by norm_num)
  have ht1 : t ≤ 1 / 2 := min_le_right _ _
  have htε : dist t 0 < ε := by
    rw [Real.dist_eq, sub_zero, abs_of_pos ht0]
    exact lt_of_le_of_lt (min_le_left _ _) (half_lt_self hε)
  have hloc : f x ≤ f (x + t • (y - x)) := hball htε
  have hseg : x + t • (y - x) = (1 - t) • x + t • y := by
    rw [smul_sub, sub_smul, one_smul]
    abel
  have hconv : f ((1 - t) • x + t • y) ≤ (1 - t) • f x + t • f y :=
    hf.2 (Set.mem_univ x) (Set.mem_univ y) (by linarith) ht0.le (by ring)
  rw [hseg] at hloc
  simp only [smul_eq_mul] at hconv
  nlinarith
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Optimisation.leanTry it in the Lean web editor
local_min_convex_global_libraryLean 4Applies a library theoremFormally verified
/-- The same principle from Mathlib: `IsMinOn.of_isLocalMin_of_convex_univ` (whose proof also
restricts `f` to the segment from `x` to `y`). -/
theorem local_min_convex_global_library {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E]
    {f : E → ℝ} (hf : ConvexOn ℝ Set.univ f) {x : E} (hx : IsLocalMin f x) :
    ∀ y, f x ≤ f y :=
  IsMinOn.of_isLocalMin_of_convex_univ hx hf
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Optimisation.leanTry it in the Lean web editor
convex_sublevelLean 4Applies a library theoremFormally verified
/-- **Sublevel sets of a convex function are convex** (Mathlib's `ConvexOn.convex_le`): the set
of points where `f ≤ r` is convex. In particular the set of minimisers of a convex function is
convex, so it is empty, a single point, or infinite. -/
theorem convex_sublevel {E : Type*} [NormedAddCommGroup E] [NormedSpace ℝ E] {f : E → ℝ}
    (hf : ConvexOn ℝ Set.univ f) (r : ℝ) : Convex ℝ {x ∈ Set.univ | f x ≤ r} :=
  hf.convex_le r
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Optimisation.leanTry it in the Lean web editor

The least-norm problem solved by the Lagrange condition, with Pythagoras as the certificate:

least_normLean 4Proved here from basic factsFormally verified
/-- **The least-norm solution of a linear equation.** Among all `x` with `⟪a, x⟫ = b`, the
smallest is `x* = (b / ‖a‖²) a` — the point the Lagrange condition `∇‖x‖² = λ ∇⟪a, x⟫`, i.e.
`2 x = λ a`, predicts. The proof is Pythagoras: `x − x*` is orthogonal to `x*`, so
`‖x‖² = ‖x − x*‖² + ‖x*‖² ≥ ‖x*‖²`. -/
theorem least_norm {E : Type*} [NormedAddCommGroup E] [InnerProductSpace ℝ E] (a : E) (b : ℝ)
    (ha : a ≠ 0) (x : E) (hx : inner ℝ a x = b) :
    ‖(b / ‖a‖ ^ 2) • a‖ ^ 2 ≤ ‖x‖ ^ 2 := by
  set xs : E := (b / ‖a‖ ^ 2) • a with hxs
  have ha2 : ‖a‖ ^ 2 ≠ 0 := by positivity
  have horth : inner ℝ (x - xs) xs = 0 := by
    rw [hxs, inner_smul_right, inner_sub_left, inner_smul_left, real_inner_comm, hx,
      real_inner_self_eq_norm_sq]
    simp only [RCLike.conj_to_real]
    field_simp
    ring
  have hpy : ‖x‖ ^ 2 = ‖x - xs‖ ^ 2 + ‖xs‖ ^ 2 := by
    have h := norm_add_sq_real (x - xs) xs
    rw [sub_add_cancel] at h
    rw [h, horth]
    ring
  rw [hpy]
  nlinarith [sq_nonneg ‖x - xs‖]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Optimisation.leanTry it in the Lean web editor

Theorem 9. The Lean statement takes the descent inequality (Lemma 8) and the convexity inequality (Theorem 6) as hypotheses about the iterates, and proves the rate exactly as above: the one-step bound, telescoping, and monotonicity. To show these hypotheses are not vacuous, the second theorem verifies them for every convex quadratic f(x)=a2x2f(x) = \frac a2 x^2 with 0<a≤L0 < a \le L and deduces its rate.

gradient_descent_rateLean 4Proved here from basic factsFormally verified
/-- **Gradient descent converges at rate `O(1/k)`.** Let `x (k + 1) = x k − (1/L) g k`, where
`g k` is the gradient at `x k`, and assume the two standard inequalities for a convex function
with `L`-Lipschitz gradient: the *descent inequality* `f (x (k+1)) ≤ f (x k) − ‖g k‖² / (2L)` and
the *convexity inequality* `f (x k) − f x* ≤ ⟪g k, x k − x*⟫`. Then
`k · (f (x k) − f x*) ≤ (L/2) ‖x 0 − x*‖²`. Proof (the lesson's): each step satisfies
`f (x (k+1)) − f x* ≤ (L/2)(‖x k − x*‖² − ‖x (k+1) − x*‖²)`; these telescope, and the values
`f (x k)` decrease. -/
theorem gradient_descent_rate {E : Type*} [NormedAddCommGroup E] [InnerProductSpace ℝ E]
    (f : E → ℝ) (x g : ℕ → E) (xs : E) (L : ℝ) (hL : 0 < L)
    (hstep : ∀ k, x (k + 1) = x k - (1 / L) • g k)
    (hdesc : ∀ k, f (x (k + 1)) ≤ f (x k) - 1 / (2 * L) * ‖g k‖ ^ 2)
    (hconv : ∀ k, f (x k) - f xs ≤ inner ℝ (g k) (x k - xs)) (n : ℕ) :
    (n : ℝ) * (f (x n) - f xs) ≤ L / 2 * ‖x 0 - xs‖ ^ 2 := by
  -- One step: the gap is bounded by the decrease of the squared distance to `x*`.
  have step : ∀ k, f (x (k + 1)) - f xs ≤
      L / 2 * (‖x k - xs‖ ^ 2 - ‖x (k + 1) - xs‖ ^ 2) := by
    intro k
    have hx1 : x (k + 1) - xs = (x k - xs) - (1 / L) • g k := by
      rw [hstep]
      abel
    have hn : ‖x (k + 1) - xs‖ ^ 2 = ‖x k - xs‖ ^ 2 - 2 * (1 / L) * inner ℝ (g k) (x k - xs)
        + (1 / L) ^ 2 * ‖g k‖ ^ 2 := by
      rw [hx1, norm_sub_sq_real, inner_smul_right, norm_smul, real_inner_comm, mul_pow,
        Real.norm_eq_abs, sq_abs]
      ring
    have h1 := hdesc k
    have h2 := hconv k
    have h3 : L / 2 * (‖x k - xs‖ ^ 2 - (‖x k - xs‖ ^ 2 - 2 * (1 / L) * inner ℝ (g k) (x k - xs)
        + (1 / L) ^ 2 * ‖g k‖ ^ 2)) = inner ℝ (g k) (x k - xs) - 1 / (2 * L) * ‖g k‖ ^ 2 := by
      field_simp
      ring
    rw [hn, h3]
    linarith
  -- Telescoping the steps.
  have tele : ∀ n : ℕ, (∑ k ∈ Finset.range n, (f (x (k + 1)) - f xs)) ≤
      L / 2 * (‖x 0 - xs‖ ^ 2 - ‖x n - xs‖ ^ 2) := by
    intro n
    induction n with
    | zero => simp
    | succ n ih =>
      rw [Finset.sum_range_succ]
      have := step n
      nlinarith
  -- The values decrease along the iteration.
  have mono : ∀ k n, k ≤ n → f (x n) ≤ f (x k) := by
    intro k n hkn
    induction hkn with
    | refl => exact le_refl _
    | @step m _ ih =>
      have h1 := hdesc m
      have h2 : 0 ≤ 1 / (2 * L) * ‖g m‖ ^ 2 := by positivity
      linarith
  have hsum : (n : ℝ) * (f (x n) - f xs) ≤ ∑ k ∈ Finset.range n, (f (x (k + 1)) - f xs) := by
    have hle : ∀ k ∈ Finset.range n, f (x n) - f xs ≤ f (x (k + 1)) - f xs := by
      intro k hk
      have := mono (k + 1) n (Finset.mem_range.mp hk)
      linarith
    have := Finset.card_nsmul_le_sum (Finset.range n) _ _ hle
    simpa using this
  have := tele n
  have : 0 ≤ L / 2 * ‖x n - xs‖ ^ 2 := by positivity
  linarith
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Optimisation.leanTry it in the Lean web editor
gradient_descent_quadraticLean 4Proved here from basic factsFormally verified
/-- **The hypotheses are not vacuous: convex quadratics satisfy them.** For `f(x) = (a/2) x²` on
`ℝ` with `0 < a ≤ L`, gradient descent with step `1/L` is `x (k+1) = (1 − a/L) x k`, and the
rate theorem gives `k · (a/2) x_k² ≤ (L/2) x_0²`. We check the descent inequality (it reduces to
`(1 − a/L)² ≤ 1 − a/L`) and the convexity inequality (`(a/2) x² ≤ a x²`), then apply
`gradient_descent_rate` with minimiser `0`. -/
theorem gradient_descent_quadratic (a L : ℝ) (ha : 0 < a) (haL : a ≤ L) (x : ℕ → ℝ)
    (hstep : ∀ k, x (k + 1) = x k - (1 / L) * (a * x k)) (n : ℕ) :
    (n : ℝ) * (a / 2 * x n ^ 2) ≤ L / 2 * x 0 ^ 2 := by
  have hL : 0 < L := lt_of_lt_of_le ha haL
  have h1 : 0 ≤ 1 - a / L := by
    rw [sub_nonneg, div_le_one hL]
    exact haL
  have h2 : 1 - a / L ≤ 1 := by
    have : 0 ≤ a / L := by positivity
    linarith
  have key := gradient_descent_rate (fun y : ℝ => a / 2 * y ^ 2) x (fun k => a * x k) 0 L hL
    (fun k => by rw [hstep k]; simp [smul_eq_mul])
    (fun k => by
      show a / 2 * x (k + 1) ^ 2 ≤ a / 2 * x k ^ 2 - 1 / (2 * L) * ‖a * x k‖ ^ 2
      rw [hstep k, Real.norm_eq_abs, sq_abs]
      have e1 : x k - 1 / L * (a * x k) = (1 - a / L) * x k := by field_simp
      have e2 : a / 2 * x k ^ 2 - 1 / (2 * L) * (a * x k) ^ 2
          = a / 2 * x k ^ 2 * (1 - a / L) := by
        field_simp
      rw [e1, e2, show a / 2 * ((1 - a / L) * x k) ^ 2 = a / 2 * x k ^ 2 * (1 - a / L) ^ 2 by ring]
      apply mul_le_mul_of_nonneg_left _ (by positivity)
      nlinarith)
    (fun k => by
      simp only [Real.inner_apply, sub_zero]
      nlinarith [sq_nonneg (x k)]) n
  simpa using key
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/Optimisation.leanTry it in the Lean web editor

What is and is not formalised. Independent: Theorem 1, Corollary 2(a)–(b), Theorem 5, the least-norm problem, the rate argument of Theorem 9 and its quadratic instance. From Mathlib: the local-to-global principle and convex sublevel sets. Not formalised: Farkas' lemma and strong duality (Mathlib has related cone-duality results, but not the LP theorem in this form), the simplex method, the KKT theorem, Theorem 6, and Lemma 8 (the derivation of the descent inequality from a Lipschitz gradient). The Lean exercises ask for weak duality and the optimality certificate.

ComputationC

Simplex steps and descent rates

The first program implements the tableau simplex method with exact fractions and solves the workshop problem twice. With Dantzig's rule (enter the variable with the largest reduced profit) it visits (0,0)→(0,6)→(2,6)(0,0) \to (0,6) \to (2,6); with Bland's rule it takes the longer route (0,0)→(4,0)→(4,3)→(2,6)(0,0) \to (4,0) \to (4,3) \to (2,6). It then reads the shadow prices (0,32,1)(0, \tfrac32, 1) from the final tableau, checks strong duality and complementary slackness exactly, and detects an unbounded problem.

The simplex method and LP duality, in exact arithmeticPythonExact computationComputationally tested
"""The simplex method in exact arithmetic, with the dual read off at the end.

A small workshop makes two products. Product 1 uses 1 hour of workshop A and 3
hours of workshop C; product 2 uses 2 hours of workshop B and 2 hours of C.
Each week A, B and C have 4, 12 and 18 hours. Profits are 3 and 5 per unit:

    maximise 3x + 5y  subject to  x <= 4,  2y <= 12,  3x + 2y <= 18,  x, y >= 0.

The program runs the tableau simplex method with exact fractions, once with
Dantzig's rule (enter the variable with the largest reduced profit) and once
with Bland's rule (smallest index), and prints the vertices visited. The final
tableau also contains the optimal dual solution - the "shadow prices" of the
three workshops - and the program checks strong duality and complementary
slackness, then shows the method detecting an unbounded problem.

Exact rational arithmetic: an exact computation for these problems.
"""

from fractions import Fraction

def simplex(a, b, c, rule="dantzig"):
    """Maximise c.x subject to a x <= b, x >= 0, assuming b >= 0.

    Returns (status, x, y, value, path) where status is "optimal" or
    "unbounded", y is the dual solution and path lists the vertices visited.
    """
    m, n = len(a), len(c)
    rows = [[Fraction(v) for v in a[i]] + [Fraction(int(i == j)) for j in
            range(m)] + [Fraction(b[i])] for i in range(m)]
    obj = [Fraction(-v) for v in c] + [Fraction(0)] * (m + 1)
    basis = [n + i for i in range(m)]

    def vertex():
        x = [Fraction(0)] * n
        for i, var in enumerate(basis):
            if var < n:
                x[var] = rows[i][-1]
        return tuple(x)

    path = [vertex()]
    while True:
        candidates = [j for j in range(n + m) if obj[j] < 0]
        if not candidates:
            break
        col = (min(candidates, key=lambda j: (obj[j], j)) if rule == "dantzig"
               else min(candidates))
        ratios = [(rows[i][-1] / rows[i][col], basis[i], i)
                  for i in range(m) if rows[i][col] > 0]
        if not ratios:
            return "unbounded", None, None, None, path
        _, _, r = min(ratios)
        piv = rows[r][col]
        rows[r] = [v / piv for v in rows[r]]
        for i in range(m):
            if i != r and rows[i][col] != 0:
                f = rows[i][col]
                rows[i] = [u - f * v for u, v in zip(rows[i], rows[r])]
        f = obj[col]
        obj = [u - f * v for u, v in zip(obj, rows[r])]
        basis[r] = col
        path.append(vertex())
    y = tuple(obj[n:n + m])
    return "optimal", vertex(), y, obj[-1], path

def dot(u, v):
    return sum(Fraction(p) * Fraction(q) for p, q in zip(u, v))

A = [[1, 0], [0, 2], [3, 2]]
B = [4, 12, 18]
C = [3, 5]

def show(v):
    return "(" + ", ".join(str(t) for t in v) + ")"

def main():
    print("maximise 3x + 5y  s.t.  x <= 4, 2y <= 12, 3x + 2y <= 18, x, y >= 0")
    for rule in ("dantzig", "bland"):
        status, x, y, value, path = simplex(A, B, C, rule)
        print(f"{rule:>8} rule: vertices " +
              " -> ".join(show(p) for p in path) + f"; value {value}")
    status, x, y, value, _ = simplex(A, B, C)
    print("optimal x =", show(x), " dual y (shadow prices) =", show(y))
    aty = [dot([row[j] for row in A], y) for j in range(2)]
    ax = [dot(row, x) for row in A]
    print("dual feasible: A^T y =", show(aty), ">= c =", show(C),
          " y >= 0:", all(v >= 0 for v in y))
    print(f"primal value c.x = {dot(C, x)},  dual value b.y = {dot(B, y)}")
    slack = [bi - v for bi, v in zip(B, ax)]
    print("complementary slackness: y_i * slack_i =",
          show(yi * s for yi, s in zip(y, slack)))
    print("   (workshop A has slack 2 hours, so its shadow price is 0)")
    print()
    status, *_ = simplex([[1, -1]], [1], [1, 1])
    print("maximise x + y s.t. x - y <= 1:", status,
          "(a column with no positive entry)")
    print()
    print("Epistemic status: exact rational arithmetic, so the optimal vertex,\n"
          "the dual solution and the equality of the two values are exact for\n"
          "this problem. That equality for every LP with an optimum is the\n"
          "strong duality theorem, proved in the references; weak duality and\n"
          "complementary slackness are proved in the lesson and in Lean.")

if __name__ == "__main__":
    main()
Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

The second program runs gradient descent on a convex quadratic with μ=2\mu = 2 and L=7L = 7. It compares the gap with the O(1/k)O(1/k) bound of Theorem 9, which holds but is far from tight here, and with the geometric rate available for strongly convex functions. It shows that the step 1.9/L1.9/L still converges while 2.1/L2.1/L explodes, that Newton's method finishes in one step, and that gradient descent on the mean squared error recovers the least-squares line.

Gradient descent: rates, step sizes, Newton and least squaresPythonNumerical approximationComputationally tested
"""Gradient descent and Newton's method on convex quadratics and least squares.

For f(x) = (1/2) x^T Q x - b^T x with Q symmetric positive definite, the
gradient Q x - b is L-Lipschitz with L = largest eigenvalue of Q. The lesson
proves that gradient descent with step 1/L satisfies
    f(x_k) - f* <= L |x_0 - x*|^2 / (2k),
and for a quadratic with smallest eigenvalue mu > 0 the gap even shrinks
geometrically, at least as fast as (1 - mu/L)^(2k) times the initial gap
(stopped at k = 20, before rounding errors of size 1e-16 dominate). The program compares both bounds with the
actual gaps, shows what happens for step sizes 1/L, 1.9/L and 2.1/L, shows
Newton's method finishing in one step on a quadratic, and fits a straight line
to noisy data by gradient descent on the mean squared error, comparing the
result with the exact normal-equations solution.

Floating-point (numerical) evidence about specific problems.
"""

import numpy as np

Q = np.array([[3.0, 2.0], [2.0, 6.0]])
B = np.array([1.0, -2.0])
X0 = np.array([4.0, 3.0])

def f(x):
    """The quadratic (1/2) x^T Q x - b^T x."""
    return 0.5 * x @ Q @ x - B @ x

def grad(x):
    return Q @ x - B

def gradient_descent(x0, step, iters, gradient=grad):
    """Iterates x_{k+1} = x_k - step * gradient(x_k); returns all iterates."""
    xs = [np.array(x0, dtype=float)]
    for _ in range(iters):
        xs.append(xs[-1] - step * gradient(xs[-1]))
    return xs

def newton_step(x):
    """One Newton step x - Q^{-1} grad(x) for the quadratic."""
    return x - np.linalg.solve(Q, grad(x))

def line_data(seed, n=40):
    """Noisy samples of y = 2x + 1 for x in [0, 1]."""
    rng = np.random.default_rng(seed)
    x = np.linspace(0, 1, n)
    return x, 2 * x + 1 + 0.1 * rng.standard_normal(n)

def fit_line_gd(x, y, iters):
    """Least-squares line by gradient descent on the mean squared error."""
    a = np.column_stack([x, np.ones_like(x)])
    lip = 2 * np.linalg.eigvalsh(a.T @ a / len(x)).max()

    def g(w):
        return 2 * a.T @ (a @ w - y) / len(x)

    return gradient_descent(np.zeros(2), 1 / lip, iters, g)[-1]

def main():
    mu, lip = np.linalg.eigvalsh(Q)
    xstar = np.linalg.solve(Q, B)
    fstar = f(xstar)
    r2 = np.sum((X0 - xstar) ** 2)
    print(f"f(x) = x^T Q x / 2 - b^T x with eigenvalues mu = {mu:.0f},"
          f" L = {lip:.0f}")
    print("   k   gap f(x_k) - f*   bound L|x0-x*|^2/(2k)   (1-mu/L)^(2k) gap0")
    xs = gradient_descent(X0, 1 / lip, 100)
    for k in (1, 2, 5, 10, 20):
        gap = f(xs[k]) - fstar
        print(f"{k:4d}   {gap:14.3e}   {lip * r2 / (2 * k):21.3e}"
              f"   {(1 - mu / lip) ** (2 * k) * (f(X0) - fstar):17.3e}")
    print()
    print("step size   gap after 50 steps")
    for factor in (1.0, 1.9, 2.1):
        gap = f(gradient_descent(X0, factor / lip, 50)[-1]) - fstar
        print(f"{factor:.1f}/L      {gap:12.3e}")
    print()
    print("Newton: one step from x0 lands at x* with error",
          f"{np.abs(newton_step(X0) - xstar).max():.1e}")
    x, y = line_data(2024)
    a = np.column_stack([x, np.ones_like(x)])
    exact = np.linalg.solve(a.T @ a, a.T @ y)
    w = fit_line_gd(x, y, 2000)
    print(f"line fit: normal equations slope {exact[0]:.4f}, intercept"
          f" {exact[1]:.4f}")
    print(f"          gradient descent  slope {w[0]:.4f}, intercept"
          f" {w[1]:.4f}")
    print()
    print("Epistemic status: floating-point computations on specific problems.\n"
          "They illustrate the O(1/k) theorem (proved in the lesson and in\n"
          "Lean, from the descent and convexity inequalities) and the\n"
          "divergence for steps above 2/L; they do not prove them.")

if __name__ == "__main__":
    main()
Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

The first program is exact for its problems. The second is floating-point evidence: it illustrates the theorems but does not prove them, and its gaps stop shrinking at about 10−1610^{-16}, the limit of double-precision arithmetic.

Explore

Explore: corners, step sizes and false valleys

The three constraint lines of the workshop problem bound the feasible pentagon (the corners are marked). The fourth line is the profit level 3x+5y=c3x + 5y = c. Increase cc: the line moves up and to the right, and the last corner of the pentagon it touches is the optimum (2,6)(2, 6), at c=36c = 36.

Sliding the profit line across the feasible region

A point moves along the curve as t changes: x and y are both functions of t.

(0, 0)(4, 0)(4, 3)(2, 6)(0, 6)
  • x = 4 (workshop A)
  • 2y = 12 (workshop B)
  • 3x + 2y = 18 (workshop C)
  • profit 3x + 5y = c
  • (4, 0.375)
  • (0.375, 6)
  • (0.375, 8.438)
  • (0.375, 3.775)

Gradient descent on f(x)=(x−1)2f(x) = (x - 1)^2 (so L=2L = 2) is the iteration x↦x−2h(x−1)x \mapsto x - 2h(x - 1). In the cobweb diagram, try h=0.25h = 0.25 (steady convergence), h=0.5=1/Lh = 0.5 = 1/L (one step, like Newton), h=0.9h = 0.9 (oscillating convergence) and h=1.05>2/Lh = 1.05 > 2/L (divergence).

Gradient descent as an iteration: the step size decides

Feed each output back in: xₖ₊₁ = f(xₖ). The cobweb diagram shows where the orbit goes.

f(x) =
x₀

Iterates xₖ against k

  • y = f(x)
  • y = x
  • cobweb path

Last iterates: x28 = 1, x29 = 1, x30 = 1

The orbit appears to settle at a fixed point x* ≈ 1.

Fixed points in view (numerical): x* = 1 (attracting: |f′(x*)| < 1)

Based on 3,000 iterations in floating-point arithmetic: numerical evidence, not proof.

A non-convex landscape: the gradient flow x˙=−∇f\dot{\mathbf x} = -\nabla f of the double well f(x,y)=(x2−1)2+y2f(x, y) = (x^2 - 1)^2 + y^2 has two sinks at (±1,0)(\pm 1, 0) and a saddle at the origin, also a critical point but not a minimum. Start trajectories near the yy-axis and watch them choose a valley.

Gradient flow of a double well: two minima and a saddle

Arrows show where the system moves next. Click to start a trajectory, or choose an example.

Examples

x′ = −4·x·(x² − 1), y′ = −2·y

darker, longer arrows = faster forward in time backward in timeequilibrium (hollow = stable or centre)

Click the plane to start a trajectory, or type a start point below.

Start point

Trajectories: 4. They are numerical approximations (fourth-order Runge–Kutta), not exact formulas.

Nonlinear system. Equilibria found numerically in this window, classified by their linearisation (Jacobian matrix):

  1. 1. (−1, 0): stable node (λ = −8, −2)
  2. 2. (0, 0): saddle (unstable) (λ = −2, 4)
  3. 3. (1, 0): stable node (λ = −8, −2)
TDD = T²/41, 32
Trace T and determinant D: below the T-axis, saddles; above the dashed parabola D = T²/4, spirals; between them, nodes; on the upper D-axis, centres. Left of the D-axis is stable, right is unstable.
Exercises

Exercises

1. Optimisation

Warm-upHuman

Maximise 2x+y2x + y subject to x+y≤4x + y \le 4, x≤3x \le 3, x,y≥0x, y \ge 0. What is the optimal value?

2. Optimisation

Warm-upHuman

Which of these functions R→R\mathbb{R} \to \mathbb{R} are convex? (Choose all that apply.)

Choose all that apply

3. Optimisation

CoreHuman

In the workshop problem (max⁡3x+5y\max 3x + 5y subject to x≤4x \le 4, 2y≤122y \le 12, 3x+2y≤183x + 2y \le 18, x,y≥0x, y \ge 0) the optimal dual solution is y=(0,32,1)y = (0, \tfrac32, 1). By how much does the maximum profit increase if workshop C gets one extra hour (so 3x+2y≤193x + 2y \le 19)?

4. Optimisation

CoreHuman

In the proof of weak duality, cTx≤(ATy)Tx=yT(Ax)≤yTbc^{\mathsf T}x \le (A^{\mathsf T}y)^{\mathsf T}x = y^{\mathsf T}(Ax) \le y^{\mathsf T}b. Which hypotheses justify the last inequality yT(Ax)≤yTby^{\mathsf T}(Ax) \le y^{\mathsf T}b?

Choose one

5. Optimisation

CoreHuman

Minimise (x−3)2+(y−1)2(x - 3)^2 + (y - 1)^2 subject to x+y≤2x + y \le 2. Which point is the minimiser?

Choose one

6. Optimisation

CoreFormal

The Lean theorem local_min_convex_global assumes hf : ConvexOn ℝ Set.univ f and hx : IsLocalMin f x and concludes f x ≤ f y. Which function and point show that the convexity hypothesis hf cannot be dropped?

Choose one

7. Optimisation

StretchHuman

Gradient descent with step 1/L1/L is run on a convex LL-smooth function with L=4L = 4, starting at distance ∥x0−x∗∥=3\|x_0 - x^*\| = 3 from a minimiser. Using Theorem 9, what is the smallest number of steps kk that guarantees f(xk)−f(x∗)≤0.01f(x_k) - f(x^*) \le 0.01?

8. Optimisation

StretchComputational

Write gradient_descent(grad, x0, step, iters) that applies x↦x−step⋅grad(x)x \mapsto x - \text{step} \cdot \text{grad}(x) to a number x0 iters times and returns the final value. Then use it on f(x)=2(x−3)2f(x) = 2(x - 3)^2, whose gradient is 4(x−3)4(x - 3) (so L=4L = 4), and observe that steps below 2/L=0.52/L = 0.5 converge while larger steps diverge.

Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.
Common misconceptionsH

Common misconceptions

Misconception

"Every critical point is a minimum." ∇f(x)=0\nabla f(x) = 0 is necessary for an unconstrained interior minimum, not sufficient: x3x^3 at 00 is an inflection point, −x2-x^2 has a maximum, and x2−y2x^2 - y^2 (or the double well's origin) has a saddle. For convex functions every critical point is a global minimum (Theorem 6), which is one reason convexity is so valuable.

Misconception

"Every linear program has an optimal solution." An LP may be infeasible (constraints x≤0x \le 0 and x≥1x \ge 1) or unbounded (max⁡x+y\max x + y subject to x−y≤1x - y \le 1). What is true: a feasible LP with bounded objective attains its optimum, and by Corollary 2(c) the primal is unbounded only if the dual is infeasible.

Misconception

"The optimum of an LP is always a single corner." If the objective is parallel to an edge of the feasible region, the whole edge is optimal (the set of optimal solutions is convex, by Theorem 5). What is guaranteed is that some optimal solution is a vertex, when the region has vertices.

Misconception

"A bigger step makes gradient descent faster." For an LL-smooth function, steps larger than 2/L2/L can make the iterates diverge — the quadratic L2x2\frac L2x^2 already shows it — and steps near 2/L2/L oscillate. The safe default 1/L1/L is what Theorem 9 analyses. When LL is unknown, line searches or adaptive step sizes are used.

Misconception

"Lagrange's condition ∇f=λ∇h\nabla f = \lambda\nabla h identifies the minimum." It is necessary (given a constraint qualification), not sufficient: it also holds at constrained maxima and saddle points. Sufficiency needs convexity (Theorem 7(a)) or second-order conditions. Conversely, without a constraint qualification a minimiser may have no multipliers at all, as the example min⁡x\min x subject to x2≤0x^2 \le 0 shows.

ViewpointsH

Many ways of seeing

Geometry— Polyhedra, supporting hyperplanes and duality

A linear program lives on a convex polyhedron, and its optimum is where a hyperplane of constant objective supports the polyhedron: it touches the polyhedron, which lies entirely on one side. The Minkowski–Weyl theorem says that bounded polyhedra are exactly convex hulls of finitely many points, which is why optimising a linear function reduces to checking vertices. LP duality is a statement about separating and supporting hyperplanes (the proof of Farkas' lemma constructs one by projecting onto a convex cone), and in convex geometry the dual of a polytope containing the origin is its polar, with vertices and facets exchanged. The simplex method walks along the edge graph of the polyhedron. Whether that graph always has diameter polynomial in the number of facets is the polynomial Hirsch conjecture, still open; the original Hirsch conjecture was disproved by Francisco Santos in 2010.

Analysis— Convex analysis and Fenchel duality

The Legendre–Fenchel transform f∗(p)=sup⁡x(p⋅x−f(x))f^*(p) = \sup_x (p \cdot x - f(x)) turns a convex function into another one, and f∗∗=ff^{**} = f for closed convex ff (Fenchel–Moreau). Weak and strong LP duality are special cases of Fenchel–Rockafellar duality, inf⁡x(f(x)+g(Ax))=sup⁡y(−f∗(ATy)−g∗(−y))\inf_x (f(x) + g(Ax)) = \sup_y(-f^*(A^{\mathsf T}y) - g^*(-y)) under a constraint qualification. Non-differentiable convex functions such as ∣x∣|x| or max⁡iai⋅x\max_i a_i \cdot x have subgradients instead of gradients, and 0∈∂f(x∗)0 \in \partial f(x^*) characterises their minima. In infinite dimensions, existence of minimisers rests on compactness (often weak compactness) and lower semicontinuity — the "direct method" of the calculus of variations. See functional analysis.

Topology— Critical points and the shape of the landscape

Morse theory relates the critical points of a function to the topology of its domain. As rr increases, the sublevel set {f≤r}\{f \le r\} changes its topology only when rr passes a critical value, and a non-degenerate critical point of index kk attaches a kk-dimensional cell. Consequently a smooth function on a closed surface of genus gg with only non-degenerate critical points has at least 2+2g2 + 2g of them (the Morse inequalities: at least the sum of the Betti numbers), so every such function on a torus has at least four critical points. Saddles are therefore forced by topology, not just bad luck. The double well in the visualisation shows a one-dimensional version: two minima force a saddle between them, a mountain-pass point. See differential topology.

Combinatorics— Integer programs, flows and matchings

Requiring integer solutions makes optimisation much harder: integer linear programming is NP-hard. But for totally unimodular constraint matrices (Hoffman and Kruskal, 1956), such as incidence matrices of bipartite graphs and of directed networks, every vertex of the polyhedron is integral, so the LP solves the integer problem. LP duality then becomes combinatorial min–max theorems: the max-flow min-cut theorem (Ford and Fulkerson, 1956), König's theorem that in a bipartite graph the maximum matching equals the minimum vertex cover, and the assignment problem. In 1962 Kwan Mei-Ko (Guan Meigu) in China posed and solved the "Chinese postman problem" of the shortest closed route covering every street, now solved in general by matching. See graph theory.

Probability— Least squares, likelihood and stochastic gradients

If data satisfy yi=ai⋅w+εiy_i = a_i \cdot w + \varepsilon_i with independent Gaussian errors, maximising the likelihood of ww is exactly minimising ∑(yi−ai⋅w)2\sum (y_i - a_i \cdot w)^2: least squares is maximum likelihood (Gauss's justification, 1809). Other noise models give other convex objectives — Laplace noise gives least absolute deviations, logistic models give the convex log-loss of logistic regression. When the objective is an average over a huge data set, stochastic gradient descent uses the gradient on a random small batch, an unbiased but noisy estimate; with diminishing step sizes it converges in expectation for convex problems (Robbins and Monro, 1951, in the language of stochastic approximation). See statistics.

Physics— Least action, equilibrium and constraint forces

Nature optimises, at least in a mathematical sense. Fermat's principle (light takes the path of least time) gives Snell's law of refraction; mechanical equilibria are critical points of potential energy, stable ones being minima; and the laws of motion follow from making the action stationary (see classical mechanics). Lagrange introduced his multipliers in the Mécanique analytique (1788) for exactly this: a multiplier is the force the constraint must exert. The KKT conditions are the same picture with walls that can push but not pull (so μi≥0\mu_i \ge 0), and that exert no force when not touched (μigi=0\mu_i g_i = 0). Gradient descent is the overdamped motion of a particle sliding downhill through treacle. These are heuristics and models; the theorems above stand on their proofs.

Computation— What can be optimised efficiently

The dividing line in computational optimisation is roughly convex versus non-convex. Linear programs and, more generally, convex problems with efficiently computable constraints (such as semidefinite programs) can be solved to accuracy ε\varepsilon in time polynomial in the size and log⁡(1/ε)\log(1/\varepsilon) by interior-point methods (Nesterov and Nemirovski, 1994). Integer programming, and minimising general non-convex polynomials, are NP-hard. In machine learning, gradient methods on non-convex losses work remarkably well in practice, and why they do is an active research question. For first-order methods on LL-smooth convex functions, Nesterov showed that O(1/k2)O(1/k^2) is the best possible worst-case rate, and his accelerated method attains it. See complexity theory and numerical analysis.

History & global context

History and global context

  • Calculus of extremes. Pierre de Fermat's method of adequality (1630s) found maxima and minima by what we would call setting the derivative to zero, and his principle of least time explained refraction. Joseph-Louis Lagrange introduced multipliers for constrained problems in his Mécanique analytique (1788). Augustin-Louis Cauchy proposed the method of steepest descent in 1847, for solving systems of equations from astronomy.
  • Inequalities. Joseph Fourier studied systems of linear inequalities in the 1820s (Fourier–Motzkin elimination), and Gyula Farkas proved his lemma around 1894–1902 in Kolozsvár (now Cluj-Napoca).
  • Linear programming. Leonid Kantorovich formulated linear programming and its dual valuations in Leningrad in 1939; he shared the 1975 Nobel prize in economics with Tjalling Koopmans for the theory of optimal allocation of resources. In the United States George Dantzig invented the simplex method in 1947, and John von Neumann, who had proved the minimax theorem for games in 1928, recognised LP duality the same year. George Stigler's "diet problem" (1945) was one of the first LPs solved by computation.
  • Nonlinear and convex optimisation. William Karush (1939, master's thesis, Chicago) and Harold Kuhn and Albert Tucker (1951) gave the conditions now named after them. Werner Fenchel and R. Tyrrell Rockafellar (Convex Analysis, 1970) built convex duality theory.
  • Algorithms. Leonid Khachiyan (Moscow, 1979) proved LPs solvable in polynomial time with the ellipsoid method. Narendra Karmarkar, born in Gwalior, India, introduced a practical polynomial-time interior-point method at Bell Labs in 1984, and Yurii Nesterov (1983) found the accelerated gradient method. Kwan Mei-Ko's 1962 Chinese postman problem is an early landmark of combinatorial optimisation.
Further reading

Further reading

  • Stephen Boyd and Lieven Vandenberghe, Convex Optimization (2004) — convex sets, functions, duality and KKT, with many applications (freely available from the authors).
  • Jorge Nocedal and Stephen J. Wright, Numerical Optimization (1999; 2nd ed. 2006) — gradient, Newton and quasi-Newton methods, KKT theory and constraint qualifications.
  • Jiří Matoušek and Bernd Gärtner, Understanding and Using Linear Programming (2007) — a lively account of LP, the simplex method, duality and Farkas' lemma.
  • Dimitris Bertsimas and John N. Tsitsiklis, Introduction to Linear Optimization (1997).
  • Yurii Nesterov, Introductory Lectures on Convex Optimization (2004; 2nd ed. Lectures on Convex Optimization, 2018) — complexity of first-order methods and acceleration.
  • Vašek Chvátal, Linear Programming (1983) — a classic, with combinatorial applications.