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.
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.
Definitions
Definition— optimisation problem, local and global minimum
An optimisation problem asks for , where is the objective and the feasible set (maximising is minimising ). A point is a global minimiser if for all , and a local minimiser if this holds for all in some ball around . The problem is infeasible if and unbounded if .
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
with an matrix and inequalities between vectors meant entry by entry. A vertex of the feasible polyhedron is a feasible point at which linearly independent constraints are tight.
Definition— convex set, convex function
A set is convex if whenever and . A function on a convex set is convex if
strictly convex if the inequality is strict for and , and -strongly convex if is convex. A differentiable is -smooth if its gradient is -Lipschitz: .
Definition— Lagrangian and KKT conditions
For the problem subject to () and (), with differentiable functions, the Lagrangian is . A point with multipliers satisfies the Karush–Kuhn–Tucker (KKT) conditions if
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 iterates . Newton's method iterates , using the Hessian matrix .
Examples and non-examples
Example— A production problem, solved by looking
The Kumasi workshop makes units of product 1 and of product 2, using hour of workshop A and of workshop C per unit of product 1, and hours of B and of C per unit of product 2. A, B and C have , and hours a week, and the profits are and per unit:
The feasible region is a pentagon with vertices , , , , , where the objective takes the values . The optimum is , with profit : workshops B and C are fully used, while A has hours to spare. (The visualisation lets you slide the profit line.)
Example— LPs without optimal solutions
subject to and is infeasible. subject to , is unbounded: is feasible for every , with objective . 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, , , and every norm, on , the maximum of finitely many convex functions, and . Convex sets: half-spaces , balls, polyhedra (intersections of finitely many half-spaces), and sublevel sets of convex functions. Not convex: , , the double well (with two global minima and a local maximum at ), and the annulus . Note that is convex but not differentiable at its minimum.
Example— A constrained minimum, by KKT
Minimise — the squared distance to — subject to . The unconstrained minimiser is infeasible, so the constraint will be tight. KKT: gives , and gives , so with minimum value . The multiplier is the rate at which the optimal value would fall if the constraint were relaxed to (it becomes ).
Linear programming and duality
Theorem— Theorem 1 (weak duality)
If is feasible for (P) and is feasible for (D), then .
Proof
Using with , and then with :
∎
Theorem— Corollary 2 (certificates and complementary slackness)
(a) If feasible and have , both are optimal. (b) In that case for every and for every . (c) If (P) is unbounded, (D) is infeasible, and vice versa.
Proof
(a) Every feasible has , and symmetrically for . (b) Equality of the ends of the chain in Theorem 1 forces both inequalities to be equalities: and . These are sums of non-negative products, so every product vanishes. (c) A dual-feasible would bound every primal value by .
∎
Theorem— Theorem 3 (Farkas' lemma)
For a matrix and vector , exactly one of the following holds: (i) for some ; (ii) there is with and .
Proof
Not both: otherwise . Suppose (i) fails, so . The cone is convex, and it is closed (a finitely generated cone is closed; this follows from Carathéodory's theorem, which writes each point of using linearly independent columns of ). Let be the point of nearest to (it exists since is closed), and put . For and , the point is in and is no closer to ; expanding and letting gives . Taking and gives , so for all — in particular — and .
∎
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 be the optimal value of (P) and . The system , , has no solution. Adding slack variables and applying Farkas' lemma gives and with and . Here , since would contradict the feasibility of (P) by Theorem 1. Then is dual feasible with value below . Since was arbitrary and Theorem 1 gives the reverse inequality, ; 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 : one more hour in workshop B would raise the maximum profit by , one more in C by , and one more in A by nothing, since A already has slack (complementary slackness). Check: . These shadow prices are Kantorovich's "objectively determined valuations".
The simplex method. An LP in inequality form with starts at the vertex . 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.
Convexity: local is global
Theorem— Theorem 5 (local minima of convex functions are global)
Let be convex on a convex set . Every local minimiser of on is a global minimiser. The set of minimisers is convex, and if is strictly convex there is at most one.
Proof
Let be a local minimiser and . For the point lies in , and for small enough it lies in the ball where is minimal. Then
so , and dividing by gives . The minimisers form the sublevel set , which is convex. If were both minimisers of a strictly convex , their midpoint would have .
∎
Theorem— Theorem 6 (first-order characterisation)
A differentiable on a convex open set is convex if and only if for all . Consequently, for convex differentiable on , if and only if is a global minimiser.
Proof
If is convex, for , by the definition with weights and ; letting the left side tends to . Conversely, given the inequality, put and add times the inequality at to times the inequality at : the gradient terms cancel and leave . The consequence: if the inequality gives for all .
∎
A twice-differentiable is convex exactly when its Hessian is positive semidefinite everywhere (by Theorem 6 applied along lines). Without convexity none of this holds: has but no minimum, and has a saddle at the origin.
Lagrange multipliers and the KKT conditions
From multivariable calculus: if is a local minimiser of subject to and , then for some , because the gradient of must be perpendicular to the constraint surface. For example, the point of the plane closest to the origin satisfies , so . Convexity turns this necessary condition into a proof of optimality: is orthogonal to for every feasible , so . (This is the Lean theorem least_norm.)
Theorem— Theorem 7 (KKT conditions)
Consider subject to and , with continuously differentiable functions.
(a) Sufficiency. If and every are convex, every is affine, and satisfies the KKT conditions, then is a global minimiser.
(b) Necessity. If is a local minimiser and a constraint qualification holds at — for example, the gradients of the tight constraints are linearly independent, or (for convex problems) some point satisfies all strictly (Slater's condition) — then there are multipliers making the KKT conditions hold.
Proof
(a) Let be feasible. By Theorem 6 for and the KKT equation,
Since is affine, . By Theorem 6 for , , and with and we get . So .
(b) Sketch. Under linear independence of the active gradients, a first-order feasible direction that decreased could be followed along a curve of feasible points (implicit function theorem). So no such exists, and Farkas' lemma converts "no improving feasible direction" into the existence of and . 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 subject to . The only feasible point is , but for every .
Gradient descent: a convergence proof
Theorem— Lemma 8 (descent lemma)
If is -Lipschitz, then . In particular, the step gives .
Proof
By the fundamental theorem of calculus along the segment and Cauchy–Schwarz,
For , the right-hand side becomes .
∎
Theorem— Theorem 9 (rate of gradient descent)
Let be convex and -smooth with a minimiser , and let . Then for every ,
Proof
Write . By Lemma 8, ; in particular the values decrease. By Theorem 6, . Combining,
where the equality is the expansion of . Summing over , the right-hand side telescopes to at most . Since the values decrease, the left-hand sum is at least .
∎
Three remarks. Step size. For the iteration is , which converges exactly when . Larger steps overshoot and diverge, as the experiment and the cobweb diagram show. Strong convexity. If is also -strongly convex, the gap shrinks geometrically, like . The ratio , the condition number, governs the speed. Faster methods. Nesterov's accelerated gradient method (1983) achieves , 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 to data by least squares means minimising , which is convex with gradient . By Theorem 6 its minimisers are exactly the solutions of the normal equations , unique when has independent columns. Geometrically is the orthogonal projection of onto the column space of . For huge data sets one runs (stochastic) gradient descent on instead of solving the normal equations, and the second experiment checks that both give the same line.
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 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 _ _/-- **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/-- **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]
linarithTheorem 5, proved along the segment as above, then the one-line Mathlib version, and convexity of sublevel sets:
/-- **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/-- 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/-- **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 rThe least-norm problem solved by the Lagrange condition, with Pythagoras as the certificate:
/-- **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‖]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 with and deduces its rate.
/-- **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/-- **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 keyWhat 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.
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 ; with Bland's rule it takes the longer route . It then reads the shadow prices from the final tableau, checks strong duality and complementary slackness exactly, and detects an unbounded problem.
"""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()The second program runs gradient descent on a convex quadratic with and . It compares the gap with the 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 still converges while 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 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()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 , the limit of double-precision arithmetic.
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 . Increase : the line moves up and to the right, and the last corner of the pentagon it touches is the optimum , at .
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.
- 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 (so ) is the iteration . In the cobweb diagram, try (steady convergence), (one step, like Newton), (oscillating convergence) and (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.
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 of the double well has two sinks at and a saddle at the origin, also a critical point but not a minimum. Start trajectories near the -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.
x′ = −4·x·(x² − 1), y′ = −2·y
Click the plane to start a trajectory, or type a start point below.
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, 0): stable node (λ = −8, −2)
- 2. (0, 0): saddle (unstable) (λ = −2, 4)
- 3. (1, 0): stable node (λ = −8, −2)
Exercises
1. Optimisation
Warm-upHumanMaximise subject to , , . What is the optimal value?
2. Optimisation
Warm-upHumanWhich of these functions are convex? (Choose all that apply.)
3. Optimisation
CoreHumanIn the workshop problem ( subject to , , , ) the optimal dual solution is . By how much does the maximum profit increase if workshop C gets one extra hour (so )?
4. Optimisation
CoreHumanIn the proof of weak duality, . Which hypotheses justify the last inequality ?
5. Optimisation
CoreHumanMinimise subject to . Which point is the minimiser?
6. Optimisation
CoreFormalThe 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?
7. Optimisation
StretchHumanGradient descent with step is run on a convex -smooth function with , starting at distance from a minimiser. Using Theorem 9, what is the smallest number of steps that guarantees ?
8. Optimisation
StretchComputationalWrite gradient_descent(grad, x0, step, iters) that applies to a number x0 iters times and returns the final value. Then use it on , whose gradient is (so ), and observe that steps below converge while larger steps diverge.
Common misconceptions
Misconception
"Every critical point is a minimum." is necessary for an unconstrained interior minimum, not sufficient: at is an inflection point, has a maximum, and (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 and ) or unbounded ( subject to ). 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 -smooth function, steps larger than can make the iterates diverge — the quadratic already shows it — and steps near oscillate. The safe default is what Theorem 9 analyses. When is unknown, line searches or adaptive step sizes are used.
Misconception
"Lagrange's condition 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 subject to shows.
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 turns a convex function into another one, and for closed convex (Fenchel–Moreau). Weak and strong LP duality are special cases of Fenchel–Rockafellar duality, under a constraint qualification. Non-differentiable convex functions such as or have subgradients instead of gradients, and 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 increases, the sublevel set changes its topology only when passes a critical value, and a non-degenerate critical point of index attaches a -dimensional cell. Consequently a smooth function on a closed surface of genus with only non-degenerate critical points has at least 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 with independent Gaussian errors, maximising the likelihood of is exactly minimising : 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 ), and that exert no force when not touched (). 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 in time polynomial in the size and 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 -smooth convex functions, Nesterov showed that is the best possible worst-case rate, and his accelerated method attains it. See complexity theory and numerical analysis.
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
- 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.