os_stochastic#

  • Series: lecture-python.myst

  • File: lectures/os_stochastic.md

  • Audit date: 2026-08-26

  • Corpus snapshot: e25fdf2345

  • Categories audited: writing, math, code, figures, references, links, admonitions (JAX out of scope)

  • Overall score: 7.6 / 10

  • Priority: HIGH

Score breakdown#

Category

Score

One-line note

Writing

3/10

qe-writing-006 ×11; qe-writing-003 ×5; qe-writing-002 ×5, +4 more.

Math

7/10

qe-math-010 (proposed) ×4; qe-math-009 ×2.

Code

7.5/10

qe-code-001 ×6; qe-code-004 ×1.

JAX

out of scope

JAX rules target lecture-jax.

Figures

7.5/10

qe-fig-005 ×5.

References

10/10

no mechanical violations detected.

Links

8/10

qe-link-002 ×3.

Admonitions

10/10

no mechanical violations detected.

Issues#

Critical#

None found.

High severity#

  • [qe-code-001] (reviewer) — Follow PEP8 unless closer to mathematical notation. Count: 6. Lines: 460, 481, 500, 582, 653, 670. Example: 460 assigns a lambda to a name, objective = lambda x: -g(x), which PEP8 asks be written as a def, and names the argument x where every other use of x in the lecture is the state and this one is consumption; 582 and 731 are single-quoted one-line docstrings padded with spaces (" Compute the v-greedy policy on x_grid.", " Solve by value function iteration. ") where the other five docstrings in the lecture use """ (452, 501, 557, 634, 644); 481-487 aligns the trailing field comments in class Model with several spaces on 481-485 but only one on 486-487 (x_grid: np.ndarray # state grid), below PEP8’s two; 500, 527, 581 and 730 indent the closing ) of a multi-line signature to 4 columns, the same column as the body that follows, so ) -> Model: and # Set up grid line up; 653-655 and 832-834 put α = 0.4 and γ = 1.5 immediately against a top-level def with no blank line, where 632-643 does leave one; and 670-671 uses a 4-space gap before # Start at the solution and a 13-space gap before # Apply T once on consecutive lines.

  • [qe-fig-005] — Descriptive figure names for cross-referencing. Count: 5. Lines: 667, 688, 762, 788, 849. Example: code-cell figure without mystnb figure metadata.

  • [qe-math-010 (proposed)] — Blackboard \mathbb{P}, \mathbb{E}, \mathbb{V} with braces. Count: 4. Lines: 122, 203, 206, 227. Example: missing braces: \mathbb E.

  • [qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 5. Lines: 232, 437, 716, 776, 801. Example: the same gloss is given twice for what is the same expression: 210-211 says {eq}`texss` is “the total expected present value of following policy \(\sigma\) forever, given initial income \(x_0\)” and 232-233 says {eq}`vfcsdp00` is “the lifetime value of following policy \(\sigma\) forever, starting at initial condition \(x\)”. Line 437’s parenthetical “(In subsequent lectures we will focus on efficiency and speed.)” restates the {note} already made at 50. And each of the last three figures is summarised by a verdict rather than a number: 716 “We are clearly getting closer” immediately after 714 has already said the iterates converge; 776 “The figure shows that we are pretty much on the money”; 801-802 “the figure shows that we’ve done a good job in this instance” - solve_model computes error at 739 and prints it at 742, so an actual sup-norm deviation is available and would replace all three.

  • [qe-writing-003] (reviewer) — Maintain logical flow. Count: 5. Lines: 79, 106, 556, 575, 835. Example: line 79 is an unfinished placeholder in the past tense at the head of the main section - “Here we described the new model and the optimization problem.” The sentence at 96 ends with a dangling “and”, the {math} block at 98-102 intervenes, 104 closes it with “is current savings.”, and then 106 opens a fresh paragraph with a second dangling “and all variables are required to be nonnegative.” Line 553 says “The next function implements the Bellman operator” and shows T; line 575 then says “Here’s the function:” and shows get_greedy, which the prose has never mentioned - the sentence points at nothing and the greedy policy of {eq}`defgp20` gets no introduction. T’s signature at 556 annotates -> tuple[np.ndarray, np.ndarray] but the body returns the single array v_new at 572. And the exercise at 813-815 asks for \(u(c) = c^{1-\gamma}/(1-\gamma)\) while its own solution at 835 codes (c**(1 - γ) - 1) / (1 - γ), a different function.

  • [qe-writing-006] — Capitalize lecture titles properly. Count: 11. Lines: 74, 155, 249, 291, 329, 372, 443, 551, 596, 718, …. Example: H2 Title Case: ‘The Model’ (Model).

Medium severity#

  • [qe-link-002] — Use doc links for cross-series references. Count: 3. Lines: 167, 187, 273. Example: raw link to dp.quantecon.org.

  • [qe-math-009] (reviewer) — Choose simplicity in mathematical notation. Count: 2. Lines: 471, 473. Example: 471 names the shock scale parameter \(\nu\) in a lecture whose central object is the value function \(v\) - the two glyphs differ by a hairline, and they appear together in the same code (ν: float at 485 alongside v_array, v_new, v_greedy) and the same call (v_star(x_grid, α, model.β, model.μ) at 670). Line 473 then uses \(\zeta\) for the standard normal driving \(\xi\), so two visually similar Greek letters carry the two closely related shock objects. A plain letter for the scale (say \(s\) or \(\eta\)) and reusing \(\varepsilon\) for the normal would both be simpler and remove the collision.

  • [qe-writing-004] — Avoid unnecessary capitalization in narrative text. Count: 1. Lines: 320. Example: mid-sentence ‘Theorem’.

  • [qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 2. Lines: 264, 335. Example: the lecture is otherwise a model of the rule - definitions are bold throughout (production function 96, current savings 104, adapted 146, state 150, control 151, policy functions 160, feasible consumption policy 173, value function 235, optimal 246, Bellman equation 251, \(v\)-greedy 296, Bellman operator 333, value function iteration 394). Two places invert it: 264 introduces the term in italic, “This is a functional equation in \(v\), in the sense that a given \(v\) can either satisfy it or not satisfy it”, which is a definition; and 335 bolds operator for a parenthetical aside - “(The term operator is usually reserved for functions that send functions into functions!)” - which is emphasis.

  • [qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 3. Lines: 471, 694, 776. Example: lines 32-43 say the key difference from {doc}`os` and {doc}`os_numerical` is that wealth now evolves stochastically through a production function, and 471-475 introduces the lognormal \(\xi = \exp(\mu + \nu\zeta)\) - but all five figures (667, 688, 762, 788, 849) plot \(v\) or \(\sigma\) against \(x\), which is exactly what the deterministic predecessors plot. Nothing draws \(\phi\), nothing draws the production function \(f\), and nothing simulates a path of \(\{x_t\}\) under \(\sigma^*\), so the reader never sees the randomness the lecture is about. Second, 694-699 encodes the iteration index in plt.cm.jet colours and then explains the encoding in prose at 711 (“hotter colors given to higher iterates”) - a colorbar would carry that inside the figure, and jet is not perceptually ordered so the encoding is hard to read even once explained. Third, the accuracy claims at 681, 776 and 801 are made in words about figures where two curves overlap; a plot of \(v_{\text{approx}} - v^*\) would show the error that the overlap hides.

Low severity#

  • [qe-code-004] — Use quantecon Timer context manager. Count: 1. Lines: 843. Example: %%time.

  • [qe-writing-008] — Remove excessive whitespace between words. Count: 1. Lines: 818. Example: 2 spaces.

Strengths#

  • Every mathematical object is later reachable by name in the code: B at 522 is the display at 517, T at 556 is {eq}`fcbell20_optgrowth`, get_greedy at 578 is {eq}`defgp20`, and x_grid/shocks on the Model tuple are the grid and the draws from \(\phi\) - so the implementation can be read against the theory line for line.

  • The machinery is validated before it is trusted: 660-679 applies T once to the exact \(v^*\) and plots \(Tv^*\) against \(v^*\), which catches a bug in B, in the interp1d call or in the Monte Carlo average before a single iteration is run, and 681 states what the reader should see.

  • The closed-form solution of {cite}`Ljungqvist2012` (609-625) is transcribed term by term into v_star as c1-c4 (633-641) and σ_star (643-647), and then actually used as the benchmark in three figures (701, 768, 794) rather than quoted and abandoned.

  • The choice of Monte Carlo for the expectation is defended rather than assumed: 546-549 says it is not the most efficient quadrature but that it preserves the contraction property of the Bellman operator, with a citation to {cite}`pal2013`.

  • Shocks are drawn once at model creation with an explicit seed and stored on the tuple (507-511), so B sees the same draws at every call and T is a deterministic map - which is what makes the fixed-tolerance loop at 737-743 meaningful.

  • The four conditions on the consumption path are given as a numbered list at 141-146, and adapted is spelled out as “\(c_t\) depends only on current and historical outcomes, not on future outcomes such as \(\xi_{t+1}\)” - the assumption a first reader of a stochastic dynamic program is most likely to skip.

  • create_model types and defaults every primitive (490-500) and each Model field carries its own one-line comment (481-487), so the parameterisation is legible without reading the constructor body.