wald_friedman_2#
Series: lecture-python.myst
File:
lectures/wald_friedman_2.mdAudit date: 2026-08-26
Corpus snapshot:
e25fdf2345Categories audited: writing, math, code, figures, references, links, admonitions (JAX out of scope)
Overall score: 7.0 / 10
Priority: HIGH
Score breakdown#
Category |
Score |
One-line note |
|---|---|---|
Writing |
3/10 |
|
Math |
6/10 |
|
Code |
7.5/10 |
|
JAX |
out of scope |
JAX rules target |
Figures |
5/10 |
|
References |
9/10 |
|
Links |
8.5/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: 182, 473, 567, 597, 645, 663. Example: three lambdas are bound to names (E731):
f0andf1at 182-183 andh_funcat 473, whose parameterpalso shadows the module-level functionpdefined at 178 and used insidef0/f1. 645-648 assigns five locals insimulate-f0,f1,f0_rvs,f1_rvs,π_grid- and uses none of them, because 651 and 653 re-fetchwf.f0andwf.f0_rvsdirectly (F841 x5). 663 testswhile decision_made is False:wherewhile not decision_made:is the idiom. 575 and 583 useassert False, "..."to signal an error condition;assertis stripped underpython -O, soraise ValueErroris the correct form. 597 omits the space after a comma,np.column_stack([...]),axis=1(E231). Five lines carry trailing whitespace (567, 571, 576, 577, 579), including a comment ending in two spaces at 577. And the decorators are inconsistent: 462 writes@jit(nopython=True, parallel=True)wherenopython=Trueis now the default, while 177, 497 and 552 use a bare@jit. The docstrings at 640, 555 and 690 are also separated from theirdefby a blank line, against PEP 257.[qe-fig-003] — No matplotlib embedded titles. Count: 5. Lines: 188, 192, 534, 713, 719. Example: .set_title.
[qe-fig-008] — Use lw=2 for line charts. Count: 5. Lines: 532, 533, 593, 594, 595. Example: plot() without lw=.
[qe-math-010 (proposed)] — Blackboard \mathbb{P}, \mathbb{E}, \mathbb{V} with braces. Count: 9. Lines: 131, 142, 278, 315, 321, 327, 349, 350, 457. Example: missing braces:
\mathbb P.[qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 6. Lines: 46, 57, 59, 109, 122, 343. Example: 57 is a single sentence of about 75 words running from “In this lecture, we reformulate…” to “…sampling from that joint distribution”, carrying two scare-quoted terms, a cross-reference and three relative clauses. 46 is 48 words. 59-62 argues in a circle across two sentences - the prior lets the statistician form the joint distribution, and the joint distribution lets him “calculate the conditional distributions that he wants”, which are the conditionals he started from. 109-113 is two four-line sentences differing only in a subscript. 122-123 restates 107 and 120 for the third time (“He (or she) wants to know which of two probability distributions \(f_0\) or \(f_1\) governs \(z\)” / “The observer has something to learn, namely, whether the observations are drawn from \(f_0\) or from \(f_1\)” / “The decision maker wants to decide which of the two distributions is generating outcomes”). And 343-381 displays the same integral three times in forty lines - as the third line of
{eq}`optdec2`, again as{eq}`funceq`, and again as \(Qh(\pi)\) - with only the left-hand side changing. The two bulleted idea lists at 70-84 also overlap: all four items of the second list are already in 64-68.[qe-writing-003] (reviewer) — Maintain logical flow. Count: 6. Lines: 254, 454, 532, 603, 631, 750. Example: 631 and 635 state specific numbers - “The average number of draws is around 6.6” and “the decision-maker is correct 80% of the time” - about a figure produced by an unseeded simulation: the file contains no
seedordefault_rngcall anywhere, and 424-425, 436 and 439 all callnp.random.betadirectly, so both figures and both numbers change on every build. 603-604 draws the two cutoff markers at the wrong heights: with \(\pi\) the probability that \(f=f_1\) (131), the binding cost at \(\pi=B\) is \(B L_0\) and at \(\pi=A\) is \((1-A)L_1\) - as 613-614 says - but the code writesplt.vlines(B, 0, (1 - B) * wf.L1)andplt.vlines(A, 0, A * wf.L0), i.e. each line is drawn to the other branch’s cost. The sibling lecturenavy_captainhas the same figure with the assignment the other way round at its lines 585-586. 531-537 plots the two densities with no x data -ax.plot(wf.f0(wf.π_grid))- so the axis runs over grid indices 0 to 199 while 534 labels it “\(z_k\)”, and it reusesπ_grid, a grid of beliefs, as the grid of \(z\) values; the equivalent cell at 184-202 does it correctly with its owngrid. 454 and 753-757 call the object a “value function” where the rest of the lecture, its headings and its code call it a cost function (267, 500, 540, 556, 607, 613). 750-759 invites four investigations and one of them turns on “the number of points and linear functions \(m\)”, where \(m\) is never defined in the lecture - the grid parameter isπ_grid_size- and the same passage says “piecewise linear approximation” at 754 and “piecewise continuous approximation” at 757 for the same thing. And the{figure}at 254-256 has an empty body: no caption, no:name:, no alt text, for the picture 252 introduces as “the following figure”.[qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 5. Lines: 48, 57, 103, 269, 762. Example: 103 sets a book title in bold - Dynamic Programming and Stochastic Control - where a title takes italic; 269 re-bolds dynamic programming 226 lines after the definition at 43. Emphasis is carried by single quotes rather than italic in five places: ‘hypothesis’ (48), ‘conditions on the parameters’ (53), and ‘objective’ and ‘subjective’ at 57. The one italic in the file is exchangeable at 762, which is a term being introduced and so belongs in bold - and the definitions the lecture does bold (sequential probability ratio test 75, power 76, critical region 77, uniformly most powerful test 78, functional equation 367, stopping times 629) show the convention is otherwise understood.
[qe-writing-006] — Capitalize lecture titles properly. Count: 6. Lines: 100, 205, 225, 265, 540, 728. Example: H2 Title Case: ‘A Dynamic Programming Approach’ (Dynamic, Programming, Approach).
[qe-writing-008] — Remove excessive whitespace between words. Count: 43. Lines: 36, 38, 40, 46, 57, 66, 80, 83, 117, 120, …. Example: 2 spaces.
Medium severity#
[qe-fig-001] — Do not set figure size unless necessary. Count: 4. Lines: 186, 531, 591, 710. Example: figsize=.
[qe-fig-005] — Descriptive figure names for cross-referencing. Count: 4. Lines: 176, 254, 528, 551. Example: {figure} without :name:.
[qe-link-001] — Use markdown style links for lectures in same lecture series. Count: 2. Lines: 117, 763. Example: full URL to own series (python.quantecon.org).
[qe-math-009] (reviewer) — Choose simplicity in mathematical notation. Count: 4. Lines: 131, 156, 318, 349. Example: 131 puts prose inside a probability - \(\mathbb P \{ f = f_1 \mid \textrm{ no observations} \}\), with a leading space inside the braces - to say that \(\pi_{-1}\) is the prior, which the surrounding sentence already says. 156 writes the mixture as \(f_{{\pi}_k}(v)\), with a redundant brace group inside the subscript, where 291 writes the same object as \(f_{\pi}(v)\). 318 says “two numbers \(A, B \in (0,1) \times (0,1)\)”, which asserts that each of \(A\) and \(B\) lies in a product of two intervals; \(A, B \in (0,1)\) is what is meant. And 349-350 writes the same expectation two ways one line apart, \(\mathbb E [J(\pi')]\) then \(\mathbb E_{\pi'} \min\{\cdots\}\), with spaces inserted inside the delimiters throughout (\(J (\pi')\) at 278).
[qe-writing-001] — Use one sentence per paragraph. Count: 2. Lines: 36, 762. Example: 2 sentences in one paragraph.
[qe-writing-004] — Avoid unnecessary capitalization in narrative text. Count: 2. Lines: 103. Example: mid-sentence ‘Programming’.
[qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 4. Lines: 254, 715, 728, 750. Example: the lecture’s most important picture - the \([0,B]\), \((B,A)\), \([A,1]\) partition that is the answer - is a static PNG dropped in at 254 with an empty directive body, no caption and no name. It is also schematic, so it shows invented cutoffs rather than the ones computed at 587, even though drawing three intervals on a line with the real \(A\) and \(B\) is a handful of matplotlib calls. 728-748 sets up a comparative static, asks the reader to predict two outcomes (736-737), and then produces a new pair of histograms at 741 with independently auto-scaled axes 15 lines below the baseline pair at 725 - so the comparison the section exists to make has to be done from memory across two figures. 715-721 positions both annotations by arithmetic on the data (
xy=(max(tdist)/2, max(np.histogram(tdist, bins=max(tdist))[0])/2)), which will land on top of the bars for other parameter settings, and the right-hand panel is a two-bin histogram of a boolean - a bar chart of two numbers, one of which is also printed as the annotation beside it. And 750-759 hands the reader four investigations as a plain bulleted list rather than an{exercise}, so none of them is numbered, linkable or answerable; the lecture has no exercise at all.[qe-writing-009 (proposed)] — Write “IID” — not “i.i.d.” or “iid”. Count: 2. Lines: 46, 66. Example: i.i.d…
Low severity#
[qe-fig-002] — Prefer code-generated figures. Count: 1. Lines: 254. Example: static image .png.
[qe-ref-001] — Use correct citation style. Count: 1. Lines: 764. Example:
{cite}in narrative flow: ‘{cite}’.
Strengths#
The
{note}at 134-137 flags a notational departure from the source the lecture is following: Bertsekas attaches the belief to \(f_0\), this lecture attaches it to \(f_1\), and the note says so and gives the reason - to match the frequentist lecture it is paired with. A reader holding the book open is told exactly where the two differ.The Bellman equation is developed as five successive rewritings, each labelled and each a transformation of the one before:
{eq}`new1`at 271-280 with\underbracenaming its three branches,{eq}`optdec`at 302-307 abbreviating the continuation value as \(h(\pi)\),{eq}`optdec2`at 345-353 unfolding \(h\) into an integral,{eq}`funceq`at 357-362 isolating the equation in the unknown function, and the operator \(Qh\) at 378-381 that the code then implements.240-263 asks the reader to guess the answer before deriving it - three sentences of reasoning about \(\pi\) near 1, near 0 and in the middle, then the schematic, then “You might like to pause at this point and try to predict the impact of a parameter such as \(c\) or \(L_0\) on \(A\) or \(B\)” - and 730-737 uses the same device again before doubling \(c\).
The type I/type II bookkeeping is set up once and then attached to the specific terms where it matters: 227-238 identifies \(L_1\) with a type I error and \(L_0\) with a type II error under the null \(f=f_0\), and 311-314 labels \(\pi L_0\) and \((1-\pi)L_1\) with those errors at the point they enter
{eq}`optdec`.Events are written with braces throughout - \(\mathbb P\{f = f_1 \mid z_k, z_{k-1}, \ldots, z_0\}\) (142) - which is what proposed qe-math-014 (proposed) asks for, and the density case convention is never broken: \(f_0\), \(f_1\), \(f_\pi\) and \(f(z;a,b)\) are all lowercase densities and no CDF is introduced.
454-457 states the numerical approximation before the code that implements it - iterate on a finite \(\pi\) grid, use linear interpolation between grid points when evaluating \(\mathbb E[J(\pi')]\) - so
h_func = lambda p: np.interp(p, π_grid, h)at 473 arrives already explained.The mixture figure at 176-202 shows the two component densities in one panel and three mixtures at \(\pi_k = 0.25, 0.5, 0.75\) in the other, with the mixing weight in each legend label, so the object defined at 155-160 is visible before it is used in the Bellman equation.
Recommended actions#
Seed the simulations.
np.random.betais called unseeded at 424-425, 436 and 439, and 631 and 635 assert “around 6.6” draws and “correct 80% of the time” about figures that are redrawn on every build - either seed the draws or stop quoting the numbers in the prose.Fix the swapped cutoff markers at 603-604: at \(\pi = B\) the binding cost is \(B L_0\) and at \(\pi = A\) it is \((1-A) L_1\), per 613-614, so the two
vlinesheights are exchanged relative to the branches they mark.Fix the distributions figure at 531-537: pass an x grid to
ax.plot, so the axis labelled “\(z_k\)” at 534 actually carries \(z\) values instead of the indices 0-199, and use a grid of \(z\) rather than reusingπ_grid, which is a grid of beliefs.Replace the static PNG at 254 with a generated figure that draws the three intervals using the \(A\) and \(B\) computed at 587, and give it a caption and a
:name:so 252’s “the following figure” can become a cross-reference - the directive body is currently empty.Settle one name for \(J\): “cost function” in the headings, prose and code against “value function” at 454, 753 and 757. In the same pass define or delete the undefined \(m\) at 757 and reconcile “piecewise linear” (754) with “piecewise continuous” (757).
Turn 750-759 into an
{exercise}with a solution - four numbered investigations that are currently a bulleted list, in a lecture with no exercise at all - and put the baseline and doubled-\(c\) histograms of 725 and 741 on shared axes so the comparative static at 744-748 can be seen rather than remembered.Code cleanup: convert the three lambdas (182, 183, 473) to
defs and rename theh_funcparameter that shadowspfrom 178; delete the five unused locals at 645-648; replaceassert Falseat 575 and 583 withraise ValueError; change 663 towhile not decision_made:; add the comma space at 597; strip the trailing whitespace at 567, 571, 576, 577 and 579; and make the@jitdecorators consistent (462 against 177, 497, 552).Add the braces the nine
qe-math-010(proposed) sites need -\mathbb Pand\mathbb Eat 131, 142, 278, 315, 321, 327, 349, 350, 457 - and replace the prose-inside-probability at 131 with a plain statement that \(\pi_{-1}\) is the prior.Sweep the mechanical remainder: the 43 double spaces, the six title-case headings (100, 205, 225, 265, 540, 728), the two “i.i.d.” spellings (46, 66), the two full
python.quantecon.orgURLs that should be{doc}references (117, 763), the two multi-sentence paragraphs (36, 762),mystnbmetadata and captions for the four un-named figures (176, 254, 528, 551), the fiveset_titlecalls moved into captions, the fourfigsizeoverrides, andlw=2on the five bareplot()calls.