15. Lagrange multipliers

📖 Reading · 11 min
💡 Every code box below is live — edit it and hit Run.

§10.6 found extrema by searching the entire plane for points where \nabla f=\vec0. Many real optimization problems aren't free to search the whole plane — they need the maximum or minimum of f restricted to a curve, like maximizing area subject to a fixed perimeter. This closing lesson of the module handles exactly that, using nothing beyond §10.5's gradient and the geometric fact that a gradient is always perpendicular to a level curve.

The constrained optimization problem

\text{maximize (or minimize) }f(x,y)\quad\text{subject to}\quad g(x,y)=c

The constraint g(x,y)=c is itself one of §10.0's level curves — so the problem is: among all points on that one curve, which gives f its largest (or smallest) value?

The key geometric idea

Picture f's level curves overlaid on the constraint curve g=c. Walking along the constraint curve, f's value changes — unless, at some point, the constraint curve happens to be tangent to one of f's own level curves. At a tangency point, moving along the constraint (in either direction) produces no immediate change in f's level — exactly the condition for a local extremum of f restricted to that curve.

Two curves are tangent exactly when their tangent lines coincide — which happens exactly when their normal directions coincide. §10.5 established that \nabla f is normal to f's level curve and \nabla g is normal to g's level curve at every point. So tangency between the two level curves means:

\nabla f=\lambda\nabla g\qquad\text{for some scalar }\lambda

\lambda is the Lagrange multiplier — it's not itself the quantity of interest, just the proportionality constant that makes the two parallel gradients equal.

The method

Solve the system of equations:

f_x=\lambda g_x,\qquad f_y=\lambda g_y,\qquad g(x,y)=c

— three equations (two from the parallel-gradient condition, one from the constraint itself) in three unknowns (x, y, \lambda). Every solution (x,y) is a candidate for the constrained extremum; evaluate f at each candidate and compare to determine which gives the max, which gives the min (the same "evaluate every candidate and compare" discipline as §3.5's closed-interval extrema search, since the second-derivative test from §10.6 doesn't directly apply to a constrained problem).

Why this trades one hard problem for an easier one: instead of searching a whole curve (infinitely many points) for where f stops changing, the parallel-gradient condition reduces the search to solving a finite system of equations — turning a genuinely infinite search into an algebra problem.

Doing it in Python

Maximizing f(x,y)=xy subject to x+y=10 — the classic problem behind "of all rectangles with a fixed perimeter, the square encloses the most area":

import sympy as sp

x, y, lam = sp.symbols('x y lam')
f = x * y
g = x + y - 10   # constraint: x + y = 10

f_x, f_y = sp.diff(f, x), sp.diff(f, y)
g_x, g_y = sp.diff(g, x), sp.diff(g, y)

system = [sp.Eq(f_x, lam * g_x), sp.Eq(f_y, lam * g_y), sp.Eq(g, 0)]
solution = sp.solve(system, [x, y, lam])
print(f"solution: {solution}")

max_value = f.subs({x: solution[x], y: solution[y]})
print(f"maximum value of xy subject to x+y=10: {max_value}")

Confirming the tangency picture directly — checking that \nabla f and \nabla g really are parallel (scalar multiples of each other) at the solution:

import sympy as sp

x, y = sp.symbols('x y')
f = x * y
g = x + y - 10

grad_f = sp.Matrix([sp.diff(f, x), sp.diff(f, y)]).subs({x: 5, y: 5})
grad_g = sp.Matrix([sp.diff(g, x), sp.diff(g, y)]).subs({x: 5, y: 5})

print(f"grad f at (5,5) = {grad_f.T}")
print(f"grad g at (5,5) = {grad_g.T}")
print(f"grad f is grad g scaled by: {grad_f[0] / grad_g[0]}  (matches lambda from the solve)")

A minimization problem: minimizing distance from the origin to a line — recovering §9.3's distance formula through an entirely different method:

import sympy as sp

x, y, lam = sp.symbols('x y lam')
f = x**2 + y**2               # squared distance from the origin (easier to work with than the root)
g = x + y - 4                 # constraint: on the line x+y=4

f_x, f_y = sp.diff(f, x), sp.diff(f, y)
g_x, g_y = sp.diff(g, x), sp.diff(g, y)

system = [sp.Eq(f_x, lam * g_x), sp.Eq(f_y, lam * g_y), sp.Eq(g, 0)]
solution = sp.solve(system, [x, y, lam])
min_distance = sp.sqrt(f.subs({x: solution[x], y: solution[y]}))
print(f"closest point: ({solution[x]}, {solution[y]})")
print(f"minimum distance = {min_distance}")

Worked example

Maximize f(x,y)=xy subject to x+y=10.

\nabla f=\langle y,x\rangle,\qquad\nabla g=\langle1,1\rangle

y=\lambda(1)=\lambda,\qquad x=\lambda(1)=\lambda

So x=y=\lambda. Substitute into the constraint x+y=10:

\lambda+\lambda=10\ \Longrightarrow\ \lambda=5\ \Longrightarrow\ x=y=5

f(5,5)=(5)(5)=\boxed{25}

Sanity check. This is exactly the classical fact that among all rectangles with a fixed perimeter (here, 2(x+y)=20), the square maximizes area — x=y=5 is indeed a square. Try a non-square point on the same constraint, like (8,2): f(8,2)=16<25; or (9,1): f(9,1)=9<25 — both smaller, consistent with 25 being the maximum. ✓ The parallel-gradient condition, \nabla f=\lambda\nabla g, translated directly into x=y here — a clean algebraic signature of the geometric "tangent level curves" picture.

Your turn

1. Minimize f(x,y)=x^2+y^2 subject to x+y=4 (find the point on the line closest to the origin).

2. Maximize f(x,y)=x+y subject to the constraint x^2+y^2=8 (a circle — find the farthest point from the origin in the positive-coordinate direction, in the sense of maximizing x+y).

3. True or false: the Lagrange multiplier \lambda itself has no useful meaning — it's purely a bookkeeping device with no interpretation.

Solutions

1. \nabla f=\langle2x,2y\rangle, \nabla g=\langle1,1\rangle. 2x=\lambda, 2y=\lambda\Rightarrow x=y. Substituting into x+y=4: 2x=4\Rightarrow x=y=2.

f(2,2)=4+4=\boxed8\text{, at the point }(2,2)

(Matching §9.3's projection-based distance formula: the closest point on x+y=4 to the origin is indeed (2,2), at distance \sqrt8=2\sqrt2 — two entirely different methods, same answer.)

2. \nabla f=\langle1,1\rangle, \nabla g=\langle2x,2y\rangle. 1=2\lambda x, 1=2\lambda y\Rightarrow x=y (both equal \frac1{2\lambda}). Substituting into x^2+y^2=8: $2x^2=8\Rightarrow x^2=4\Rightarrow x=\pm2$, so x=y=2 or x=y=-2.

f(2,2)=4,\qquad f(-2,-2)=-4

\boxed{\text{maximum is }4\text{, at }(2,2)}

(the point (-2,-2) is the minimum on this same constraint — Lagrange's method finds all candidates, and comparing their f-values sorts out which is which, exactly as the method description warned.)

3. False. \lambda does carry meaning: it measures the sensitivity of the optimal value of f to small changes in the constraint constant c — specifically, $\lambda\approx\frac{\Delta(\text{optimal }f)}{\Delta c}$. In problem 1, \lambda=2x=4 at the solution — meaning if the constraint shifted slightly, from x+y=4 to x+y=4.1, the minimum squared-distance value would shift by roughly \lambda\times0.1=0.4. This interpretation is exactly why Lagrange multipliers show up throughout economics (as a "shadow price" — how much an optimal outcome would improve per unit relaxation of a constraint) far beyond pure geometry.

Check yourself in code

Maximize f(x,y)=xy subject to x+y=10 using Lagrange multipliers.

Print exactly this:

x = 5, y = 5, lambda = 5
maximum value = 25
import sympy as sp

x, y, lam = sp.symbols('x y lam')
f = x * y
g = x + y - 10

f_x, f_y = sp.diff(f, x), sp.diff(f, y)
g_x, g_y = sp.diff(g, x), sp.diff(g, y)

system = [sp.Eq(f_x, lam * g_x), sp.Eq(f_y, lam * g_y), sp.Eq(g, 0)]
solution = sp.solve(system, [x, y, lam])
print("x = ..., y = ..., lambda = ...")

max_value = f.subs({x: solution[x], y: solution[y]})
print("maximum value = ...")
import sympy as sp

x, y, lam = sp.symbols('x y lam')
f = x * y
g = x + y - 10

f_x, f_y = sp.diff(f, x), sp.diff(f, y)
g_x, g_y = sp.diff(g, x), sp.diff(g, y)

system = [sp.Eq(f_x, lam * g_x), sp.Eq(f_y, lam * g_y), sp.Eq(g, 0)]
solution = sp.solve(system, [x, y, lam])
print(f"x = {solution[x]}, y = {solution[y]}, lambda = {solution[lam]}")

max_value = f.subs({x: solution[x], y: solution[y]})
print(f"maximum value = {max_value}")

Lagrange multipliers turn "optimize f restricted to a curve g=c" into an algebra problem by requiring \nabla f=\lambda\nabla g — the geometric condition that f's level curve is tangent to the constraint at any restricted extremum, since tangent curves share a normal direction, and §10.5 already established gradients as exactly that normal direction. The multiplier \lambda isn't just bookkeeping: it measures how sensitively the optimal value would respond to loosening the constraint, a fact that makes this method as central to economics as it is to geometry.

That closes this module's rebuild of single-variable calculus for functions of several variables — limits, derivatives, tangent planes, the chain rule, gradients, and now constrained optimization. Next: integration gets the same treatment, extending a single integral to sweep across an entire region of the plane or a solid in space.