GitHub

@@ -34,8 +34,8 @@ stochastically.

34343535

We can think of this cake as a harvest that regrows if we save some seeds.

363637-

Specifically, if we save (invest) part of today's cake, it grows into next

38-

period's cake according to a stochastic production process.

37+

Specifically, if we save and invest part of today's harvest $x_t$, it grows into next

38+

period's harvest $x_{t+1}$ according to a stochastic production process.

39394040

```{note}

4141

The term "cake eating" is not such a good fit now that we have a stochastic and

@@ -81,55 +81,49 @@ import matplotlib.pyplot as plt

8181

import numpy as np

8282

from scipy.interpolate import interp1d

8383

from scipy.optimize import minimize_scalar

84+

from typing import NamedTuple, Callable

85+8486

```

85878688

## The Model

87898890

```{index} single: Stochastic Cake Eating; Model

8991

```

909291-

Consider an agent who owns an amount $x_t \in \mathbb R_+ := [0, \infty)$ of a consumption good at time $t$.

93+

Here we described the new model and the optimization problem.

929493-

This output can either be consumed or invested.

95+

### Setup

949695-

When the good is invested, it is transformed one-for-one into capital.

97+

Consider an agent who owns an amount $x_t \in \mathbb R_+ := [0, \infty)$ of a consumption good at time $t$.

969897-

The resulting capital stock, denoted here by $k_{t+1}$, will then be used for production.

99+

This output can either be consumed or saved and used for production.

9810099101

Production is stochastic, in that it also depends on a shock $\xi_{t+1}$ realized at the end of the current period.

100102101103

Next period output is

102104103105

$$

104-

x_{t+1} := f(k_{t+1}) \xi_{t+1}

106+

x_{t+1} := f(s_t) \xi_{t+1}

105107

$$

106108107-

where $f \colon \mathbb R_+ \to \mathbb R_+$ is called the production function.

108-109-

The resource constraint is

109+

where $f \colon \mathbb R_+ \to \mathbb R_+$ is the **production function** and

110110111111

```{math}

112112

:label: outcsdp0

113113114-

k_{t+1} + c_t \leq x_t

114+

s_t = x_t - c_t

115115

```

116116117-

and all variables are required to be nonnegative.

117+

is **current savings**.

118118119-

### Assumptions and Comments

119+

and all variables are required to be nonnegative.

120120121121

In what follows,

122122123123

* The sequence $\{\xi_t\}$ is assumed to be IID.

124124

* The common distribution of each $\xi_t$ will be denoted by $\phi$.

125125

* The production function $f$ is assumed to be increasing and continuous.

126-

* Depreciation of capital is not made explicit but can be incorporated into the production function.

127-128-

While many other treatments of stochastic consumption-saving models use $k_t$ as the state variable, we will use $x_t$.

129126130-

This will allow us to treat a stochastic model while maintaining only one state variable.

131-132-

We consider alternative states and timing specifications in some of our other lectures.

133127134128

### Optimization

135129

@@ -157,21 +151,20 @@ where

157151

* $u$ is a bounded, continuous and strictly increasing utility function and

158152

* $\beta \in (0, 1)$ is a discount factor.

159153160-

In {eq}`og_conse` we are assuming that the resource constraint {eq}`outcsdp0` holds with equality --- which is reasonable because $u$ is strictly increasing and no output will be wasted at the optimum.

161-162154

In summary, the agent's aim is to select a path $c_0, c_1, c_2, \ldots$ for consumption that is

163155164156

1. nonnegative,

165-

1. feasible in the sense of {eq}`outcsdp0`,

157+

1. feasible,

166158

1. optimal, in the sense that it maximizes {eq}`texs0_og2` relative to all other feasible consumption sequences, and

167-

1. **adapted**, in the sense that the action $c_t$ depends only on

168-

observable outcomes, not on future outcomes such as $\xi_{t+1}$.

159+

1. **adapted**, in the sense that the current action $c_t$ depends only on current and historical outcomes, not on future outcomes such as $\xi_{t+1}$.

169160170161

In the present context

171162172163

* $x_t$ is called the **state** variable --- it summarizes the "state of the world" at the start of each period.

173164

* $c_t$ is called the **control** variable --- a value chosen by the agent each period after observing the state.

174165166+167+175168

### The Policy Function Approach

176169177170

```{index} single: Stochastic Cake Eating; Policy Function Approach

@@ -183,14 +176,10 @@ A policy function is a map from past and present observables into current action

183176184177

We'll be particularly interested in **Markov policies**, which are maps from the current state $x_t$ into a current action $c_t$.

185178186-

For dynamic programming problems such as this one (in fact for any [Markov decision process](https://en.wikipedia.org/wiki/Markov_decision_process)), the optimal policy is always a Markov policy.

179+

For dynamic programming problems such as this one, the optimal policy is always a Markov policy (see, e.g., [DP1](https://dp.quantecon.org/)).

187180188-

In other words, the current state $x_t$ provides a [sufficient statistic](https://en.wikipedia.org/wiki/Sufficient_statistic)

189-

for the history in terms of making an optimal decision today.

190-191-

This is quite intuitive, but if you wish you can find proofs in texts such as {cite}`StokeyLucas1989` (section 4.1).

192-193-

Hereafter we focus on finding the best Markov policy.

181+

In other words, the current state $x_t$ provides a sufficient statistic for the history

182+

in terms of making an optimal decision today.

194183195184

In our context, a Markov policy is a function $\sigma \colon

196185

\mathbb R_+ \to \mathbb R_+$, with the understanding that states are mapped to actions via

@@ -199,7 +188,7 @@ $$

199188

c_t = \sigma(x_t) \quad \text{for all } t

200189

$$

201190202-

In what follows, we will call $\sigma$ a *feasible consumption policy* if it satisfies

191+

In what follows, we will call $\sigma$ a **feasible consumption policy** if it satisfies

203192204193

```{math}

205194

:label: idp_fp_og2

@@ -246,9 +235,11 @@ The aim is to select a policy that makes this number as large as possible.

246235247236

The next section covers these ideas more formally.

248237238+239+249240

### Optimality

250241251-

The $\sigma$ associated with a given policy $\sigma$ is the mapping defined by

242+

The lifetime value $v_{\sigma}$ associated with a given policy $\sigma$ is the mapping defined by

252243253244

```{math}

254245

:label: vfcsdp00

@@ -259,8 +250,7 @@ v_{\sigma}(x) =

259250260251

when $\{x_t\}$ is given by {eq}`firstp0_og2` with $x_0 = x$.

261252262-

In other words, it is the lifetime value of following policy $\sigma$

263-

starting at initial condition $x$.

253+

In other words, it is the lifetime value of following policy $\sigma$ forever, starting at initial condition $x$.

264254265255

The **value function** is then defined as

266256

@@ -270,15 +260,17 @@ The **value function** is then defined as

270260

v^*(x) := \sup_{\sigma \in \Sigma} \; v_{\sigma}(x)

271261

```

272262273-

The value function gives the maximal value that can be obtained from state $x$, after considering all feasible policies.

263+

The value function gives the maximal value that can be obtained from state $x$,

264+

after considering all feasible policies.

274265275-

A policy $\sigma \in \Sigma$ is called **optimal** if it attains the supremum in {eq}`vfcsdp0` for all $x \in \mathbb R_+$.

266+

A policy $\sigma \in \Sigma$ is called **optimal** if it attains the supremum in

267+

{eq}`vfcsdp0` for all $x \in \mathbb R_+$.

276268277-

### The Bellman Equation

278269279-

With our assumptions on utility and production functions, the value function as defined in {eq}`vfcsdp0` also satisfies a **Bellman equation**.

270+

### The Bellman Equation

280271281-

For this problem, the Bellman equation takes the form

272+

The following equation is called the **Bellman equation** associated with this

273+

dynamic programming problem.

282274283275

```{math}

284276

:label: fpb30

@@ -290,15 +282,16 @@ v(x) = \max_{0 \leq c \leq x}

290282

\qquad (x \in \mathbb R_+)

291283

```

292284293-

This is a *functional equation in* $v$.

285+

This is a *functional equation in* $v$, in the sense that a given $v$ can either

286+

satisfy it or not satisfy it.

294287295288

The term $\int v(f(x - c) z) \phi(dz)$ can be understood as the expected next period value when

296289297290

* $v$ is used to measure value

298291

* the state is $x$

299292

* consumption is set to $c$

300293301-

As shown in [EDTC](https://johnstachurski.net/edtc.html), theorem 10.1.11 and a range of other texts,

294+

As shown in [EDTC](https://johnstachurski.net/edtc.html), Theorem 10.1.11 and a range of other texts,

302295

the value function $v^*$ satisfies the Bellman equation.

303296304297

In other words, {eq}`fpb30` holds when $v=v^*$.

@@ -308,15 +301,17 @@ The intuition is that maximal value from a given state can be obtained by optima

308301

* current reward from a given action, vs

309302

* expected discounted future value of the state resulting from that action

310303311-

The Bellman equation is important because it gives us more information about the value function.

304+

The Bellman equation is important because it

305+306+

1. gives us more information about the value function and

307+

2. suggests a way of computing the value function, which we discuss below.

312308313-

It also suggests a way of computing the value function, which we discuss below.

314309315-

### Greedy Policies

316310317-

The primary importance of the value function is that we can use it to compute optimal policies.

318311319-

The details are as follows.

312+

### Greedy Policies

313+314+

The value function can be used to compute optimal policies.

320315321316

Given a continuous function $v$ on $\mathbb R_+$, we say that

322317

$\sigma \in \Sigma$ is $v$-**greedy** if $\sigma(x)$ is a solution to

@@ -343,21 +338,22 @@ In our setting, we have the following key result

343338

The intuition is similar to the intuition for the Bellman equation, which was

344339

provided after {eq}`fpb30`.

345340346-

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

341+

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

347342348343

Hence, once we have a good approximation to $v^*$, we can compute the

349344

(approximately) optimal policy by computing the corresponding greedy policy.

350345351346

The advantage is that we are now solving a much lower dimensional optimization

352347

problem.

353348349+354350

### The Bellman Operator

355351356352

How, then, should we compute the value function?

357353358354

One way is to use the so-called **Bellman operator**.

359355360-

(An operator is a map that sends functions into functions.)

356+

(The term **operator** is usually reserved for functions that send functions into functions!)

361357362358

The Bellman operator is denoted by $T$ and defined by

363359

@@ -371,11 +367,10 @@ Tv(x) := \max_{0 \leq c \leq x}

371367

\qquad (x \in \mathbb R_+)

372368

```

373369374-

In other words, $T$ sends the function $v$ into the new function

375-

$Tv$ defined by {eq}`fcbell20_optgrowth`.

370+

In other words, $T$ sends the function $v$ into the new function $Tv$ defined by {eq}`fcbell20_optgrowth`.

376371377-

By construction, the set of solutions to the Bellman equation

378-

{eq}`fpb30` *exactly coincides with* the set of fixed points of $T$.

372+

By construction, the set of solutions to the Bellman equation {eq}`fpb30`

373+

*exactly coincides with* the set of fixed points of $T$.

379374380375

For example, if $Tv = v$, then, for any $x \geq 0$,

381376

@@ -392,6 +387,9 @@ which says precisely that $v$ is a solution to the Bellman equation.

392387393388

It follows that $v^*$ is a fixed point of $T$.

394389390+391+392+395393

### Review of Theoretical Results

396394397395

```{index} single: Dynamic Programming; Theory

@@ -430,7 +428,7 @@ Our problem now is how to compute it.

430428

```{index} single: Dynamic Programming; Unbounded Utility

431429

```

432430433-

The results stated above assume that the utility function is bounded.

431+

The results stated above assume that $u$ is bounded.

434432435433

In practice economists often work with unbounded utility functions --- and so will we.

436434

@@ -458,36 +456,18 @@ Let's now look at computing the value function and the optimal policy.

458456

Our implementation in this lecture will focus on clarity and

459457

flexibility.

460458461-

Both of these things are helpful, but they do cost us some speed --- as you

462-

will see when you run the code.

459+

(In subsequent lectures we will focus on efficiency and speed.)

463460464-

The algorithm we will use is fitted value function iteration, which was

465-

described in earlier lectures {doc}`the McCall model <mccall_fitted_vfi>` and

466-

{doc}`cake eating <cake_eating_numerical>`.

461+

We will use fitted value function iteration, which was

462+

already described in {doc}`cake eating <cake_eating_numerical>`.

467463468-

The algorithm will be

469-470-

(fvi_alg)=

471-

1. Begin with an array of values $\{ v_1, \ldots, v_I \}$ representing

472-

the values of some initial function $v$ on the grid points $\{ x_1, \ldots, x_I \}$.

473-

1. Build a function $\hat v$ on the state space $\mathbb R_+$ by

474-

linear interpolation, based on these data points.

475-

1. Obtain and record the value $T \hat v(x_i)$ on each grid point

476-

$x_i$ by repeatedly solving {eq}`fcbell20_optgrowth`.

477-

1. Unless some stopping condition is satisfied, set

478-

$\{ v_1, \ldots, v_I \} = \{ T \hat v(x_1), \ldots, T \hat v(x_I) \}$ and go to step 2.

479464480465

### Scalar Maximization

481466482467

To maximize the right hand side of the Bellman equation {eq}`fpb30`, we are going to use

483468

the `minimize_scalar` routine from SciPy.

484469485-

Since we are maximizing rather than minimizing, we will use the fact that the

486-

maximizer of $g$ on the interval $[a, b]$ is the minimizer of

487-

$-g$ on the same interval.

488-489-

To this end, and to keep the interface tidy, we will wrap `minimize_scalar`

490-

in an outer function as follows:

470+

To keep the interface tidy, we will wrap `minimize_scalar` in an outer function as follows:

491471492472

```{code-cell} python3

493473

def maximize(g, a, b, args):

@@ -507,25 +487,25 @@ def maximize(g, a, b, args):

507487

return maximizer, maximum

508488

```

509489510-

### Stochastic Cake Eating Model

511490512-

We will assume for now that $\phi$ is the distribution of $\xi := \exp(\mu + s \zeta)$ where

491+492+

### Model

493+494+

We will assume for now that $\phi$ is the distribution of $\xi := \exp(\mu + \nu \zeta)$ where

513495514496

* $\zeta$ is standard normal,

515497

* $\mu$ is a shock location parameter and

516-

* $s$ is a shock scale parameter.

498+

* $\nu$ is a shock scale parameter.

517499518500

We will store the primitives of the model in a `NamedTuple`.

519501520502

```{code-cell} python3

521-

from typing import NamedTuple, Callable

522-523503

class Model(NamedTuple):

524504

u: Callable # utility function

525505

f: Callable # production function

526506

β: float # discount factor

527507

μ: float # shock location parameter

528-

s: float # shock scale parameter

508+

ν: float # shock scale parameter

529509

grid: np.ndarray # state grid

530510

shocks: np.ndarray # shock draws

531511

@@ -534,7 +514,7 @@ def create_model(u: Callable,

534514

f: Callable,

535515

β: float = 0.96,

536516

μ: float = 0.0,

537-

s: float = 0.1,

517+

ν: float = 0.1,

538518

grid_max: float = 4.0,

539519

grid_size: int = 120,

540520

shock_size: int = 250,

@@ -547,9 +527,9 @@ def create_model(u: Callable,

547527548528

# Store shocks (with a seed, so results are reproducible)

549529

np.random.seed(seed)

550-

shocks = np.exp(μ + s * np.random.randn(shock_size))

530+

shocks = np.exp(μ + ν * np.random.randn(shock_size))

551531552-

return Model(u=u, f=f, β, μ=μ, s=s, grid=grid, shocks=shocks)

532+

return Model(u, f, β, μ, ν, grid, shocks)

553533554534555535

def state_action_value(c: float,

@@ -618,12 +598,13 @@ def T(v: np.ndarray, model: Model) -> tuple[np.ndarray, np.ndarray]:

618598

Let's suppose now that

619599620600

$$

621-

f(k) = k^{\alpha}

601+

f(x-c) = (x-c)^{\alpha}

622602

\quad \text{and} \quad

623603

u(c) = \ln c

624604

$$

625605626-

For this particular problem, an exact analytical solution is available (see {cite}`Ljungqvist2012`, section 3.1.2), with

606+

For this particular problem, an exact analytical solution is available (see

607+

{cite}`Ljungqvist2012`, section 3.1.2), with

627608628609

```{math}

629610

:label: dpi_tv

@@ -670,8 +651,8 @@ Next let's create an instance of the model with the above primitives and assign

670651671652

```{code-cell} python3

672653

α = 0.4

673-

def fcd(k):

674-

return k**α

654+

def fcd(s):

655+

return s**α

675656676657

model = create_model(u=np.log, f=fcd)

677658

```

Read the original on github.com ↗