From 03196de9dfaa129607f67e53503d769ad6142828 Mon Sep 17 00:00:00 2001 From: kp992 <145801876+kp992@users.noreply.github.com> Date: Mon, 29 Apr 2024 12:52:06 +0530 Subject: [PATCH] Use np.interp instead of interpolation.interp (#156) * Use np.interp instead of interpolation.interp * apply suggestions * re-enable build failures on warnings * MAINT: update ci.yml workflow versions and report upload * Fix interp issues --------- Co-authored-by: mmcky --- .github/workflows/ci.yml | 18 ++++--- lectures/BCG_complete_mkts.md | 1 - lectures/BCG_incomplete_mkts.md | 49 +++++++++---------- .../opt_tax_recur/recursive_allocation.py | 12 ++--- lectures/coase.md | 42 +++++++--------- lectures/lucas_model.md | 33 +++++-------- lectures/opt_tax_recur.md | 2 - 7 files changed, 72 insertions(+), 85 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7934f3a5..f072929a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,9 +5,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Setup Anaconda - uses: conda-incubator/setup-miniconda@v2 + uses: conda-incubator/setup-miniconda@v3 with: auto-update-conda: true auto-activate-base: true @@ -35,7 +35,7 @@ jobs: shell: bash -l {0} run: pip list - name: Download "build" folder (cache) - uses: dawidd6/action-download-artifact@v2 + uses: dawidd6/action-download-artifact@v3 with: workflow: cache.yml branch: main @@ -61,14 +61,20 @@ jobs: shell: bash -l {0} run: | rm -r _build/.doctrees - jb build lectures --path-output ./ + jb build lectures --path-output ./ -nW --keep-going + - name: Upload Execution Reports (Download Notebooks) + uses: actions/upload-artifact@v4 + if: failure() + with: + name: execution-reports + path: _build/jupyter/reports - name: Save Build as Artifact - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: _build path: _build - name: Preview Deploy to Netlify - uses: nwtgck/actions-netlify@v1.1 + uses: nwtgck/actions-netlify@v2 with: publish-dir: '_build/html/' production-branch: master diff --git a/lectures/BCG_complete_mkts.md b/lectures/BCG_complete_mkts.md index 0e77e277..dac8dea0 100644 --- a/lectures/BCG_complete_mkts.md +++ b/lectures/BCG_complete_mkts.md @@ -31,7 +31,6 @@ In addition to what's in Anaconda, this lecture will need the following librarie tags: [hide-output] --- !pip install --upgrade quantecon -!pip install interpolation !conda install -y -c plotly plotly plotly-orca ``` diff --git a/lectures/BCG_incomplete_mkts.md b/lectures/BCG_incomplete_mkts.md index 78cb5578..91df9591 100644 --- a/lectures/BCG_incomplete_mkts.md +++ b/lectures/BCG_incomplete_mkts.md @@ -3,8 +3,10 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.1 kernelspec: - display_name: Python 3 + display_name: Python 3 (ipykernel) language: python name: python3 --- @@ -26,12 +28,10 @@ kernelspec: In addition to what's in Anaconda, this lecture will need the following libraries: -```{code-cell} ipython ---- -tags: [hide-output] ---- +```{code-cell} ipython3 +:tags: [hide-output] + !pip install --upgrade quantecon -!pip install interpolation !conda install -y -c plotly plotly plotly-orca ``` @@ -703,15 +703,14 @@ Parameters include: - $\beta$: Discount factor. Default value is 0.96. - bound: Bound for truncated normal distribution. Default value is 3. -```{code-cell} ipython +```{code-cell} ipython3 import numpy as np from scipy.stats import truncnorm from scipy.integrate import quad from numba import njit -from interpolation import interp ``` -```{code-cell} python3 +```{code-cell} ipython3 class BCG_incomplete_markets: # init method or constructor @@ -784,7 +783,7 @@ class BCG_incomplete_markets: rv = truncnorm(ta, tb, loc=πœ‡, scale=𝜎) πœ–_range = np.linspace(ta, tb, 1000000) pdf_range = rv.pdf(πœ–_range) - self.g = njit(lambda πœ–: interp(πœ–_range, pdf_range, πœ–)) + self.g = njit(lambda πœ–: np.interp(πœ–, πœ–_range, pdf_range)) #************************************************************* @@ -1206,14 +1205,14 @@ Below we show some examples computed with the class `BCG_incomplete markets`. In the first example, we set up an instance of the BCG incomplete markets model with default parameter values. -```{code-cell} python3 -:tags: ["hide-output"] +```{code-cell} ipython3 +:tags: [hide-output] mdl = BCG_incomplete_markets() kss,bss,Vss,qss,pss,c10ss,c11ss,c20ss,c21ss,πœƒ1ss = mdl.solve_eq(print_crit=False) ``` -```{code-cell} python3 +```{code-cell} ipython3 print(-kss+qss+pss*bss) print(Vss) print(πœƒ1ss) @@ -1229,7 +1228,7 @@ Thus, let’s see if the firm is actually maximizing its firm value given the equilibrium pricing function $q(k,b)$ for equity and $p(k,b)$ for bonds. -```{code-cell} python3 +```{code-cell} ipython3 kgrid, bgrid, Vgrid, Qgrid, Pgrid = mdl.eq_valuation(c10ss, c11ss, c20ss, c21ss,N=30) print('Maximum valuation of the firm value in the (k,B) grid: {:.5f}'.format(Vgrid.max())) @@ -1246,7 +1245,7 @@ Below we will plot the firm’s value as a function of $k,b$. We’ll also plot the equilibrium price functions $q(k,b)$ and $p(k,b)$. -```{code-cell} python3 +```{code-cell} ipython3 from IPython.display import Image import matplotlib.pyplot as plt from mpl_toolkits import mplot3d @@ -1367,7 +1366,7 @@ $$ The function also outputs agent 1’s bond holdings $\xi_1$. -```{code-cell} python3 +```{code-cell} ipython3 def off_eq_check(mdl,kss,bss,e=0.1): # Big K and big B k = kss @@ -1603,7 +1602,7 @@ structure for the firm. We first check the case in which $b^{**} = b^* - e$ where $e = 0.1$: -```{code-cell} python3 +```{code-cell} ipython3 #====================== Experiment 1 ======================# Ve1,ke1,be1,pe1,qe1,c10e1,c11e1,c20e1,c21e1,πœ‰1e1 = off_eq_check(mdl, kss, @@ -1655,7 +1654,7 @@ Therefore, $(k^*,b^{*}-e)$ would not be an equilibrium. Next, we check for $b^{**} = b^* + e$. -```{code-cell} python3 +```{code-cell} ipython3 #====================== Experiment 2 ======================# Ve2,ke2,be2,pe2,qe2,c10e2,c11e2,c20e2,c21e2,πœ‰1e2 = off_eq_check(mdl, kss, @@ -1708,7 +1707,7 @@ want to hold corporate debt. For example, $\xi^1 > 0$: -```{code-cell} python3 +```{code-cell} ipython3 print('Bond holdings of agent 1: {:.3f}'.format(πœ‰1e2)) ``` @@ -1726,7 +1725,7 @@ It is also interesting to look at the equilibrium price functions $q(k,b)$ and $p(k,b)$ faced by firms in our rational expectations equilibrium. -```{code-cell} python3 +```{code-cell} ipython3 # Equity Valuation fig = go.Figure(data=[go.Scatter3d(x=[kss], y=[bss], @@ -1756,7 +1755,7 @@ Image(fig.to_image(format="png")) # code locally ``` -```{code-cell} python3 +```{code-cell} ipython3 # Bond Valuation fig = go.Figure(data=[go.Scatter3d(x=[kss], y=[bss], @@ -1815,8 +1814,8 @@ $$ The function `valuations_by_agent` is used in calculating these valuations. -```{code-cell} python3 -:tags: ["hide-output"] +```{code-cell} ipython3 +:tags: [hide-output] # Lists for storage wlist = [] @@ -1864,7 +1863,7 @@ for i in range(10): p2list.append(P2) ``` -```{code-cell} python3 +```{code-cell} ipython3 # Plot fig, ax = plt.subplots(3,2,figsize=(12,12)) ax[0,0].plot(wlist,klist) @@ -1909,7 +1908,7 @@ Now let’s see how the two types of agents value bonds and equities, keeping in mind that the type that values the asset highest determines the equilibrium price (and thus the pertinent set of Big $C$’s). -```{code-cell} python3 +```{code-cell} ipython3 # Comparing the prices fig, ax = plt.subplots(1,3,figsize=(16,6)) diff --git a/lectures/_static/lecture_specific/opt_tax_recur/recursive_allocation.py b/lectures/_static/lecture_specific/opt_tax_recur/recursive_allocation.py index 2ce9387e..c197f11c 100644 --- a/lectures/_static/lecture_specific/opt_tax_recur/recursive_allocation.py +++ b/lectures/_static/lecture_specific/opt_tax_recur/recursive_allocation.py @@ -131,8 +131,8 @@ def simulate(self, b0, s0, T, sHist=None): # Time 1 onward for t in range(1, T): s, x = sHist[t], xHist[t-1] - cHist[t] = interp(self.x_grid, self.c1[:, s], x) - nHist[t] = interp(self.x_grid, self.n1[:, s], x) + cHist[t] = np.interp(x, self.x_grid, self.c1[:, s]) + nHist[t] = np.interp(x, self.x_grid, self.n1[:, s]) Ο„Hist[t] = self.Ο„(cHist[t], nHist[t]) @@ -140,8 +140,8 @@ def simulate(self, b0, s0, T, sHist=None): c, n = np.empty((2, self.S)) for sprime in range(self.S): - c[sprime] = interp(x_grid, self.c1[:, sprime], x) - n[sprime] = interp(x_grid, self.n1[:, sprime], x) + c[sprime] = np.interp(x, x_grid, self.c1[:, sprime]) + n[sprime] = np.interp(x, x_grid, self.n1[:, sprime]) Euc = Ο€[sHist[t-1]] @ Uc(c, 1-n) RHist[t-1] = Uc(cHist[t-1], 1-nHist[t-1]) / (self.pref.Ξ² * Euc) @@ -150,7 +150,7 @@ def simulate(self, b0, s0, T, sHist=None): if t < T-1: sprime = sHist[t+1] - xHist[t] = interp(self.x_grid, self.xprime1[:, s, sprime], x) + xHist[t] = np.interp(x, self.x_grid, self.xprime1[:, s, sprime]) return [cHist, nHist, Bhist, Ο„Hist, gHist, yHist, xHist, RHist] @@ -209,7 +209,7 @@ def obj_V(z_sub, x, s, V, pref, Ο€, g, x_grid, b0=None): # prepare Vprime vector Vprime = np.empty(S) for sprime in range(S): - Vprime[sprime] = interp(x_grid, V[:, sprime], xprime[sprime]) + Vprime[sprime] = np.interp(xprime[sprime], x_grid, V[:, sprime]) # compute the objective value obj = U(c, l) + Ξ² * Ο€[s] @ Vprime diff --git a/lectures/coase.md b/lectures/coase.md index 41fe1c99..b34cec1a 100644 --- a/lectures/coase.md +++ b/lectures/coase.md @@ -3,8 +3,10 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.1 kernelspec: - display_name: Python 3 + display_name: Python 3 (ipykernel) language: python name: python3 --- @@ -24,15 +26,6 @@ kernelspec: :depth: 2 ``` -In addition to what's in Anaconda, this lecture will need the following libraries: - -```{code-cell} ipython ---- -tags: [hide-output] ---- -!pip install interpolation -``` - ## Overview In 1937, Ronald Coase wrote a brilliant essay on the nature of the firm {cite}`coase1937nature`. @@ -57,12 +50,10 @@ Couldn't the associated within-firm planning be done more efficiently by the mar We'll use the following imports: -```{code-cell} ipython +```{code-cell} ipython3 import numpy as np import matplotlib.pyplot as plt -%matplotlib inline from scipy.optimize import fminbound -from interpolation import interp ``` ### Why Firms Exist @@ -447,7 +438,7 @@ At each iterate, we will use continuous piecewise linear interpolation of functi To begin, here's a class to store primitives and a grid: -```{code-cell} python3 +```{code-cell} ipython3 class ProductionChain: def __init__(self, @@ -464,7 +455,7 @@ Now let's implement and iterate with $T$ until convergence. Recalling that our initial condition must lie in $\mathcal P$, we set $p_0 = c$ -```{code-cell} python3 +```{code-cell} ipython3 def compute_prices(pc, tol=1e-5, max_iter=5000): """ Compute prices by iterating with T @@ -481,7 +472,7 @@ def compute_prices(pc, tol=1e-5, max_iter=5000): while error > tol and i < max_iter: for j, s in enumerate(grid): - Tp = lambda t: delta * interp(grid, p, t) + c(s - t) + Tp = lambda t: delta * np.interp(t, grid, p) + c(s - t) new_p[j] = Tp(fminbound(Tp, 0, s)) error = np.max(np.abs(p - new_p)) p = new_p @@ -492,14 +483,14 @@ def compute_prices(pc, tol=1e-5, max_iter=5000): else: print(f"Warning: iteration hit upper bound {max_iter}") - p_func = lambda x: interp(grid, p, x) + p_func = lambda x: np.interp(x, grid, p) return p_func ``` The next function computes optimal choice of upstream boundary and range of task implemented for a firm face price function p_function and with downstream boundary $s$. -```{code-cell} python3 +```{code-cell} ipython3 def optimal_choices(pc, p_function, s): """ Takes p_func as the true function, minimizes on [0,s] @@ -524,7 +515,7 @@ their respective upstream boundary, treating the previous firm's upstream bounda In doing so, we start with firm 1, who has downstream boundary $s=1$. -```{code-cell} python3 +```{code-cell} ipython3 def compute_stages(pc, p_function): s = 1.0 transaction_stages = [s] @@ -539,7 +530,7 @@ Let's try this at the default parameters. The next figure shows the equilibrium price function, as well as the boundaries of firms as vertical lines -```{code-cell} python3 +```{code-cell} ipython3 pc = ProductionChain() p_star = compute_prices(pc) @@ -558,7 +549,7 @@ plt.show() Here's the function $\ell^*$, which shows how large a firm with downstream boundary $s$ chooses to be -```{code-cell} python3 +```{code-cell} ipython3 ell_star = np.empty(pc.n) for i, s in enumerate(pc.grid): t, e = optimal_choices(pc, p_star, s) @@ -590,9 +581,9 @@ Check your intuition by computing the number of firms at delta in (1.01, 1.05, 1 ```{solution-start} coa_ex1 :class: dropdown ``` -Here is one solution +Here is one solution -```{code-cell} python3 +```{code-cell} ipython3 for delta in (1.01, 1.05, 1.1): pc = ProductionChain(delta=delta) @@ -601,6 +592,7 @@ for delta in (1.01, 1.05, 1.1): num_firms = len(transaction_stages) print(f"When delta={delta} there are {num_firms} firms") ``` + ```{solution-end} ``` @@ -636,7 +628,7 @@ associated with diminishing returns to management --- which induce convexity --- Here's one way to compute and graph value added across firms -```{code-cell} python3 +```{code-cell} ipython3 pc = ProductionChain() p_star = compute_prices(pc) stages = compute_stages(pc, p_star) @@ -654,4 +646,4 @@ plt.show() ``` ```{solution-end} -``` \ No newline at end of file +``` diff --git a/lectures/lucas_model.md b/lectures/lucas_model.md index cc931e81..69900538 100644 --- a/lectures/lucas_model.md +++ b/lectures/lucas_model.md @@ -3,8 +3,10 @@ jupytext: text_representation: extension: .md format_name: myst + format_version: 0.13 + jupytext_version: 1.16.1 kernelspec: - display_name: Python 3 + display_name: Python 3 (ipykernel) language: python name: python3 --- @@ -27,15 +29,6 @@ kernelspec: :depth: 2 ``` -In addition to what's in Anaconda, this lecture will need the following libraries: - -```{code-cell} ipython ---- -tags: [hide-output] ---- -!pip install interpolation -``` - ## Overview As stated in an [earlier lecture](https://python-intro.quantecon.org/markov_asset.html), an asset is a claim on a stream of prospective payments. @@ -52,13 +45,11 @@ Another difference to our [first asset pricing lecture](https://python-intro.qua Let's start with some imports: -```{code-cell} ipython +```{code-cell} ipython3 import numpy as np -from interpolation import interp from numba import njit, prange from scipy.stats import lognorm import matplotlib.pyplot as plt -%matplotlib inline ``` ## The Lucas Model @@ -401,7 +392,7 @@ Utility will take the isoelastic form $u(c) = c^{1-\gamma}/(1-\gamma)$, where $\ We will set up a `LucasTree` class to hold parameters of the model -```{code-cell} python3 +```{code-cell} ipython3 class LucasTree: """ Class to store parameters of the Lucas tree model. @@ -436,7 +427,7 @@ class LucasTree: The following function takes an instance of the `LucasTree` and generates a jitted version of the Lucas operator -```{code-cell} python3 +```{code-cell} ipython3 def operator_factory(tree, parallel_flag=True): """ @@ -458,7 +449,7 @@ def operator_factory(tree, parallel_flag=True): """ # Turn f into a function - Af = lambda x: interp(grid, f, x) + Af = lambda x: np.interp(x, grid, f) Tf = np.empty_like(f) # Apply the T operator to f using Monte Carlo integration @@ -474,7 +465,7 @@ def operator_factory(tree, parallel_flag=True): To solve the model, we write a function that iterates using the Lucas operator to find the fixed point. -```{code-cell} python3 +```{code-cell} ipython3 def solve_model(tree, tol=1e-6, max_iter=500): """ Compute the equilibrium price function associated with Lucas @@ -505,7 +496,7 @@ def solve_model(tree, tol=1e-6, max_iter=500): Solving the model and plotting the resulting price function -```{code-cell} python3 +```{code-cell} ipython3 tree = LucasTree() price_vals = solve_model(tree) @@ -552,7 +543,8 @@ Replicate {ref}`the figure ` to show how discount factors affect pri ```{solution-start} lucas_ex1 :class: dropdown ``` -```{code-cell} python3 + +```{code-cell} ipython3 fig, ax = plt.subplots(figsize=(10, 6)) for Ξ² in (.95, 0.98): @@ -566,5 +558,6 @@ ax.legend(loc='upper left') ax.set(xlabel='$y$', ylabel='price', xlim=(min(grid), max(grid))) plt.show() ``` + ```{solution-end} -``` \ No newline at end of file +``` diff --git a/lectures/opt_tax_recur.md b/lectures/opt_tax_recur.md index 8c8815ec..929f48fc 100644 --- a/lectures/opt_tax_recur.md +++ b/lectures/opt_tax_recur.md @@ -31,7 +31,6 @@ In addition to what's in Anaconda, this lecture will need the following librarie tags: [hide-output] --- !pip install --upgrade quantecon -!pip install interpolation ``` ## Overview @@ -73,7 +72,6 @@ import matplotlib.pyplot as plt from scipy.optimize import root from quantecon import MarkovChain from quantecon.optimize.nelder_mead import nelder_mead -from interpolation import interp from numba import njit, prange, float64 from numba.experimental import jitclass ```