Constrained Optimization and Lagrange Multipliers
Everything so far assumed the answer could be anywhere. It usually cannot. A probability must stay in , a portfolio’s weights must sum to one, an SVM’s margin variables must stay non-negative (Chapter 12). So:
The trouble is that gradient descent has no idea what a constraint is. This page is the standard way to teach it one, and the move is smaller than it looks: replace an infinite wall with a slope.
What you’ll learn
Section titled “What you’ll learn”- Equations 7.18 and 7.19: the indicator-function reformulation, which is exactly correct and completely unoptimisable — measured, its gradient is undefined everywhere outside the feasible set.
- Equation 7.20, the Lagrangian, and why a linear penalty is the right relaxation.
- Definition 7.1: the primal problem, the dual problem, and .
- The minimax inequality (Equation 7.23) with a worked case where the gap is exactly , so you can see it is an inequality rather than an identity.
- Weak duality (Equation 7.27), and why the dual is always concave even when the primal is a mess.
- Measured on the book’s Example 7.6: , duality gap exactly zero, and complementary slackness holding to machine precision.
- Measured on a nonconvex problem: a duality gap of 1.984123, with the dual’s optimum attained at , a point the primal forbids.
- Equation 7.28: how equality constraints fold in, and why their multipliers come out unconstrained.
Intuition: a wall you can feel, or a wall you cannot
Section titled “Intuition: a wall you can feel, or a wall you cannot”You are minimising altitude, and there is a fence.
The naive fix is to declare the far side of the fence infinitely high. That is honest — you will never end up there — but it is useless to a hiker in fog. Step over the fence and everything reads “infinitely high”, in every direction. Nothing tells you which way to go back.
The Lagrangian fix is to charge rent instead. Crossing the fence by one metre costs altitude-units. Now the far side is still discouraging, but it has a slope, and a slope is the one thing a gradient method can use. Better still, you get to pick : too small and the optimum sits outside the fence, too large and it hugs the fence unnecessarily. Somewhere in between is a price at which the unconstrained optimum of the rented landscape lands exactly on the fence — and that price is .
flowchart TD P["primal, Eq 7.17
min f subject to g <= 0"] P --> I["Eq 7.18: add an indicator
J = f + sum of 1(g_i)"] I --> BAD["exactly equivalent
but +infinity everywhere outside:
no gradient, no method"] P --> LAG["Eq 7.20: add lambda-transpose g
a LINEAR penalty"] LAG --> SMOOTH["smooth in x for fixed lambda,
and a lower bound for lambda >= 0"] SMOOTH --> D["Eq 7.22: the dual
max over lambda of min over x"] D --> CONC["always CONCAVE in lambda,
however ugly f and g are"] CONC --> W["Eq 7.27: weak duality
d-star <= p-star, always"] W --> S["convex primal: gap is ZERO
Section 7.3"] W --> G["nonconvex primal: gap can be real
measured 1.984123"]
The math
Section titled “The math”First attempt: an indicator function
Section titled “First attempt: an indicator function”Turn the constraint into a penalty that is free when satisfied and unbearable when not:
Minimising over all of gives exactly the constrained answer, because any infeasible point scores . So this reformulation is correct. It is also, in the book’s words, “equally difficult to optimize”, and it is worth being precise about why: the penalty is not merely steep, it is flat at infinity. Every infeasible point looks identical to every other one, so a gradient computed out there is undefined and carries no information about the direction of the feasible set. There is nothing to descend.
Second attempt: charge linearly
Section titled “Second attempt: charge linearly”Introduce Lagrange multipliers , one per inequality, and replace the step function with a linear function:
stacking the constraints into and the multipliers into .
Two properties, and everything else on this page follows from them:
- For and feasible, . Each and each , so every term in the sum is non-positive. The Lagrangian under-estimates the objective on the feasible set.
- Taking the maximum over recovers the indicator exactly. If is feasible, the best you can do is set and get . If some , push that and the supremum is . The infinite step function has been reconstructed as a maximum of linear functions, which is the actual trick.
So the original problem is
Definition 7.1: primal and dual
Section titled “Definition 7.1: primal and dual”The primal problem is the one we started with, in the variables . Its Lagrangian dual problem is
Duality in general means converting a problem in one set of variables into a problem in another. Note what has been traded: the primal has variables and constraints; the dual has variables and the single requirement . If that is a bargain, and §7.3.1 makes the choice explicit for linear programs.
The minimax inequality
Section titled “The minimax inequality”For any function of two arguments,
Maximin is at most minimax. The proof is two lines. Start from the observation that for all ,
The left side does not depend on and the right side does not depend on , so take the maximum over on the left — legitimate, since the inequality holds for every — and the minimum over on the right. The inequality survives both, giving the result.
The intuition worth keeping: the player who moves second has the advantage. On the minimax side sees before choosing; on the maximin side sees . Whoever reacts does at least as well.
Weak duality
Section titled “Weak duality”Apply that to the Lagrangian:
The left side is the primal optimum ; the right side is the dual optimum . So , always — that is weak duality, and it means any dual feasible hands you a certified lower bound on the primal answer, for free.
Equality constraints
Section titled “Equality constraints”Each equality splits into the pair and . Both get non-negative multipliers, say and , and their contribution is . The difference of two non-negative numbers is an arbitrary real number, so:
Inequality multipliers are constrained to be non-negative; equality multipliers are unconstrained. That asymmetry is not a convention, it is a consequence — and it is a fast way to check that you have written a Lagrangian correctly.
Worked example by hand
Section titled “Worked example by hand”The book’s Example 7.6, which is also its Figure 7.4:
subject to and , written in the standard form with
Step 1: ignore the constraints. With the gradient is , zero at . Since ,
with . This point is infeasible: violates by .
Step 2: the constraint must bind. Since the objective is a strictly convex bowl and its centre lies outside the box, the constrained optimum sits on the boundary — on the face nearest the centre, which is . Substituting:
A one-variable quadratic. Its derivative vanishes at , comfortably inside , giving
So the constraint costs in objective value.
Step 3: read off the multipliers. At a constrained optimum the stationarity condition is .
Only the second row of (the constraint ) is active, and . So we need :
Notice that the second component of came out exactly zero. That is not luck: is interior, so no constraint pushes on it, so must already be flat in that direction. Constrained optimality is “flat where you are free, pushed where you are pinned”.
Step 4: complementary slackness. For each , either or :
| constraint | product | status | |||
|---|---|---|---|---|---|
| 1 | slack | ||||
| 2 | active | ||||
| 3 | slack | ||||
| 4 | slack |
A multiplier is the price of a constraint. A constraint that is not binding is free.
See it move
Section titled “See it move”The single most useful thing to feel here is as a price. Drag it and watch the unconstrained minimiser of the Lagrangian walk toward the boundary; the price at which it arrives is .
A second sketch, for the fact that surprises people: the dual of a nonconvex problem is still concave and still gives a bound, but the bound need not be tight.
From scratch
Section titled “From scratch”import numpy as np
# The book's Example 7.6, which is also its Figure 7.4.
Q = np.array([[2.0, 1.0], [1.0, 4.0]])
c = np.array([5.0, 3.0])
A = np.array([[1.0, 0.0], [-1.0, 0.0], [0.0, 1.0], [0.0, -1.0]])
b = np.ones(4) # the box -1 <= x_i <= 1
def f(x):
return 0.5 * x @ Q @ x + c @ x
def g(x):
return A @ x - b # feasible means every entry <= 0
# --- Equation 7.18: correct, and impossible to descend ---------------------
def J(x):
return f(x) if np.all(g(x) <= 0) else np.inf
x_unc = np.linalg.solve(Q, -c)
print(f"unconstrained minimiser (-17/7, -1/7) = "
f"[{x_unc[0]:.6f}, {x_unc[1]:.6f}] f = {f(x_unc):.6f}")
print(f"feasible? {np.all(g(x_unc) <= 0)} worst violation "
f"{g(x_unc).max():+.6f}")
print(f"J at that point = {J(x_unc)}")
h = 1e-6
for probe in (np.array([-1.5, -0.5]), np.array([-3.0, -0.5])):
fd = []
for d in range(2):
e = np.zeros(2); e[d] = h
num = J(probe + e) - J(probe - e)
fd.append("undefined" if not np.isfinite(num) else f"{num / (2*h):+.4f}")
print(f" finite-difference grad of J at {probe.tolist()}: ({fd[0]}, {fd[1]})")
print(" -> outside the box every direction looks identical. No slope to follow.")
# --- Equation 7.20: the Lagrangian ---------------------------------------
def L(x, lam):
return f(x) + lam @ g(x)
def D(lam):
"""min over x of L. For a positive definite Q this is closed form."""
v = c + A.T @ lam
xs = np.linalg.solve(Q, -v)
return 0.5 * xs @ Q @ xs + v @ xs - lam @ b, xs
x_con = np.array([-1.0, -0.5]) # solved by hand on the x1 = -1 edge
print(f"\nconstrained optimum [{x_con[0]}, {x_con[1]}] f = {f(x_con):.6f}")
print(f"the constraint costs {f(x_con) - f(x_unc):.6f}")
print("\nfor lambda >= 0 the Lagrangian is a LOWER BOUND at any feasible x:")
for lam in (np.zeros(4), np.array([0.0, 1.0, 0.0, 0.0]), np.full(4, 0.5)):
print(f" lambda = {lam.tolist()} L = {L(x_con, lam):+.6f} "
f"<= f = {f(x_con):+.6f}: {L(x_con, lam) <= f(x_con) + 1e-12}")
# --- the dual, maximised over the one coordinate that matters ------------
ts = np.linspace(0.0, 6.0, 60001)
dv = np.array([D(np.array([0.0, t, 0.0, 0.0]))[0] for t in ts])
k = int(np.argmax(dv))
lam_star = np.array([0.0, ts[k], 0.0, 0.0])
dstar, x_from_dual = D(lam_star)
print(f"\nlambda* = {np.round(lam_star, 6).tolist()}")
print(f"d* = {dstar:.9f} p* = {f(x_con):.9f} gap = {f(x_con) - dstar:.3e}")
print(f"x recovered from the dual = "
f"[{x_from_dual[0]:.6f}, {x_from_dual[1]:.6f}]")
print("\ncomplementary slackness:")
for i, (l, gi) in enumerate(zip(lam_star, g(x_con))):
print(f" i={i} lambda={l:8.5f} g={gi:+8.5f} product={l * gi:+.1e} "
f"{'ACTIVE' if abs(gi) < 1e-9 else 'slack'}")
print("stationarity ||Qx + c + A^T lambda|| =",
f"{np.linalg.norm(Q @ x_con + c + A.T @ lam_star):.2e}")
# --- weak duality only, on a nonconvex primal ---------------------------
print("\n--- a nonconvex primal keeps a real gap -------------------------")
xs = np.linspace(-4.0, 4.0, 40001)
fn = xs ** 4 - 8.0 * xs ** 2 + xs
gn = -xs # the constraint x >= 0
p_star = fn[gn <= 0].min()
x_p = xs[gn <= 0][int(np.argmin(fn[gn <= 0]))]
lams = np.linspace(0.0, 6.0, 1201)
dn = np.array([(fn + t * gn).min() for t in lams])
kb = int(np.argmax(dn))
x_d = xs[int(np.argmin(fn + lams[kb] * gn))]
print(f"min x^4 - 8x^2 + x subject to x >= 0")
print(f" p* = {p_star:.6f} at x = {x_p:.6f}")
print(f" d* = {dn[kb]:.6f} at lambda = {lams[kb]:.4f}, attained at x = {x_d:.4f}")
print(f" that x is feasible: {x_d >= 0}")
print(f" duality GAP = {p_star - dn[kb]:.6f}")unconstrained minimiser (-17/7, -1/7) = [-2.428571, -0.142857] f = -6.285714
feasible? False worst violation +1.428571
J at that point = inf
finite-difference grad of J at [-1.5, -0.5]: (undefined, undefined)
finite-difference grad of J at [-3.0, -0.5]: (undefined, undefined)
-> outside the box every direction looks identical. No slope to follow.
constrained optimum [-1.0, -0.5] f = -4.500000
the constraint costs 1.785714
for lambda >= 0 the Lagrangian is a LOWER BOUND at any feasible x:
lambda = [0.0, 0.0, 0.0, 0.0] L = -4.500000 <= f = -4.500000: True
lambda = [0.0, 1.0, 0.0, 0.0] L = -4.500000 <= f = -4.500000: True
lambda = [0.5, 0.5, 0.5, 0.5] L = -6.500000 <= f = -4.500000: True
lambda* = [0.0, 2.5, 0.0, 0.0]
d* = -4.500000000 p* = -4.500000000 gap = 0.000e+00
x recovered from the dual = [-1.000000, -0.500000]
complementary slackness:
i=0 lambda= 0.00000 g=-2.00000 product=-0.0e+00 slack
i=1 lambda= 2.50000 g=+0.00000 product=+0.0e+00 ACTIVE
i=2 lambda= 0.00000 g=-1.50000 product=-0.0e+00 slack
i=3 lambda= 0.00000 g=-0.50000 product=-0.0e+00 slack
stationarity ||Qx + c + A^T lambda|| = 0.00e+00
--- a nonconvex primal keeps a real gap -------------------------
min x^4 - 8x^2 + x subject to x >= 0
p* = -14.015877 at x = 1.968000
d* = -16.000000 at lambda = 1.0000, attained at x = -2.0000
that x is feasible: False
duality GAP = 1.984123On real data
Section titled “On real data”Reading the plot
Section titled “Reading the plot”The first figure is the argument of the whole page in three steps. The left panel is Equation 7.18
drawn honestly. Inside the feasible region, is — same curve, same gradient — and note which
way that gradient points: out through the wall, toward the unconstrained minimum at . So a
gradient method started anywhere feasible walks straight at the boundary and then leaves. One step past
it, the value is and the measured finite-difference gradient is undefined in both
coordinates. Not large. Not steep. Undefined, and identically so at and at .
The penalty knows you have broken the rule and cannot tell you how badly.
The middle panel is the repair. Each curve is for a fixed price, and every one of them is a smooth quadratic — differentiable everywhere, no wall anywhere. Watch the marked minimisers move right as grows: at the minimiser is the unconstrained one, and by it has arrived exactly at the boundary. The constraint has been converted from a prohibition into an incentive.
The right panel closes it. rises, peaks, and falls, and its peak touches the dashed line — the measured gap at the peak is , which is my grid resolution rather than a real shortfall. This is strong duality, and §7.3 explains why we were entitled to it: the problem is convex.
The second figure is where constrained optimality stops resembling unconstrained optimality. The red circle is where , and it is not the answer — it lies outside the box by . The green star is the answer, and at the green star the gradient is emphatically not zero: . It points straight out through the left wall with magnitude , and the wall pushes back with force . The condition is a balance of forces, not a vanishing derivative.
The table earns its place through the second component of that gradient: exactly . The variable is interior — nothing is pinning it — so must already be flat along it. That is the general shape of a constrained optimum: flat in the directions you are free to move, pushed in the directions you are pinned. And complementary slackness is the bookkeeping for that: three of four constraints are slack and carry multiplier zero, one is active and carries . A multiplier is a price, and unbinding constraints are free.
The third figure is the one to be careful with, because two of its panels look similar and mean opposite things. The left panel makes the minimax inequality concrete. With on the unit square: for a fixed , the adversary picks the far corner, so , minimised at giving . Going the other way, for a fixed the minimiser just picks and scores , so . Gap exactly . The order of the min and the max is not a formality.
The middle and right panels are the same machinery on two problems, and the difference is convexity. The convex quadratic program’s dual rises to touch — gap , and the recovered from is , the primal answer exactly. Solve either problem and you have solved the other.
The right panel is the same procedure on subject to , and it fails instructively. The primal answer is at , in the right-hand well. The dual’s best is at — and look where it is attained: , in the forbidden left well. At the penalty term cancels the objective’s term exactly, the two wells become symmetric at depth , and the minimisation picks the infeasible one. No price fixes this. Raising tilts the landscape but cannot delete a well; the minimiser jumps between wells rather than sliding, and it is precisely that discontinuity that the concave cannot represent. The gap is , and it is structural: the dual only ever sees the convex envelope of the problem.
Pitfalls
Section titled “Pitfalls”Compare
Section titled “Compare”| indicator, Eq 7.18 | Lagrangian, Eq 7.20 | |
|---|---|---|
| equivalent to the primal | exactly | only after |
| value on an infeasible point | finite | |
| differentiable in | no | yes, wherever and are |
| gradient outside the feasible set | undefined, and uninformative | points back toward feasibility |
| extra variables | none | multipliers |
| usable by a gradient method | no | yes |
| primal | dual | |
|---|---|---|
| variables | ||
| direction | minimise | maximise |
| constraints | of them, | just |
| shape | whatever and are | always concave |
| optimum | ||
| cheaper when | ||
| gap on Example 7.6 | — | |
| gap on the nonconvex quartic | — |
-
Equation 7.18 replaces the constraints with an infinite step function. Why is that not a solution?
The reformulation is exactly correct — that is what makes it tempting. The problem is that it is flat at infinity: measured finite-difference gradients of J came back undefined in both coordinates at x1 = -1.5 and, identically, at x1 = -3.0. The penalty knows you broke the rule and cannot say how badly.
pch.quizShowAnswer
B — Because the penalty is +infinity on the whole infeasible region, so a gradient there is undefined and identical everywhere — there is nothing to descend — The reformulation is exactly correct — that is what makes it tempting. The problem is that it is flat at infinity: measured finite-difference gradients of J came back undefined in both coordinates at x1 = -1.5 and, identically, at x1 = -3.0. The penalty knows you broke the rule and cannot say how badly.
-
At the constrained optimum of Example 7.6, what is the gradient of f?
Constrained optimality is a balance of forces, not a vanishing derivative: grad f + A-transpose lambda = 0. The second component being exactly zero is the tell that x2 is interior — free directions must be flat, pinned directions are pushed.
pch.quizShowAnswer
B — [2.5, 0], pointing out through the active wall and balanced by lambda-2 = 2.5 — Constrained optimality is a balance of forces, not a vanishing derivative: grad f + A-transpose lambda = 0. The second component being exactly zero is the tell that x2 is interior — free directions must be flat, pinned directions are pushed.
-
Why is the dual function D always concave, even for a horrible nonconvex primal?
This is the structural payoff of duality. D is a minimum over x of functions that are each affine in lambda, so concavity is automatic and maximising D is always tractable. Whether the resulting bound is tight is the separate question that convexity answers.
pch.quizShowAnswer
B — Because for each fixed x, L is affine in lambda, and a pointwise minimum of affine functions is concave — This is the structural payoff of duality. D is a minimum over x of functions that are each affine in lambda, so concavity is automatic and maximising D is always tractable. Whether the resulting bound is tight is the separate question that convexity answers.
-
For the nonconvex problem min x^4 - 8x^2 + x subject to x >= 0, the dual optimum is -16 at lambda = 1. Where is it attained?
At lambda = 1 the penalty exactly cancels the objective's +x term, the two wells tie at -16, and the minimisation takes the forbidden one. No price deletes a well, so the minimiser jumps between wells rather than sliding — and that discontinuity is what the concave dual cannot represent. Gap 1.984123.
pch.quizShowAnswer
B — At x = -2, which violates the constraint — the dual picks the infeasible left well — At lambda = 1 the penalty exactly cancels the objective's +x term, the two wells tie at -16, and the minimisation takes the forbidden one. No price deletes a well, so the minimiser jumps between wells rather than sliding — and that discontinuity is what the concave dual cannot represent. Gap 1.984123.
-
How do equality constraints h(x) = 0 fit into this framework?
The two non-negative multipliers appear only through their difference, and a difference of non-negative numbers is an arbitrary real. So the sign constraint on inequality multipliers is a consequence rather than a convention — and clamping an equality multiplier to be non-negative silently converts the equality into a one-sided inequality.
pch.quizShowAnswer
B — Each splits into h <= 0 and -h <= 0, and the difference of their two non-negative multipliers makes the equality multiplier unconstrained — The two non-negative multipliers appear only through their difference, and a difference of non-negative numbers is an arbitrary real. So the sign constraint on inequality multipliers is a consequence rather than a convention — and clamping an equality multiplier to be non-negative silently converts the equality into a one-sided inequality.
🧪 Try It Yourself
Section titled “🧪 Try It Yourself”Exercise 1 – Check feasibility before you trust an optimum
Section titled “Exercise 1 – Check feasibility before you trust an optimum”Exercise 2 – Equation 7.19 has nothing to descend
Section titled “Exercise 2 – Equation 7.19 has nothing to descend”Exercise 3 – The Lagrangian bounds the primal from below
Section titled “Exercise 3 – The Lagrangian bounds the primal from below”Exercise 4 – Solve the dual and read off the multiplier
Section titled “Exercise 4 – Solve the dual and read off the multiplier”Exercise 5 – Weak duality always, strong duality only sometimes
Section titled “Exercise 5 – Weak duality always, strong duality only sometimes”Recall card
Section titled “Recall card”- Equation 7.18 is right and useless. The indicator reformulation gives the correct answer and is +infinity on the whole infeasible region, so its measured gradient is undefined — identically at x1 = -1.5 and at x1 = -3.0. Flat at infinity means nothing to descend.
- Equation 7.20 is the whole idea: replace the infinite step with lambda-transpose g, a linear penalty. Smooth in x for every fixed lambda.
- Two facts do all the work. For non-negative lambda and feasible x, L is at most f, because every term is non-positive. And J(x) is the maximum over non-negative lambda of L, which rebuilds the infinite step as a maximum of linear functions.
- Definition 7.1: the dual is max over lambda >= 0 of D(lambda), where D(lambda) = min over x of L. The primal has d variables and m constraints; the dual has m variables and one sign condition.
- The minimax inequality is strict in general. For phi = (x-y)^2 on the unit square, maximin = 0 and minimax = 1/4. Whoever moves second has the advantage.
- Weak duality, always: the dual optimum never exceeds the primal optimum. Any dual-feasible lambda is a certified lower bound on the primal answer, for free.
- D is always concave, because it is a pointwise minimum of functions affine in lambda — however nonconvex f and the g_i are. That is duality’s structural payoff; tightness is a separate question.
- Example 7.6 measured: unconstrained minimiser (-17/7, -1/7) with f = -6.285714, infeasible by 1.428571. Constrained optimum (-1, -1/2) with f = -4.5, so the constraint costs 1.785714. lambda-star = 2.5 on the single active face, gap exactly zero.
- The gradient does NOT vanish at a constrained optimum. There it is [2.5, 0]: pushed in the pinned direction, flat in the free one. The condition is grad f + A-transpose lambda = 0.
- Complementary slackness: for each i, either g_i = 0 or lambda_i = 0. A multiplier is the PRICE of a constraint, so a slack constraint is free and a big multiplier means expensive, not violated.
- A nonconvex primal keeps a real gap. On min x^4 - 8x^2 + x subject to x >= 0: p* = -14.015877, d* = -16 at lambda = 1, gap 1.984123 — and the dual’s minimiser is x = -2, which the primal forbids. The minimiser JUMPS between wells rather than sliding, and the concave dual cannot represent that.
- Equality multipliers are unconstrained, because h = 0 splits into two inequalities whose two non-negative multipliers enter only as a difference. The sign condition on inequality multipliers is a consequence, not a convention.
Next: the class of problems where the gap is guaranteed to be zero. Convex Sets and Convex Functions
pch.coffeeTagline
pch.coffeeCtapch.feedbackHeading
pch.feedbackSubheading