likelihood_ratio_process_2#

  • Series: lecture-python.myst

  • File: lectures/likelihood_ratio_process_2.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.4 / 10

  • Priority: HIGH

Score breakdown#

Category

Score

One-line note

Writing

3/10

qe-writing-001 ×6; qe-writing-005 ×7; qe-writing-003 ×5, +4 more.

Math

9.5/10

qe-math-009 ×3.

Code

7.5/10

qe-code-001 ×6.

JAX

out of scope

JAX rules target lecture-jax.

Figures

4/10

qe-fig-005 ×13; qe-fig-003 ×4; qe-fig-006 ×4, +2 more.

References

7.5/10

qe-ref-001 ×5.

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, g and h are module-level globals rebound five times across the file - 149-150, 622, 1107-1108, 1253-1254, 1354-1356, 1686-1688 - and simulate_blume_easley captures 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 stale h at 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 is for n in range(N) at 1441: parallel=True has nothing to parallelise without prange, 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. Meanwhile simulate_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 for a**b. 739 and 746 use f-strings with no placeholder (ax1.set_title(f'Close Beliefs')). 792-794 puts three if/elif/else bodies on the same line as their conditions. 1447-1448 writes c1_share[n, 0] = \u03bb * 1.0 / (1 - \u03bb + \u03bb * 1.0)  # This equals \u03bb rather than = \u03bb. And rng = 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_ex3 derives 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 the h bound 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 from nature_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 in likelihood_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_easley loops for t in range(1, T) (1058) over arrays initialised to np.nan (1043-1046) and never fills column 0, so sequences[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_ex7 states “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 sets 1e-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_ex3 fills in the price derivation the body skipped, lr_ex4 adds Bayesian learning to both agents, lr_ex5 widens the gap between the beliefs, lr_ex6 adds 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”), and lr_ex7 pushes 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.