F5-dev-01 — Cobb–Douglas consumer: closed-form demands with numerical validation
Question
A consumer with u(x1,x2) = α ln x1 + (1−α) ln x2 maximises utility subject to p1x1 + p2x2 ≤ m. We want the Marshallian demands x1*, x2*, the indirect utility v(p,m), and the budget residual at the optimum. We also check the closed form against a separate numerical maximisation.
Data and exclusions
data/parameters.csv has 4 rows: α = 0.35, p1 = 2.5, p2 = 4.0, m = 120.0. All four rows were used. Nothing was excluded and no data issues were found (no missing values, no duplicates, all values inside their admissible ranges).
Method
Derivation. ln is strictly increasing, so utility is strictly increasing in both goods and the budget constraint must bind at the optimum. Marginal utility goes to +∞ as x_i → 0⁺, so any bundle on the boundary (x_i = 0, where u = −∞) is beaten by an interior bundle. The Lagrangian is L = α ln x1 + (1−α) ln x2 + λ(m − p1x1 − p2x2), with first-order conditions α/x1 = λp1 and (1−α)/x2 = λp2. Adding p1x1 = α/λ and p2x2 = (1−α)/λ and using the binding budget gives λ = 1/m. That yields
- x1* = α m / p1, x2* = (1−α) m / p2,
- v(p,m) = α ln(α m/p1) + (1−α) ln((1−α) m/p2),
- MRS = [α/x1]/[(1−α)/x2] = p1/p2 at the optimum, and the expenditure share on good 1 is α.
Assumptions for a unique interior optimum: 0 < α < 1, p1 > 0, p2 > 0, m > 0. Under these, u is strictly concave on the open positive orthant (Hessian diag(−α/x1², −(1−α)/x2²) is negative definite) and the budget set is convex and compact, so the stationary point is the unique global maximum. The script checks these parameter restrictions with assertions before computing anything. They do not hold at the edges: if α ∈ {0,1}, one good gets zero weight and the log form breaks down at zero consumption. With non-positive prices or income the problem is unbounded or empty.
Numerical validation (does not use the closed form). All checks are in out/analysis.py. Each one maximises u directly:
- A bounded scalar optimiser (scipy
minimize_scalar, method "bounded", xatol 1e-12) over x1 ∈ (0, m/p1) along the budget line, with x2 = (m − p1x1)/p2. This uses only the fact that utility is monotone, so the budget binds. - A grid search over the budget line: 2,000,001 points, spacing ≈ 2.4e-5 in x1.
- A 2-D SLSQP optimiser with the budget imposed only as an inequality and non-negativity bounds, started from (1,1). This checks that the budget binds rather than assuming it.
indirect_utility_numerical is the larger of the maxima from checks 1 and 2. Scope: the validation covers only the single parameter point in parameters.csv (α=0.35, p1=2.5, p2=4, m=120). It does not cover other parameter values; there the analytic derivation is what supports the result. Nothing is random, so no seed is used. Full diagnostics are in out/validation_details.json.
Results
| quantity | value |
|---|---|
| x1* | 16.8 |
| x2* | 19.5 |
| v(p,m) | 2.9182520128635305 |
| budget residual | 0.0 |
| MRS at optimum | 0.625 |
| p1/p2 | 0.625 |
| expenditure share, good 1 | 0.35 (= α) |
| numerical max utility | 2.9182520128635305 |
The numerical checks agree with the closed form:
- Bounded scalar search: x1 = 16.8000002 (difference 2.3e-7). The utility value matches the closed form to the last printed digit (difference 0.0 in double precision).
- Grid search: x1 = 16.79999 (difference 9.6e-6, within one grid step), with utility 8.8e-14 below the closed form.
- SLSQP: x = (16.8000007, 19.4999996), budget slack 2.8e-14, so the budget binds as the theory predicts.
At the optimum, MRS equals the price ratio and the expenditure share equals α, as expected.
Uncertainty
This is a deterministic theoretical exercise, so there is no sampling uncertainty. The only error is numerical. Utility is flat near the maximum (first derivative zero), so utility values agree to about 1e-16. The maximiser locations are less precise: about 1e-7 for the scalar optimiser and 1e-5 for the grid.
Limitations and open issues
- The numerical check covers one parameter point only. The general formula rests on the analytic derivation.
- Corner cases (α ∈ {0,1}, zero prices, zero income) are outside the scope and would be rejected by the script's assertions.
n_analysedcounts the 4 parameter rows read. The task has one parameter point, which is made up of 4 parameters.