From 434ccfeafef0ad601ce8ce194fb131a9c21c54d3 Mon Sep 17 00:00:00 2001 From: Humphrey Yang Date: Sun, 31 Aug 2025 19:02:46 +0200 Subject: [PATCH 1/4] incorprate reader's feedback --- lectures/divergence_measures.md | 34 ++++--- lectures/imp_sample.md | 20 +++- lectures/likelihood_ratio_process.md | 136 +++++++++++++------------ lectures/likelihood_ratio_process_2.md | 40 ++++++-- lectures/likelihood_var.md | 24 ++++- 5 files changed, 161 insertions(+), 93 deletions(-) diff --git a/lectures/divergence_measures.md b/lectures/divergence_measures.md index b95d30d4e..c783fda66 100644 --- a/lectures/divergence_measures.md +++ b/lectures/divergence_measures.md @@ -4,7 +4,7 @@ jupytext: extension: .md format_name: myst format_version: 0.13 - jupytext_version: 1.17.1 + jupytext_version: 1.16.6 kernelspec: display_name: Python 3 (ipykernel) language: python @@ -60,10 +60,6 @@ import pandas as pd from IPython.display import display, Math ``` - - - - ## Primer on entropy, cross-entropy, KL divergence Before diving in, we'll introduce some useful concepts in a simple setting. @@ -163,6 +159,8 @@ f(z; a, b) = \frac{\Gamma(a+b) z^{a-1} (1-z)^{b-1}}{\Gamma(a) \Gamma(b)} \Gamma(p) := \int_{0}^{\infty} x^{p-1} e^{-x} dx $$ +We introduce two Beta distributions $f(x)$ and $g(x)$, which we will use to illustrate the different divergence measures. + Let's define parameters and density functions in Python ```{code-cell} ipython3 @@ -198,8 +196,6 @@ plt.legend() plt.show() ``` - - (rel_entropy)= ## Kullback–Leibler divergence @@ -457,15 +453,14 @@ plt.show() We now generate plots illustrating how overlap visually diminishes as divergence measures increase. - ```{code-cell} ipython3 param_grid = [ ((1, 1), (1, 1)), ((1, 1), (1.5, 1.2)), ((1, 1), (2, 1.5)), ((1, 1), (3, 1.2)), - ((1, 1), (5, 1)), - ((1, 1), (0.3, 0.3)) + ((1, 1), (0.3, 0.3)), + ((1, 1), (5, 1)) ] ``` @@ -510,9 +505,24 @@ def plot_dist_diff(para_grid): return divergence_data divergence_data = plot_dist_diff(param_grid) -``` - +from pandas.plotting import parallel_coordinates +kl_gf_values = [float(result['KL(g, f)']) for result in results] + +df_plot = pd.DataFrame({ + "KL(f,g)": kl_fg_values, + "KL(g,f)": kl_gf_values, + "JS": js_values, + "Chernoff": chernoff_values +}) +df_plot["pair"] = df_plot.index.astype(str) # just to group lines + +plt.figure(figsize=(8,5)) +parallel_coordinates(df_plot, "pair", color="blue", alpha=0.3) +plt.ylabel("Value") +plt.title("Parallel comparison of divergence measures per pair") +plt.show() +``` ## KL divergence and maximum-likelihood estimation diff --git a/lectures/imp_sample.md b/lectures/imp_sample.md index 11c7258f9..37b546725 100644 --- a/lectures/imp_sample.md +++ b/lectures/imp_sample.md @@ -233,7 +233,7 @@ For our importance sampling estimate, we set $q = h$. estimate(g_a, g_b, h_a, h_b, T=1, N=10000) ``` -Evidently, even at T=1, our importance sampling estimate is closer to $1$ than is the Monte Carlo estimate. +Evidently, even at $T=1$, our importance sampling estimate is closer to $1$ than is the Monte Carlo estimate. Bigger differences arise when computing expectations over longer sequences, $E_0\left[L\left(\omega^t\right)\right]$. @@ -248,6 +248,16 @@ estimate(g_a, g_b, g_a, g_b, T=10, N=10000) estimate(g_a, g_b, h_a, h_b, T=10, N=10000) ``` +The Monte Carlo method underestimates because the likelihood ratio $L(\omega^T) = \prod_{t=1}^T \frac{f(\omega_t)}{g(\omega_t)}$ has a highly skewed distribution under $g$. + +Most samples from $g$ produce small likelihood ratios, while the true mean requires occasional very large values that are rarely sampled. + +In our case, since $g(\omega) \to 0$ as $\omega \to 0$ while $f(\omega)$ remains bounded, the Monte Carlo procedure undersamples precisely where the likelihood ratio $\frac{f(\omega)}{g(\omega)}$ is largest. + +As $T$ increases, this problem worsens exponentially, making standard Monte Carlo increasingly unreliable. + +Importance sampling with $q = h$ fixes this by sampling more uniformly from regions important to both $f$ and $g$. + ## Distribution of Sample Mean We next study the bias and efficiency of the Monte Carlo and importance sampling approaches. @@ -364,10 +374,10 @@ b_list = [0.5, 1.2, 5.] ```{code-cell} ipython3 w_range = np.linspace(1e-5, 1-1e-5, 1000) -plt.plot(w_range, g(w_range), label=f'p=Beta({g_a}, {g_b})') -plt.plot(w_range, p(w_range, a_list[0], b_list[0]), label=f'g=Beta({a_list[0]}, {b_list[0]})') -plt.plot(w_range, p(w_range, a_list[1], b_list[1]), label=f'g=Beta({a_list[1]}, {b_list[1]})') -plt.plot(w_range, p(w_range, a_list[2], b_list[2]), label=f'g=Beta({a_list[2]}, {b_list[2]})') +plt.plot(w_range, g(w_range), label=f'g=Beta({g_a}, {g_b})') +plt.plot(w_range, p(w_range, a_list[0], b_list[0]), label=f'$h_1$=Beta({a_list[0]},{b_list[0]})') +plt.plot(w_range, p(w_range, a_list[1], b_list[1]), label=f'$h_2$=Beta({a_list[1]},{b_list[1]})') +plt.plot(w_range, p(w_range, a_list[2], b_list[2]), label=f'$h_3$=Beta({a_list[2]},{b_list[2]})') plt.title('real data generating process $g$ and importance distribution $h$') plt.legend() plt.ylim([0., 3.]) diff --git a/lectures/likelihood_ratio_process.md b/lectures/likelihood_ratio_process.md index 5a7213702..d7e7d0973 100644 --- a/lectures/likelihood_ratio_process.md +++ b/lectures/likelihood_ratio_process.md @@ -993,33 +993,9 @@ def compute_protocol_1_errors(π_minus_1, T_max, N_simulations, f_func, g_func, 'L_cumulative': L_cumulative, 'true_models': true_models } - -def compute_protocol_2_errors(π_minus_1, T_max, N_simulations, f_func, g_func, - F_params=(1, 1), G_params=(3, 1.2)): - """ - Compute error probabilities for Protocol 2. - """ - sequences, true_models = protocol_2(π_minus_1, - T_max, N_simulations, F_params, G_params) - l_ratios, _ = compute_likelihood_ratios(sequences, f_func, g_func) - - T_range = np.arange(1, T_max + 1) - - accuracy = np.empty(T_max) - for t in range(T_max): - predictions = (l_ratios[:, t] >= 1) - actual = true_models[:, t] - accuracy[t] = np.mean(predictions == actual) - - return { - 'T_range': T_range, - 'accuracy': accuracy, - 'l_ratios': l_ratios, - 'true_models': true_models - } ``` -The following code visualizes the error probabilities for timing protocol 1 and 2 +The following code visualizes the error probabilities for timing protocol 1 ```{code-cell} ipython3 :tags: [hide-input] @@ -1058,44 +1034,6 @@ def analyze_protocol_1(π_minus_1, T_max, N_simulations, f_func, g_func, return result -def analyze_protocol_2(π_minus_1, T_max, N_simulations, f_func, g_func, - theory_error=None, F_params=(1, 1), G_params=(3, 1.2)): - """Analyze Protocol 2.""" - result = compute_protocol_2_errors(π_minus_1, T_max, N_simulations, - f_func, g_func, F_params, G_params) - - # Plot results - plt.figure(figsize=(10, 6)) - plt.plot(result['T_range'], result['accuracy'], - 'b-', linewidth=2, label='empirical accuracy') - - if theory_error is not None: - plt.axhline(1 - theory_error, color='r', linestyle='--', - label=f'theoretical accuracy = {1 - theory_error:.4f}') - - plt.xlabel('$t$') - plt.ylabel('accuracy') - plt.legend() - plt.ylim(0.5, 1.0) - plt.show() - - return result - -def compare_protocols(result1, result2): - """Compare results from both protocols.""" - plt.figure(figsize=(10, 6)) - - plt.plot(result1['T_range'], result1['error_prob'], linewidth=2, - label='Protocol 1 (Model Selection)') - plt.plot(result2['T_range'], 1 - result2['accuracy'], - linestyle='--', linewidth=2, - label='Protocol 2 (classification)') - - plt.xlabel('$T$') - plt.ylabel('error probability') - plt.legend() - plt.show() - # Analyze Protocol 1 π_minus_1 = 0.5 T_max = 30 @@ -1130,6 +1068,33 @@ $$ (eq:classerrorprob) where $\tilde \alpha_t = {\rm Prob}(l_t < 1 \mid f)$ and $\tilde \beta_t = {\rm Prob}(l_t \geq 1 \mid g)$. +```{code-cell} ipython3 +def compute_protocol_2_errors(π_minus_1, T_max, N_simulations, f_func, g_func, + F_params=(1, 1), G_params=(3, 1.2)): + """ + Compute error probabilities for Protocol 2. + """ + sequences, true_models = protocol_2(π_minus_1, + T_max, N_simulations, F_params, G_params) + l_ratios, _ = compute_likelihood_ratios(sequences, f_func, g_func) + + T_range = np.arange(1, T_max + 1) + + accuracy = np.empty(T_max) + for t in range(T_max): + predictions = (l_ratios[:, t] >= 1) + actual = true_models[:, t] + accuracy[t] = np.mean(predictions == actual) + + return { + 'T_range': T_range, + 'accuracy': accuracy, + 'l_ratios': l_ratios, + 'true_models': true_models + } + +``` + Since for each $t$, the decision boundary is the same, the decision boundary can be computed as ```{code-cell} ipython3 @@ -1177,11 +1142,11 @@ plt.tight_layout() plt.show() ``` -To the left of the green vertical line $g < f$, so $l_t < 1$; therefore a $w_t$ that falls to the left of the green line is classified as a type $g$ individual. +To the left of the green vertical line $g < f$, so $l_t > 1$; therefore a $w_t$ that falls to the left of the green line is classified as a type $f$ individual. - * The shaded orange area equals $\beta$ -- the probability of classifying someone as a type $g$ individual when it is really a type $f$ individual. + * The shaded red area equals $\beta$ -- the probability of classifying someone as a type $g$ individual when it is really a type $f$ individual. -To the right of the green vertical line $g > f$, so $l_t >1 $; therefore a $w_t$ that falls to the right of the green line is classified as a type $f$ individual. +To the right of the green vertical line $g > f$, so $l_t < 1$; therefore a $w_t$ that falls to the right of the green line is classified as a type $g$ individual. * The shaded blue area equals $\alpha$ -- the probability of classifying someone as a type $f$ when it is really a type $g$ individual. @@ -1213,6 +1178,29 @@ Now we simulate timing protocol 2 and compute the classification error probabili In the next cell, we also compare the theoretical classification accuracy to the empirical classification accuracy ```{code-cell} ipython3 +def analyze_protocol_2(π_minus_1, T_max, N_simulations, f_func, g_func, + theory_error=None, F_params=(1, 1), G_params=(3, 1.2)): + """Analyze Protocol 2.""" + result = compute_protocol_2_errors(π_minus_1, T_max, N_simulations, + f_func, g_func, F_params, G_params) + + # Plot results + plt.figure(figsize=(10, 6)) + plt.plot(result['T_range'], result['accuracy'], + 'b-', linewidth=2, label='empirical accuracy') + + if theory_error is not None: + plt.axhline(1 - theory_error, color='r', linestyle='--', + label=f'theoretical accuracy = {1 - theory_error:.4f}') + + plt.xlabel('$t$') + plt.ylabel('accuracy') + plt.legend() + plt.ylim(0.5, 1.0) + plt.show() + + return result + # Analyze Protocol 2 result_p2 = analyze_protocol_2(π_minus_1, T_max, N_simulations, f, g, theory_error, (F_a, F_b), (G_a, G_b)) @@ -1221,7 +1209,21 @@ result_p2 = analyze_protocol_2(π_minus_1, T_max, N_simulations, f, g, Let's watch decisions made by the two timing protocols as more and more observations accrue. ```{code-cell} ipython3 -# Compare both protocols +def compare_protocols(result1, result2): + """Compare results from both protocols.""" + plt.figure(figsize=(10, 6)) + + plt.plot(result1['T_range'], result1['error_prob'], linewidth=2, + label='Protocol 1 (Model Selection)') + plt.plot(result2['T_range'], 1 - result2['accuracy'], + linestyle='--', linewidth=2, + label='Protocol 2 (classification)') + + plt.xlabel('$T$') + plt.ylabel('error probability') + plt.legend() + plt.show() + compare_protocols(result_p1, result_p2) ``` diff --git a/lectures/likelihood_ratio_process_2.md b/lectures/likelihood_ratio_process_2.md index fdff7ec2c..3a8e7eda8 100644 --- a/lectures/likelihood_ratio_process_2.md +++ b/lectures/likelihood_ratio_process_2.md @@ -260,7 +260,7 @@ To design a socially optimal allocation, the social planner wants to know what a As for the endowment sequences, agent $i$ believes that nature draws i.i.d. sequences from joint densities $$ -\pi_t^i(s^t) = \pi(s_t)^i \pi^i(s_{t-1}) \cdots \pi^i(s_0) +\pi_t^i(s^t) = \pi^i(s_t) \pi^i(s_{t-1}) \cdots \pi^i(s_0) $$ As for attitudes toward bearing risks, agent $i$ has a one-period utility function @@ -269,7 +269,7 @@ $$ u(c_t^i) = \ln (c_t^i) $$ -with marginal utility of consumption in period $i$ +with marginal utility of consumption in period $t$ $$ u'(c_t^i) = \frac{1}{c_t^i} @@ -303,7 +303,36 @@ This means that the social planner knows and respects * each agent's one period utility function $u(\cdot) = \ln(\cdot)$ * each agent $i$'s probability model $\{\pi_t^i(s^t)\}_{t=0}^\infty$ -Consequently, we anticipate that these objects will appear in the social planner's rule for allocating the aggregate endowment each period. +Consequently, we anticipate that these objects will appear in the social planner's rule for allocating the aggregate endowment each period. + +The Lagrangian for the social planner's problem is + +$$ +L = \sum_{t=0}^{\infty}\sum_{s^t} \{ \lambda \delta^t u(c_t^1(s^t)) \pi_t^1(s^t) + (1-\lambda) \delta^t u(c_t^2(s^t)) \pi_t^2(s^t) + \theta_t(s^t)(1-c_t^1(s^t)-c_t^2(s^t)) \} +$$ + +where $\theta_t(s^t)$ are the shadow prices. + +The first order conditions for maximizing $L$ with respect to $c_t^i(s^t)$ are: + +$$ +\lambda \delta^t u'(c_t^1(s^t)) \pi_t^1(s^t) = \theta_t(s^t), \quad (1-\lambda) \delta^t u'(c_t^2(s^t)) \pi_t^2(s^t) = \theta_t(s^t) +$$ + +Substituting formula {eq}`eq:allocationrule1` for $c_t^1(s^t)$, we get + +$$ +\theta_t(s^t) = \delta^t [(1-\lambda)\pi_t^2(s^t) + \lambda \pi_t^1(s^t)] +$$ + +Now for the competitive equilibrium, notice that if we take $\mu_1 = \frac{1}{\lambda}$ and $\mu_2 = \frac{1}{1-\lambda}$, formula {eq}`eq:allocationce` agrees with formula {eq}`eq:allocationrule1`, and we get from {eq}`eq:priceequation1` + +$$ +p_t(s^t) = \delta^t \lambda \pi_t^1(s^t) \frac{1-\lambda + \lambda l_t(s^t)}{\lambda l_t(s^t)} = \delta^t \pi_t^2(s^t)[1-\lambda + \lambda l_t(s^t)] = +\delta^t \bigl[(1 - \lambda) \pi_t^2(s^t) + \lambda \pi_t^1(s^t)\bigr] +$$ + +Thus, "shadow" prices $\theta_t(s^t)$ in the planning problem equal the competitive equilibrium prices $p_t(s^t)$. First-order necessary conditions for maximizing welfare criterion {eq}`eq:welfareW` subject to the feasibility constraint {eq}`eq:feasibility` are @@ -833,11 +862,6 @@ Likelihood ratio processes appear again in {doc}`advanced:additive_functionals`. -{doc}`ge_arrow` - - - - ## Exercises ```{exercise} diff --git a/lectures/likelihood_var.md b/lectures/likelihood_var.md index 2bacf4812..38511aaad 100644 --- a/lectures/likelihood_var.md +++ b/lectures/likelihood_var.md @@ -234,7 +234,29 @@ def simulate_var(model, T, N_paths=1): ## Likelihood ratio process -Now let's compute likelihood ratio processes for comparing two VAR models +Now let's compute likelihood ratio processes for comparing two VAR models. + +For a VAR model with state vector $x_t$, the log likelihood ratio at time $t$ is + +$$ +\ell_t = \log \frac{p_f(x_t | x_{t-1})}{p_g(x_t | x_{t-1})} +$$ + +where $p_f$ and $p_g$ are the conditional densities under models $f$ and $g$ respectively. + +The cumulative log likelihood ratio process is + +$$ +L_t = \sum_{s=1}^{t} \ell_s = \sum_{s=1}^{t} \log \frac{p_f(x_s | x_{s-1})}{p_g(x_s | x_{s-1})} +$$ + +For the VAR model $x_{t+1} = A x_t + C w_{t+1}$ where $w_{t+1} \sim \mathcal{N}(0, I)$, the conditional density is + +$$ +p(x_{t+1} | x_t) = (2\pi)^{-n/2} |CC^T|^{-1/2} \exp\left(-\frac{1}{2}(x_{t+1} - Ax_t)^T (CC^T)^{-1} (x_{t+1} - Ax_t)\right) +$$ + +Let's write those equations in Python ```{code-cell} ipython3 def compute_likelihood_ratio_var(paths, model_f, model_g): From 91a35c2a97654388a3dba8482f087feac4326518 Mon Sep 17 00:00:00 2001 From: Humphrey Yang Date: Mon, 1 Sep 2025 08:30:08 +0200 Subject: [PATCH 2/4] updates --- lectures/divergence_measures.md | 17 - lectures/imp_sample.md | 21 +- lectures/likelihood_ratio_process.md | 14 +- lectures/likelihood_ratio_process_2.md | 52 +-- lectures/likelihood_var.md | 15 +- lectures/quantecon_review_instructions.md | 473 ++++++++++++++++++++++ 6 files changed, 507 insertions(+), 85 deletions(-) create mode 100644 lectures/quantecon_review_instructions.md diff --git a/lectures/divergence_measures.md b/lectures/divergence_measures.md index c783fda66..747b815b3 100644 --- a/lectures/divergence_measures.md +++ b/lectures/divergence_measures.md @@ -505,23 +505,6 @@ def plot_dist_diff(para_grid): return divergence_data divergence_data = plot_dist_diff(param_grid) - -from pandas.plotting import parallel_coordinates -kl_gf_values = [float(result['KL(g, f)']) for result in results] - -df_plot = pd.DataFrame({ - "KL(f,g)": kl_fg_values, - "KL(g,f)": kl_gf_values, - "JS": js_values, - "Chernoff": chernoff_values -}) -df_plot["pair"] = df_plot.index.astype(str) # just to group lines - -plt.figure(figsize=(8,5)) -parallel_coordinates(df_plot, "pair", color="blue", alpha=0.3) -plt.ylabel("Value") -plt.title("Parallel comparison of divergence measures per pair") -plt.show() ``` ## KL divergence and maximum-likelihood estimation diff --git a/lectures/imp_sample.md b/lectures/imp_sample.md index 37b546725..09ae67576 100644 --- a/lectures/imp_sample.md +++ b/lectures/imp_sample.md @@ -36,7 +36,7 @@ import matplotlib.pyplot as plt from math import gamma ``` -## Mathematical Expectation of Likelihood Ratio +## Mathematical expectation of likelihood ratio In {doc}`this lecture `, we studied a likelihood ratio $\ell \left(\omega_t\right)$ @@ -57,11 +57,10 @@ $$ Our goal is to approximate the mathematical expectation $E \left[ L\left(\omega^t\right) \right]$ well. In {doc}`this lecture `, we showed that $E \left[ L\left(\omega^t\right) \right]$ equals $1$ for all $t$. + We want to check out how well this holds if we replace $E$ by with sample averages from simulations. -This turns out to be easier said than done because for -Beta distributions assumed above, $L\left(\omega^t\right)$ has -a very skewed distribution with a very long tail as $t \rightarrow \infty$. +This turns out to be easier said than done because for Beta distributions assumed above, $L\left(\omega^t\right)$ has a very skewed distribution with a very long tail as $t \rightarrow \infty$. This property makes it difficult efficiently and accurately to estimate the mean by standard Monte Carlo simulation methods. @@ -156,7 +155,7 @@ $$ E^g\left[\ell\left(\omega\right)\right] = \int_\Omega \ell(\omega) g(\omega) d\omega = \int_\Omega \ell(\omega) \frac{g(\omega)}{h(\omega)} h(\omega) d\omega = E^h\left[\ell\left(\omega\right) \frac{g(\omega)}{h(\omega)}\right] $$ -## Selecting a Sampling Distribution +## Selecting a sampling distribution Since we must use an $h$ that has larger mass in parts of the distribution to which $g$ puts low mass, we use $h=Beta(0.5, 0.5)$ as our importance distribution. @@ -178,7 +177,7 @@ plt.ylim([0., 3.]) plt.show() ``` -## Approximating a Cumulative Likelihood Ratio +## Approximating a cumulative likelihood ratio We now study how to use importance sampling to approximate ${E} \left[L(\omega^t)\right] = \left[\prod_{i=1}^T \ell \left(\omega_i\right)\right]$. @@ -252,13 +251,13 @@ The Monte Carlo method underestimates because the likelihood ratio $L(\omega^T) Most samples from $g$ produce small likelihood ratios, while the true mean requires occasional very large values that are rarely sampled. -In our case, since $g(\omega) \to 0$ as $\omega \to 0$ while $f(\omega)$ remains bounded, the Monte Carlo procedure undersamples precisely where the likelihood ratio $\frac{f(\omega)}{g(\omega)}$ is largest. +In our case, since $g(\omega) \to 0$ as $\omega \to 0$ while $f(\omega)$ remains constant, the Monte Carlo procedure undersamples precisely where the likelihood ratio $\frac{f(\omega)}{g(\omega)}$ is largest. As $T$ increases, this problem worsens exponentially, making standard Monte Carlo increasingly unreliable. Importance sampling with $q = h$ fixes this by sampling more uniformly from regions important to both $f$ and $g$. -## Distribution of Sample Mean +## Distribution of sample mean We next study the bias and efficiency of the Monte Carlo and importance sampling approaches. @@ -333,7 +332,7 @@ The simulation exercises above show that the importance sampling estimates are u Evidently, the bias increases with increases in $T$. -## Choosing a Sampling Distribution +## Choosing a sampling distribution +++ @@ -341,9 +340,7 @@ Above, we arbitraily chose $h = Beta(0.5,0.5)$ as the importance distribution. Is there an optimal importance distribution? -In our particular case, since we know in advance that $E_0 \left[ L\left(\omega^t\right) \right] = 1$. - -We can use that knowledge to our advantage. +In our particular case, since we know in advance that $E_0 \left[ L\left(\omega^t\right) \right] = 1$, we can use that knowledge to our advantage. Thus, suppose that we simply use $h = f$. diff --git a/lectures/likelihood_ratio_process.md b/lectures/likelihood_ratio_process.md index d7e7d0973..dc1e2bb1d 100644 --- a/lectures/likelihood_ratio_process.md +++ b/lectures/likelihood_ratio_process.md @@ -194,7 +194,7 @@ def plot_likelihood_paths(l_seq, title="Likelihood ratio paths", ``` (nature_likeli)= -## Nature Permanently Draws from Density g +## Nature permanently draws from density g We first simulate the likelihood ratio process when nature permanently draws from $g$. @@ -264,7 +264,7 @@ Mathematical induction implies $E\left[L\left(w^{t}\right)\bigm|q=g\right]=1$ for all $t \geq 1$. -## Peculiar Property +## Peculiar property How can $E\left[L\left(w^{t}\right)\bigm|q=g\right]=1$ possibly be true when most probability mass of the likelihood ratio process is piling up near $0$ as @@ -300,7 +300,7 @@ We explain the problem in more detail in {doc}`this lecture `. There we describe an alternative way to compute the mean of a likelihood ratio by computing the mean of a _different_ random variable by sampling from a _different_ probability distribution. -## Nature Permanently Draws from Density f +## Nature permanently draws from density f Now suppose that before time $0$ nature permanently decided to draw repeatedly from density $f$. @@ -348,7 +348,7 @@ plt.plot(range(T), np.sum(l_seq_f > 10000, axis=0) / N) plt.show() ``` -## Likelihood Ratio Test +## Likelihood ratio test We now describe how to employ the machinery of Neyman and Pearson {cite}`Neyman_Pearson` to test the hypothesis that history $w^t$ is generated by repeated @@ -959,7 +959,7 @@ $$ p(\textrm{wrong decision}) = {1 \over 2} (\alpha_T + \beta_T) . $$ (eq:detectionerrorprob) -Now let's simulate timing protocol 1 and 2 and compute the error probabilities +Now let's simulate timing protocol 1 and compute the error probabilities ```{code-cell} ipython3 @@ -1068,6 +1068,8 @@ $$ (eq:classerrorprob) where $\tilde \alpha_t = {\rm Prob}(l_t < 1 \mid f)$ and $\tilde \beta_t = {\rm Prob}(l_t \geq 1 \mid g)$. +Now let's write some code to simulate it + ```{code-cell} ipython3 def compute_protocol_2_errors(π_minus_1, T_max, N_simulations, f_func, g_func, F_params=(1, 1), G_params=(3, 1.2)): @@ -1712,7 +1714,7 @@ P_g = np.array([[0.5, 0.3, 0.2], markov_results = analyze_markov_chains(P_f, P_g) ``` -## Related Lectures +## Related lectures Likelihood processes play an important role in Bayesian learning, as described in {doc}`likelihood_bayes` and as applied in {doc}`odu`. diff --git a/lectures/likelihood_ratio_process_2.md b/lectures/likelihood_ratio_process_2.md index 3a8e7eda8..ba5c6a603 100644 --- a/lectures/likelihood_ratio_process_2.md +++ b/lectures/likelihood_ratio_process_2.md @@ -65,7 +65,7 @@ from math import gamma from scipy.integrate import quad ``` -## Review: Likelihood Ratio Processes +## Review: likelihood ratio processes We'll begin by reminding ourselves definitions and properties of likelihood ratio processes. @@ -166,7 +166,7 @@ def simulate(a, b, T=50, N=500): return l_arr ``` -## Blume and Easley's Setting +## Blume and Easley's setting Let the random variable $s_t \in (0,1)$ at time $t =0, 1, 2, \ldots$ be distributed according to the same Beta distribution with parameters $\theta = \{\theta_1, \theta_2\}$. @@ -195,7 +195,7 @@ $$c^1(s_t) = y_t^1 = s_t. $$ But in our model, agent 1 is not alone. -## Nature and Agents' Beliefs +## Nature and agents' beliefs Nature draws i.i.d. sequences $\{s_t\}_{t=0}^\infty$ from $\pi_t(s^t)$. @@ -239,7 +239,7 @@ $$ c_t^1 + c_t^2 = 1 . $$ -## A Socialist Risk-Sharing Arrangement +## A socialist risk-sharing arrangement In order to share risks, a benevolent social planner dictates a history-dependent consumption allocation that takes the form of a sequence of functions @@ -284,7 +284,7 @@ $$ (eq:objectiveagenti) where $\delta \in (0,1)$ is an intertemporal discount factor, and $u(\cdot)$ is a strictly increasing, concave one-period utility function. -## Social Planner's Allocation Problem +## Social planner's allocation problem The benevolent dictator has all the information it requires to choose a consumption allocation that maximizes the social welfare criterion @@ -305,45 +305,12 @@ This means that the social planner knows and respects Consequently, we anticipate that these objects will appear in the social planner's rule for allocating the aggregate endowment each period. -The Lagrangian for the social planner's problem is - -$$ -L = \sum_{t=0}^{\infty}\sum_{s^t} \{ \lambda \delta^t u(c_t^1(s^t)) \pi_t^1(s^t) + (1-\lambda) \delta^t u(c_t^2(s^t)) \pi_t^2(s^t) + \theta_t(s^t)(1-c_t^1(s^t)-c_t^2(s^t)) \} -$$ - -where $\theta_t(s^t)$ are the shadow prices. - -The first order conditions for maximizing $L$ with respect to $c_t^i(s^t)$ are: - -$$ -\lambda \delta^t u'(c_t^1(s^t)) \pi_t^1(s^t) = \theta_t(s^t), \quad (1-\lambda) \delta^t u'(c_t^2(s^t)) \pi_t^2(s^t) = \theta_t(s^t) -$$ - -Substituting formula {eq}`eq:allocationrule1` for $c_t^1(s^t)$, we get - -$$ -\theta_t(s^t) = \delta^t [(1-\lambda)\pi_t^2(s^t) + \lambda \pi_t^1(s^t)] -$$ - -Now for the competitive equilibrium, notice that if we take $\mu_1 = \frac{1}{\lambda}$ and $\mu_2 = \frac{1}{1-\lambda}$, formula {eq}`eq:allocationce` agrees with formula {eq}`eq:allocationrule1`, and we get from {eq}`eq:priceequation1` - -$$ -p_t(s^t) = \delta^t \lambda \pi_t^1(s^t) \frac{1-\lambda + \lambda l_t(s^t)}{\lambda l_t(s^t)} = \delta^t \pi_t^2(s^t)[1-\lambda + \lambda l_t(s^t)] = -\delta^t \bigl[(1 - \lambda) \pi_t^2(s^t) + \lambda \pi_t^1(s^t)\bigr] -$$ - -Thus, "shadow" prices $\theta_t(s^t)$ in the planning problem equal the competitive equilibrium prices $p_t(s^t)$. - - First-order necessary conditions for maximizing welfare criterion {eq}`eq:welfareW` subject to the feasibility constraint {eq}`eq:feasibility` are $$\frac{\pi_t^2(s^t)}{\pi_t^1(s^t)} \frac{(1/c_t^2(s^t))}{(1/c_t^1(s^t))} = \frac{\lambda}{1-\lambda}$$ which can be rearranged to become - - - $$ \frac{c_t^1(s^t)}{c_t^2(s^t)} = \frac{\lambda}{1-\lambda} l_t(s^t) $$ (eq:allocationrule0) @@ -390,7 +357,7 @@ $$ -## If You're So Smart, $\ldots$ +## If you're so smart, $\ldots$ Let's compute some values of limiting allocations {eq}`eq:allocationrule1` for some interesting possible limiting @@ -429,7 +396,7 @@ Doing this will allow us to connect our analysis with an argument of {cite}`alch -## Competitive Equilibrium Prices +## Competitive equilibrium prices Two fundamental welfare theorems for general equilibrium models lead us to anticipate that there is a connection between the allocation that solves the social planning problem we have been studying and the allocation in a **competitive equilibrium** with complete markets in history-contingent commodities. @@ -555,6 +522,9 @@ According to formula {eq}`eq:pformulafinal`, we have the following possible limi * when $l_\infty = \infty$, $c_\infty^1 = 1 $ and tails of competitive equilibrium prices reflect agent $1$'s probability model $\pi_t^1(s^t)$ according to $p_t(s^t) \propto \delta^t \pi_t^1(s^t) $ * for small $t$'s, competitive equilibrium prices reflect both agents' probability models. +We leave the verification of the shadow prices to the reader since it follows from +the same reasoning. + ## Simulations Now let's implement some simulations when agent $1$ believes marginal density @@ -850,7 +820,7 @@ This ties in nicely with {eq}`eq:kl_likelihood_link`. -## Related Lectures +## Related lectures Complete markets models with homogeneous beliefs, a kind often used in macroeconomics and finance, are studied in this quantecon lecture {doc}`ge_arrow`. diff --git a/lectures/likelihood_var.md b/lectures/likelihood_var.md index 38511aaad..9f76cf2b0 100644 --- a/lectures/likelihood_var.md +++ b/lectures/likelihood_var.md @@ -20,7 +20,7 @@ kernelspec: ``` -# Likelihood Processes for VAR Models +# Likelihood Processes For VAR Models ```{contents} Contents :depth: 2 @@ -156,11 +156,11 @@ Given the Gaussian structure, the conditional distribution $f(x_{t+1} | x_t)$ is - Mean: $A x_t$ - Covariance: $CC'$ -The log conditional density is: +The log conditional density is $$ \log f(x_{t+1} | x_t) = -\frac{n}{2} \log(2\pi) - \frac{1}{2} \log \det(CC') - \frac{1}{2} (x_{t+1} - A x_t)' (CC')^{-1} (x_{t+1} - A x_t) -$$ +$$ (eq:cond_den) ```{code-cell} ipython3 def log_likelihood_transition(x_next, x_curr, model): @@ -250,11 +250,8 @@ $$ L_t = \sum_{s=1}^{t} \ell_s = \sum_{s=1}^{t} \log \frac{p_f(x_s | x_{s-1})}{p_g(x_s | x_{s-1})} $$ -For the VAR model $x_{t+1} = A x_t + C w_{t+1}$ where $w_{t+1} \sim \mathcal{N}(0, I)$, the conditional density is +where $p_f(x_t | x_{t-1})$ and $p_g(x_t | x_{t-1})$ are given by their respective conditional densities defined in {eq}`eq:cond_den`. -$$ -p(x_{t+1} | x_t) = (2\pi)^{-n/2} |CC^T|^{-1/2} \exp\left(-\frac{1}{2}(x_{t+1} - Ax_t)^T (CC^T)^{-1} (x_{t+1} - Ax_t)\right) -$$ Let's write those equations in Python @@ -293,7 +290,7 @@ def compute_likelihood_ratio_var(paths, model_f, model_g): return log_L_ratios if N_paths > 1 else log_L_ratios[0] ``` -## Example 1: Two AR(1) processes +## Example 1: two AR(1) processes Let's start with a simple example comparing two univariate AR(1) processes with $A_f = 0.8$, $A_g = 0.5$, and $C_f = 0.3$, $C_g = 0.4$ @@ -336,7 +333,7 @@ plt.show() As we expected, the likelihood ratio processes goes to $+\infty$ as $T$ increases, indicating that model $f$ is chosen correctly by our algorithm. -## Example 2: Bivariate VAR models +## Example 2: bivariate VAR models Now let's consider an example with bivariate VAR models with diff --git a/lectures/quantecon_review_instructions.md b/lectures/quantecon_review_instructions.md new file mode 100644 index 000000000..53f54af14 --- /dev/null +++ b/lectures/quantecon_review_instructions.md @@ -0,0 +1,473 @@ +# QuantEcon Intermediate Lecture Series Review Instructions + +## How to Use This Document + +When asked to review a lecture file, Claude Code will: +1. Read this instruction document first +2. Read the lecture file to be reviewed +3. Systematically review the lecture against all rules in this document +4. Propose changes one at a time with detailed reasoning +5. Wait for your approval before implementing each change +6. Commit and push each approved change with detailed commit messages +7. Perform a second review pass to ensure consistency + +**Example usage**: "Please read the instruction in quantecon_review_instructions.md and review the xxx.md lecture accordingly" + +## Overview +This document provides comprehensive instructions for reviewing QuantEcon Intermediate Lecture series. + +**CRITICAL REQUIREMENT**: When proposing ANY change, you MUST: +1. State the specific rule being applied (e.g., "According to Title Rule #2...") +2. Quote the exact text from the rule +3. Explain why the current text violates this rule +4. Show the proposed correction + +Example format: +``` +According to [Rule Category] Rule #[Number]: "[exact rule text]" +Current: "The Algorithm" +Proposed: "The algorithm" +Reason: "Algorithm" is not a proper noun, so it should not be capitalized in section headings. +``` + +**REVIEW WORKFLOW**: You MUST follow this iterative workflow: + +### Phase 1: Initial Review and Changes +1. **Read and analyze** the entire lecture file first +2. **Provide an issue summary** listing all violations found: + ``` + Issues Found: + 1. [Rule Category] Rule #X: [Brief description of violation] + 2. [Rule Category] Rule #Y: [Brief description of violation] + ... (continue for all issues) + ``` +3. **Begin iterative changes** - For EACH change proposal, you MUST include: + - **Issue reference**: "Addressing Issue #X from the summary" + - **Rule violated**: State the specific rule (e.g., "Title Rule #2") + - **Quote the exact rule text**: Include the full rule description + - **Current text**: Show the exact current text that violates the rule + - **Proposed correction**: Show the exact proposed new text + - **Detailed explanation**: Explain why this violates the rule and why the change is necessary + + Example format for each proposal: + ``` + **Addressing Issue #1 from the summary** + + According to Title Rule #2: "Capitalize ONLY the first word and proper nouns in all other headings (sections, subsections, etc.)" + + Current: "The Algorithm for Value Function Iteration" + Proposed: "The algorithm for value function iteration" + + Explanation: This is a section heading, not a lecture title. According to Title Rule #2, only the first word should be capitalized. "Algorithm", "Value", "Function", and "Iteration" are not proper nouns, so they should be lowercase. + ``` +4. **Wait for user approval** before implementing +5. **After approval**, implement the change +6. **Commit and push** immediately with detailed message: + ```bash + git add [file] + git commit -m "Fix: [Description] (Rule #X: [rule name]) + + Applied [Rule Category] Rule #[Number] which states: + \"[exact rule text]\" + + Changed: [what was changed] + Reason: [why it violated the rule]" + + git push + ``` +6. **Proceed to next change** and repeat until all issues are addressed + +### Phase 2: Second Pass Review +After all initial changes are complete: +1. **Perform a comprehensive second review** to check for: + - Any rules missed in the first pass + - Compatibility issues introduced by changes (e.g., after JAX conversion, text may need updates) + - Consistency across the entire document + - Verify all mathematical notation is correct + - Ensure code examples still work with changes +2. **Propose any additional changes** found, following the same approval process +3. **Confirm completion** when no more issues are found + +### Important Notes: +- **NEVER** implement changes without user approval +- **ALWAYS** propose changes one at a time for clarity +- **ALWAYS** wait for explicit approval before making each change +- **ALWAYS** reference back to the issue summary** when proposing each change +- **ALWAYS** include the FULL detailed reasoning** for each proposal, even if it was mentioned in the summary +- Each commit should address exactly ONE rule violation or issue +- Push after each commit to maintain clear history in the pull request +- Do not skip the detailed explanation even if the issue seems obvious + +**FUNDAMENTAL PRINCIPLE**: Only make changes when something is incorrect. Do not modify material unless there are actual errors (grammar, spelling, technical inaccuracies, or style guide violations). + +--- + +## PART A: GENERAL WRITING RULES + +### Writing Rule #1: Clarity and Brevity +Keep writing clear and short. The value of the lecture = (importance and clarity of information) ÷ (number of words). + +### Writing Rule #2: One-Sentence Paragraphs +**MANDATORY**: Use one sentence paragraphs only. Each paragraph must contain exactly one sentence. + +### Writing Rule #3: Short Sentences +Keep those one-sentence paragraphs short and clear. Avoid complex, multi-clause sentences when possible. + +### Writing Rule #4: Logical Flow +Ensure logical flow without jumps. Choose carefully what to pay attention to and minimize distractions. + +### Writing Rule #5: Simplicity Preference +If you have a choice between two reasonable options, always pick the simplest one. + +### Writing Rule #6: Capitalization - General +Don't capitalize words unless you need to (proper nouns, beginning of sentences, or as specified in rules below). + +### Writing Rule #7: Mathematical Symbol Choice +Use 𝒫 instead of P when you have the option to choose freely in mathematical notation. + +### Writing Rule #8: Visual Presentation +Good lectures look good and use colors and layout to emphasize ideas. Ensure proper formatting for readability. + +--- + +## PART B: TITLES AND HEADINGS RULES + +### Title Rule #1: Lecture Titles +Capitalize ALL words in lecture titles. +- Example: "How it Works: Data, Variables and Names" ✓ +- Not: "How it works: data, variables and names" ✗ + +### Title Rule #2: Section/Subsection Headings +Capitalize ONLY the first word and proper nouns in all other headings (sections, subsections, etc.). +- Example: "Binary packages with Python frontends" ✓ +- Example: "Adding a new reference to QuantEcon" ✓ +- Not: "Binary Packages with Python Frontends" ✗ + +--- + +## PART C: EMPHASIS AND FORMATTING RULES + +### Format Rule #1: Definitions +Use **bold** for definitions. +- Example: "A **closed set** is a set whose complement is open." + +### Format Rule #2: Emphasis +Use *italic* for emphasis. +- Example: "All consumers have *identical* endowments." + +### Format Rule #3: Jupyter Book Theme +Lectures are powered by Jupyter Book with the theme quantecon-book-theme. Adhere to conventions for best results. + +--- + +## PART D: MATHEMATICAL NOTATION RULES + +### Math Rule #1: Transpose Notation +Use `\top` (renders as ⊤) to represent the transpose of a vector or matrix. +- Correct: A⊤ using `\top` +- Wrong: A' or AT or A^T + +### Math Rule #2: Vectors/Matrices of Ones +Use `\mathbb{1}` (renders as 𝟙) to represent a vector or matrix of ones. Always explain it in the lecture (e.g., "Let 𝟙 be an n × 1 vector of ones..."). + +### Math Rule #3: Matrix Brackets +Matrices ALWAYS use square brackets with `\begin{bmatrix}...\end{bmatrix}`. +- Never use parentheses `\begin{pmatrix}` for matrices + +### Math Rule #4: No Bold Face +Do NOT use bold face for either matrices or vectors. +- Wrong: **A**, **x** +- Correct: A, x + +### Math Rule #5: Sequence Notation +Sequences use curly brackets: `\{x_t\}_{t=0}^{\infty}` +- Not: (x_t) or [x_t] + +### Math Rule #6: Aligned Environment +Use `\begin{aligned}...\end{aligned}` when inside a `$$` math environment. +- Critical for PDF builds +- Never use `\begin{align}` inside `$$` (causes LaTeX build failure) + +### Math Rule #7: Equation Numbering +Do NOT use `\tag` for manual equation numbering. Use built-in equation numbering: +``` +$$ +x_y = 2 +$$ (label) +``` +Then reference with `{eq}\`label\`` + +--- + +## PART E: CODE STYLE RULES + +### Code Rule #1: PEP8 Compliance +Follow PEP8 unless there's a good reason to do otherwise (e.g., to match mathematical notation). + +### Code Rule #2: Matrix Capitalization +It's acceptable to use capitals for matrices to match mathematical notation. + +### Code Rule #3: Operator Spacing +Operators are typically surrounded by spaces: `a * b`, `a + b` +- Exception: Write `a**b` for exponentiation (no spaces) + +### Code Rule #4: Unicode Greek Letters +**MANDATORY**: Prefer Unicode symbols for Greek letters commonly used in economics: +- Use `α` instead of `alpha` +- Use `β` instead of `beta` +- Use `γ` instead of `gamma` +- Use `δ` instead of `delta` +- Use `ε` instead of `epsilon` +- Use `σ` instead of `sigma` +- Use `θ` instead of `theta` +- Use `ρ` instead of `rho` + +### Code Rule #5: Package Installation +- QuantEcon lectures should run in a base Anaconda installation +- Any non-Anaconda packages must be installed at the top of the lecture +- Use `tags: [hide-output]` when output is not central +- Example: +```python +!pip install quantecon yfinance --quiet +``` + +### Code Rule #6: Performance Timing +Use modern `qe.Timer()` context manager, NOT manual timing patterns. +- Correct: `with qe.Timer(): result = computation()` +- Wrong: Using `time.time()` manually or `tic/tac/toc` functions + +--- + +## PART F: JAX-SPECIFIC RULES + +### JAX Rule #1: No JAX Installation +Do NOT install JAX at the top of lectures. It may install `jax[cpu]` which is not optimal. + +### JAX Rule #2: GPU Admonition +When using JAX with GPU, include the standard GPU admonition warning about hardware acceleration. + +### JAX Rule #3: Functional Programming - No Mutation +Functions should NOT modify their inputs. Return new data instead. +- Wrong: `state[0] += shock` +- Correct: `state.at[0].add(shock)` + +### JAX Rule #4: Pure Functions +Functions should be deterministic with no side effects. + +### JAX Rule #5: Model Structure Pattern +Replace classes with: +1. `NamedTuple` for storing primitives +2. Factory functions for creating instances +3. Collections of pure functions for computations + +### JAX Rule #6: No jitclass +Eliminate `jitclass` - use simple `NamedTuple` instead. + +### JAX Rule #7: NumPy to JAX Conversion +- Import: `import jax.numpy as jnp` (not `numpy as np`) +- Array creation: `jnp.zeros(10)` (not `np.zeros(10)`) +- Functional updates: `arr.at[0].set(5)` (not `arr[0] = 5`) + +### JAX Rule #8: Loop Patterns +Replace explicit loops with JAX constructs: +- Use `jax.lax.scan` when collecting intermediate results +- Use `jax.lax.fori_loop` for simple fixed-iteration loops +- Use `jax.lax.while_loop` for conditional loops + +### JAX Rule #9: Random Number Generation +Use JAX random with explicit key management: +```python +import jax.random as jr +key = jr.PRNGKey(42) +shocks = jr.normal(key, (100,)) +``` + +### JAX Rule #10: JAX Transformations +Leverage JAX transformations: +- Use `@jax.jit` for compilation +- Use `vmap` for vectorization +- Use `grad` for automatic differentiation + +--- + +## PART G: EXERCISE AND PROOF RULES + +### Exercise Rule #1: Gated Syntax Usage +Use gated syntax (`exercise-start`/`exercise-end`) whenever exercise uses: +- Executable code cells +- Any nested directives (math, note, etc.) + +### Exercise Rule #2: Solution Dropdown +Use `:class: dropdown` for solutions by default. + +### Exercise Rule #3: Exercise-Solution Pairing +Each exercise admonition MUST be paired with a solution admonition. + +### Exercise Rule #4: PDF Compatibility +For PDF builds, use `image` directive (not `figure` directive) when inside another directive like exercise. + +### Exercise Rule #5: Nested Directives - Tick Count +When using tick count management (for non-exercise directives): +- Inner directive: 3 ticks (```) +- Outer directive: 4 ticks (````) + +### Exercise Rule #6: Directive Support +- `exercise` and `solution`: Support both tick count AND gated syntax +- `prf:` directives (proof, theorem, etc.): Only tick count management +- Standard MyST directives: Only tick count management + +--- + +## PART H: REFERENCE AND CITATION RULES + +### Reference Rule #1: Citations +Use the cite role: `{cite}\`bibtex-label\`` +- Example: `{cite}\`StokeyLucas1989\`` + +### Reference Rule #2: Adding References +New references must be added to `/lectures/_static/quant-econ.bib` + +### Reference Rule #3: Internal Links +For same lecture series: Use standard markdown links `[text](filename)` +- Leave text blank to use page title: `[](figures)` + +### Reference Rule #4: Cross-Series Links +For different lecture series: Use `{doc}` links with intersphinx +- Example: `{doc}\`intro:linear_equations\`` + +--- + +## PART I: INDEX ENTRY RULES + +### Index Rule #1: Inline Index Entries +Use `:index:` for unchanged keywords: `{index}\`bellman equation\`` + +### Index Rule #2: Index Directives +Use directives for complex arrangements or nested entries: +``` +```{index} single: Dynamic Programming; Bellman Equation +``` +``` + +### Index Rule #3: Case Sensitivity +Index items are case sensitive - maintain consistency. + +--- + +## PART J: BINARY PACKAGE RULES + +### Binary Rule #1: graphviz Package +If using graphviz: +1. Install with `pip install graphviz` at lecture top +2. Check `.github/workflows/ci.yml` for preview builds +3. Add note admonition about local installation requirements + +--- + +## REVIEW CHECKLIST WITH RULE REFERENCES + +When reviewing, check each item and reference the specific rule when proposing changes: + +### Writing and Formatting +- [ ] One-sentence paragraphs (Writing Rule #2) +- [ ] Short, clear sentences (Writing Rule #3) +- [ ] Logical flow without jumps (Writing Rule #4) +- [ ] Minimal capitalization (Writing Rule #6) +- [ ] Bold for definitions (Format Rule #1) +- [ ] Italic for emphasis (Format Rule #2) + +### Titles and Headings +- [ ] Lecture titles: all words capitalized (Title Rule #1) +- [ ] Section headings: only first word capitalized (Title Rule #2) + +### Mathematical Notation +- [ ] Transpose uses `\top` (Math Rule #1) +- [ ] Vectors of ones use `\mathbb{1}` (Math Rule #2) +- [ ] Matrices use square brackets (Math Rule #3) +- [ ] No bold face for matrices/vectors (Math Rule #4) +- [ ] Sequences use curly brackets (Math Rule #5) +- [ ] `aligned` inside `$$` environments (Math Rule #6) +- [ ] No manual equation numbering with `\tag` (Math Rule #7) + +### Code Style +- [ ] PEP8 compliance (Code Rule #1) +- [ ] Unicode Greek letters (Code Rule #4) +- [ ] Proper operator spacing (Code Rule #3) +- [ ] Package installation at top (Code Rule #5) +- [ ] `qe.Timer()` for timing (Code Rule #6) + +### JAX-Specific (if applicable) +- [ ] No JAX installation command (JAX Rule #1) +- [ ] Pure functions, no mutation (JAX Rules #3, #4) +- [ ] NamedTuple instead of jitclass (JAX Rules #5, #6) +- [ ] JAX arrays and operations (JAX Rule #7) +- [ ] JAX loop constructs (JAX Rule #8) +- [ ] Explicit PRNG keys (JAX Rule #9) + +### Exercises and Solutions +- [ ] Gated syntax when needed (Exercise Rule #1) +- [ ] Dropdown solutions (Exercise Rule #2) +- [ ] All exercises have solutions (Exercise Rule #3) +- [ ] Proper tick count for nesting (Exercise Rule #5) + +--- + +## HOW TO REFERENCE RULES + +When proposing changes, use this format: + +"According to [Rule Category] Rule #[Number], [current text/code] should be changed to [proposed text/code] because [brief explanation]." + +Examples: +- "According to Writing Rule #2, this multi-sentence paragraph should be split into separate one-sentence paragraphs." +- "According to Code Rule #4, `alpha` should be changed to `α` to use Unicode Greek letters." +- "According to Math Rule #1, `A'` should be changed to `A^\top` for proper transpose notation." +- "According to Title Rule #2, 'Binary Packages With Python Frontends' should be 'Binary packages with Python frontends' (only first word capitalized)." + +--- + +## IMPORTANT REMINDERS + +1. **Only fix actual errors** - Don't change stylistic preferences unless they violate rules +2. **Preserve author intent** - Don't add or remove content unless fixing errors +3. **Document all changes** - Reference specific rule numbers for transparency +4. **Check technical accuracy** - Ensure mathematical and code correctness +5. **Maintain consistency** - Apply rules uniformly throughout the lecture + +--- + +## GIT COMMIT MESSAGE FORMAT + +When committing changes after review, use this format for the commit message: + +``` +Fix: [Brief description] per QuantEcon style guide + +Applied rules: +- Title Rule #2: Section headings capitalization +- Writing Rule #2: One-sentence paragraphs +- Code Rule #4: Unicode Greek letters + +Details: +- Changed "The Algorithm" to "The algorithm" (Title Rule #2) +- Split multi-sentence paragraphs (Writing Rule #2) +- Replaced "alpha" with "α" in code (Code Rule #4) +``` + +For single-rule fixes, use: +``` +Fix: [Description] (Title Rule #2: section heading capitalization) +``` + +Example: +``` +Fix: Correct section heading capitalizations (Title Rule #2) + +Changed 3 section headings to follow Title Rule #2 which states: +"Capitalize ONLY the first word and proper nouns in all other headings" + +Changes: +- "The Algorithm" → "The algorithm" +- "Value Function Iteration" → "Value function iteration" +- "Fitted Value Function Iteration" → "Fitted value function iteration" +``` \ No newline at end of file From 565431bb634678941e68372c5c8a56e7eecd346c Mon Sep 17 00:00:00 2001 From: Humphrey Yang Date: Mon, 1 Sep 2025 16:52:54 +0200 Subject: [PATCH 3/4] updates --- lectures/likelihood_ratio_process.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lectures/likelihood_ratio_process.md b/lectures/likelihood_ratio_process.md index dc1e2bb1d..fc62a4145 100644 --- a/lectures/likelihood_ratio_process.md +++ b/lectures/likelihood_ratio_process.md @@ -26,6 +26,12 @@ kernelspec: :depth: 2 ``` +In addition to what’s in Anaconda, this lecture will need the following libraries: + +```{code-cell} ipython3 +:tags: [hide-output] +!pip install --upgrade quantecon +``` ## Overview From c99788dd0cd489b8587ea6317f542f840f583cdd Mon Sep 17 00:00:00 2001 From: Humphrey Yang Date: Tue, 2 Sep 2025 09:06:02 +0200 Subject: [PATCH 4/4] updates --- lectures/quantecon_review_instructions.md | 473 ---------------------- 1 file changed, 473 deletions(-) delete mode 100644 lectures/quantecon_review_instructions.md diff --git a/lectures/quantecon_review_instructions.md b/lectures/quantecon_review_instructions.md deleted file mode 100644 index 53f54af14..000000000 --- a/lectures/quantecon_review_instructions.md +++ /dev/null @@ -1,473 +0,0 @@ -# QuantEcon Intermediate Lecture Series Review Instructions - -## How to Use This Document - -When asked to review a lecture file, Claude Code will: -1. Read this instruction document first -2. Read the lecture file to be reviewed -3. Systematically review the lecture against all rules in this document -4. Propose changes one at a time with detailed reasoning -5. Wait for your approval before implementing each change -6. Commit and push each approved change with detailed commit messages -7. Perform a second review pass to ensure consistency - -**Example usage**: "Please read the instruction in quantecon_review_instructions.md and review the xxx.md lecture accordingly" - -## Overview -This document provides comprehensive instructions for reviewing QuantEcon Intermediate Lecture series. - -**CRITICAL REQUIREMENT**: When proposing ANY change, you MUST: -1. State the specific rule being applied (e.g., "According to Title Rule #2...") -2. Quote the exact text from the rule -3. Explain why the current text violates this rule -4. Show the proposed correction - -Example format: -``` -According to [Rule Category] Rule #[Number]: "[exact rule text]" -Current: "The Algorithm" -Proposed: "The algorithm" -Reason: "Algorithm" is not a proper noun, so it should not be capitalized in section headings. -``` - -**REVIEW WORKFLOW**: You MUST follow this iterative workflow: - -### Phase 1: Initial Review and Changes -1. **Read and analyze** the entire lecture file first -2. **Provide an issue summary** listing all violations found: - ``` - Issues Found: - 1. [Rule Category] Rule #X: [Brief description of violation] - 2. [Rule Category] Rule #Y: [Brief description of violation] - ... (continue for all issues) - ``` -3. **Begin iterative changes** - For EACH change proposal, you MUST include: - - **Issue reference**: "Addressing Issue #X from the summary" - - **Rule violated**: State the specific rule (e.g., "Title Rule #2") - - **Quote the exact rule text**: Include the full rule description - - **Current text**: Show the exact current text that violates the rule - - **Proposed correction**: Show the exact proposed new text - - **Detailed explanation**: Explain why this violates the rule and why the change is necessary - - Example format for each proposal: - ``` - **Addressing Issue #1 from the summary** - - According to Title Rule #2: "Capitalize ONLY the first word and proper nouns in all other headings (sections, subsections, etc.)" - - Current: "The Algorithm for Value Function Iteration" - Proposed: "The algorithm for value function iteration" - - Explanation: This is a section heading, not a lecture title. According to Title Rule #2, only the first word should be capitalized. "Algorithm", "Value", "Function", and "Iteration" are not proper nouns, so they should be lowercase. - ``` -4. **Wait for user approval** before implementing -5. **After approval**, implement the change -6. **Commit and push** immediately with detailed message: - ```bash - git add [file] - git commit -m "Fix: [Description] (Rule #X: [rule name]) - - Applied [Rule Category] Rule #[Number] which states: - \"[exact rule text]\" - - Changed: [what was changed] - Reason: [why it violated the rule]" - - git push - ``` -6. **Proceed to next change** and repeat until all issues are addressed - -### Phase 2: Second Pass Review -After all initial changes are complete: -1. **Perform a comprehensive second review** to check for: - - Any rules missed in the first pass - - Compatibility issues introduced by changes (e.g., after JAX conversion, text may need updates) - - Consistency across the entire document - - Verify all mathematical notation is correct - - Ensure code examples still work with changes -2. **Propose any additional changes** found, following the same approval process -3. **Confirm completion** when no more issues are found - -### Important Notes: -- **NEVER** implement changes without user approval -- **ALWAYS** propose changes one at a time for clarity -- **ALWAYS** wait for explicit approval before making each change -- **ALWAYS** reference back to the issue summary** when proposing each change -- **ALWAYS** include the FULL detailed reasoning** for each proposal, even if it was mentioned in the summary -- Each commit should address exactly ONE rule violation or issue -- Push after each commit to maintain clear history in the pull request -- Do not skip the detailed explanation even if the issue seems obvious - -**FUNDAMENTAL PRINCIPLE**: Only make changes when something is incorrect. Do not modify material unless there are actual errors (grammar, spelling, technical inaccuracies, or style guide violations). - ---- - -## PART A: GENERAL WRITING RULES - -### Writing Rule #1: Clarity and Brevity -Keep writing clear and short. The value of the lecture = (importance and clarity of information) ÷ (number of words). - -### Writing Rule #2: One-Sentence Paragraphs -**MANDATORY**: Use one sentence paragraphs only. Each paragraph must contain exactly one sentence. - -### Writing Rule #3: Short Sentences -Keep those one-sentence paragraphs short and clear. Avoid complex, multi-clause sentences when possible. - -### Writing Rule #4: Logical Flow -Ensure logical flow without jumps. Choose carefully what to pay attention to and minimize distractions. - -### Writing Rule #5: Simplicity Preference -If you have a choice between two reasonable options, always pick the simplest one. - -### Writing Rule #6: Capitalization - General -Don't capitalize words unless you need to (proper nouns, beginning of sentences, or as specified in rules below). - -### Writing Rule #7: Mathematical Symbol Choice -Use 𝒫 instead of P when you have the option to choose freely in mathematical notation. - -### Writing Rule #8: Visual Presentation -Good lectures look good and use colors and layout to emphasize ideas. Ensure proper formatting for readability. - ---- - -## PART B: TITLES AND HEADINGS RULES - -### Title Rule #1: Lecture Titles -Capitalize ALL words in lecture titles. -- Example: "How it Works: Data, Variables and Names" ✓ -- Not: "How it works: data, variables and names" ✗ - -### Title Rule #2: Section/Subsection Headings -Capitalize ONLY the first word and proper nouns in all other headings (sections, subsections, etc.). -- Example: "Binary packages with Python frontends" ✓ -- Example: "Adding a new reference to QuantEcon" ✓ -- Not: "Binary Packages with Python Frontends" ✗ - ---- - -## PART C: EMPHASIS AND FORMATTING RULES - -### Format Rule #1: Definitions -Use **bold** for definitions. -- Example: "A **closed set** is a set whose complement is open." - -### Format Rule #2: Emphasis -Use *italic* for emphasis. -- Example: "All consumers have *identical* endowments." - -### Format Rule #3: Jupyter Book Theme -Lectures are powered by Jupyter Book with the theme quantecon-book-theme. Adhere to conventions for best results. - ---- - -## PART D: MATHEMATICAL NOTATION RULES - -### Math Rule #1: Transpose Notation -Use `\top` (renders as ⊤) to represent the transpose of a vector or matrix. -- Correct: A⊤ using `\top` -- Wrong: A' or AT or A^T - -### Math Rule #2: Vectors/Matrices of Ones -Use `\mathbb{1}` (renders as 𝟙) to represent a vector or matrix of ones. Always explain it in the lecture (e.g., "Let 𝟙 be an n × 1 vector of ones..."). - -### Math Rule #3: Matrix Brackets -Matrices ALWAYS use square brackets with `\begin{bmatrix}...\end{bmatrix}`. -- Never use parentheses `\begin{pmatrix}` for matrices - -### Math Rule #4: No Bold Face -Do NOT use bold face for either matrices or vectors. -- Wrong: **A**, **x** -- Correct: A, x - -### Math Rule #5: Sequence Notation -Sequences use curly brackets: `\{x_t\}_{t=0}^{\infty}` -- Not: (x_t) or [x_t] - -### Math Rule #6: Aligned Environment -Use `\begin{aligned}...\end{aligned}` when inside a `$$` math environment. -- Critical for PDF builds -- Never use `\begin{align}` inside `$$` (causes LaTeX build failure) - -### Math Rule #7: Equation Numbering -Do NOT use `\tag` for manual equation numbering. Use built-in equation numbering: -``` -$$ -x_y = 2 -$$ (label) -``` -Then reference with `{eq}\`label\`` - ---- - -## PART E: CODE STYLE RULES - -### Code Rule #1: PEP8 Compliance -Follow PEP8 unless there's a good reason to do otherwise (e.g., to match mathematical notation). - -### Code Rule #2: Matrix Capitalization -It's acceptable to use capitals for matrices to match mathematical notation. - -### Code Rule #3: Operator Spacing -Operators are typically surrounded by spaces: `a * b`, `a + b` -- Exception: Write `a**b` for exponentiation (no spaces) - -### Code Rule #4: Unicode Greek Letters -**MANDATORY**: Prefer Unicode symbols for Greek letters commonly used in economics: -- Use `α` instead of `alpha` -- Use `β` instead of `beta` -- Use `γ` instead of `gamma` -- Use `δ` instead of `delta` -- Use `ε` instead of `epsilon` -- Use `σ` instead of `sigma` -- Use `θ` instead of `theta` -- Use `ρ` instead of `rho` - -### Code Rule #5: Package Installation -- QuantEcon lectures should run in a base Anaconda installation -- Any non-Anaconda packages must be installed at the top of the lecture -- Use `tags: [hide-output]` when output is not central -- Example: -```python -!pip install quantecon yfinance --quiet -``` - -### Code Rule #6: Performance Timing -Use modern `qe.Timer()` context manager, NOT manual timing patterns. -- Correct: `with qe.Timer(): result = computation()` -- Wrong: Using `time.time()` manually or `tic/tac/toc` functions - ---- - -## PART F: JAX-SPECIFIC RULES - -### JAX Rule #1: No JAX Installation -Do NOT install JAX at the top of lectures. It may install `jax[cpu]` which is not optimal. - -### JAX Rule #2: GPU Admonition -When using JAX with GPU, include the standard GPU admonition warning about hardware acceleration. - -### JAX Rule #3: Functional Programming - No Mutation -Functions should NOT modify their inputs. Return new data instead. -- Wrong: `state[0] += shock` -- Correct: `state.at[0].add(shock)` - -### JAX Rule #4: Pure Functions -Functions should be deterministic with no side effects. - -### JAX Rule #5: Model Structure Pattern -Replace classes with: -1. `NamedTuple` for storing primitives -2. Factory functions for creating instances -3. Collections of pure functions for computations - -### JAX Rule #6: No jitclass -Eliminate `jitclass` - use simple `NamedTuple` instead. - -### JAX Rule #7: NumPy to JAX Conversion -- Import: `import jax.numpy as jnp` (not `numpy as np`) -- Array creation: `jnp.zeros(10)` (not `np.zeros(10)`) -- Functional updates: `arr.at[0].set(5)` (not `arr[0] = 5`) - -### JAX Rule #8: Loop Patterns -Replace explicit loops with JAX constructs: -- Use `jax.lax.scan` when collecting intermediate results -- Use `jax.lax.fori_loop` for simple fixed-iteration loops -- Use `jax.lax.while_loop` for conditional loops - -### JAX Rule #9: Random Number Generation -Use JAX random with explicit key management: -```python -import jax.random as jr -key = jr.PRNGKey(42) -shocks = jr.normal(key, (100,)) -``` - -### JAX Rule #10: JAX Transformations -Leverage JAX transformations: -- Use `@jax.jit` for compilation -- Use `vmap` for vectorization -- Use `grad` for automatic differentiation - ---- - -## PART G: EXERCISE AND PROOF RULES - -### Exercise Rule #1: Gated Syntax Usage -Use gated syntax (`exercise-start`/`exercise-end`) whenever exercise uses: -- Executable code cells -- Any nested directives (math, note, etc.) - -### Exercise Rule #2: Solution Dropdown -Use `:class: dropdown` for solutions by default. - -### Exercise Rule #3: Exercise-Solution Pairing -Each exercise admonition MUST be paired with a solution admonition. - -### Exercise Rule #4: PDF Compatibility -For PDF builds, use `image` directive (not `figure` directive) when inside another directive like exercise. - -### Exercise Rule #5: Nested Directives - Tick Count -When using tick count management (for non-exercise directives): -- Inner directive: 3 ticks (```) -- Outer directive: 4 ticks (````) - -### Exercise Rule #6: Directive Support -- `exercise` and `solution`: Support both tick count AND gated syntax -- `prf:` directives (proof, theorem, etc.): Only tick count management -- Standard MyST directives: Only tick count management - ---- - -## PART H: REFERENCE AND CITATION RULES - -### Reference Rule #1: Citations -Use the cite role: `{cite}\`bibtex-label\`` -- Example: `{cite}\`StokeyLucas1989\`` - -### Reference Rule #2: Adding References -New references must be added to `/lectures/_static/quant-econ.bib` - -### Reference Rule #3: Internal Links -For same lecture series: Use standard markdown links `[text](filename)` -- Leave text blank to use page title: `[](figures)` - -### Reference Rule #4: Cross-Series Links -For different lecture series: Use `{doc}` links with intersphinx -- Example: `{doc}\`intro:linear_equations\`` - ---- - -## PART I: INDEX ENTRY RULES - -### Index Rule #1: Inline Index Entries -Use `:index:` for unchanged keywords: `{index}\`bellman equation\`` - -### Index Rule #2: Index Directives -Use directives for complex arrangements or nested entries: -``` -```{index} single: Dynamic Programming; Bellman Equation -``` -``` - -### Index Rule #3: Case Sensitivity -Index items are case sensitive - maintain consistency. - ---- - -## PART J: BINARY PACKAGE RULES - -### Binary Rule #1: graphviz Package -If using graphviz: -1. Install with `pip install graphviz` at lecture top -2. Check `.github/workflows/ci.yml` for preview builds -3. Add note admonition about local installation requirements - ---- - -## REVIEW CHECKLIST WITH RULE REFERENCES - -When reviewing, check each item and reference the specific rule when proposing changes: - -### Writing and Formatting -- [ ] One-sentence paragraphs (Writing Rule #2) -- [ ] Short, clear sentences (Writing Rule #3) -- [ ] Logical flow without jumps (Writing Rule #4) -- [ ] Minimal capitalization (Writing Rule #6) -- [ ] Bold for definitions (Format Rule #1) -- [ ] Italic for emphasis (Format Rule #2) - -### Titles and Headings -- [ ] Lecture titles: all words capitalized (Title Rule #1) -- [ ] Section headings: only first word capitalized (Title Rule #2) - -### Mathematical Notation -- [ ] Transpose uses `\top` (Math Rule #1) -- [ ] Vectors of ones use `\mathbb{1}` (Math Rule #2) -- [ ] Matrices use square brackets (Math Rule #3) -- [ ] No bold face for matrices/vectors (Math Rule #4) -- [ ] Sequences use curly brackets (Math Rule #5) -- [ ] `aligned` inside `$$` environments (Math Rule #6) -- [ ] No manual equation numbering with `\tag` (Math Rule #7) - -### Code Style -- [ ] PEP8 compliance (Code Rule #1) -- [ ] Unicode Greek letters (Code Rule #4) -- [ ] Proper operator spacing (Code Rule #3) -- [ ] Package installation at top (Code Rule #5) -- [ ] `qe.Timer()` for timing (Code Rule #6) - -### JAX-Specific (if applicable) -- [ ] No JAX installation command (JAX Rule #1) -- [ ] Pure functions, no mutation (JAX Rules #3, #4) -- [ ] NamedTuple instead of jitclass (JAX Rules #5, #6) -- [ ] JAX arrays and operations (JAX Rule #7) -- [ ] JAX loop constructs (JAX Rule #8) -- [ ] Explicit PRNG keys (JAX Rule #9) - -### Exercises and Solutions -- [ ] Gated syntax when needed (Exercise Rule #1) -- [ ] Dropdown solutions (Exercise Rule #2) -- [ ] All exercises have solutions (Exercise Rule #3) -- [ ] Proper tick count for nesting (Exercise Rule #5) - ---- - -## HOW TO REFERENCE RULES - -When proposing changes, use this format: - -"According to [Rule Category] Rule #[Number], [current text/code] should be changed to [proposed text/code] because [brief explanation]." - -Examples: -- "According to Writing Rule #2, this multi-sentence paragraph should be split into separate one-sentence paragraphs." -- "According to Code Rule #4, `alpha` should be changed to `α` to use Unicode Greek letters." -- "According to Math Rule #1, `A'` should be changed to `A^\top` for proper transpose notation." -- "According to Title Rule #2, 'Binary Packages With Python Frontends' should be 'Binary packages with Python frontends' (only first word capitalized)." - ---- - -## IMPORTANT REMINDERS - -1. **Only fix actual errors** - Don't change stylistic preferences unless they violate rules -2. **Preserve author intent** - Don't add or remove content unless fixing errors -3. **Document all changes** - Reference specific rule numbers for transparency -4. **Check technical accuracy** - Ensure mathematical and code correctness -5. **Maintain consistency** - Apply rules uniformly throughout the lecture - ---- - -## GIT COMMIT MESSAGE FORMAT - -When committing changes after review, use this format for the commit message: - -``` -Fix: [Brief description] per QuantEcon style guide - -Applied rules: -- Title Rule #2: Section headings capitalization -- Writing Rule #2: One-sentence paragraphs -- Code Rule #4: Unicode Greek letters - -Details: -- Changed "The Algorithm" to "The algorithm" (Title Rule #2) -- Split multi-sentence paragraphs (Writing Rule #2) -- Replaced "alpha" with "α" in code (Code Rule #4) -``` - -For single-rule fixes, use: -``` -Fix: [Description] (Title Rule #2: section heading capitalization) -``` - -Example: -``` -Fix: Correct section heading capitalizations (Title Rule #2) - -Changed 3 section headings to follow Title Rule #2 which states: -"Capitalize ONLY the first word and proper nouns in all other headings" - -Changes: -- "The Algorithm" → "The algorithm" -- "Value Function Iteration" → "Value function iteration" -- "Fitted Value Function Iteration" → "Fitted value function iteration" -``` \ No newline at end of file