os_stochastic#
Series: lecture-python.myst
File:
lectures/os_stochastic.mdAudit date: 2026-08-26
Corpus snapshot:
e25fdf2345Categories 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 |
|
Math |
7/10 |
|
Code |
7.5/10 |
|
JAX |
out of scope |
JAX rules target |
Figures |
7.5/10 |
|
References |
10/10 |
no mechanical violations detected. |
Links |
8/10 |
|
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 adef, and names the argumentxwhere every other use ofxin 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 inclass Modelwith 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 gridline up; 653-655 and 832-834 putα = 0.4andγ = 1.5immediately against a top-leveldefwith no blank line, where 632-643 does leave one; and 670-671 uses a 4-space gap before# Start at the solutionand a 13-space gap before# Apply T onceon 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_modelcomputeserrorat 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 showsT; line 575 then says “Here’s the function:” and showsget_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 arrayv_newat 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 (
ν: floatat 485 alongsidev_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 inplt.cm.jetcolours and then explains the encoding in prose at 711 (“hotter colors given to higher iterates”) - a colorbar would carry that inside the figure, andjetis 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:
Bat 522 is the display at 517,Tat 556 is{eq}`fcbell20_optgrowth`,get_greedyat 578 is{eq}`defgp20`, andx_grid/shockson theModeltuple 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
Tonce to the exact \(v^*\) and plots \(Tv^*\) against \(v^*\), which catches a bug inB, in theinterp1dcall 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 intov_starasc1-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
Bsees the same draws at every call andTis 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_modeltypes and defaults every primitive (490-500) and eachModelfield carries its own one-line comment (481-487), so the parameterisation is legible without reading the constructor body.
Recommended actions#
Replace the placeholder sentence at 79 and repair the sentence broken across 96-106: the “and” ending 96 is closed at 104, and 106 then opens with a second dangling “and all variables are required to be nonnegative”.
Introduce
get_greedybefore showing it - 575’s “Here’s the function:” refers to a function the prose never names - and fixT’s return annotation at 556, which promises a two-tuple where 572 returns one array.Make exercise 1 and its solution solve the same problem: 813-815 states \(u(c) = c^{1-\gamma}/(1-\gamma)\), 835 codes
(c**(1 - γ) - 1) / (1 - γ).Rename the labels left over from the lecture’s previous life as an optimal-growth lecture -
(optgrowth)=at 12,(benchmark_cake_mod)=at 595 on a section titled “An Example”, and thetexs0_og2,og_conse,idp_fp_og2,firstp0_og2,fcbell20_optgrowth,og_ex1equation and exercise labels - so a reader searching the source for “savings” finds them.Sentence-case the eleven flagged headings plus the twelfth hiding inside the
{index}role at 404 (“Unbounded Utility”), addmystnb: figure: name/captionmetadata to the five figure cells (667, 688, 762, 788, 849), brace the four\mathbb Eat 122, 203, 206 and 227, and make the three raw quantecon links at 167, 187 and 273{doc}links.Add the figure the lecture is missing - the lognormal \(\phi\) of 471-475, the production function \(f\), or a simulated path of \(\{x_t\}\) under \(\sigma^*\) - and replace the verdicts at 716, 776 and 801 with the sup-norm error
solve_modelalready computes at 739; give the shock scale a symbol other than \(\nu\) while doing so.Clean the code cells:
%%timeat 843 toqe.Timer()(qe-code-004), the lambda assignment at 460, the two padded single-quote docstrings at 582 and 731, the comment gaps at 486-487 and 670-671, the missing blank lines at 653 and 832, the double space at 818, and the trailing blank line inside the imports cell at 71.