Skip to content

Commit 5efda54

Browse files
jstacclaude
andauthored
Fix inconsistent code-cell language specifications (#756)
* misc * Fix inconsistent code-cell language specifications in optimal savings lectures Standardize code-cell language specifications to eliminate jupytext UserWarnings: - os_egm_jax.md: Change ipython to python3 (no IPython magics used) - os_stochastic.md: Change ipython to python3 (no IPython magics used) - os_time_iter.md: Change all cells to ipython (uses !pip install magic) These changes ensure consistent language specifications within each notebook, resolving warnings during jupytext conversion while maintaining functionality. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent b624539 commit 5efda54

File tree

4 files changed

+65
-79
lines changed

4 files changed

+65
-79
lines changed

lectures/os_egm.md

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,8 @@ First we remind ourselves of the theory and then we turn to numerical methods.
6060

6161
We work with the model set out in {doc}`os_time_iter`, following the same terminology and notation.
6262

63-
The Euler equation is
64-
65-
```{math}
66-
:label: egm_euler
67-
68-
(u'\circ \sigma^*)(x)
69-
= \beta \int (u'\circ \sigma^*)(f(x - \sigma^*(x)) z) f'(x - \sigma^*(x)) z \phi(dz)
70-
```
71-
72-
As we saw, the Coleman-Reffett operator is a nonlinear operator $K$ engineered so that $\sigma^*$ is a fixed point of $K$.
63+
As we saw, the Coleman-Reffett operator is a nonlinear operator $K$ engineered so that the optimal policy
64+
$\sigma^*$ is a fixed point of $K$.
7365

7466
It takes as its argument a continuous strictly increasing consumption policy $\sigma \in \Sigma$.
7567

@@ -85,9 +77,7 @@ u'(c)
8577
### Exogenous Grid
8678

8779
As discussed in {doc}`os_time_iter`, to implement the method on a
88-
computer, we need numerical approximation.
89-
90-
In particular, we represent a policy function by a set of values on a finite grid.
80+
computer, we represent a policy function by a set of values on a finite grid.
9181

9282
The function itself is reconstructed from this representation when necessary,
9383
using interpolation or some other method.
@@ -191,19 +181,21 @@ class Model(NamedTuple):
191181
u_prime_inv: Callable # inverse of u_prime
192182
193183
194-
def create_model(u: Callable,
195-
f: Callable,
196-
β: float = 0.96,
197-
μ: float = 0.0,
198-
ν: float = 0.1,
199-
grid_max: float = 4.0,
200-
grid_size: int = 120,
201-
shock_size: int = 250,
202-
seed: int = 1234,
203-
α: float = 0.4,
204-
u_prime: Callable = None,
205-
f_prime: Callable = None,
206-
u_prime_inv: Callable = None) -> Model:
184+
def create_model(
185+
u: Callable,
186+
f: Callable,
187+
β: float = 0.96,
188+
μ: float = 0.0,
189+
ν: float = 0.1,
190+
grid_max: float = 4.0,
191+
grid_size: int = 120,
192+
shock_size: int = 250,
193+
seed: int = 1234,
194+
α: float = 0.4,
195+
u_prime: Callable = None,
196+
f_prime: Callable = None,
197+
u_prime_inv: Callable = None
198+
) -> Model:
207199
"""
208200
Creates an instance of the optimal savings model.
209201
"""
@@ -214,7 +206,9 @@ def create_model(u: Callable,
214206
np.random.seed(seed)
215207
shocks = np.exp(μ + ν * np.random.randn(shock_size))
216208
217-
return Model(u, f, β, μ, ν, s_grid, shocks, α, u_prime, f_prime, u_prime_inv)
209+
return Model(
210+
u, f, β, μ, ν, s_grid, shocks, α, u_prime, f_prime, u_prime_inv
211+
)
218212
```
219213

220214
### The Operator
@@ -282,12 +276,14 @@ s_grid = model.s_grid
282276
Here's our solver routine:
283277

284278
```{code-cell} python3
285-
def solve_model_time_iter(model: Model,
286-
c_init: np.ndarray,
287-
x_init: np.ndarray,
288-
tol: float = 1e-5,
289-
max_iter: int = 1000,
290-
verbose: bool = True):
279+
def solve_model_time_iter(
280+
model: Model, # Model details
281+
c_init: np.ndarray, # initial guess of consumption on EG
282+
x_init: np.ndarray, # initial guess of endogenous grid
283+
tol: float = 1e-5, # Error tolerance
284+
max_iter: int = 1000, # Max number of iterations of K
285+
verbose: bool = True # If true print output
286+
):
291287
"""
292288
Solve the model using time iteration with EGM.
293289
"""

lectures/os_egm_jax.md

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ We'll also use JAX's `vmap` function to fully vectorize the Coleman-Reffett oper
3939

4040
Let's start with some standard imports:
4141

42-
```{code-cell} ipython
42+
```{code-cell} python3
4343
import matplotlib.pyplot as plt
4444
import jax
4545
import jax.numpy as jnp
@@ -113,7 +113,7 @@ def create_model(
113113
key = jax.random.PRNGKey(seed)
114114
shocks = jnp.exp(μ + s * jax.random.normal(key, shape=(shock_size,)))
115115
116-
return Model(β, μ, s=s, s_grid=s_grid, shocks=shocks, α=α)
116+
return Model(β, μ, s, s_grid, shocks, α)
117117
```
118118

119119

@@ -141,12 +141,7 @@ def K(
141141
The Coleman-Reffett operator using EGM
142142
143143
"""
144-
145-
# Simplify names
146-
β, α = model.β, model.α
147-
s_grid, shocks = model.s_grid, model.shocks
148-
149-
# Linear interpolation of policy using endogenous grid
144+
β, μ, s, s_grid, shocks, α = model
150145
σ = lambda x_val: jnp.interp(x_val, x_in, c_in)
151146
152147
# Define function to compute consumption at a single grid point

lectures/os_stochastic.md

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ More information on this savings problem can be found in
6262

6363
Let's start with some imports:
6464

65-
```{code-cell} ipython
65+
```{code-cell} python3
6666
import matplotlib.pyplot as plt
6767
import numpy as np
6868
from scipy.interpolate import interp1d
@@ -270,7 +270,7 @@ The term $\int v(f(x - c) z) \phi(dz)$ can be understood as the expected next pe
270270
* the state is $x$
271271
* consumption is set to $c$
272272

273-
As shown in [DP1](https://dp.quantecon.org/), Theorem 10.1.11 and a range of other texts,
273+
As shown in [DP1](https://dp.quantecon.org/) and a range of other texts,
274274
the value function $v^*$ satisfies the Bellman equation.
275275

276276
In other words, {eq}`fpb30` holds when $v=v^*$.
@@ -313,10 +313,9 @@ function.
313313

314314
In our setting, we have the following key result
315315

316-
* A feasible consumption policy is optimal if and only if it is $v^*$-greedy.
317-
318-
The intuition is similar to the intuition for the Bellman equation, which was
319-
provided after {eq}`fpb30`.
316+
```{prf:theorem}
317+
A feasible consumption policy is optimal if and only if it is $v^*$-greedy.
318+
```
320319

321320
See, for example, Theorem 10.1.11 of [EDTC](https://johnstachurski.net/edtc.html).
322321

@@ -359,7 +358,7 @@ v(x)
359358
= Tv(x)
360359
= \max_{0 \leq c \leq x}
361360
\left\{
362-
u(c) + \beta \int v^*(f(x - c) z) \phi(dz)
361+
u(c) + \beta \int v(f(x - c) z) \phi(dz)
363362
\right\}
364363
$$
365364

@@ -515,20 +514,18 @@ def create_model(
515514
We set up the right-hand side of the Bellman equation
516515

517516
$$
518-
B(x, c, v) := u(c) + \beta \int v^*(f(x - c) z) \phi(dz)
517+
B(x, c, v) := u(c) + \beta \int v(f(x - c) z) \phi(dz)
519518
$$
520519

521520

522521
```{code-cell} python3
523522
def B(
524-
x: float,
525-
c: float,
526-
v_array: np.ndarray,
527-
model: Model
528-
) -> float:
529-
"""
530-
Right hand side of the Bellman equation.
531-
"""
523+
x: float, # State
524+
c: float, # Action
525+
v_array: np.ndarray, # Array representing a guess of the value fn
526+
model: Model # An instance of Model containing parameters
527+
):
528+
532529
u, f, β, μ, ν, x_grid, shocks = model
533530
v = interp1d(x_grid, v_array)
534531
@@ -569,7 +566,7 @@ def T(v: np.ndarray, model: Model) -> tuple[np.ndarray, np.ndarray]:
569566
570567
for i in range(len(x_grid)):
571568
x = x_grid[i]
572-
c_star, v_max = maximize(lambda c: B(x, c, v, model), x)
569+
_, v_max = maximize(lambda c: B(x, c, v, model), x)
573570
v_new[i] = v_max
574571
575572
return v_new
@@ -731,12 +728,8 @@ def solve_model(
731728
verbose: bool = True, # print iteration info
732729
print_skip: int = 25 # iterations between prints
733730
):
734-
"""
735-
Solve model by iterating with the Bellman operator.
736-
737-
"""
731+
" Solve by value function iteration. "
738732
739-
# Set up loop
740733
v = model.u(model.x_grid) # Initial condition
741734
i = 0
742735
error = tol + 1

lectures/os_time_iter.md

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,22 +84,23 @@ Recall the Bellman equation
8484
```{math}
8585
:label: cpi_fpb30
8686
87-
v^*(x) = \max_{0 \leq c \leq x}
87+
v(x) = \max_{0 \leq c \leq x}
8888
\left\{
89-
u(c) + \beta \int v^*(f(x - c) z) \phi(dz)
89+
u(c) + \beta \int v(f(x - c) z) \phi(dz)
9090
\right\}
9191
\quad \text{for all} \quad
9292
x \in \mathbb R_+
9393
```
9494

95-
Let the optimal consumption policy be denoted by $\sigma^*$.
95+
Let $v^*$ be the value function and let $\sigma^*$ be the optimal consumption policy.
9696

97-
We know that $\sigma^*$ is a $v^*$-greedy policy so that $\sigma^*(x)$ is the maximizer in {eq}`cpi_fpb30`.
97+
We know that $\sigma^*$ is a $v^*$-greedy policy.
9898

9999
The conditions above imply that
100100

101101
* $\sigma^*$ is the unique optimal policy for the optimal savings problem
102-
* the optimal policy is continuous, strictly increasing and also **interior**, in the sense that $0 < \sigma^*(x) < x$ for all strictly positive $x$, and
102+
* the optimal policy is continuous, strictly increasing and also **interior**,
103+
in the sense that $0 < \sigma^*(x) < x$ for all strictly positive $x$, and
103104
* the value function is strictly concave and continuously differentiable, with
104105

105106
```{math}
@@ -108,7 +109,8 @@ The conditions above imply that
108109
(v^*)'(x) = u' (\sigma^*(x) ) := (u' \circ \sigma^*)(x)
109110
```
110111

111-
The last result is called the **envelope condition** due to its relationship with the [envelope theorem](https://en.wikipedia.org/wiki/Envelope_theorem).
112+
The last result is called the **envelope condition** due to its relationship
113+
with the [envelope theorem](https://en.wikipedia.org/wiki/Envelope_theorem).
112114

113115
To see why {eq}`cpi_env` holds, write the Bellman equation in the equivalent
114116
form
@@ -278,7 +280,7 @@ As in {doc}`os_stochastic`, we assume that
278280
This allows us to compare our results to the analytical solutions we obtained in
279281
that lecture:
280282

281-
```{code-cell} python3
283+
```{code-cell} ipython
282284
def v_star(x, α, β, μ):
283285
"""
284286
True value function
@@ -303,7 +305,7 @@ For this we need access to the functions $u'$ and $f, f'$.
303305

304306
We use the same `Model` structure from {doc}`os_stochastic`.
305307

306-
```{code-cell} python3
308+
```{code-cell} ipython
307309
class Model(NamedTuple):
308310
u: Callable # utility function
309311
f: Callable # production function
@@ -379,7 +381,7 @@ state $x$ and $σ$, the current guess of the policy.
379381

380382
Here's the operator $K$, that implements the root-finding step.
381383

382-
```{code-cell} ipython3
384+
```{code-cell} ipython
383385
def K(σ: np.ndarray, model: Model) -> np.ndarray:
384386
"""
385387
The Coleman-Reffett operator
@@ -402,7 +404,7 @@ def K(σ: np.ndarray, model: Model) -> np.ndarray:
402404

403405
Let's generate an instance and plot some iterates of $K$, starting from $σ(x) = x$.
404406

405-
```{code-cell} python3
407+
```{code-cell} ipython
406408
# Define utility and production functions with derivatives
407409
α = 0.4
408410
u = lambda c: np.log(c)
@@ -441,7 +443,7 @@ Here is a function called `solve_model_time_iter` that takes an instance of
441443
using time iteration.
442444

443445

444-
```{code-cell} python3
446+
```{code-cell} ipython
445447
def solve_model_time_iter(
446448
model: Model,
447449
σ_init: np.ndarray,
@@ -473,7 +475,7 @@ def solve_model_time_iter(
473475

474476
Let's call it:
475477

476-
```{code-cell} python3
478+
```{code-cell} ipython
477479
# Unpack
478480
grid = model.grid
479481
@@ -483,7 +485,7 @@ grid = model.grid
483485

484486
Here is a plot of the resulting policy, compared with the true policy:
485487

486-
```{code-cell} python3
488+
```{code-cell} ipython
487489
# Unpack
488490
grid, α, β = model.grid, model.α, model.β
489491
@@ -503,7 +505,7 @@ Again, the fit is excellent.
503505

504506
The maximal absolute deviation between the two policies is
505507

506-
```{code-cell} python3
508+
```{code-cell} ipython
507509
# Unpack
508510
grid, α, β = model.grid, model.α, model.β
509511
@@ -540,7 +542,7 @@ Compute and plot the optimal policy.
540542

541543
We define the CRRA utility function and its derivative.
542544

543-
```{code-cell} python3
545+
```{code-cell} ipython
544546
γ = 1.5
545547
546548
def u_crra(c):
@@ -556,7 +558,7 @@ model_crra = create_model(u=u_crra, f=f, α=α,
556558

557559
Now we solve and plot the policy:
558560

559-
```{code-cell} python3
561+
```{code-cell} ipython
560562
%%time
561563
# Unpack
562564
grid = model_crra.grid

0 commit comments

Comments
 (0)