likelihood_ratio_process_2#
Series: lecture-python.myst
File:
lectures/likelihood_ratio_process_2.mdAudit date: 2026-08-26
Corpus snapshot:
e25fdf2345Categories audited: writing, math, code, figures, references, links, admonitions (JAX out of scope)
Overall score: 7.4 / 10
Priority: HIGH
Score breakdown#
Category |
Score |
One-line note |
|---|---|---|
Writing |
3/10 |
|
Math |
9.5/10 |
|
Code |
7.5/10 |
|
JAX |
out of scope |
JAX rules target |
Figures |
4/10 |
|
References |
7.5/10 |
|
Links |
10/10 |
no mechanical violations detected. |
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: 146, 600, 739, 792, 1419, 1441. Example:
f,gandhare module-level globals rebound five times across the file - 149-150, 622, 1107-1108, 1253-1254, 1354-1356, 1686-1688 - andsimulate_blume_easleycaptures them as default arguments at 600 (f_belief=f, g_belief=g), so the defaults freeze whatever was bound when the cell ran. That is the mechanism behind the stalehat 810-811, and it makes cell order load-bearing in a file with seven such rebindings.@jit(parallel=True)at 1419 decorates a function whose only loop isfor n in range(N)at 1441:parallel=Truehas nothing to parallelise withoutprange, which the sibling function at 1362-1375 uses correctly - and the same body builds string-keyed Python dicts at 1428-1431, 1443, 1454 and 1493, which nopython mode does not accept, so the decorator is at best inert. Meanwhilesimulate_learning_blume_easley(1035-1092) runs the identical N-by-T scalar double loop with no decorator at all. 146 spaces the exponentiation three different ways in one expression,r * x** (a-1) * (1 - x) ** (b-1), where the rule asks fora**b. 739 and 746 use f-strings with no placeholder (ax1.set_title(f'Close Beliefs')). 792-794 puts threeif/elif/elsebodies on the same line as their conditions. 1447-1448 writesc1_share[n, 0] = \u03bb * 1.0 / (1 - \u03bb + \u03bb * 1.0) # This equals \u03bbrather than= \u03bb. Andrng = np.random.default_rng()is called five times with no seed (67, 1125, 1248, 1595, 1723) while the prose makes quantitative claims about the output at 667-671, 690, 824-828, 1205-1209 and 1773.[qe-fig-001] — Do not set figure size unless necessary. Count: 14. Lines: 638, 730, 761, 1153, 1510, 1514, 1549, 1553, 1615, 1629, …. Example: figsize=.
[qe-fig-005] — Descriptive figure names for cross-referencing. Count: 13. Lines: 637, 708, 760, 1199, 1213, 1279, 1284, 1614, 1628, 1639, …. Example: code-cell figure without mystnb figure metadata.
[qe-ref-001] — Use correct citation style. Count: 5. Lines: 37, 412, 838. Example:
{cite}in narrative flow: ‘{cite}’.[qe-writing-001] — Use one sentence per paragraph. Count: 6. Lines: 421, 667, 669, 671, 838, 1664. Example: 2 sentences in one paragraph.
[qe-writing-003] (reviewer) — Maintain logical flow. Count: 5. Lines: 502, 673, 810, 1043, 1713. Example: 502 contradicts the lecture’s own exercise solution. The body writes the competitive-equilibrium allocation as \(c_t^1(s^t) = \frac{\mu_1 l_t(s^t)}{\mu_2 + \mu_1 l_t(s^t)}\), but the solution to
lr_ex3derives the same object at 878-892 and gets \(\frac{\mu_2 l_t}{\mu_1 + \mu_2 l_t}\) - the two multipliers transposed. The solution is the correct one, twice over: equating the two forms of{eq}`eq:priceequation1`at 487-493 gives \(c^1/c^2 = (\mu_2/\mu_1) l_t\), and 510-521 only works with \(\mu_1 = 1-\lambda\) (511, 911), which reproduces the planner’s rule{eq}`eq:allocationrule1`and the price formula{eq}`eq:pformulafinal`from the solution’s version and not from 502’s. So 502 as printed makes 510’s “formula{eq}`eq:allocationce`agrees with formula{eq}`eq:allocationrule1`” false. Second, 810-811 and 817-818 print KL divergences against thehbound at 622 - an equal mixture of the original Beta(1,1) and Beta(3,1.2) - while the figure those numbers are meant to explain draws its third column fromnature_params[...][2] = (2, 1.5)(762-763, 775), a plain Beta. 758 asks the reader “From the right panel, can we infer the relation between \(KL(h,g)\) and \(KL(h,f)\)?” and 813-814 answers with a different \(h\) than the panel used. Third, three cross-lecture references do not resolve:[this section](KL_link)(673),[that section](llr_h)(675) and{eq}`eq:kl_likelihood_link`(830) all target labels defined inlikelihood_ratio_process.md(721, 666, 730) - a bare Markdown link is read as a relative path and an{eq}label is document-local, so all three break; the sibling lecture does the same thing correctly at its own line 1826 with{ref}this section <llr_h>``. Fourth,simulate_learning_blume_easleyloopsfor t in range(1, T)(1058) over arrays initialised tonp.nan(1043-1046) and never fills column 0, sosequences[n, 0]is discarded and the figures at 1180-1181 plot a leading NaN - the three-model version at 1447-1448 seeds column 0 explicitly, so the two implementations disagree about the same convention. Fifth,lr_ex7states “Agent 2: \(\pi^g_0 = \pi^f_0 = 0\) (rigid belief in model \(h\))” (1662) and the solution’s comment repeats “Agent 2: \u03c0_f = 0, \u03c0_g = 0, \u03c0_h = 1” (1711-1712), but the code sets1e-10(1713-1714); 1749’s “agent 2 is not updating” is then only approximately true and nothing says why the zero was replaced.[qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 7. Lines: 51, 123, 397, 433, 443, 462. Example: the file has fourteen bold spans and exactly one italic, and the split is uneven in both directions. Bold is correct on the definitions - likelihood ratio process (96, 111), Pareto weights (51), rational expectations (211), continuation Pareto weight (347), competitive equilibrium (418), multilateral (468), numeraire (512) - but it also carries six plain emphases that the rule assigns to italic: provided (51), wealths (397), price (402), prices (433), vector (443, “there is (very long) vector of prices”) and single (462, “a single intertemporal budget constraint”). The one italic in the file runs the other way: 123 writes “the likelihood process satisfies the recursion”, naming a term where the rule asks for bold.
[qe-writing-008] — Remove excessive whitespace between words. Count: 80. Lines: 54, 246, 402, 408, 410, 412, 418, 421, 422, 429, …. Example: 3 spaces.
Medium severity#
[qe-fig-003] — No matplotlib embedded titles. Count: 4. Lines: 651, 739, 746, 788. Example: .set_title.
[qe-fig-006] — Lowercase axis labels. Count: 4. Lines: 650, 659, 719, 786. Example: axis label
Likelihood ratio $l_t$.[qe-fig-008] — Use lw=2 for line charts. Count: 2. Lines: 647, 657. Example: plot() without lw=.
[qe-math-009] (reviewer) — Choose simplicity in mathematical notation. Count: 3. Lines: 323, 965, 1174. Example: \(\pi\) carries three different kinds of object. It is a density through the first half - \(\pi(s_t)\), \(\pi_t(s^t)\), \(\pi^i_t(s^t)\) at 179-208, 265, 306, 543-554 - then a scalar Bayesian posterior probability at 965-968 (\(\pi_0 \in (0,1)\), \(\pi_t = \pi_0 L(s^t)/(\ldots)\)), then a posterior probability over models at 1310-1331 (\(\pi^f_0\), \(\pi^g(s^t)\)), so \(\pi^f(s^t)\) at 1322 and \(\pi^i_t(s^t)\) at 265 look alike and mean quite different things. The likelihood ratio is spelled three ways for two objects: the review section reserves \(\ell(w_t)\) for the one-period ratio and \(L(w^t)\) for its cumulative product (101-121), and then 323 introduces \(l_t(s^t) = \pi^1_t(s^t)/\pi^2_t(s^t)\) - a product over the whole history - under the lower-case letter, after which the axis label at 650 calls the cumulative product “Likelihood ratio \(l_t\)” while plotting
l_cum. And 1174 transposes the indices,r'median $\pi_i^t$', where 207, 265, 980, 985 and 1111 all write \(\pi^i_t\).[qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 4. Lines: 34, 437, 448, 1294. Example: the passage that sets up the budget constraint loses a word in three consecutive sentences: 435 reads “Trade is multilateral in the sense that that there is a “Walrasian auctioneer””, 437 - the sentence that actually states the constraint - reads “requires that the total value of the agent’s endowment stream be at least as the total value of its consumption stream”, dropping “great as”, and 448 reads “These prices determined at time \(-1\) before the economy starts”, dropping “are”. 1289-1294 breaks a parallel across a stray blank line: “So learning occurs more quickly.” then, two lines later, “So do consumption shares.” - which does not complete the construction. And 34 is a 45-word single sentence carrying the whole research programme (“Blume and Easley constructed formal models to study how differences of opinions about probabilities governing risky income processes would influence outcomes and be reflected in prices of stocks, bonds, and insurance policies that individuals use to share and hedge risks”).
[qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 3. Lines: 289, 530, 638. Example: the analytical core of the lecture - the planner’s problem and its equivalence to the competitive equilibrium, 289 to 537 - carries no figure at all, although the allocation rule
{eq}`eq:allocationrule1`is a two-line plot in \(l_t\) and \(\lambda\) that would put all three limiting cases enumerated at 371-394 on one set of axes and show the continuation Pareto weight \(\lambda_t\) of 350 moving. The three limiting cases of the price formula listed at 530-534 are likewise never plotted, even though{eq}`eq:pformulafinal`is closed-form in objects the simulations already compute. And the figure at 638-664, which the lecture builds up to with an explicit invitation to guess (633-636), labels only its top row:ax.set_title(title)is inside the first block (651) and the three consumption-share panels below get no title, so the reader has to count columns to know which is which - and the top row is log-scaled (648) while the bottom is not, with nothing saying so.[qe-writing-009 (proposed)] — Write “IID” — not “i.i.d.” or “iid”. Count: 4. Lines: 186, 202, 207, 262. Example: i.i.d…
Low severity#
None found.
Strengths#
The lecture is honest about the shape of its own argument and signposts each turn: 46-49 states the two arrangements to be compared before either is built, 51 states the theorem that will connect them and the condition it needs, 505-508 announces the guess-and-verify as a matching exercise with two named items, and 536 says plainly which verification is left to the reader.
The self-contained review at 70-136 rebuilds every object the lecture needs - the two candidate densities, nature’s once-and-for-all choice, the per-period ratio \(\ell(w_t)\), the cumulative \(L(w^t)\), the recursion \(L(w^t) = \ell(w_t)L(w^{t-1})\), and the mean-one property under \(g\) (107-109) - so the lecture reads without the prerequisite open in another tab.
The proposed
qe-math-015(proposed) convention holds throughout: densities and mixtures are lowercase everywhere (\(f\), \(g\), \(h\), \(\pi\), \(\pi^i\), \(m^i\) at 74-81, 543-557, 974-986, 1304-1317), and the uppercase letters are reserved for cumulative products and likelihoods (\(L(w^t)\) at 115, \(L(s^t)\) at 962), so no CDF-versus-density confusion arises.The planner’s allocation rule is derived to a form that carries the economics rather than stopping at the first-order condition: 310-345 goes from the FOC to \(c^1_t = \lambda l_t/(1-\lambda+\lambda l_t)\), and 347-363 then renames that expression the continuation Pareto weight \(\lambda_t(s^t)\) so that the rule becomes \(c^1_t = \lambda_t\) - which makes the three limiting cases at 371-394 readable directly off the definition.
The reader is repeatedly asked to predict before being shown: 633 (“have some fun by guessing whether agent 1 or agent 2 will have a larger and larger consumption share”), 756-758 (“Staring at the figure below, can we infer the relation between \(KL(f,g)\) and \(KL(g,f)\)?”), 1635-1637 (“Before reading the next figure, please guess how consumption shares evolve”) - and each guess is then settled with a computed number, not an assertion (685-687, 813-821).
The KL divergences are computed by quadrature rather than approximated, in two small composable functions (573-594), and then used to explain the simulation asymmetry rather than merely reported: 690-696 states the two inequalities, 692 says what the first one means in words (“the average “surprise” from having belief \(g\) when nature chooses \(f\) is greater than …”), and 824-828 uses the second to account for the different convergence speeds across panels.
The five exercises form a genuine progression rather than a set of variations:
lr_ex3fills in the price derivation the body skipped,lr_ex4adds Bayesian learning to both agents,lr_ex5widens the gap between the beliefs,lr_ex6adds a third model and a general-versus-simple contrast that ends in a real conclusion (1646-1650, “Agent 1 learns more quickly because he uses a simpler model”), andlr_ex7pushes one agent to a near-dogmatic prior and shows learning stall (1747-1754).Side material is factored into
{note}blocks rather than interrupting the argument - the Alchian and Friedman conjecture (36-39), where the welfare theorems are applied elsewhere (53-55), what a rational-expectations model would assume (210-212), the wealth interpretation of the three limiting cases (396-403), and the numeraire question (514-516) - and the last of these is the objection a careful reader raises at exactly that point.
Recommended actions#
Fix
{eq}`eq:allocationce`at 502: it should read \(c_t^1(s^t) = \frac{\mu_2 l_t(s^t)}{\mu_1 + \mu_2 l_t(s^t)}\), as the lecture’s own solution derives at 878-892. As printed, 510’s claim that{eq}`eq:allocationce`agrees with{eq}`eq:allocationrule1`under \(\mu_1 = 1-\lambda\), \(\mu_2 = \lambda\) is false, and the price formula at 521 does not follow.Recompute the KL diagnostics at 810-811 and 817-818 against the \(h\) the figure actually uses -
nature_params[...][2]is Beta(2, 1.5) at 762-763, not the 622 mixture - or change the figure’s third column to draw from the mixture, so that 758’s question and 813-821’s answer concern the same distribution.Repair the three broken cross-lecture references: 673 and 675 to
{ref}this section <KL_link>/ `{ref}`that section <llr_h>with a{doc}pointer tolikelihood_ratio_process, and 830, which cites an equation label defined only in that other file.Seed the five
np.random.default_rng()calls (67, 1125, 1248, 1595, 1723), since 667-671, 690, 824-828, 1205-1209 and 1773 all make claims about specific figures that are redrawn from fresh draws on every build.Stop rebinding
f,gandhas globals (149-150, 622, 1107-1108, 1253-1254, 1354-1356, 1686-1688) and drop the captured defaults at 600 - pass the densities in explicitly, which is what makes the stale-hbug at 810 possible.Either give
simulate_three_model_allocation(1419) aprangeloop and a nopython-compatible body, or dropparallel=True, which currently decorates a plainrangeloop over string-keyed dicts; and decide whethersimulate_learning_blume_easley(1035) should be jitted like its two siblings.Fill column 0 in
simulate_learning_blume_easley(1043-1058) as the three-model version does at 1447-1448, so the first draw is used and the figures do not open on a NaN; and replace the1e-10at 1713-1714 with a note explaining why an exact zero prior cannot be used, since 1662 and 1711 both say zero.Sweep the presentation items: the six bold emphases moved to italic (51, 397, 402, 433, 443, 462) and recursion (123) to bold, the four “i.i.d.” spellings to “IID” (186, 202, 207, 262) - 77, 92 and 136 already do it right - the eighty double-space runs, the five
{cite}sites wanting{cite:t}(37, 412, 838), titles on the bottom row of the figure at 638-664,mystnbcaption and name metadata for the thirteen unnamed code-cell figures, lower-case axis labels at 650, 659, 719 and 786, and the fourteenfigsizeoverrides.