additive_functionals#
Series: lecture-python-advanced.myst
File:
lectures/additive_functionals.mdAudit date: 2026-08-26
Corpus snapshot:
b83d6da399Categories audited: writing, math, code, figures, references, links, admonitions (JAX out of scope)
Overall score: 6.6 / 10
Priority: HIGH
Score breakdown#
Category |
Score |
One-line note |
|---|---|---|
Writing |
5.5/10 |
|
Math |
3.5/10 |
|
Code |
7/10 |
|
JAX |
out of scope |
JAX rules target |
Figures |
3.5/10 |
|
References |
9/10 |
|
Links |
7.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: 11. Lines: 283, 291, 312, 396, 482, 518, 563, 686, 1122, 1128, …. Example: the two long code cells carry most of the file’s style debt. Naming: 1122 and 1175 unpack a simulation into
foo, barand then readx = bar[0, :],y = bar[1, :]; 1128 names the path countI(PEP8 E741, and unlike the identity matrix at 372 it has no mathematical justification - it isn_paths); 1132-1133 usestoreX/storeY, 516, 599 and 682 useLI, UI, and 562, 571 and 656 useMdist/Sdist, all camel- or upper-case locals with no mathematical reading. Spacing and continuation: 482 and 648 writefor t in range (T)(E211); 396 hasobs = temp * FFinv * tempwith a double space; 572 hasscale = np.exp(...)and 657scale= np.exp(...)as keyword arguments (PEP8 asks for no spaces either side); the argument lists at 517-524, 601-609, 683-685, 1314-1316 and 1426-1434 are indented to arbitrary columns well past their opening delimiter (E128), and 563-570, 581-593, 657-664 and 671-676 add backslash continuations inside parentheses where they are inert; 615, 1086-1090, 1099-1101 and 1239 leave trailing whitespace; 461 and 615 follow a top-leveldefwith one blank line where 531 uses two. Redundant or dead:(.5)at 386, 400, 564, 582, 589, 658 and 672 wraps a float literal in parentheses; 587 writes1/np.exp(-y[...])wherenp.exp(y[...])is the same thing and is what 580 and 588 do;ldens_to_plotis built at 1252-1253 and never used;amfis a parameter ofplot_given_paths(415) andplot_martingale_paths(615) and is never read in either body; andself.add_decompis set toNoneat 279 and never assigned beforeconstruct_ssruns at 302, so theif self.add_decomp:branch at 312-313 is unreachable. Three items are latent defects rather than style: 283 and 289 testif not np.any(F)/if not np.any(ν)where the signature’s sentinel isNone, so a genuine all-zeroForνsilently takes the default branch; 291 usestype(ν) == floatinstead ofisinstance(E721); and 396’stemp * FFinv * tempis elementwise, which is a quadratic form only whenk == 1, in a class whose docstring at 248 promises it “Handles both matrix and scalar inputs”. Finally 686-687 puts a backslash continuation inside a string literal, so the figure title readsMartingale components for many paths offollowed by thirty-two spaces and then$y_1$.[qe-fig-001] — Do not set figure size unless necessary. Count: 9. Lines: 422, 622, 718, 1059, 1085, 1255, 1312, 1367, 1425. Example: figsize=.
[qe-fig-003] — No matplotlib embedded titles. Count: 11. Lines: 431, 441, 451, 456, 526, 610, 686, 721, 724, 1258, …. Example: .set_title.
[qe-fig-005] — Descriptive figure names for cross-referencing. Count: 10. Lines: 696, 874, 930, 964, 1054, 1074, 1220, 1308, 1352, 1414. Example: code-cell figure without mystnb figure metadata.
[qe-fig-008] — Use lw=2 for line charts. Count: 23. Lines: 425, 426, 427, 429, 435, 436, 445, 446, 455, 720, …. Example: plot() without lw=.
[qe-link-002] — Use doc links for cross-series references. Count: 5. Lines: 128, 227, 773, 1279, 1285. Example: raw link to python-intro.quantecon.org.
[qe-math-009] (reviewer) — Choose simplicity in mathematical notation. Count: 5. Lines: 55, 900, 906, 970, 989. Example: \(\phi\) carries three unrelated meanings. At 55 it is the multiplicative functional itself (“if a process \(\{y_t\}\) is an additive functional and \(\phi_t = \exp(y_t)\)”), at 210 it is the autoregressive lag polynomial \(\phi(z)\), and at 202-204 (and
ϕ_1..ϕ_4in code at 697) it is the four AR coefficients - and the object introduced as \(\phi_t\) at 55 is renamed \(M_t\) at 892 without a word, 840 lines later. The tilde macro is inconsistent for the same symbol:\widetilde M_tat 906, 914, 950, 978, 984, 989, 1005-1030 against\tilde M_tat 970 and 1106 and\tilde{M}_tat 1111 and 1258, and{\widetilde M}_tat 989. Case is inconsistent inside a single pair of displays: 900 writes the martingale sum as \(\sum_{j=1}^t H \cdot Z_j\) with an uppercase \(Z\) where 914 and 984 use lowercase \(z_j\), and 906 writes \(\tilde e(X_0)/\tilde e(x_t)\) with an uppercase \(X_0\) where every other appearance of the initial state is \(x_0\) (103, 735, 881, 900, 920).[qe-math-010 (proposed)] — Blackboard \mathbb{P}, \mathbb{E}, \mathbb{V} with braces. Count: 16. Lines: 999, 1005, 1008, 1013, 1030, 1099, 1295, 1297, 1328, 1339, …. Example: non-blackboard
\mathrm{Var}.[qe-writing-008] — Remove excessive whitespace between words. Count: 21. Lines: 38, 44, 57, 66, 68, 89, 207, 225, 229, 863, …. Example: 2 spaces.
Medium severity#
[qe-math-011 (proposed)] — Distribution names in plain letters, not \mathcal / \mathbb. Count: 4. Lines: 101, 103, 120, 989. Example: decorated distribution
{\cal N}.[qe-writing-002] (reviewer) — Keep writing clear, concise, and valuable. Count: 3. Lines: 38, 862, 943. Example: the opening four paragraphs (38-46) take four sentences to say that growth breaks stationarity and that two model classes accommodate it, with 44 running to 33 words and restating 42 (“But there are good ways to model time series that have persistent growth that still enable statistical learning based on a law of large numbers for an asymptotically stationary and ergodic process”). 862-867 is three paragraphs and a parenthetical to say that the class also handles multiplicative functionals, one of which is a gloss on the class’s own name. And two sentences are missing words: “It is interesting to how the martingale behaves as \(T \rightarrow +\infty\)” (943) and “only the squared norm \(H \cdot H\) and \(t\) matters” (1443).
[qe-writing-003] (reviewer) — Maintain logical flow. Count: 4. Lines: 243, 871, 927, 1252. Example: 160 lines of implementation arrive before the reader is told what they are for: the
AMF_LSS_VARclass occupies 243-406 and the three plotting functions 412-690, while the section that explains the class is “## Code” at 858-867, which has to open by pointing backwards - “The classAMF_LSS_VARmentioned{ref}`above <amf_lss>`does all that we want” - and only then reveals what AMF stands for (865-867). The prose at 871-872 and 927-928 then instructs the reader to do by hand what the executed notebook has already done: “If you run{ref}`the code that first simulated that example <addfunc_egcode>`again and then the method call you will generate (modulo randomness) the plot” (also missing a verb) and “If you run … again and then the method call in the cell below you’ll obtain the graph in the next cell” - both immediately above cells that run unconditionally. And the same object is named three different things in three consecutive paragraphs: “population 95% probability coverage sets” (879), “population 95% confidence bands” (935) and “purple 95 percent frequency coverage interval” (974), of which the middle one is the wrong term for a population object.[qe-writing-005] (reviewer) — Use bold for definitions, italic for emphasis. Count: 4. Lines: 124, 960, 1097, 1268. Example: the lecture’s named phenomenon is formatted three ways: peculiar property in bold at 960 (“The second is a peculiar property noted and proved by Hansen and Sargent”) and again in bold at 1268, but peculiar property in italic at 1097. The two growth types are handled the other way round from the two process classes: 50-51 bolds the definitions additive functionals and multiplicative functionals, while 124 and 55 italicise arithmetic growth and, at 51, quote “geometric growth” - three treatments for one pair of defined terms. 881 uses italic correctly for emphasis (“all starting from the same non-random initial conditions”), which is what makes the definitional italics stand out.
[qe-writing-007] (reviewer) — Use visual elements to enhance understanding. Count: 3. Lines: 615, 1252, 1255. Example: the figure that carries the lecture’s headline claim has no axes at all:
plot_martingale_paths(615-631) draws a shaded band, a horizontal line and 25 paths, with no axis labels, no legend and no tick annotation, and it is the figure used for the \(T = 12000\) demonstration of the peculiar property at 964-967 - so the “purple 95 percent frequency coverage interval collapses around zero” that 974 asks the reader to see is unlabelled on both axes. Second, the six-panel density figure at 1255-1265 is built withoutsharex/sharey, so each panel auto-scales and the leftward collapse claimed at 1270-1272 has to be inferred across six differently scaled axes; andldens_to_plot- the densities of \(\log \widetilde M_t\), the Gaussian object that 989 says the whole property follows from - is computed at 1252-1253 and then never plotted, so the one panel that would make the argument obvious is constructed and discarded. Third,plot_given_pathsputs the titles inside the axes (431, 441, 451, 456) and the panels share a \(y\) axis (sharey=True, 422) even though \(y_t\), \(m_t\), \(s_t\) and \(\tau_t\) have very different scales, which is what forces the martingale panel’s band to be read against the trend panel’s range.
Low severity#
[qe-ref-001] — Use correct citation style. Count: 1. Lines: 82. Example:
{cite}in narrative flow: ‘{cite}’.
Strengths#
The additive functional is built from two named pieces with every dimension stated - the VAR
{eq}`old1_additive_functionals`with \(x_t\) \(n\times1\), \(A\) \(n \times n\) stable, \(z_{t+1}\) \(m \times 1\) IID, \(B\) \(n \times m\) (99-103), then the increment equation{eq}`old2_additive_functionals`as a function of exactly three listed objects (105-118) - so a reader can check any later matrix against a declared shape.The state-space embedding is shown twice at increasing size and the second one is derived from the first: 132-183 builds the three-block system for \((1, x_t, y_t)\), and 780-853 extends it to the five-block system for \((1, t, x_t, y_t, m_t)\) whose observation matrix picks out \(\tau_t\), \(m_t\) and \(s_t\) directly (814-836) - which is precisely the
Abar/Gbarconstruction the code assembles row by row with a comment naming each row’s target (328-352).The decomposition is stated as an identity with each term labelled in the display itself -
\underbrace{t\nu}_{\text{trend component}}, the martingale sum overbraced, \(-g x_t\) as the stationary component, \(g x_0 + y_0\) as initial conditions (753-760) - and 763 then asks the reader to verify that differencing it returns{eq}`old2_additive_functionals`, which is the one check that makes the whole decomposition credible.The peculiar property is set up as two separately checkable claims - \(E_0 \widetilde M_t = 1\) for all \(t\), yet \(\widetilde M_t \to 0\) almost surely (952-955) - the first is explained in one line from the martingale property (957-958), and then 964-974 demonstrates both at once by extending the horizon to \(T = 12000\) and pointing at the mean line and the collapsing coverage band separately.
The moment section reduces everything to one scalar and says so: 999 defines \(a_t := t(H\cdot H) = \mathrm{Var}(\log \widetilde M_t)\), 1005 gives every raw moment as \(\exp(\tfrac12 k(k-1)a_t)\), 1013-1021 gives variance, skewness and kurtosis in terms of \(a_t\) alone, and 1026 states the consequence - which is exactly what Exercise 3 (1393-1443) then asks the reader to verify by choosing two different \(H\) vectors with the same norm.
1099-1101 explains the shape of the distribution rather than describing the plot: “most probability density concentrates near zero, while a long right tail preserves the unit mean” is the reconciliation of the two properties at 952-955, and 1270-1275 restates it as four checkable observations about the six density panels.
The three exercises build on the two functions the lecture just defined (
log10_raw_moment,log10_var_skew_kurt,squared_norm) rather than on new code, and each solution ends with the analytical reason for what the plot shows - the \(k=1\) slope is zero because \(E[\widetilde M_t]=1\) (1328), and \(\log_{10}(\mathrm{Var}+1) = a_t\log_{10} e\) is linear because \(\mathrm{Var}+1 = e^{a_t}\) (1387-1388).
Recommended actions#
Fix the three latent defects in
AMF_LSS_VAR: 283 and 289 should testF is None/ν is Nonerather thannot np.any(...), which mishandles a genuine zero matrix; 291 should useisinstance(ν, float); and 396’sobs = temp * FFinv * tempis elementwise, sologlikelihood_pathis only correct for a scalar observation, contradicting the class docstring at 246-248.Delete the dead code:
ldens_to_plot(1252-1253), the unreachableif self.add_decomp:branch (312-313, sinceadd_decompisNonewhenconstruct_ssruns at 302), and the unusedamfparameter ofplot_given_paths(415) andplot_martingale_paths(615).Rename
foo, barat 1122 and 1175, the path countIat 1128, andstoreX/storeY,Mdist/Sdist,LI/UI- none has a mathematical reading, unlike the identityIat 372 and the matricesA, B, D, F, H, which should stay capitalised.Give the martingale figure axes:
plot_martingale_paths(615-631) has no axis labels, no legend and no title, and it is the figure the \(T = 12000\) demonstration at 964-974 depends on; then addshareyto the six density panels at 1255 and plot the \(\log \widetilde M_t\) densities thatlogMtilde_t_densityalready computes.Settle the notation: rename the multiplicative functional so that \(\phi_t\) at 55 and \(M_t\) at 892 are one symbol (and so \(\phi\) is left to the AR polynomial at 210 and the coefficients at 202), pick one of
\widetilde M/\tilde M/{\widetilde M}, and lowercase \(Z_j\) at 900 and \(X_0\) at 906 to match 914, 984 and 103.Move the class and the plotting functions (243-690) below the exposition that describes them at 858-867, or move a short statement of what
AMF_LSS_VARis and what AMF stands for above line 243 - and drop the “if you run the code again” instructions at 871-872 and 927-928, which describe a manual workflow the executed cells make unnecessary.Pick one name for the shaded regions - 879 says “probability coverage sets”, 935 “confidence bands”, 974 “frequency coverage interval” - and use “coverage”, since these are population objects computed from
LinearStateSpacemoments and not confidence intervals.Run the PEP8 sweep listed under qe-code-001:
range (T)at 482 and 648, the misaligned continuations at 517-524, 601-609, 683-685, 1314-1316 and 1426-1434, the inert backslashes inside parentheses at 563-593 and 657-676, the(.5)literals, the keyword spacing at 572 and 657, and the backslash inside the string literal at 686-687.Finish the mechanical items: the eleven embedded titles (431, 441, 451, 456, 526, 610, 686, 721, 724, 1258, 1261),
mystnb: figure: caption/nameon the ten figure cells, the ninefigsize=, the 23plot()calls withoutlw=2, the five raw links to{doc}(128, 227, 773, 1279, 1285), the four{\cal N}/{\mathcal N}(101, 103, 120, 989 - qe-math-011, proposed), the sixteen\mathrm{Var}/\mathrm{Skew}/\mathrm{Kurt}and bareE(qe-math-010 (proposed)),{cite}to{cite:t}at 82, and the 21 double spaces.