From 1d8178c10ba9c9776433420bd58bd558437b4efa Mon Sep 17 00:00:00 2001 From: mmcky Date: Mon, 24 Apr 2023 09:18:14 +1000 Subject: [PATCH 01/19] ENH: enable linkchecker --- .github/workflows/linkcheck.yml | 88 ++++++++++++++++----------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/.github/workflows/linkcheck.yml b/.github/workflows/linkcheck.yml index 83ce8c5e4..6f4358355 100644 --- a/.github/workflows/linkcheck.yml +++ b/.github/workflows/linkcheck.yml @@ -1,44 +1,44 @@ -# name: Link Checker [Anaconda, Linux] -# on: -# pull_request: -# types: [opened, reopened] -# schedule: -# # UTC 12:00 is early morning in Australia -# - cron: '0 12 * * *' -# jobs: -# link-check-linux: -# name: Link Checking (${{ matrix.python-version }}, ${{ matrix.os }}) -# runs-on: ${{ matrix.os }} -# strategy: -# fail-fast: false -# matrix: -# os: ["ubuntu-latest"] -# python-version: ["3.9"] -# steps: -# - name: Checkout -# uses: actions/checkout@v2 -# - name: Setup Anaconda -# uses: conda-incubator/setup-miniconda@v2 -# with: -# auto-update-conda: true -# auto-activate-base: true -# miniconda-version: 'latest' -# python-version: 3.9 -# environment-file: environment.yml -# activate-environment: quantecon -# - name: Download "build" folder (cache) -# uses: dawidd6/action-download-artifact@v2 -# with: -# workflow: cache.yml -# branch: main -# name: build-cache -# path: _build -# - name: Link Checker -# shell: bash -l {0} -# run: jb build lectures --path-output=./ --builder=custom --custom-builder=linkcheck -# - name: Upload Link Checker Reports -# uses: actions/upload-artifact@v2 -# if: failure() -# with: -# name: linkcheck-reports -# path: _build/linkcheck \ No newline at end of file +name: Link Checker [Anaconda, Linux] +on: + pull_request: + types: [opened, reopened] + schedule: + # UTC 12:00 is early morning in Australia + - cron: '0 12 * * *' +jobs: + link-check-linux: + name: Link Checking (${{ matrix.python-version }}, ${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: ["ubuntu-latest"] + python-version: ["3.10"] + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup Anaconda + uses: conda-incubator/setup-miniconda@v2 + with: + auto-update-conda: true + auto-activate-base: true + miniconda-version: 'latest' + python-version: "3.10" + environment-file: environment.yml + activate-environment: quantecon + - name: Download "build" folder (cache) + uses: dawidd6/action-download-artifact@v2 + with: + workflow: cache.yml + branch: main + name: build-cache + path: _build + - name: Link Checker + shell: bash -l {0} + run: jb build lectures --path-output=./ --builder=custom --custom-builder=linkcheck + - name: Upload Link Checker Reports + uses: actions/upload-artifact@v2 + if: failure() + with: + name: linkcheck-reports + path: _build/linkcheck \ No newline at end of file From 504b48b33ce5892543ebf5debf7d3f63a0a70be3 Mon Sep 17 00:00:00 2001 From: hengchengzhang Date: Wed, 28 Jun 2023 16:27:37 +1000 Subject: [PATCH 02/19] Fix typo --- lectures/commod_price.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lectures/commod_price.md b/lectures/commod_price.md index d59b0a2e1..35191abd6 100644 --- a/lectures/commod_price.md +++ b/lectures/commod_price.md @@ -143,7 +143,7 @@ In this section we define the equilibrium and discuss how to compute it. Speculators are assumed to be risk neutral, which means that they buy the commodity whenever expected profits are positive. -As a consequence, if expected prices are positive, then the market is not in +As a consequence, if expected profits are positive, then the market is not in equilibrium. Hence, to be in equilibrium, prices must satisfy the "no-arbitrage" From 189ce3c91c295e70f40d54842d380d2d6d08b660 Mon Sep 17 00:00:00 2001 From: John Stachurski Date: Wed, 28 Jun 2023 17:57:24 +1000 Subject: [PATCH 03/19] misc (#254) --- lectures/commod_price.md | 76 ++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 27 deletions(-) diff --git a/lectures/commod_price.md b/lectures/commod_price.md index 35191abd6..0489e8e7f 100644 --- a/lectures/commod_price.md +++ b/lectures/commod_price.md @@ -9,31 +9,58 @@ kernelspec: name: python3 --- -For this lecture we need the `yfinance` library. -```{code-cell} ipython3 -:tags: [hide-output] -!pip install yfinance -``` # Commodity Prices -For more than half of all countries around the globe, [commodities](https://en.wikipedia.org/wiki/Commodity) account for [the majority of total exports](https://unctad.org/publication/commodities-and-development-report-2019). +## Outline +For more than half of all countries around the globe, [commodities](https://en.wikipedia.org/wiki/Commodity) account for [the majority of total exports](https://unctad.org/publication/commodities-and-development-report-2019). Examples of commodities include copper, diamonds, iron ore, lithium, cotton and coffee beans. In this lecture we give an introduction to the theory of commodity prices. -The figure below shows the price of cotton in USD since the start of 2016. +The lecture is quite advanced relative to other lectures in this series. + +We need to compute an equilibrium, and that equilibrium is described by a +price function. + +We will solve an equation where the price function is the unknown. + +This is harder than solving an equation for an unknown number, or vector. + +The lecture will discuss one way to solve a "functional equation" for an unknown +function + +For this lecture we need the `yfinance` library. ```{code-cell} ipython3 -:tags: [hide-input, hide-output] +:tags: [hide-output] +!pip install yfinance +``` + +We will use the following imports + +```{code-cell} ipython3 +import numpy as np import yfinance as yf import matplotlib.pyplot as plt +from scipy.interpolate import interp1d +from scipy.optimize import minimize_scalar, brentq +from scipy.stats import beta +``` + +## Data + +The figure below shows the price of cotton in USD since the start of 2016. + +```{code-cell} ipython3 +:tags: [hide-input, hide-output] + s = yf.download('CT=F', '2016-1-1', '2023-4-1')['Adj Close'] ``` @@ -51,11 +78,18 @@ plt.show() The figure shows surprisingly large movements in the price of cotton. -In general, prices depend on the choices and actions of suppliers, consumers and -speculators. +What causes these movements? + +In general, prices depend on the choices and actions of + +1. suppliers, +2. consumers, and +3. speculators. -Our focus will be on the interaction between these parties, viewed through the -lens of the standard competitive storage model +Our focus will be on the interaction between these parties. + +We will connect them together in a dynamic model of supply and demand, called +the *competitive storage model*. This model was developed by {cite}`samuelson1971stochastic`, @@ -65,8 +99,8 @@ This model was developed by -## Outline +## The competitive storage model In the competitive storage model, commodities are assets that @@ -91,16 +125,6 @@ The equilibrium price is determined competitively. It is a function of the current state (which determines current harvests and predicts future harvests). -We begin with the following imports - - -```{code-cell} ipython3 -import numpy as np -import matplotlib.pyplot as plt -from scipy.interpolate import interp1d -from scipy.optimize import minimize_scalar, brentq -from scipy.stats import beta -``` ## The model @@ -113,8 +137,6 @@ The harvest of the commodity at time $t$ is $Z_t$. We assume that the sequence $\{ Z_t \}_{t \geq 1}$ is IID with common density function $\phi$. -The harvests take values in $S$, a subset of the nonnegative numbers. - Speculators can store the commodity between periods, with $I_t$ units purchased in the current period yielding $\alpha I_t$ units in the next. @@ -176,7 +198,7 @@ Regarding quantities, Mathematically, -* supply $ = X_t = \alpha I_{t-1} + Z_t$ +* supply $ = X_t = \alpha I_{t-1} + Z_t$, which takes values in $S := \mathbb R_+$, while * demand $ = D(p_t) + I_t$ Thus, the market equilibrium condition is @@ -193,7 +215,7 @@ The initial condition $X_0 \in S$ is treated as given. ### An equilibrium function -Now to find an equilibrium? +How can we find an equilibrium? Our path of attack will be to seek a system of prices that depend only on the current state. From 23ec1dd81c68fe91f67eec5e5bed676853eac430 Mon Sep 17 00:00:00 2001 From: thomassargent30 Date: Wed, 28 Jun 2023 09:41:07 -0600 Subject: [PATCH 04/19] Tom's edit of equalizing diff lecture June 28 --- lectures/equalizing_difference.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lectures/equalizing_difference.md b/lectures/equalizing_difference.md index 58494cbc9..e8c5d26eb 100644 --- a/lectures/equalizing_difference.md +++ b/lectures/equalizing_difference.md @@ -53,6 +53,8 @@ Let * $\gamma_c > 1$ be the (gross) rate of growth of wages of a college graduate, so that $ w_t^c = w_0^c \gamma_c^t$ + * $D$ be the upfront monetary costs of going to college + If someone goes to work immediately after high school and works for the $T+1$ years $t=0, 1, 2, \ldots, T$, she earns present value @@ -79,7 +81,7 @@ $$ where $$ -A_c =w_0^c (R^{-1} \gamma_c)^4 \left[ \frac{1 - (R^{-1} \gamma_c)^{T-3} }{1 - R^{-1} \gamma_c } \right] +A_c = (R^{-1} \gamma_c)^4 \left[ \frac{1 - (R^{-1} \gamma_c)^{T-3} }{1 - R^{-1} \gamma_c } \right] $$ The present value $c_0$ is the "human wealth" at the beginning of time $0$ of someone who chooses to attend college for four years and then start to work at time $t=4$ at the wage of a college graduate. From 687c44ca1e44174996d975be4c6481518132a624 Mon Sep 17 00:00:00 2001 From: Thomas Sargent Date: Wed, 28 Jun 2023 16:04:37 -0600 Subject: [PATCH 05/19] Tom's first edit of day of cons smoothing lecture --- lectures/cons_smooth.md | 234 +++++++++++++++++++++------------------- 1 file changed, 121 insertions(+), 113 deletions(-) diff --git a/lectures/cons_smooth.md b/lectures/cons_smooth.md index 472134f71..4d2fc4695 100644 --- a/lectures/cons_smooth.md +++ b/lectures/cons_smooth.md @@ -98,119 +98,6 @@ def creat_cs_model(R=1.05, g1=1, g2=1/2, T=65): +++ {"user_expressions": []} -## Difference equations with linear algebra - -As a warmup, we'll describe a useful way of representing and "solving" linear difference equations. - -To generate some $y$ vectors, we'll just write down a linear difference equation -with appropriate initial conditions and then use linear algebra to solve it. - -### First-order difference equation - -We'll start with a first-order linear difference equation for $\{y_t\}_{t=0}^T$: - -$$ -y_{t} = \lambda y_{t-1}, \quad t = 1, 2, \ldots, T -$$ - -where $y_0$ is a given initial condition. - - -We can cast this set of $T$ equations as a single matrix equation - -$$ -\begin{bmatrix} -1 & 0 & 0 & \cdots & 0 & 0 \cr --\lambda & 1 & 0 & \cdots & 0 & 0 \cr -0 & -\lambda & 1 & \cdots & 0 & 0 \cr - \vdots & \vdots & \vdots & \cdots & \vdots & \vdots \cr -0 & 0 & 0 & \cdots & -\lambda & 1 -\end{bmatrix} -\begin{bmatrix} -y_1 \cr y_2 \cr y_3 \cr \vdots \cr y_T -\end{bmatrix} -= -\begin{bmatrix} -\lambda y_0 \cr 0 \cr 0 \cr \vdots \cr 0 -\end{bmatrix} -$$ - - -Multiplying both sides by inverse of the matrix on the left provides the solution - -```{math} -:label: fst_ord_inverse - -\begin{bmatrix} -y_1 \cr y_2 \cr y_3 \cr \vdots \cr y_T -\end{bmatrix} -= -\begin{bmatrix} -1 & 0 & 0 & \cdots & 0 & 0 \cr -\lambda & 1 & 0 & \cdots & 0 & 0 \cr -\lambda^2 & \lambda & 1 & \cdots & 0 & 0 \cr - \vdots & \vdots & \vdots & \cdots & \vdots & \vdots \cr -\lambda^{T-1} & \lambda^{T-2} & \lambda^{T-3} & \cdots & \lambda & 1 -\end{bmatrix} -\begin{bmatrix} -\lambda y_0 \cr 0 \cr 0 \cr \vdots \cr 0 -\end{bmatrix} -``` - -```{exercise} -:label: consmooth_ex1 - -In the {eq}`fst_ord_inverse`, we multiply the inverse of the matrix $A$. In this exercise, please confirm that - -$$ -\begin{bmatrix} -1 & 0 & 0 & \cdots & 0 & 0 \cr -\lambda & 1 & 0 & \cdots & 0 & 0 \cr -\lambda^2 & \lambda & 1 & \cdots & 0 & 0 \cr - \vdots & \vdots & \vdots & \cdots & \vdots & \vdots \cr -\lambda^{T-1} & \lambda^{T-2} & \lambda^{T-3} & \cdots & \lambda & 1 -\end{bmatrix} -$$ - -is the inverse of $A$ and check that $A A^{-1} = I$ - -``` - -### Second order difference equation - -The second-order linear difference equation for $\{y_t\}_{t=0}^T$ is - -$$ -y_{t} = \lambda_1 y_{t-1} + \lambda_2 y_{t-2}, \quad t = 1, 2, \ldots, T -$$ - -Similarly, we can cast this set of $T$ equations as a single matrix equation - -$$ -\begin{bmatrix} -1 & 0 & 0 & \cdots & 0 & 0 & 0 \cr --\lambda_1 & 1 & 0 & \cdots & 0 & 0 & 0 \cr --\lambda_2 & -\lambda_1 & 1 & \cdots & 0 & 0 & 0 \cr - \vdots & \vdots & \vdots & \cdots & \vdots & \vdots \cr -0 & 0 & 0 & \cdots & -\lambda_2 & -\lambda_1 & 1 -\end{bmatrix} -\begin{bmatrix} -y_1 \cr y_2 \cr y_3 \cr \vdots \cr y_T -\end{bmatrix} -= -\begin{bmatrix} -\lambda_1 y_0 + \lambda_2 y_{-1} \cr \lambda_2 y_0 \cr 0 \cr \vdots \cr 0 -\end{bmatrix} -$$ - -Multiplying both sides by inverse of the matrix on the left again provides the solution. - -```{exercise} -:label: consmooth_ex2 - -As an exercise, we ask you to represent and solve a **third order linear difference equation**. -How many initial conditions must you specify? -``` ## Friedman-Hall consumption-smoothing model @@ -558,3 +445,124 @@ plt.ylabel('derivatives of welfare') plt.xlabel(r'$\phi$') plt.show() ``` + + +## Difference equations with linear algebra + +In the preceding sections we have used linear algebra to solve a consumption smoothing model. + +The same tools from linear algebra -- matrix multiplication and matrix inversion -- can be used to study many other dynamic models too. + +We'll concluse this lecture by giving a couple of examples. + +In particular, we'll describe a useful way of representing and "solving" linear difference equations. + +To generate some $y$ vectors, we'll just write down a linear difference equation +with appropriate initial conditions and then use linear algebra to solve it. + +### First-order difference equation + +We'll start with a first-order linear difference equation for $\{y_t\}_{t=0}^T$: + +$$ +y_{t} = \lambda y_{t-1}, \quad t = 1, 2, \ldots, T +$$ + +where $y_0$ is a given initial condition. + + +We can cast this set of $T$ equations as a single matrix equation + +$$ +\begin{bmatrix} +1 & 0 & 0 & \cdots & 0 & 0 \cr +-\lambda & 1 & 0 & \cdots & 0 & 0 \cr +0 & -\lambda & 1 & \cdots & 0 & 0 \cr + \vdots & \vdots & \vdots & \cdots & \vdots & \vdots \cr +0 & 0 & 0 & \cdots & -\lambda & 1 +\end{bmatrix} +\begin{bmatrix} +y_1 \cr y_2 \cr y_3 \cr \vdots \cr y_T +\end{bmatrix} += +\begin{bmatrix} +\lambda y_0 \cr 0 \cr 0 \cr \vdots \cr 0 +\end{bmatrix} +$$ + + +Multiplying both sides by inverse of the matrix on the left provides the solution + +```{math} +:label: fst_ord_inverse + +\begin{bmatrix} +y_1 \cr y_2 \cr y_3 \cr \vdots \cr y_T +\end{bmatrix} += +\begin{bmatrix} +1 & 0 & 0 & \cdots & 0 & 0 \cr +\lambda & 1 & 0 & \cdots & 0 & 0 \cr +\lambda^2 & \lambda & 1 & \cdots & 0 & 0 \cr + \vdots & \vdots & \vdots & \cdots & \vdots & \vdots \cr +\lambda^{T-1} & \lambda^{T-2} & \lambda^{T-3} & \cdots & \lambda & 1 +\end{bmatrix} +\begin{bmatrix} +\lambda y_0 \cr 0 \cr 0 \cr \vdots \cr 0 +\end{bmatrix} +``` + +```{exercise} +:label: consmooth_ex1 + +In the {eq}`fst_ord_inverse`, we multiply the inverse of the matrix $A$. In this exercise, please confirm that + +$$ +\begin{bmatrix} +1 & 0 & 0 & \cdots & 0 & 0 \cr +\lambda & 1 & 0 & \cdots & 0 & 0 \cr +\lambda^2 & \lambda & 1 & \cdots & 0 & 0 \cr + \vdots & \vdots & \vdots & \cdots & \vdots & \vdots \cr +\lambda^{T-1} & \lambda^{T-2} & \lambda^{T-3} & \cdots & \lambda & 1 +\end{bmatrix} +$$ + +is the inverse of $A$ and check that $A A^{-1} = I$ + +``` + +### Second order difference equation + +The second-order linear difference equation for $\{y_t\}_{t=0}^T$ is + +$$ +y_{t} = \lambda_1 y_{t-1} + \lambda_2 y_{t-2}, \quad t = 1, 2, \ldots, T +$$ + +Similarly, we can cast this set of $T$ equations as a single matrix equation + +$$ +\begin{bmatrix} +1 & 0 & 0 & \cdots & 0 & 0 & 0 \cr +-\lambda_1 & 1 & 0 & \cdots & 0 & 0 & 0 \cr +-\lambda_2 & -\lambda_1 & 1 & \cdots & 0 & 0 & 0 \cr + \vdots & \vdots & \vdots & \cdots & \vdots & \vdots \cr +0 & 0 & 0 & \cdots & -\lambda_2 & -\lambda_1 & 1 +\end{bmatrix} +\begin{bmatrix} +y_1 \cr y_2 \cr y_3 \cr \vdots \cr y_T +\end{bmatrix} += +\begin{bmatrix} +\lambda_1 y_0 + \lambda_2 y_{-1} \cr \lambda_2 y_0 \cr 0 \cr \vdots \cr 0 +\end{bmatrix} +$$ + +Multiplying both sides by inverse of the matrix on the left again provides the solution. + +```{exercise} +:label: consmooth_ex2 + +As an exercise, we ask you to represent and solve a **third order linear difference equation**. +How many initial conditions must you specify? +``` From 48fe4af1dd613f6ef5c19d8a5ae01ae24d6f5f79 Mon Sep 17 00:00:00 2001 From: thomassargent30 Date: Wed, 28 Jun 2023 18:51:32 -0600 Subject: [PATCH 06/19] Tom's second edit of June 28 of consumption-smoothing lecture --- lectures/cons_smooth.md | 93 +++++++++++++++++++++++++++++++++-------- 1 file changed, 75 insertions(+), 18 deletions(-) diff --git a/lectures/cons_smooth.md b/lectures/cons_smooth.md index 4d2fc4695..17bb0b34b 100644 --- a/lectures/cons_smooth.md +++ b/lectures/cons_smooth.md @@ -17,9 +17,19 @@ kernelspec: ## Overview -In this lecture, we'll present some useful models of economic dynamics using only linear algebra -- matrix multiplication and matrix inversion. +Technically, this lecture is a sequel to this quantecon lecture {doc}`present values `, although it might not seem so at first. -{doc}`Present value formulas` are at the core of the models. +It will take a while for a "present value" or asset price explicilty to appear in this lecture, but when it does it will be a key actor. + +In this lecture, we'll study a famous model of the "consumption function" that Milton Friedman {cite}`Friedman1956` and Robert Hall {cite}`Hall1978`) proposed to fit some empirical data patterns that the simple Keynesian model described in this quantecon lecture {doc}`geometric series ` had missed. + +The key insight of Friedman and Hall was that today's consumption ought not to depend just on today's income: it should also depend on a person's anticipations of her **future** incomes at various dates. + +In this lecture, we'll study what is sometimes called the "consumption-smoothing model" using only linear algebra, in particular matrix multiplication and matrix inversion. + +Formulas presented in {doc}`present value formulas` are at the core of the consumption smoothing model because they are used to define a consumer's "human wealth". + +As usual, we'll start with by importing some Python modules. ```{code-cell} ipython3 import numpy as np @@ -29,7 +39,12 @@ from collections import namedtuple +++ {"user_expressions": []} -Let +Our model describes the behavior of a consumer who lives from time $t=0, 1, \ldots, T$, receives an income stream $\{y_t\}_{t=0}^T$, +and chooses a consumption stream $\{c_t\}_{t=0}^T$. + +The consumer faces a gross interest rate of $R >1$ that is constant over time, at which she is free to borrow or lend, up to some limits that we'll describe below. + +To set up the model, let * $T \geq 2$ be a positive integer that constitutes a time-horizon @@ -47,18 +62,20 @@ Let * $a_{T+1} \geq 0$ be a terminal condition on final assets -A sequence of budget constraints constrains the triple of sequences $y, c, a$ +The consumer faces a sequence of budget constraints that constrains the triple of sequences $y, c, a$ $$ a_{t+1} = R (a_t+ y_t - c_t), \quad t =0, 1, \ldots T $$ (eq:a_t) -Our model has the following logical flow +Notice that there are $T+1$ such budget constraints, one for each $t=0, 1, \ldots, T$. + +Our model has the following logical flow. * start with an exogenous income sequence $y$, an initial financial wealth $a_0$, and a candidate consumption path $c$. - * use equation {eq}`eq:a_t` to compute a path $a$ of financial wealth + * use the system of equations {eq}`eq:a_t` for $t=0, \ldots, T$ to compute a path $a$ of financial wealth * verify that $a_{T+1}$ satisfies the terminal wealth constraint $a_{T+1} \geq 0$. @@ -68,6 +85,13 @@ Our model has the following logical flow Below, we'll describe how to execute these steps using linear algebra -- matrix inversion and multiplication. +The above procedure seems like a sensible way to find "budget-feasible" consumption paths $c$, i.e., paths that are consistent +with the exogenous income stream $y$, the initial financial asset level $a_0$, and the terminal asset level $a_{T+1}$. + +In general, there will be many budget feasible consumption paths $c$. + +Among all budget-feasible consumption paths, which one **should** the consumer want to choose? + We shall eventually evaluate alternative budget feasible consumption paths $c$ using the following **welfare criterion** @@ -81,6 +105,10 @@ where $g_1 > 0, g_2 > 0$. We shall see that when $\beta R = 1$ (a condition assumed by Milton Friedman {cite}`Friedman1956` and Robert Hall {cite}`Hall1978`), this criterion assigns higher welfare to **smoother** consumption paths. +By **smoother** we mean as close as possible to being constant over time. + +Let's dive in and do some calculations that will help us understand how the model works. + Here we use default parameters $R = 1.05$, $g_1 = 1$, $g_2 = 1/2$, and $T = 65$. We create a namedtuple to store these parameters with default values. @@ -101,7 +129,7 @@ def creat_cs_model(R=1.05, g1=1, g2=1/2, T=65): ## Friedman-Hall consumption-smoothing model -A key object is what Milton Friedman called "non-human" or "non-financial" wealth at time $0$: +A key object in the model is what Milton Friedman called "human" or "non-financial" wealth at time $0$: $$ @@ -109,6 +137,12 @@ h_0 \equiv \sum_{t=0}^T R^{-t} y_t = \begin{bmatrix} 1 & R^{-1} & \cdots & R^{-T \begin{bmatrix} y_0 \cr y_1 \cr \vdots \cr y_T \end{bmatrix} $$ +Human or non-financial wealth is evidently just the present value at time $0$ of the consumer's income stream $y$. + +Notice that formally it very much resembles the asset price that we computed in this quantecon lecture {doc}`present values `. + +Indeed, this is why Milton Friedman called it "human capital". + By iterating on equation {eq}`eq:a_t` and imposing the terminal condition $$ @@ -121,31 +155,33 @@ $$ \sum_{t=0}^T R^{-t} c_t = a_0 + h_0, $$ -which says that the present value of the consumption stream equals the sum of finanical and non-financial wealth. +which says that the present value of the consumption stream equals the sum of finanical and non-financial (or human) wealth. -Robert Hall {cite}`Hall1978` showed that when $\beta R = 1$, a condition Milton Friedman had assumed, +Robert Hall {cite}`Hall1978` showed that when $\beta R = 1$, a condition Milton Friedman had also assumed, it is "optimal" for a consumer to **smooth consumption** by setting $$ c_t = c_0 \quad t =0, 1, \ldots, T $$ +(Later we'll present a "variational argument" that shows that this constant path is indeed optimal when $\beta R =1$.) + In this case, we can use the intertemporal budget constraint to write $$ -c_0 = \left(\sum_{t=0}^T R^{-t}\right)^{-1} (a_0 + h_0) -$$ +c_t = \left(\sum_{t=0}^T R^{-t}\right)^{-1} (a_0 + h_0), \quad t= 0, 1, \ldots, T. +$$ (eq:conssmoothing) -This is the consumption-smoothing model in a nutshell. +Equation {eq}`eq:conssmoothing` is the consumption-smoothing model in a nutshell. +++ {"user_expressions": []} ## Permanent income model of consumption As promised, we'll provide step by step instructions on how to use linear algebra, readily implemented -in Python, to solve the consumption smoothing model. +in Python, to compute all the objects in play in the consumption-smoothing model. -In the calculations below, please we'll set default values of $R > 1$, e.g., $R = 1.05$, and $\beta = R^{-1}$. +In the calculations below, we'll set default values of $R > 1$, e.g., $R = 1.05$, and $\beta = R^{-1}$. ### Step 1 @@ -166,7 +202,7 @@ $$ ### Step 3 -Formulate system +Formulate the system of difference equations as follows (we'll say more about the mechanics of using linear algebra to solve such difference equations later in the last part of this lecture): $$ \begin{bmatrix} @@ -275,6 +311,15 @@ print('Welfare:', welfare(cs_model, c_seq)) ### Feasible consumption variations +Earlier, we had promised to present an argument that supports our claim that a constant consumption play $c_t = c_0$ for all +$t$ is optimal. + +Let's do that now. + +Although simple and direct, the approach we'll take is actually an example of what is called the "calculus of variations". + +Let's dive in and see what the key idea is. + To explore what types of consumption paths are welfare-improving, we shall create an **admissible consumption path variation sequence** $\{v_t\}_{t=0}^T$ that satisfies @@ -282,7 +327,7 @@ $$ \sum_{t=0}^T R^{-t} v_t = 0 $$ -We'll compute a two-parameter class of admissible variations +Here we'll compute a two-parameter class of admissible variations of the form $$ @@ -421,7 +466,7 @@ plt.show() welfare_grad = welfare_vec(ξ1_arr, 1.02) welfare_grad = np.gradient(welfare_grad) plt.plot(ξ1_arr, welfare_grad) -plt.ylabel('derivatives of welfare') +plt.ylabel('derivative of welfare') plt.xlabel(r'$\xi_1$') plt.show() ``` @@ -441,11 +486,23 @@ plt.show() welfare_grad = welfare_vec(0.05, ϕ_arr) welfare_grad = np.gradient(welfare_grad) plt.plot(ξ1_arr, welfare_grad) -plt.ylabel('derivatives of welfare') +plt.ylabel('derivative of welfare') plt.xlabel(r'$\phi$') plt.show() ``` +## Wrapping up the consumption-smoothing model + +The consumption-smoothing model of Milton Friedman {cite}`Friedman1956` and Robert Hall {cite}`Hall1978`) is a cornerstone of modern macro +that has important ramifications about the size of the Keynesian "fiscal policy multiplier" described briefly in +quantecon lecture {doc}`geometric series `. + +In particular, Milton Friedman and others showed that it **lowered** the fiscal policy multiplier relative to the one implied by +the simple Keynesian consumption function presented in {doc}`geometric series `. + +Friedman and Hall's work opened the door to a lively literature on the aggregate consumption function and implied fiscal multipliers that +remains very active today. + ## Difference equations with linear algebra From 78940fdea0f02a2d48b7032834f5cb54a4ff5f79 Mon Sep 17 00:00:00 2001 From: hengchengzhang Date: Mon, 26 Jun 2023 13:32:30 +1000 Subject: [PATCH 07/19] Fix userwarning --- lectures/scalar_dynam.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lectures/scalar_dynam.md b/lectures/scalar_dynam.md index 58605a1a1..10e082f89 100644 --- a/lectures/scalar_dynam.md +++ b/lectures/scalar_dynam.md @@ -365,7 +365,7 @@ def plot45(g, xmin, xmax, x0, num_arrows=6, var='x'): x = g(x) xticks.append(x) xtick_labels.append(r'${}_{}$'.format(var, str(i+1))) - ax.plot((x, x), (0, x), 'k-', ls='dotted') + ax.plot((x, x), (0, x), 'k', ls='dotted') xticks.append(xmax) xtick_labels.append(xmax) From f438208661f3aee18007629304d940b315f6c5a0 Mon Sep 17 00:00:00 2001 From: thomassargent30 Date: Thu, 29 Jun 2023 12:33:16 -0600 Subject: [PATCH 08/19] Tom's June 29 edits of equalizing difference lecture --- lectures/equalizing_difference.md | 172 +++++++++++++++++++++++++++++- 1 file changed, 170 insertions(+), 2 deletions(-) diff --git a/lectures/equalizing_difference.md b/lectures/equalizing_difference.md index e8c5d26eb..2582c104b 100644 --- a/lectures/equalizing_difference.md +++ b/lectures/equalizing_difference.md @@ -13,6 +13,8 @@ kernelspec: # Equalizing Difference Model +## Overview + This lecture presents a model of the college-high-school wage gap in which the "time to build" a college graduate plays a key role. @@ -26,6 +28,14 @@ The idea behind this condition is that lifetime earnings have to adjust to make It is just one instance of an "equalizing difference" theory of relative wage rates, a class of theories dating back at least to Adam Smith's **Wealth of Nations** {cite}`smith2010wealth`. +For most of this lecture, the only mathematical tools that we'll use are from linear algebra, in particular, matrix multiplication and matrix inversion. + +However, at the very end of the lecture, we'll use calculus just in case readers want to see how computing partial derivatives could let us present some findings more concisely. + +(And doing that will let us show off how good Python is at doing calculus!) + +But if you don't know calculus, our tools from linear algebra are certainly enough. + As usual, we'll start by importing some Python modules. ```{code-cell} ipython3 @@ -33,6 +43,10 @@ import numpy as np import matplotlib.pyplot as plt ``` +## The indifference condition + +The key idea is that the initial college wage premium has to adjust to make a representative worker indifferent between going to college and not going to college. + Let * $R > 1$ be the gross rate of return on a one-period bond @@ -119,6 +133,8 @@ $$ w_0^h A_h = \phi w_0^h A_c - D . $$ (eq:equalize) +This is the "indifference condition" that is at the heart of the model. + Solving equation {eq}`eq:equalize` for the college wage premium $\phi$ we obtain $$ @@ -139,7 +155,7 @@ But first we'll describe a possible alternative interpretation of our model. -## A tweaked model: workers and entrepreneurs +## Reinterpreting the model: workers and entrepreneurs We can add a parameter and reinterpret variables to get a model of entrepreneurs versus workers. @@ -308,7 +324,7 @@ plt.show() ``` -**Entrepreneur-worker interpretation** +## Entrepreneur-worker interpretation Now let's adopt the entrepreneur-worker interpretation of our model. @@ -335,6 +351,158 @@ plt.show() Does the graph make sense to you? + + +## An application of calculus + +So far, we have used only linear algebra and it has been a good enough tool for us to figure out how our model works. + +However, someone who knows calculus might ask "Instead of plotting those graphs, why didn't you just take partial derivatives?" + +We'll briefly do just that, yes, the questioner is correct and that partial derivatives are indeed a good tool for discovering the "comparative statics" properities of our model. + +A reader who doesn't know calculus could read no further and feel confident that applying linear algebra has taught us the main properties of the model. + +But for a reader interested in how we can get Python to do all the hard work involved in computing partial derivatives, we'll say a few things about that now. + +We'll use the Python module 'sympy' to compute partial derivatives of $\phi$ with respect to the parameters that determine it. + +Let's import key functions from sympy. + +```{code-cell} ipython3 +from sympy import Symbol, Lambda, symbols +``` + +Define symbols + +```{code-cell} ipython3 +γ_h, γ_c, w_h0, D = symbols('\gamma_h, \gamma_h_c, w_0^h, D', real=True) +R, T = Symbol('R', real=True), Symbol('T', integer=True) +``` + +Define function $A_h$ + +```{code-cell} ipython3 +A_h = Lambda((γ_h, R, T), (1 - (γ_h/R)**(T+1)) / (1 - γ_h/R)) +A_h +``` + +Define function $A_c$ + ```{code-cell} ipython3 +A_c = Lambda((γ_c, R, T), (1 - (γ_c/R)**(T-3)) / (1 - γ_c/R) * (γ_c/R)**4) +A_c +``` + +Now, define $\phi$ +```{code-cell} ipython3 +ϕ = Lambda((D, γ_h, γ_c, R, T, w_h0), A_h(γ_h, R, T)/A_c(γ_c, R, T) + D/(w_h0*A_c(γ_c, R, T))) ``` + +```{code-cell} ipython3 +ϕ +``` + +We begin by setting default parameter values. + +```{code-cell} ipython3 +R_value = 1.05 +T_value = 40 +γ_h_value, γ_c_value = 1.01, 1.01 +w_h0_value = 1 +D_value = 10 +``` + +Now let's compute $\frac{\partial \phi}{\partial D}$ and then evaluate it at the default values + +```{code-cell} ipython3 +ϕ_D = ϕ(D, γ_h, γ_c, R, T, w_h0).diff(D) +ϕ_D +``` + +```{code-cell} ipython3 +# Numerical value at default parameters +ϕ_D_func = Lambda((D, γ_h, γ_c, R, T, w_h0), ϕ_D) +ϕ_D_func(D_value, γ_h_value, γ_c_value, R_value, T_value, w_h0_value) +``` + +Thus, as with our graph above, we find that raising $R$ increases the initial college wage premium $\phi$. + ++++ + +Compute $\frac{\partial \phi}{\partial T}$ and evaluate it a default parameters + +```{code-cell} ipython3 +ϕ_T = ϕ(D, γ_h, γ_c, R, T, w_h0).diff(T) +ϕ_T +``` + +```{code-cell} ipython3 +# Numerical value at default parameters +ϕ_T_func = Lambda((D, γ_h, γ_c, R, T, w_h0), ϕ_T) +ϕ_T_func(D_value, γ_h_value, γ_c_value, R_value, T_value, w_h0_value) +``` + +We find that raising $T$ decreases the initial college wage premium $\phi$. + +This is because college graduates now have longer career lengths to "pay off" the time and other costs they paid to go to college + ++++ + +Let's compute $\frac{\partial \phi}{\partial γ_h}$ and evaluate it at default parameters. + +```{code-cell} ipython3 +ϕ_γ_h = ϕ(D, γ_h, γ_c, R, T, w_h0).diff(γ_h) +ϕ_γ_h +``` + +```{code-cell} ipython3 +# Numerical value at default parameters +ϕ_γ_h_func = Lambda((D, γ_h, γ_c, R, T, w_h0), ϕ_γ_h) +ϕ_γ_h_func(D_value, γ_h_value, γ_c_value, R_value, T_value, w_h0_value) +``` + +We find that raising $\gamma_h$ increases the initial college wage premium $\phi$, as we did with our graphical analysis earlier + ++++ + +Compute $\frac{\partial \phi}{\partial γ_c}$ and evaluate it numerically at default parameter values + +```{code-cell} ipython3 +ϕ_γ_c = ϕ(D, γ_h, γ_c, R, T, w_h0).diff(γ_c) +ϕ_γ_c +``` + +```{code-cell} ipython3 +# Numerical value at default parameters +ϕ_γ_c_func = Lambda((D, γ_h, γ_c, R, T, w_h0), ϕ_γ_c) +ϕ_γ_c_func(D_value, γ_h_value, γ_c_value, R_value, T_value, w_h0_value) +``` + +We find that raising $\gamma_c$ decreases the initial college wage premium $\phi$, as we did with our graphical analysis earlier + ++++ + +Let's compute $\frac{\partial \phi}{\partial R}$ and evaluate it numerically at default parameter values + +```{code-cell} ipython3 +ϕ_R = ϕ(D, γ_h, γ_c, R, T, w_h0).diff(R) +ϕ_R +``` + +```{code-cell} ipython3 +# Numerical value at default parameters +ϕ_R_func = Lambda((D, γ_h, γ_c, R, T, w_h0), ϕ_R) +ϕ_R_func(D_value, γ_h_value, γ_c_value, R_value, T_value, w_h0_value) +``` + ++++ {"tags": []} + +We find that raising the gross interest rate $R$ increases the initial college wage premium $\phi$, as we did with our graphical analysis earlier + + + +```{code-cell} ipython3 + +``` \ No newline at end of file From 664da8ec91bcf124e50a66867b53b97352d40de4 Mon Sep 17 00:00:00 2001 From: thomassargent30 Date: Thu, 29 Jun 2023 14:09:49 -0600 Subject: [PATCH 09/19] Tom's edits of consumption smoothing lecture, June 29 --- lectures/cons_smooth.md | 65 ++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/lectures/cons_smooth.md b/lectures/cons_smooth.md index 17bb0b34b..085622daf 100644 --- a/lectures/cons_smooth.md +++ b/lectures/cons_smooth.md @@ -23,7 +23,7 @@ It will take a while for a "present value" or asset price explicilty to appear i In this lecture, we'll study a famous model of the "consumption function" that Milton Friedman {cite}`Friedman1956` and Robert Hall {cite}`Hall1978`) proposed to fit some empirical data patterns that the simple Keynesian model described in this quantecon lecture {doc}`geometric series ` had missed. -The key insight of Friedman and Hall was that today's consumption ought not to depend just on today's income: it should also depend on a person's anticipations of her **future** incomes at various dates. +The key insight of Friedman and Hall was that today's consumption ought not to depend just on today's non-financial income: it should also depend on a person's anticipations of her **future** non-financial incomes at various dates. In this lecture, we'll study what is sometimes called the "consumption-smoothing model" using only linear algebra, in particular matrix multiplication and matrix inversion. @@ -39,8 +39,11 @@ from collections import namedtuple +++ {"user_expressions": []} -Our model describes the behavior of a consumer who lives from time $t=0, 1, \ldots, T$, receives an income stream $\{y_t\}_{t=0}^T$, -and chooses a consumption stream $\{c_t\}_{t=0}^T$. +Our model describes the behavior of a consumer who lives from time $t=0, 1, \ldots, T$, receives a stream $\{y_t\}_{t=0}^T$ of non-financial income and chooses a consumption stream $\{c_t\}_{t=0}^T$. + +We usually think of the non-financial income stream as coming from the person's salary from supplying labor. + +The model takes that non-financial income stream as an input, regarding it as "exogenous" in the sense of not being determined by the model. The consumer faces a gross interest rate of $R >1$ that is constant over time, at which she is free to borrow or lend, up to some limits that we'll describe below. @@ -48,7 +51,7 @@ To set up the model, let * $T \geq 2$ be a positive integer that constitutes a time-horizon - * $y = \{y_t\}_{t=0}^T$ be an exogenous sequence of non-negative financial incomes $y_t$ + * $y = \{y_t\}_{t=0}^T$ be an exogenous sequence of non-negative non-financial incomes $y_t$ * $a = \{a_t\}_{t=0}^{T+1}$ be a sequence of financial wealth @@ -62,31 +65,40 @@ To set up the model, let * $a_{T+1} \geq 0$ be a terminal condition on final assets +While the sequence of financial wealth $a$ is to be determined by the model, it must satisfy two **boundary conditions** that require it to be equal to $a_0$ at time $0$ and $a_{T+1}$ at time $T+1$. + +The **terminal condition** $a_{T+1} \geq 0$ requires that the consumer not die leaving debts. + +(We'll see that a utility maximizing consumer won't **want** to die leaving positive assets, so she'll arrange her affairs to make +$a_{T+1} = 0.) + The consumer faces a sequence of budget constraints that constrains the triple of sequences $y, c, a$ $$ a_{t+1} = R (a_t+ y_t - c_t), \quad t =0, 1, \ldots T $$ (eq:a_t) -Notice that there are $T+1$ such budget constraints, one for each $t=0, 1, \ldots, T$. +Notice that there are $T+1$ such budget constraints, one for each $t=0, 1, \ldots, T$. + +Given a sequence $y$ of non-financial income, there is a big set of **pairs** $(a, c)$ of (financial wealth, consumption) sequences that satisfy the sequence of budget constraints {eq}`eq:a_t`. Our model has the following logical flow. - * start with an exogenous income sequence $y$, an initial financial wealth $a_0$, and + * start with an exogenous non-financial income sequence $y$, an initial financial wealth $a_0$, and a candidate consumption path $c$. * use the system of equations {eq}`eq:a_t` for $t=0, \ldots, T$ to compute a path $a$ of financial wealth * verify that $a_{T+1}$ satisfies the terminal wealth constraint $a_{T+1} \geq 0$. - * If it does, declare that the candidate path is budget feasible. + * If it does, declare that the candidate path is **budget feasible**. * if the candidate consumption path is not budget feasible, propose a path with less consumption sometimes and start over Below, we'll describe how to execute these steps using linear algebra -- matrix inversion and multiplication. The above procedure seems like a sensible way to find "budget-feasible" consumption paths $c$, i.e., paths that are consistent -with the exogenous income stream $y$, the initial financial asset level $a_0$, and the terminal asset level $a_{T+1}$. +with the exogenous non-financial income stream $y$, the initial financial asset level $a_0$, and the terminal asset level $a_{T+1}$. In general, there will be many budget feasible consumption paths $c$. @@ -103,10 +115,14 @@ W = \sum_{t=0}^T \beta^t (g_1 c_t - \frac{g_2}{2} c_t^2 ) where $g_1 > 0, g_2 > 0$. -We shall see that when $\beta R = 1$ (a condition assumed by Milton Friedman {cite}`Friedman1956` and Robert Hall {cite}`Hall1978`), this criterion assigns higher welfare to **smoother** consumption paths. +The fact that the utility function $g_1 c_t - \frac{g_2}{2} c_t^2$ has diminishing marginal utility imparts a preference for consumption that is very smooth when $\beta R \approx 1$. + +Indeed, we shall see that when $\beta R = 1$ (a condition assumed by Milton Friedman {cite}`Friedman1956` and Robert Hall {cite}`Hall1978`), this criterion assigns higher welfare to **smoother** consumption paths. By **smoother** we mean as close as possible to being constant over time. +The preference for smooth consumption paths that is built into the model gives it the name "consumption smoothing model". + Let's dive in and do some calculations that will help us understand how the model works. Here we use default parameters $R = 1.05$, $g_1 = 1$, $g_2 = 1/2$, and $T = 65$. @@ -137,7 +153,7 @@ h_0 \equiv \sum_{t=0}^T R^{-t} y_t = \begin{bmatrix} 1 & R^{-1} & \cdots & R^{-T \begin{bmatrix} y_0 \cr y_1 \cr \vdots \cr y_T \end{bmatrix} $$ -Human or non-financial wealth is evidently just the present value at time $0$ of the consumer's income stream $y$. +Human or non-financial wealth is evidently just the present value at time $0$ of the consumer's non-financial income stream $y$. Notice that formally it very much resembles the asset price that we computed in this quantecon lecture {doc}`present values `. @@ -169,14 +185,14 @@ $$ In this case, we can use the intertemporal budget constraint to write $$ -c_t = \left(\sum_{t=0}^T R^{-t}\right)^{-1} (a_0 + h_0), \quad t= 0, 1, \ldots, T. +c_t = c_0 = \left(\sum_{t=0}^T R^{-t}\right)^{-1} (a_0 + h_0), \quad t= 0, 1, \ldots, T. $$ (eq:conssmoothing) Equation {eq}`eq:conssmoothing` is the consumption-smoothing model in a nutshell. +++ {"user_expressions": []} -## Permanent income model of consumption +## Mechanics of Consumption smoothing model As promised, we'll provide step by step instructions on how to use linear algebra, readily implemented in Python, to compute all the objects in play in the consumption-smoothing model. @@ -194,15 +210,17 @@ $$ ### Step 2 -Compute +Compute the optimal level of consumption $c_0 $ $$ -c_0 = \left( \frac{1 - R^{-1}}{1 - R^{-(T+1)}} \right) (a_0 + \sum_{t=0}^T R^t y_t ) +c_t = c_0 = \left( \frac{1 - R^{-1}}{1 - R^{-(T+1)}} \right) (a_0 + \sum_{t=0}^T R^t y_t ) , \quad t = 0, 1, \ldots, T $$ ### Step 3 -Formulate the system of difference equations as follows (we'll say more about the mechanics of using linear algebra to solve such difference equations later in the last part of this lecture): +In this step, we use the system of equations {eq}`eq:a_t` for $t=0, \ldots, T$ to compute a path $a$ of financial wealth. + +To do this, we translated that system of difference equations into a single matrix equation as follows (we'll say more about the mechanics of using linear algebra to solve such difference equations later in the last part of this lecture): $$ \begin{bmatrix} @@ -232,6 +250,9 @@ $$ a_{T+1} = 0. $$ +We have built into the our calculations that the consumer leaves life with exactly zero assets, just barely satisfying the +terminal condition that $a_{T+1} \geq 0$. + Let's verify this with our Python code. First we implement this model in `compute_optimal` @@ -260,13 +281,13 @@ def compute_optimal(model, a0, y_seq): We use an example where the consumer inherits $a_0<0$ (which can be interpreted as a student debt). -The income process $\{y_t\}_{t=0}^{T}$ is constant and positive up to $t=45$ and then becomes zero afterward. +The non-financial process $\{y_t\}_{t=0}^{T}$ is constant and positive up to $t=45$ and then becomes zero afterward. ```{code-cell} ipython3 # Financial wealth a0 = -2 # such as "student debt" -# Income process +# non-financial Income process y_seq = np.concatenate([np.ones(46), np.zeros(20)]) cs_model = creat_cs_model() @@ -276,15 +297,15 @@ print('check a_T+1=0:', np.abs(a_seq[-1] - 0) <= 1e-8) ``` -The visualization shows the path of income, consumption, and financial assets. +The visualization shows the path of non-financial income, consumption, and financial assets. ```{code-cell} ipython3 # Sequence Length T = cs_model.T -plt.plot(range(T+1), y_seq, label='income') +plt.plot(range(T+1), y_seq, label='non-financial income') plt.plot(range(T+1), c_seq, label='consumption') -plt.plot(range(T+2), a_seq, label='asset') +plt.plot(range(T+2), a_seq, label='financial wealth') plt.plot(range(T+2), np.zeros(T+2), '--') plt.legend() @@ -327,6 +348,10 @@ $$ \sum_{t=0}^T R^{-t} v_t = 0 $$ +This equation says that the **present value** of admissible variations must be zero. + +(So once again, we encounter our formula for the present value of an "asset".) + Here we'll compute a two-parameter class of admissible variations of the form From 02ee033f9ccb7c033a3cbeb501eb4fea4a377256 Mon Sep 17 00:00:00 2001 From: hengchengzhang Date: Thu, 29 Jun 2023 19:43:15 +1000 Subject: [PATCH 10/19] Updates --- lectures/eigen_II.md | 157 +++++++++++++++++++++++++++++-------------- 1 file changed, 105 insertions(+), 52 deletions(-) diff --git a/lectures/eigen_II.md b/lectures/eigen_II.md index 8414f8843..f61c9a25f 100644 --- a/lectures/eigen_II.md +++ b/lectures/eigen_II.md @@ -11,9 +11,9 @@ kernelspec: name: python3 --- -# Spectral Theory +# The Perron-Frobenius Theorem -```{index} single: Spectral Theory +```{index} single: The Perron-Frobenius Theorem ``` ```{contents} Contents @@ -51,8 +51,6 @@ Nonnegative matrices have several special and useful properties. In this section we will discuss some of them --- in particular, the connection between nonnegativity and eigenvalues. -Let $a^{k}_{ij}$ be element $(i,j)$ of $A^k$. - An $n \times m$ matrix $A$ is called **nonnegative** if every element of $A$ is nonnegative, i.e., $a_{ij} \geq 0$ for every $i,j$. @@ -65,38 +63,56 @@ We introduced irreducible matrices in the [Markov chain lecture](mc_irreducible) Here we generalize this concept: -An $n \times n$ matrix $A$ is called irreducible if, for each $i,j$ with $1 \leq i, j \leq n$, there exists a $k \geq 0$ such that $a^{k}_{ij} > 0$. - -A matrix $A$ that is not irreducible is called reducible. +Let $a^{k}_{ij}$ be element $(i,j)$ of $A^k$. -Here are some examples to illustrate this further. +An $n \times n$ nonnegative matrix $A$ is called irreducible if $A + A^2 + A^3 + \cdots \gg 0$, where $\gg 0$ denotes every element in $A$ is nonnegative. -1. $A = \begin{bmatrix} 0.5 & 0.1 \\ 0.2 & 0.2 \end{bmatrix}$ is irreducible since $a_{ij}>0$ for all $(i,j)$. +In other words, for each $i,j$ with $1 \leq i, j \leq n$, there exists a $k \geq 0$ such that $a^{k}_{ij} > 0$. -2. $A = \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix}$ is irreducible since $a_{12},a_{21} >0$ and $a^{2}_{11},a^{2}_{22} >0$. +Here are some examples to illustrate this further: -3. $A = \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix}$ is reducible since $A^k = A$ for all $k \geq 0$ and thus - $a^{k}_{12},a^{k}_{21} = 0$ for all $k \geq 0$. +$$ +A = \begin{bmatrix} 0.5 & 0.1 \\ + 0.2 & 0.2 +\end{bmatrix} +$$ -### Primitive matrices +$A$ is irreducible since $a_{ij}>0$ for all $(i,j)$. -Let $A$ be a square nonnegative matrix and let $A^k$ be the $k^{th}$ power of $A$. +$$ +B = \begin{bmatrix} 0 & 1 \\ + 1 & 0 +\end{bmatrix} +, \quad +B^2 = \begin{bmatrix} 1 & 0 \\ + 0 & 1 +\end{bmatrix} +$$ -A matrix is called **primitive** if there exists a $k \in \mathbb{N}$ such that $A^k$ is everywhere positive. +$B$ is irreducible since $b_{12},b_{21} >0$ and $b^{2}_{11},b^{2}_{22} >0$. -It means that $A$ is called primitive if there is an integer $k \geq 0$ such that $a^{k}_{ij} > 0$ for *all* $(i,j)$. +$$ +C = \begin{bmatrix} 1 & 0 \\ + 0 & 1 +\end{bmatrix} +$$ -We can see that if a matrix is primitive, then it implies the matrix is irreducible. +$C$ is reducible since $C^k = C$ for all $k \geq 0$ and thus + $c^{k}_{12},c^{k}_{21} = 0$ for all $k \geq 0$. ### Left eigenvectors -We previously discussed right (ordinary) eigenvectors $Av = \lambda v$. +Recall that we previously discussed eigenvectors in {ref}`Eigenvalues and Eigenvectors `. -Here we introduce left eigenvectors. +The eigenvalue $\lambda$ and its cooresponding eigenvecotr $v$ of matrix $A$ satisfy -Left eigenvectors will play important roles in what follows, including that of stochastic steady states for dynamic models under a Markov assumption. +$$ +Av = \lambda v. +$$ + +In this section we will define $v$ as right eigenvectors since we will be introducing left eigenvectors now. -We will talk more about this later, but for now, let's define left eigenvectors. +Left eigenvectors will play important roles in what follows, including that of stochastic steady states for dynamic models under a Markov assumption. A vector $w$ is called a left eigenvector of $A$ if $w$ is an eigenvector of $A^\top$. @@ -109,19 +125,16 @@ A = np.array([[3, 2], [1, 4]]) # Compute right eigenvectors and eigenvalues -λ_r, v = eig(A) +λ, v = eig(A) # Compute left eigenvectors and eigenvalues -λ_l, w = eig(A.T) +λ, w = eig(A.T) -print("Right Eigenvalues:") -print(λ_r) -print("\nRight Eigenvectors:") -print(v) -print("\nLeft Eigenvalues:") -print(λ_l) -print("\nLeft Eigenvectors:") -print(w) +np.set_printoptions(precision=5) + +print(f"The eigenvalues of A are:\n {λ}\n") +print(f"The corresponding right eigenvectors are: \n {v[:,0]} and {-v[:,1]}\n") +print(f"The corresponding left eigenvectors are: \n {w[:,0]} and {-w[:,1]}\n") ``` We can use `scipy.linalg.eig` with argument `left=True` to find left eigenvectors directly @@ -129,17 +142,14 @@ We can use `scipy.linalg.eig` with argument `left=True` to find left eigenvector ```{code-cell} ipython3 eigenvals, ε, e = sp.linalg.eig(A, left=True) -print("Right Eigenvalues:") -print(λ_r) -print("\nRight Eigenvectors:") -print(v) -print("\nLeft Eigenvalues:") -print(λ_l) -print("\nLeft Eigenvectors:") -print(w) +print(f"The eigenvalues of A are:\n {eigenvals.real}\n") +print(f"The corresponding right eigenvectors are: \n {e[:,0]} and {-e[:,1]}\n") +print(f"The corresponding left eigenvectors are: \n {ε[:,0]} and {-ε[:,1]}\n") ``` -Note that the eigenvalues for both left and right eigenvectors are the same, but the eigenvectors themselves are different. +We can find that the eigenvalues are the same while the eigenvectors themselves are different. + +(Also note that we are taking the nonnegative value of the eigenvector of {ref}`dominant eigenvalue `, this is because `eig` automatically normalize the eigenvectors.) We can then take transpose to obtain $A^\top w = \lambda w$ and obtain $w^\top A= \lambda w^\top$. @@ -168,11 +178,7 @@ Moreover if $A$ is also irreducible then, 4. the eigenvector $v$ associated with the eigenvalue $r(A)$ is strictly positive. 5. there exists no other positive eigenvector $v$ (except scalar multiples of $v$) associated with $r(A)$. -If $A$ is primitive then, - -6. the inequality $|\lambda| \leq r(A)$ is **strict** for all eigenvalues $\lambda$ of $A$ distinct from $r(A)$, and -7. with $v$ and $w$ normalized so that the inner product of $w$ and $v = 1$, we have -$ r(A)^{-m} A^m$ converges to $v w^{\top}$ when $m \rightarrow \infty$. The matrix $v w^{\top}$ is called the **Perron projection** of $A$ +(More of the Perron-Frobenius theorem about primitive matrices will be introduced {ref}`below `.) ``` (This is a relatively simple version of the theorem --- for more details see @@ -184,7 +190,7 @@ Let's build our intuition for the theorem using a simple example we have seen [b Now let's consider examples for each case. -#### Example 1: irreducible matrix +#### Example: Irreducible matrix Consider the following irreducible matrix $A$: @@ -200,7 +206,7 @@ We can compute the dominant eigenvalue and the corresponding eigenvector eig(A) ``` -Now we can go through our checklist to verify the claims of the Perron-Frobenius Theorem for the irreducible matrix $A$: +Now we will can see the claims of the Perron-Frobenius Theorem holds for the irreducible matrix $A$: 1. The dominant eigenvalue is real-valued and non-negative. 2. All other eigenvalues have absolute values less than or equal to the dominant eigenvalue. @@ -208,7 +214,54 @@ Now we can go through our checklist to verify the claims of the Perron-Frobenius 4. As the matrix is irreducible, the eigenvector associated with the dominant eigenvalue is strictly positive. 5. There exists no other positive eigenvector associated with the dominant eigenvalue. -#### Example 2: primitive matrix +(prim_matrices)= +### Primitive matrices + +We know that in real world situations it's hard for a matrix to be everywhere positive (although they have nice properties). + +The primitive matrices, however, can still give us helpful properties with looser definitions. + +Let $A$ be a square nonnegative matrix and let $A^k$ be the $k^{th}$ power of $A$. + +A matrix is called **primitive** if there exists a $k \in \mathbb{N}$ such that $A^k$ is everywhere positive. + +Recall the examples given in irreducible matrices: + +$$ +A = \begin{bmatrix} 0.5 & 0.1 \\ + 0.2 & 0.2 +\end{bmatrix} +$$ + +$A$ here is also a primitive matrix since $A^k$ is everywhere nonnegative for $k \in \mathbb{N}$. + +$$ +B = \begin{bmatrix} 0 & 1 \\ + 1 & 0 +\end{bmatrix} +, \quad +B^2 = \begin{bmatrix} 1 & 0 \\ + 0 & 1 +\end{bmatrix} +$$ + +$B$ is irreducible but not premitive since there are always zeros in either principal diagonal or secondary diagonal. + +We can see that if a matrix is primitive, then it implies the matrix is irreducible but not vice versa. + +Now let's step back to the primitive matrices part of the Perron-Frobenius Theorem + +```{prf:Theorem} Continous of Perron-Frobenius Theorem +:label: con-perron-frobenius + +If $A$ is primitive then, + +6. the inequality $|\lambda| \leq r(A)$ is **strict** for all eigenvalues $\lambda$ of $A$ distinct from $r(A)$, and +7. with $v$ and $w$ normalized so that the inner product of $w$ and $v = 1$, we have +$ r(A)^{-m} A^m$ converges to $v w^{\top}$ when $m \rightarrow \infty$. The matrix $v w^{\top}$ is called the **Perron projection** of $A$. +``` + +#### Example 1: Primitive matrix Consider the following primitive matrix $B$: @@ -226,7 +279,7 @@ We compute the dominant eigenvalue and the corresponding eigenvector eig(B) ``` -Now let's verify the claims of the Perron-Frobenius Theorem for the primitive matrix $B$: +Now let's give some examples to see if the claims of the Perron-Frobenius Theorem holds for the primitive matrix $B$: 1. The dominant eigenvalue is real-valued and non-negative. 2. All other eigenvalues have absolute values strictly less than the dominant eigenvalue. @@ -327,11 +380,11 @@ These examples show how the Perron-Frobenius Theorem relates to the eigenvalues In fact we have already seen the theorem in action before in {ref}`the markov chain lecture `. (spec_markov)= -#### Example 3: Connection to Markov chains +#### Example 2: Connection to Markov chains We are now prepared to bridge the languages spoken in the two lectures. -A primitive matrix is both irreducible (or strongly connected in the language of {ref}`graph theory` and aperiodic. +A primitive matrix is both irreducible and aperiodic. So Perron-Frobenius Theorem explains why both Imam and Temple matrix and Hamilton matrix converge to a stationary distribution, which is the Perron projection of the two matrices @@ -398,7 +451,7 @@ As we have seen, the largest eigenvalue for a primitive stochastic matrix is one This can be proven using [Gershgorin Circle Theorem](https://en.wikipedia.org/wiki/Gershgorin_circle_theorem), but it is out of the scope of this lecture. -So by the statement (6) of Perron-Frobenius Theorem, $\lambda_i<1$ for all $i Date: Thu, 29 Jun 2023 20:56:05 +1000 Subject: [PATCH 11/19] Updates --- lectures/eigen_I.md | 117 +++++++++++++++++++++++++++++++-- lectures/eigen_II.md | 150 ++++++------------------------------------- 2 files changed, 134 insertions(+), 133 deletions(-) diff --git a/lectures/eigen_I.md b/lectures/eigen_I.md index 924f59a2f..dfd74c820 100644 --- a/lectures/eigen_I.md +++ b/lectures/eigen_I.md @@ -35,7 +35,7 @@ At the same time, these concepts are extremely useful for * machine learning * and many other fields of science. -In this lecture we explain the basics of eigenvalues and eigenvectors. +In this lecture we explain the basics of eigenvalues and eigenvectors and introduce the Neumann Series Lemma. We assume in this lecture that students are familiar with matrices and understand {doc}`the basics of matrix algebra`. @@ -791,7 +791,6 @@ When solving $Av = \lambda v$, We will see some examples below. - ### Some mathematical details We note some mathematical details for more advanced readers. @@ -813,8 +812,6 @@ in $\lambda$ of degree $n$. This in turn implies the existence of $n$ solutions in the complex plane, although some might be repeated. - - ### Facts Some nice facts about the eigenvalues of a square matrix $A$ are as follows: @@ -857,6 +854,118 @@ The eigenvectors and eigenvalues of a map $A$ determine how a vector $v$ is tran This is discussed further later. + +(la_neumann)= +## The Neumann Series Lemma + +```{index} single: Neumann's Lemma +``` + +In this section we present a famous result about series of matrices that has +many applications in economics. + +### Scalar series + +Here's a fundamental result about series that you surely know: + +If $a$ is a number and $|a| < 1$, then + +```{math} +:label: gp_sum + + \sum_{k=0}^{\infty} a^k =\frac{1}{1-a} = (1 - a)^{-1} + +``` + +For a one-dimensional linear equation $x = ax + b$ where x is unknown we can thus conclude that the solution $x^{*}$ is given by: + +$$ + x^{*} = \frac{b}{1-a} = \sum_{k=0}^{\infty} a^k b +$$ + +### Matrix series + +A generalization of this idea exists in the matrix setting. + +Consider the system of equations $x = Ax + b$ where $A$ is an $n \times n$ +square matrix and $x$ and $b$ are both column vectors in $\mathbb{R}^n$. + +Using matrix algebra we can conclude that the solution to this system of equations will be given by: + +```{math} +:label: neumann_eqn + + x^{*} = (I-A)^{-1}b + +``` + +What guarantees the existence of a unique vector $x^{*}$ that satisfies +{eq}`neumann_eqn`? + +The following is a fundamental result in functional analysis that generalizes +{eq}`gp_sum` to a multivariate case. + +(neumann_series_lemma)= +```{prf:Theorem} Neumann Series Lemma +:label: neumann_series_lemma + +Let $A$ be a square matrix and let $A^k$ be the $k$-th power of $A$. + +Let $r(A)$ be the **spectral radius** of $A$, defined as $\max_i |\lambda_i|$, where + +* $\{\lambda_i\}_i$ is the set of eigenvalues of $A$ and +* $|\lambda_i|$ is the modulus of the complex number $\lambda_i$ + +Neumann's Theorem states the following: If $r(A) < 1$, then $I - A$ is invertible, and + +$$ +(I - A)^{-1} = \sum_{k=0}^{\infty} A^k +$$ +``` + +We can see the Neumann Series Lemma in action in the following example. + +```{code-cell} ipython3 +A = np.array([[0.4, 0.1], + [0.7, 0.2]]) + +evals, evecs = eig(A) # finding eigenvalues and eigenvectors + +r = max(abs(λ) for λ in evals) # compute spectral radius +print(r) +``` + +The spectral radius $r(A)$ obtained is less than 1. + +Thus, we can apply the Neumann Series Lemma to find $(I-A)^{-1}$. + +```{code-cell} ipython3 +I = np.identity(2) #2 x 2 identity matrix +B = I - A +``` + +```{code-cell} ipython3 +B_inverse = np.linalg.inv(B) #direct inverse method +``` + +```{code-cell} ipython3 +A_sum = np.zeros((2,2)) #power series sum of A +A_power = I +for i in range(50): + A_sum += A_power + A_power = A_power @ A +``` + +Let's check equality between the sum and the inverse methods. + +```{code-cell} ipython3 +np.allclose(A_sum, B_inverse) +``` + +Although we truncate the infinite sum at $k = 50$, both methods give us the same +result which illustrates the result of the Neumann Series Lemma. + + ## Exercises ```{exercise} diff --git a/lectures/eigen_II.md b/lectures/eigen_II.md index f61c9a25f..0078f5307 100644 --- a/lectures/eigen_II.md +++ b/lectures/eigen_II.md @@ -30,7 +30,7 @@ In addition to what's in Anaconda, this lecture will need the following librarie In this lecture we will begin with the foundational concepts in spectral theory. -Then we will explore the Perron-Frobenius Theorem and the Neumann Series Lemma, and connect them to applications in Markov chains and networks. +Then we will explore the Perron-Frobenius Theorem and connect it to applications in Markov chains and networks. We will use the following imports: @@ -65,7 +65,7 @@ Here we generalize this concept: Let $a^{k}_{ij}$ be element $(i,j)$ of $A^k$. -An $n \times n$ nonnegative matrix $A$ is called irreducible if $A + A^2 + A^3 + \cdots \gg 0$, where $\gg 0$ denotes every element in $A$ is nonnegative. +An $n \times n$ nonnegative matrix $A$ is called irreducible if $A + A^2 + A^3 + \cdots \gg 0$, where $\gg 0$ indicates that every element in $A$ is strictly positive. In other words, for each $i,j$ with $1 \leq i, j \leq n$, there exists a $k \geq 0$ such that $a^{k}_{ij} > 0$. @@ -89,7 +89,7 @@ B^2 = \begin{bmatrix} 1 & 0 \\ \end{bmatrix} $$ -$B$ is irreducible since $b_{12},b_{21} >0$ and $b^{2}_{11},b^{2}_{22} >0$. +$B$ is irreducible since $B + B^2$ is a matrix of ones. $$ C = \begin{bmatrix} 1 & 0 \\ @@ -97,24 +97,26 @@ C = \begin{bmatrix} 1 & 0 \\ \end{bmatrix} $$ -$C$ is reducible since $C^k = C$ for all $k \geq 0$ and thus +$C$ is not irreducible since $C^k = C$ for all $k \geq 0$ and thus $c^{k}_{12},c^{k}_{21} = 0$ for all $k \geq 0$. ### Left eigenvectors Recall that we previously discussed eigenvectors in {ref}`Eigenvalues and Eigenvectors `. -The eigenvalue $\lambda$ and its cooresponding eigenvecotr $v$ of matrix $A$ satisfy +In particular, $\lambda$ is an eigenvalue of $A$ and $v$ is an eigenvector of $A$ if $v$ is nonzero and satisfy $$ Av = \lambda v. $$ -In this section we will define $v$ as right eigenvectors since we will be introducing left eigenvectors now. +In this section we introduce left eigenvectors. + +To avoid confusion, what we previously referred to as "eigenvectors" will be called "right eigenvectors". Left eigenvectors will play important roles in what follows, including that of stochastic steady states for dynamic models under a Markov assumption. -A vector $w$ is called a left eigenvector of $A$ if $w$ is an eigenvector of $A^\top$. +A vector $w$ is called a left eigenvector of $A$ if $w$ is a right eigenvector of $A^\top$. In other words, if $w$ is a left eigenvector of matrix $A$, then $A^\top w = \lambda w$, where $\lambda$ is the eigenvalue associated with the left eigenvector $v$. @@ -124,12 +126,13 @@ This hints at how to compute left eigenvectors A = np.array([[3, 2], [1, 4]]) -# Compute right eigenvectors and eigenvalues +# Compute eigenvalues and right eigenvectors λ, v = eig(A) -# Compute left eigenvectors and eigenvalues +# Compute eigenvalues and left eigenvectors λ, w = eig(A.T) +# Keep 5 decimals np.set_printoptions(precision=5) print(f"The eigenvalues of A are:\n {λ}\n") @@ -137,7 +140,7 @@ print(f"The corresponding right eigenvectors are: \n {v[:,0]} and {-v[:,1]}\n") print(f"The corresponding left eigenvectors are: \n {w[:,0]} and {-w[:,1]}\n") ``` -We can use `scipy.linalg.eig` with argument `left=True` to find left eigenvectors directly +We can also use `scipy.linalg.eig` with argument `left=True` to find left eigenvectors directly ```{code-cell} ipython3 eigenvals, ε, e = sp.linalg.eig(A, left=True) @@ -147,9 +150,9 @@ print(f"The corresponding right eigenvectors are: \n {e[:,0]} and {-e[:,1]}\n") print(f"The corresponding left eigenvectors are: \n {ε[:,0]} and {-ε[:,1]}\n") ``` -We can find that the eigenvalues are the same while the eigenvectors themselves are different. +The eigenvalues are the same while the eigenvectors themselves are different. -(Also note that we are taking the nonnegative value of the eigenvector of {ref}`dominant eigenvalue `, this is because `eig` automatically normalize the eigenvectors.) +(Also note that we are taking the nonnegative value of the eigenvector of {ref}`dominant eigenvalue `, this is because `eig` automatically normalizes the eigenvectors.) We can then take transpose to obtain $A^\top w = \lambda w$ and obtain $w^\top A= \lambda w^\top$. @@ -206,7 +209,7 @@ We can compute the dominant eigenvalue and the corresponding eigenvector eig(A) ``` -Now we will can see the claims of the Perron-Frobenius Theorem holds for the irreducible matrix $A$: +Now we can see the claims of the Perron-Frobenius Theorem holds for the irreducible matrix $A$: 1. The dominant eigenvalue is real-valued and non-negative. 2. All other eigenvalues have absolute values less than or equal to the dominant eigenvalue. @@ -245,7 +248,7 @@ B^2 = \begin{bmatrix} 1 & 0 \\ \end{bmatrix} $$ -$B$ is irreducible but not premitive since there are always zeros in either principal diagonal or secondary diagonal. +$B$ is irreducible but not primitive since there are always zeros in either principal diagonal or secondary diagonal. We can see that if a matrix is primitive, then it implies the matrix is irreducible but not vice versa. @@ -279,7 +282,7 @@ We compute the dominant eigenvalue and the corresponding eigenvector eig(B) ``` -Now let's give some examples to see if the claims of the Perron-Frobenius Theorem holds for the primitive matrix $B$: +Now let's give some examples to see if the claims of the Perron-Frobenius Theorem hold for the primitive matrix $B$: 1. The dominant eigenvalue is real-valued and non-negative. 2. All other eigenvalues have absolute values strictly less than the dominant eigenvalue. @@ -377,7 +380,7 @@ The result shows that the matrix is not primitive as it is not everywhere positi These examples show how the Perron-Frobenius Theorem relates to the eigenvalues and eigenvectors of positive matrices and the convergence of the power of matrices. -In fact we have already seen the theorem in action before in {ref}`the markov chain lecture `. +In fact we have already seen the theorem in action before in {ref}`the Markov chain lecture `. (spec_markov)= #### Example 2: Connection to Markov chains @@ -386,7 +389,7 @@ We are now prepared to bridge the languages spoken in the two lectures. A primitive matrix is both irreducible and aperiodic. -So Perron-Frobenius Theorem explains why both Imam and Temple matrix and Hamilton matrix converge to a stationary distribution, which is the Perron projection of the two matrices +So Perron-Frobenius Theorem explains why both Imam and Temple matrix and [Hamilton matrix](https://en.wikipedia.org/wiki/Hamiltonian_matrix) converge to a stationary distribution, which is the Perron projection of the two matrices ```{code-cell} ipython3 P = np.array([[0.68, 0.12, 0.20], @@ -453,7 +456,6 @@ but it is out of the scope of this lecture. So by the statement (6) of Perron-Frobenius Theorem, $\lambda_i<1$ for all $i` to find the solution $x^{*}$ if it exists. ```{exercise-end} ``` From 1b227e5c155fe07495c57a86e8f1cce844d33e31 Mon Sep 17 00:00:00 2001 From: hengchengzhang Date: Thu, 29 Jun 2023 21:13:34 +1000 Subject: [PATCH 12/19] Updates --- lectures/eigen_II.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lectures/eigen_II.md b/lectures/eigen_II.md index 0078f5307..ead83b82c 100644 --- a/lectures/eigen_II.md +++ b/lectures/eigen_II.md @@ -28,8 +28,6 @@ In addition to what's in Anaconda, this lecture will need the following librarie !pip install quantecon ``` -In this lecture we will begin with the foundational concepts in spectral theory. - Then we will explore the Perron-Frobenius Theorem and connect it to applications in Markov chains and networks. We will use the following imports: @@ -389,7 +387,7 @@ We are now prepared to bridge the languages spoken in the two lectures. A primitive matrix is both irreducible and aperiodic. -So Perron-Frobenius Theorem explains why both Imam and Temple matrix and [Hamilton matrix](https://en.wikipedia.org/wiki/Hamiltonian_matrix) converge to a stationary distribution, which is the Perron projection of the two matrices +So Perron-Frobenius Theorem explains why both {ref}`Imam and Temple matrix ` and [Hamilton matrix](https://en.wikipedia.org/wiki/Hamiltonian_matrix) converge to a stationary distribution, which is the Perron projection of the two matrices ```{code-cell} ipython3 P = np.array([[0.68, 0.12, 0.20], From fe45c0f5466c082bd66d7297bf5041bc4ca15126 Mon Sep 17 00:00:00 2001 From: hengchengzhang Date: Thu, 29 Jun 2023 21:14:35 +1000 Subject: [PATCH 13/19] Updates --- lectures/eigen_II.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lectures/eigen_II.md b/lectures/eigen_II.md index ead83b82c..36d3ec835 100644 --- a/lectures/eigen_II.md +++ b/lectures/eigen_II.md @@ -28,6 +28,8 @@ In addition to what's in Anaconda, this lecture will need the following librarie !pip install quantecon ``` +In this lecture we will begin with the foundational concepts in spectral theory. + Then we will explore the Perron-Frobenius Theorem and connect it to applications in Markov chains and networks. We will use the following imports: From 0ea28adcb45c14224848f2778cbdb1db6836e77e Mon Sep 17 00:00:00 2001 From: thomassargent30 Date: Fri, 30 Jun 2023 11:11:41 -0600 Subject: [PATCH 14/19] Tom's June 30 edit of consum smoothing lecture --- lectures/cons_smooth.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lectures/cons_smooth.md b/lectures/cons_smooth.md index 085622daf..bc43a5d44 100644 --- a/lectures/cons_smooth.md +++ b/lectures/cons_smooth.md @@ -615,13 +615,15 @@ is the inverse of $A$ and check that $A A^{-1} = I$ ### Second order difference equation -The second-order linear difference equation for $\{y_t\}_{t=0}^T$ is +A second-order linear difference equation for $\{y_t\}_{t=0}^T$ is $$ y_{t} = \lambda_1 y_{t-1} + \lambda_2 y_{t-2}, \quad t = 1, 2, \ldots, T $$ -Similarly, we can cast this set of $T$ equations as a single matrix equation +where now $y_0$ and $y_{-1}$ are two given initial equations determined outside the model. + +As we did with the first-order difference equation, we can cast this set of $T$ equations as a single matrix equation $$ \begin{bmatrix} From 5e5f35698344bd04c83820886f3677433bdd56cc Mon Sep 17 00:00:00 2001 From: mmcky Date: Sat, 1 Jul 2023 17:25:27 +1000 Subject: [PATCH 15/19] MAINT: review workflows and actions (#251) * MAINT: review workflows and actions * Fix Syntax for PDF * Update cache and publish workflows * enable some mathjax macros * FIX: fail the cache on execution issue * FIX: heavy_tails --- .github/workflows/cache.yml | 15 +------ .github/workflows/ci.yml | 44 +++++++++--------- .github/workflows/publish.yml | 44 +++++++++--------- lectures/_config.yml | 5 +++ lectures/cagan_adaptive.md | 72 +++++++++-------------------- lectures/cagan_ree.md | 85 +++++++++++++---------------------- lectures/heavy_tails.md | 1 + lectures/networks.md | 74 +++++++++++++----------------- 8 files changed, 134 insertions(+), 206 deletions(-) diff --git a/.github/workflows/cache.yml b/.github/workflows/cache.yml index bd6f50e2d..384638b47 100644 --- a/.github/workflows/cache.yml +++ b/.github/workflows/cache.yml @@ -18,23 +18,10 @@ jobs: python-version: "3.10" environment-file: environment.yml activate-environment: quantecon - # - name: Install latex dependencies - # run: | - # sudo apt-get -qq update - # sudo apt-get install -y \ - # texlive-latex-recommended \ - # texlive-latex-extra \ - # texlive-fonts-recommended \ - # texlive-fonts-extra \ - # texlive-xetex \ - # latexmk \ - # xindy \ - # dvipng \ - # cm-super - name: Build HTML shell: bash -l {0} run: | - jb build lectures --path-output ./ + jb build lectures --path-output ./ -W --keep-going - name: Upload "_build" folder (cache) uses: actions/upload-artifact@v2 with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64d3a4f81..e46f62ddf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,22 +15,22 @@ jobs: python-version: "3.10" environment-file: environment.yml activate-environment: quantecon - # - name: Graphics Support - # run: | - # sudo apt-get -qq update && sudo apt-get install -y graphviz - # - name: Install latex dependencies - # run: | - # sudo apt-get -qq update - # sudo apt-get install -y \ - # texlive-latex-recommended \ - # texlive-latex-extra \ - # texlive-fonts-recommended \ - # texlive-fonts-extra \ - # texlive-xetex \ - # latexmk \ - # xindy \ - # dvipng \ - # cm-super + - name: Graphics Support #TODO: Review if graphviz is needed + run: | + sudo apt-get -qq update && sudo apt-get install -y graphviz + - name: Install latex dependencies + run: | + sudo apt-get -qq update + sudo apt-get install -y \ + texlive-latex-recommended \ + texlive-latex-extra \ + texlive-fonts-recommended \ + texlive-fonts-extra \ + texlive-xetex \ + latexmk \ + xindy \ + dvipng \ + cm-super - name: Display Conda Environment Versions shell: bash -l {0} run: conda list @@ -45,12 +45,12 @@ jobs: name: build-cache path: _build # Build Assets (Download Notebooks and PDF via LaTeX) - # - name: Build PDF from LaTeX - # shell: bash -l {0} - # run: | - # jb build lectures --builder pdflatex --path-output ./ -n --keep-going - # mkdir -p _build/html/_pdf - # cp -u _build/latex/*.pdf _build/html/_pdf + - name: Build PDF from LaTeX + shell: bash -l {0} + run: | + jb build lectures --builder pdflatex --path-output ./ -n --keep-going + mkdir -p _build/html/_pdf + cp -u _build/latex/*.pdf _build/html/_pdf - name: Build Download Notebooks (sphinx-tojupyter) shell: bash -l {0} run: | diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 6a01b0e6c..cd9343d0c 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -19,19 +19,19 @@ jobs: python-version: "3.10" environment-file: environment.yml activate-environment: quantecon - # - name: Install latex dependencies - # run: | - # sudo apt-get -qq update - # sudo apt-get install -y \ - # texlive-latex-recommended \ - # texlive-latex-extra \ - # texlive-fonts-recommended \ - # texlive-fonts-extra \ - # texlive-xetex \ - # latexmk \ - # xindy \ - # dvipng \ - # cm-super + - name: Install latex dependencies + run: | + sudo apt-get -qq update + sudo apt-get install -y \ + texlive-latex-recommended \ + texlive-latex-extra \ + texlive-fonts-recommended \ + texlive-fonts-extra \ + texlive-xetex \ + latexmk \ + xindy \ + dvipng \ + cm-super - name: Display Conda Environment Versions shell: bash -l {0} run: conda list @@ -46,15 +46,15 @@ jobs: name: build-cache path: _build # Build Assets (Download Notebooks and PDF via LaTeX) - # - name: Build PDF from LaTeX - # shell: bash -l {0} - # run: | - # jb build lectures --builder pdflatex --path-output ./ -n --keep-going - # - name: Copy LaTeX PDF for GH-PAGES - # shell: bash -l {0} - # run: | - # mkdir -p _build/html/_pdf - # cp -u _build/latex/*.pdf _build/html/_pdf + - name: Build PDF from LaTeX + shell: bash -l {0} + run: | + jb build lectures --builder pdflatex --path-output ./ -n --keep-going + - name: Copy LaTeX PDF for GH-PAGES + shell: bash -l {0} + run: | + mkdir -p _build/html/_pdf + cp -u _build/latex/*.pdf _build/html/_pdf - name: Build Download Notebooks (sphinx-tojupyter) shell: bash -l {0} run: | diff --git a/lectures/_config.yml b/lectures/_config.yml index 254479fba..ac3efae12 100644 --- a/lectures/_config.yml +++ b/lectures/_config.yml @@ -60,6 +60,11 @@ sphinx: binderhub_url : https://mybinder.org # The URL of the BinderHub (e.g., https://mybinder.org) colab_url : https://colab.research.google.com thebe : false # Add a thebe button to pages (requires the repository to run on Binder) + mathjax3_config: + tex: + macros: + "argmax" : "arg\\,max" + "argmin" : "arg\\,min" mathjax_path: https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js rediraffe_redirects: index_toc.md: intro.md diff --git a/lectures/cagan_adaptive.md b/lectures/cagan_adaptive.md index 05e68c782..512ff90ec 100644 --- a/lectures/cagan_adaptive.md +++ b/lectures/cagan_adaptive.md @@ -11,10 +11,6 @@ kernelspec: name: python3 --- -+++ {"user_expressions": []} - - - # A Fiscal Theory of Price Level with Adaptive Expectations ## Introduction @@ -27,29 +23,23 @@ from collections import namedtuple import matplotlib.pyplot as plt ``` -+++ {"user_expressions": []} - - - This lecture is a sequel or prequel to this lecture {doc}`fiscal theory of the price level `. We'll use linear algebra to do some experiments with an alternative "fiscal theory of the price level". Like the model in this lecture {doc}`fiscal theory of the price level `, the model asserts that when a government persistently spends more than it collects in taxes and prints money to finance the shortfall, it puts upward pressure on the price level and generates persistent inflation. +Instead of the "perfect foresight" or "rational expectations" version of the model in this lecture {doc}`fiscal theory of the price level `, our model in the present lecture is an "adaptive expectations" version of a model that Philip Cagan {cite}`Cagan` used to study the monetary dynamics of hyperinflations. +It combines these components: -Instead of the "perfect foresight" or "rational expectations" version of the model in this lecture {doc}`fiscal theory of the price level `, our model in the present lecture is an "adaptive expectations" version of a model that Philip Cagan {cite}`Cagan` used to study the monetary dynamics of hyperinflations. +* a demand function for real money balances that asserts that the logarithm of the quantity of real balances demanded depends inversely on the public's expected rate of inflation -It combines these components: +* an **adaptive expectations** model that describes how the public's anticipated rate of inflation responds to past values of actual inflation - * a demand function for real money balances that asserts that the logarithm of the quantity of real balances demanded depends inversely on the public's expected rate of inflation - - * an **adaptive expectations** model that describes how the public's anticipated rate of inflation responds to past values of actual inflation - - * an equilibrium condition that equates the demand for money to the supply - - * an exogenous sequence of rates of growth of the money supply +* an equilibrium condition that equates the demand for money to the supply + +* an exogenous sequence of rates of growth of the money supply Our model stays quite close to Cagan's original specification. @@ -62,13 +52,13 @@ the model. Let - * $ m_t $ be the log of the supply of nominal money balances; - * $\mu_t = m_{t+1} - m_t $ be the net rate of growth of nominal balances; - * $p_t $ be the log of the price level; - * $\pi_t = p_{t+1} - p_t $ be the net rate of inflation between $t$ and $ t+1$; - * $\pi_t^*$ be the public's expected rate of inflation between $t$ and $t+1$; - * $T$ the horizon -- i.e., the last period for which the model will determine $p_t$ - * $\pi_0^*$ public's initial expected rate of inflation between time $0$ and time $1$. +* $ m_t $ be the log of the supply of nominal money balances; +* $\mu_t = m_{t+1} - m_t $ be the net rate of growth of nominal balances; +* $p_t $ be the log of the price level; +* $\pi_t = p_{t+1} - p_t $ be the net rate of inflation between $t$ and $ t+1$; +* $\pi_t^*$ be the public's expected rate of inflation between $t$ and $t+1$; +* $T$ the horizon -- i.e., the last period for which the model will determine $p_t$ +* $\pi_0^*$ public's initial expected rate of inflation between time $0$ and time $1$. The demand for real balances $\exp\left(\frac{m_t^d}{p_t}\right)$ is governed by the following version of the Cagan demand function @@ -91,8 +81,6 @@ $$ (eq:eqfiscth1) Taking the difference between equation {eq}`eq:eqfiscth1` at time $t+1$ and at time $t$ gives - - $$ \pi_t = \mu_t + \alpha \pi_{t+1}^* - \alpha \pi_t^* $$ (eq:eqpipi) @@ -112,15 +100,10 @@ As endogenous outputs of our model we want to find sequences $\pi = \{\pi_t\}_{t We'll do some mental experiments by studying how the model outputs vary as we vary the model inputs. - - - ## Representing key equations with linear algebra We begin by writing the equation {eq}`eq:adaptexpn` adaptive expectations model for $\pi_t^*$ for $t=0, \ldots, T$ as - - $$ \begin{bmatrix} 1 & 0 & 0 & \cdots & 0 & 0 \cr -\lambda & 1 & 0 & \cdots & 0 & 0 \cr @@ -153,12 +136,11 @@ $$ (eq:eq1) where the $(T+2) \times (T+2) $matrix $A$, the $(T+2)\times (T+1)$ matrix $B$, and the vectors $\pi^* , \pi_0, \pi_0^*$ are defined implicitly by aligning these two equations. - - Next we write the key equation {eq}`eq:eqpipi` in matrix notation as -$$ \begin{bmatrix} +$$ +\begin{bmatrix} \pi_0 \cr \pi_1 \cr \pi_1 \cr \vdots \cr \pi_T \end{bmatrix} = \begin{bmatrix} \mu_0 \cr \mu_1 \cr \mu_2 \cr \vdots \cr \mu_T \end{bmatrix} @@ -185,21 +167,18 @@ $$ (eq:eq2) where the $(T+1) \times (T+2)$ matrix $C$ is defined implicitly to align this equation with the preceding equation system. - - ## Harvesting returns from our matrix formulation - We now have all of the ingredients we need to solve for $\pi$ as a function of $\mu, \pi_0, \pi_0^*$. Combine equations {eq}`eq:eq1`and {eq}`eq:eq2` to get $$ -\begin{align*} +\begin{aligned} A \pi^* & = (1-\lambda) B \pi + \pi_0^* \cr & = (1-\lambda) B \left[ \mu + C \pi^* \right] + \pi_0^* -\end{align*} +\end{aligned} $$ which implies that @@ -228,7 +207,6 @@ Knowing these, we can then quickly calculate the associated sequence $p$ of the from equation {eq}`eq:eqfiscth1`. Let's fill in the details for this step. - Since we now know $\mu$ it is easy to compute $m$. @@ -290,8 +268,6 @@ $$ which is just $\pi^*$ with the last element dropped. - - ## Forecast errors Our computations will verify that @@ -416,30 +392,25 @@ $$ (eq:suffcond) The source of this condition is the following string of deductions: $$ -\begin{align*} +\begin{aligned} \pi_{t}&=\mu_{t}+\alpha\pi_{t+1}^{*}-\alpha\pi_{t}^{*}\\\pi_{t+1}^{*}&=\lambda\pi_{t}^{*}+(1-\lambda)\pi_{t}\\\pi_{t}&=\frac{\mu_{t}}{1-\alpha(1-\lambda)}-\frac{\alpha(1-\lambda)}{1-\alpha(1-\lambda)}\pi_{t}^{*}\\\implies\pi_{t}^{*}&=\frac{1}{\alpha(1-\lambda)}\mu_{t}-\frac{1-\alpha(1-\lambda)}{\alpha(1-\lambda)}\pi_{t}\\\pi_{t+1}&=\frac{\mu_{t+1}}{1-\alpha(1-\lambda)}-\frac{\alpha(1-\lambda)}{1-\alpha(1-\lambda)}\left(\lambda\pi_{t}^{*}+(1-\lambda)\pi_{t}\right)\\&=\frac{\mu_{t+1}}{1-\alpha(1-\lambda)}-\frac{\lambda}{1-\alpha(1-\lambda)}\mu_{t}+\frac{\lambda-\alpha(1-\lambda)}{1-\alpha(1-\lambda)}\pi_{t} -\end{align*} +\end{aligned} $$ By assuring that the coefficient on $\pi_t$ is less than one in absolute value, condition {eq}`eq:suffcond` assures stability of the dynamics of $\{\pi_t\}$ described by the last line of our string of deductions. The reader is free to study outcomes in examples that violate condition {eq}`eq:suffcond`. - ```{code-cell} ipython3 print(np.abs((λ - α*(1-λ))/(1 - α*(1-λ)))) ``` -+++ {"user_expressions": []} ```{code-cell} ipython3 print(λ - α*(1-λ)) ``` -+++ {"user_expressions": []} Now we'll turn to some experiments. - - ### Experiment 1 We'll study a situation in which the rate of growth of the money supply is $\mu_0$ @@ -460,14 +431,12 @@ Notice that we studied exactly this experiment in a rational expectations vers So by comparing outcomes across the two lectures, we can learn about consequences of assuming adaptive expectations, as we do here, instead of rational expectations as we assumed in that other lecture. - ```{code-cell} ipython3 μ_seq_1 = np.append(μ0*np.ones(T1), μ_star*np.ones(T+1-T1)) # solve and plot π_seq_1, Eπ_seq_1, m_seq_1, p_seq_1 = solve_and_plot(md, μ_seq_1) ``` -+++ {"user_expressions": []} We invite the reader to compare outcomes with those under rational expectations studied in this lecture {doc}`fiscal theory of the price level `. @@ -494,4 +463,3 @@ The sluggish fall in inflation is explained by how anticipated inflation $\pi_t # solve and plot π_seq_2, Eπ_seq_2, m_seq_2, p_seq_2 = solve_and_plot(md, μ_seq_2) ``` -+++ {"user_expressions": []} \ No newline at end of file diff --git a/lectures/cagan_ree.md b/lectures/cagan_ree.md index edfc68ef1..981c40641 100644 --- a/lectures/cagan_ree.md +++ b/lectures/cagan_ree.md @@ -11,8 +11,6 @@ kernelspec: name: python3 --- -+++ {"user_expressions": []} - # A Fiscal Theory of the Price Level ## Introduction @@ -25,9 +23,6 @@ from collections import namedtuple import matplotlib.pyplot as plt ``` -+++ {"user_expressions": []} - - We'll use linear algebra first to explain and then do some experiments with a "fiscal theory of the price level". A fiscal theory of the price level was described by Thomas Sargent and Neil Wallace in chapter 5 of @@ -43,9 +38,9 @@ persistent inflation. The "fiscal theory of the price level" asserts that - * to **start** a persistent inflation the government simply persistently runs a money-financed government deficit - - * to **stop** a persistent inflation the government simply stops persistently running a money-financed government deficit +* to **start** a persistent inflation the government simply persistently runs a money-financed government deficit + +* to **stop** a persistent inflation the government simply stops persistently running a money-financed government deficit Our model is a "rational expectations" (or "perfect foresight") version of a model that Philip Cagan {cite}`Cagan` used to study the monetary dynamics of hyperinflations. @@ -65,23 +60,23 @@ As in the {doc}`present values ` and {doc}`consumption smoothing 0 ; \quad t = 0, 1, \ldots, T . $$ (eq:caganmd) - This equation asserts that the demand for real balances is inversely related to the public's expected rate of inflation. - People somehow acquire **perfect foresight** by their having solved a forecasting problem. @@ -103,9 +96,9 @@ $$ \pi_t^* = \pi_t , % \forall t $$ (eq:ree) -while equating demand for money to supply lets us set $m_t^d = m_t$ for all $t \geq 0$. +while equating demand for money to supply lets us set $m_t^d = m_t$ for all $t \geq 0$. -The preceding equations then imply +The preceding equations then imply $$ m_t - p_t = -\alpha(p_{t+1} - p_t) \: , \: \alpha > 0 @@ -121,17 +114,17 @@ $$ which we rewrite as a forward-looking first-order linear difference equation in $\pi_s$ with $\mu_s$ as a "forcing variable": -\begin{equation} +$$ \pi_t = \frac{\alpha}{1+\alpha} \pi_{t+1} + \frac{1}{1+\alpha} \mu_t , \quad t= 0, 1, \ldots , T -\end{equation} +$$ where $ 0< \frac{\alpha}{1+\alpha} <1 $. Setting $\delta =\frac{\alpha}{1+\alpha}$ let's us represent the preceding equation as -\begin{equation} +$$ \pi_t = \delta \pi_{t+1} + (1-\delta) \mu_t , \quad t =0, 1, \ldots, T -\end{equation} +$$ Write this system of $T+1$ equations as the single matrix equation @@ -240,8 +233,6 @@ def create_cagan_model(m0, α, T, μ_seq): return CaganREE(m0, T, μ_seq, α, δ, π_end) ``` -+++ {"user_expressions": []} - Here we use the following parameter values: ```{code-cell} ipython3 @@ -255,8 +246,6 @@ m0 = 1 μ_star = 0 ``` -+++ {"user_expressions": []} - Now we can solve the model to compute $\pi_t$, $m_t$ and $p_t$ for $t =1, \ldots, T+1$ using the matrix equation above ```{code-cell} ipython3 @@ -280,8 +269,6 @@ def solve(model): return π_seq, m_seq, p_seq ``` -+++ {"user_expressions": []} - ### Some quantitative experiments In the experiments below, we'll use formula {eq}`eq:piterm` as our terminal condition for expected inflation. @@ -387,7 +374,7 @@ $$ p_t = m_t + \alpha \pi_t $$ (eq:pformula2) -or, by using equation {eq}`eq:fisctheory1`, +or, by using equation {eq}`eq:fisctheory1`, $$ p_t = m_t + \alpha \left[ (1-\delta) \sum_{s=t}^T \delta^{s-t} \mu_s + \delta^{T+1-t} \pi_{T+1}^* \right] @@ -402,14 +389,12 @@ equation {eq}`eq:pformula2`, the log of real balances jumps But in order for $m_t - p_t$ to jump, which variable jumps, $m_{T_1}$ or $p_{T_1}$? - ### What jumps? What jumps at $T_1$? Is it $p_{T_1}$ or $m_{T_1}$? - If we insist that the money supply $m_{T_1}$ is locked at its value $m_{T_1}^1$ inherited from the past, then formula {eq}`eq:pformula2` implies that the price level jumps downward at time $T_1$, to coincide with the downward jump in $\pi_{T_1}$ @@ -417,7 +402,7 @@ An alternative assumption about the money supply level is that as part of the "i the government resets $m_{T_1}$ according to $$ - m_{T_1}^2 - m_{T_1}^1 = \alpha (\pi^1 - \pi^2) +m_{T_1}^2 - m_{T_1}^1 = \alpha (\pi^1 - \pi^2) $$ (eq:eqnmoneyjump) By letting money jump according to equation {eq}`eq:eqnmoneyjump` the monetary authority prevents the price level from **falling** at the moment that the unanticipated stabilization arrives. @@ -436,10 +421,11 @@ We'll study both cases. #### $m_{T_{1}}$ does not jump. $$ -\begin{align*} +\begin{aligned} m_{T_{1}}&=m_{T_{1}-1}+\mu_{0}\\\pi_{T_{1}}&=\mu^{*}\\p_{T_{1}}&=m_{T_{1}}+\alpha\pi_{T_{1}} -\end{align*} +\end{aligned} $$ + Simply glue the sequences $t\leq T_1$ and $t > T_1$. #### $m_{T_{1}}$ jumps. @@ -489,7 +475,6 @@ We set this up so that the $\{\mu_t\}$ sequences that describe the sudden stabil are identical to those for experiment 1, the foreseen sudden stabilization. The following code does the calculations and plots outcomes. - ```{code-cell} ipython3 # path 1 @@ -565,8 +550,6 @@ plt.tight_layout() plt.show() ``` -+++ {"user_expressions": []} - We invite you to compare these graphs with corresponding ones for the foreseen stabilization analyzed in experiment 1 above. Note how the inflation graph in the top middle panel is now identical to the @@ -575,15 +558,14 @@ money growth graph in the top left panel, and how now the log of real balances p The bottom panels plot $m$ and $p$ under two possible ways that $m_{T_1}$ might adjust as required by the upward jump in $m - p$ at $T_1$. - * the orange line lets $m_{T_1}$ jump upward in order to make sure that the log price level $p_{T_1}$ does not fall. - - * the blue line lets $p_{T_1}$ fall while stopping the money supply from jumping. +* the orange line lets $m_{T_1}$ jump upward in order to make sure that the log price level $p_{T_1}$ does not fall. + +* the blue line lets $p_{T_1}$ fall while stopping the money supply from jumping. Here is a way to interpret what the government is doing when the orange line policy is in place. The government prints money to finance expenditure with the "velocity dividend" that it reaps from the increased demand for real balances brought about by the permanent decrease in the rate of growth of the money supply. - The next code generates a multi-panel graph that includes outcomes of both experiments 1 and 2. That allows us to assess how important it is to understand whether the sudden permanent drop in $\mu_t$ at $t=T_1$ is fully unanticipated, as in experiment 1, or completely @@ -635,10 +617,6 @@ plt.tight_layout() plt.show() ``` -+++ {"user_expressions": []} - - - #### Experiment 3 **Foreseen gradual stabilization** @@ -652,7 +630,6 @@ $$ \mu_t = \phi^t \mu_0 + (1 - \phi^t) \mu^* . $$ - Next we perform an experiment in which there is a perfectly foreseen **gradual** decrease in the rate of growth of the money supply. The following code does the calculations and plots the results. diff --git a/lectures/heavy_tails.md b/lectures/heavy_tails.md index 114b4012f..3b156588e 100644 --- a/lectures/heavy_tails.md +++ b/lectures/heavy_tails.md @@ -757,6 +757,7 @@ df_gdp1 = extract_wb(varlist=variable_code, s="2021", e="2021", varnames=variable_names) +df_gdp1.dropna(inplace=True) ``` ```{code-cell} ipython3 diff --git a/lectures/networks.md b/lectures/networks.md index 46c6a3a71..b041a854e 100644 --- a/lectures/networks.md +++ b/lectures/networks.md @@ -528,18 +528,16 @@ convenient for numerical work, is via a matrix. The **adjacency matrix** of a weighted directed graph with nodes $\{v_1, \ldots, v_n\}$, edges $E$ and weight function $w$ is the matrix $$ -\begin{equation*} - A = (a_{ij})_{1 \leq i,j \leq n} - \quad \text{with} \quad - a_{ij} = - % - \begin{cases} - w(v_i, v_j) & \text{ if } (v_i, v_j) \in E - \\ - 0 & \text{ otherwise}. - \end{cases} - % -\end{equation*} +A = (a_{ij})_{1 \leq i,j \leq n} +\quad \text{with} \quad +a_{ij} = +% +\begin{cases} + w(v_i, v_j) & \text{ if } (v_i, v_j) \in E + \\ + 0 & \text{ otherwise}. +\end{cases} +% $$ Once the nodes in $V$ are enumerated, the weight function and @@ -679,11 +677,9 @@ The following result is useful in many applications: For distinct nodes $i, j$ in $V$ and any integer $k$, we have $$ -\begin{equation*} - a^k_{i j} > 0 - \quad \text{if and only if} \quad - \text{ $j$ is accessible from $i$}. -\end{equation*} +a^k_{i j} > 0 +\quad \text{if and only if} \quad +\text{ $j$ is accessible from $i$}. $$ ```` @@ -905,12 +901,11 @@ Let $r(A)$ denote the {ref}`spectral radius` of $A$. The **eigenvector centrality** of the graph is defined as the $n$-vector $e$ that solves -```{math} -:label: ev_central +$$ \begin{aligned} e = \frac{1}{r(A)} A e. \end{aligned} -``` +$$ (ev_central) In other words, $e$ is the dominant eigenvector of $A$ (the eigenvector of the largest eigenvalue --- see the discussion of the {ref}`Perron-Frobenius theorem` in the eigenvalue lecture. @@ -918,12 +913,11 @@ largest eigenvalue --- see the discussion of the {ref}`Perron-Frobenius theorem< To better understand {eq}`ev_central`, we write out the full expression for some element $e_i$ -```{math} -:label: eq_eicen +$$ \begin{aligned} e_i = \frac{1}{r(A)} \sum_{1 \leq j \leq n} a_{ij} e_j \end{aligned} -``` +$$ (eq_eicen) Note the recursive nature of the definition: the centrality obtained by node @@ -1027,21 +1021,19 @@ centrality for networks called Katz centrality. Fixing $\beta$ in $(0, 1/r(A))$, the **Katz centrality** of a weighted directed graph with adjacency matrix $A$ is defined as the vector $\kappa$ that solves - -```{math} -:label: katz_central - \kappa_i = \beta \sum_{1 \leq j 1} a_{ij} \kappa_j + 1 - \qquad \text{for all } i \in \{0, \ldots, n-1\}. -``` + +$$ +\kappa_i = \beta \sum_{1 \leq j 1} a_{ij} \kappa_j + 1 +\qquad \text{for all } i \in \{0, \ldots, n-1\}. +$$ (katz_central) Here $\beta$ is a parameter that we can choose. In vector form we can write -```{math} -:label: katz_central_vec - \kappa = \mathbf 1 + \beta A \kappa -``` +$$ +\kappa = \mathbf 1 + \beta A \kappa +$$ (katz_central_vec) where $\mathbf 1$ is a column vector of ones. @@ -1055,7 +1047,7 @@ because then $r(\beta A) < 1$. This means that {eq}`katz_central_vec` has the unique solution $$ - \kappa = (I - \beta A)^{-1} \mathbf{1} +\kappa = (I - \beta A)^{-1} \mathbf{1} $$ @@ -1097,10 +1089,9 @@ with high centrality.) For example, the **authority-based eigenvector centrality** of a weighted directed graph with adjacency matrix $A$ is the vector $e$ solving -```{math} -:label: eicena0 - e = \frac{1}{r(A)} A^\top e. -``` +$$ +e = \frac{1}{r(A)} A^\top e. +$$ (eicena0) The only difference from the original definition is that $A$ is replaced by its transpose. @@ -1109,10 +1100,9 @@ its transpose. Element-by-element, this is given by -```{math} -:label: eicena - e_j = \frac{1}{r(A)} \sum_{1 \leq i \leq n} a_{ij} e_i -``` +$$ +e_j = \frac{1}{r(A)} \sum_{1 \leq i \leq n} a_{ij} e_i +$$ (eicena) We see $e_j$ will be high if many nodes with high authority rankings link to $j$. From 6edd7367f5c090a9eb4649489adacb9ab690b0db Mon Sep 17 00:00:00 2001 From: hengchengzhang Date: Sun, 2 Jul 2023 10:14:17 +1000 Subject: [PATCH 16/19] Add ignored link --- lectures/_config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lectures/_config.yml b/lectures/_config.yml index ac3efae12..99c6c743c 100644 --- a/lectures/_config.yml +++ b/lectures/_config.yml @@ -37,6 +37,8 @@ latex: sphinx: extra_extensions: [sphinx_multitoc_numbering, sphinxext.rediraffe, sphinx_exercise, sphinx_togglebutton, sphinx_proof, sphinx_tojupyter] config: + # false-positive links + linkcheck_ignore: ['https://doi.org/https://doi.org/10.2307/1235116'] # myst-nb config nb_render_image_options: width: 80% From d8bb2164e9c6cf1b46c0b7a639574b0cdbc728dd Mon Sep 17 00:00:00 2001 From: hengchengzhang Date: Sun, 2 Jul 2023 10:14:23 +1000 Subject: [PATCH 17/19] Fix broken links --- lectures/about.md | 2 +- lectures/eigen_I.md | 2 +- lectures/markov_chains_II.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lectures/about.md b/lectures/about.md index 4e8facf9a..0b419cc51 100644 --- a/lectures/about.md +++ b/lectures/about.md @@ -60,7 +60,7 @@ In particular, we sincerely thank and give credit to - [Aakash Gupta](https://github.com/AakashGfude) - [Shu Hu](https://github.com/shlff) -- [Jiacheng Li](https://l10727@nyu.edu) +- Jiacheng Li - [Smit Lunagariya](https://github.com/Smit-create) - [Matthew McKay](https://github.com/mmcky) - [Maanasee Sharma](https://github.com/maanasee) diff --git a/lectures/eigen_I.md b/lectures/eigen_I.md index dfd74c820..334ba6aaa 100644 --- a/lectures/eigen_I.md +++ b/lectures/eigen_I.md @@ -1268,7 +1268,7 @@ The vector fields explain why we observed the trajectories of the vector $v$ mul The pattern demonstrated here is because we have complex eigenvalues and eigenvectors. -We can plot the complex plane for one of the matrices using `Arrow3D` class retrieved from [stackoverflow](https://stackoverflow.com/questions/22867620/putting-arrowheads-on-vectors-in-matplotlibs-3d-plot). +We can plot the complex plane for one of the matrices using `Arrow3D` class retrieved from [stackoverflow](https://stackoverflow.com/questions/22867620/putting-arrowheads-on-vectors-in-a-3d-plot). ```{code-cell} ipython3 --- diff --git a/lectures/markov_chains_II.md b/lectures/markov_chains_II.md index 9a48378d9..aeb58ca54 100644 --- a/lectures/markov_chains_II.md +++ b/lectures/markov_chains_II.md @@ -361,7 +361,7 @@ The diagram of the Markov chain shows that it is **irreducible** In fact it has a periodic cycle --- the state cycles between the two states in a regular way. -This is called [periodicity](https://stats.libretexts.org/Bookshelves/Probability_Theory/Probability_Mathematical_Statistics_and_Stochastic_Processes_(Siegrist)/16%3A_Markov_Processes/16.05%3A_Periodicity_of_Discrete-Time_Chains#:~:text=A%20state%20in%20a%20discrete,limiting%20behavior%20of%20the%20chain.). +This is called [periodicity](https://stats.libretexts.org/Bookshelves/Probability_Theory/Probability_Mathematical_Statistics_and_Stochastic_Processes_(Siegrist)/16%3A_Markov_Processes/16.05%3A_Periodicity_of_Discrete-Time_Chains). It is still irreducible so ergodicity holds. From 78d992c9d35b2f7b43f33b54b9758de6b0d80c47 Mon Sep 17 00:00:00 2001 From: mmcky Date: Sun, 2 Jul 2023 16:50:15 +1000 Subject: [PATCH 18/19] update reference to QuantEcon.py --- lectures/markov_chains_I.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lectures/markov_chains_I.md b/lectures/markov_chains_I.md index 42fc028c0..715b6d5c3 100644 --- a/lectures/markov_chains_I.md +++ b/lectures/markov_chains_I.md @@ -462,7 +462,7 @@ always close to 0.25 (for the `P` matrix above). ### Using QuantEcon's routines -QuantEcon.py has routines for handling Markov chains, including simulation. +The [quantecon package](https://github.com/quantecon/QuantEcon.py) has routines for handling Markov chains, including simulation. Here's an illustration using the same $P$ as the preceding example From ab0977f35876cf49da8af803f5879ea0390ab0f7 Mon Sep 17 00:00:00 2001 From: mmcky Date: Sun, 2 Jul 2023 17:37:24 +1000 Subject: [PATCH 19/19] fix all instances --- lectures/markov_chains_I.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lectures/markov_chains_I.md b/lectures/markov_chains_I.md index 126a4cd51..402859103 100644 --- a/lectures/markov_chains_I.md +++ b/lectures/markov_chains_I.md @@ -462,7 +462,7 @@ always close to 0.25 (for the `P` matrix above). ### Using QuantEcon's routines -The [quantecon package](https://github.com/quantecon/QuantEcon.py) has routines for handling Markov chains, including simulation. +[QuantEcon.py](http://quantecon.org/quantecon-py) has routines for handling Markov chains, including simulation. Here's an illustration using the same $P$ as the preceding example @@ -749,7 +749,7 @@ Not surprisingly it tends to zero as $\beta \to 0$, and to one as $\alpha \to 0$ ### Calculating stationary distributions -A stable algorithm for computing stationary distributions is implemented in QuantEcon.py. +A stable algorithm for computing stationary distributions is implemented in [QuantEcon.py](http://quantecon.org/quantecon-py). Here's an example