From dd0c57093161d06c5a06909eccbbfabbedeccb46 Mon Sep 17 00:00:00 2001 From: Humphrey Yang Date: Tue, 7 Feb 2023 11:47:42 +1100 Subject: [PATCH 1/4] update according to comments --- lectures/markov_chains.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/lectures/markov_chains.md b/lectures/markov_chains.md index 032473cee..84d7d8cd4 100644 --- a/lectures/markov_chains.md +++ b/lectures/markov_chains.md @@ -914,13 +914,12 @@ fig, axes = plt.subplots(nrows=1, ncols=n_state) plt.subplots_adjust(wspace=0.35) for i in range(n_state): axes[i].grid() - axes[i].set_ylim(ψ_star[i]-0.2, ψ_star[i]+0.2) axes[i].axhline(ψ_star[i], linestyle='dashed', lw=2, color = 'black', - label = fr'$\psi^*(X={i})$') + label = fr'$\psi^*({i})$') axes[i].set_xlabel('t') - axes[i].set_ylabel(fr'average time spent at X={i}') + axes[i].set_ylabel(fr'average time spent at {i}') - # Compute the fraction of time spent, for each X=x + # Compute the fraction of time spent, for each x for x0, col in ((0, 'blue'), (1, 'green'), (2, 'red')): # Generate time series that starts at different x0 X = mc.simulate(n, init=x0) @@ -980,11 +979,11 @@ for i in range(n_state): axes[i].grid() axes[i].set_ylim(0.45, 0.55) axes[i].axhline(ψ_star[i], linestyle='dashed', lw=2, color = 'black', - label = fr'$\psi^*(X={i})$') + label = fr'$\psi^*({i})$') axes[i].set_xlabel('t') - axes[i].set_ylabel(fr'average time spent at X={i}') + axes[i].set_ylabel(fr'average time spent at {i}') - # Compute the fraction of time spent, for each X=x + # Compute the fraction of time spent, for each x for x0 in range(n_state): # Generate time series starting at different x_0 X = mc.simulate(n, init=x0) @@ -1108,9 +1107,9 @@ for x0 in x0s: for i in range(n_state): axes[i].axhline(ψ_star[i], linestyle='dashed', lw=2, color = 'black', - label = fr'$\psi^*(X={i})$') + label = fr'$\psi^*({i})$') axes[i].set_xlabel('t') - axes[i].set_ylabel(fr'$\psi(X={i})$') + axes[i].set_ylabel(fr'$\psi({i})$') axes[i].legend() plt.show() @@ -1147,9 +1146,9 @@ for x0 in x0s: axes[i].plot(range(20, n), X[20:,i], alpha=0.3) for i in range(n_state): - axes[i].axhline(ψ_star[i], linestyle='dashed', lw=2, color = 'black', label = fr'$\psi^* (X={i})$') + axes[i].axhline(ψ_star[i], linestyle='dashed', lw=2, color = 'black', label = fr'$\psi^* ({i})$') axes[i].set_xlabel('t') - axes[i].set_ylabel(fr'$\psi(X={i})$') + axes[i].set_ylabel(fr'$\psi({i})$') axes[i].legend() plt.show() @@ -1348,7 +1347,7 @@ for x0 in range(8): X_bar = (X == x0).cumsum() / (1 + np.arange(N, dtype=float)) ax.plot(X_bar - ψ_star[x0], label=f'$X = {x0+1} $') ax.set_xlabel('t') - ax.set_ylabel(fr'average time spent in a state $- \psi^* (X=x)$') + ax.set_ylabel(fr'average time spent in a state $- \psi^* (x)$') ax.legend() plt.show() From ae592bd5ab5072d6a26bb91a7867459fdd207ffc Mon Sep 17 00:00:00 2001 From: Humphrey Yang Date: Tue, 7 Feb 2023 23:08:47 +1100 Subject: [PATCH 2/4] changes based on comments --- lectures/lln_clt.md | 2 ++ lectures/markov_chains.md | 25 ++++++++++--------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/lectures/lln_clt.md b/lectures/lln_clt.md index b3015d8ec..7224ac67a 100644 --- a/lectures/lln_clt.md +++ b/lectures/lln_clt.md @@ -368,6 +368,8 @@ Since the distribution of $\bar X$ follows a standard normal distribution, but t This violates {eq}`exp`, and thus breaks LLN. ```{note} +:name: iid_violation + Although in this case, the violation of IID breaks LLN, it is not always the case for correlated data. We will show an example in the [exercise](lln_ex3). diff --git a/lectures/markov_chains.md b/lectures/markov_chains.md index 84d7d8cd4..5e428d08f 100644 --- a/lectures/markov_chains.md +++ b/lectures/markov_chains.md @@ -255,8 +255,6 @@ Then we can address a range of questions, such as We'll cover such applications below. - - ### Defining Markov Chains So far we've given examples of Markov chains but now let's define them more @@ -308,9 +306,6 @@ chain $\{X_t\}$ as follows: By construction, the resulting process satisfies {eq}`mpp`. - - - ## Simulation ```{index} single: Markov Chains; Simulation @@ -864,10 +859,8 @@ Importantly, the result is valid for any choice of $\psi_0$. Notice that the theorem is related to the law of large numbers. -TODO -- link to our undergrad lln and clt lecture - It tells us that, in some settings, the law of large numbers sometimes holds even when the -sequence of random variables is not IID. +sequence of random variables is [not IID](iid_violation). (mc_eg1-2)= @@ -919,7 +912,7 @@ for i in range(n_state): axes[i].set_xlabel('t') axes[i].set_ylabel(fr'average time spent at {i}') - # Compute the fraction of time spent, for each x + # Compute the fraction of time spent, starting from different x_0s for x0, col in ((0, 'blue'), (1, 'green'), (2, 'red')): # Generate time series that starts at different x0 X = mc.simulate(n, init=x0) @@ -948,6 +941,8 @@ $$ The diagram of the Markov chain shows that it is **irreducible** ```{code-cell} ipython3 +:tags: [hide-input] + dot = Digraph(comment='Graph') dot.attr(rankdir='LR') dot.node("0") @@ -1077,6 +1072,7 @@ In the case of Hamilton's Markov chain, the distribution $\psi P^t$ converges to P = np.array([[0.971, 0.029, 0.000], [0.145, 0.778, 0.077], [0.000, 0.508, 0.492]]) + # Define the number of iterations n = 50 n_state = P.shape[0] @@ -1096,7 +1092,7 @@ for i in range(n): # Loop through many initial values for x0 in x0s: x = x0 - X = np.zeros((n,n_state)) + X = np.zeros((n, n_state)) # Obtain and plot distributions at each state for t in range(0, n): @@ -1294,7 +1290,7 @@ In this exercise, 1. show this process is asymptotically stationary and calculate the stationary distribution using simulations. -1. use simulation to show ergodicity. +1. use simulations to demonstrate ergodicity of this process. ```` @@ -1322,7 +1318,7 @@ codes_B = ( '1','2','3','4','5','6','7','8') np.linalg.matrix_power(P_B, 10) ``` -We find rows transition matrix converge to the stationary distribution +We find rows of transition matrix converge to the stationary distribution ```{code-cell} ipython3 mc = qe.MarkovChain(P_B) @@ -1353,7 +1349,7 @@ ax.legend() plt.show() ``` -We can see that the time spent at each state quickly converges to the stationary distribution. +Note that the average time spent at each state quickly converges to the stationary distribution. ```{solution-end} ``` @@ -1451,10 +1447,9 @@ However, another way to verify irreducibility is by checking whether $A$ satisfi Assume A is an $n \times n$ $A$ is irreducible if and only if $\sum_{k=0}^{n-1}A^k$ is a positive matrix. -(see more at \cite{zhao_power_2012} and [here](https://math.stackexchange.com/questions/3336616/how-to-prove-this-matrix-is-a-irreducible-matrix)) +(see more: {cite}`zhao_power_2012` and [here](https://math.stackexchange.com/questions/3336616/how-to-prove-this-matrix-is-a-irreducible-matrix)) Based on this claim, write a function to test irreducibility. - ``` ```{solution-start} mc_ex3 From 1377f9bcf08317860a7561300e8371bfe0679f77 Mon Sep 17 00:00:00 2001 From: Humphrey Yang Date: Wed, 8 Feb 2023 10:58:17 +1100 Subject: [PATCH 3/4] improve based on comments --- lectures/markov_chains.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lectures/markov_chains.md b/lectures/markov_chains.md index 5e428d08f..00bec27df 100644 --- a/lectures/markov_chains.md +++ b/lectures/markov_chains.md @@ -1103,9 +1103,9 @@ for x0 in x0s: for i in range(n_state): axes[i].axhline(ψ_star[i], linestyle='dashed', lw=2, color = 'black', - label = fr'$\psi^*({i})$') + label = fr'$\psi^*(i)$') axes[i].set_xlabel('t') - axes[i].set_ylabel(fr'$\psi({i})$') + axes[i].set_ylabel(fr'$\psi(i)$') axes[i].legend() plt.show() @@ -1144,7 +1144,7 @@ for x0 in x0s: for i in range(n_state): axes[i].axhline(ψ_star[i], linestyle='dashed', lw=2, color = 'black', label = fr'$\psi^* ({i})$') axes[i].set_xlabel('t') - axes[i].set_ylabel(fr'$\psi({i})$') + axes[i].set_ylabel(fr'$\psi(i)$') axes[i].legend() plt.show() @@ -1318,7 +1318,7 @@ codes_B = ( '1','2','3','4','5','6','7','8') np.linalg.matrix_power(P_B, 10) ``` -We find rows of transition matrix converge to the stationary distribution +We find that rows of the transition matrix converge to the stationary distribution ```{code-cell} ipython3 mc = qe.MarkovChain(P_B) @@ -1349,7 +1349,7 @@ ax.legend() plt.show() ``` -Note that the average time spent at each state quickly converges to the stationary distribution. +Note that the fraction of time spent at each state quickly converges to the probability assigned to that state by the stationary distribution. ```{solution-end} ``` From 02dd8b36bc65e9b9244b82d7ef855212246a3dec Mon Sep 17 00:00:00 2001 From: Humphrey Yang Date: Wed, 8 Feb 2023 15:46:58 +1100 Subject: [PATCH 4/4] update math symbols --- lectures/markov_chains.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lectures/markov_chains.md b/lectures/markov_chains.md index 00bec27df..ba559e824 100644 --- a/lectures/markov_chains.md +++ b/lectures/markov_chains.md @@ -905,12 +905,13 @@ n_state = P.shape[1] fig, axes = plt.subplots(nrows=1, ncols=n_state) ψ_star = mc.stationary_distributions[0] plt.subplots_adjust(wspace=0.35) + for i in range(n_state): axes[i].grid() axes[i].axhline(ψ_star[i], linestyle='dashed', lw=2, color = 'black', label = fr'$\psi^*({i})$') axes[i].set_xlabel('t') - axes[i].set_ylabel(fr'average time spent at {i}') + axes[i].set_ylabel(f'fraction of time spent at {i}') # Compute the fraction of time spent, starting from different x_0s for x0, col in ((0, 'blue'), (1, 'green'), (2, 'red')): @@ -970,13 +971,14 @@ mc = MarkovChain(P) n_state = P.shape[1] fig, axes = plt.subplots(nrows=1, ncols=n_state) ψ_star = mc.stationary_distributions[0] + for i in range(n_state): axes[i].grid() axes[i].set_ylim(0.45, 0.55) axes[i].axhline(ψ_star[i], linestyle='dashed', lw=2, color = 'black', label = fr'$\psi^*({i})$') axes[i].set_xlabel('t') - axes[i].set_ylabel(fr'average time spent at {i}') + axes[i].set_ylabel(f'fraction of time spent at {i}') # Compute the fraction of time spent, for each x for x0 in range(n_state): @@ -1103,9 +1105,9 @@ for x0 in x0s: for i in range(n_state): axes[i].axhline(ψ_star[i], linestyle='dashed', lw=2, color = 'black', - label = fr'$\psi^*(i)$') + label = fr'$\psi^*({i})$') axes[i].set_xlabel('t') - axes[i].set_ylabel(fr'$\psi(i)$') + axes[i].set_ylabel(fr'$\psi({i})$') axes[i].legend() plt.show() @@ -1142,9 +1144,9 @@ for x0 in x0s: axes[i].plot(range(20, n), X[20:,i], alpha=0.3) for i in range(n_state): - axes[i].axhline(ψ_star[i], linestyle='dashed', lw=2, color = 'black', label = fr'$\psi^* ({i})$') + axes[i].axhline(ψ_star[i], linestyle='dashed', lw=2, color = 'black', label = fr'$\psi^*({i})$') axes[i].set_xlabel('t') - axes[i].set_ylabel(fr'$\psi(i)$') + axes[i].set_ylabel(fr'$\psi({i})$') axes[i].legend() plt.show() @@ -1339,11 +1341,11 @@ ax.axhline(0, linestyle='dashed', lw=2, color = 'black', alpha=0.4) for x0 in range(8): - # Calculate the average time for each worker + # Calculate the fraction of time for each worker X_bar = (X == x0).cumsum() / (1 + np.arange(N, dtype=float)) ax.plot(X_bar - ψ_star[x0], label=f'$X = {x0+1} $') ax.set_xlabel('t') - ax.set_ylabel(fr'average time spent in a state $- \psi^* (x)$') + ax.set_ylabel(r'fraction of time spent in a state $- \psi^* (x)$') ax.legend() plt.show()