Skip to content

Commit ff39fee

Browse files
jstacclaude
andcommitted
Simplify McCall model solution to single scalar equation
Simplified the solution method by solving for v_e(w) in closed form as a function of d, then substituting into the equation for d. This reduces the problem from iterating on both a vector (v_e) and scalar (d) to iterating on just the scalar d. Key improvements: - Added derivation showing v_e(w) = (u(w) + βαd) / (1 - β(1-α)) - Reduced to single scalar fixed-point equation for d - Simplified code: now only iterate on scalar d instead of vector + scalar - Compute v_e from d using closed-form expression after convergence - More efficient: fewer variables to track during iteration - Clearer mathematical structure The implementation now directly reflects the simplified mathematical approach, making it easier to understand and computationally more efficient. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 1fad734 commit ff39fee

File tree

1 file changed

+71
-37
lines changed

1 file changed

+71
-37
lines changed

lectures/mccall_model_with_separation.md

Lines changed: 71 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,39 @@ v_e(w) = u(w) + \beta
224224
\right]
225225
```
226226

227+
### Simplifying to a Single Equation
228+
229+
We can simplify further by solving {eq}`bell01_mccall` for $v_e$ as a function of $d$.
230+
231+
Rearranging {eq}`bell01_mccall` gives
232+
233+
$$
234+
v_e(w) - \beta(1-\alpha)v_e(w) = u(w) + \beta\alpha d
235+
$$
236+
237+
or
238+
239+
```{math}
240+
:label: v_e_closed
241+
242+
v_e(w) = \frac{u(w) + \beta\alpha d}{1 - \beta(1-\alpha)}
243+
```
244+
245+
Substituting this into {eq}`bell02_mccall` yields
246+
247+
```{math}
248+
:label: bell_scalar
249+
250+
d = \sum_{w' \in \mathbb W} \max \left\{ \frac{u(w') + \beta\alpha d}{1 - \beta(1-\alpha)}, \, u(c) + \beta d \right\} q(w')
251+
```
252+
253+
This is a single scalar equation in $d$.
227254

228255
### The Reservation Wage
229256

230-
Suppose we can use {eq}`bell02_mccall` and {eq}`bell01_mccall` to solve for
231-
$d$ and $v_e$.
257+
Suppose we can use {eq}`bell_scalar` to solve for $d$.
232258

233-
(We will do this soon.)
259+
Once we have $d$, we can obtain $v_e$ from {eq}`v_e_closed`.
234260

235261
We can then determine optimal behavior for the worker.
236262

@@ -254,36 +280,32 @@ $$
254280
We'll use the same iterative approach to solving the Bellman equations that we
255281
adopted in the {doc}`first job search lecture <mccall_model>`.
256282

257-
Here this amounts to
258-
259-
1. make guesses for $d$ and $v_e$
260-
1. plug these guesses into the right-hand sides of {eq}`bell02_mccall` and {eq}`bell01_mccall`
261-
1. update the left-hand sides from this rule and then repeat
283+
Since we have reduced the problem to a single scalar equation {eq}`bell_scalar`,
284+
we only need to iterate on $d$.
262285

263-
In other words, we are iterating using the rules
286+
The iteration rule is
264287

265288
```{math}
266-
:label: bell1001
289+
:label: bell_iter
267290
268291
d_{n+1} = \sum_{w' \in \mathbb W}
269-
\max \left\{ v_{e,n}(w'), \, u(c) + \beta d_n \right\} q(w')
292+
\max \left\{ \frac{u(w') + \beta\alpha d_n}{1 - \beta(1-\alpha)}, \, u(c) + \beta d_n \right\} q(w')
270293
```
271294

295+
starting from some initial condition $d_0$.
296+
297+
Once convergence is achieved, we can compute $v_e$ from {eq}`v_e_closed`:
298+
272299
```{math}
273-
:label: bell2001
300+
:label: bell_v_e_final
274301
275-
v_{e,n+1}(w) = u(w) + \beta
276-
\left[
277-
(1-\alpha)v_{e,n}(w) + \alpha d_n
278-
\right]
302+
v_e(w) = \frac{u(w) + \beta\alpha d}{1 - \beta(1-\alpha)}
279303
```
280304

281-
starting from some initial conditions $d_0, v_{e,0}$.
305+
This approach is simpler than iterating on both $d$ and $v_e$ simultaneously, as
306+
we now only need to track a single scalar value.
282307

283-
As before, the system always converges to the true solutions---in this case,
284-
the $v_e$ and $d$ that solve {eq}`bell02_mccall` and {eq}`bell01_mccall`.
285-
286-
(A proof can be obtained via the Banach contraction mapping theorem.)
308+
(Convergence can be established via the Banach contraction mapping theorem.)
287309

288310
## Implementation
289311

@@ -328,40 +350,52 @@ Now we iterate until successive realizations are closer together than some small
328350

329351
We then return the current iterate as an approximate solution.
330352

353+
First, we define a function to compute $v_e$ from $d$:
354+
331355
```{code-cell} ipython3
332356
@jax.jit
333-
def update(model, v_e, d):
334-
" One update on the Bellman equations. "
357+
def compute_v_e(model, d):
358+
" Compute v_e from d using the closed-form expression. "
359+
α, β, w = model.α, model.β, model.w
360+
return (u(w) + β * α * d) / (1 - β * (1 - α))
361+
```
362+
363+
Now we implement the iteration on $d$ only:
364+
365+
```{code-cell} ipython3
366+
@jax.jit
367+
def update_d(model, d):
368+
" One update of the scalar d. "
335369
α, β, c, w, q = model.α, model.β, model.c, model.w, model.q
336-
v_e_new = u(w) + β * ((1 - α) * v_e + α * d)
370+
v_e = compute_v_e(model, d)
337371
d_new = jnp.maximum(v_e, u(c) + β * d) @ q
338-
return v_e_new, d_new
372+
return d_new
339373
340374
@jax.jit
341375
def solve_model(model, tol=1e-5, max_iter=2000):
342376
" Iterates to convergence on the Bellman equations. "
343377
344378
def cond_fun(state):
345-
v_e, d, i, error = state
379+
d, i, error = state
346380
return jnp.logical_and(error > tol, i < max_iter)
347381
348382
def body_fun(state):
349-
v_e, d, i, error = state
350-
v_e_new, d_new = update(model, v_e, d)
351-
error_1 = jnp.max(jnp.abs(v_e_new - v_e))
352-
error_2 = jnp.abs(d_new - d)
353-
error_new = jnp.maximum(error_1, error_2)
354-
return v_e_new, d_new, i + 1, error_new
355-
356-
# Initial state: (v_e, d, i, error)
357-
v_e_init = jnp.ones_like(model.w)
383+
d, i, error = state
384+
d_new = update_d(model, d)
385+
error_new = jnp.abs(d_new - d)
386+
return d_new, i + 1, error_new
387+
388+
# Initial state: (d, i, error)
358389
d_init = 1.0
359390
i_init = 0
360391
error_init = tol + 1
361392
362-
init_state = (v_e_init, d_init, i_init, error_init)
393+
init_state = (d_init, i_init, error_init)
363394
final_state = jax.lax.while_loop(cond_fun, body_fun, init_state)
364-
v_e_final, d_final, _, _ = final_state
395+
d_final, _, _ = final_state
396+
397+
# Compute v_e from the converged d
398+
v_e_final = compute_v_e(model, d_final)
365399
366400
return v_e_final, d_final
367401
```

0 commit comments

Comments
 (0)