From 0dbf48d8faca768798e7d8604700ecc6d1fb42df Mon Sep 17 00:00:00 2001 From: annabellasd Date: Mon, 25 Sep 2023 20:20:43 -0800 Subject: [PATCH 01/26] updated lectures --- lectures/continuous_time/covid_sde.md | 121 +++++++++++++------------ lectures/continuous_time/seir_model.md | 81 +++++++++-------- 2 files changed, 103 insertions(+), 99 deletions(-) diff --git a/lectures/continuous_time/covid_sde.md b/lectures/continuous_time/covid_sde.md index c0576465..b13b6b85 100644 --- a/lectures/continuous_time/covid_sde.md +++ b/lectures/continuous_time/covid_sde.md @@ -230,40 +230,41 @@ First, construct our $F$ from {eq}`dfcvsde` and $G$ from {eq}`dG` ```{code-cell} julia function F(x, p, t) - s, i, r, d, R₀, δ = x - (;γ, R̄₀, η, σ, ξ, θ, δ_bar) = p - - return [-γ*R₀*s*i; # ds/dt - γ*R₀*s*i - γ*i; # di/dt - (1-δ)*γ*i; # dr/dt - δ*γ*i; # dd/dt - η*(R̄₀(t, p) - R₀);# dR₀/dt - θ*(δ_bar - δ); # dδ/dt - ] + s, i, r, d, R_0, delta = x + (; gamma, R_bar_0, eta, sigma, xi, theta, delta_bar) = p + + return [-gamma * R_0 * s * i; # ds/dt + gamma * R_0 * s * i - gamma * i; # di/dt + (1 - delta) * gamma * i; # dr/dt + delta * gamma * i; # dd/dt + eta * (R_bar_0(t, p) - R_0); # dR_0/dt + theta * (delta_bar - delta); # ddelta/dt + ] end function G(x, p, t) - s, i, r, d, R₀, δ = x - (;γ, R̄₀, η, σ, ξ, θ, δ_bar) = p + s, i, r, d, R_0, delta = x + (; gamma, R_bar_0, eta, sigma, xi, theta, delta_bar) = p - return [0; 0; 0; 0; σ*sqrt(R₀); ξ*sqrt(δ * (1-δ))] + return [0; 0; 0; 0; sigma * sqrt(R_0); xi * sqrt(delta * (1 - delta))] end ``` Next create a settings generator, and then define a [SDEProblem](https://docs.sciml.ai/stable/tutorials/sde_example/#Example-2:-Systems-of-SDEs-with-Diagonal-Noise-1) with Diagonal Noise. ```{code-cell} julia -p_gen = @with_kw (T = 550.0, γ = 1.0 / 18, η = 1.0 / 20, - R₀_n = 1.6, R̄₀ = (t, p) -> p.R₀_n, δ_bar = 0.01, - σ = 0.03, ξ = 0.004, θ = 0.2, N = 3.3E8) -p = p_gen() # use all defaults +p_gen(; T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, + R_0_n = 1.6, R_bar_0 = (t, p) -> p.R_0_n, delta_bar = 0.01, + sigma = 0.03, xi = 0.004, theta = 0.2, N = 3.3E8) = (; T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N) + +p = p_gen() # use all defaults i_0 = 25000 / p.N r_0 = 0.0 d_0 = 0.0 s_0 = 1.0 - i_0 - r_0 - d_0 -R̄₀_0 = 0.5 # starting in lockdown -δ_0 = p.δ_bar -x_0 = [s_0, i_0, r_0, d_0, R̄₀_0, δ_0] +R_bar_0_0 = 0.5 # starting in lockdown +delta_0 = p.delta_bar +x_0 = [s_0, i_0, r_0, d_0, R_bar_0_0, delta_0] prob = SDEProblem(F, G, x_0, (0, p.T), p) ``` @@ -370,29 +371,29 @@ We will shut down the shocks to the mortality rate (i.e. $\xi = 0$) to focus on Consider $\eta = 1/50$ and $\eta = 1/20$, where we start at the same initial condition of $R_0(0) = 0.5$. ```{code-cell} julia -function generate_η_experiment(η; p_gen = p_gen, trajectories = 100, - saveat = 1.0, x_0 = x_0, T = 120.0) - p = p_gen(η = η, ξ = 0.0) +function generate_eta_experiment(eta; p_gen, trajectories = 100, saveat = 1.0, x_0, T = 120.0) + p = p_gen(eta = eta, xi = 0.0) ensembleprob = EnsembleProblem(SDEProblem(F, G, x_0, (0, T), p)) - sol = solve(ensembleprob, SOSRI(), EnsembleThreads(), - trajectories = trajectories, saveat = saveat) + sol = solve(ensembleprob, SOSRI(), EnsembleThreads(), trajectories = trajectories, saveat = saveat) return EnsembleSummary(sol) end # Evaluate two different lockdown scenarios -η_1 = 1/50 -η_2 = 1/20 -summ_1 = generate_η_experiment(η_1) -summ_2 = generate_η_experiment(η_2) -plot(summ_1, idxs = (4,5), +eta_1 = 1 / 50 +eta_2 = 1 / 20 +summ_1 = generate_eta_experiment(eta_1) +summ_2 = generate_eta_experiment(eta_2) + +plot(summ_1, idxs = (4, 5), title = ["Proportion Dead" L"R_0"], ylabel = [L"d(t)" L"R_0(t)"], xlabel = L"t", legend = [:topleft :bottomright], - labels = L"Middle 95% Quantile, $\eta = %$η_1$", + labels = L"Middle 95% Quantile, $\eta = %$eta_1$", layout = (2, 1), size = (900, 900), fillalpha = 0.5) -plot!(summ_2, idxs = (4,5), + +plot!(summ_2, idxs = (4, 5), legend = [:topleft :bottomright], - labels = L"Middle 95% Quantile, $\eta = %$η_2$", size = (900, 900), fillalpha = 0.5) + labels = L"Middle 95% Quantile, $\eta = %$eta_2$", size = (900, 900), fillalpha = 0.5) ``` While the the mean of the $d(t)$ increases, unsurprisingly, we see that the 95% quantile for later time periods is also much larger - even after the $R_0$ has converged. @@ -411,24 +412,24 @@ Since empirical estimates of $R_0(t)$ discussed in {cite}`NBERw27128` and other We start the model with 100,000 active infections. ```{code-cell} julia -R₀_L = 0.5 # lockdown -η_experiment = 1.0/10 -σ_experiment = 0.04 -R̄₀_lift_early(t, p) = t < 30.0 ? R₀_L : 2.0 -R̄₀_lift_late(t, p) = t < 120.0 ? R₀_L : 2.0 +R_0_L = 0.5 # lockdown +eta_experiment = 1.0 / 10 +sigma_experiment = 0.04 -p_early = p_gen(R̄₀ = R̄₀_lift_early, η = η_experiment, σ = σ_experiment) -p_late = p_gen(R̄₀ = R̄₀_lift_late, η = η_experiment, σ = σ_experiment) +R_bar_0_lift_early(t, p) = t < 30.0 ? R_0_L : 2.0 +R_bar_0_lift_late(t, p) = t < 120.0 ? R_0_L : 2.0 +p_early = p_gen(R_bar_0 = R_bar_0_lift_early, eta = eta_experiment, sigma = sigma_experiment) +p_late = p_gen(R_bar_0 = R_bar_0_lift_late, eta = eta_experiment, sigma = sigma_experiment) # initial conditions i_0 = 100000 / p_early.N r_0 = 0.0 d_0 = 0.0 s_0 = 1.0 - i_0 - r_0 - d_0 -δ_0 = p_early.δ_bar +delta_0 = p_early.delta_bar -x_0 = [s_0, i_0, r_0, d_0, R₀_L, δ_0] # start in lockdown +x_0 = [s_0, i_0, r_0, d_0, R_0_L, delta_0] # start in lockdown prob_early = SDEProblem(F, G, x_0, (0, p_early.T), p_early) prob_late = SDEProblem(F, G, x_0, (0, p_late.T), p_late) ``` @@ -438,13 +439,13 @@ Simulating for a single realization of the shocks, we see the results are qualit ```{code-cell} julia sol_early = solve(prob_early, SOSRI()) sol_late = solve(prob_late, SOSRI()) -plot(sol_early, vars = [5, 1,2,4], +plot(sol_early, vars = [5, 1, 2, 4], title = [L"R_0" "Susceptible" "Infected" "Dead"], layout = (2, 2), size = (900, 600), ylabel = [L"R_0(t)" L"s(t)" L"i(t)" L"d(t)"], xlabel = L"t", legend = [:bottomright :topright :topright :topleft], label = ["Early" "Early" "Early" "Early"]) -plot!(sol_late, vars = [5, 1,2,4], +plot!(sol_late, vars = [5, 1, 2, 4], legend = [:bottomright :topright :topright :topleft], label = ["Late" "Late" "Late" "Late"], xlabel = L"t") ``` @@ -535,24 +536,26 @@ We will redo the "Ending Lockdown" simulation from above, where the only differe ```{code-cell} julia function F_reinfect(x, p, t) - s, i, r, d, R₀, δ = x - (;γ, R̄₀, η, σ, ξ, θ, δ_bar, ν) = p - - return [-γ*R₀*s*i + ν*r; # ds/dt - γ*R₀*s*i - γ*i; # di/dt - (1-δ)*γ*i - ν*r # dr/dt - δ*γ*i; # dd/dt - η*(R̄₀(t, p) - R₀);# dR₀/dt - θ*(δ_bar - δ); # dδ/dt - ] + s, i, r, d, R_0, delta = x + (;gamma, R_bar_0, eta, sigma, xi, theta, delta_bar, nu) = p + + return [ + -gamma * R_0 * s * i + nu * r; # ds/dt + gamma * R_0 * s * i - gamma * i; # di/dt + (1 - delta) * gamma * i - nu * r; # dr/dt + delta * gamma * i; # dd/dt + eta * (R_bar_0(t, p) - R_0); # dR_0/dt + theta * (delta_bar - delta); # ddelta/dt + ] end -p_re_gen = @with_kw ( T = 550.0, γ = 1.0 / 18, η = 1.0 / 20, - R₀_n = 1.6, R̄₀ = (t, p) -> p.R₀_n, - δ_bar = 0.01, σ = 0.03, ξ = 0.004, θ = 0.2, N = 3.3E8, ν = 1/360) +p_re_gen(; T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, + R_0_n = 1.6, R_bar_0 = (t, p) -> p.R_0_n, + delta_bar = 0.01, sigma = 0.03, xi = 0.004, theta = 0.2, + N = 3.3E8, nu = 1/360) = (; T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N, nu) -p_re_early = p_re_gen(R̄₀ = R̄₀_lift_early, η = η_experiment, σ = σ_experiment) -p_re_late = p_re_gen(R̄₀ = R̄₀_lift_late, η = η_experiment, σ = σ_experiment) +p_re_early = p_re_gen(R_bar_0 = R_bar_0 _lift_early, eta = eta_experiment, sigma = sigma_experiment) +p_re_late = p_re_gen(R_bar_0 = R_bar_0 _lift_late, eta = eta_experiment, sigma = sigma_experiment) trajectories = 400 saveat = 1.0 diff --git a/lectures/continuous_time/seir_model.md b/lectures/continuous_time/seir_model.md index c36fdb06..14c98d0c 100644 --- a/lectures/continuous_time/seir_model.md +++ b/lectures/continuous_time/seir_model.md @@ -171,13 +171,13 @@ We begin by implementing a simple version of this model with a constant $R_0$ an First, define the system of equations ```{code-cell} julia -function F_simple(x, p, t; γ = 1/18, R₀ = 3.0, σ = 1/5.2) +function F_simple(x, p, t; gamma = 1/18, R_0 = 3.0, sigma = 1/5.2) s, e, i, r = x - return [-γ*R₀*s*i; # ds/dt = -γR₀si - γ*R₀*s*i - σ*e;# de/dt = γR₀si -σe - σ*e - γ*i; # di/dt = σe -γi - γ*i; # dr/dt = γi + return [-gamma * R_0 * s * i; # ds/dt + gamma * R_0 * s * i - sigma * e; # de/dt + sigma * e - gamma * i; # di/dt + gamma * i; # dr/dt ] end ``` @@ -195,7 +195,7 @@ tspan = (0.0, 350.0) # ≈ 350 days prob = ODEProblem(F_simple, x_0, tspan) ``` -With this, choose an ODE algorithm and solve the initial value problem. A good default algorithm for non-stiff ODEs of this sort might be `Tsit5()`, which is the Tsitouras 5/4 Runge-Kutta method). +With this, choose an ODE algorithm and solve the initial value problem. A good default algorithm for non-stiff ODEs of this sort might be `Tsit5()`, which is the Tsitouras 5/4 Runge-Kutta method. ```{code-cell} julia sol = solve(prob, Tsit5()) @@ -242,7 +242,7 @@ While we could integrate the deaths given the solution to the model ex-post, it This is a common trick when solving systems of ODEs. While equivalent in principle to using the appropriate quadrature scheme, this becomes especially convenient when adaptive time-stepping algorithms are used to solve the ODEs (i.e. there is not a regular time grid). Note that when doing so, $d(0) = \int_0^0 \delta \gamma i(\tau) d \tau = 0$ is the initial condition. -The system {eq}`seir_system` and the supplemental equations can be written in vector form $x := [s, e, i, r, R₀, c, d]$ with parameter tuple $p := (\sigma, \gamma, \eta, \delta, \bar{R}_0(\cdot))$ +The system {eq}`seir_system` and the supplemental equations can be written in vector form $x := [s, e, i, r, R_0, c, d]$ with parameter tuple $p := (\sigma, \gamma, \eta, \delta, \bar{R}_0(\cdot))$ Note that in those parameters, the targeted reproduction number, $\bar{R}_0(t)$, is an exogenous function. @@ -289,35 +289,36 @@ First, construct our $F$ from {eq}`dfcv` ```{code-cell} julia function F(x, p, t) - s, e, i, r, R₀, c, d = x - (;σ, γ, R̄₀, η, δ) = p - - return [-γ*R₀*s*i; # ds/dt - γ*R₀*s*i - σ*e; # de/dt - σ*e - γ*i; # di/dt - γ*i; # dr/dt - η*(R̄₀(t, p) - R₀);# dR₀/dt - σ*e; # dc/dt - δ*γ*i; # dd/dt + s, e, i, r, R_0, c, d = x + (;sigma, gamma, R_0_bar, eta, delta) = p + + return [-gamma * R_0 * s * i; # ds/dt + gamma * R_0 * s * i - sigma * e; # de/dt + sigma * e - γ*i; # di/dt + gamma * i; # dr/dt + eta * (R_bar_0(t, p) - R_0); # dR_0/dt + sigma * e; # dc/dt + delta * gamma * i; # dd/dt ] end; + ``` This function takes the vector `x` of states in the system and extracts the fixed parameters passed into the `p` object. -The only confusing part of the notation is the `R̄₀(t, p)` which evaluates the `p.R̄₀` at this time (and also allows it to depend on the `p` parameter). +The only confusing part of the notation is the `R_0(t, p)` which evaluates the `p.R_bar_0` at this time (and also allows it to depend on the `p` parameter). ### Parameters - +#####HERE ENDED The baseline parameters are put into a named tuple generator (see previous lectures using [Parameters.jl](https://github.com/mauro3/Parameters.jl)) with default values discussed above. ```{code-cell} julia -p_gen = @with_kw ( T = 550.0, γ = 1.0 / 18, σ = 1 / 5.2, η = 1.0 / 20, - R₀_n = 1.6, δ = 0.01, N = 3.3E8, - R̄₀ = (t, p) -> p.R₀_n); +p_gen(T = 550.0, gamma = 1.0 / 18, sigma = 1 / 5.2, eta = 1.0 / 20, + R_0_n = 1.6, delta = 0.01, N = 3.3E8, + R_0_bar = (t, p) -> p.R_0_n) = (T, gamma, sigma, eta, R_0_n, delta, N, R_0_bar) ``` -Note that the default $\bar{R}_0(t)$ function always equals $R_{0n}$ -- a parameterizable natural level of $R_0$ used only by the `R̄₀` function +Note that the default $\bar{R}_0(t)$ function always equals $R_{0n}$ -- a parameterizable natural level of $R_0$ used only by the `R_hat_0` function Setting initial conditions, we choose a fixed $s, i, e, r$, as well as $R_0(0) = R_{0n}$ and $m(0) = 0.01$ @@ -328,7 +329,7 @@ i_0 = 1E-7 e_0 = 4.0 * i_0 s_0 = 1.0 - i_0 - e_0 -x_0 = [s_0, e_0, i_0, 0.0, p.R₀_n, 0.0, 0.0] +x_0 = [s_0, e_0, i_0, 0.0, p.R_0_n, 0.0, 0.0] tspan = (0.0, p.T) prob = ODEProblem(F, x_0, tspan, p) ``` @@ -372,9 +373,9 @@ Let's start with the case where $\bar{R}_0(t) = R_{0n}$ is constant. We calculate the time path of infected people under different assumptions of $R_{0n}$: ```{code-cell} julia -R₀_n_vals = range(1.6, 3.0, length = 6) -sols = [solve(ODEProblem(F, x_0, tspan, p_gen(R₀_n = R₀_n)), - Tsit5(), saveat=0.5) for R₀_n in R₀_n_vals]; +R_0_n_vals = range(1.6, 3.0, length = 6) +sols = [solve(ODEProblem(F, x_0, tspan, p_gen(R_0_n = R_0_n)), + Tsit5(), saveat=0.5) for R_0_n in R_0_n_vals]; ``` Here we chose `saveat=0.5` to get solutions that were evenly spaced every `0.5`. @@ -384,7 +385,7 @@ Changing the saved points is just a question of storage/interpolation, and does Let's plot current cases as a fraction of the population. ```{code-cell} julia -labels = permutedims([L"R_0 = %$r" for r in R₀_n_vals]) +labels = permutedims([L"R_0 = %$r" for r in R_0_n_vals]) infecteds = [sol[3,:] for sol in sols] plot(infecteds, label=labels, legend=:topleft, lw = 2, xlabel = L"t", ylabel = L"i(t)", title = "Current Cases") @@ -413,21 +414,21 @@ In the simple case, where $\bar{R}_0(t) = R_{0n}$ is independent of the state, t We will examine the case where $R_0(0) = 3$ and then it falls to $R_{0n} = 1.6$ due to the progressive adoption of stricter mitigation measures. -The parameter `η` controls the rate, or the speed at which restrictions are +The parameter `eta` controls the rate, or the speed at which restrictions are imposed. We consider several different rates: ```{code-cell} julia -η_vals = [1/5, 1/10, 1/20, 1/50, 1/100] -labels = permutedims([L"\eta = %$η" for η in η_vals]); +eta_vals = [1/5, 1/10, 1/20, 1/50, 1/100] +labels = permutedims([L"\eta = %$eta" for eta in eta_vals]); ``` Let's calculate the time path of infected people, current cases, and mortality ```{code-cell} julia x_0 = [s_0, e_0, i_0, 0.0, 3.0, 0.0, 0.0] -sols = [solve(ODEProblem(F, x_0, tspan, p_gen(η=η)), Tsit5(), saveat=0.5) for η in η_vals]; +sols = [solve(ODEProblem(F, x_0, tspan, p_gen(eta=eta)), Tsit5(), saveat=0.5) for eta in eta_vals]; ``` Next, plot the $R_0$ over time: @@ -468,11 +469,11 @@ The parameters considered here start the model with 25,000 active infections and 75,000 agents already exposed to the virus and thus soon to be contagious. ```{code-cell} julia -R₀_L = 0.5 # lockdown -R̄₀_lift_early(t, p) = t < 30.0 ? R₀_L : 2.0 -R̄₀_lift_late(t, p) = t < 120.0 ? R₀_L : 2.0 -p_early = p_gen(R̄₀= R̄₀_lift_early, η = 10.0) -p_late = p_gen(R̄₀= R̄₀_lift_late, η = 10.0) +R_0_L = 0.5 # lockdown +R_bar_0_lift_early(t, p) = t < 30.0 ? R_0_L : 2.0 +R_bar_0_lift_late(t, p) = t < 120.0 ? R_0_L : 2.0 +p_early = p_gen(R_bar_0= R_bar_0_lift_early, eta = 10.0) +p_late = p_gen(R_bar_0= R_bar_0_lift_late, eta = 10.0) # initial conditions @@ -480,9 +481,9 @@ i_0 = 25000 / p_early.N e_0 = 75000 / p_early.N s_0 = 1.0 - i_0 - e_0 -x_0 = [s_0, e_0, i_0, 0.0, R₀_L, 0.0, 0.0] # start in lockdown +x_0 = [s_0, e_0, i_0, 0.0, R_0_L, 0.0, 0.0] # start in lockdown -# create two problems, with rapid movement of R₀(t) towards R̄₀(t) +# create two problems, with rapid movement of R_0(t) towards R_hat_0(t) prob_early = ODEProblem(F, x_0, tspan, p_early) prob_late = ODEProblem(F, x_0, tspan, p_late) ``` @@ -501,7 +502,7 @@ plot!(sol_late, vars = [7], label = "Lift Late", xlabel = L"t") Next we examine the daily deaths, $\frac{d D(t)}{dt} = N \delta \gamma i(t)$. ```{code-cell} julia -flow_deaths(sol, p) = p.N * p.δ * p.γ * sol[3,:] +flow_deaths(sol, p) = p.N * p.delta * p.gamma * sol[3,:] plot(sol_early.t, flow_deaths(sol_early, p_early), title = "Flow Deaths", label = "Lift Early") plot!(sol_late.t, flow_deaths(sol_late, p_late), label = "Lift Late", xlabel = L"t") From ab24bd648465c306e27b99b6e59f7c4099658f4d Mon Sep 17 00:00:00 2001 From: annabellasd Date: Mon, 25 Sep 2023 20:27:31 -0800 Subject: [PATCH 02/26] Update seir_model.md --- lectures/continuous_time/seir_model.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lectures/continuous_time/seir_model.md b/lectures/continuous_time/seir_model.md index 14c98d0c..61c5afe8 100644 --- a/lectures/continuous_time/seir_model.md +++ b/lectures/continuous_time/seir_model.md @@ -294,7 +294,7 @@ function F(x, p, t) return [-gamma * R_0 * s * i; # ds/dt gamma * R_0 * s * i - sigma * e; # de/dt - sigma * e - γ*i; # di/dt + sigma * e - gamma * i; # di/dt gamma * i; # dr/dt eta * (R_bar_0(t, p) - R_0); # dR_0/dt sigma * e; # dc/dt From f0317ce942254ea90ef9d4ed83d10e8ff117a594 Mon Sep 17 00:00:00 2001 From: annabellasd Date: Thu, 28 Sep 2023 12:50:20 -0800 Subject: [PATCH 03/26] update --- lectures/continuous_time/covid_sde.md | 2 +- lectures/continuous_time/seir_model.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lectures/continuous_time/covid_sde.md b/lectures/continuous_time/covid_sde.md index b13b6b85..d1435efa 100644 --- a/lectures/continuous_time/covid_sde.md +++ b/lectures/continuous_time/covid_sde.md @@ -371,7 +371,7 @@ We will shut down the shocks to the mortality rate (i.e. $\xi = 0$) to focus on Consider $\eta = 1/50$ and $\eta = 1/20$, where we start at the same initial condition of $R_0(0) = 0.5$. ```{code-cell} julia -function generate_eta_experiment(eta; p_gen, trajectories = 100, saveat = 1.0, x_0, T = 120.0) +function generate_eta_experiment(eta; p_gen = p_gen, trajectories = 100, saveat = 1.0, x_0 = x_0, T = 120.0) p = p_gen(eta = eta, xi = 0.0) ensembleprob = EnsembleProblem(SDEProblem(F, G, x_0, (0, T), p)) sol = solve(ensembleprob, SOSRI(), EnsembleThreads(), trajectories = trajectories, saveat = saveat) diff --git a/lectures/continuous_time/seir_model.md b/lectures/continuous_time/seir_model.md index 61c5afe8..2d17cb2f 100644 --- a/lectures/continuous_time/seir_model.md +++ b/lectures/continuous_time/seir_model.md @@ -290,7 +290,7 @@ First, construct our $F$ from {eq}`dfcv` ```{code-cell} julia function F(x, p, t) s, e, i, r, R_0, c, d = x - (;sigma, gamma, R_0_bar, eta, delta) = p + (;sigma, gamma, R_bar_0, eta, delta) = p return [-gamma * R_0 * s * i; # ds/dt gamma * R_0 * s * i - sigma * e; # de/dt @@ -313,9 +313,9 @@ The only confusing part of the notation is the `R_0(t, p)` which evaluates the ` The baseline parameters are put into a named tuple generator (see previous lectures using [Parameters.jl](https://github.com/mauro3/Parameters.jl)) with default values discussed above. ```{code-cell} julia -p_gen(T = 550.0, gamma = 1.0 / 18, sigma = 1 / 5.2, eta = 1.0 / 20, +p_gen(;T = 550.0, gamma = 1.0 / 18, sigma = 1 / 5.2, eta = 1.0 / 20, R_0_n = 1.6, delta = 0.01, N = 3.3E8, - R_0_bar = (t, p) -> p.R_0_n) = (T, gamma, sigma, eta, R_0_n, delta, N, R_0_bar) + R_bar_0 = (t, p) -> p.R_0_n) = (;T, gamma, sigma, eta, R_0_n, delta, N, R_bar_0) ``` Note that the default $\bar{R}_0(t)$ function always equals $R_{0n}$ -- a parameterizable natural level of $R_0$ used only by the `R_hat_0` function From 06035485c4ff0221ceed11b638e3420ab59ba43b Mon Sep 17 00:00:00 2001 From: annabellasd Date: Thu, 28 Sep 2023 18:04:25 -0800 Subject: [PATCH 04/26] Update covid_sde.md --- lectures/continuous_time/covid_sde.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lectures/continuous_time/covid_sde.md b/lectures/continuous_time/covid_sde.md index d1435efa..0d57d381 100644 --- a/lectures/continuous_time/covid_sde.md +++ b/lectures/continuous_time/covid_sde.md @@ -554,8 +554,8 @@ p_re_gen(; T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, delta_bar = 0.01, sigma = 0.03, xi = 0.004, theta = 0.2, N = 3.3E8, nu = 1/360) = (; T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N, nu) -p_re_early = p_re_gen(R_bar_0 = R_bar_0 _lift_early, eta = eta_experiment, sigma = sigma_experiment) -p_re_late = p_re_gen(R_bar_0 = R_bar_0 _lift_late, eta = eta_experiment, sigma = sigma_experiment) +p_re_early = p_re_gen(R_bar_0 = R_bar_0_lift_early, eta = eta_experiment, sigma = sigma_experiment) +p_re_late = p_re_gen(R_bar_0 = R_bar_0_lift_late, eta = eta_experiment, sigma = sigma_experiment) trajectories = 400 saveat = 1.0 From 4b3477ec4c3424c396f98c4571c4460038f75e46 Mon Sep 17 00:00:00 2001 From: annabellasd Date: Wed, 4 Oct 2023 20:36:52 -0800 Subject: [PATCH 05/26] Update covid_sde.md --- lectures/continuous_time/covid_sde.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lectures/continuous_time/covid_sde.md b/lectures/continuous_time/covid_sde.md index 0d57d381..ff1bee0d 100644 --- a/lectures/continuous_time/covid_sde.md +++ b/lectures/continuous_time/covid_sde.md @@ -387,12 +387,12 @@ summ_2 = generate_eta_experiment(eta_2) plot(summ_1, idxs = (4, 5), title = ["Proportion Dead" L"R_0"], ylabel = [L"d(t)" L"R_0(t)"], xlabel = L"t", - legend = [:topleft :bottomright], + legend = :topleft, labels = L"Middle 95% Quantile, $\eta = %$eta_1$", layout = (2, 1), size = (900, 900), fillalpha = 0.5) plot!(summ_2, idxs = (4, 5), - legend = [:topleft :bottomright], + legend = :topleft, labels = L"Middle 95% Quantile, $\eta = %$eta_2$", size = (900, 900), fillalpha = 0.5) ``` From 088e6a29ac5212a71dbd4c8d46319737b3dede3a Mon Sep 17 00:00:00 2001 From: annabellasd Date: Thu, 5 Oct 2023 20:54:04 -0800 Subject: [PATCH 06/26] spacing updates --- lectures/continuous_time/covid_sde.md | 22 +++++++++++----------- lectures/continuous_time/seir_model.md | 14 +++++++------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lectures/continuous_time/covid_sde.md b/lectures/continuous_time/covid_sde.md index ff1bee0d..15d148d1 100644 --- a/lectures/continuous_time/covid_sde.md +++ b/lectures/continuous_time/covid_sde.md @@ -231,20 +231,20 @@ First, construct our $F$ from {eq}`dfcvsde` and $G$ from {eq}`dG` ```{code-cell} julia function F(x, p, t) s, i, r, d, R_0, delta = x - (; gamma, R_bar_0, eta, sigma, xi, theta, delta_bar) = p + (;gamma, R_bar_0, eta, sigma, xi, theta, delta_bar) = p return [-gamma * R_0 * s * i; # ds/dt gamma * R_0 * s * i - gamma * i; # di/dt - (1 - delta) * gamma * i; # dr/dt - delta * gamma * i; # dd/dt + (1 - delta) * gamma * i; # dr/dt + delta * gamma * i; # dd/dt eta * (R_bar_0(t, p) - R_0); # dR_0/dt - theta * (delta_bar - delta); # ddelta/dt + theta * (delta_bar - delta); # ddelta/dt ] end function G(x, p, t) s, i, r, d, R_0, delta = x - (; gamma, R_bar_0, eta, sigma, xi, theta, delta_bar) = p + (;gamma, R_bar_0, eta, sigma, xi, theta, delta_bar) = p return [0; 0; 0; 0; sigma * sqrt(R_0); xi * sqrt(delta * (1 - delta))] end @@ -253,9 +253,9 @@ end Next create a settings generator, and then define a [SDEProblem](https://docs.sciml.ai/stable/tutorials/sde_example/#Example-2:-Systems-of-SDEs-with-Diagonal-Noise-1) with Diagonal Noise. ```{code-cell} julia -p_gen(; T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, +p_gen(;T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, R_0_n = 1.6, R_bar_0 = (t, p) -> p.R_0_n, delta_bar = 0.01, - sigma = 0.03, xi = 0.004, theta = 0.2, N = 3.3E8) = (; T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N) + sigma = 0.03, xi = 0.004, theta = 0.2, N = 3.3E8) = (;T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N) p = p_gen() # use all defaults i_0 = 25000 / p.N @@ -549,13 +549,13 @@ function F_reinfect(x, p, t) ] end -p_re_gen(; T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, +p_re_gen(;T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, R_0_n = 1.6, R_bar_0 = (t, p) -> p.R_0_n, delta_bar = 0.01, sigma = 0.03, xi = 0.004, theta = 0.2, - N = 3.3E8, nu = 1/360) = (; T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N, nu) + N = 3.3E8, nu = 1/360) = (;T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N, nu) -p_re_early = p_re_gen(R_bar_0 = R_bar_0_lift_early, eta = eta_experiment, sigma = sigma_experiment) -p_re_late = p_re_gen(R_bar_0 = R_bar_0_lift_late, eta = eta_experiment, sigma = sigma_experiment) +p_re_early = p_re_gen(R_bar_0 = R_bar_0_lift_early, eta = eta_experiment, sigma = sigma_experiment) +p_re_late = p_re_gen(R_bar_0 = R_bar_0_lift_late, eta = eta_experiment, sigma = sigma_experiment) trajectories = 400 saveat = 1.0 diff --git a/lectures/continuous_time/seir_model.md b/lectures/continuous_time/seir_model.md index 2d17cb2f..06606dd7 100644 --- a/lectures/continuous_time/seir_model.md +++ b/lectures/continuous_time/seir_model.md @@ -293,8 +293,8 @@ function F(x, p, t) (;sigma, gamma, R_bar_0, eta, delta) = p return [-gamma * R_0 * s * i; # ds/dt - gamma * R_0 * s * i - sigma * e; # de/dt - sigma * e - gamma * i; # di/dt + gamma * R_0 * s * i - sigma * e; # de/dt + sigma * e - gamma * i; # di/dt gamma * i; # dr/dt eta * (R_bar_0(t, p) - R_0); # dR_0/dt sigma * e; # dc/dt @@ -306,7 +306,7 @@ end; This function takes the vector `x` of states in the system and extracts the fixed parameters passed into the `p` object. -The only confusing part of the notation is the `R_0(t, p)` which evaluates the `p.R_bar_0` at this time (and also allows it to depend on the `p` parameter). +The only confusing part of the notation is the `R_bar_0(t, p)` which evaluates the `p.R_bar_0` at this time (and also allows it to depend on the `p` parameter). ### Parameters #####HERE ENDED @@ -318,7 +318,7 @@ p_gen(;T = 550.0, gamma = 1.0 / 18, sigma = 1 / 5.2, eta = 1.0 / 20, R_bar_0 = (t, p) -> p.R_0_n) = (;T, gamma, sigma, eta, R_0_n, delta, N, R_bar_0) ``` -Note that the default $\bar{R}_0(t)$ function always equals $R_{0n}$ -- a parameterizable natural level of $R_0$ used only by the `R_hat_0` function +Note that the default $\bar{R}_0(t)$ function always equals $R_{0n}$ -- a parameterizable natural level of $R_0$ used only by the `R_bar_0` function Setting initial conditions, we choose a fixed $s, i, e, r$, as well as $R_0(0) = R_{0n}$ and $m(0) = 0.01$ @@ -472,8 +472,8 @@ and 75,000 agents already exposed to the virus and thus soon to be contagious. R_0_L = 0.5 # lockdown R_bar_0_lift_early(t, p) = t < 30.0 ? R_0_L : 2.0 R_bar_0_lift_late(t, p) = t < 120.0 ? R_0_L : 2.0 -p_early = p_gen(R_bar_0= R_bar_0_lift_early, eta = 10.0) -p_late = p_gen(R_bar_0= R_bar_0_lift_late, eta = 10.0) +p_early = p_gen(R_bar_0 = R_bar_0_lift_early, eta = 10.0) +p_late = p_gen(R_bar_0 = R_bar_0_lift_late, eta = 10.0) # initial conditions @@ -483,7 +483,7 @@ s_0 = 1.0 - i_0 - e_0 x_0 = [s_0, e_0, i_0, 0.0, R_0_L, 0.0, 0.0] # start in lockdown -# create two problems, with rapid movement of R_0(t) towards R_hat_0(t) +# create two problems, with rapid movement of R_0(t) towards R_bar_0(t) prob_early = ODEProblem(F, x_0, tspan, p_early) prob_late = ODEProblem(F, x_0, tspan, p_late) ``` From af3c999b9975d994ccb4554295ff0c6e11b92bd5 Mon Sep 17 00:00:00 2001 From: annabellasd Date: Mon, 9 Oct 2023 19:32:32 -0800 Subject: [PATCH 07/26] updated --- format_myst.jl | 4 +- lectures/dynamic_programming_squared/amss.md | 270 +++++++++--------- .../dynamic_programming_squared/dyn_stack.md | 112 ++++---- .../dynamic_programming_squared/lqramsey.md | 105 ++++--- .../opt_tax_recur.md | 214 +++++++------- 5 files changed, 348 insertions(+), 357 deletions(-) diff --git a/format_myst.jl b/format_myst.jl index 0e24e1dd..fcf44d03 100644 --- a/format_myst.jl +++ b/format_myst.jl @@ -58,7 +58,9 @@ function format_myst(input_file_path, output_file_path, extra_replacements = fal replacements = Dict("α" => "alpha", "β" => "beta", "γ" => "gamma", "≤" => "<=", "≥" => ">=", "Σ" => "Sigma", "σ" => "sigma","μ"=>"mu","ϕ"=>"phi","ψ"=>"psi","ϵ"=>"epsilon", "δ"=>"delta","θ" => "theta","ζ"=>"zeta","X̄" => "X_bar","p̄" => "p_bar","x̂" => "x_hat","λ"=>"lambda", - "ρ"=>"rho","u′" => "u_prime" , "f′"=>"f_prime"," ∂u∂c"=>"dudc","Π"=>"Pi","π"=>"pi"," ξ"=>"Xi","c̄"=>"c_bar","w̄"=>"w_bar") + "ρ"=>"rho","u′" => "u_prime" , "f′"=>"f_prime"," ∂u∂c"=>"dudc","Π"=>"Pi","π"=>"pi","ξ"=>"xi","c̄"=>"c_bar", + "w̄"=>"w_bar","Θ" => "Theta", "Ξ" =>"Xi", "Q̃" => "Q_tilde","R̃" => "R_tilde","Ã" => "A_tilde", "B̃" => "B_tilde", + "P̃" => "P_tilde","F̃" => "F_tilde","d̃" => "d_tilde") # Replace the code blocks in the content and handle exceptions try diff --git a/lectures/dynamic_programming_squared/amss.md b/lectures/dynamic_programming_squared/amss.md index e9fee44a..971a52c6 100644 --- a/lectures/dynamic_programming_squared/amss.md +++ b/lectures/dynamic_programming_squared/amss.md @@ -404,10 +404,10 @@ import QuantEcon.simulate mutable struct Model{TF <: AbstractFloat, TM <: AbstractMatrix{TF}, TV <: AbstractVector{TF}} - β::TF - Π::TM + beta::TF + Pi::TM G::TV - Θ::TV + Theta::TV transfers::Bool U::Function Uc::Function @@ -426,19 +426,19 @@ struct SequentialAllocation{TP <: Model, S::TI cFB::TV nFB::TV - ΞFB::TV + XiFB::TV zFB::TV end function SequentialAllocation(model::Model) - β, Π, G, Θ = model.β, model.Π, model.G, model.Θ - mc = MarkovChain(Π) - S = size(Π, 1) # Number of states + beta, Pi, G, Theta = model.beta, model.Pi, model.G, model.Theta + mc = MarkovChain(Pi) + S = size(Pi, 1) # Number of states # Now find the first best allocation - cFB, nFB, ΞFB, zFB = find_first_best(model, S, 1) + cFB, nFB, XiFB, zFB = find_first_best(model, S, 1) - return SequentialAllocation(model, mc, S, cFB, nFB, ΞFB, zFB) + return SequentialAllocation(model, mc, S, cFB, nFB, XiFB, zFB) end @@ -446,13 +446,13 @@ function find_first_best(model::Model, S::Integer, version::Integer) if version != 1 && version != 2 throw(ArgumentError("version must be 1 or 2")) end - β, Θ, Uc, Un, G, Π = - model.β, model.Θ, model.Uc, model.Un, model.G, model.Π + beta, Theta, Uc, Un, G, Pi = + model.beta, model.Theta, model.Uc, model.Un, model.G, model.Pi function res!(out, z) c = z[1:S] n = z[S+1:end] - out[1:S] = Θ .* Uc.(c, n) + Un.(c, n) - out[S+1:end] = Θ .* n .- c .- G + out[1:S] = Theta .* Uc.(c, n) + Un.(c, n) + out[S+1:end] = Theta .* n .- c .- G end res = nlsolve(res!, 0.5 * ones(2 * S)) @@ -463,32 +463,32 @@ function find_first_best(model::Model, S::Integer, version::Integer) if version == 1 cFB = res.zero[1:S] nFB = res.zero[S+1:end] - ΞFB = Uc(cFB, nFB) # Multiplier on the resource constraint - zFB = vcat(cFB, nFB, ΞFB) - return cFB, nFB, ΞFB, zFB + XiFB = Uc(cFB, nFB) # Multiplier on the resource constraint + zFB = vcat(cFB, nFB, XiFB) + return cFB, nFB, XiFB, zFB elseif version == 2 cFB = res.zero[1:S] nFB = res.zero[S+1:end] IFB = Uc(cFB, nFB) .* cFB + Un(cFB, nFB) .* nFB - xFB = \(LinearAlgebra.I - β * Π, IFB) + xFB = \(LinearAlgebra.I - beta * Pi, IFB) zFB = [vcat(cFB[s], xFB[s], xFB) for s in 1:S] return cFB, nFB, IFB, xFB, zFB end end -function time1_allocation(pas::SequentialAllocation, μ::Real) +function time1_allocation(pas::SequentialAllocation, mu::Real) model, S = pas.model, pas.S - Θ, β, Π, G, Uc, Ucc, Un, Unn = - model.Θ, model.β, model.Π, model.G, + Theta, beta, Pi, G, Uc, Ucc, Un, Unn = + model.Theta, model.beta, model.Pi, model.G, model.Uc, model.Ucc, model.Un, model.Unn function FOC!(out, z::Vector) c = z[1:S] n = z[S+1:2S] - Ξ = z[2S+1:end] - out[1:S] = Uc.(c, n) - μ * (Ucc.(c, n) .* c + Uc.(c, n)) - Ξ # FOC c - out[S+1:2S] = Un.(c, n) - μ * (Unn(c, n) .* n .+ Un.(c, n)) + Θ .* Ξ # FOC n - out[2S+1:end] = Θ .* n - c .- G # resource constraint + Xi = z[2S+1:end] + out[1:S] = Uc.(c, n) - mu * (Ucc.(c, n) .* c + Uc.(c, n)) - Xi # FOC c + out[S+1:2S] = Un.(c, n) - mu * (Unn(c, n) .* n .+ Un.(c, n)) + Theta .* Xi # FOC n + out[2S+1:end] = Theta .* n - c .- G # resource constraint return out end # Find the root of the FOC @@ -497,35 +497,35 @@ function time1_allocation(pas::SequentialAllocation, μ::Real) error("Could not find LS allocation.") end z = res.zero - c, n, Ξ = z[1:S], z[S+1:2S], z[2S+1:end] + c, n, Xi = z[1:S], z[S+1:2S], z[2S+1:end] # Now compute x I = Uc(c, n) .* c + Un(c, n) .* n - x = \(LinearAlgebra.I - β * model.Π, I) - return c, n, x, Ξ + x = \(LinearAlgebra.I - beta * model.Pi, I) + return c, n, x, Xi end function time0_allocation(pas::SequentialAllocation, B_::AbstractFloat, s_0::Integer) model = pas.model - Π, Θ, G, β = model.Π, model.Θ, model.G, model.β + Pi, Theta, G, beta = model.Pi, model.Theta, model.G, model.beta Uc, Ucc, Un, Unn = model.Uc, model.Ucc, model.Un, model.Unn # First order conditions of planner's problem function FOC!(out, z) - μ, c, n, Ξ = z[1], z[2], z[3], z[4] - xprime = time1_allocation(pas, μ)[3] + mu, c, n, Xi = z[1], z[2], z[3], z[4] + xprime = time1_allocation(pas, mu)[3] out .= vcat( - Uc(c, n) .* (c - B_) + Un(c, n) .* n + β * dot(Π[s_0, :], xprime), - Uc(c, n) .- μ * (Ucc(c, n) .* (c - B_) + Uc(c, n)) .- Ξ, - Un(c, n) .- μ * (Unn(c, n) .* n + Un(c, n)) + Θ[s_0] .* Ξ, - (Θ .* n .- c .- G)[s_0] + Uc(c, n) .* (c - B_) + Un(c, n) .* n + beta * dot(Pi[s_0, :], xprime), + Uc(c, n) .- mu * (Ucc(c, n) .* (c - B_) + Uc(c, n)) .- Xi, + Un(c, n) .- mu * (Unn(c, n) .* n + Un(c, n)) + Theta[s_0] .* Xi, + (Theta .* n .- c .- G)[s_0] ) end # Find root - res = nlsolve(FOC!, [0.0, pas.cFB[s_0], pas.nFB[s_0], pas.ΞFB[s_0]]) + res = nlsolve(FOC!, [0.0, pas.cFB[s_0], pas.nFB[s_0], pas.XiFB[s_0]]) if res.f_converged == false error("Could not find time 0 LS allocation.") end @@ -533,18 +533,18 @@ function time0_allocation(pas::SequentialAllocation, end -function time1_value(pas::SequentialAllocation, μ::Real) +function time1_value(pas::SequentialAllocation, mu::Real) model = pas.model - c, n, x, Ξ = time1_allocation(pas, μ) + c, n, x, Xi = time1_allocation(pas, mu) U_val = model.U.(c, n) - V = \(LinearAlgebra.I - model.β*model.Π, U_val) + V = \(LinearAlgebra.I - model.beta*model.Pi, U_val) return c, n, x, V end function Τ(model::Model, c::Union{Real,Vector}, n::Union{Real,Vector}) Uc, Un = model.Uc.(c, n), model.Un.(c, n) - return 1. .+ Un./(model.Θ .* Uc) + return 1. .+ Un./(model.Theta .* Uc) end @@ -554,7 +554,7 @@ function simulate(pas::SequentialAllocation, sHist::Union{Vector, Nothing}=nothing) model = pas.model - Π, β, Uc = model.Π, model.β, model.Uc + Pi, beta, Uc = model.Pi, model.beta, model.Uc if isnothing(sHist) sHist = QuantEcon.simulate(pas.mc, T, init=s_0) @@ -563,25 +563,25 @@ function simulate(pas::SequentialAllocation, nHist = zeros(T) Bhist = zeros(T) ΤHist = zeros(T) - μHist = zeros(T) + muHist = zeros(T) RHist = zeros(T-1) # time 0 - μ, cHist[1], nHist[1], _ = time0_allocation(pas, B_, s_0) + mu, cHist[1], nHist[1], _ = time0_allocation(pas, B_, s_0) ΤHist[1] = Τ(pas.model, cHist[1], nHist[1])[s_0] Bhist[1] = B_ - μHist[1] = μ + muHist[1] = mu # time 1 onward for t in 2:T - c, n, x, Ξ = time1_allocation(pas,μ) + c, n, x, Xi = time1_allocation(pas,mu) u_c = Uc(c,n) s = sHist[t] ΤHist[t] = Τ(pas.model, c, n)[s] - Eu_c = dot(Π[sHist[t-1],:], u_c) + Eu_c = dot(Pi[sHist[t-1],:], u_c) cHist[t], nHist[t], Bhist[t] = c[s], n[s], x[s] / u_c[s] - RHist[t-1] = Uc(cHist[t-1], nHist[t-1]) / (β * Eu_c) - μHist[t] = μ + RHist[t-1] = Uc(cHist[t-1], nHist[t-1]) / (beta * Eu_c) + muHist[t] = mu end - return cHist, nHist, Bhist, ΤHist, sHist, μHist, RHist + return cHist, nHist, Bhist, ΤHist, sHist, muHist, RHist end @@ -603,7 +603,7 @@ end function BellmanEquation(model::Model, xgrid::AbstractVector, policies0::Vector) - S = size(model.Π, 1) # number of states + S = size(model.Pi, 1) # number of states xbar = [minimum(xgrid), maximum(xgrid)] time_0 = false cf, nf, xprimef = policies0 @@ -618,19 +618,19 @@ function get_policies_time1(T::BellmanEquation, i_x::Integer, x::AbstractFloat, s::Integer, Vf::AbstractArray) model, S = T.model, T.S - β, Θ, G, Π = model.β, model.Θ, model.G, model.Π + beta, Theta, G, Pi = model.beta, model.Theta, model.G, model.Pi U, Uc, Un = model.U, model.Uc, model.Un function objf(z::Vector, grad) c, xprime = z[1], z[2:end] n=c+G[s] Vprime = [Vf[sprime](xprime[sprime]) for sprime in 1:S] - return -(U(c, n) + β * dot(Π[s, :], Vprime)) + return -(U(c, n) + beta * dot(Pi[s, :], Vprime)) end function cons(z::Vector, grad) c, xprime = z[1], z[2:end] n=c+G[s] - return x - Uc(c, n) * c - Un(c, n) * n - β * dot(Π[s, :], xprime) + return x - Uc(c, n) * c - Un(c, n) * n - beta * dot(Pi[s, :], xprime) end lb = vcat(0, T.xbar[1] * ones(S)) ub = vcat(1 - G[s], T.xbar[2] * ones(S)) @@ -657,18 +657,18 @@ end function get_policies_time0(T::BellmanEquation, B_::AbstractFloat, s0::Integer, Vf::Array) model, S = T.model, T.S - β, Θ, G, Π = model.β, model.Θ, model.G, model.Π + beta, Theta, G, Pi = model.beta, model.Theta, model.G, model.Pi U, Uc, Un = model.U, model.Uc, model.Un function objf(z, grad) c, xprime = z[1], z[2:end] n = c+G[s0] Vprime = [Vf[sprime](xprime[sprime]) for sprime in 1:S] - return -(U(c, n) + β * dot(Π[s0, :], Vprime)) + return -(U(c, n) + beta * dot(Pi[s0, :], Vprime)) end function cons(z::Vector, grad) c, xprime = z[1], z[2:end] n = c + G[s0] - return -Uc(c, n) * (c - B_) - Un(c, n) * n - β * dot(Π[s0, :], xprime) + return -Uc(c, n) * (c - B_) - Un(c, n) * n - beta * dot(Pi[s0, :], xprime) end lb = vcat(0, T.xbar[1] * ones(S)) ub = vcat(1-G[s0], T.xbar[2] * ones(S)) @@ -985,53 +985,53 @@ struct RecursiveAllocation{TP <: Model, mc::MarkovChain S::TI T::BellmanEquation_Recursive - μgrid::TVg + mugrid::TVg xgrid::TVg Vf::Array policies::TT end -function RecursiveAllocation(model::Model, μgrid::AbstractArray) +function RecursiveAllocation(model::Model, mugrid::AbstractArray) G = model.G - S = size(model.Π, 1) # number of states - mc = MarkovChain(model.Π) + S = size(model.Pi, 1) # number of states + mc = MarkovChain(model.Pi) # now find the first best allocation - Vf, policies, T, xgrid = solve_time1_bellman(model, μgrid) + Vf, policies, T, xgrid = solve_time1_bellman(model, mugrid) T.time_0 = true # Bellman equation now solves time 0 problem - return RecursiveAllocation(model, mc, S, T, μgrid, xgrid, Vf, policies) + return RecursiveAllocation(model, mc, S, T, mugrid, xgrid, Vf, policies) end -function solve_time1_bellman(model::Model{TR}, μgrid::AbstractArray) where {TR <: Real} - Π = model.Π - S = size(model.Π, 1) +function solve_time1_bellman(model::Model{TR}, mugrid::AbstractArray) where {TR <: Real} + Pi = model.Pi + S = size(model.Pi, 1) # First get initial fit from lucas stockey solution. # Need to change things to be ex_ante PP = SequentialAllocation(model) function incomplete_allocation(PP::SequentialAllocation, - μ_::AbstractFloat, + mu_::AbstractFloat, s_::Integer) - c, n, x, V = time1_value(PP, μ_) - return c, n, dot(Π[s_, :], x), dot(Π[s_, :], V) + c, n, x, V = time1_value(PP, mu_) + return c, n, dot(Pi[s_, :], x), dot(Pi[s_, :], V) end cf = Array{Function}(undef, S, S) nf = Array{Function}(undef, S, S) xprimef = Array{Function}(undef, S, S) Vf = Vector{Function}(undef, S) - xgrid = Array{TR}(undef, S, length(μgrid)) + xgrid = Array{TR}(undef, S, length(mugrid)) for s_ in 1:S - c = Array{TR}(undef, length(μgrid), S) - n = Array{TR}(undef, length(μgrid), S) - x = Array{TR}(undef, length(μgrid)) - V = Array{TR}(undef, length(μgrid)) - for (i_μ, μ) in enumerate(μgrid) - c[i_μ, :], n[i_μ, :], x[i_μ], V[i_μ] = - incomplete_allocation(PP, μ, s_) + c = Array{TR}(undef, length(mugrid), S) + n = Array{TR}(undef, length(mugrid), S) + x = Array{TR}(undef, length(mugrid)) + V = Array{TR}(undef, length(mugrid)) + for (i_mu, mu) in enumerate(mugrid) + c[i_mu, :], n[i_mu, :], x[i_mu], V[i_mu] = + incomplete_allocation(PP, mu, s_) end xprimes = repeat(x, 1, S) xgrid[s_, :] = x @@ -1051,7 +1051,7 @@ function solve_time1_bellman(model::Model{TR}, μgrid::AbstractArray) where {TR # Create xgrid xbar = [maximum(minimum(xgrid)), minimum(maximum(xgrid))] - xgrid = range(xbar[1], xbar[2], length = length(μgrid)) + xgrid = range(xbar[1], xbar[2], length = length(mugrid)) # Now iterate on Bellman equation T = BellmanEquation_Recursive(model, xgrid, policies) @@ -1113,7 +1113,7 @@ function Tau(pab::RecursiveAllocation, n::AbstractArray) model = pab.model Uc, Un = model.Uc(c, n), model.Un(c, n) - return 1. .+ Un ./ (model.Θ .* Uc) + return 1. .+ Un ./ (model.Theta .* Uc) end Tau(pab::RecursiveAllocation, c::Real, n::Real) = Tau(pab, [c], [n]) @@ -1133,7 +1133,7 @@ function simulate(pab::RecursiveAllocation, B_::TF, s_0::Integer, T::Integer, sHist::Vector=simulate(pab.mc, T, init=s_0)) where {TF <: AbstractFloat} model, mc, Vf, S = pab.model, pab.mc, pab.Vf, pab.S - Π, Uc = model.Π, model.Uc + Pi, Uc = model.Pi, model.Uc cf, nf, xprimef, TTf = pab.policies cHist = Array{TF}(undef, T) @@ -1142,13 +1142,13 @@ function simulate(pab::RecursiveAllocation, xHist = Array{TF}(undef, T) TauHist = Array{TF}(undef, T) THist = Array{TF}(undef, T) - μHist = Array{TF}(undef, T) + muHist = Array{TF}(undef, T) #time0 cHist[1], nHist[1], xHist[1], THist[1] = time0_allocation(pab, B_, s_0) TauHist[1] = Tau(pab, cHist[1], nHist[1])[s_0] Bhist[1] = B_ - μHist[1] = Vf[s_0](xHist[1]) + muHist[1] = Vf[s_0](xHist[1]) #time 1 onward for t in 2:T @@ -1165,14 +1165,14 @@ function simulate(pab::RecursiveAllocation, Tau_val = Tau(pab, c, n)[s] u_c = Uc(c, n) - Eu_c = dot(Π[s_, :], u_c) + Eu_c = dot(Pi[s_, :], u_c) - μHist[t] = Vf[s](xprime[s]) + muHist[t] = Vf[s](xprime[s]) cHist[t], nHist[t], Bhist[t], TauHist[t] = c[s], n[s], x/Eu_c, Tau_val xHist[t], THist[t] = xprime[s], TT[s] end - return cHist, nHist, Bhist, xHist, TauHist, THist, μHist, sHist + return cHist, nHist, Bhist, xHist, TauHist, THist, muHist, sHist end @@ -1180,7 +1180,7 @@ function BellmanEquation_Recursive(model::Model{TF}, xgrid::AbstractVector{TF}, policies0::Array) where {TF <: AbstractFloat} - S = size(model.Π, 1) # number of states + S = size(model.Pi, 1) # number of states xbar = [minimum(xgrid), maximum(xgrid)] time_0 = false z0 = Array{Array}(undef, length(xgrid), S) @@ -1209,33 +1209,33 @@ function get_policies_time1(T::BellmanEquation_Recursive, Vf::AbstractArray{Function}, xbar::AbstractVector) model, S = T.model, T.S - β, Θ, G, Π = model.β, model.Θ, model.G, model.Π + beta, Theta, G, Pi = model.beta, model.Theta, model.G, model.Pi U,Uc,Un = model.U, model.Uc, model.Un - S_possible = sum(Π[s_, :].>0) - sprimei_possible = findall(Π[s_, :].>0) + S_possible = sum(Pi[s_, :].>0) + sprimei_possible = findall(Pi[s_, :].>0) function objf(z, grad) c, xprime = z[1:S_possible], z[S_possible+1:2S_possible] - n = (c .+ G[sprimei_possible]) ./ Θ[sprimei_possible] + n = (c .+ G[sprimei_possible]) ./ Theta[sprimei_possible] Vprime = [Vf[sprimei_possible[si]](xprime[si]) for si in 1:S_possible] - return -dot(Π[s_, sprimei_possible], U.(c, n) + β * Vprime) + return -dot(Pi[s_, sprimei_possible], U.(c, n) + beta * Vprime) end function cons(out, z, grad) c, xprime, TT = z[1:S_possible], z[S_possible + 1:2S_possible], z[2S_possible + 1:3S_possible] - n = (c .+ G[sprimei_possible]) ./ Θ[sprimei_possible] + n = (c .+ G[sprimei_possible]) ./ Theta[sprimei_possible] u_c = Uc.(c, n) - Eu_c = dot(Π[s_, sprimei_possible], u_c) - out .= x * u_c/Eu_c - u_c .* (c - TT) - Un(c, n) .* n - β * xprime + Eu_c = dot(Pi[s_, sprimei_possible], u_c) + out .= x * u_c/Eu_c - u_c .* (c - TT) - Un(c, n) .* n - beta * xprime end function cons_no_trans(out, z, grad) c, xprime = z[1:S_possible], z[S_possible + 1:2S_possible] - n = (c .+ G[sprimei_possible]) ./ Θ[sprimei_possible] + n = (c .+ G[sprimei_possible]) ./ Theta[sprimei_possible] u_c = Uc.(c, n) - Eu_c = dot(Π[s_, sprimei_possible], u_c) - out .= x * u_c / Eu_c - u_c .* c - Un(c, n) .* n - β * xprime + Eu_c = dot(Pi[s_, sprimei_possible], u_c) + out .= x * u_c / Eu_c - u_c .* c - Un(c, n) .* n - beta * xprime end if model.transfers == true @@ -1302,19 +1302,19 @@ function get_policies_time0(T::BellmanEquation_Recursive, Vf::AbstractArray{Function}, xbar::AbstractVector) model = T.model - β, Θ, G = model.β, model.Θ, model.G + beta, Theta, G = model.beta, model.Theta, model.G U, Uc, Un = model.U, model.Uc, model.Un function objf(z, grad) c, xprime = z[1], z[2] - n = (c + G[s0]) / Θ[s0] - return -(U(c, n) + β * Vf[s0](xprime)) + n = (c + G[s0]) / Theta[s0] + return -(U(c, n) + beta * Vf[s0](xprime)) end function cons(z,grad) c, xprime, TT = z[1], z[2], z[3] - n = (c + G[s0]) / Θ[s0] - return -Uc(c, n) * (c - B_ - TT) - Un(c, n) * n - β * xprime + n = (c + G[s0]) / Theta[s0] + return -Uc(c, n) * (c - B_ - TT) - Un(c, n) * n - beta * xprime end cons_no_trans(z, grad) = cons(vcat(z, 0), grad) @@ -1430,29 +1430,29 @@ This utility function is implemented in the following constructor ```{code-cell} julia function crra_utility(; - β = 0.9, - σ = 2.0, - γ = 2.0, - Π = 0.5 * ones(2, 2), + beta = 0.9, + sigma = 2.0, + gamma = 2.0, + Pi = 0.5 * ones(2, 2), G = [0.1, 0.2], - Θ = ones(Float64, 2), + Theta = ones(Float64, 2), transfers = false ) function U(c, n) - if σ == 1.0 + if sigma == 1.0 U = log(c) else - U = (c.^(1.0 - σ) - 1.0) / (1.0 - σ) + U = (c.^(1.0 - sigma) - 1.0) / (1.0 - sigma) end - return U - n.^(1 + γ) / (1 + γ) + return U - n.^(1 + gamma) / (1 + gamma) end # Derivatives of utility function - Uc(c,n) = c.^(-σ) - Ucc(c,n) = -σ * c.^(-σ - 1.0) - Un(c,n) = -n.^γ - Unn(c,n) = -γ * n.^(γ - 1.0) + Uc(c,n) = c.^(-sigma) + Ucc(c,n) = -sigma * c.^(-sigma - 1.0) + Un(c,n) = -n.^gamma + Unn(c,n) = -gamma * n.^(gamma - 1.0) n_less_than_one = false - return Model(β, Π, G, Θ, transfers, + return Model(beta, Pi, G, Theta, transfers, U, Uc, Ucc, Un, Unn, n_less_than_one) end ``` @@ -1469,22 +1469,22 @@ triangle denote war. ```{code-cell} julia time_example = crra_utility(G=[0.1, 0.1, 0.1, 0.2, 0.1, 0.1], - Θ = ones(6)) # Θ can in principle be random + Theta = ones(6)) # Theta can in principle be random -time_example.Π = [ 0.0 1.0 0.0 0.0 0.0 0.0; +time_example.Pi = [ 0.0 1.0 0.0 0.0 0.0 0.0; 0.0 0.0 1.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.5 0.5 0.0; 0.0 0.0 0.0 0.0 0.0 1.0; 0.0 0.0 0.0 0.0 0.0 1.0; 0.0 0.0 0.0 0.0 0.0 1.0] -# Initialize μgrid for value function iteration -μgrid = range(-0.7, 0.01, length = 200) +# Initialize mugrid for value function iteration +mugrid = range(-0.7, 0.01, length = 200) time_example.transfers = true # Government can use transfers time_sequential = SequentialAllocation(time_example) # Solve sequential problem -time_bellman = RecursiveAllocation(time_example, μgrid) +time_bellman = RecursiveAllocation(time_example, mugrid) sHist_h = [1, 2, 3, 4, 6, 6, 6] sHist_l = [1, 2, 3, 5, 6, 6, 6] @@ -1500,16 +1500,16 @@ titles = hcat("Consumption", "Labor Supply", "Government Debt", "Tax Rate", "Government Spending", "Output") sim_seq_l_plot = hcat(sim_seq_l[1:3]..., sim_seq_l[4], time_example.G[sHist_l], - time_example.Θ[sHist_l] .* sim_seq_l[2]) + time_example.Theta[sHist_l] .* sim_seq_l[2]) sim_bel_l_plot = hcat(sim_bel_l[1:3]..., sim_bel_l[5], time_example.G[sHist_l], - time_example.Θ[sHist_l] .* sim_bel_l[2]) + time_example.Theta[sHist_l] .* sim_bel_l[2]) sim_seq_h_plot = hcat(sim_seq_h[1:3]..., sim_seq_h[4], time_example.G[sHist_h], - time_example.Θ[sHist_h] .* sim_seq_h[2]) + time_example.Theta[sHist_h] .* sim_seq_h[2]) sim_bel_h_plot = hcat(sim_bel_h[1:3]..., sim_bel_h[5], time_example.G[sHist_h], - time_example.Θ[sHist_h] .* sim_bel_h[2]) + time_example.Theta[sHist_h] .* sim_bel_h[2]) p = plot(size = (920, 750), layout =(3, 2), xaxis=(0:6), grid=false, titlefont=Plots.font("sans-serif", 10)) plot!(p, title = titles) @@ -1574,20 +1574,20 @@ $$ In accordance, we will re-define our utility function ```{code-cell} julia -function log_utility(;β = 0.9, - ψ = 0.69, - Π = 0.5 * ones(2, 2), +function log_utility(;beta = 0.9, + psi = 0.69, + Pi = 0.5 * ones(2, 2), G = [0.1, 0.2], - Θ = ones(2), + Theta = ones(2), transfers = false) # Derivatives of utility function - U(c,n) = log(c) + ψ * log(1 - n) + U(c,n) = log(c) + psi * log(1 - n) Uc(c,n) = 1 ./ c Ucc(c,n) = -c.^(-2.0) - Un(c,n) = -ψ ./ (1.0 .- n) - Unn(c,n) = -ψ ./ (1.0 .- n).^2.0 + Un(c,n) = -psi ./ (1.0 .- n) + Unn(c,n) = -psi ./ (1.0 .- n).^2.0 n_less_than_one = true - return Model(β, Π, G, Θ, transfers, + return Model(beta, Pi, G, Theta, transfers, U, Uc, Ucc, Un, Unn, n_less_than_one) end ``` @@ -1604,7 +1604,7 @@ log_example = log_utility() log_example.transfers = true # Government can use transfers log_sequential = SequentialAllocation(log_example) # Solve sequential problem -log_bellman = RecursiveAllocation(log_example, μgrid) # Solve recursive problem +log_bellman = RecursiveAllocation(log_example, mugrid) # Solve recursive problem T = 20 sHist = [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1] @@ -1614,9 +1614,9 @@ sim_seq = simulate(log_sequential, 0.5, 1, T, sHist) sim_bel = simulate(log_bellman, 0.5, 1, T, sHist) sim_seq_plot = hcat(sim_seq[1:3]..., - sim_seq[4], log_example.G[sHist], log_example.Θ[sHist] .* sim_seq[2]) + sim_seq[4], log_example.G[sHist], log_example.Theta[sHist] .* sim_seq[2]) sim_bel_plot = hcat(sim_bel[1:3]..., - sim_bel[5], log_example.G[sHist], log_example.Θ[sHist] .* sim_bel[2]) + sim_bel[5], log_example.G[sHist], log_example.Theta[sHist] .* sim_bel[2]) #plot policies p = plot(size = (920, 750), layout = grid(3, 2), @@ -1656,9 +1656,9 @@ sim_seq_long = simulate(log_sequential, 0.5, 1, T_long) sHist_long = sim_seq_long[end-2] sim_bel_long = simulate(log_bellman, 0.5, 1, T_long, sHist_long) sim_seq_long_plot = hcat(sim_seq_long[1:4]..., - log_example.G[sHist_long], log_example.Θ[sHist_long] .* sim_seq_long[2]) + log_example.G[sHist_long], log_example.Theta[sHist_long] .* sim_seq_long[2]) sim_bel_long_plot = hcat(sim_bel_long[1:3]..., sim_bel_long[5], - log_example.G[sHist_long], log_example.Θ[sHist_long] .* sim_bel_long[2]) + log_example.G[sHist_long], log_example.Theta[sHist_long] .* sim_bel_long[2]) p = plot(size = (920, 750), layout = (3, 2), xaxis=(0:50:T_long), grid=false, titlefont=Plots.font("sans-serif", 10)) diff --git a/lectures/dynamic_programming_squared/dyn_stack.md b/lectures/dynamic_programming_squared/dyn_stack.md index e8c1d5d7..1496434b 100644 --- a/lectures/dynamic_programming_squared/dyn_stack.md +++ b/lectures/dynamic_programming_squared/dyn_stack.md @@ -929,16 +929,10 @@ We define named tuples and default values for the model and solver settings, and instantiate one copy of each ```{code-cell} julia -model = @with_kw (a0 = 10, - a1 = 2, - β = 0.96, - γ = 120., - n = 300) +model(;a0 = 10, a1 = 2, beta = 0.96, gamma = 120., n = 300) = (; a0, a1, beta, gamma, n) # things like tolerances, etc. -settings = @with_kw (tol0 = 1e-8, - tol1 = 1e-16, - tol2 = 1e-2) +settings(;tol0 = 1e-8,tol1 = 1e-16,tol2 = 1e-2) = (;tol0, tol1, tol2) defaultModel = model(); defaultSettings = settings(); @@ -947,12 +941,12 @@ defaultSettings = settings(); Now we can compute the actual policy using the LQ routine from QuantEcon.jl ```{code-cell} julia -@unpack a0, a1, β, γ, n = defaultModel -@unpack tol0, tol1, tol2 = defaultSettings +(;a0, a1, beta, gamma, n) = defaultModel +(;tol0, tol1, tol2) = defaultSettings -βs = [β^x for x = 0:n-1] +betas = [beta^x for x = 0:n-1] Alhs = I + zeros(4, 4); -Alhs[4, :] = [β * a0 / (2 * γ), -β * a1 / (2 * γ), -β * a1 / γ, β] # Euler equation coefficients +Alhs[4, :] = [beta * a0 / (2 * gamma), -beta * a1 / (2 * gamma), -beta * a1 / gamma, beta] # Euler equation coefficients Arhs = I + zeros(4, 4); Arhs[3, 4] = 1.; Alhsinv = inv(Alhs); @@ -960,8 +954,8 @@ Alhsinv = inv(Alhs); A = Alhsinv * Arhs; B = Alhsinv * [0, 1, 0, 0,]; R = [0 -a0/2 0 0; -a0/2 a1 a1/2 0; 0 a1/2 0 0; 0 0 0 0]; -Q = γ; -lq = QuantEcon.LQ(Q, R, A, B, bet=β); +Q = gamma; +lq = QuantEcon.LQ(Q, R, A, B, bet=beta); P, F, d = stationary_values(lq) P22 = P[4:end, 4:end]; @@ -970,17 +964,17 @@ P22inv = inv(P22); H_0_0 = -P22inv * P21; # simulate forward -π_leader = zeros(n); +pi_leader = zeros(n); z0 = [1, 1, 1]; x0 = H_0_0 * z0; y0 = vcat(z0, x0); Random.seed!(1) # for reproducibility yt, ut = compute_sequence(lq, y0, n); -π_matrix = R + F' * Q * F; +pi_matrix = R + F' * Q * F; for t in 1:n - π_leader[t] = -(yt[:, t]' * π_matrix * yt[:, t]); + pi_leader[t] = -(yt[:, t]' * pi_matrix * yt[:, t]); end println("Computed policy for Stackelberg leader: $F") @@ -1017,7 +1011,7 @@ We'll compute it two ways (they give identical answers -- just a check on coding and thinking) ```{code-cell} julia -v_leader_forward = sum(βs .* π_leader); +v_leader_forward = sum(betas .* pi_leader); v_leader_direct = -yt[:, 1]' * P * yt[:, 1]; println("v_leader_forward (forward sim) is $v_leader_forward") @@ -1034,7 +1028,7 @@ tags: [remove-cell] ```{code-cell} julia # manually check whether P is an approximate fixed point -P_next = (R + F' * Q * F + β * (A - B * F)' * P * (A - B * F)); +P_next = (R + F' * Q * F + beta * (A - B * F)' * P * (A - B * F)); all(P - P_next .< tol0) ``` @@ -1049,7 +1043,7 @@ tags: [remove-cell] # manually checks whether two different ways of computing the # value function give approximately the same answer v_expanded = -((y0' * R * y0 + ut[:, 1]' * Q * ut[:, 1] + - β * (y0' * (A - B * F)' * P * (A - B * F) * y0))); + beta * (y0' * (A - B * F)' * P * (A - B * F) * y0))); (v_leader_direct - v_expanded < tol0)[1, 1] ``` @@ -1102,14 +1096,14 @@ We check that the recursive **Big** $K$ **, little** $k$ formulation of the foll $\vec q_1$ that we computed when we solved the Stackelberg problem ```{code-cell} julia -Ã = I + zeros(5, 5); -Ã[1:4, 1:4] .= A - B * F; -R̃ = [0 0 0 0 -a0/2; 0 0 0 0 a1/2; 0 0 0 0 0; 0 0 0 0 0; -a0/2 a1/2 0 0 a1]; -Q̃ = Q; -B̃ = [0, 0, 0, 0, 1]; - -lq_tilde = QuantEcon.LQ(Q̃, R̃, Ã, B̃, bet=β); -P̃, F̃, d̃ = stationary_values(lq_tilde); +A_tilde = I + zeros(5, 5); +A_tilde[1:4, 1:4] .= A - B * F; +R_tilde = [0 0 0 0 -a0/2; 0 0 0 0 a1/2; 0 0 0 0 0; 0 0 0 0 0; -a0/2 a1/2 0 0 a1]; +Q_tilde = Q; +B_tilde = [0, 0, 0, 0, 1]; + +lq_tilde = QuantEcon.LQ(Q_tilde, R_tilde, A_tilde, B_tilde, bet=beta); +P_tilde, F_tilde, d_tilde = stationary_values(lq_tilde); y0_tilde = vcat(y0, y0[3]); yt_tilde = compute_sequence(lq_tilde, y0_tilde, n)[1]; ``` @@ -1159,7 +1153,7 @@ Can you spot what features of $\tilde F$ imply this? Hint: remember the components of $X_t$ ```{code-cell} julia -F̃ # policy function in the follower's problem +F_tilde # policy function in the follower's problem ``` ```{code-cell} julia @@ -1167,43 +1161,43 @@ P # value function in the Stackelberg problem ``` ```{code-cell} julia -P̃ # value function in the follower's problem +P_tilde # value function in the follower's problem ``` ```{code-cell} julia # manually check that P is an approximate fixed point -all((P - ((R + F' * Q * F) + β * (A - B * F)' * P * (A - B * F)) .< tol0)) +all((P - ((R + F' * Q * F) + beta * (A - B * F)' * P * (A - B * F)) .< tol0)) ``` ```{code-cell} julia --- tags: [remove-cell] --- -#test all((P - ((R + F' * Q * F) + β * (A - B * F)' * P * (A - B * F)) .< tol0)) +#test all((P - ((R + F' * Q * F) + beta * (A - B * F)' * P * (A - B * F)) .< tol0)) ``` ```{code-cell} julia # compute `P_guess` using `F_tilde_star` -F̃_star = -[0, 0, 0, 1, 0]'; +F_tilde_star = -[0, 0, 0, 1, 0]'; P_guess = zeros(5, 5); for i in 1:1000 - P_guess = ((R̃ + F̃_star' * Q̃ * F̃_star) + - β * (Ã - B̃ * F̃_star)' * P_guess - * (Ã - B̃ * F̃_star)); + P_guess = ((R_tilde + F_tilde_star' * Q_tilde * F_tilde_star) + + beta * (A_tilde - B_tilde * F_tilde_star)' * P_guess + * (A_tilde - B_tilde * F_tilde_star)); end ``` ```{code-cell} julia # value function in the follower's problem --(y0_tilde' * P̃ * y0_tilde)[1, 1] +-(y0_tilde' * P_tilde * y0_tilde)[1, 1] ``` ```{code-cell} julia --- tags: [remove-cell] --- -@test -(y0_tilde' * P̃ * y0_tilde)[1, 1] ≈ 112.65590740578173 +@test -(y0_tilde' * P_tilde * y0_tilde)[1, 1] ≈ 112.65590740578173 ``` ```{code-cell} julia @@ -1220,8 +1214,8 @@ tags: [remove-cell] ```{code-cell} julia # c policy using policy iteration algorithm -F_iter = (β * inv(Q + β * B̃' * P_guess * B̃) - * B̃' * P_guess * Ã); +F_iter = (beta * inv(Q + beta * B_tilde' * P_guess * B_tilde) + * B_tilde' * P_guess * A_tilde); P_iter = zeros(5, 5); dist_vec = zeros(5, 5); @@ -1229,22 +1223,22 @@ for i in 1:100 # compute P_iter dist_vec = similar(P_iter) for j in 1:1000 - P_iter = (R̃ + F_iter' * Q * F_iter) + β * - (Ã - B̃ * F_iter)' * P_iter * - (Ã - B̃ * F_iter); + P_iter = (R_tilde + F_iter' * Q * F_iter) + beta * + (A_tilde - B_tilde * F_iter)' * P_iter * + (A_tilde - B_tilde * F_iter); # update F_iter - F_iter = β * inv(Q + β * B̃' * P_iter * B̃) * - B̃' * P_iter * Ã; + F_iter = beta * inv(Q + beta * B_tilde' * P_iter * B_tilde) * + B_tilde' * P_iter * A_tilde; - dist_vec = P_iter - ((R̃ + F_iter' * Q * F_iter) + - β * (Ã - B̃ * F_iter)' * P_iter * - (Ã - B̃ * F_iter)); + dist_vec = P_iter - ((R_tilde + F_iter' * Q * F_iter) + + beta * (A_tilde - B_tilde * F_iter)' * P_iter * + (A_tilde - B_tilde * F_iter)); end end if maximum(abs.(dist_vec)) < 1e-8 - dist_vec2 = F_iter - (β * inv(Q + β * B̃' * P_iter * B̃) * B̃' * P_iter * Ã) + dist_vec2 = F_iter - (beta * inv(Q + beta * B_tilde' * P_iter * B_tilde) * B_tilde' * P_iter * A_tilde) if maximum(abs.(dist_vec2)) < 1e-8 @show F_iter else @@ -1260,7 +1254,7 @@ yt_tilde_star = zeros(n, 5); yt_tilde_star[1, :] = y0_tilde; for t in 1:n-1 - yt_tilde_star[t+1, :] = (Ã - B̃ * F̃_star) * yt_tilde_star[t, :]; + yt_tilde_star[t+1, :] = (A_tilde - B_tilde * F_tilde_star) * yt_tilde_star[t, :]; end plot([yt_tilde_star[:, 5], yt_tilde[3, :]], labels = [L"\tilde{q}" L"q"]) @@ -1317,13 +1311,13 @@ B1 = [0, 0, 1]; B2 = [0, 1, 0]; R1 = [0 0 -a0/2; 0 0 a1/2; -a0/2 a1/2 a1]; R2 = [0 -a0/2 0; -a0/2 a1 a1/2; 0 a1/2 0]; -Q1 = Q2 = γ; +Q1 = Q2 = gamma; S1 = S2 = W1 = W2 = M1 = M2 = 0.; # solve using nnash from QE F1, F2, P1, P2 = nnash(A, B1, B2, R1, R2, Q1, Q2, S1, S2, W1, W2, M1, M2, - beta = β, + beta = beta, tol = tol1); # simulate forward @@ -1370,11 +1364,11 @@ tags: [remove-cell] # compute values u1 = -F1 * z; u2 = -F2 * z; -π_1 = (p .* q1)' - γ * u1.^2; -π_2 = (p .* q2)' - γ * u2.^2; +pi_1 = (p .* q1)' - gamma * u1.^2; +pi_2 = (p .* q2)' - gamma * u2.^2; -v1_forward = π_1 * βs; -v2_forward = π_2 * βs; +v1_forward = pi_1 * betas; +v2_forward = pi_2 * betas; v1_direct = -z[:, 1]' * P1 * z[:, 1]; v2_direct = -z[:, 1]' * P2 * z[:, 1]; @@ -1395,8 +1389,8 @@ tags: [remove-cell] ```{code-cell} julia # sanity check -Λ_1 = A - B2 * F2; -lq1 = QuantEcon.LQ(Q1, R1, Λ_1, B1, bet = β); +Lambda_1 = A - B2 * F2; +lq1 = QuantEcon.LQ(Q1, R1, Lambda_1, B1, bet = beta); P1_ih, F1_ih, d = stationary_values(lq1); v2_direct_alt = -z[:, 1]' * P1_ih * z[:, 1] + d; @@ -1411,7 +1405,7 @@ vt_follower = zeros(n); for t in 1:n vt_MPE[t] = -z[:, t]' * P1 * z[:, t]; - vt_follower[t] = -yt_tilde[:, t]' * P̃ * yt_tilde[:, t]; + vt_follower[t] = -yt_tilde[:, t]' * P_tilde * yt_tilde[:, t]; end plot([vt_MPE, vt_leader, vt_follower], labels = ["MPE" "Stackelberg leader" "Stackelberg follower"], diff --git a/lectures/dynamic_programming_squared/lqramsey.md b/lectures/dynamic_programming_squared/lqramsey.md index d42e659e..3ba55490 100644 --- a/lectures/dynamic_programming_squared/lqramsey.md +++ b/lectures/dynamic_programming_squared/lqramsey.md @@ -599,7 +599,7 @@ struct DiscreteStochProcess{TF <: AbstractFloat} <: AbstractStochProcess end struct Economy{TF <: AbstractFloat, SP <: AbstractStochProcess} - β::TF + beta::TF Sg::Matrix{TF} Sd::Matrix{TF} Sb::Matrix{TF} @@ -613,7 +613,7 @@ function compute_exog_sequences(econ, x) g, d, b, s = [dropdims(S * x, dims = 1) for S in (Sg, Sd, Sb, Ss)] #= solve for Lagrange multiplier in the govt budget constraint - In fact we solve for ν = λ / (1 + 2*λ). Here ν is the + In fact we solve for ν = lambda / (1 + 2*lambda). Here ν is the solution to a quadratic equation a(ν^2 - ν) + b = 0 where a and b are expected discounted sums of quadratic forms of the state. =# Sm = Sb - Sd - Ss @@ -631,17 +631,17 @@ function compute_allocation(econ, Sm, ν, x, b) c = dropdims(Sc * x, dims = 1) l = dropdims(Sl * x, dims = 1) p = dropdims((Sb - Sc) * x, dims = 1) # Price without normalization - τ = 1 .- l ./ (b .- c) - rvn = l .* τ + tau = 1 .- l ./ (b .- c) + rvn = l .* tau - return Sc, Sl, c, l, p, τ, rvn + return Sc, Sl, c, l, p, tau, rvn end function compute_ν(a0, b0) disc = a0^2 - 4a0 * b0 - if disc ≥ 0 + if disc >= 0 ν = 0.5 *(a0 - sqrt(disc)) / a0 else println("There is no Ramsey equilibrium for these parameters.") @@ -658,17 +658,17 @@ function compute_ν(a0, b0) end -function compute_Π(B, R, rvn, g, ξ) - π = B[2:end] - R[1:end-1] .* B[1:end-1] - rvn[1:end-1] + g[1:end-1] - Π = cumsum(π .* ξ) - return π, Π +function compute_Pi(B, R, rvn, g,Xi) + pi = B[2:end] - R[1:end-1] .* B[1:end-1] - rvn[1:end-1] + g[1:end-1] + Pi = cumsum(pi .*Xi) + return pi, Pi end function compute_paths(econ::Economy{<:AbstractFloat, <:DiscreteStochProcess}, T) # simplify notation - @unpack β, Sg, Sd, Sb, Ss = econ - @unpack P, x_vals = econ.proc + (;beta, Sg, Sd, Sb, Ss) = econ + (;P, x_vals) = econ.proc mc = MarkovChain(P) state = simulate(mc, T, init=1) @@ -679,7 +679,7 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:DiscreteStochProcess}, T # compute a0, b0 ns = size(P, 1) - F = I - β.*P + F = I - beta.*P a0 = (F \ ((Sm * x_vals)'.^2))[1] ./ 2 H = ((Sb - Sd + Sg) * x_vals) .* ((Sg - Ss)*x_vals) b0 = (F \ H')[1] ./ 2 @@ -688,29 +688,27 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:DiscreteStochProcess}, T ν = compute_ν(a0, b0) # Solve for the allocation given ν and x - Sc, Sl, c, l, p, τ, rvn = compute_allocation(econ, Sm, ν, x, b) + Sc, Sl, c, l, p, tau, rvn = compute_allocation(econ, Sm, ν, x, b) # compute remaining variables H = ((Sb - Sc) * x_vals) .* ((Sl - Sg) * x_vals) - (Sl * x_vals).^2 temp = dropdims(F * H', dims = 2) B = temp[state] ./ p H = dropdims(P[state, :] * ((Sb - Sc) * x_vals)', dims = 2) - R = p ./ (β .* H) + R = p ./ (beta .* H) temp = dropdims(P[state, :] *((Sb - Sc) * x_vals)', dims = 2) - ξ = p[2:end] ./ temp[1:end-1] + Xi = p[2:end] ./ temp[1:end-1] - # compute π - π, Π = compute_Π(B, R, rvn, g, ξ) + # compute pi + pi, Pi = compute_Pi(B, R, rvn, g,Xi) - return (g = g, d = d, b = b, s = s, c = c, - l = l, p = p, τ = τ, rvn = rvn, B = B, - R = R, π = π, Π = Π, ξ = ξ) + return (;g, d, b, s, c, l, p, tau, rvn, B, R, pi, Pi, Xi) end function compute_paths(econ::Economy{<:AbstractFloat, <:ContStochProcess}, T) # simplify notation - @unpack β, Sg, Sd, Sb, Ss = econ - @unpack A, C = econ.proc + (;beta, Sg, Sd, Sb, Ss) = econ + (;A, C) = econ.proc # generate an initial condition x0 satisfying x0 = A x0 nx, nx = size(A) @@ -733,37 +731,34 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:ContStochProcess}, T) # compute a0 and b0 H = Sm'Sm - a0 = 0.5 * var_quadratic_sum(A, C, H, β, x0) + a0 = 0.5 * var_quadratic_sum(A, C, H, beta, x0) H = (Sb - Sd + Sg)'*(Sg + Ss) - b0 = 0.5 * var_quadratic_sum(A, C, H, β, x0) + b0 = 0.5 * var_quadratic_sum(A, C, H, beta, x0) # compute lagrange multiplier ν = compute_ν(a0, b0) # solve for the allocation given ν and x - Sc, Sl, c, l, p, τ, rvn = compute_allocation(econ, Sm, ν, x, b) + Sc, Sl, c, l, p, tau, rvn = compute_allocation(econ, Sm, ν, x, b) # compute remaining variables H = Sl'Sl - (Sb - Sc)' *(Sl - Sg) L = zeros(T) for t in eachindex(L) - L[t] = var_quadratic_sum(A, C, H, β, x[:, t]) + L[t] = var_quadratic_sum(A, C, H, beta, x[:, t]) end B = L ./ p - Rinv = dropdims(β .* (Sb- Sc)*A*x, dims = 1) ./ p + Rinv = dropdims(beta .* (Sb- Sc)*A*x, dims = 1) ./ p R = 1 ./ Rinv AF1 = (Sb - Sc) * x[:, 2:end] AF2 = (Sb - Sc) * A * x[:, 1:end-1] - ξ = AF1 ./ AF2 - ξ = dropdims(ξ, dims = 1) + Xi = AF1 ./ AF2 + Xi = dropdims(Xi, dims = 1) - # compute π - π, Π = compute_Π(B, R, rvn, g, ξ) + # compute pi + pi, Pi = compute_Pi(B, R, rvn, g,Xi) - return (g = g, d = d, b = b, s = s, - c = c, l = l, p = p, τ = τ, - rvn = rvn, B = B, R = R, - π = π, Π = Π, ξ = ξ) + return(;g, d, b, s, c, l, p, tau, rvn, B, R, pi, Pi, Xi) end function gen_fig_1(path) @@ -784,7 +779,7 @@ function gen_fig_1(path) plt_4 = plot(path.rvn, lw=2, label=L"\tau_t l_t") plot!(plt_4, path.g, lw=2, label=L"g_t") - plot!(plt_4, path.π, lw=2, label=L"\pi_t") + plot!(plt_4, path.pi, lw=2, label=L"\pi_t") plot!(plt_4, xlabel="Time", grid=true) plot(plt_1, plt_2, plt_3, plt_4, layout=(2,2), size = (800,600)) @@ -794,7 +789,7 @@ function gen_fig_2(path) T = length(path.c) - paths = [path.ξ, path.Π] + paths = [path.Xi, path.Pi] labels = [L"\xi_t", L"\Pi_t"] plt_1 = plot() plt_2 = plot() @@ -847,17 +842,17 @@ using Random Random.seed!(42) # parameters -β = 1 / 1.05 -ρ, mg = .7, .35 -A = [ρ mg*(1 - ρ); 0.0 1.0] -C = [sqrt(1 - ρ^2) * mg / 10 0.0; 0 0] +beta = 1 / 1.05 +rho, mg = .7, .35 +A = [rho mg*(1 - rho); 0.0 1.0] +C = [sqrt(1 - rho^2) * mg / 10 0.0; 0 0] Sg = [1.0 0.0] Sd = [0.0 0.0] Sb = [0 2.135] Ss = [0.0 0.0] proc = ContStochProcess(A, C) -econ = Economy(β, Sg, Sd, Sb, Ss, proc) +econ = Economy(beta, Sg, Sd, Sb, Ss, proc) T = 50 path = compute_paths(econ, T) @@ -874,10 +869,10 @@ tags: [remove-cell] #test path.c[36] ≈ 0.6291101011610297 atol = 1e-3 #test path.B[9] ≈ 0.07442403655989423 atol = 1e-3 #test path.rvn[27] ≈ 0.35013269833342753 atol = 1e-3 - #test path.π[31] ≈ -0.05846215388377568 atol = 1e-3 + #test path.pi[31] ≈ -0.05846215388377568 atol = 1e-3 #test path.R[43] ≈ 1.0437715852385672 atol = 1e-3 - #test path.ξ[43] ≈ 1.001895202392805 atol = 1e-3 - #test path.Π[43] ≈ -0.4185282208457552 atol = 1e-3 # plot tests + #test path.xi[43] ≈ 1.001895202392805 atol = 1e-3 + #test path.Pi[43] ≈ -0.4185282208457552 atol = 1e-3 # plot tests end ``` @@ -911,7 +906,7 @@ Random.seed!(42); ```{code-cell} julia # Parameters -β = 1 / 1.05 +beta = 1 / 1.05 P = [0.8 0.2 0.0 0.0 0.5 0.5 0.0 0.0 1.0] @@ -929,7 +924,7 @@ Sb = [0.0 0.0 1.0 0.0 0.0] Ss = [0.0 0.0 0.0 1.0 0.0] proc = DiscreteStochProcess(P, x_vals) -econ = Economy(β, Sg, Sd, Sb, Ss, proc) +econ = Economy(beta, Sg, Sd, Sb, Ss, proc) T = 15 path = compute_paths(econ, T) @@ -949,7 +944,7 @@ tags: [remove-cell] #test path.c[2] ≈ 0.6147870853305598 #@test path.R ≈ [1.05, 1.05, 1.05, 1.05, 1.05, 1.0930974212983846, 1.05, 1.05, 1.05, 1.05, # 1.05, 1.05, 1.05, 1.05, 1.05] - #@test path.ξ ≈ [1.0, 1.0, 1.0, 1.0, 1.0, 0.9589548368586813, 1.0, 1.0, 1.0, 1.0, 1.0, + #@test path.xi ≈ [1.0, 1.0, 1.0, 1.0, 1.0, 0.9589548368586813, 1.0, 1.0, 1.0, 1.0, 1.0, # 1.0, 1.0, 1.0] end ``` @@ -997,21 +992,21 @@ Random.seed!(42); tags: [hide-output] --- # parameters -β = 1 / 1.05 -ρ, mg = .95, .35 -A = [0. 0. 0. ρ mg*(1-ρ); +beta = 1 / 1.05 +rho, mg = .95, .35 +A = [0. 0. 0. rho mg*(1-rho); 1. 0. 0. 0. 0.; 0. 1. 0. 0. 0.; 0. 0. 1. 0. 0.; 0. 0. 0. 0. 1.] C = zeros(5, 5) -C[1, 1] = sqrt(1 - ρ^2) * mg / 8 +C[1, 1] = sqrt(1 - rho^2) * mg / 8 Sg = [1. 0. 0. 0. 0.] Sd = [0. 0. 0. 0. 0.] Sb = [0. 0. 0. 0. 2.135] Ss = [0. 0. 0. 0. 0.] proc = ContStochProcess(A, C) -econ = Economy(β, Sg, Sd, Sb, Ss, proc) +econ = Economy(beta, Sg, Sd, Sb, Ss, proc) T = 50 path = compute_paths(econ, T) @@ -1028,7 +1023,7 @@ tags: [remove-cell] #test path.rvn[7] ≈ 0.35146870025913474 #test path.c[2] ≈ 0.6259521929536346 #test path.R[5][1] ≈ 1.0501742289013196 - #test path.ξ[10] ≈ 1.002202281639002 + #test path.xi[10] ≈ 1.002202281639002 end ``` diff --git a/lectures/dynamic_programming_squared/opt_tax_recur.md b/lectures/dynamic_programming_squared/opt_tax_recur.md index 2a6aea2e..449f412a 100644 --- a/lectures/dynamic_programming_squared/opt_tax_recur.md +++ b/lectures/dynamic_programming_squared/opt_tax_recur.md @@ -726,10 +726,10 @@ import QuantEcon: simulate mutable struct Model{TF <: AbstractFloat, TM <: AbstractMatrix{TF}, TV <: AbstractVector{TF}} - β::TF - Π::TM + beta::TF + Pi::TM G::TV - Θ::TV + Theta::TV transfers::Bool U::Function Uc::Function @@ -747,31 +747,31 @@ import QuantEcon: simulate S::TI cFB::TV nFB::TV - ΞFB::TV + XiFB::TV zFB::TV end function SequentialAllocation(model) - β, Π, G, Θ = model.β, model.Π, model.G, model.Θ - mc = MarkovChain(Π) - S = size(Π, 1) # Number of states + beta, Pi, G, Theta = model.beta, model.Pi, model.G, model.Theta + mc = MarkovChain(Pi) + S = size(Pi, 1) # Number of states # now find the first best allocation - cFB, nFB, ΞFB, zFB = find_first_best(model, S, 1) + cFB, nFB, XiFB, zFB = find_first_best(model, S, 1) - return SequentialAllocation(model, mc, S, cFB, nFB, ΞFB, zFB) + return SequentialAllocation(model, mc, S, cFB, nFB, XiFB, zFB) end function find_first_best(model, S, version) if version != 1 && version != 2 throw(ArgumentError("version must be 1 or 2")) end - β, Θ, Uc, Un, G, Π = - model.β, model.Θ, model.Uc, model.Un, model.G, model.Π + beta, Theta, Uc, Un, G, Pi = + model.beta, model.Theta, model.Uc, model.Un, model.G, model.Pi function res!(out, z) c = z[1:S] n = z[S+1:end] - out[1:S] = Θ .* Uc(c, n) + Un(c, n) - out[S+1:end] = Θ .* n - c - G + out[1:S] = Theta .* Uc(c, n) + Un(c, n) + out[S+1:end] = Theta .* n - c - G end res = nlsolve(res!, 0.5 * ones(2 * S)) @@ -782,31 +782,31 @@ function find_first_best(model, S, version) if version == 1 cFB = res.zero[1:S] nFB = res.zero[S+1:end] - ΞFB = Uc(cFB, nFB) # Multiplier on the resource constraint - zFB = vcat(cFB, nFB, ΞFB) - return cFB, nFB, ΞFB, zFB + XiFB = Uc(cFB, nFB) # Multiplier on the resource constraint + zFB = vcat(cFB, nFB, XiFB) + return cFB, nFB, XiFB, zFB elseif version == 2 cFB = res.zero[1:S] nFB = res.zero[S+1:end] IFB = Uc(cFB, nFB) .* cFB + Un(cFB, nFB) .* nFB - xFB = \(I - β * Π, IFB) + xFB = \(I - beta * Pi, IFB) zFB = [vcat(cFB[s], xFB[s], xFB) for s in 1:S] return cFB, nFB, IFB, xFB, zFB end end -function time1_allocation(pas::SequentialAllocation, μ) +function time1_allocation(pas::SequentialAllocation, mu) model, S = pas.model, pas.S - Θ, β, Π, G, Uc, Ucc, Un, Unn = - model.Θ, model.β, model.Π, model.G, + Theta, beta, Pi, G, Uc, Ucc, Un, Unn = + model.Theta, model.beta, model.Pi, model.G, model.Uc, model.Ucc, model.Un, model.Unn function FOC!(out, z) c = z[1:S] n = z[S+1:2S] - Ξ = z[2S+1:end] - out[1:S] = Uc(c, n) .- μ * (Ucc(c, n) .* c .+ Uc(c, n)) .- Ξ # FOC c - out[S+1:2S] = Un(c, n) .- μ * (Unn(c, n) .* n .+ Un(c, n)) + Θ .* Ξ # FOC n - out[2S+1:end] = Θ .* n - c - G # Resource constraint + Xi = z[2S+1:end] + out[1:S] = Uc(c, n) .- mu * (Ucc(c, n) .* c .+ Uc(c, n)) .- Xi # FOC c + out[S+1:2S] = Un(c, n) .- mu * (Unn(c, n) .* n .+ Un(c, n)) + Theta .* Xi # FOC n + out[2S+1:end] = Theta .* n - c - G # Resource constraint return out end # Find the root of the FOC @@ -815,56 +815,56 @@ function time1_allocation(pas::SequentialAllocation, μ) error("Could not find LS allocation.") end z = res.zero - c, n, Ξ = z[1:S], z[S+1:2S], z[2S+1:end] + c, n, Xi = z[1:S], z[S+1:2S], z[2S+1:end] # Now compute x Inv = Uc(c, n) .* c + Un(c, n) .* n - x = \(I - β * model.Π, Inv) - return c, n, x, Ξ + x = \(I - beta * model.Pi, Inv) + return c, n, x, Xi end function time0_allocation(pas::SequentialAllocation, B_, s_0) model = pas.model - Π, Θ, G, β = model.Π, model.Θ, model.G, model.β + Pi, Theta, G, beta = model.Pi, model.Theta, model.G, model.beta Uc, Ucc, Un, Unn = model.Uc, model.Ucc, model.Un, model.Unn # First order conditions of planner's problem function FOC!(out, z) - μ, c, n, Ξ = z[1], z[2], z[3], z[4] - xprime = time1_allocation(pas, μ)[3] + mu, c, n, Xi = z[1], z[2], z[3], z[4] + xprime = time1_allocation(pas, mu)[3] out .= vcat( - Uc(c, n) .* (c - B_) .+ Un(c, n) .* n + β * dot(Π[s_0, :], xprime), - Uc(c, n) .- μ * (Ucc(c, n) .* (c - B_) + Uc(c, n)) - Ξ, - Un(c, n) .- μ * (Unn(c, n) .* n .+ Un(c, n)) + Θ[s_0] .* Ξ, - (Θ .* n .- c - G)[s_0] + Uc(c, n) .* (c - B_) .+ Un(c, n) .* n + beta * dot(Pi[s_0, :], xprime), + Uc(c, n) .- mu * (Ucc(c, n) .* (c - B_) + Uc(c, n)) - Xi, + Un(c, n) .- mu * (Unn(c, n) .* n .+ Un(c, n)) + Theta[s_0] .* Xi, + (Theta .* n .- c - G)[s_0] ) end # Find root - res = nlsolve(FOC!, [0.0, pas.cFB[s_0], pas.nFB[s_0], pas.ΞFB[s_0]]) + res = nlsolve(FOC!, [0.0, pas.cFB[s_0], pas.nFB[s_0], pas.XiFB[s_0]]) if res.f_converged == false error("Could not find time 0 LS allocation.") end return (res.zero...,) end -function time1_value(pas::SequentialAllocation, μ) +function time1_value(pas::SequentialAllocation, mu) model = pas.model - c, n, x, Ξ = time1_allocation(pas, μ) + c, n, x, Xi = time1_allocation(pas, mu) U_val = model.U.(c, n) - V = \(I - model.β*model.Π, U_val) + V = \(I - model.beta*model.Pi, U_val) return c, n, x, V end function Τ(model, c, n) Uc, Un = model.Uc.(c, n), model.Un.(c, n) - return 1 .+ Un ./ (model.Θ .* Uc) + return 1 .+ Un ./ (model.Theta .* Uc) end function simulate(pas::SequentialAllocation, B_, s_0, T, sHist = nothing) model = pas.model - Π, β, Uc = model.Π, model.β, model.Uc + Pi, beta, Uc = model.Pi, model.beta, model.Uc if isnothing(sHist) sHist = QuantEcon.simulate(pas.mc, T, init=s_0) @@ -873,25 +873,25 @@ function simulate(pas::SequentialAllocation, B_, s_0, T, sHist = nothing) nHist = similar(cHist) Bhist = similar(cHist) ΤHist = similar(cHist) - μHist = similar(cHist) + muHist = similar(cHist) RHist = zeros(T-1) # time 0 - μ, cHist[1], nHist[1], _ = time0_allocation(pas, B_, s_0) + mu, cHist[1], nHist[1], _ = time0_allocation(pas, B_, s_0) ΤHist[1] = Τ(pas.model, cHist[1], nHist[1])[s_0] Bhist[1] = B_ - μHist[1] = μ + muHist[1] = mu # time 1 onward for t in 2:T - c, n, x, Ξ = time1_allocation(pas,μ) + c, n, x, Xi = time1_allocation(pas,mu) u_c = Uc(c,n) s = sHist[t] ΤHist[t] = Τ(pas.model, c, n)[s] - Eu_c = dot(Π[sHist[t-1],:], u_c) + Eu_c = dot(Pi[sHist[t-1],:], u_c) cHist[t], nHist[t], Bhist[t] = c[s], n[s], x[s] / u_c[s] - RHist[t-1] = Uc(cHist[t-1], nHist[t-1]) / (β * Eu_c) - μHist[t] = μ + RHist[t-1] = Uc(cHist[t-1], nHist[t-1]) / (beta * Eu_c) + muHist[t] = mu end - return cHist, nHist, Bhist, ΤHist, sHist, μHist, RHist + return cHist, nHist, Bhist, ΤHist, sHist, muHist, RHist end mutable struct BellmanEquation{TP <: Model, @@ -911,7 +911,7 @@ end end function BellmanEquation(model, xgrid, policies0) - S = size(model.Π, 1) # Number of states + S = size(model.Pi, 1) # Number of states xbar = collect(extrema(xgrid)) time_0 = false cf, nf, xprimef = policies0 @@ -924,19 +924,19 @@ end function get_policies_time1(T, i_x, x, s, Vf) model, S = T.model, T.S - β, Θ, G, Π = model.β, model.Θ, model.G, model.Π + beta, Theta, G, Pi = model.beta, model.Theta, model.G, model.Pi U, Uc, Un = model.U, model.Uc, model.Un function objf(z, grad) c, xprime = z[1], z[2:end] n = c + G[s] Vprime = [Vf[sprime](xprime[sprime]) for sprime in 1:S] - return -(U(c, n) + β * dot(Π[s, :], Vprime)) + return -(U(c, n) + beta * dot(Pi[s, :], Vprime)) end function cons(z, grad) c, xprime = z[1], z[2:end] n = c+G[s] - return x - Uc(c, n) * c - Un(c, n) * n - β * dot(Π[s, :], xprime) + return x - Uc(c, n) * c - Un(c, n) * n - beta * dot(Pi[s, :], xprime) end lb = vcat(0, T.xbar[1] * ones(S)) ub = vcat(1 - G[s], T.xbar[2] * ones(S)) @@ -962,18 +962,18 @@ end function get_policies_time0(T, B_, s0, Vf) model, S = T.model, T.S - β, Θ, G, Π = model.β, model.Θ, model.G, model.Π + beta, Theta, G, Pi = model.beta, model.Theta, model.G, model.Pi U, Uc, Un = model.U, model.Uc, model.Un function objf(z, grad) c, xprime = z[1], z[2:end] n = c + G[s0] Vprime = [Vf[sprime](xprime[sprime]) for sprime in 1:S] - return -(U(c, n) + β * dot(Π[s0, :], Vprime)) + return -(U(c, n) + beta * dot(Pi[s0, :], Vprime)) end function cons(z, grad) c, xprime = z[1], z[2:end] n = c + G[s0] - return -Uc(c, n) * (c - B_) - Un(c, n) * n - β * dot(Π[s0, :], xprime) + return -Uc(c, n) * (c - B_) - Un(c, n) * n - beta * dot(Pi[s0, :], xprime) end lb = vcat(0, T.xbar[1] * ones(S)) ub = vcat(1-G[s0], T.xbar[2] * ones(S)) @@ -1295,41 +1295,41 @@ The above steps are implemented in a type called RecursiveAllocation --- tags: [output_scroll] --- - struct RecursiveAllocation{TP <: Model, TI <: Integer, +struct RecursiveAllocation{TP <: Model, TI <: Integer, TVg <: AbstractVector, TVv <: AbstractVector, TVp <: AbstractArray} model::TP mc::MarkovChain S::TI T::BellmanEquation - μgrid::TVg + mugrid::TVg xgrid::TVg Vf::TVv policies::TVp end -function RecursiveAllocation(model, μgrid) - mc = MarkovChain(model.Π) +function RecursiveAllocation(model, mugrid) + mc = MarkovChain(model.Pi) G = model.G - S = size(model.Π, 1) # Number of states + S = size(model.Pi, 1) # Number of states # Now find the first best allocation - Vf, policies, T, xgrid = solve_time1_bellman(model, μgrid) + Vf, policies, T, xgrid = solve_time1_bellman(model, mugrid) T.time_0 = true # Bellman equation now solves time 0 problem - return RecursiveAllocation(model, mc, S, T, μgrid, xgrid, Vf, policies) + return RecursiveAllocation(model, mc, S, T, mugrid, xgrid, Vf, policies) end -function solve_time1_bellman(model, μgrid) - μgrid0 = μgrid - S = size(model.Π, 1) +function solve_time1_bellman(model, mugrid) + mugrid0 = mugrid + S = size(model.Pi, 1) # First get initial fit PP = SequentialAllocation(model) - c = zeros(length(μgrid), 2) + c = zeros(length(mugrid), 2) n = similar(c) x = similar(c) V = similar(c) - for (i, μ) in enumerate(μgrid0) - c[i, :], n[i, :], x[i, :], V[i, :] = time1_value(PP, μ) + for (i, mu) in enumerate(mugrid0) + c[i, :], n[i, :], x[i, :], V[i, :] = time1_value(PP, mu) end Vf = Vector{AbstractInterpolation}(undef, 2) cf = similar(Vf) @@ -1346,7 +1346,7 @@ function solve_time1_bellman(model, μgrid) policies = [cf, nf, xprimef] # Create xgrid xbar = [maximum(minimum(x, dims = 1)), minimum(maximum(x, dims = 1))] - xgrid = range(xbar[1], xbar[2], length = length(μgrid0)) + xgrid = range(xbar[1], xbar[2], length = length(mugrid0)) # Now iterate on bellman equation T = BellmanEquation(model, xgrid, policies) diff = 1.0 @@ -1410,19 +1410,19 @@ end function simulate(pab::RecursiveAllocation, B_, s_0, T, sHist = QuantEcon.simulate(mc, s_0, T)) model, S, policies = pab.model, pab.S, pab.policies - β, Π, Uc = model.β, model.Π, model.Uc + beta, Pi, Uc = model.beta, model.Pi, model.Uc cf, nf, xprimef = policies[1], policies[2], policies[3] cHist = zeros(T) nHist = similar(cHist) Bhist = similar(cHist) ΤHist = similar(cHist) - μHist = similar(cHist) + muHist = similar(cHist) RHist = zeros(T - 1) # time 0 cHist[1], nHist[1], xprime = time0_allocation(pab, B_, s_0) ΤHist[1] = Τ(pab.model, cHist[1], nHist[1])[s_0] Bhist[1] = B_ - μHist[1] = 0.0 + muHist[1] = 0.0 # time 1 onward for t in 2:T s, x = sHist[t], xprime[sHist[t]] @@ -1431,12 +1431,12 @@ function simulate(pab::RecursiveAllocation, B_, s_0, T, xprime = [xprimef[s, sprime](x) for sprime in 1:S] ΤHist[t] = Τ(pab.model, c, n)[s] u_c = Uc(c, n) - Eu_c = dot(Π[sHist[t-1], :], u_c) - μHist[t] = pab.Vf[s](x) - RHist[t-1] = Uc(cHist[t-1], nHist[t-1]) / (β * Eu_c) + Eu_c = dot(Pi[sHist[t-1], :], u_c) + muHist[t] = pab.Vf[s](x) + RHist[t-1] = Uc(cHist[t-1], nHist[t-1]) / (beta * Eu_c) cHist[t], nHist[t], Bhist[t] = c[s], n, x / u_c[s] end - return cHist, nHist, Bhist, ΤHist, sHist, μHist, RHist + return cHist, nHist, Bhist, ΤHist, sHist, muHist, RHist end ``` @@ -1490,29 +1490,29 @@ This utility function is implemented in the type CRRAutility ```{code-cell} julia function crra_utility(; - β = 0.9, - σ = 2.0, - γ = 2.0, - Π = 0.5 * ones(2, 2), + beta = 0.9, + sigma = 2.0, + gamma = 2.0, + Pi = 0.5 * ones(2, 2), G = [0.1, 0.2], - Θ = ones(2), + Theta = ones(2), transfers = false ) function U(c, n) - if σ == 1.0 + if sigma == 1.0 U = log(c) else - U = (c.^(1.0 .- σ) .- 1.0) / (1.0 - σ) + U = (c.^(1.0 .- sigma) .- 1.0) / (1.0 - sigma) end - return U .- n.^(1 + γ) / (1 + γ) + return U .- n.^(1 + gamma) / (1 + gamma) end # Derivatives of utility function - Uc(c,n) = c.^(-σ) - Ucc(c,n) = -σ * c.^(-σ - 1.0) - Un(c,n) = -n.^γ - Unn(c,n) = -γ * n.^(γ - 1.0) + Uc(c,n) = c.^(-sigma) + Ucc(c,n) = -sigma * c.^(-sigma - 1.0) + Un(c,n) = -n.^gamma + Unn(c,n) = -gamma * n.^(gamma - 1.0) n_less_than_one = false - return Model(β, Π, G, Θ, transfers, + return Model(beta, Pi, G, Theta, transfers, U, Uc, Ucc, Un, Unn, n_less_than_one) end ``` @@ -1529,9 +1529,9 @@ using Random Random.seed!(42) # For reproducible results. M_time_example = crra_utility(G=[0.1, 0.1, 0.1, 0.2, 0.1, 0.1], - Θ=ones(6)) # Θ can in principle be random + Theta=ones(6)) # Theta can in principle be random -M_time_example.Π = [0.0 1.0 0.0 0.0 0.0 0.0; +M_time_example.Pi = [0.0 1.0 0.0 0.0 0.0 0.0; 0.0 0.0 1.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.5 0.5 0.0; 0.0 0.0 0.0 0.0 0.0 1.0; @@ -1556,9 +1556,9 @@ titles = hcat("Consumption", "Output") sim_seq_l_plot = [sim_seq_l[1:4]..., M_time_example.G[sHist_l], - M_time_example.Θ[sHist_l].*sim_seq_l[2]] + M_time_example.Theta[sHist_l].*sim_seq_l[2]] sim_seq_h_plot = [sim_seq_h[1:4]..., M_time_example.G[sHist_h], - M_time_example.Θ[sHist_h].*sim_seq_h[2]] + M_time_example.Theta[sHist_h].*sim_seq_h[2]] #plots = plot(layout=(3,2), size=(800,600)) @@ -1579,7 +1579,7 @@ tags: [remove-cell] --- @testset begin @test M_time_example.G[sHist_l] ≈ [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] - #test M_time_example.Θ[sHist_l] .* sim_seq_l[2] ≈ [1.026385289423105, 0.9945696863679917, + #test M_time_example.Theta[sHist_l] .* sim_seq_l[2] ≈ [1.026385289423105, 0.9945696863679917, # 0.9945696863679917, 0.9945696863679917, # 0.9945696863679917, 0.9945696863679917, # 0.9945696863679917] @@ -1701,7 +1701,7 @@ Random.seed!(42); # For reproducible results. ``` ```{code-cell} julia -M2 = crra_utility(G=[0.15], Π=ones(1, 1), Θ=[1.0]) +M2 = crra_utility(G=[0.15], Pi=ones(1, 1), Theta=[1.0]) PP_seq_time0 = SequentialAllocation(M2) # solve sequential problem @@ -1819,20 +1819,20 @@ $$ We will write a new constructor LogUtility to represent this utility function ```{code-cell} julia -function log_utility(;β = 0.9, - ψ = 0.69, - Π = 0.5 * ones(2, 2), +function log_utility(;beta = 0.9, + psi = 0.69, + Pi = 0.5 * ones(2, 2), G = [0.1, 0.2], - Θ = ones(2), + Theta = ones(2), transfers = false) # Derivatives of utility function - U(c,n) = log(c) + ψ * log(1 - n) + U(c,n) = log(c) + psi * log(1 - n) Uc(c,n) = 1 ./ c Ucc(c,n) = -c.^(-2.0) - Un(c,n) = -ψ ./ (1.0 .- n) - Unn(c,n) = -ψ ./ (1.0 .- n).^2.0 + Un(c,n) = -psi ./ (1.0 .- n) + Unn(c,n) = -psi ./ (1.0 .- n).^2.0 n_less_than_one = true - return Model(β, Π, G, Θ, transfers, + return Model(beta, Pi, G, Theta, transfers, U, Uc, Ucc, Un, Unn, n_less_than_one) end ``` @@ -1853,9 +1853,9 @@ Random.seed!(42); # For reproducible results. ```{code-cell} julia M1 = log_utility() -μ_grid = range(-0.6, 0.0, length = 200) +mu_grid = range(-0.6, 0.0, length = 200) PP_seq = SequentialAllocation(M1) # Solve sequential problem -PP_bel = RecursiveAllocation(M1, μ_grid) # Solve recursive problem +PP_bel = RecursiveAllocation(M1, mu_grid) # Solve recursive problem T = 20 sHist = [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1] @@ -1865,8 +1865,8 @@ sim_seq = simulate(PP_seq, 0.5, 1, T, sHist) sim_bel = simulate(PP_bel, 0.5, 1, T, sHist) # Plot policies -sim_seq_plot = [sim_seq[1:4]..., M1.G[sHist], M1.Θ[sHist].*sim_seq[2]] -sim_bel_plot = [sim_bel[1:4]..., M1.G[sHist], M1.Θ[sHist].*sim_bel[2]] +sim_seq_plot = [sim_seq[1:4]..., M1.G[sHist], M1.Theta[sHist].*sim_seq[2]] +sim_bel_plot = [sim_bel[1:4]..., M1.G[sHist], M1.Theta[sHist].*sim_bel[2]] titles = hcat("Consumption", "Labor Supply", From cb7d0919caf36da4498adaedf39b4a3b01ad6fc7 Mon Sep 17 00:00:00 2001 From: annabellasd Date: Tue, 10 Oct 2023 18:24:39 -0800 Subject: [PATCH 08/26] updating merge continous time files last --- lectures/continuous_time/covid_sde.md | 126 ++++++++++++------------- lectures/continuous_time/seir_model.md | 82 ++++++++-------- 2 files changed, 101 insertions(+), 107 deletions(-) diff --git a/lectures/continuous_time/covid_sde.md b/lectures/continuous_time/covid_sde.md index 15d148d1..5de74e98 100644 --- a/lectures/continuous_time/covid_sde.md +++ b/lectures/continuous_time/covid_sde.md @@ -230,41 +230,40 @@ First, construct our $F$ from {eq}`dfcvsde` and $G$ from {eq}`dG` ```{code-cell} julia function F(x, p, t) - s, i, r, d, R_0, delta = x - (;gamma, R_bar_0, eta, sigma, xi, theta, delta_bar) = p - - return [-gamma * R_0 * s * i; # ds/dt - gamma * R_0 * s * i - gamma * i; # di/dt - (1 - delta) * gamma * i; # dr/dt - delta * gamma * i; # dd/dt - eta * (R_bar_0(t, p) - R_0); # dR_0/dt - theta * (delta_bar - delta); # ddelta/dt - ] + s, i, r, d, R₀, δ = x + (;γ, R̄₀, η, σ, ξ, θ, δ_bar) = p + + return [-γ*R₀*s*i; # ds/dt + γ*R₀*s*i - γ*i; # di/dt + (1-δ)*γ*i; # dr/dt + δ*γ*i; # dd/dt + η*(R̄₀(t, p) - R₀);# dR₀/dt + θ*(δ_bar - δ); # dδ/dt + ] end function G(x, p, t) - s, i, r, d, R_0, delta = x - (;gamma, R_bar_0, eta, sigma, xi, theta, delta_bar) = p + s, i, r, d, R₀, δ = x + (;γ, R̄₀, η, σ, ξ, θ, δ_bar) = p - return [0; 0; 0; 0; sigma * sqrt(R_0); xi * sqrt(delta * (1 - delta))] + return [0; 0; 0; 0; σ*sqrt(R₀); ξ*sqrt(δ * (1-δ))] end ``` Next create a settings generator, and then define a [SDEProblem](https://docs.sciml.ai/stable/tutorials/sde_example/#Example-2:-Systems-of-SDEs-with-Diagonal-Noise-1) with Diagonal Noise. ```{code-cell} julia -p_gen(;T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, - R_0_n = 1.6, R_bar_0 = (t, p) -> p.R_0_n, delta_bar = 0.01, - sigma = 0.03, xi = 0.004, theta = 0.2, N = 3.3E8) = (;T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N) - -p = p_gen() # use all defaults +p_gen = @with_kw (T = 550.0, γ = 1.0 / 18, η = 1.0 / 20, + R₀_n = 1.6, R̄₀ = (t, p) -> p.R₀_n, δ_bar = 0.01, + σ = 0.03, ξ = 0.004, θ = 0.2, N = 3.3E8) +p = p_gen() # use all defaults i_0 = 25000 / p.N r_0 = 0.0 d_0 = 0.0 s_0 = 1.0 - i_0 - r_0 - d_0 -R_bar_0_0 = 0.5 # starting in lockdown -delta_0 = p.delta_bar -x_0 = [s_0, i_0, r_0, d_0, R_bar_0_0, delta_0] +R̄₀_0 = 0.5 # starting in lockdown +δ_0 = p.δ_bar +x_0 = [s_0, i_0, r_0, d_0, R̄₀_0, δ_0] prob = SDEProblem(F, G, x_0, (0, p.T), p) ``` @@ -371,29 +370,29 @@ We will shut down the shocks to the mortality rate (i.e. $\xi = 0$) to focus on Consider $\eta = 1/50$ and $\eta = 1/20$, where we start at the same initial condition of $R_0(0) = 0.5$. ```{code-cell} julia -function generate_eta_experiment(eta; p_gen = p_gen, trajectories = 100, saveat = 1.0, x_0 = x_0, T = 120.0) - p = p_gen(eta = eta, xi = 0.0) +function generate_η_experiment(η; p_gen = p_gen, trajectories = 100, + saveat = 1.0, x_0 = x_0, T = 120.0) + p = p_gen(η = η, ξ = 0.0) ensembleprob = EnsembleProblem(SDEProblem(F, G, x_0, (0, T), p)) - sol = solve(ensembleprob, SOSRI(), EnsembleThreads(), trajectories = trajectories, saveat = saveat) + sol = solve(ensembleprob, SOSRI(), EnsembleThreads(), + trajectories = trajectories, saveat = saveat) return EnsembleSummary(sol) end # Evaluate two different lockdown scenarios -eta_1 = 1 / 50 -eta_2 = 1 / 20 -summ_1 = generate_eta_experiment(eta_1) -summ_2 = generate_eta_experiment(eta_2) - -plot(summ_1, idxs = (4, 5), +η_1 = 1/50 +η_2 = 1/20 +summ_1 = generate_η_experiment(η_1) +summ_2 = generate_η_experiment(η_2) +plot(summ_1, idxs = (4,5), title = ["Proportion Dead" L"R_0"], ylabel = [L"d(t)" L"R_0(t)"], xlabel = L"t", - legend = :topleft, - labels = L"Middle 95% Quantile, $\eta = %$eta_1$", + legend = [:topleft :bottomright], + labels = L"Middle 95% Quantile, $\eta = %$η_1$", layout = (2, 1), size = (900, 900), fillalpha = 0.5) - -plot!(summ_2, idxs = (4, 5), - legend = :topleft, - labels = L"Middle 95% Quantile, $\eta = %$eta_2$", size = (900, 900), fillalpha = 0.5) +plot!(summ_2, idxs = (4,5), + legend = [:topleft :bottomright], + labels = L"Middle 95% Quantile, $\eta = %$η_2$", size = (900, 900), fillalpha = 0.5) ``` While the the mean of the $d(t)$ increases, unsurprisingly, we see that the 95% quantile for later time periods is also much larger - even after the $R_0$ has converged. @@ -412,24 +411,24 @@ Since empirical estimates of $R_0(t)$ discussed in {cite}`NBERw27128` and other We start the model with 100,000 active infections. ```{code-cell} julia -R_0_L = 0.5 # lockdown -eta_experiment = 1.0 / 10 -sigma_experiment = 0.04 +R₀_L = 0.5 # lockdown +η_experiment = 1.0/10 +σ_experiment = 0.04 +R̄₀_lift_early(t, p) = t < 30.0 ? R₀_L : 2.0 +R̄₀_lift_late(t, p) = t < 120.0 ? R₀_L : 2.0 -R_bar_0_lift_early(t, p) = t < 30.0 ? R_0_L : 2.0 -R_bar_0_lift_late(t, p) = t < 120.0 ? R_0_L : 2.0 +p_early = p_gen(R̄₀ = R̄₀_lift_early, η = η_experiment, σ = σ_experiment) +p_late = p_gen(R̄₀ = R̄₀_lift_late, η = η_experiment, σ = σ_experiment) -p_early = p_gen(R_bar_0 = R_bar_0_lift_early, eta = eta_experiment, sigma = sigma_experiment) -p_late = p_gen(R_bar_0 = R_bar_0_lift_late, eta = eta_experiment, sigma = sigma_experiment) # initial conditions i_0 = 100000 / p_early.N r_0 = 0.0 d_0 = 0.0 s_0 = 1.0 - i_0 - r_0 - d_0 -delta_0 = p_early.delta_bar +δ_0 = p_early.δ_bar -x_0 = [s_0, i_0, r_0, d_0, R_0_L, delta_0] # start in lockdown +x_0 = [s_0, i_0, r_0, d_0, R₀_L, δ_0] # start in lockdown prob_early = SDEProblem(F, G, x_0, (0, p_early.T), p_early) prob_late = SDEProblem(F, G, x_0, (0, p_late.T), p_late) ``` @@ -439,13 +438,13 @@ Simulating for a single realization of the shocks, we see the results are qualit ```{code-cell} julia sol_early = solve(prob_early, SOSRI()) sol_late = solve(prob_late, SOSRI()) -plot(sol_early, vars = [5, 1, 2, 4], +plot(sol_early, vars = [5, 1,2,4], title = [L"R_0" "Susceptible" "Infected" "Dead"], layout = (2, 2), size = (900, 600), ylabel = [L"R_0(t)" L"s(t)" L"i(t)" L"d(t)"], xlabel = L"t", legend = [:bottomright :topright :topright :topleft], label = ["Early" "Early" "Early" "Early"]) -plot!(sol_late, vars = [5, 1, 2, 4], +plot!(sol_late, vars = [5, 1,2,4], legend = [:bottomright :topright :topright :topleft], label = ["Late" "Late" "Late" "Late"], xlabel = L"t") ``` @@ -536,26 +535,24 @@ We will redo the "Ending Lockdown" simulation from above, where the only differe ```{code-cell} julia function F_reinfect(x, p, t) - s, i, r, d, R_0, delta = x - (;gamma, R_bar_0, eta, sigma, xi, theta, delta_bar, nu) = p - - return [ - -gamma * R_0 * s * i + nu * r; # ds/dt - gamma * R_0 * s * i - gamma * i; # di/dt - (1 - delta) * gamma * i - nu * r; # dr/dt - delta * gamma * i; # dd/dt - eta * (R_bar_0(t, p) - R_0); # dR_0/dt - theta * (delta_bar - delta); # ddelta/dt - ] + s, i, r, d, R₀, δ = x + (;γ, R̄₀, η, σ, ξ, θ, δ_bar, ν) = p + + return [-γ*R₀*s*i + ν*r; # ds/dt + γ*R₀*s*i - γ*i; # di/dt + (1-δ)*γ*i - ν*r # dr/dt + δ*γ*i; # dd/dt + η*(R̄₀(t, p) - R₀);# dR₀/dt + θ*(δ_bar - δ); # dδ/dt + ] end -p_re_gen(;T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, - R_0_n = 1.6, R_bar_0 = (t, p) -> p.R_0_n, - delta_bar = 0.01, sigma = 0.03, xi = 0.004, theta = 0.2, - N = 3.3E8, nu = 1/360) = (;T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N, nu) +p_re_gen = @with_kw ( T = 550.0, γ = 1.0 / 18, η = 1.0 / 20, + R₀_n = 1.6, R̄₀ = (t, p) -> p.R₀_n, + δ_bar = 0.01, σ = 0.03, ξ = 0.004, θ = 0.2, N = 3.3E8, ν = 1/360) -p_re_early = p_re_gen(R_bar_0 = R_bar_0_lift_early, eta = eta_experiment, sigma = sigma_experiment) -p_re_late = p_re_gen(R_bar_0 = R_bar_0_lift_late, eta = eta_experiment, sigma = sigma_experiment) +p_re_early = p_re_gen(R̄₀ = R̄₀_lift_early, η = η_experiment, σ = σ_experiment) +p_re_late = p_re_gen(R̄₀ = R̄₀_lift_late, η = η_experiment, σ = σ_experiment) trajectories = 400 saveat = 1.0 @@ -608,4 +605,3 @@ In this case, there are significant differences between the early and late death This bleak simulation has assumed that no individuals has long-term immunity and that there will be no medical advancements on that time horizon - both of which are unlikely to be true. Nevertheless, it suggests that the timing of lifting lockdown has a more profound impact after 18 months if we allow stochastic shocks imperfect immunity. - diff --git a/lectures/continuous_time/seir_model.md b/lectures/continuous_time/seir_model.md index 06606dd7..021af008 100644 --- a/lectures/continuous_time/seir_model.md +++ b/lectures/continuous_time/seir_model.md @@ -171,13 +171,13 @@ We begin by implementing a simple version of this model with a constant $R_0$ an First, define the system of equations ```{code-cell} julia -function F_simple(x, p, t; gamma = 1/18, R_0 = 3.0, sigma = 1/5.2) +function F_simple(x, p, t; γ = 1/18, R₀ = 3.0, σ = 1/5.2) s, e, i, r = x - return [-gamma * R_0 * s * i; # ds/dt - gamma * R_0 * s * i - sigma * e; # de/dt - sigma * e - gamma * i; # di/dt - gamma * i; # dr/dt + return [-γ*R₀*s*i; # ds/dt = -γR₀si + γ*R₀*s*i - σ*e;# de/dt = γR₀si -σe + σ*e - γ*i; # di/dt = σe -γi + γ*i; # dr/dt = γi ] end ``` @@ -195,7 +195,7 @@ tspan = (0.0, 350.0) # ≈ 350 days prob = ODEProblem(F_simple, x_0, tspan) ``` -With this, choose an ODE algorithm and solve the initial value problem. A good default algorithm for non-stiff ODEs of this sort might be `Tsit5()`, which is the Tsitouras 5/4 Runge-Kutta method. +With this, choose an ODE algorithm and solve the initial value problem. A good default algorithm for non-stiff ODEs of this sort might be `Tsit5()`, which is the Tsitouras 5/4 Runge-Kutta method). ```{code-cell} julia sol = solve(prob, Tsit5()) @@ -242,7 +242,7 @@ While we could integrate the deaths given the solution to the model ex-post, it This is a common trick when solving systems of ODEs. While equivalent in principle to using the appropriate quadrature scheme, this becomes especially convenient when adaptive time-stepping algorithms are used to solve the ODEs (i.e. there is not a regular time grid). Note that when doing so, $d(0) = \int_0^0 \delta \gamma i(\tau) d \tau = 0$ is the initial condition. -The system {eq}`seir_system` and the supplemental equations can be written in vector form $x := [s, e, i, r, R_0, c, d]$ with parameter tuple $p := (\sigma, \gamma, \eta, \delta, \bar{R}_0(\cdot))$ +The system {eq}`seir_system` and the supplemental equations can be written in vector form $x := [s, e, i, r, R₀, c, d]$ with parameter tuple $p := (\sigma, \gamma, \eta, \delta, \bar{R}_0(\cdot))$ Note that in those parameters, the targeted reproduction number, $\bar{R}_0(t)$, is an exogenous function. @@ -289,36 +289,35 @@ First, construct our $F$ from {eq}`dfcv` ```{code-cell} julia function F(x, p, t) - s, e, i, r, R_0, c, d = x - (;sigma, gamma, R_bar_0, eta, delta) = p - - return [-gamma * R_0 * s * i; # ds/dt - gamma * R_0 * s * i - sigma * e; # de/dt - sigma * e - gamma * i; # di/dt - gamma * i; # dr/dt - eta * (R_bar_0(t, p) - R_0); # dR_0/dt - sigma * e; # dc/dt - delta * gamma * i; # dd/dt + s, e, i, r, R₀, c, d = x + (;σ, γ, R̄₀, η, δ) = p + + return [-γ*R₀*s*i; # ds/dt + γ*R₀*s*i - σ*e; # de/dt + σ*e - γ*i; # di/dt + γ*i; # dr/dt + η*(R̄₀(t, p) - R₀);# dR₀/dt + σ*e; # dc/dt + δ*γ*i; # dd/dt ] end; - ``` This function takes the vector `x` of states in the system and extracts the fixed parameters passed into the `p` object. -The only confusing part of the notation is the `R_bar_0(t, p)` which evaluates the `p.R_bar_0` at this time (and also allows it to depend on the `p` parameter). +The only confusing part of the notation is the `R̄₀(t, p)` which evaluates the `p.R̄₀` at this time (and also allows it to depend on the `p` parameter). ### Parameters -#####HERE ENDED + The baseline parameters are put into a named tuple generator (see previous lectures using [Parameters.jl](https://github.com/mauro3/Parameters.jl)) with default values discussed above. ```{code-cell} julia -p_gen(;T = 550.0, gamma = 1.0 / 18, sigma = 1 / 5.2, eta = 1.0 / 20, - R_0_n = 1.6, delta = 0.01, N = 3.3E8, - R_bar_0 = (t, p) -> p.R_0_n) = (;T, gamma, sigma, eta, R_0_n, delta, N, R_bar_0) +p_gen = @with_kw ( T = 550.0, γ = 1.0 / 18, σ = 1 / 5.2, η = 1.0 / 20, + R₀_n = 1.6, δ = 0.01, N = 3.3E8, + R̄₀ = (t, p) -> p.R₀_n); ``` -Note that the default $\bar{R}_0(t)$ function always equals $R_{0n}$ -- a parameterizable natural level of $R_0$ used only by the `R_bar_0` function +Note that the default $\bar{R}_0(t)$ function always equals $R_{0n}$ -- a parameterizable natural level of $R_0$ used only by the `R̄₀` function Setting initial conditions, we choose a fixed $s, i, e, r$, as well as $R_0(0) = R_{0n}$ and $m(0) = 0.01$ @@ -329,7 +328,7 @@ i_0 = 1E-7 e_0 = 4.0 * i_0 s_0 = 1.0 - i_0 - e_0 -x_0 = [s_0, e_0, i_0, 0.0, p.R_0_n, 0.0, 0.0] +x_0 = [s_0, e_0, i_0, 0.0, p.R₀_n, 0.0, 0.0] tspan = (0.0, p.T) prob = ODEProblem(F, x_0, tspan, p) ``` @@ -373,9 +372,9 @@ Let's start with the case where $\bar{R}_0(t) = R_{0n}$ is constant. We calculate the time path of infected people under different assumptions of $R_{0n}$: ```{code-cell} julia -R_0_n_vals = range(1.6, 3.0, length = 6) -sols = [solve(ODEProblem(F, x_0, tspan, p_gen(R_0_n = R_0_n)), - Tsit5(), saveat=0.5) for R_0_n in R_0_n_vals]; +R₀_n_vals = range(1.6, 3.0, length = 6) +sols = [solve(ODEProblem(F, x_0, tspan, p_gen(R₀_n = R₀_n)), + Tsit5(), saveat=0.5) for R₀_n in R₀_n_vals]; ``` Here we chose `saveat=0.5` to get solutions that were evenly spaced every `0.5`. @@ -385,7 +384,7 @@ Changing the saved points is just a question of storage/interpolation, and does Let's plot current cases as a fraction of the population. ```{code-cell} julia -labels = permutedims([L"R_0 = %$r" for r in R_0_n_vals]) +labels = permutedims([L"R_0 = %$r" for r in R₀_n_vals]) infecteds = [sol[3,:] for sol in sols] plot(infecteds, label=labels, legend=:topleft, lw = 2, xlabel = L"t", ylabel = L"i(t)", title = "Current Cases") @@ -414,21 +413,21 @@ In the simple case, where $\bar{R}_0(t) = R_{0n}$ is independent of the state, t We will examine the case where $R_0(0) = 3$ and then it falls to $R_{0n} = 1.6$ due to the progressive adoption of stricter mitigation measures. -The parameter `eta` controls the rate, or the speed at which restrictions are +The parameter `η` controls the rate, or the speed at which restrictions are imposed. We consider several different rates: ```{code-cell} julia -eta_vals = [1/5, 1/10, 1/20, 1/50, 1/100] -labels = permutedims([L"\eta = %$eta" for eta in eta_vals]); +η_vals = [1/5, 1/10, 1/20, 1/50, 1/100] +labels = permutedims([L"\eta = %$η" for η in η_vals]); ``` Let's calculate the time path of infected people, current cases, and mortality ```{code-cell} julia x_0 = [s_0, e_0, i_0, 0.0, 3.0, 0.0, 0.0] -sols = [solve(ODEProblem(F, x_0, tspan, p_gen(eta=eta)), Tsit5(), saveat=0.5) for eta in eta_vals]; +sols = [solve(ODEProblem(F, x_0, tspan, p_gen(η=η)), Tsit5(), saveat=0.5) for η in η_vals]; ``` Next, plot the $R_0$ over time: @@ -469,11 +468,11 @@ The parameters considered here start the model with 25,000 active infections and 75,000 agents already exposed to the virus and thus soon to be contagious. ```{code-cell} julia -R_0_L = 0.5 # lockdown -R_bar_0_lift_early(t, p) = t < 30.0 ? R_0_L : 2.0 -R_bar_0_lift_late(t, p) = t < 120.0 ? R_0_L : 2.0 -p_early = p_gen(R_bar_0 = R_bar_0_lift_early, eta = 10.0) -p_late = p_gen(R_bar_0 = R_bar_0_lift_late, eta = 10.0) +R₀_L = 0.5 # lockdown +R̄₀_lift_early(t, p) = t < 30.0 ? R₀_L : 2.0 +R̄₀_lift_late(t, p) = t < 120.0 ? R₀_L : 2.0 +p_early = p_gen(R̄₀= R̄₀_lift_early, η = 10.0) +p_late = p_gen(R̄₀= R̄₀_lift_late, η = 10.0) # initial conditions @@ -481,9 +480,9 @@ i_0 = 25000 / p_early.N e_0 = 75000 / p_early.N s_0 = 1.0 - i_0 - e_0 -x_0 = [s_0, e_0, i_0, 0.0, R_0_L, 0.0, 0.0] # start in lockdown +x_0 = [s_0, e_0, i_0, 0.0, R₀_L, 0.0, 0.0] # start in lockdown -# create two problems, with rapid movement of R_0(t) towards R_bar_0(t) +# create two problems, with rapid movement of R₀(t) towards R̄₀(t) prob_early = ODEProblem(F, x_0, tspan, p_early) prob_late = ODEProblem(F, x_0, tspan, p_late) ``` @@ -502,7 +501,7 @@ plot!(sol_late, vars = [7], label = "Lift Late", xlabel = L"t") Next we examine the daily deaths, $\frac{d D(t)}{dt} = N \delta \gamma i(t)$. ```{code-cell} julia -flow_deaths(sol, p) = p.N * p.delta * p.gamma * sol[3,:] +flow_deaths(sol, p) = p.N * p.δ * p.γ * sol[3,:] plot(sol_early.t, flow_deaths(sol_early, p_early), title = "Flow Deaths", label = "Lift Early") plot!(sol_late.t, flow_deaths(sol_late, p_late), label = "Lift Late", xlabel = L"t") @@ -518,4 +517,3 @@ Despite its richness, the model above is fully deterministic. The policy $\bar{ One way that randomness can lead to aggregate fluctuations is the granularity that comes through the discreteness of individuals. This topic, the connection between SDEs and the Langevin equations typically used in the approximation of chemical reactions in well-mixed media is explored in further lectures on continuous time Markov chains. Instead, in the {doc}`next lecture `, we will concentrate on randomness that comes from aggregate changes in behavior or policy. - From 90480b0137162f57b15fbd8844ebb6f06962f652 Mon Sep 17 00:00:00 2001 From: annabellasd Date: Mon, 6 Nov 2023 15:26:19 -0800 Subject: [PATCH 09/26] Updated with Trang's Comments --- lectures/dynamic_programming_squared/amss.md | 10 ++-- .../dynamic_programming_squared/dyn_stack.md | 7 ++- .../dynamic_programming_squared/lqramsey.md | 55 +++++++++---------- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/lectures/dynamic_programming_squared/amss.md b/lectures/dynamic_programming_squared/amss.md index 971a52c6..8656283f 100644 --- a/lectures/dynamic_programming_squared/amss.md +++ b/lectures/dynamic_programming_squared/amss.md @@ -542,7 +542,7 @@ function time1_value(pas::SequentialAllocation, mu::Real) end -function Τ(model::Model, c::Union{Real,Vector}, n::Union{Real,Vector}) +function T(model::Model, c::Union{Real,Vector}, n::Union{Real,Vector}) Uc, Un = model.Uc.(c, n), model.Un.(c, n) return 1. .+ Un./(model.Theta .* Uc) end @@ -562,12 +562,12 @@ function simulate(pas::SequentialAllocation, cHist = zeros(T) nHist = zeros(T) Bhist = zeros(T) - ΤHist = zeros(T) + THist = zeros(T) muHist = zeros(T) RHist = zeros(T-1) # time 0 mu, cHist[1], nHist[1], _ = time0_allocation(pas, B_, s_0) - ΤHist[1] = Τ(pas.model, cHist[1], nHist[1])[s_0] + THist[1] = T(pas.model, cHist[1], nHist[1])[s_0] Bhist[1] = B_ muHist[1] = mu # time 1 onward @@ -575,13 +575,13 @@ function simulate(pas::SequentialAllocation, c, n, x, Xi = time1_allocation(pas,mu) u_c = Uc(c,n) s = sHist[t] - ΤHist[t] = Τ(pas.model, c, n)[s] + THist[t] = T(pas.model, c, n)[s] Eu_c = dot(Pi[sHist[t-1],:], u_c) cHist[t], nHist[t], Bhist[t] = c[s], n[s], x[s] / u_c[s] RHist[t-1] = Uc(cHist[t-1], nHist[t-1]) / (beta * Eu_c) muHist[t] = mu end - return cHist, nHist, Bhist, ΤHist, sHist, muHist, RHist + return cHist, nHist, Bhist, THist, sHist, muHist, RHist end diff --git a/lectures/dynamic_programming_squared/dyn_stack.md b/lectures/dynamic_programming_squared/dyn_stack.md index 1496434b..8380fb20 100644 --- a/lectures/dynamic_programming_squared/dyn_stack.md +++ b/lectures/dynamic_programming_squared/dyn_stack.md @@ -929,7 +929,7 @@ We define named tuples and default values for the model and solver settings, and instantiate one copy of each ```{code-cell} julia -model(;a0 = 10, a1 = 2, beta = 0.96, gamma = 120., n = 300) = (; a0, a1, beta, gamma, n) +model(;a0 = 10, a1 = 2, beta = 0.96, gamma = 120., n = 300) = (; a0, a1, beta, gamma, n) # things like tolerances, etc. settings(;tol0 = 1e-8,tol1 = 1e-16,tol2 = 1e-2) = (;tol0, tol1, tol2) @@ -1166,7 +1166,7 @@ P_tilde # value function in the follower's problem ```{code-cell} julia # manually check that P is an approximate fixed point -all((P - ((R + F' * Q * F) + beta * (A - B * F)' * P * (A - B * F)) .< tol0)) +all((P - ((R + F' * Q * F) + beta * (A - B * F)' * P * (A - B * F)) .< tol0)) ``` ```{code-cell} julia @@ -1410,7 +1410,8 @@ end plot([vt_MPE, vt_leader, vt_follower], labels = ["MPE" "Stackelberg leader" "Stackelberg follower"], title = "MPE vs Stackelberg Values", - xlabel = L"t") + xlabel = L"t", + legend = :outertopright) ``` ```{code-cell} julia diff --git a/lectures/dynamic_programming_squared/lqramsey.md b/lectures/dynamic_programming_squared/lqramsey.md index 3ba55490..efb4269d 100644 --- a/lectures/dynamic_programming_squared/lqramsey.md +++ b/lectures/dynamic_programming_squared/lqramsey.md @@ -613,8 +613,8 @@ function compute_exog_sequences(econ, x) g, d, b, s = [dropdims(S * x, dims = 1) for S in (Sg, Sd, Sb, Ss)] #= solve for Lagrange multiplier in the govt budget constraint - In fact we solve for ν = lambda / (1 + 2*lambda). Here ν is the - solution to a quadratic equation a(ν^2 - ν) + b = 0 where + In fact we solve for nu = lambda / (1 + 2*lambda). Here nu is the + solution to a quadratic equation a(nu^2 - nu) + b = 0 where a and b are expected discounted sums of quadratic forms of the state. =# Sm = Sb - Sd - Ss @@ -622,12 +622,11 @@ function compute_exog_sequences(econ, x) end -function compute_allocation(econ, Sm, ν, x, b) - Sg, Sd, Sb, Ss = econ.Sg, econ.Sd, econ.Sb, econ.Ss - - # solve for the allocation given ν and x - Sc = 0.5 .* (Sb + Sd - Sg - ν .* Sm) - Sl = 0.5 .* (Sb - Sd + Sg - ν .* Sm) +function compute_allocation(econ, Sm, nu, x, b) + (;Sg, Sd, Sb, Ss) = econ + # solve for the allocation given nu and x + Sc = 0.5 .* (Sb + Sd - Sg - nu .* Sm) + Sl = 0.5 .* (Sb - Sd + Sg - nu .* Sm) c = dropdims(Sc * x, dims = 1) l = dropdims(Sl * x, dims = 1) p = dropdims((Sb - Sc) * x, dims = 1) # Price without normalization @@ -638,29 +637,29 @@ function compute_allocation(econ, Sm, ν, x, b) end -function compute_ν(a0, b0) +function compute_nu(a0, b0) disc = a0^2 - 4a0 * b0 if disc >= 0 - ν = 0.5 *(a0 - sqrt(disc)) / a0 + nu = 0.5 *(a0 - sqrt(disc)) / a0 else println("There is no Ramsey equilibrium for these parameters.") error("Government spending (economy.g) too low") end # Test that the Lagrange multiplier has the right sign - if ν * (0.5 - ν) < 0 + if nu * (0.5 - nu) < 0 print("Negative multiplier on the government budget constraint.") error("Government spending (economy.g) too low") end - return ν + return nu end -function compute_Pi(B, R, rvn, g,Xi) +function compute_Pi(B, R, rvn, g,xi) pi = B[2:end] - R[1:end-1] .* B[1:end-1] - rvn[1:end-1] + g[1:end-1] - Pi = cumsum(pi .*Xi) + Pi = cumsum(pi .*xi) return pi, Pi end @@ -685,10 +684,10 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:DiscreteStochProcess}, T b0 = (F \ H')[1] ./ 2 # compute lagrange multiplier - ν = compute_ν(a0, b0) + nu = compute_nu(a0, b0) - # Solve for the allocation given ν and x - Sc, Sl, c, l, p, tau, rvn = compute_allocation(econ, Sm, ν, x, b) + # Solve for the allocation given nu and x + Sc, Sl, c, l, p, tau, rvn = compute_allocation(econ, Sm, nu, x, b) # compute remaining variables H = ((Sb - Sc) * x_vals) .* ((Sl - Sg) * x_vals) - (Sl * x_vals).^2 @@ -697,12 +696,12 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:DiscreteStochProcess}, T H = dropdims(P[state, :] * ((Sb - Sc) * x_vals)', dims = 2) R = p ./ (beta .* H) temp = dropdims(P[state, :] *((Sb - Sc) * x_vals)', dims = 2) - Xi = p[2:end] ./ temp[1:end-1] + xi = p[2:end] ./ temp[1:end-1] # compute pi - pi, Pi = compute_Pi(B, R, rvn, g,Xi) + pi, Pi = compute_Pi(B, R, rvn, g, xi) - return (;g, d, b, s, c, l, p, tau, rvn, B, R, pi, Pi, Xi) + return (;g, d, b, s, c, l, p, tau, rvn, B, R, pi, Pi, xi) end function compute_paths(econ::Economy{<:AbstractFloat, <:ContStochProcess}, T) @@ -736,10 +735,10 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:ContStochProcess}, T) b0 = 0.5 * var_quadratic_sum(A, C, H, beta, x0) # compute lagrange multiplier - ν = compute_ν(a0, b0) + nu = compute_nu(a0, b0) - # solve for the allocation given ν and x - Sc, Sl, c, l, p, tau, rvn = compute_allocation(econ, Sm, ν, x, b) + # solve for the allocation given nu and x + Sc, Sl, c, l, p, tau, rvn = compute_allocation(econ, Sm, nu, x, b) # compute remaining variables H = Sl'Sl - (Sb - Sc)' *(Sl - Sg) @@ -752,13 +751,13 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:ContStochProcess}, T) R = 1 ./ Rinv AF1 = (Sb - Sc) * x[:, 2:end] AF2 = (Sb - Sc) * A * x[:, 1:end-1] - Xi = AF1 ./ AF2 - Xi = dropdims(Xi, dims = 1) + xi = AF1 ./ AF2 + xi = dropdims(xi, dims = 1) # compute pi - pi, Pi = compute_Pi(B, R, rvn, g,Xi) + pi, Pi = compute_Pi(B, R, rvn, g, xi) - return(;g, d, b, s, c, l, p, tau, rvn, B, R, pi, Pi, Xi) + return(;g, d, b, s, c, l, p, tau, rvn, B, R, pi, Pi, xi) end function gen_fig_1(path) @@ -789,7 +788,7 @@ function gen_fig_2(path) T = length(path.c) - paths = [path.Xi, path.Pi] + paths = [path.xi, path.Pi] labels = [L"\xi_t", L"\Pi_t"] plt_1 = plot() plt_2 = plot() From cb0970ec0b47a0ece4442c92c04e1b19f5690f54 Mon Sep 17 00:00:00 2001 From: annabellasd Date: Thu, 9 Nov 2023 09:21:23 -0800 Subject: [PATCH 10/26] double Tau functions fixed --- lectures/dynamic_programming_squared/amss.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lectures/dynamic_programming_squared/amss.md b/lectures/dynamic_programming_squared/amss.md index 8656283f..3eb04880 100644 --- a/lectures/dynamic_programming_squared/amss.md +++ b/lectures/dynamic_programming_squared/amss.md @@ -542,7 +542,7 @@ function time1_value(pas::SequentialAllocation, mu::Real) end -function T(model::Model, c::Union{Real,Vector}, n::Union{Real,Vector}) +function Omega(model::Model, c::Union{Real,Vector}, n::Union{Real,Vector}) Uc, Un = model.Uc.(c, n), model.Un.(c, n) return 1. .+ Un./(model.Theta .* Uc) end @@ -562,12 +562,12 @@ function simulate(pas::SequentialAllocation, cHist = zeros(T) nHist = zeros(T) Bhist = zeros(T) - THist = zeros(T) + OmegaHist = zeros(T) muHist = zeros(T) RHist = zeros(T-1) # time 0 mu, cHist[1], nHist[1], _ = time0_allocation(pas, B_, s_0) - THist[1] = T(pas.model, cHist[1], nHist[1])[s_0] + OmegaHist[1] = Omega(pas.model, cHist[1], nHist[1])[s_0] Bhist[1] = B_ muHist[1] = mu # time 1 onward @@ -575,13 +575,13 @@ function simulate(pas::SequentialAllocation, c, n, x, Xi = time1_allocation(pas,mu) u_c = Uc(c,n) s = sHist[t] - THist[t] = T(pas.model, c, n)[s] + OmegaHist[t] = Omega(pas.model, c, n)[s] Eu_c = dot(Pi[sHist[t-1],:], u_c) cHist[t], nHist[t], Bhist[t] = c[s], n[s], x[s] / u_c[s] RHist[t-1] = Uc(cHist[t-1], nHist[t-1]) / (beta * Eu_c) muHist[t] = mu end - return cHist, nHist, Bhist, THist, sHist, muHist, RHist + return cHist, nHist, Bhist, OmegaHist, sHist, muHist, RHist end From dc8565f4250e7cfc324e34cef486462195708c36 Mon Sep 17 00:00:00 2001 From: mmcky Date: Wed, 20 Dec 2023 16:27:54 +1100 Subject: [PATCH 11/26] MAINT: run cache monthly to avoid stale cache --- .github/workflows/cache.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/cache.yml b/.github/workflows/cache.yml index c2b500b5..ffe4987a 100644 --- a/.github/workflows/cache.yml +++ b/.github/workflows/cache.yml @@ -3,6 +3,9 @@ on: push: branches: - main + schedule: + # Run monthly to avoid stale cache + - cron: '0 0 1 * *' jobs: cache: runs-on: ubuntu-latest From 51842d12be5fae727ce97d35a4501def09eb78ae Mon Sep 17 00:00:00 2001 From: mmcky Date: Sat, 30 Dec 2023 14:16:44 +1100 Subject: [PATCH 12/26] MAINT: Upgrade quantecon-book-theme and python=3.11 (#281) * MAINT: Upgrade quantecon-book-theme and python=3.11 * upgrade to quantecon-book-theme==0.7.1 * add transparent logo for dark mode * adjust author information for new theme --- .github/workflows/cache.yml | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/publish.yml | 2 +- lectures/_config.yml | 8 ++++++++ lectures/_static/quantecon-logo-transparent.png | Bin 0 -> 50790 bytes lectures/intro.md | 2 +- requirements.txt | 2 +- 7 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 lectures/_static/quantecon-logo-transparent.png diff --git a/.github/workflows/cache.yml b/.github/workflows/cache.yml index ffe4987a..8446fc4b 100644 --- a/.github/workflows/cache.yml +++ b/.github/workflows/cache.yml @@ -15,7 +15,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.9 + python-version: 3.11 - name: Install Python Dependencies run: | pip install -r requirements.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 02f21aba..c500be5e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.9 + python-version: 3.11 - name: Install Python Dependencies run: | pip install -r requirements.txt diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4168e38f..89d80144 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -13,7 +13,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.9 + python-version: 3.11 - name: Install Python Dependencies run: | pip install -r requirements.txt diff --git a/lectures/_config.yml b/lectures/_config.yml index 2298f5f0..966d57d6 100644 --- a/lectures/_config.yml +++ b/lectures/_config.yml @@ -56,6 +56,14 @@ sphinx: html_theme: quantecon_book_theme html_static_path: ['_static'] html_theme_options: + authors: + - name: Jesse Perla + url: https://www.jesseperla.com + - name: Thomas J. Sargent + url: http://www.tomsargent.com/ + - name: John Stachurski + url: https://johnstachurski.net/ + dark_logo: quantecon-logo-transparent.png header_organisation_url: https://quantecon.org header_organisation: QuantEcon repository_url: https://github.com/quantecon/lecture-julia.myst diff --git a/lectures/_static/quantecon-logo-transparent.png b/lectures/_static/quantecon-logo-transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..e9ead46c4e0d229ddd015e28e4382aafda3737c8 GIT binary patch literal 50790 zcmeFa1yogS+Bd#IR6s(MQlwQ-x}^~bmF|%4?h-h(B8`P2(xQZvq{N{FRHVC0x;qZ> zzc;A!%(ve8{`0=;ooBw8aj)g^>~rqC?yIlgJ_O0jO5$Q)#D*XU_s(rGMF_&$grL*O zn5V!er%T5J!GBnGw>2Cg=*)Te9~$)PH7NvPteY#VJE_Y^^BLM&GwU1K8W=OXS=)iu z5F{Y%W~XmxY3xL0U~Fn`BS^DUT0ui)ZX`&f#wEilV|UBg%>1^ygRzpktg@lIr6I2o zjj#}vfEynez}nbJpUTbJ%Epn;O_1hjTt4s~{+NY^>Zpm6r6A2sctR?58F{K(whqQr zyv%G&hODe?R6M-Q`ZtU?dAK+@c^RqLS=l*QSUFhOIhfcu_*l94IJu~PTr^-p2O|?c zMKOsV(}6od8Z##+J3bZ`S65eNR}N-d2U8X{US3`nR(2M4b|%n*$??98lfE01jU(;P z5yXrg4IRwwoXl-)sNfOx4Q!pA1Zluxk9T2h_iI=i#~+jeG-Gkow_{;rW`%ck)X>QA zS35gr2dksWjSN|gt&FXWZJZoITee?q?aXYQY#q&P|Hjb2zW%ET0Ci<#e$DY;uEpB= z*A$LU;x1qtKM3+)wsus$Z)eP+XzXa~>|kgt?gExc3-88`@0NqHzLTwkvaPMv&$E*M zxnwGKPG%k|dKrB~a~pUQ*Z$DOSWMr^Sda!jHzqb#CJt6*b~Zj%Rz7xC23GjZaZ?#v zBXg7c|7BBlK90X`3i!rI-%0=fx3Q5SpNXx5wLaLgxwXEjF^ipzDGk*xLh{|RwX$^p z6NA-p9IZk|hVPDzqm#akq46CtK^m}YW^;2RK4UIcLt{g3LncEu4lX86R$c=p10#Jl zCT?CHZeCs{^v;EoM=)c)t&cPgrm%i2icpO;hV5Z=^ZSDw;>;4a! zP%^gv@y^Pe>WB~c^bKMD7NjwR57yX-=Euk8|6>Xq59?}X3Zrt4quWF{1k)Xa~5B zs@!-ZEK>G`Dw(-_hGbf1G&|$X!z=obv(&i*x{X8**;N+ z+IL6TA_J$8OJA(G$&QpO{NnR4BlOn|#20}0b#s0B4pR@XuKi@+En5bXxsl<9t z|GJ^B7W(xblVB6==Z(mt9Q>c}A<^GcK)(qE{pKhL`Yjg_^jm>I&~Hr(LH{Uwp+tLR zd3@|OD<*b(yOBkf;sX;eg!cwNNdWsaqWi-du_{_lcHx}q=O)Df?ccM;jh*~yv3_f+ z-7a9;Gvjx`rjyxRI(?25j9D~N}crurzL7TInacJ;=s80W#iumU`GSL@* zxDtEsoXI9l*XE`qydxZ?rXJ!C9hey;Ll7&)Pu*VZlj%{2Q@UkCxi3f@5tlCwL8KSt zR?v^Q9lZPwpZ{-8=@Fsrcm;PpXXceIz9bv`Na-~;IJ%sh5`=q9Lc269kjV3CnDy*% zZ4TdQjYXZYL?Dj88(Cc@Wcf+xfBTHzQIM!-MKN4q&RyqtIQ9`g&~*sa|LN2bulgKH zz)8-^=}SFDtX~}~oTfu3j+yxI>2EFiJE052geS( z(2ww$Ev*F;AwSJM@6!og5Rct-xUy9FEYR`&ktvS@=KlOjHd@Wxw|QJ0t$D zcJ}{mT%kavl|&pB zCXG3BZ^M$2HSt0>^dJ9J5sVCfRsa=QIjv=UoT`I6w^08rryNvkeAxIuxE@-4n-X@L{j^+p zrdihN9H=$~c`eT^eN(L#^xEiI3LKXl+8PA-ArQjXvHY~F|Nh=BI~RJfK%tK7xRqDq zD}~|F#)<>u8;HgBzi5ui6xw= zu)S>VPPx2zGDRdxq>WV%6Yqvoy3eiNpyUe&Xr}^6NSkg1;Eaz17%>Okx?z9$2{s|A z>9@18ve?q+gi>gt)$tY!19#D8E{k0D<&VXC$MvOOyQYXPO;B#QEB!@7^k_u-;=6Pq z%7m)kXmQuI%&gh;cgUqRbSUz305Ho(myf`~j`tqrJ|A+4@}N80*;){y4-Eec&^7Xr z-e172mudbW+d-IrFsn3ve@d70504jZzdaOxkkh_1D4f2(v@%YK=$qLqS%8h$Gsz!V zjoj@a%0roMdboq<^OQe;GzhBxg2cTo_6O(q9Kj#F4l#^B0D1p$U9RH%)SQs@rsLtf z?xyhej&AB8>R?9FG}e3j3!V18v#)+^3T(wk6_w(h*S7Of_uzS7`BH=J{@bwAxW<17 zr~c_%`m+g_ye@aR;JtV_z;bwZVQA|e<$=!BQ(Nym%QNVZO8Xy-@jv5y{~TicZ_Z*= z4cEZG+i&{EJB52tcCR9i^W*Y(u-y2F>3Gda4gz&Sr(3j;aEJJy)97#}`#=#;zBQ22 z6|cgvv*0Am(>^8VkHl$2il(Dzh4Mgre`uQrX*+(z?_tZnKQ$0&De%9!{(rVa|2cd4 zgWj+stJuyyL>$KN%~oUp#j##9JmyOZJS!Ed2PU*r| zfs!mZ6!h9lmgA4rEfPe75@df)K5}XpHC{1u5di!2E-}`g0i1e#{WI*@pJO%uzFDM6 z(V^M-e&OAlnZt*!EW#fMepn_S7GM_>x>OHF?r8%I!tuo!^!J(6qob*$FFy#8v)nJa!g_Hdam`SVN4K>_uBU0LQLuAtw2!SFZBsN_e90OCtj(o z{>PsG5p@5n(>*qcA{^w1ZToj?VN1X!+V*%J(K7$#k$=qDG3uIC0@zse*bmN+{SW71 zV4t=&7AW@Zq%aN2sC@i`l~apB@HWTr3I~EZW*-5z3q()%IF-6`DV$ z=a8H*U&aLLAh7u$8+f)?dg{wF_o|9YB+w+ro0$&^H&Ok;jhF>_-n-iMas2B0nQNNi zYD;rMb4T5mR}Ob=xyo5q$+#&vpZ$lQ!5{U=U-9!V8HW`C(9omH~z!jI@sK`crth| zXJ#oJG33|fii-Pfq3+{Ptg#>w9lk$5X8!xE|34|1H%k_-*iK!ul&sL58y-c)d$sM5 z$ACXQVftFR@V@?ncSN(${`>YF=l=6hae2hyvhkFE{NV!-{Z<@)m*l3{EN9yW z!7?{R3m@342*dtQ>&I%NCcM{EfCaVO72fZ!aG=206oiJV6#r66|9>mH@&D{e{a)CS zEQ6Q7mtlS+sz8s`;=L~0uJu^&#yWrEZEtV;o}C%p!#f~c9`;_PC5zDf+bXTd!QN zD+S%&J85A@h%2ri8Q-D~)Z)7z(VueTf4Bxc7H+er$@s#HPRNygV2Sc5_uj01pDR4d zm5Y!aThmO3?bwVTegGAR)E~h4e^R>qx8DBm>h0eY`$e&zHKO$8eyPLq{?Or?LO9E& zm+$oFS4n=W`=7`1C#9YKZLQtEhD-4yp^d}8yF4yCMK+v0ff~x$fqB5^)bu6_@hc4r zL3e)ph(Bcm`p+ov9i@cZ_VzrzEi5dSr|KgpU4w-KB_k+sDR_b^;-jNKc3QrUk9Tcq zYO>iY+D46flN~HIG&IO&chB|R{Yk7)rJ~^_vXcpf;%3>H^F+c+=e{nS z$%h@dKTCwv$mudQfyv29oUi<1BP^m`1l#8~LB{{+8WF-k`LG00={k*u)IX(@!})wd zTU#4J045(DO-%R&Ias>fbDD`qSXdZyRnTKoI?@({W?C&^Z*yyl|J}QHeqQikTZB)Q z$4xtms*@!nPDNCAbSUo<(FX@5COf&faJvn3PE1T>4qNVdlaP>D=z{ika(;*wQHAAD zDqR5+6BC@zq_u731gjn!v(Jq^;F`yffs2a^D=(L*$I9Buczx`bFLzET87^USA{j(T z3-ae^-k6~?fp#*0B1{CaJ8{C^LqUN_rm|C0Q~u0e{r&yeFceoLLp+k@YKp`o7K&Mo z0hNxvEY~Y#6xgB5dI6Z@`fczCy_lOf{l(GpG1q3ksj;+vVL|sISkE(pfebCDYCkDw zNV8hh*Vo6=$;G8sfu%(T>rrybGZvH<7ItZ9X>pQrkw`ru)ZY7c@f7It>gv_E668`Z zBka$?CYmZ49|w)I{_EGfhkJWv-fnL69o=VhzkOR>bqLr^s_fC#)O=D0_p@M`Racn1 zAt<=;J}V1*gH5&j#XKmF`QTun5+>iidxwgNiP_J{$T(e1*;{ z9T8eC2j7AoJ26|gf_U2U4}~y6%`ipJ$?H06zl|zpn?4Mcfy9}W$qj4=O47Z<>Td@(bCbuJGgW+f2=w2o5lwv zC8by(n#0?}D^pipZZbwq4fgiVRJg4qIojK|7O27dSBZ{~r*xXhn`Z_$BD^L0$cM6# zjcsjhR2^zt(T(DEETZl!d6-KZ?&Z&@^O9-?+uzCY*EV0pIBaTe=5LM@l;U56dzNRu zf4^Q-ROCF9Tu4kzZ1CiL-v#h_8sILPT&+8VH($JXVYz|K&dNHKSdO_|+pNx4Y)<{* zr89;00fnGDC+1#l{G9509bMfByh!Y4@Q~)*JUl2eGO|;CnlW*4g-5^mGXusuM{p^G z8R0yQM?yYA^GQtr(6!Wh(1c()BtchTHmBoTRn^U@owX_K=U|jd|AocH%{lIyL_?yP zIDk()NizHptX{n@hQh)xSJ_1?DD1tMT z58lWQv+7BdUYV+@>Mn~eQhE!S#Gp$s3FJ(vrz8;5O2UVkq8I3wuFz%u_9$tXrPJv; zBu}J0hDBz{KqUvij_w{o{`5Bze0`(?5p{)?_|o&|&zk^0TU&zGBdT59-Kcx_?w#_h zdxX`*!NDxmnbP+;{@&}af4NefP5sY0l~cc#;l5|y}kYXlCi66(fOr`_V(7_|bwyD4wYE95@^xB{h@vWpt1&rY{m-Lp1K@f8TX0Xt3J<3q|fL)-4>o#|5 ze33w-`ywwJ-222GWbJ5Y$6B~WJpc##1D91jUq(l>o#kwsm`J$^KB2l&B}DpoaB%RT zSQL@_IzU9%E7uyxOX-<2XZ)?X@v7lMS7lC0O3Fd8TD;Hoa%8w-|u)KT^%`K&+?y5b}xB?uEIz zY;E14%!u4)bF;G+TVrFQso9eTWOe7h=E_J8mM=|D-#$7nO$&W}ea5FMaOdr4P-N|V zB%++%O*UgGVOmsBP!KMnyY^|dtagl-VTNa~wb~Mz%LK$qMsr3U>fI zdHN|v82tkh79COyP3mxOm;jH#PN@9kO-)T{J<6xQ6Z<07OFE@zC$CpK1Ff^4nVI>x zY;s^=fC{F(h%CXZ$LjYW-vs5>%%$b!7LgWgAg%Dj)jrPvJb~!Z73t*uUiwdMrE>8? z>(p8QtU*3N*il7*bMPMD#riI2fJJ}xbpFdORa0i|t}iy`a8OZEV$tEz8%I@xp` z-R!xIhW+)XdW1>0^cY#Jzk~4;dXw(OGe?3>&^TSs=_|q2Q?s+Pw{6t=IJT$q`QB3n39p>xa-HRt}Yz(Oa~VilOxS(UVT=Cmu8tWod$3lIQo;j z(}Yz`Jn=yXG0kEr*<2hP?e~Fwy$P@M;j7r#h4{F*i>9UVPmWn(jYL?Xg8OEiLIbxG^Zx|SR<7RIMhc*puZIx$llv~kO!KucA zjo*zstPLSK1)B*AdJAnplmho=HeZEQSQ^au$WbHVG?mIKMM&Vl+=R}2C6;Pa-sx>C zfWMxd0q$Lad&R6NxDmMrHb*XIXYTA=0BF;qm)*_L|MKo73JMp)=&9?%6>yvK4yGQG zMC8j#vj%v5GC*!za|#PpdmSl(;x8;LB)pQQ9Iyn;GsArwZ5TnC-~}wKa?IAnjlA-5 z!3_@hBO*YLDA=)5VO~=(Ham;0!ty1<61D&xQn7rSY5d?FWDQcUMTAwQfUbArJRBX{ z&y|HrGkz&8Exq@}aqj4-H`uwjR6@2c4DKeq)enIeWK9h^ogLgwpG_rcNCH-i%t+$8 zP_vqv+H*l3@Vz`fP_YGW@!2}%A9BIHk1D~u|2?J**y9CufuGp@^D zl-idd?V<;cBxL;POAs);%EIuCrg#p%4Ry7v$_-v#g=a=q+}zwHt!y8x2>im1j96qp z2u+x-PA)7h^~0wxG6(4D!N|zCZfat3{l1M<6uXVe164#JST9vYT3VWBS#xqSEg6i& zG9#}Na*Igkiy#No1dg8boZ6b%kpqB*+2@ zJ{9MMV~iukG0rX_6C5m4`fOKGdAYUSote%IwG`p0fdMTb%v}ygo@DuPYS{Wp&uQD0 z`QE&?cn-cKaZ}D@DG36;@{*G4`}Z@jzx=GUb3O+Gt7mSWCd|vLvAd?)N`U*-0l1HY z!^13~A?8uT1v@u4vnPyTl`VJu5O)6Qez*M)MryT+t-z6q-PyU{@GJ8?0F3iMLa^R2 z?4_-*ciqQFirHY~Tfs5mX;U4qpbd{r(08gZ#$M8f_j zFwZ3$3TJ>Dmm+M+SP$rEc|?7irQUd9@!L1h97qF>3yV!#Weik<9bfvg?z>+>&K-)H}wBC^}5}M7LZ(jcPO&XkGp{)@tWbicv!V)1hak^Z! zY@G}07Ma0z=|>E6^ySi3aJpirbEhw>zE!X80IMHtZB>|QzV-_~zib0y(6p;&Mi+Em zjf{;Yd3buh_VR|s3%<p5a3dYv-TSyoIB$aBUq@Se1B6jh9!=M)^N)uD z6iPIt%rw2AL%MIO`Ir3{ou5zMV5~Wld??-A*myztM{A#=v*2^5dH)s9wgo*OETD81y6u-^_}X6RKynwi0RkB!~T(?8q-5ySE45OmZ#9g}#bM^foIxh7EmY^lG# z11sx<8E$qBWD=a+%XPXxw~46)sQ&dj8^AgXz&dBTB%f*no|Kc7Ra`pqD&T=+sCpzV zW#r_xU@{?^KD@a8!0IbrHuf*nhG%C0bwXx3CLvftd#$PG{reyDr##lDAK!$v1f&SN zHu&AF<4BN(=ukVTDB9n*F3&Wt1U~zSLUCEy{JML27Sk=Vt-N<~@k1!CtR*R16sq|2 zxeSut>y_4Gw23s1XX|rE4SP2Zkqax=!f&l0miQ^@F*jQ^@jpUtWK}}106%WSDU<8) zjI4^{k*RKCk5Y@-D1}2hy+AxBx$3p3PPahf4HWc+fo**8vs8pPt1z+4cE|(JNkeFs z*~`3%wk8cKVxprj^m@6(Bi{E^j42F|UE9p8skwzB%AbEt9j;ru!syl1*eHIscy?Ur z5IECzIKfNn+ZqA^k%@vO`(DHJEq8%2+GppFAVNKRoH9c)X8ih%4nMW37P=neu= zh-bgXbDj&x#B<+r0yZy6*|cX)?6Qg8j0(IVB((T~&3v|T?Gx_F_?jr-J55tkP?&hf z2)(HE4|lBH(XhWIWb>&=h5(x${cf#XmGIZIi7$GZgC*xptzUKsUn&fe3^^e8h`R7X9gcL*!ZAAlxaY)`XrK;&Xlgl1>ieT%dE z1Sii)iw{J4L!K}2u*++B6oW6k@Dq%bB6JG0MJK6`PY-A4wk;;EKUJkSq!e*>ew@1d zyB|U%Ig4n#EVKB6t_g15OmLHtIO{bEi^8&ni)qY>FYK>n%^7%K=d;8b5E+_Fyx~gU zL>U}j?!3<&G2WD+mfi6__BhseRC*1MsJfuBfAJeVtyPm@(M>ux|LZ@(^7RV2g zuSnDol$D(gyDpw=ZEkR;CoC+iEl!S}IN{@%g#8|)sC&&|Rv%%PM=H&?^AW&@8IG23 zTS+U%(&~;;5`Wy4i&iB>;VwWpe`1!(Vplwe-sbaM9gk4W;OF4Vcr5cqg#eR~k&r$a z=WfT`L&9#S%|w$p(+HH{blGm+THu%)v2eeebcp5t^w`$wgjD^7)N4TeJ=j%TTH73w z@@wJrRpS@kG`eRt6lfiCgzh1D9xL=9HK+70z=HhJB^>OE75VK4{kkWJdHiB-(DK`4 z5!aujuGl1)A5W~8tP-Ni7&Gw{fHOU}4QkG}1w5Ojvk=IQ7xX^Rk};L;aKCu%7H0DE z_$yQRJRu@0AtWpqdkGK0F{Ny5Y#ad3y_XJ4w$S{+hmZq%8eR?#!(p`BZ`EmBZ-C^c zlf-9Q>GnbH_??{{FQ=Z67O6+^e2bk*1mAmyhE&%x69WSrfI59p^f27q{*t5NEG5Xe-~|^5 z(S9V--_;i<84xANV%bK@I^$$JQz_=)e|8cGUMmJsk$2Q|Fcpy#6T~?ckQydwwg|YJ+4f9=`AXEYhelw9k z_bm3NeM5+M74no-&8V?M2(xF&B9{^&f_8vzq&sfzX(8pkhaOyO&4^pPOnqh zrx&vV*MlKM)t23O_^2PE({bMKVX&RY>v|9!@7P#9o}N^5dg(IASAt;L8<1W(EZ>%4dq81kxE<|ESFtH(l z^4JH;qn_}#L{5Zi9P|u9OD`(ha`h;0peL4eo8%<_sNf=PFgsf^f0X;ar$k0IP62ya zSuncI{rU%_4b$NUX+#jn1zcq@`qW=sVW2zi)$NS##Tgx*Je~{kGg97L$C0VWttp&-ruMh4+o*o~ z_N}MqO2{I;z1AaRldw~e{Bz9LpJaB56>xY6=JT@cy~Qi#8UtgL?d8fW6q0)e2gy79 zLC)a8ZXH$Bfhvoi7LdN!>o%U`6cl&gpMajT`ucnz97HAEAkNzkyUo#&dmF`UPdf&Z z+LYRNY273WXjpsaHU=Pc=q|~5uCX#^bUK@_Ys|Jyl7qUr*$UMK+PMa|ocK6s0{CQ3 zg&AsidL>H`_zKl|O9wqXQH_Z72mIZhPo~R?XB?=J9C8-oQ5tz`rEn>vI#iTJL#&0f zL`n;|PU8{*i=N490bXGkkbK=o?bm9b#Bisa%bHhKa&P8jDqMeZq?;rkP8@4y_Ut-C)h^v7`p}^=?AaWv4~cHgjVG(SQMKU zoccx!8EZU*2?BDnSD5X?5FqAN+cGZ#<((9vaIEzSx`ETYz#HHL*&r@VdA|=K%(B>M z60YAKB(T;Lixqvwj0A2C=K2*{kX;&(lT}@*$)0i=FI}k>Yi@5_?I0Q zoZ~k(oV(qap6AAxc2J+(ofXHuPzN&d6!gf?K7lc>Ua@0Bwgh=OiP#D+fvEd8U6k-o z2T6T(;@hS{WdSJ2r}R-wnF6h@wl){(K(yZQVAi{&6ETRe(nlrDKygluj3iJ}ThUhE zh|pKCe8l%gL{~843Wz*sZ-iI6fyYhyCPDap3hnOMlcnr(NRA?m)1*9A$bMcSA*B8M z5VzOTZc*T)9C!Ps3&XaxwBwAuqJ$=654C_NyL-7)ik$C>WUH;Ub>?|rBwz4EO9)wb z&H2(rjxP-1xb~s+;pbO4O6ZN00#HMHPSU_(zkU_7miKX!{=f^%mj0kC4CAjpA?pxK z%* zhU(-tBEUPw8M3@&J4WCgzE3^mVb6F$=#i3gq{3qTUAtUXPkoL7Bg>=PnC!d{EL6P#n8GG&C?UZ);_B<6$Kx)@JMV z_~yIx8@%HZ9Qlvs87ikcuJyQjc^%ZE$|*jRE!q%y3k%#^cV`neImgo~^PrtRRU&e# zH_z0tJdHrS@TD{FVsshjtpU%kT4iC(p7zqgh6;P3Id%izAJyLo7v>=+OJb0`L^8&f z6&{~!q*N9WQ{4fHc!--0-;nbOeB@|fg>>zQ%N(9NZ6floiX|dam3(1&uEacdM$Y;bJ_0Wa%<0^pzXv(p0P&_CC+t z*v?=*ClFZq2FLWYaEoR_$!j|&9V)&}g8b^iaaPq8eNms)%fj%I2=0bR27C{u(j_NC8==`ljn#%cc3xp9xnHQ^sf)*Q zAzntKp+pku!rd%wx5hLJxq%<#h@L3)bq{aC1U*00&rX*=G$~EuHLckGDhSbiio`nJ z7{r`NrtXozOlG;_wE1!}v19603 z#I&YWSe{O5;rmJzafL{0d_a}Zc04aS#qD0e4vi6Med)Aa>llePTz6Uyz^Q z5n=g7p_B0o?QDH+b-EbJpsaj=~*0khBaDHccYhwO^Hrkn?MF*GWk7QGYXVn&8+`USCl0?8H=lD7wS zas_NK?t}E-#*?HdNGZX3eIq-|kY5V!b?3=a+ISXO&>6IJ#1T(#FqT^$fWe~n!T zwFvo1C|4vFg_p0eNjl8k0;Q-JIPwPT4Y|nF5kB^T7 zk2Ff2Quh%Ng^vZ+rf-Pc?eW%RNl-4ZxrQziK`Bh()RL*_gyxUwSi8|oALUv81^6yy zfzy|J2mAVFHEDJ;45Vr1NvrCwU+X~^;TLO34I_Vi0e4IFptY?{(R*O9B@r%%`qA+O z2gQNxe@W&lk$ATdEm|jlxsKcdvLCV-H zaJTibgQ+Q<&2_PN#aYIJHgtXw3=9n6SWsoTc>UFzwCRN8@4~8^H@Tk9e7;BnG{)R#t{Q=nB==TXUPy(5Fb!3X{Bx~EsRG6#MZnS63y%u!} zzroK>##q63mteYoVBnIIBS>#7NceQBB4b{#=&D{^bd-jCCWBc6zmzG@Y;X5ac_OpL zQ=1*4j5v6Bx`F%5eHM2m(oouI2Bg6Jn=#6yq|pnW@hF3&6denGg0{f3jP#f`P>0XO zFjW~9A}{GnnQj9`R-U#PX;6L1{eG{^#MRKS#-S8n*|@lw4gA4I20kvViwak^RJ^YG zDOIx@6@YWr(A9Nq>{iUZv0iOfJ}_0^D8#(^$xN;8u!=1TjkDLOWtTSEHJ)drW#`lqa1v)99Gg zVX0-8Z%wgPrfDJJ!KU%toYbdPzKmW0AHatQEPL8EcssP!WVr(rt~_P=RsqxxE#I=4 zU!^b(R*`%A_U+K_(u%F^y$e?kyavcG^i#}-IGT;t6_u8h?2d6bAP(<;K3E4B5wb)6 zO_JF2w#42ZB~2Bp)t~q(@vJSUmBS z4rF1Jb3eTcVfkDUk1o>xX*I=OiMbkKOcLU>VEI;Ek;^7LG`*O=w?L=UnqDynyUcy?QOwQfSw8)%%*vCK6V-um`cHx2g6Eo`)xianx#w`bSIm6_1L?LnP@Jpdz1zDnprFYAa25Dy z7kL^b+#bD+e^YaVuz?GLCLS3$_U5G%na(osiCwyMDb#4@U9nCuS&BVJJ#L$T!TsnD z*~Uwygq#qo7sz4l7cz#p1D`I1Rd-;Z+c;cd(NcwF=|&TR!H+|spQYNg10*kOJ>5mZvpv4Y$v1+z#>SkRZ_xfJAkknr-O%nWw!LSN%?5!(sGfor zCC{A>e^5l8Z{Z@mnNe&53LNG}pNpqI-J4<^mZ^XG^3mB?`8l`uAZ!rC{|d7BmHuL- zHV{=dz0q^>?`&)AFSeZNhJot~(uS&hWc=013Swa~e62)Hs$UrR%$_0qzW^0BOBbbV zwR*X~n1Et1Z|qdXno`}ht94vy9FxmN%&4x$U}i6S#6Uit7r}gcLADo-RbPIJYsf?e zVB(7DPyL^K?43k24U6SsF~5R>4JfeKMU7h*f|?cCp-}Jwj6wp*vb(y%*r5uS!)ekp zTbm61{FtB)x%2#w9!%2^^X!aE6fb&mt_*l+Nl%uB@j)mzP9 z=f8zB%vmt6SpKYhJ`SEx>U`-&ZP)?e)|(``+yme1k=%Ff7f7~x;8}}x!sjNZoq7T$ z?i*fHjE4FE=d3+j|&W*Ap%i8Jh#E8 zGAI%(i_6B}C)2(gjP6EQ+i)(PtAPzo1i_hkZy4YVM^3E{4aGSs&0AgxNiiDllRNz_ zFhn-c{{8he&2OeLZ$pB?vQ#ja;H5)?CKX1hqv z%O-g=&(0p&E`?_&eQpzicsw?}sr;faBQbMmMQB85A%HWo&U^DL}Q&-cNP1WJ7^m`R3B#TO9oz|S0SIYDE$-Qx&YF84T71nV9 zU;ksHw$twZQ~8ym=AJUC0KJvNhCZ9R6ymP%M8QKY3`jsivkXy6z;zaq_r?AtkS^C?rcZI*ct;8tutaqWa4%^z=GNlyudaYKNE;HoVRMYYn zW4F!zvM_H&1pwhB>`@s$U6aDCvY!)cfr$(G_Q<2-Q^{1YEi zUjLd)6G#3J*~;Ob3H@>o(&Nhj&In0Lt_;~##L$%i`kb<1j>e$B1T0B z;)cE_C(V*IA2L&*zkdDt8_DRoS&r)cXQyvl-*3%T6>2<-yjQ&3-SK>=4rIr>|9O0J%Pf!7GsYt{Rd z^c_VPxdKtj3x=&rWWLB+=Qg-KKuwUHgiIu%4*o1{csshm~EsUN?6tYk-ED%aWc1jgz*DcLhEw?rL26}d5 zt{2c+hxm?y-@HhmzkUdb6!pDtnJ62i?C$PP{$j-LzO$P0pwstGX=WiNa0NbESmRz4 zMRdHWvr|P+f^PK39kgTs^AgEhzd)n*cJ1a*;~Y?!QPK`BlkxUd6~k1r$+ z0_9v>liJltCxCQ17^yVFd9gVFwRktj3umt)couFZ5*M6&?I8CueIZ=y{&4TkL58^B zI94RT!@!GzdZ&jy{r%^s=WgRx3B^<=k{=cMPPCgmV4i(?8Y8U@RM5-c4xYPicS5AX z8o)U5@bJ<-m#~V=x+SgSdtasItG@MI>U6QPz>RE20$5e+=%_yTi8-9s+>2f7ZC)4L z1dci1oTKN3>Me`6^mMTNP2)E1uRs7|@Nij0)bf?MDMz-+<@)ElnZl>m}((+3Syt4|habb{iY zMS0XzpHWyO7OOL zANMR>_&T=IxK>6Au5J2;`BRMu43tG$A00?#?NID&mh^)VI+B2{dfUjhp4bOq9T6B) zsmI%AQEuK^c=NN0+C^+H z>+1yEl6=GmptHxFfNQ}#52FYYsJKp|6vd@SFdZ}RVQnfDX@(~@;cf7NsCHp~J``Aw zkCSCM$G^G-n)}3oOm1{$cDCA@m&#m?)?60=YU1t+M!KW|9a38%SB2bt6ciG2Va@`; znsrd?0h0mXi`>zsB3=QoS$^=A#x2rN;bd|a>sA+%1d5*(c|irK9(s)MR1MtG6y@5o zl9F?MGeOEXG84&dWu_9T+dy09Uu`2d1I_)_{XyaX@%5WvA?M;2;xC4$1tW~x|Eit5 z(o4~iN3YClLJTzz_aL8($A}rgH$L2DIhVKs%$61xB{Z!!o1OTy8*-U?cXxNqfC`#4 zL#rGI=W?|CbrEoWd3hYxZfxCrF7EELA{)xM^_u{>jzujq#YnXVRaRO`78@UL zSrhWnBrZ4MVtA%%8Psz0TWMe=K3_Y}CCQ72_I0)xtb>T$clIN2gp!7JnTU+g5}bY# z=Xu7J9y&X*1%Rar_KrZ$-&d<)%Sr*5o@etF4X4fN^MN49tzflmYT?$a z>tjMkx;5BG##Mv$Oec zL(2fwRGf1Jv+xN{>p9(^aI01bt#34SR9)`s(`ee0P{?_pvOwysOY6~*V75pWV4zCW zGXjm%K?DLkf)iY4!?~cp@OZ5S<|Y6e^U5n{KMY0y$wbdTp-_{XMU8U?y7E(WQq^(w zX`iP|`?uZ72a<)?R{6~9o8=8*G?6bqA4|MmcucV3V!I=PaW~t2ql6iS0wj~*Z9zV= zi2dD8Dk%T`x<#ty3VP-Ek-bhSI{MirAEADb73y3TI*CdhG-AKzl@%Ko$0vUx`7SNA z9s?g^n@dji`k*m9l>8G-?jg;s6QmSGC}_kUtbsoG_?s4Cumy0)ufRhWgohL=b(iAW z;?v$AQx6jui8@gC&B%VYPY;g+WxTz3?xiKb$&M=E5<$BQfYV3{L*S>`x8ngKAv*Am z^Zmnv@|$4w6fnbZ582w<@~cB9@_{1-GChg~L=Z6*92V^<5)XYyq)sdsV1&`Edlk*z zJQNX!yIVFkHaIXuNH`^lkTEbAQNs}{d;Vq2^F0b8DKwwjBWZO^D|s=ZBkI{04^WDy z00<~Sj|-?SAv13NC}|Z=$Oi;xCq@)3)W1O^-N5*n0DD3?A=xPi*0pP-q&fpbUI2IF zfr%f`Xrk1 zGb-0G-%f39Yz$LHgUD~k4A#`t^n#X*`bdyT46hr{^@U|<+7~Dke^z;r>;U;z_q(-1 zS{=-0AOo0y4%JE}ECIA%GI)|D9Kd05VL_F8;h~rs>(U1PQW1QH(0Zf@c&%jZXwjB{ z*kB!!Oo73c_xIZy}-4B|6H0BFs$(Uu5@59eQ+chY351t6g>w>_YqNy0@Upq=0*9Q7nnb87B*> zQFfKaB@S`%rKoRVRU}0BlZ*;p3~si3aUTfx2Z?64ouSlpHM?)S%Eb zO{(gcC5QnE6uJ1&$_ho@0FSH*H#aqzfSrNMxwN>L6%%Sv0)lauf~sg|d3C1!-6Vx;w+dhCNO*L>BtbUQ~g6j6ceVlw#{fqn#n8uS=d)do)(~8F%qvn zY+`2cnb_W585a;MlEzv??5r9etN}P?0mgQ~HaySQH{=YE$l+f7S=P%kA;pE5TsKP< z(Z13{djMG2Y8CBUa_j<+P6G><402Ef0lSyr1NZqb2;vtE;5`t`8_M_LZC15hSw|Cr z;XWp|LuDFYmrBaYE`gY?)lEQ$Ur0!&^y5c@>0=Y-C zm%q({hiJF3sHj_67M=sl0-pF|qqkO@KX2i;`8qcC0)~$VK<}CY62u;a1B<^S@j!W+ zW9+Cg1iLh+#2IwVnvK|_FP!wT0nl}qA-}EZX|w#IqIVPU!%*NNybX@@PBB)Wy@!Y8 zSqKT9&r>md?%VF}3XJ{w;vl~-2yNkuzQY?A?G}5i>>70MEWT!BSD1B4aq;a5`V(hx zbkaARRg7;WB2Am)!T@OX!O=5iu#UODSw&kwZi60=@X?nlKmxE&m#*3oXdDbVOWjjH zqNS@_wCi3igVR}8Cy|l;A{YUMN`MD;roTHM53|c)DGbCqM32(H-Nll>O6cJ%;Gj(8 z5HK}2Po4r#bJ%fHMBMWp1n}m>AB#-|zo!gZyWP%-NVF(5(CtsW=W`KYk;*o@1pr(R zL;6twGDJ6)OLL~Ti1H(<*jXP!HR&I6s4<70EObl&CN|sL?a+`lP2nju`;GK zu0ZPm{s!i#MKbqI+?)a2Xljkr@uP!ob&D4ud2EM5fm+6R2c*;8f-kmY>ICTxVE(6B zz^S}j2u3`{=9h?~zQ4O}zOr^Mf!kWGs}zas^80}dz7BqnZ6seimt{Uc-wbwF;$J{q zcdm34-h2H{6DSq(RpT`AAK?N*?VAqeMo|J)|{L({+u^6zl@;zWcZeFdIo zN}9SXA_J3Te5JUcn;(!I_*FgPc%TO>l^-G;ktT2g9kxttx2<(WU;w@HDO$8=g}O>) zC-go8d}-h89FWgicn+M;z$3p2k+S|IUs_0EJkZe`v<+wT$wfW_#hqH2P%!vV4OaI) z$YJ=5aKICi{!Shq{kxXe?VIHD$>-+`gwSy|Jh=4Dt&beAKGUas;7{LO?Ww1d0a}yN zt%%&kPqBd9Ku}PS3k(R<-u98;(QD1bbO^pfho&h3_2zbW`*6<_E^8d_Ze#%Vvj)$a z6?6khU`+sB7|||21F9C88vUgQC1zo`@*yB^VY#*eqzVDn06|U(4{@IZ z03nAYHk2R?(kJhkUDyiu?I`ZHyA&V`?-`uH0ao?s;j)C=*Ed^Fb19Qsdf>*d0=LnP z8|(jT@5}$8Y}>fUQWB*UEkY_KdkeCQR*6-f0#`ceWtRTl!{d4R2lE=2u#>-%B7p{59h$}F6E>wt$ z1C>Xup2V68Fvr*Kc# zX&VQFTH7UB0R%9aTWGYD*KS6~s#_mC+#zk2Vq~MFsOb6{F|-$6ULdJ{`CY>$MJBKG zU~@DWUcCH_{mufxNW<*`>vez|>BJWgp8r8s#P}JQpc%;KYwuhCP;_8$x}8~sUJAC3 zzXE6(KGyN?fajX$BWmRgUZH7nErZfl0E?GlvzZ>?p-n3!=k#vc+tqDVtDQ;v@HVQ@ zbv%C3q0Yc7sw4j>;?WVt^C4Z8H52!e_tba>Y`=1@&>TdyI+8nyOOt%*oIogl@?#rX z&o0=t;M+Mf&TaqpoUHCofG=}a3_Hu{LA4$jpS*N|r@9vMuuUi>xnu_aFxi7p0xsc` z?k@q)aM(rd0|^s=s+Bpu)u6gN21ew}{^3a2Ikq=>*VHzf{%7#_|osZq0>7r|(iO$hE|_@mG=oxPP|y)_6(TT#uU6 zN4B6EDh=rUAbMaUg#uetcf2%bpjiCoh0--QOZe<@#WilN;WpqNcz_ZI$ z{;Pafix#5Q3Fx1bsoFK5*7#20A}<$-7ZqOTyUn=!0jWC&o$)9E2d@M@PvNZp`|6l5 zLL}Nk(CyLjR9nHqsh{V>|Dg-aWC*JPRpcBShbvy`9-`j(-wxACc5v<+zEif)M#dvC zX_f={QhAsNP=;ta$T^}8taB3P^Z19mf-+iS69r+89bndugPh>U8G@}=X3MT;4^~OH z0RI_Vl*V(z+#I^?g|DDwMn=?A-9|9Z_FKAh-5EFnaTs`N*u9v0w@N46a8LGaMGAc90HxN2rVI^P z4EA=8>o;ltSYCFY%E`F9wcWW*!A2Kz6gX&7N2GBmt>=b{gPZ9>`v)%XsCkwA5@Q({eYn%Ic{BZoXA)yDAaK9Zfd39= z$x*3-4;g$|;+ExNA#b}A>GrwdU_?sLo*Brwgy<{3z1MTOK1C?u8G;c|nA>L__}b-z za`cUUrJDr|Pv((Q_FbK=wMXwn8O2DZoeY9dMO)Q9lMc@vTOzJH4_(x`Z3Gdx?l0EJ zEfKZ2iQ}xPBkoW8cJkN82A1+(l&BwmBR5CYHqFJ$!^22B!xoVSd)fLW$qQ0aQefpg zdBPI>X1^U=MP+4uYg4!`#kR$0!p$nv+UOU`Ao2k5 zI=~1LaBJH3fdU+7(4L|$_U~~=t#Tub&19p2$8XqH3EPGhtMLtono4^G!$Jt|DMG~T zeDsax&zg|MZ&~p9%-}O6Q7Eoo1Q3arVc?}odr^0(Lc$Go8~I)H$XEF1kNMEkRX z5!&uoEInTBO=V?Y!hG%kGj$f$K*557ZoJZ&sMh17=c^!^bi9)dfxIeq+t|!uW{*Lk z6jdVRNa4gsn!y2g4-eE#hF*wCyqE$RJWm)kCpR9QymK$O-B4LMO(h!Mf&RuL9;~D1 zn}p#houaXO3&#S#bRNuo1fD<3Rg5i8f3ydQwNP&x5KK8=U`G}V?5twZ!hZ567r&^%!#CC(fh?TVCgG*IuO?q zZ_7(D0;;lcI#2x*+49~D1FFYoJHmGo2vjeqt3VHCO0WwZos+X6MzeXFKlPo6Ff8wnd}aYy zl6+9oe4L1(NLaJDzx{N-s0axf-*|N~I5U>xxkWbSs%5jn{d}uZKjO!)N9DI-gPYZE z3N!Y_sM>w$@2$d2Qp0-5xQf(VTVmhh_tImuB!N~NYmW$xMO07RxJ}%EjH%kOk75GL&vDH=>e%Yh(pThA9D5cBdv?x zh$J|de%vL6aDz~oKw=YbQe%8RXL`%>Br!whwjyzjl{QIPoG^GI-AWDsVeTpOAhY@# z+AG9m7h>&SP0pPUmxJV!jWoiat;s6E)U8C84I80(w-7nD4nAwVpRS4Gr|mL94=C}d zui{r_&vbT~2#+0L=mJFsEXUk%#sIoAknF+p^LiQ?>LB3zxC>TWFMp~0aXq}Uz*VP^ zW9_Q3N0h7Sh&G~kizU8&68wK+d3S$(nmB84y622MRk5oj{bE8&a1te-K6O#u8MpXQ`)ezY_Xn#%7yRYFbh>kteNT zXVkUC?@@;gy1W>43M z(AXk!f(DDv&UI~Jp}m@UF0$eN&q0gC-ppeaoT45zch~m3z+;`5rE9TanO#c@f!1;8 z$c#}vv|G;zCt}5q@ghdj5K}S~&GAT1w?LS~y$3%S&T2mM&9qXs>IrgX@)T-qvdul5 zpKF+w9xRF_Wy>iJ#_JT6SsZlSQK(%siQ zzE=b5dF2h|#c}qnx!Q)Q;1HJ61=zM@{G%|?WG$uk9g(7{Ho6YUky62t4tuAk4!{dL zmNh!Z2nl?h0uvuK(ZhEJi>L5~vbQd>=+O)R#fW{4tBrhcc@;DFxY2xWY^~k%IQ1$x z0+c1)tKseUkNe?SX76}ezzGt`ukbj!YE{%#z&eWTSy4y_R&;92q$Y=eu#OZ z!Y-KXVuYizQ>)2KS&jO#7f$*odkG3pXiQCIo*7w>dG#!0{8tL|-E5S8XVS8c7&d)# zCqf2n#jD>wT6YH@E%}=cl|QaExNahA5$w<1Jnu!RO@WogxxCY6;QDa?>&sK(xfo)R zkkDY@T3%8W{@K@c^FAJZBr?lG#}9@|SQSz2!6_zF|q1N3@oh{^_KKE&=qhNp$>YK`m(?c_tCO}P@3A5Qg7G-}S z&8H(p!|!XPmxR7|f777YM_j8u#dm5!dSL0yx;a`d&{9H~n9I5@a#0YsER)A{W~}SI zQJewYOcsA)|0)9Nq%GgDE^G zeVjO=ZlSJbVsD?H!j}=-k$tE!Tn)|psEl(WRa8xdO@#%q5oys5&~LGv@a~7Z&X}=R zE}s5QO=86^bc|IUSGqKNeQp1RHDWoT6zj`<{{}|?!~TfV-AMKtOb_N>PfS<0iR(9# zL^oF#Hyz#Oy|&JoGF2#!7)mJk`7}a2N!Y2Mi+Tui*W^RxXexe}mwd0|Kr}&*SKy_+ zr;C}Sl++m0g5-fdRiBmDgqq%*QBRynYh2N-g!Epc)amanb;;rZ?yG968lDhX+F(HQc+L@&`M*HPd?3a1c)rPk4cC{V49^ zVSfEIcVz?ldZL)bzL)FH5W=^d#%;LY%iiX6CvPR@OMt9K9J`Z#i1<#+A30OzueD`b zNHfMx`P`iJuz5n=Q`xGHebZX6Z-{s=MGymoDe_q!f-bK_3OMwtiZpsbN+hU9u{cpy zKbI_(VeeEY3RYsq)}Y5x#Dx?$gs0AF2Ut>G`}k%StLo(2tbosu1kk#wjp&E;p2OXH zm`8ftB3o|-q+r8k>elZ&h{YOF-pLcYMO)=PhNCUIEGjqnz3GQql<>;xXpLZm-q{+J z2dksva@kEH8ga2h{rj<1hYG$+tAWyIcb6RTu#~%_uB!3(#VqYU;$Z{jNg6eZ9M03! zGGZC{rEpL}%QUjwXEl#F^;8Ij7HP|4#=efo|Wx`m*| z!f?a8n$U|~8$tc1pV?1fBSl>(GR2uqCzMndbJ4SQv7T>LWBqgz(^ttc7URbfl2nQV zDy0Yy^@-W!SS!CBEmm1~yI8I5DvO$xuBpi+(8zY_Pu2ul@$3jgFq%vw_}&GciTI3& z;Y*<ic|W>2ZB~#wBP40-;62sxyz+DzffZSIY>mUd|J}pS(0%Od#~O@_r1G{giL< zUiwil?$D1B6RSk2N^`CjF$Zz(T0)&DVzPTVRS-oB6612{5V(1n_h3k-jdjK68CsjE z`E~`N$L2i7 zjqf|m%`}Gd!wFGj%IwIUOW6$(g+sBp(r7}cd=Uf~HeRzOISh)8dR>b2|Iu!{D@dN~ z>U1VKqMWNOa4eR#Bq)2orH_!>jy^6_9T@5BA=T9%I>6Pl@t5F}N7R9w#BLGgu=8P! z(d@ZU+7Lfj;Vm~_(%JmUn=+m=H@)H6#`+*ue(5_VD;2dE>N;K@(bhB>h78VhJ+u#D z3?(bZukl{&9h9Iu>AyO~vCVX3(MTX|_@I=l90?fzS45S4MLQ@dHS05ls=D*Ngjuk+)0y1_}a3hRxbI7k~UqQ9Lu1!JdN3* zq3T_?wsAAt-cqsiG$#oUw9Fu{G>1%BB5S{aiW(OQZnO(liK?j5ikLm27bj|OZgy(; zU`+Q+%dY}?osrJ>pCVCN@)S=$KR@4i$Kwy)n3EBU8UgDLXw?(__0pCs?Pt3SEl|Fw zCHv>xgV&z3M9h5P;jk;7w!WJC94SO3vLOrsj;s*&^fjvgwUr#kpn`BS?G}!nJiVUh zK^E?mEBF!?lk&E9!%)znLGn7+d~Y}F+S%g1?1Ggt`8fWX5HtzRCa3L`@oiAvN zmak8p+7~8TV~}tYAp#gCH*qdaE-tRfP4C!AZ2DrvGeXEEbC+ho!A9IpA#d)AHPpgP zi26r9d&K_X(2siBnbzXWlDN2KVBOmVC}JjXw&)#H3CRyZ?-OD*W1Ez&%AwW-3^4or zH?`)EKFwBXSE(2MOElCwX~&a8F9@W6FSeMARw1xw0FFT zc^z0r?(95Mc?z1m&92xXrVX;?OZ_-7EeCe(9b#-B8U&~U#_3L6I zs0Zp;oEI^pX^&p5cr7-VFlD)YO+CDF(@fFLgkPA5rTA}-kALgmyeK+mWd;dGYtm?2 zdj>^@`}=Lf@Jd!?rtxRl0a*D1JE^-2Wa%~yS_ziQFZ~*00%Tu`8^{*ydb2Y+Y#6L@ z$_xAzW<(=oF|-OAozXj1!mYz=5@>;IYZU$t6tR+=lfdUq;;VY2ruTIMLZB0r(kW4F zfNB#JT+x=CU5u5k>D}Yw{!GPV-zZHsbTr)coFuzywkC5akZorQGzAeGVS5Y(zF{yk zuUpHsRqNidm78O;{asS-c8GT8AByN_;kqfiVChiVgfU;)*JI)1>}tMM zGrFH^McC);BHL<4Yr)d3%X4E_)v+7xm>nXh3~mHB=jNx4jSZ8pCm$!i?8uWy(nNRj z)UA9vLO9Zwol;>R5UatlNf&R9l>L$scDeIpqFoD9Zd!ImhGhq#q2VuD0MnooPK342 zpw>&aPP!8kc{DomTjypBszD}RGz+13vPQ-Du|BT`_ergl6I^-wu6+JgdCPO?%^96X zi8fQkwmsXRK&Vvubf@K1%Qb{Z%@E`S&gIC_ZM#<;rpNB(+sh9E89oj*ac{}RK5`y` z5edgq29|!*JzFi85N_^%|IQV=GUI(;*rA}qbg%#BHDaaHSecGr{ovr>dTEVmt@954 zYG-!pXHJdX%a^;D^9;#KO?j3BXA+e8ZZIX@00BB?!g*aLLf^5S`$|Iy&53M%`?_TK zrz0uu_r=epGMXwWq}1Au0?ysRe9qavvKCuErQxR zM7SKW3$z)Cd1#ect$faN!Zmj(xqH&thpbwBX`%T(9u+>TE-4P~e(#&K`v%Me*9ur# zBakzYMic7ZRYK6VxLxgZ(1k4Irbgl{+!)hfr?wTM?4u;0%2m@z2$qdN)S20_UDNhn zJ91uY1q1lHo(Z?oym{?vyEX!`c;0NnoBSkD%fP`gy!~uZiNLj74^%hn zYP^=n?56H%)I<7x$x~@2?Mp~m;S&Yr`5yJGmW))%bV!emsrgWbn2G)e%naU+pqk?dy+{%MaE8TRMo*%m!jHZ7HyZVudusSN*$|p z(`859LvnYC>tIUiC4j)DNIBG~h+J*rGEfLd=n9OI{Bl*p`21PfUFzN;F7CQmNvjvn zIszWnG_&o|yp?yFsEpS~odxDPmpz-ZhfXHPN~2G6bVgUPGllDYAfMq1l4vP9&U44$ zdQJh~V!}>PuG4ka6T*!vrTeMdF5X9!*q8m`giII6Sdk;hcm>q=bYN<(+KQs*ar~CalP~m31{Hakf}q zzyINlTO-o}#jWbcIh;~ZpX{>PE7630dV&=xXYVK%nZ8&!iw#}+88t#qaK>f_YnlU) zugXPmC8{yg+)PSo)bvjHf&ka<-DZ(=XVU3@4Z-`^>e8ONv8vX+4oz!{^mj|u&H46; zEv8~hhFvif@w@`qo9VVPuaW-_JES8iYo2?yAuq>Wyu1igAH`+HU z=6U=6*nLs&ks5UgqM1pE)y?A6XQ%KowXG+TUwgi{jZHxtbnZz-SUgNm-k2G5UY;3j zEv!A>S)`LMUaP$LSi0>e_0wwpuq!8~!HZut!CD66^HE7bfk~|byv`xMLS%1a-B7QG z5-Dev%2Cz-frQ+=b!lHK?ctroLxf7UfmtKAvl&4WJi^>*Vn3L)2J5)U_aa`rjUJ=+ zc?>2{t7x1gt_fMndVN=%=QU%kksMlNvZyae^6(i}nr~KWh;Eqh6xq|Tpjmqv2>8%W zi}ZrJe^vSjaL+c)DmA_( zFE`wOdzoB#Sk&)9x5;3COI?R}`)384I7qak@JgHE1(r;SbSR^(Qsr^~OaQhj(pgtj za`pYqcgW4Ld1wIbBS2`V2gJou6EADQXci&7Y(BTCoj>~C`tlVP#3bOv!yoWoCRJjm ztX?GyCNnZLEZZ8>DPlkxZFu;toIkYQ&eU_>*d)1WtU;#Mg-}r<39RAwMyacVjYYOL zPj^>K&vLksqbwA-BE3a@bJ(fh(=;Ut==MemZ6|ijnAIH%92b-&=;-KhZufh)t6DzC z#C5yBFNCXJ+@IfoqzCWi6)ol?>^#FKfhqZ2`>@}l^0EG6({$4}18*6I->8H`<5Ln$T20{n?O@*W4Y1aj=d>^`Fk9_*WR4befg zLb-Ci2|NsN`+|10Q&bFuGvotz8V@U;_;8ja*c3jHFH_i`qLbbmvpOS$rHu_tyF2#I z>>OckJy4QxVeJ zqxK4%dfe}$3#MC+WwEPZ@62W_)Yf6+xA2d7VVljj+0TG^J$+VI6_OGl$f+xPP59A? zq57QjQx5=vcIF_5Z7)TEuv?>2D>j?EBvtO%R*zd*@U@Vr9$gQ@*Ix5;YGqw}aElkU zZ?mm5e?vZ&KQB6e)pyq5;5cBanX)grkK*~l|Dl|y^1GGz!X z7AVhG$0y5ieB;gKR|T{7j?jSdfUdZi>zEwzOI9sb&obq;*pZi4Do!>>PM%p+Iq%1G z5O`X_*$BGiy?^~0@e=FCm25T!<#P$D{C)fBnqtQ>9SpT z&t>1&gYrebo};IrLMsDzqf8Wkd45K_zkvA5H|40}ev?%3#bHGak(E0!lRnxQDULT` zJ`P8RsH*HgHxG_Zd1nleZob*)|4m~k)f|`jg^>QeyVCxG_v*sPx>q6lYWi^fSq20! zkf)*7y5rSJ>VsJ$+9{r2E?n_T&qoE6NUL2Hksc1+ne4(hqVHWar=02@E>USbrwZu0 zgYktu_E!5Xj#iql5ExKeFDQ56zIgC;!2Oy@$jULSgq8#OuXbd}M&Ga^ld1^nu{F}x z^!c7Boln7=eph)NniL{RBrjaJaIm=?&`WWIf%WubXm5(*<2i9jzM3yszPg^`Gxom@ zfv-0@98#V-s|>@Z^n91?p2gEQ|v~Kec#^-Ha``WqioIJ zbl9*^bN8K<8%y8r#rKH+Dr+u1Q!tkz@tv)%Q#{0Yzj>Uv(&*RbpWB5Mm6YE585Qi6 zO&i$IYki#o+}$NzURO%)300_lS+VLp;P?8q=hO#t4@w_19=HdeZ2`iv8gr+H>@Zfz zgU(ORvhdBzE`-X%4jGBGQ9%}r>YB;;Y^7NheUd&F;~N#YJ{d)eE@N*soyykD|En(l zBhfDYkV*X{u%aT|{Q#@NpujXc^~b~!OpbnLsp7*kU)?92+w`K>kuwO{lkw(DShET7 zJbl&Ec$gl!?KTN(X(#Yqu6vt|@_Cz4JIc`-=JC7res8)0(tUm^E<9YwJ^LZBenGkE z-YomR*EUa_Cvvk7#Y_dMWFH@9x-?vRY^>C$ekU&xlk=7^`g+6ogX7+8ipYG-$fj}z zW_qOQutz02#@mT{bmRTK)z58Z-uTo`C8>qxG*Wj;%0tp%6^(Ma%Pq2IgS9{-muuyj zl5unGHA!Y$?=aFlfHD;=Q8Uy-m28*4!~Fq)zc4xVs;b zX((VifW9iC{GcsxdDdvR9WJmW8`6&XArj-=1FL!RMmy(sbpUG|?RrC|YIzhzY5s;e zg_t`9CrXfP-)`cMVSNKPHnZ91WrB}5emfXID@(R>_(GgM>&R;`eI$U?^yD29)3~H2 z`clTPsIa<^mHILLZ2S7e`c4EU>-hO@cI}Y@NztnFLKR;(WaFt~5$u4%M|a_3D7yI( z64O*`>JXL1N3?UnsoR4p=O2Tn&u;d*ZWd&3Lx`*Aav2-D50BMsZakx5B?*J#F6Wt^ zSk-9k*|ABD(_5(3;nkldOSgnx)*PRu4GGaJ*=7*ZO2Gv}9(Y8x#)i24;OJ;U`v6I) zJCGDBOX(`~%nY=l_=r$&o`&cD#al@&)4IP=vTEI(g;3*z9_yUvT8uSc#cP{~9a;J7 zWO+C1O0ACQqraikjl&JrwB98ycysEX|ijrA3!acjFT4u(Ado1@jknTC`k ztAU<=7KG*&Yk<)rxVEi^3jOmN{Pc(1*cMcU@rl~S-vkTzBN5P@M|(UK{5eVj zpyilUe?MruhS+V3^pKDcU%tuUf-z8_OR$mNb%P^99y0*`jH}ur?K_(|9>_i77b^mn z1t#IxkimElg*e>c7TgTJqLu?7GjZ+SNlEU>VB~77&Zi_s2LJxqH`jjGa!o8|wB|dB zlmN|9Uc&$)WsIo`!YO!trq*u^(P3PzazKfRW7uQGLtv?8RV_1OrC=Q#f}E~R+ZM&d0DU(#k!igWR^%8daZru+*7K1DVTRE8j^Y>H3@@oBQV7sdLu3s=kqtT6I zt>8f_nG_0u)xz%=VRgp@vicwH4oIaa5HZB@ zL?W>l5ZAqZ#ZHmSih%z4_ap(-T{!x;)H0w))tWa>zVoyjoPSi_N%DruN{wXg*g=>A z)cWuCiU682_bg*CW1R+WYs6+5gVkok@t)-8>nl0*XNbYv_Ya54`w2#50HmTD$g02r zF`5UcKJR~~9L{6*KbGu;uEoHC&GW?VV()q1O2V=qgO^PgRA(Byts%I{?lk)*btG{a1#STa?@tU)338&O1qW3zHavI z&wQ!E!bghDcp6jy7&T{w3TbQQoS%`eNs!Ke`ezPS;E0PvFMz%-kK$w7pws{lnF>hI z9QTS&`n-hx=dBT&>BHstb*#zZA4;t z?(Z2;3x#2M(pvA2{sluXFlQIwi(C6Gah=+^TnEEc*dXFd8w^~JNdQdRoj;G(WZZc^ z%%6nS{!Rv5izw~)efw{~eFZ0ns8FE{pfm#gB>KX_LQW!@;)=lt&;9OQt~w}Q62qe! zEcZP3&7TyiKOptEYW;nDdtNl?9XyA{sTwUAf9T;R3R7ad?WTQ zG6)gS^xrgE;7?QoxkjxA0C1bUxeS&fgAd%1NCI`qJ$-JAoWyvESmIqlwUL+?zS`em z?u%b_uU}0BTF2JqKce@UE73)jV+er$>nNg>pGq;Mq83rJ7GpmE literal 0 HcmV?d00001 diff --git a/lectures/intro.md b/lectures/intro.md index e8957b8d..7ca20f2e 100644 --- a/lectures/intro.md +++ b/lectures/intro.md @@ -11,7 +11,7 @@ kernelspec: # Quantitative Economics with Julia -This website presents a set of lectures on quantitative economic modeling, designed and written by [Jesse Perla](https://www.jesseperla.com), [Thomas J. Sargent](http://www.tomsargent.com/) and [John Stachurski](http://johnstachurski.net/). The language instruction is Julia. +This website presents a set of lectures on quantitative economic modeling. ```{tableofcontents} ``` \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index e2869105..b4a8b16c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ jupyter-book==0.15.1 -quantecon-book-theme==0.5.3 +quantecon-book-theme==0.7.1 sphinx-tojupyter==0.3.0 sphinxext.rediraffe==0.2.7 \ No newline at end of file From 4b7cf91c02b23a1aa7193e6731647cac1277f707 Mon Sep 17 00:00:00 2001 From: Trang Truong <91804044+htrangtr@users.noreply.github.com> Date: Sat, 30 Dec 2023 10:46:30 -0800 Subject: [PATCH 13/26] edit unicode conversion (#280) * edit latex missing \ * basic edits of unicode typos and missing space * edit unicode and add commas * add + for some functions --- lectures/tools_and_techniques/geom_series.md | 6 +++--- .../iterative_methods_sparsity.md | 6 +++--- lectures/tools_and_techniques/linear_algebra.md | 6 +++--- .../tools_and_techniques/numerical_linear_algebra.md | 12 ++++++------ 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lectures/tools_and_techniques/geom_series.md b/lectures/tools_and_techniques/geom_series.md index 0ad2dc00..362026c5 100644 --- a/lectures/tools_and_techniques/geom_series.md +++ b/lectures/tools_and_techniques/geom_series.md @@ -499,7 +499,7 @@ in a project with gross one period nominal rate of return accumulates project - thus, $1$ dollar invested at time $0$ pays interest $r$ dollars after one period, so we have $r+1 = R$ - dollars at time$1$ + dollars at time $1$ - at time $1$ we reinvest $1+r =R$ dollars and receive interest of $r R$ dollars at time $2$ plus the *principal* $R$ dollars, so we receive $r R + R = (1+r)R = R^2$ @@ -551,7 +551,7 @@ The **present value** of the lease is $$ \begin{aligned} -p_0 & = x_0 + x_1/R + x_2/(R^2) + \ddots \\ +p_0 & = x_0 + x_1/R + x_2/(R^2) + \cdots \\ & = x_0 (1 + G R^{-1} + G^2 R^{-2} + \cdots ) \\ & = x_0 \frac{1}{1 - G R^{-1}} \end{aligned} @@ -704,7 +704,7 @@ plot!(plt, T, y_3, label = L"$T$-period Lease First-order Approx. adj.") Evidently our approximations perform well for small values of $T$. -However, holding $g$ and r fixed, our approximations deteriorate as $T$ increases. +However, holding $g$ and $r$ fixed, our approximations deteriorate as $T$ increases. Next we compare the infinite and finite duration lease present values over different lease lengths $T$. diff --git a/lectures/tools_and_techniques/iterative_methods_sparsity.md b/lectures/tools_and_techniques/iterative_methods_sparsity.md index 42896d18..48fe8f1d 100644 --- a/lectures/tools_and_techniques/iterative_methods_sparsity.md +++ b/lectures/tools_and_techniques/iterative_methods_sparsity.md @@ -457,7 +457,7 @@ equation through methods such as value-function iteration. The condition we will examine here is called [**diagonal dominance**](https://en.wikipedia.org/wiki/Diagonally_dominant_matrix). $$ -|A_{ii}| \geq \sum_{j\neq i} |A_{ij}| \quad\text{for all } i = 1\ldots N +|A_{ii}| \geq \sum_{j\neq i} |A_{ij}| \quad\text{for all } i = 1, \ldots N $$ That is, in every row, the diagonal element is weakly greater in absolute value than the sum of all of the other elements in the row. In cases @@ -466,7 +466,7 @@ where it is strictly greater, we say that the matrix is strictly diagonally domi With our example, given that $Q$ is the infinitesimal generator of a Markov chain, we know that each row sums to 0, and hence it is weakly diagonally dominant. -However, notice that when $\rho > 0$, and since the diagonal of $Q$ is negative, $A = rho I - Q$ makes the matrix strictly diagonally dominant. +However, notice that when $\rho > 0$, and since the diagonal of $Q$ is negative, $A = \rho I - Q$ makes the matrix strictly diagonally dominant. ### Jacobi Iteration @@ -1187,7 +1187,7 @@ $$ If $Q$ is a matrix, we could just take its transpose to find the adoint. However, with matrix-free methods, we need to implement the adjoint-vector product directly. -The logic for the adjoint is that for a given $n = (n_1,\ldots, n_m, \ldots n_M)$, the $Q^T$ product for that row has terms enter when +The logic for the adjoint is that for a given $n = (n_1,\ldots, n_m, \ldots, n_M)$, the $Q^T$ product for that row has terms enter when 1. $1 < n_m \leq N$, entering into the identical $n$ except with one less customer in the $m$ position 1. $1 \leq n_m < N$, entering into the identical $n$ except with one more customer in the $m$ position diff --git a/lectures/tools_and_techniques/linear_algebra.md b/lectures/tools_and_techniques/linear_algebra.md index 397090ad..10f9689e 100644 --- a/lectures/tools_and_techniques/linear_algebra.md +++ b/lectures/tools_and_techniques/linear_algebra.md @@ -402,7 +402,7 @@ $m > n$ vectors in $\mathbb R ^n$ must be linearly dependent. The following statements are equivalent to linear independence of $A := \{a_1, \ldots, a_k\} \subset \mathbb R ^n$. 1. No vector in $A$ can be formed as a linear combination of the other elements. -1. If $\beta_1 a_1 + \cdots \beta_k a_k = 0$ for scalars $\beta_1, \ldots, \beta_k$, then $\beta_1 = \cdots = \beta_k = 0$. +1. If $\beta_1 a_1 + \cdots + \beta_k a_k = 0$ for scalars $\beta_1, \ldots, \beta_k$, then $\beta_1 = \cdots = \beta_k = 0$. (The zero in the first expression is the origin of $\mathbb R ^n$) @@ -415,13 +415,13 @@ In other words, if $A := \{a_1, \ldots, a_k\} \subset \mathbb R ^n$ is linearly independent and $$ -y = \beta_1 a_1 + \cdots \beta_k a_k +y = \beta_1 a_1 + \cdots + \beta_k a_k $$ then no other coefficient sequence $\gamma_1, \ldots, \gamma_k$ will produce the same vector $y$. -Indeed, if we also have $y = \gamma_1 a_1 + \cdots \gamma_k a_k$, +Indeed, if we also have $y = \gamma_1 a_1 + \cdots + \gamma_k a_k$, then $$ diff --git a/lectures/tools_and_techniques/numerical_linear_algebra.md b/lectures/tools_and_techniques/numerical_linear_algebra.md index 749eec56..19d93766 100644 --- a/lectures/tools_and_techniques/numerical_linear_algebra.md +++ b/lectures/tools_and_techniques/numerical_linear_algebra.md @@ -626,7 +626,7 @@ Q = Tridiagonal(fill(alpha, N - 1), [-alpha; fill(-2alpha, N - 2); -alpha], Here we can use `Tridiagonal` to exploit the structure of the problem. -Consider a simple payoff vector $r$ associated with each state, and a discount rate $rho$. Then we can solve for +Consider a simple payoff vector $r$ associated with each state, and a discount rate $\rho$. Then we can solve for the expected present discounted value in a way similar to the discrete-time case. $$ @@ -655,23 +655,23 @@ linear problem. v = A \ r ``` -The $Q$ is also used to calculate the evolution of the Markov chain, in direct analogy to the $psi_{t+k} = psi_t P^k$ evolution with the transition matrix $P$ of the discrete case. +The $Q$ is also used to calculate the evolution of the Markov chain, in direct analogy to the $\psi_{t+k} = \psi_t P^k$ evolution with the transition matrix $P$ of the discrete case. In the continuous case, this becomes the system of linear differential equations $$ -\dot{psi}(t) = Q(t)^T psi(t) +\dot{\psi}(t) = Q(t)^T \psi(t) $$ given the initial condition $\psi(0)$ and where the $Q(t)$ intensity matrix is allowed to vary with time. In the simplest case of a constant $Q$ matrix, this is a simple constant-coefficient system of linear ODEs with coefficients $Q^T$. -If a stationary equilibrium exists, note that $\dot{psi}(t) = 0$, and the stationary solution $psi^{*}$ needs to satisfy +If a stationary equilibrium exists, note that $\dot{\psi}(t) = 0$, and the stationary solution $\psi^{*}$ needs to satisfy $$ -0 = Q^T psi^{*} +0 = Q^T \psi^{*} $$ -Notice that this is of the form $0 psi^{*} = Q^T psi^{*}$ and hence is equivalent to finding the eigenvector associated with the $\lambda = 0$ eigenvalue of $Q^T$. +Notice that this is of the form $0 \psi^{*} = Q^T \psi^{*}$ and hence is equivalent to finding the eigenvector associated with the $\lambda = 0$ eigenvalue of $Q^T$. With our example, we can calculate all of the eigenvalues and eigenvectors From bf0ae39a3ec344383b05da210e94aa5de225e678 Mon Sep 17 00:00:00 2001 From: Jesse Perla Date: Tue, 2 Jan 2024 22:22:09 -0800 Subject: [PATCH 14/26] Julia 1.10 support (#283) * Julia 1.10 updates in progress * Fixed regressions with Julia 1.10 --- .github/workflows/cache.yml | 2 +- .github/workflows/ci.yml | 2 +- .github/workflows/format.yml | 2 +- .github/workflows/publish.yml | 2 +- .gitignore | 4 +- README.md | 12 +- lectures/Manifest.toml | 1438 +++++++++-------- lectures/Project.toml | 6 +- lectures/_config.yml | 4 +- lectures/about_lectures.md | 2 +- lectures/continuous_time/covid_sde.md | 2 +- lectures/continuous_time/seir_model.md | 2 +- lectures/dynamic_programming/career.md | 2 +- .../coleman_policy_iter.md | 2 +- lectures/dynamic_programming/discrete_dp.md | 2 +- .../dynamic_programming/egm_policy_iter.md | 2 +- lectures/dynamic_programming/ifp.md | 2 +- lectures/dynamic_programming/jv.md | 2 +- lectures/dynamic_programming/lqcontrol.md | 2 +- lectures/dynamic_programming/mccall_model.md | 2 +- .../mccall_model_with_separation.md | 2 +- lectures/dynamic_programming/odu.md | 2 +- lectures/dynamic_programming/optgrowth.md | 2 +- lectures/dynamic_programming/perm_income.md | 2 +- .../dynamic_programming/perm_income_cons.md | 2 +- lectures/dynamic_programming/robustness.md | 2 +- lectures/dynamic_programming/smoothing.md | 2 +- lectures/dynamic_programming/wald_friedman.md | 10 +- lectures/dynamic_programming_squared/amss.md | 10 +- .../dynamic_programming_squared/dyn_stack.md | 2 +- .../dynamic_programming_squared/lqramsey.md | 2 +- .../opt_tax_recur.md | 2 +- .../fundamental_types.md | 2 +- .../getting_started_julia/getting_started.md | 2 +- .../introduction_to_types.md | 2 +- .../getting_started_julia/julia_by_example.md | 2 +- .../getting_started_julia/julia_essentials.md | 2 +- .../introduction_dynamics/ar1_processes.md | 2 +- .../introduction_dynamics/finite_markov.md | 2 +- lectures/introduction_dynamics/kalman.md | 2 +- .../introduction_dynamics/linear_models.md | 2 +- .../introduction_dynamics/scalar_dynam.md | 2 +- lectures/introduction_dynamics/short_path.md | 2 +- .../introduction_dynamics/wealth_dynamics.md | 2 +- .../more_julia/data_statistical_packages.md | 2 +- lectures/more_julia/general_packages.md | 2 +- lectures/more_julia/generic_programming.md | 2 +- .../optimization_solver_packages.md | 128 +- lectures/multi_agent_models/aiyagari.md | 2 +- lectures/multi_agent_models/arellano.md | 2 +- lectures/multi_agent_models/harrison_kreps.md | 2 +- lectures/multi_agent_models/lake_model.md | 2 +- lectures/multi_agent_models/lucas_model.md | 2 +- lectures/multi_agent_models/markov_asset.md | 2 +- lectures/multi_agent_models/markov_perf.md | 2 +- lectures/multi_agent_models/matsuyama.md | 2 +- .../rational_expectations.md | 2 +- lectures/multi_agent_models/schelling.md | 2 +- .../multi_agent_models/uncertainty_traps.md | 2 +- .../software_engineering/need_for_speed.md | 2 +- lectures/software_engineering/testing.md | 2 +- .../software_engineering/tools_editors.md | 2 +- .../software_engineering/version_control.md | 2 +- lectures/status.md | 2 +- .../additive_functionals.md | 2 +- lectures/time_series_models/arma.md | 2 +- .../time_series_models/classical_filtering.md | 2 +- lectures/time_series_models/estspec.md | 2 +- lectures/time_series_models/lu_tricks.md | 2 +- .../multiplicative_functionals.md | 2 +- lectures/tools_and_techniques/geom_series.md | 2 +- .../iterative_methods_sparsity.md | 35 +- .../tools_and_techniques/linear_algebra.md | 2 +- lectures/tools_and_techniques/lln_clt.md | 2 +- .../numerical_linear_algebra.md | 4 +- lectures/tools_and_techniques/orth_proj.md | 2 +- .../stationary_densities.md | 2 +- lectures/troubleshooting.md | 2 +- lectures/zreferences.md | 2 +- 79 files changed, 877 insertions(+), 912 deletions(-) diff --git a/.github/workflows/cache.yml b/.github/workflows/cache.yml index 8446fc4b..67bdcd61 100644 --- a/.github/workflows/cache.yml +++ b/.github/workflows/cache.yml @@ -37,7 +37,7 @@ jobs: - name: Set up Julia uses: julia-actions/setup-julia@v1 with: - version: 1.9 + version: 1.10.0 - name: Install IJulia and Setup Project shell: bash run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c500be5e..66e57904 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: - name: Set up Julia uses: julia-actions/setup-julia@v1 with: - version: 1.9 + version: 1.10.0 - name: Install IJulia and Setup Project shell: bash run: | diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index df510876..30f3087e 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -17,7 +17,7 @@ jobs: - name: Setup Julia uses: julia-actions/setup-julia@v1 with: - version: 1.9 + version: 1.10.0 - name: Install JuliaFormatter.jl run: julia -e 'import Pkg; Pkg.add("JuliaFormatter")' diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 89d80144..dad8ec55 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -35,7 +35,7 @@ jobs: - name: Set up Julia uses: julia-actions/setup-julia@v1 with: - version: 1.9 + version: 1.10.0 - name: Install IJulia and Setup Project shell: bash run: | diff --git a/.gitignore b/.gitignore index e00f5c0b..b23096d0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ _build -us_cities.txt \ No newline at end of file +us_cities.txt +.DS_Store +.vscode diff --git a/README.md b/README.md index fe71ad3d..bf018b82 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ It is straightforward to install the Jupyter Book and Julia software necessary f 7. Start a VS Code terminal with ```` or through any other method. Create a conda environment. ```bash - conda create -n lecture-julia.myst python=3.9 + conda create -n lecture-julia.myst python=3.11 conda activate lecture-julia.myst pip install -r requirements.txt ``` @@ -62,13 +62,9 @@ As a helper, you can call a shell script to do it for an entire folder bash format_all_directory.sh lectures/dynamic_programming ``` or to also do the unicode substitutions -```bash bash format_all_directory.sh lectures/dynamic_programming true ``` -Alternatively, the formatter will run automatically when a pull-request is made - - **(Optional) REPL Integration** With [MyST-Markdown](https://github.com/executablebooks/myst-vs-code) and [Julia](https://marketplace.visualstudio.com/items?itemName=julialang.language-julia) installed, you can ensure that pressing `` on lines of code are sent to a Julia REPL. 1. Open Key Bindings with ``. @@ -84,6 +80,7 @@ If you installed the REPL Integration above, then in a `.md` file, 3. Then, assuming that you set up the keybindings above, you can send a line of code in the markdown to the REPL with ``. Code can be executed line by line, or you can select a chunk of code and execute it. + ## Example Operations ### Building the lectures To do a full build of the lectures: @@ -100,7 +97,7 @@ jb build lectures This will take a while. But it will populate your cache, so future iteration is faster. -On Windows, if you get the following error: +It is suggested to use WSL on Windows On Windows, if you get the following error: ``` ImportError: DLL load failed while importing win32api: The specified procedure could not be found. @@ -132,5 +129,4 @@ jb clean lectures --all After execution, you can find the generated `.ipynb` and `.jl` files in `_build/jupyter_execute` for each lecture. - To see errors, you can open these in JupyterLab, the Jupyter support within VS Code, etc. -- If using the Julia REPL in VS Code, make sure to do `] activate lectures` prior to testing to ensure the packages are activated. This is not necessary when opening in Jupyter. -- Finally, the code is written using interactive scoping, so `include(_build/jupyter_execute/dynamic_programming/mccall_model.jl)` etc. may not work. However, `shift-enter` within VS Code to the REPL will work, and you can execute these with [SoftGlobalScope.jl](https://github.com/stevengj/SoftGlobalScope.jl) if strictly required. +- If using the Julia REPL in VS Code, make sure to do `] activate lectures` prior to testing to ensure the packages are activated. This is not necessary when opening in Jupyter. \ No newline at end of file diff --git a/lectures/Manifest.toml b/lectures/Manifest.toml index 05cdb251..5202eeb7 100644 --- a/lectures/Manifest.toml +++ b/lectures/Manifest.toml @@ -1,19 +1,19 @@ # This file is machine-generated - editing it directly is not advised -julia_version = "1.9.1" +julia_version = "1.10.0" manifest_format = "2.0" -project_hash = "426ee44181a1827c854acad97427614830a3ef74" +project_hash = "bbafb0ad34fec16511b07a132895ce6672068cfe" [[deps.ADTypes]] -git-tree-sha1 = "dcfdf328328f2645531c4ddebf841228aef74130" +git-tree-sha1 = "41c37aa88889c171f1300ceac1313c06e891d245" uuid = "47edcb42-4c32-4615-8424-f2b9edc5f35b" -version = "0.1.3" +version = "0.2.6" [[deps.AMD]] -deps = ["Libdl", "LinearAlgebra", "SparseArrays", "Test"] -git-tree-sha1 = "00163dc02b882ca5ec032400b919e5f5011dbd31" +deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse_jll"] +git-tree-sha1 = "45a1272e3f809d36431e57ab22703c6896b8908f" uuid = "14f7f29c-3bd6-536c-9a0b-7339e30b5a3e" -version = "0.5.0" +version = "0.5.3" [[deps.ASL_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -22,20 +22,21 @@ uuid = "ae81ac8f-d209-56e5-92de-9978fef736f9" version = "0.1.3+0" [[deps.AbstractAlgebra]] -deps = ["GroupsCore", "InteractiveUtils", "LinearAlgebra", "MacroTools", "Markdown", "Random", "RandomExtensions", "SparseArrays", "Test"] -git-tree-sha1 = "29e65c331f97db9189ef00a4c7aed8127c2fd2d4" +deps = ["GroupsCore", "InteractiveUtils", "LinearAlgebra", "MacroTools", "Preferences", "Random", "RandomExtensions", "SparseArrays", "Test"] +git-tree-sha1 = "d7832de8cf7af26abac741f10372080ac6cb73df" uuid = "c3fe647b-3220-5bb0-a1ea-a7954cac585d" -version = "0.27.10" +version = "0.34.7" [[deps.AbstractFFTs]] deps = ["LinearAlgebra"] -git-tree-sha1 = "16b6dbc4cf7caee4e1e75c49485ec67b667098a0" +git-tree-sha1 = "d92ad398961a3ed262d8bf04a1a2b8340f915fef" uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c" -version = "1.3.1" -weakdeps = ["ChainRulesCore"] +version = "1.5.0" +weakdeps = ["ChainRulesCore", "Test"] [deps.AbstractFFTs.extensions] AbstractFFTsChainRulesCoreExt = "ChainRulesCore" + AbstractFFTsTestExt = "Test" [[deps.AbstractTrees]] git-tree-sha1 = "faa260e4cb5aba097a73fab382dd4b5819d8ec8c" @@ -44,9 +45,9 @@ version = "0.4.4" [[deps.Adapt]] deps = ["LinearAlgebra", "Requires"] -git-tree-sha1 = "76289dc51920fdc6e0013c872ba9551d54961c24" +git-tree-sha1 = "cde29ddf7e5726c9fb511f340244ea3481267608" uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" -version = "3.6.2" +version = "3.7.2" weakdeps = ["StaticArrays"] [deps.Adapt.extensions] @@ -82,9 +83,9 @@ version = "3.5.1+1" [[deps.ArrayInterface]] deps = ["Adapt", "LinearAlgebra", "Requires", "SparseArrays", "SuiteSparse"] -git-tree-sha1 = "d3f758863a47ceef2248d136657cb9c033603641" +git-tree-sha1 = "bbec08a37f8722786d87bedf84eae19c020c4efa" uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" -version = "7.4.8" +version = "7.7.0" [deps.ArrayInterface.extensions] ArrayInterfaceBandedMatricesExt = "BandedMatrices" @@ -102,27 +103,19 @@ version = "7.4.8" StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" -[[deps.ArrayInterfaceCore]] -deps = ["LinearAlgebra", "SnoopPrecompile", "SparseArrays", "SuiteSparse"] -git-tree-sha1 = "e5f08b5689b1aad068e01751889f2f615c7db36d" -uuid = "30b0a656-2188-435a-8636-2ec0e6a096e2" -version = "0.1.29" - [[deps.ArrayLayouts]] -deps = ["FillArrays", "LinearAlgebra", "SparseArrays"] -git-tree-sha1 = "4aff5fa660eb95c2e0deb6bcdabe4d9a96bc4667" +deps = ["FillArrays", "LinearAlgebra"] +git-tree-sha1 = "b08a4043e1c14096ef8efe4dd97e07de5cacf240" uuid = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" -version = "0.8.18" +version = "1.4.5" +weakdeps = ["SparseArrays"] + + [deps.ArrayLayouts.extensions] + ArrayLayoutsSparseArraysExt = "SparseArrays" [[deps.Artifacts]] uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" -[[deps.Atomix]] -deps = ["UnsafeAtomics"] -git-tree-sha1 = "c06a868224ecba914baa6942988e2f2aade419be" -uuid = "a9b6321e-bd34-4604-b9c9-b65b8de01458" -version = "0.1.0" - [[deps.AxisAlgorithms]] deps = ["LinearAlgebra", "Random", "SparseArrays", "WoodburyMatrices"] git-tree-sha1 = "66771c8d21c8ff5e3a93379480a2307ac36863f7" @@ -130,29 +123,33 @@ uuid = "13072b0f-2c55-5437-9ae7-d433b7a33950" version = "1.0.1" [[deps.BandedMatrices]] -deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra", "SnoopPrecompile", "SparseArrays"] -git-tree-sha1 = "6ef8fc1d77b60f41041d59ce61ef9eb41ed97a83" +deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra", "PrecompileTools"] +git-tree-sha1 = "27baf04c642465b4289179f29bb7127f0673d4f1" uuid = "aae01518-5342-5314-be14-df237901396f" -version = "0.17.18" +version = "1.4.0" +weakdeps = ["SparseArrays"] + + [deps.BandedMatrices.extensions] + BandedMatricesSparseArraysExt = "SparseArrays" [[deps.Base64]] uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" [[deps.BenchmarkTools]] deps = ["JSON", "Logging", "Printf", "Profile", "Statistics", "UUIDs"] -git-tree-sha1 = "d9a9701b899b30332bbcb3e1679c41cce81fb0e8" +git-tree-sha1 = "f1f03a9fa24271160ed7e73051fba3c1a759b53f" uuid = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" -version = "1.3.2" +version = "1.4.0" [[deps.Bijections]] -git-tree-sha1 = "fe4f8c5ee7f76f2198d5c2a06d3961c249cce7bd" +git-tree-sha1 = "c9b163bd832e023571e86d0b90d9de92a9879088" uuid = "e2ed5e7c-b2de-5872-ae92-c73ca462fb04" -version = "0.1.4" +version = "0.1.6" [[deps.BitFlags]] -git-tree-sha1 = "43b1a4a8f797c1cddadf60499a8a077d4af2cd2d" +git-tree-sha1 = "2dc09997850d68179b69dafb58ae806167a32b1b" uuid = "d1d4a3ce-64b1-5f1a-9ba4-7e7e69966f35" -version = "0.1.7" +version = "0.1.8" [[deps.BitTwiddlingConvenienceFunctions]] deps = ["Static"] @@ -160,51 +157,23 @@ git-tree-sha1 = "0c5f81f47bbbcf4aea7b2959135713459170798b" uuid = "62783981-4cbd-42fc-bca8-16325de8dc4b" version = "0.1.5" -[[deps.BlackBoxOptim]] -deps = ["CPUTime", "Compat", "Distributed", "Distributions", "HTTP", "JSON", "LinearAlgebra", "Printf", "Random", "SpatialIndexing", "StatsBase"] -git-tree-sha1 = "136079f37e3514ec691926093924b591a8842f5d" -uuid = "a134a8b2-14d6-55f6-9291-3336d3ab0209" -version = "0.6.2" - -[[deps.BlockArrays]] -deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra"] -git-tree-sha1 = "3b15c61bcece7c426ea641d143c808ace3661973" -uuid = "8e7c35d0-a365-5155-bbbb-fb81a777f24e" -version = "0.16.25" - -[[deps.BlockBandedMatrices]] -deps = ["ArrayLayouts", "BandedMatrices", "BlockArrays", "FillArrays", "LinearAlgebra", "MatrixFactorizations", "SparseArrays", "Statistics"] -git-tree-sha1 = "f389a2752664c4103f9c481b4766d7eed78ad85b" -uuid = "ffab5731-97b5-5995-9138-79e8c1846df0" -version = "0.11.10" - [[deps.Bzip2_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] git-tree-sha1 = "19a35467a82e236ff51bc17a3a44b69ef35185a2" uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0" version = "1.0.8+0" -[[deps.CEnum]] -git-tree-sha1 = "eb4cb44a499229b3b8426dcfb5dd85333951ff90" -uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82" -version = "0.4.2" - [[deps.CPUSummary]] deps = ["CpuId", "IfElse", "PrecompileTools", "Static"] -git-tree-sha1 = "89e0654ed8c7aebad6d5ad235d6242c2d737a928" +git-tree-sha1 = "601f7e7b3d36f18790e2caf83a882d88e9b71ff1" uuid = "2a0fbf3d-bb9c-48f3-b0a9-814d99fd7ab9" -version = "0.2.3" - -[[deps.CPUTime]] -git-tree-sha1 = "2dcc50ea6a0a1ef6440d6eecd0fe3813e5671f45" -uuid = "a9c8d775-2e2e-55fc-8582-045d282d599e" -version = "1.0.0" +version = "0.2.4" [[deps.CSV]] deps = ["CodecZlib", "Dates", "FilePathsBase", "InlineStrings", "Mmap", "Parsers", "PooledArrays", "PrecompileTools", "SentinelArrays", "Tables", "Unicode", "WeakRefStrings", "WorkerUtilities"] -git-tree-sha1 = "44dbf560808d49041989b8a96cae4cffbeb7966a" +git-tree-sha1 = "679e69c611fff422038e9e21e270c4197d49d918" uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" -version = "0.10.11" +version = "0.10.12" [[deps.Cairo_jll]] deps = ["Artifacts", "Bzip2_jll", "CompilerSupportLibraries_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"] @@ -241,17 +210,15 @@ git-tree-sha1 = "8c4920235f6c561e401dfe569beb8b924adad003" uuid = "8be319e6-bccf-4806-a6f7-6fae938471bc" version = "0.5.0" -[[deps.ChainRules]] -deps = ["Adapt", "ChainRulesCore", "Compat", "Distributed", "GPUArraysCore", "IrrationalConstants", "LinearAlgebra", "Random", "RealDot", "SparseArrays", "Statistics", "StructArrays"] -git-tree-sha1 = "82e2d776be8bef478792d6cba65b06b16952f8ba" -uuid = "082447d4-558c-5d27-93f4-14fc19e9eca2" -version = "1.50.0" - [[deps.ChainRulesCore]] -deps = ["Compat", "LinearAlgebra", "SparseArrays"] -git-tree-sha1 = "e30f2f4e20f7f186dc36529910beaedc60cfa644" +deps = ["Compat", "LinearAlgebra"] +git-tree-sha1 = "2118cb2765f8197b08e5958cdd17c165427425ee" uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" -version = "1.16.0" +version = "1.19.0" +weakdeps = ["SparseArrays"] + + [deps.ChainRulesCore.extensions] + ChainRulesCoreSparseArraysExt = "SparseArrays" [[deps.CloseOpenIntervals]] deps = ["Static", "StaticArrayInterface"] @@ -261,27 +228,27 @@ version = "0.1.12" [[deps.Clustering]] deps = ["Distances", "LinearAlgebra", "NearestNeighbors", "Printf", "Random", "SparseArrays", "Statistics", "StatsBase"] -git-tree-sha1 = "a6e6ce44a1e0a781772fc795fb7343b1925e9898" +git-tree-sha1 = "407f38961ac11a6e14b2df7095a2577f7cb7cb1b" uuid = "aaaa29a8-35af-508c-8bc3-b662a17a0fe5" -version = "0.15.2" +version = "0.15.6" [[deps.CodecBzip2]] deps = ["Bzip2_jll", "Libdl", "TranscodingStreams"] -git-tree-sha1 = "2e62a725210ce3c3c2e1a3080190e7ca491f18d7" +git-tree-sha1 = "c0ae2a86b162fb5d7acc65269b469ff5b8a73594" uuid = "523fee87-0ab8-5b00-afb7-3ecf72e48cfd" -version = "0.7.2" +version = "0.8.1" [[deps.CodecZlib]] deps = ["TranscodingStreams", "Zlib_jll"] -git-tree-sha1 = "9c209fb7536406834aa938fb149964b985de6c83" +git-tree-sha1 = "cd67fc487743b2f0fd4380d4cbd3a24660d0eec8" uuid = "944b1d66-785c-5afd-91f1-9de20f533193" -version = "0.7.1" +version = "0.7.3" [[deps.ColorSchemes]] deps = ["ColorTypes", "ColorVectorSpace", "Colors", "FixedPointNumbers", "PrecompileTools", "Random"] -git-tree-sha1 = "be6ab11021cd29f0344d5c4357b163af05a48cba" +git-tree-sha1 = "67c1f244b991cad9b0aa4b7540fb758c2488b129" uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4" -version = "3.21.0" +version = "3.24.0" [[deps.ColorTypes]] deps = ["FixedPointNumbers", "Random"] @@ -290,10 +257,14 @@ uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" version = "0.11.4" [[deps.ColorVectorSpace]] -deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "SpecialFunctions", "Statistics", "TensorCore"] -git-tree-sha1 = "600cc5508d66b78aae350f7accdb58763ac18589" +deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "Requires", "Statistics", "TensorCore"] +git-tree-sha1 = "a1f44953f2382ebb937d60dafbe2deea4bd23249" uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4" -version = "0.9.10" +version = "0.10.0" +weakdeps = ["SpecialFunctions"] + + [deps.ColorVectorSpace.extensions] + SpecialFunctionsExt = "SpecialFunctions" [[deps.Colors]] deps = ["ColorTypes", "FixedPointNumbers", "Reexport"] @@ -319,9 +290,9 @@ version = "0.3.0" [[deps.Compat]] deps = ["UUIDs"] -git-tree-sha1 = "7a60c856b9fa189eb34f5f8a6f6b5529b7942957" +git-tree-sha1 = "886826d76ea9e72b35fcd000e535588f7b60f21d" uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" -version = "4.6.1" +version = "4.10.1" weakdeps = ["Dates", "LinearAlgebra"] [deps.Compat.extensions] @@ -330,24 +301,29 @@ weakdeps = ["Dates", "LinearAlgebra"] [[deps.CompilerSupportLibraries_jll]] deps = ["Artifacts", "Libdl"] uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" -version = "1.0.2+0" +version = "1.0.5+1" [[deps.CompositeTypes]] git-tree-sha1 = "02d2316b7ffceff992f3096ae48c7829a8aa0638" uuid = "b152e2b5-7a66-4b01-a709-34e65c35f657" version = "0.1.3" +[[deps.ConcreteStructs]] +git-tree-sha1 = "f749037478283d372048690eb3b5f92a79432b34" +uuid = "2569d6c7-a4a2-43d3-a901-331e8e4be471" +version = "0.2.3" + [[deps.ConcurrentUtilities]] deps = ["Serialization", "Sockets"] -git-tree-sha1 = "96d823b94ba8d187a6d8f0826e731195a74b90e9" +git-tree-sha1 = "8cfa272e8bdedfa88b6aefbbca7c19f1befac519" uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb" -version = "2.2.0" +version = "2.3.0" [[deps.ConstructionBase]] deps = ["LinearAlgebra"] -git-tree-sha1 = "738fec4d684a9a6ee9598a8bfee305b26831f28c" +git-tree-sha1 = "c53fc348ca4d40d7b371e71fd52251839080cbc9" uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9" -version = "1.5.2" +version = "1.5.4" weakdeps = ["IntervalSets", "StaticArrays"] [deps.ConstructionBase.extensions] @@ -372,9 +348,9 @@ version = "4.1.1" [[deps.DSP]] deps = ["Compat", "FFTW", "IterTools", "LinearAlgebra", "Polynomials", "Random", "Reexport", "SpecialFunctions", "Statistics"] -git-tree-sha1 = "da8b06f89fce9996443010ef92572b193f8dca1f" +git-tree-sha1 = "f7f4319567fe769debfcf7f8c03d8da1dd4e2fb0" uuid = "717857b8-e6f2-59f4-9121-6e50c889abd2" -version = "0.7.8" +version = "0.7.9" [[deps.DataAPI]] git-tree-sha1 = "8da84edb865b0b5b0100c0666a9bc9a0b71c553c" @@ -382,40 +358,41 @@ uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" version = "1.15.0" [[deps.DataFrames]] -deps = ["Compat", "DataAPI", "Future", "InlineStrings", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrettyTables", "Printf", "REPL", "Random", "Reexport", "SentinelArrays", "SnoopPrecompile", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"] -git-tree-sha1 = "aa51303df86f8626a962fccb878430cdb0a97eee" +deps = ["Compat", "DataAPI", "DataStructures", "Future", "InlineStrings", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrecompileTools", "PrettyTables", "Printf", "REPL", "Random", "Reexport", "SentinelArrays", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"] +git-tree-sha1 = "04c738083f29f86e62c8afc341f0967d8717bdb8" uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" -version = "1.5.0" +version = "1.6.1" [[deps.DataFramesMeta]] deps = ["Chain", "DataFrames", "MacroTools", "OrderedCollections", "Reexport"] -git-tree-sha1 = "7f13b2f9fa5fc843a06596f1cc917ed1a3d6740b" +git-tree-sha1 = "6970958074cd09727b9200685b8631b034c0eb16" uuid = "1313f7d8-7da2-5740-9ea0-a2ca25f37964" -version = "0.14.0" +version = "0.14.1" [[deps.DataInterpolations]] -deps = ["LinearAlgebra", "RecipesBase", "RecursiveArrayTools", "Reexport", "Requires"] -git-tree-sha1 = "e52a7c2388471ca6e7e6dcd68c98073f378b8967" +deps = ["LinearAlgebra", "PrettyTables", "RecipesBase", "Reexport", "Requires"] +git-tree-sha1 = "99f979d5e9b67c2aeee701c3683037ac8d75bdd6" uuid = "82cc6244-b520-54b8-b5a6-8a565e85f1d0" -version = "4.0.1" +version = "4.6.0" [deps.DataInterpolations.extensions] DataInterpolationsChainRulesCoreExt = "ChainRulesCore" - DataInterpolationsOptimExt = "Optim" + DataInterpolationsOptimExt = ["ForwardDiff", "Optim"] DataInterpolationsRegularizationToolsExt = "RegularizationTools" DataInterpolationsSymbolicsExt = "Symbolics" [deps.DataInterpolations.weakdeps] ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" Optim = "429524aa-4258-5aef-a3af-852621145aeb" RegularizationTools = "29dad682-9a27-4bc3-9c72-016788665182" Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" [[deps.DataStructures]] deps = ["Compat", "InteractiveUtils", "OrderedCollections"] -git-tree-sha1 = "d1fff3a548102f48987a52a2e0d114fa97d730f0" +git-tree-sha1 = "3dbd312d370723b6bb43ba9d02fc36abade4518d" uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" -version = "0.18.13" +version = "0.18.15" [[deps.DataValueInterfaces]] git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" @@ -439,13 +416,15 @@ uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab" version = "1.9.1" [[deps.DiffEqBase]] -deps = ["ArrayInterface", "ChainRulesCore", "DataStructures", "DocStringExtensions", "EnumX", "FastBroadcast", "ForwardDiff", "FunctionWrappers", "FunctionWrappersWrappers", "LinearAlgebra", "Logging", "Markdown", "MuladdMacro", "Parameters", "PreallocationTools", "Printf", "RecursiveArrayTools", "Reexport", "Requires", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Static", "StaticArraysCore", "Statistics", "Tricks", "TruncatedStacktraces", "ZygoteRules"] -git-tree-sha1 = "0a7dd11dd243a1f8c71f72f2e5fd54c0bfdeaaab" +deps = ["ArrayInterface", "DataStructures", "DocStringExtensions", "EnumX", "EnzymeCore", "FastBroadcast", "ForwardDiff", "FunctionWrappers", "FunctionWrappersWrappers", "LinearAlgebra", "Logging", "Markdown", "MuladdMacro", "Parameters", "PreallocationTools", "PrecompileTools", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Static", "StaticArraysCore", "Statistics", "Tricks", "TruncatedStacktraces"] +git-tree-sha1 = "53159da9fef2dd92815499e18f93b699ed54f397" uuid = "2b5f629d-d688-5b77-993f-72d75c75574e" -version = "6.125.1" +version = "6.145.5" [deps.DiffEqBase.extensions] + DiffEqBaseChainRulesCoreExt = "ChainRulesCore" DiffEqBaseDistributionsExt = "Distributions" + DiffEqBaseEnzymeExt = ["ChainRulesCore", "Enzyme"] DiffEqBaseGeneralizedGeneratedExt = "GeneralizedGenerated" DiffEqBaseMPIExt = "MPI" DiffEqBaseMeasurementsExt = "Measurements" @@ -453,10 +432,11 @@ version = "6.125.1" DiffEqBaseReverseDiffExt = "ReverseDiff" DiffEqBaseTrackerExt = "Tracker" DiffEqBaseUnitfulExt = "Unitful" - DiffEqBaseZygoteExt = "Zygote" [deps.DiffEqBase.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" + Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" GeneralizedGenerated = "6b9d7cbe-bcb9-11e9-073f-15a7a543e2eb" MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" @@ -464,13 +444,12 @@ version = "6.125.1" ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" - Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" [[deps.DiffEqNoiseProcess]] deps = ["DiffEqBase", "Distributions", "GPUArraysCore", "LinearAlgebra", "Markdown", "Optim", "PoissonRandom", "QuadGK", "Random", "Random123", "RandomNumbers", "RecipesBase", "RecursiveArrayTools", "Requires", "ResettableStacks", "SciMLBase", "StaticArraysCore", "Statistics"] -git-tree-sha1 = "50f82e2a705a544af539acc6a03674a4d7eee1d8" +git-tree-sha1 = "319377c927a4aa1f491228b2ac23f3554a3497c6" uuid = "77a26b50-5914-5dd7-bc55-306e6241c503" -version = "5.17.1" +version = "5.20.0" [deps.DiffEqNoiseProcess.extensions] DiffEqNoiseProcessReverseDiffExt = "ReverseDiff" @@ -478,12 +457,6 @@ version = "5.17.1" [deps.DiffEqNoiseProcess.weakdeps] ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" -[[deps.DiffEqOperators]] -deps = ["BandedMatrices", "BlockBandedMatrices", "DiffEqBase", "DomainSets", "ForwardDiff", "LazyArrays", "LazyBandedMatrices", "LinearAlgebra", "LoopVectorization", "NNlib", "Requires", "RuntimeGeneratedFunctions", "SciMLBase", "SparseArrays", "SparseDiffTools", "StaticArrays", "SuiteSparse"] -git-tree-sha1 = "ef0f24d69406bf85092c843691ab2ae3b2e34b77" -uuid = "9fdde737-9c7f-55bf-ade8-46b3f136cc48" -version = "4.45.0" - [[deps.DiffResults]] deps = ["StaticArraysCore"] git-tree-sha1 = "782dd5f4561f5d267313f23853baaaa4c52ea621" @@ -497,28 +470,35 @@ uuid = "b552c78f-8df3-52c6-915a-8e097449b14b" version = "1.15.1" [[deps.Distances]] -deps = ["LinearAlgebra", "SparseArrays", "Statistics", "StatsAPI"] -git-tree-sha1 = "49eba9ad9f7ead780bfb7ee319f962c811c6d3b2" +deps = ["LinearAlgebra", "Statistics", "StatsAPI"] +git-tree-sha1 = "66c4c81f259586e8f002eacebc177e1fb06363b0" uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7" -version = "0.10.8" +version = "0.10.11" +weakdeps = ["ChainRulesCore", "SparseArrays"] + + [deps.Distances.extensions] + DistancesChainRulesCoreExt = "ChainRulesCore" + DistancesSparseArraysExt = "SparseArrays" [[deps.Distributed]] deps = ["Random", "Serialization", "Sockets"] uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" [[deps.Distributions]] -deps = ["FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SparseArrays", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns", "Test"] -git-tree-sha1 = "c72970914c8a21b36bbc244e9df0ed1834a0360b" +deps = ["FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns"] +git-tree-sha1 = "9242eec9b7e2e14f9952e8ea1c7e31a50501d587" uuid = "31c24e10-a181-5473-b8eb-7969acd0382f" -version = "0.25.95" +version = "0.25.104" [deps.Distributions.extensions] DistributionsChainRulesCoreExt = "ChainRulesCore" DistributionsDensityInterfaceExt = "DensityInterface" + DistributionsTestExt = "Test" [deps.Distributions.weakdeps] ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" DensityInterface = "b429d917-457f-4dbc-8f4c-0cc954292b1d" + Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [[deps.DocStringExtensions]] deps = ["LibGit2"] @@ -528,9 +508,9 @@ version = "0.9.3" [[deps.DomainSets]] deps = ["CompositeTypes", "IntervalSets", "LinearAlgebra", "Random", "StaticArrays", "Statistics"] -git-tree-sha1 = "988e2db482abeb69efc76ae8b6eba2e93805ee70" +git-tree-sha1 = "51b4b84d33ec5e0955b55ff4b748b99ce2c3faa9" uuid = "5b8099bc-c8ec-5219-889f-1d9e522a28bf" -version = "0.5.15" +version = "0.6.7" [[deps.Downloads]] deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] @@ -544,38 +524,56 @@ uuid = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74" version = "0.6.8" [[deps.DynamicPolynomials]] -deps = ["DataStructures", "Future", "LinearAlgebra", "MultivariatePolynomials", "MutableArithmetics", "Pkg", "Reexport", "Test"] -git-tree-sha1 = "8b84876e31fa39479050e2d3395c4b3b210db8b0" +deps = ["Future", "LinearAlgebra", "MultivariatePolynomials", "MutableArithmetics", "Pkg", "Reexport", "Test"] +git-tree-sha1 = "fea68c84ba262b121754539e6ea0546146515d4f" uuid = "7c1d4256-1411-5781-91ec-d7bc3513ac07" -version = "0.4.6" +version = "0.5.3" [[deps.EnumX]] git-tree-sha1 = "bdb1942cd4c45e3c678fd11569d5cccd80976237" uuid = "4e289a0a-7415-4d19-859d-a7e5c4648b56" version = "1.0.4" +[[deps.EnzymeCore]] +deps = ["Adapt"] +git-tree-sha1 = "2efe862de93cd87f620ad6ac9c9e3f83f1b2841b" +uuid = "f151be2c-9106-41f4-ab19-57ee4f262869" +version = "0.6.4" + +[[deps.EpollShim_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "8e9441ee83492030ace98f9789a654a6d0b1f643" +uuid = "2702e6a9-849d-5ed8-8c21-79e8b8f9ee43" +version = "0.0.20230411+0" + +[[deps.ExceptionUnwrapping]] +deps = ["Test"] +git-tree-sha1 = "dcb08a0d93ec0b1cdc4af184b26b591e9695423a" +uuid = "460bff9d-24e4-43bc-9d9f-a8973cb893f4" +version = "0.1.10" + [[deps.Expat_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "bad72f730e9e91c08d9427d5e8db95478a3c323d" +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "4558ab818dcceaab612d1bb8c19cee87eda2b83c" uuid = "2e619515-83b5-522b-bb60-26c02a35a201" -version = "2.4.8+0" +version = "2.5.0+0" [[deps.Expectations]] deps = ["Distributions", "FastGaussQuadrature", "LinearAlgebra", "SpecialFunctions"] -git-tree-sha1 = "539c415ad6693bb7792be05a3e51e010c6795d95" +git-tree-sha1 = "5b46996cf6fc4ad19d1122884c36faa62ed0a7d2" uuid = "2fe49d83-0758-5602-8f54-1f90ad0d522b" -version = "1.9.0" +version = "1.9.2" [[deps.ExponentialUtilities]] -deps = ["Adapt", "ArrayInterface", "GPUArraysCore", "GenericSchur", "LinearAlgebra", "Printf", "SnoopPrecompile", "SparseArrays", "libblastrampoline_jll"] -git-tree-sha1 = "fb7dbef7d2631e2d02c49e2750f7447648b0ec9b" +deps = ["Adapt", "ArrayInterface", "GPUArraysCore", "GenericSchur", "LinearAlgebra", "PrecompileTools", "Printf", "SparseArrays", "libblastrampoline_jll"] +git-tree-sha1 = "602e4585bcbd5a25bc06f514724593d13ff9e862" uuid = "d4d017d3-3776-5f7e-afef-a10c40355c18" -version = "1.24.0" +version = "1.25.0" [[deps.ExprTools]] -git-tree-sha1 = "c1d06d129da9f55715c6c212866f5b1bddc5fa00" +git-tree-sha1 = "27415f162e6028e81c72b82ef756bf321213b6ec" uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04" -version = "0.1.9" +version = "0.1.10" [[deps.FFMPEG]] deps = ["FFMPEG_jll"] @@ -584,16 +582,16 @@ uuid = "c87230d0-a227-11e9-1b43-d7ebe4e7570a" version = "0.4.1" [[deps.FFMPEG_jll]] -deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "PCRE2_jll", "Pkg", "Zlib_jll", "libaom_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"] -git-tree-sha1 = "74faea50c1d007c85837327f6775bea60b5492dd" +deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "PCRE2_jll", "Zlib_jll", "libaom_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"] +git-tree-sha1 = "466d45dc38e15794ec7d5d63ec03d776a9aff36e" uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5" -version = "4.4.2+2" +version = "4.4.4+1" [[deps.FFTW]] deps = ["AbstractFFTs", "FFTW_jll", "LinearAlgebra", "MKL_jll", "Preferences", "Reexport"] -git-tree-sha1 = "06bf20fcecd258eccf9a6ef7b99856a4dfe7b64c" +git-tree-sha1 = "ec22cbbcd01cba8f41eecd7d44aac1f23ee985e3" uuid = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341" -version = "1.7.0" +version = "1.7.2" [[deps.FFTW_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -603,9 +601,9 @@ version = "3.3.10+0" [[deps.FastBroadcast]] deps = ["ArrayInterface", "LinearAlgebra", "Polyester", "Static", "StaticArrayInterface", "StrideArraysCore"] -git-tree-sha1 = "d1248fceea0b26493fd33e8e9e8c553270da03bd" +git-tree-sha1 = "a6e756a880fc419c8b41592010aebe6a5ce09136" uuid = "7034ab61-46d4-4ed7-9d0f-46aef9175898" -version = "0.2.5" +version = "0.2.8" [[deps.FastClosures]] git-tree-sha1 = "acebe244d53ee1b461970f8910c235b259e772ef" @@ -614,15 +612,15 @@ version = "0.3.2" [[deps.FastGaussQuadrature]] deps = ["LinearAlgebra", "SpecialFunctions", "StaticArrays"] -git-tree-sha1 = "0f478d8bad6f52573fb7658a263af61f3d96e43a" +git-tree-sha1 = "8ef0363cffeedb7e73339b664ce6d33cc278a3c4" uuid = "442a2c76-b920-505d-bb47-c5924d526838" -version = "0.5.1" +version = "1.0.1" [[deps.FastLapackInterface]] deps = ["LinearAlgebra"] -git-tree-sha1 = "c1293a93193f0ae94be7cf338d33e162c39d8788" +git-tree-sha1 = "b12f05108e405dadcc2aff0008db7f831374e051" uuid = "29a986be-02c6-4525-aec4-84b980013641" -version = "1.2.9" +version = "2.0.0" [[deps.FileIO]] deps = ["Pkg", "Requires", "UUIDs"] @@ -632,42 +630,60 @@ version = "1.16.1" [[deps.FilePathsBase]] deps = ["Compat", "Dates", "Mmap", "Printf", "Test", "UUIDs"] -git-tree-sha1 = "e27c4ebe80e8699540f2d6c805cc12203b614f12" +git-tree-sha1 = "9f00e42f8d99fdde64d40c8ea5d14269a2e2c1aa" uuid = "48062228-2e41-5def-b9a4-89aafe57970f" -version = "0.9.20" +version = "0.9.21" [[deps.FileWatching]] uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" [[deps.FillArrays]] -deps = ["LinearAlgebra", "Random", "SparseArrays", "Statistics"] -git-tree-sha1 = "7072f1e3e5a8be51d525d64f63d3ec1287ff2790" +deps = ["LinearAlgebra", "Random"] +git-tree-sha1 = "5b93957f6dcd33fc343044af3d48c215be2562f1" uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" -version = "0.13.11" +version = "1.9.3" +weakdeps = ["PDMats", "SparseArrays", "Statistics"] + + [deps.FillArrays.extensions] + FillArraysPDMatsExt = "PDMats" + FillArraysSparseArraysExt = "SparseArrays" + FillArraysStatisticsExt = "Statistics" [[deps.FiniteDiff]] deps = ["ArrayInterface", "LinearAlgebra", "Requires", "Setfield", "SparseArrays"] -git-tree-sha1 = "c6e4a1fbe73b31a3dea94b1da449503b8830c306" +git-tree-sha1 = "73d1214fec245096717847c62d389a5d2ac86504" uuid = "6a86dc24-6348-571c-b903-95158fe2bd41" -version = "2.21.1" -weakdeps = ["BandedMatrices", "BlockBandedMatrices", "StaticArrays"] +version = "2.22.0" [deps.FiniteDiff.extensions] FiniteDiffBandedMatricesExt = "BandedMatrices" FiniteDiffBlockBandedMatricesExt = "BlockBandedMatrices" FiniteDiffStaticArraysExt = "StaticArrays" + [deps.FiniteDiff.weakdeps] + BandedMatrices = "aae01518-5342-5314-be14-df237901396f" + BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + [[deps.FixedEffectModels]] -deps = ["DataFrames", "FixedEffects", "LinearAlgebra", "Printf", "Reexport", "Statistics", "StatsAPI", "StatsBase", "StatsFuns", "StatsModels", "Tables", "Vcov"] -git-tree-sha1 = "0c5a7774a7c74deb05a9ff09cc62f1803bb3cfdf" +deps = ["DataFrames", "FixedEffects", "LinearAlgebra", "PrecompileTools", "Printf", "Reexport", "Statistics", "StatsAPI", "StatsBase", "StatsFuns", "StatsModels", "Tables", "Vcov"] +git-tree-sha1 = "8659900a184c342a61c12508c875e9ad4a123777" uuid = "9d5cd8c9-2029-5cab-9928-427838db53e3" -version = "1.8.0" +version = "1.11.0" [[deps.FixedEffects]] -deps = ["GroupedArrays", "LinearAlgebra", "Printf", "Requires", "StatsBase"] -git-tree-sha1 = "c59a77e2f138d1253df164a233be056615f331c3" +deps = ["GroupedArrays", "LinearAlgebra", "Printf", "StatsBase"] +git-tree-sha1 = "4b5de96c36ac13f37cb7c2bfbdecd39d1b5ead5f" uuid = "c8885935-8500-56a7-9867-7708b20db0eb" -version = "2.1.2" +version = "2.3.0" + + [deps.FixedEffects.extensions] + CUDAExt = "CUDA" + MetalExt = "Metal" + + [deps.FixedEffects.weakdeps] + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + Metal = "dde4c033-4e86-420c-a63e-0dd931031962" [[deps.FixedPointNumbers]] deps = ["Statistics"] @@ -689,19 +705,19 @@ version = "0.4.2" [[deps.ForwardDiff]] deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "LogExpFunctions", "NaNMath", "Preferences", "Printf", "Random", "SpecialFunctions"] -git-tree-sha1 = "00e252f4d706b3d55a8863432e742bf5717b498d" +git-tree-sha1 = "cf0fe81336da9fb90944683b8c41984b08793dad" uuid = "f6369f11-7733-5829-9624-2563aa707210" -version = "0.10.35" +version = "0.10.36" weakdeps = ["StaticArrays"] [deps.ForwardDiff.extensions] ForwardDiffStaticArraysExt = "StaticArrays" [[deps.FreeType2_jll]] -deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"] -git-tree-sha1 = "87eb71354d8ec1a96d4a7636bd57a7347dde3ef9" +deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Zlib_jll"] +git-tree-sha1 = "d8db6a5a2fe1381c1ea4ef2cab7c69c2de7f9ea0" uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7" -version = "2.10.4+0" +version = "2.13.1+0" [[deps.FriBidi_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -725,22 +741,16 @@ deps = ["Random"] uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820" [[deps.GLFW_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Pkg", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll"] -git-tree-sha1 = "d972031d28c8c8d9d7b41a536ad7bb0c2579caca" +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll"] +git-tree-sha1 = "ff38ba61beff76b8f4acad8ab0c97ef73bb670cb" uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89" -version = "3.3.8+0" +version = "3.3.9+0" [[deps.GLM]] deps = ["Distributions", "LinearAlgebra", "Printf", "Reexport", "SparseArrays", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns", "StatsModels"] -git-tree-sha1 = "97829cfda0df99ddaeaafb5b370d6cab87b7013e" +git-tree-sha1 = "273bd1cd30768a2fddfa3fd63bbc746ed7249e5f" uuid = "38e38edf-8417-5370-95a0-9cbb8c7f171a" -version = "1.8.3" - -[[deps.GPUArrays]] -deps = ["Adapt", "GPUArraysCore", "LLVM", "LinearAlgebra", "Printf", "Random", "Reexport", "Serialization", "Statistics"] -git-tree-sha1 = "a3351bc577a6b49297248aadc23a4add1097c2ac" -uuid = "0c68f7d7-f131-5f86-a1c3-88cf8149b2d7" -version = "8.7.1" +version = "1.9.0" [[deps.GPUArraysCore]] deps = ["Adapt"] @@ -750,15 +760,15 @@ version = "0.1.5" [[deps.GR]] deps = ["Artifacts", "Base64", "DelimitedFiles", "Downloads", "GR_jll", "HTTP", "JSON", "Libdl", "LinearAlgebra", "Pkg", "Preferences", "Printf", "Random", "Serialization", "Sockets", "TOML", "Tar", "Test", "UUIDs", "p7zip_jll"] -git-tree-sha1 = "8b8a2fd4536ece6e554168c21860b6820a8a83db" +git-tree-sha1 = "27442171f28c952804dede8ff72828a96f2bfc1f" uuid = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71" -version = "0.72.7" +version = "0.72.10" [[deps.GR_jll]] -deps = ["Artifacts", "Bzip2_jll", "Cairo_jll", "FFMPEG_jll", "Fontconfig_jll", "GLFW_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pixman_jll", "Qt5Base_jll", "Zlib_jll", "libpng_jll"] -git-tree-sha1 = "19fad9cd9ae44847fe842558a744748084a722d1" +deps = ["Artifacts", "Bzip2_jll", "Cairo_jll", "FFMPEG_jll", "Fontconfig_jll", "FreeType2_jll", "GLFW_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pixman_jll", "Qt6Base_jll", "Zlib_jll", "libpng_jll"] +git-tree-sha1 = "025d171a2847f616becc0f84c8dc62fe18f0f6dd" uuid = "d2c73de3-f751-5644-a686-071e5b155ba9" -version = "0.72.7+0" +version = "0.72.10+0" [[deps.GenericSchur]] deps = ["LinearAlgebra", "Printf"] @@ -773,10 +783,10 @@ uuid = "78b55507-aeef-58d4-861c-77aaff3498b1" version = "0.21.0+0" [[deps.Glib_jll]] -deps = ["Artifacts", "Gettext_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Libiconv_jll", "Libmount_jll", "PCRE2_jll", "Pkg", "Zlib_jll"] -git-tree-sha1 = "d3b3624125c1474292d0d8ed0f65554ac37ddb23" +deps = ["Artifacts", "Gettext_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Libiconv_jll", "Libmount_jll", "PCRE2_jll", "Zlib_jll"] +git-tree-sha1 = "e94c92c7bf4819685eb80186d51c43e71d4afa17" uuid = "7746bdde-850d-59dc-9ae8-88ece973131d" -version = "2.74.0+2" +version = "2.76.5+0" [[deps.Graphite2_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -786,9 +796,9 @@ version = "1.3.14+0" [[deps.Graphs]] deps = ["ArnoldiMethod", "Compat", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"] -git-tree-sha1 = "1cf1d7dcb4bc32d7b4a5add4232db3750c27ecb4" +git-tree-sha1 = "899050ace26649433ef1af25bc17a815b3db52b7" uuid = "86223c79-3864-5bf0-83f7-82e725a168b6" -version = "1.8.0" +version = "1.9.0" [[deps.Grisu]] git-tree-sha1 = "53bb909d1151e57e2484c3d1b53e19552b887fb2" @@ -796,10 +806,10 @@ uuid = "42e2da0e-8278-4e71-bc24-59509adca0fe" version = "1.0.2" [[deps.Groebner]] -deps = ["AbstractAlgebra", "Combinatorics", "Logging", "MultivariatePolynomials", "Primes", "Random"] -git-tree-sha1 = "47f0f03eddecd7ad59c42b1dd46d5f42916aff63" +deps = ["AbstractAlgebra", "Combinatorics", "ExprTools", "Logging", "MultivariatePolynomials", "PrecompileTools", "PrettyTables", "Primes", "Printf", "Random", "SIMD", "TimerOutputs"] +git-tree-sha1 = "6b505ef15e55bdc5bb3ddbcfebdff1c9e67081e8" uuid = "0b43b601-686d-58a3-8a1c-6623616c7cd4" -version = "0.2.11" +version = "0.5.1" [[deps.GroupedArrays]] deps = ["DataAPI", "Missings"] @@ -809,15 +819,15 @@ version = "0.3.3" [[deps.GroupsCore]] deps = ["Markdown", "Random"] -git-tree-sha1 = "9e1a5e9f3b81ad6a5c613d181664a0efc6fe6dd7" +git-tree-sha1 = "6df9cd6ee79fc59feab33f63a1b3c9e95e2461d5" uuid = "d5909c97-4eac-4ecc-a3dc-fdd0858a4120" -version = "0.4.0" +version = "0.4.2" [[deps.HTTP]] -deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"] -git-tree-sha1 = "5e77dbf117412d4f164a464d610ee6050cc75272" +deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "ExceptionUnwrapping", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"] +git-tree-sha1 = "abbbb9ec3afd783a7cbd82ef01dcd088ea051398" uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3" -version = "1.9.6" +version = "1.10.1" [[deps.HarfBuzz_jll]] deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "Graphite2_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg"] @@ -827,27 +837,21 @@ version = "2.8.1+1" [[deps.HostCPUFeatures]] deps = ["BitTwiddlingConvenienceFunctions", "IfElse", "Libdl", "Static"] -git-tree-sha1 = "734fd90dd2f920a2f1921d5388dcebe805b262dc" +git-tree-sha1 = "eb8fed28f4994600e29beef49744639d985a04b2" uuid = "3e5b6fbb-0976-4d2c-9146-d79de83f2fb0" -version = "0.1.14" +version = "0.1.16" [[deps.Hwloc_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "2982b2ec1cb2e2d04b2893e211d29e1e30f8abf4" +git-tree-sha1 = "ca0f6bf568b4bfc807e7537f081c81e35ceca114" uuid = "e33a78d0-f292-5ffc-b300-72abe9b543c8" -version = "2.9.1+0" +version = "2.10.0+0" [[deps.HypergeometricFunctions]] deps = ["DualNumbers", "LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"] -git-tree-sha1 = "0ec02c648befc2f94156eaef13b0f38106212f3f" +git-tree-sha1 = "f218fe3736ddf977e0e772bc9a586b2383da2685" uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a" -version = "0.3.17" - -[[deps.IRTools]] -deps = ["InteractiveUtils", "MacroTools", "Test"] -git-tree-sha1 = "eac00994ce3229a464c2847e956d77a2c64ad3a5" -uuid = "7869d1d1-7146-5819-86e3-90919afe41df" -version = "0.4.10" +version = "0.3.23" [[deps.IfElse]] git-tree-sha1 = "debdd00ffef04665ccbb3e150747a77560e8fad1" @@ -861,9 +865,9 @@ uuid = "40713840-3770-5561-ab4c-a76e7d0d7895" version = "0.2.1" [[deps.Inflate]] -git-tree-sha1 = "5cd07aab533df5170988219191dfad0519391428" +git-tree-sha1 = "ea8031dea4aff6bd41f1df8f2fdfb25b33626381" uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9" -version = "0.1.3" +version = "0.1.4" [[deps.InlineStrings]] deps = ["Parsers"] @@ -872,15 +876,15 @@ uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48" version = "1.4.0" [[deps.IntegerMathUtils]] -git-tree-sha1 = "70f65ced5129d36dbf200b07c51ea8a955294660" +git-tree-sha1 = "b8ffb903da9f7b8cf695a8bead8e01814aa24b30" uuid = "18e54dd8-cb9d-406c-a71d-865a43cbb235" -version = "0.1.1" +version = "0.1.2" [[deps.IntelOpenMP_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "0cb9352ef2e01574eeebdb102948a58740dcaf83" +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "5fdf2fe6724d8caabf43b557b84ce53f3b7e2f6b" uuid = "1d5cc7b8-4909-519e-a0f8-d0f5ad9712d0" -version = "2023.1.0+0" +version = "2024.0.2+0" [[deps.InteractiveUtils]] deps = ["Markdown"] @@ -893,10 +897,14 @@ uuid = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" version = "0.14.7" [[deps.IntervalSets]] -deps = ["Dates", "Random", "Statistics"] -git-tree-sha1 = "3f91cd3f56ea48d4d2a75c2a65455c5fc74fa347" +deps = ["Dates", "Random"] +git-tree-sha1 = "3d8866c029dd6b16e69e0d4a939c4dfcb98fac47" uuid = "8197267c-284f-5f27-9208-e0e47529a953" -version = "0.7.3" +version = "0.7.8" +weakdeps = ["Statistics"] + + [deps.IntervalSets.extensions] + IntervalSetsStatisticsExt = "Statistics" [[deps.InvertedIndices]] git-tree-sha1 = "0dc7b50b8d436461be01300fd8cd45aa0274b038" @@ -905,15 +913,15 @@ version = "1.3.0" [[deps.Ipopt]] deps = ["Ipopt_jll", "LinearAlgebra", "MathOptInterface", "OpenBLAS32_jll", "PrecompileTools"] -git-tree-sha1 = "fdb3430a3b7b909bcb5abf9439d61450f49e3e2c" +git-tree-sha1 = "481caf9195288ec5a1968582a8bc14735575ef81" uuid = "b6b21f68-93f8-5de0-b562-5493be1d77c9" -version = "1.4.1" +version = "1.5.1" [[deps.Ipopt_jll]] deps = ["ASL_jll", "Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "MUMPS_seq_jll", "SPRAL_jll", "libblastrampoline_jll"] -git-tree-sha1 = "10aed0bc185360eef63ef34bc02d0bd7c26409d1" +git-tree-sha1 = "f06a7fd68e29c8acc96483d6f163dab58626c4b5" uuid = "9cc047cb-c261-5740-88fc-0cf96f7bdcc7" -version = "300.1400.1300+0" +version = "300.1400.1302+0" [[deps.IrrationalConstants]] git-tree-sha1 = "630b497eafcc20001bba38a4651b327dcfc491d2" @@ -921,9 +929,9 @@ uuid = "92d709cd-6900-40b7-9082-c6be49f344b6" version = "0.2.2" [[deps.IterTools]] -git-tree-sha1 = "4ced6667f9974fc5c5943fa5e2ef1ca43ea9e450" +git-tree-sha1 = "42d5f897009e7ff2cf88db414a389e5ed1bdd023" uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e" -version = "1.8.0" +version = "1.10.0" [[deps.IterableTables]] deps = ["DataValues", "IteratorInterfaceExtensions", "Requires", "TableTraits", "TableTraitsUtils"] @@ -933,9 +941,9 @@ version = "1.0.0" [[deps.IterativeSolvers]] deps = ["LinearAlgebra", "Printf", "Random", "RecipesBase", "SparseArrays"] -git-tree-sha1 = "1169632f425f79429f245113b775a0e3d121457c" +git-tree-sha1 = "b435d190ef8369cf4d79cc9dd5fba88ba0165307" uuid = "42fd0dbc-a981-5370-80f2-aaf504508153" -version = "0.9.2" +version = "0.9.3" [[deps.IteratorInterfaceExtensions]] git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" @@ -944,15 +952,15 @@ version = "1.0.0" [[deps.JLFzf]] deps = ["Pipe", "REPL", "Random", "fzf_jll"] -git-tree-sha1 = "f377670cda23b6b7c1c0b3893e37451c5c1a2185" +git-tree-sha1 = "a53ebe394b71470c7f97c2e7e170d51df21b17af" uuid = "1019f520-868f-41f5-a6de-eb00f4b6a39c" -version = "0.1.5" +version = "0.1.7" [[deps.JLLWrappers]] -deps = ["Preferences"] -git-tree-sha1 = "abc9885a7ca2052a736a600f7fa66209f96506e1" +deps = ["Artifacts", "Preferences"] +git-tree-sha1 = "7e5d6779a1e09a36db2a7b6cff50942a0a7d0fca" uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" -version = "1.4.1" +version = "1.5.0" [[deps.JSON]] deps = ["Dates", "Mmap", "Parsers", "Unicode"] @@ -962,51 +970,49 @@ version = "0.21.4" [[deps.JpegTurbo_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "6f2675ef130a300a112286de91973805fcc5ffbc" +git-tree-sha1 = "60b1194df0a3298f460063de985eae7b01bc011a" uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8" -version = "2.1.91+0" +version = "3.0.1+0" [[deps.JuMP]] -deps = ["LinearAlgebra", "MathOptInterface", "MutableArithmetics", "OrderedCollections", "Printf", "SnoopPrecompile", "SparseArrays"] -git-tree-sha1 = "3e4a73edf2ca1bfe97f1fc86eb4364f95ef0fccd" +deps = ["LinearAlgebra", "MacroTools", "MathOptInterface", "MutableArithmetics", "OrderedCollections", "PrecompileTools", "Printf", "SparseArrays"] +git-tree-sha1 = "769d01cf0d3d1f3e59594cc43c8b319b36d7c2a3" uuid = "4076af6c-e467-56ae-b986-b466b2749572" -version = "1.11.1" +version = "1.18.0" + + [deps.JuMP.extensions] + JuMPDimensionalDataExt = "DimensionalData" + + [deps.JuMP.weakdeps] + DimensionalData = "0703355e-b756-11e9-17c0-8b28908087d0" [[deps.JumpProcesses]] -deps = ["ArrayInterface", "DataStructures", "DiffEqBase", "DocStringExtensions", "FunctionWrappers", "Graphs", "LinearAlgebra", "Markdown", "PoissonRandom", "Random", "RandomNumbers", "RecursiveArrayTools", "Reexport", "SciMLBase", "StaticArrays", "TreeViews", "UnPack"] -git-tree-sha1 = "50bd271af7f6cc23be7d24c8c4804809bb5d05ae" +deps = ["ArrayInterface", "DataStructures", "DiffEqBase", "DocStringExtensions", "FunctionWrappers", "Graphs", "LinearAlgebra", "Markdown", "PoissonRandom", "Random", "RandomNumbers", "RecursiveArrayTools", "Reexport", "SciMLBase", "StaticArrays", "UnPack"] +git-tree-sha1 = "c451feb97251965a9fe40bacd62551a72cc5902c" uuid = "ccbc3e58-028d-4f4c-8cd5-9ae44345cda5" -version = "9.6.3" +version = "9.10.1" +weakdeps = ["FastBroadcast"] + + [deps.JumpProcesses.extensions] + JumpProcessFastBroadcastExt = "FastBroadcast" [[deps.KLU]] deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse_jll"] -git-tree-sha1 = "764164ed65c30738750965d55652db9c94c59bfe" +git-tree-sha1 = "884c2968c2e8e7e6bf5956af88cb46aa745c854b" uuid = "ef3ab10e-7fda-4108-b977-705223b18434" -version = "0.4.0" - -[[deps.KernelAbstractions]] -deps = ["Adapt", "Atomix", "InteractiveUtils", "LinearAlgebra", "MacroTools", "PrecompileTools", "SparseArrays", "StaticArrays", "UUIDs", "UnsafeAtomics", "UnsafeAtomicsLLVM"] -git-tree-sha1 = "47be64f040a7ece575c2b5f53ca6da7b548d69f4" -uuid = "63c18a36-062a-441e-b654-da1e3ab1ce7c" -version = "0.9.4" +version = "0.4.1" [[deps.KernelDensity]] deps = ["Distributions", "DocStringExtensions", "FFTW", "Interpolations", "StatsBase"] -git-tree-sha1 = "90442c50e202a5cdf21a7899c66b240fdef14035" +git-tree-sha1 = "fee018a29b60733876eb557804b5b109dd3dd8a7" uuid = "5ab0869b-81aa-558d-bb23-cbf5423bbe9b" -version = "0.6.7" +version = "0.6.8" [[deps.Krylov]] deps = ["LinearAlgebra", "Printf", "SparseArrays"] -git-tree-sha1 = "0356a64062656b0cbb43c504ad5de338251f4bda" +git-tree-sha1 = "8a6837ec02fe5fb3def1abc907bb802ef11a0729" uuid = "ba0b0d4f-ebba-5204-a429-3ac8c609bfb7" -version = "0.9.1" - -[[deps.KrylovKit]] -deps = ["ChainRulesCore", "GPUArraysCore", "LinearAlgebra", "Printf"] -git-tree-sha1 = "1a5e1d9941c783b0119897d29f2eb665d876ecf3" -uuid = "0b1a1467-8014-51b9-945f-bf0ae24f4b77" -version = "0.6.0" +version = "0.9.5" [[deps.LAME_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -1020,23 +1026,11 @@ git-tree-sha1 = "bf36f528eec6634efc60d7ec062008f171071434" uuid = "88015f11-f218-50d7-93a8-a6af411a945d" version = "3.0.0+1" -[[deps.LLVM]] -deps = ["CEnum", "LLVMExtra_jll", "Libdl", "Printf", "Unicode"] -git-tree-sha1 = "5007c1421563108110bbd57f63d8ad4565808818" -uuid = "929cbde3-209d-540e-8aea-75f648917ca0" -version = "5.2.0" - -[[deps.LLVMExtra_jll]] -deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"] -git-tree-sha1 = "1222116d7313cdefecf3d45a2bc1a89c4e7c9217" -uuid = "dad2f222-ce93-54a1-a47d-0025e8a3acab" -version = "0.0.22+0" - [[deps.LLVMOpenMP_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "f689897ccbe049adb19a065c495e75f372ecd42b" +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "d986ce2d884d49126836ea94ed5bfb0f12679713" uuid = "1d63c593-3942-5779-bab2-d838dc0a180e" -version = "15.0.4+0" +version = "15.0.7+0" [[deps.LZO_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -1045,15 +1039,15 @@ uuid = "dd4b983a-f0e5-5f8d-a1b7-129d4a5fb1ac" version = "2.10.1+0" [[deps.LaTeXStrings]] -git-tree-sha1 = "f2355693d6778a178ade15952b7ac47a4ff97996" +git-tree-sha1 = "50901ebc375ed41dbf8058da26f9de442febbbec" uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" -version = "1.3.0" +version = "1.3.1" [[deps.LabelledArrays]] deps = ["ArrayInterface", "ChainRulesCore", "ForwardDiff", "LinearAlgebra", "MacroTools", "PreallocationTools", "RecursiveArrayTools", "StaticArrays"] -git-tree-sha1 = "cd04158424635efd05ff38d5f55843397b7416a9" +git-tree-sha1 = "f12f2225c999886b69273f84713d1b9cb66faace" uuid = "2ee39098-c373-598a-b85f-a56591580800" -version = "1.14.0" +version = "1.15.0" [[deps.LambertW]] git-tree-sha1 = "c5ffc834de5d61d00d2b0e18c96267cffc21f648" @@ -1062,27 +1056,23 @@ version = "0.4.6" [[deps.Latexify]] deps = ["Formatting", "InteractiveUtils", "LaTeXStrings", "MacroTools", "Markdown", "OrderedCollections", "Printf", "Requires"] -git-tree-sha1 = "8c57307b5d9bb3be1ff2da469063628631d4d51e" +git-tree-sha1 = "f428ae552340899a935973270b8d98e5a31c49fe" uuid = "23fbe1c1-3f47-55db-b15f-69d7ec21a316" -version = "0.15.21" +version = "0.16.1" [deps.Latexify.extensions] DataFramesExt = "DataFrames" - DiffEqBiologicalExt = "DiffEqBiological" - ParameterizedFunctionsExt = "DiffEqBase" SymEngineExt = "SymEngine" [deps.Latexify.weakdeps] DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" - DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e" - DiffEqBiological = "eb300fae-53e8-50a0-950c-e21f52c2b7e0" SymEngine = "123dc426-2d89-5057-bbad-38513e3affd8" [[deps.LayoutPointers]] deps = ["ArrayInterface", "LinearAlgebra", "ManualMemory", "SIMDTypes", "Static", "StaticArrayInterface"] -git-tree-sha1 = "88b8f66b604da079a627b6fb2860d3704a6729a1" +git-tree-sha1 = "62edfee3211981241b57ff1cedf4d74d79519277" uuid = "10f19ff3-798f-405d-979b-55457f8fc047" -version = "0.1.14" +version = "0.1.15" [[deps.Lazy]] deps = ["MacroTools"] @@ -1091,27 +1081,19 @@ uuid = "50d2b5c4-7a5e-59d5-8109-a42b560f39c0" version = "0.15.1" [[deps.LazyArrays]] -deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra", "MacroTools", "MatrixFactorizations", "SparseArrays", "StaticArrays"] -git-tree-sha1 = "7402f6be1a28a05516c6881596879e6d18d28039" +deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra", "MacroTools", "MatrixFactorizations", "SparseArrays"] +git-tree-sha1 = "9cfca23ab83b0dfac93cb1a1ef3331ab9fe596a5" uuid = "5078a376-72f3-5289-bfd5-ec5146d43c02" -version = "0.22.18" +version = "1.8.3" +weakdeps = ["StaticArrays"] + + [deps.LazyArrays.extensions] + LazyArraysStaticArraysExt = "StaticArrays" [[deps.LazyArtifacts]] deps = ["Artifacts", "Pkg"] uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3" -[[deps.LazyBandedMatrices]] -deps = ["ArrayLayouts", "BandedMatrices", "BlockArrays", "BlockBandedMatrices", "FillArrays", "LazyArrays", "LinearAlgebra", "MatrixFactorizations", "SparseArrays", "StaticArrays"] -git-tree-sha1 = "034d371419140f14a986ab7325d11f90f30b0c6d" -uuid = "d7e5e226-e90b-4449-9968-0f923699bf6f" -version = "0.7.17" - -[[deps.LeastSquaresOptim]] -deps = ["FiniteDiff", "ForwardDiff", "LinearAlgebra", "Optim", "Printf", "SparseArrays", "Statistics", "SuiteSparse"] -git-tree-sha1 = "cef2dd16402718cf5f412e610813e2ec20d94a64" -uuid = "0fc2ff8b-aaa3-5acd-a817-1944a5e08891" -version = "0.8.4" - [[deps.LevyArea]] deps = ["LinearAlgebra", "Random", "SpecialFunctions"] git-tree-sha1 = "56513a09b8e0ae6485f34401ea9e2f31357958ec" @@ -1121,21 +1103,26 @@ version = "1.0.0" [[deps.LibCURL]] deps = ["LibCURL_jll", "MozillaCACerts_jll"] uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" -version = "0.6.3" +version = "0.6.4" [[deps.LibCURL_jll]] deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" -version = "7.84.0+0" +version = "8.4.0+0" [[deps.LibGit2]] -deps = ["Base64", "NetworkOptions", "Printf", "SHA"] +deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" +[[deps.LibGit2_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] +uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" +version = "1.6.4+0" + [[deps.LibSSH2_jll]] deps = ["Artifacts", "Libdl", "MbedTLS_jll"] uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" -version = "1.10.2+0" +version = "1.11.0+1" [[deps.Libdl]] uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" @@ -1165,10 +1152,10 @@ uuid = "7add5ba3-2f88-524e-9cd5-f83b8a55f7b8" version = "1.42.0+0" [[deps.Libiconv_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "c7cb1f5d892775ba13767a87c7ada0b980ea0a71" +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "f9557a255370125b405568f9767d6d195822a175" uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" -version = "1.16.1+2" +version = "1.17.0+0" [[deps.Libmount_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -1177,10 +1164,10 @@ uuid = "4b2f31a3-9ecc-558c-b454-b3730dcb73e9" version = "2.35.0+0" [[deps.Libtiff_jll]] -deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "LERC_jll", "Libdl", "Pkg", "Zlib_jll", "Zstd_jll"] -git-tree-sha1 = "3eb79b0ca5764d4799c06699573fd8f533259713" +deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "LERC_jll", "Libdl", "XZ_jll", "Zlib_jll", "Zstd_jll"] +git-tree-sha1 = "2da088d113af58221c52828a80378e16be7d037a" uuid = "89763e89-9b03-5906-acba-b20f662cd828" -version = "4.4.0+0" +version = "4.5.1+1" [[deps.Libuuid_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -1190,9 +1177,9 @@ version = "2.36.0+0" [[deps.LimitedLDLFactorizations]] deps = ["AMD", "LinearAlgebra", "SparseArrays"] -git-tree-sha1 = "422ddab7cac3f51acc5ae23c96e710d07df9a73e" +git-tree-sha1 = "07b3c94ba4decdd855770beddeab9187be03d6b8" uuid = "f5a24dde-3ab7-510b-b81b-6a72c6098d3b" -version = "0.5.0" +version = "0.5.1" [[deps.LineSearches]] deps = ["LinearAlgebra", "NLSolversBase", "NaNMath", "Parameters", "Printf"] @@ -1205,32 +1192,57 @@ deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" [[deps.LinearMaps]] -deps = ["LinearAlgebra", "SparseArrays", "Statistics"] -git-tree-sha1 = "a1348b9b7c87d45fa859314d56e8a87ace20561e" +deps = ["LinearAlgebra"] +git-tree-sha1 = "9df2ab050ffefe870a09c7b6afdb0cde381703f2" uuid = "7a12625a-238d-50fd-b39a-03d52299707e" -version = "3.10.1" -weakdeps = ["ChainRulesCore"] +version = "3.11.1" +weakdeps = ["ChainRulesCore", "SparseArrays", "Statistics"] [deps.LinearMaps.extensions] LinearMapsChainRulesCoreExt = "ChainRulesCore" + LinearMapsSparseArraysExt = "SparseArrays" + LinearMapsStatisticsExt = "Statistics" [[deps.LinearSolve]] -deps = ["ArrayInterface", "DocStringExtensions", "EnumX", "FastLapackInterface", "GPUArraysCore", "IterativeSolvers", "KLU", "Krylov", "KrylovKit", "LinearAlgebra", "Preferences", "RecursiveFactorization", "Reexport", "SciMLBase", "SciMLOperators", "Setfield", "SnoopPrecompile", "SparseArrays", "Sparspak", "SuiteSparse", "UnPack"] -git-tree-sha1 = "4a4f8cc7a59fadbb02d1852d1e0cef5dca3a9460" +deps = ["ArrayInterface", "ConcreteStructs", "DocStringExtensions", "EnumX", "FastLapackInterface", "GPUArraysCore", "InteractiveUtils", "KLU", "Krylov", "Libdl", "LinearAlgebra", "MKL_jll", "PrecompileTools", "Preferences", "RecursiveFactorization", "Reexport", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Sparspak", "StaticArraysCore", "UnPack"] +git-tree-sha1 = "97dc499678d50d989f1a74170840808641ce9880" uuid = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" -version = "1.42.0" +version = "2.22.0" [deps.LinearSolve.extensions] - LinearSolveHYPRE = "HYPRE" + LinearSolveBandedMatricesExt = "BandedMatrices" + LinearSolveBlockDiagonalsExt = "BlockDiagonals" + LinearSolveCUDAExt = "CUDA" + LinearSolveEnzymeExt = ["Enzyme", "EnzymeCore"] + LinearSolveFastAlmostBandedMatricesExt = ["FastAlmostBandedMatrices"] + LinearSolveHYPREExt = "HYPRE" + LinearSolveIterativeSolversExt = "IterativeSolvers" + LinearSolveKernelAbstractionsExt = "KernelAbstractions" + LinearSolveKrylovKitExt = "KrylovKit" + LinearSolveMetalExt = "Metal" + LinearSolvePardisoExt = "Pardiso" + LinearSolveRecursiveArrayToolsExt = "RecursiveArrayTools" [deps.LinearSolve.weakdeps] + BandedMatrices = "aae01518-5342-5314-be14-df237901396f" + BlockDiagonals = "0a1fb500-61f7-11e9-3c65-f5ef3456f9f0" + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" + EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" + FastAlmostBandedMatrices = "9d29842c-ecb8-4973-b1e9-a27b1157504e" HYPRE = "b5ffcf37-a2bd-41ab-a3da-4bd9bc8ad771" + IterativeSolvers = "42fd0dbc-a981-5370-80f2-aaf504508153" + KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" + KrylovKit = "0b1a1467-8014-51b9-945f-bf0ae24f4b77" + Metal = "dde4c033-4e86-420c-a63e-0dd931031962" + Pardiso = "46dd5b70-b6fb-5a00-ae2d-e8fea33afaf2" + RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" [[deps.LogExpFunctions]] deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"] -git-tree-sha1 = "c3ce8e7420b3a6e071e0fe4745f5d4300e37b13f" +git-tree-sha1 = "7d6dd4e9212aebaeed356de34ccf262a3cd415aa" uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" -version = "0.3.24" +version = "0.3.26" [deps.LogExpFunctions.extensions] LogExpFunctionsChainRulesCoreExt = "ChainRulesCore" @@ -1247,15 +1259,15 @@ uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" [[deps.LoggingExtras]] deps = ["Dates", "Logging"] -git-tree-sha1 = "cedb76b37bc5a6c702ade66be44f831fa23c681e" +git-tree-sha1 = "c1dd6d7978c12545b4179fb6153b9250c96b0075" uuid = "e6f89c97-d47a-5376-807f-9c37f3926c36" -version = "1.0.0" +version = "1.0.3" [[deps.LoopVectorization]] -deps = ["ArrayInterface", "ArrayInterfaceCore", "CPUSummary", "CloseOpenIntervals", "DocStringExtensions", "HostCPUFeatures", "IfElse", "LayoutPointers", "LinearAlgebra", "OffsetArrays", "PolyesterWeave", "PrecompileTools", "SIMDTypes", "SLEEFPirates", "Static", "StaticArrayInterface", "ThreadingUtilities", "UnPack", "VectorizationBase"] -git-tree-sha1 = "3bb62b5003bc7d2d49f26663484267dc49fa1bf5" +deps = ["ArrayInterface", "CPUSummary", "CloseOpenIntervals", "DocStringExtensions", "HostCPUFeatures", "IfElse", "LayoutPointers", "LinearAlgebra", "OffsetArrays", "PolyesterWeave", "PrecompileTools", "SIMDTypes", "SLEEFPirates", "Static", "StaticArrayInterface", "ThreadingUtilities", "UnPack", "VectorizationBase"] +git-tree-sha1 = "0f5648fbae0d015e3abe5867bca2b362f67a5894" uuid = "bdcacae8-1622-11e9-2a5c-532679323890" -version = "0.12.159" +version = "0.12.166" weakdeps = ["ChainRulesCore", "ForwardDiff", "SpecialFunctions"] [deps.LoopVectorization.extensions] @@ -1269,22 +1281,22 @@ uuid = "d00139f3-1899-568f-a2f0-47f597d42d70" version = "5.1.2+0" [[deps.MKL_jll]] -deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "Pkg"] -git-tree-sha1 = "2ce8695e1e699b68702c03402672a69f54b8aca9" +deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl"] +git-tree-sha1 = "72dc3cf284559eb8f53aa593fe62cb33f83ed0c0" uuid = "856f044c-d86e-5d09-b602-aeab76dc8ba7" -version = "2022.2.0+0" +version = "2024.0.0+0" [[deps.MUMPS_seq_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "METIS_jll", "libblastrampoline_jll"] -git-tree-sha1 = "fcf680f6feb85014723f9754ef560173d4a30843" +git-tree-sha1 = "24dd34802044008ef9a596de32d63f3c9ddb7802" uuid = "d7ed1dd3-d0ae-5e8e-bfb4-87a502085b8d" -version = "500.600.0+0" +version = "500.600.100+0" [[deps.MacroTools]] deps = ["Markdown", "Random"] -git-tree-sha1 = "42324d08725e200c23d4dfb549e0d5d89dede2d2" +git-tree-sha1 = "b211c553c199c111d998ecdaf7623d1b89b69f93" uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" -version = "0.5.10" +version = "0.5.12" [[deps.ManualMemory]] git-tree-sha1 = "bcaef4fc7a0cfe2cba636d84cda54b5e4e4ca3cd" @@ -1297,9 +1309,9 @@ uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" [[deps.MathOptInterface]] deps = ["BenchmarkTools", "CodecBzip2", "CodecZlib", "DataStructures", "ForwardDiff", "JSON", "LinearAlgebra", "MutableArithmetics", "NaNMath", "OrderedCollections", "PrecompileTools", "Printf", "SparseArrays", "SpecialFunctions", "Test", "Unicode"] -git-tree-sha1 = "19a3636968e802918f8891d729c74bd64dff6d00" +git-tree-sha1 = "d2a140e551c9ec9028483e3c7d1244f417567ac0" uuid = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" -version = "1.17.1" +version = "1.24.0" [[deps.MathProgBase]] deps = ["LinearAlgebra", "SparseArrays"] @@ -1309,20 +1321,26 @@ version = "0.7.8" [[deps.MatrixFactorizations]] deps = ["ArrayLayouts", "LinearAlgebra", "Printf", "Random"] -git-tree-sha1 = "0ff59b4b9024ab9a736db1ad902d2b1b48441c19" +git-tree-sha1 = "78f6e33434939b0ac9ba1df81e6d005ee85a7396" uuid = "a3b82374-2e81-5b9e-98ce-41277c0e4c87" -version = "0.9.6" +version = "2.1.0" + +[[deps.MaybeInplace]] +deps = ["ArrayInterface", "LinearAlgebra", "MacroTools", "SparseArrays"] +git-tree-sha1 = "a85c6a98c9e5a2a7046bc1bb89f28a3241e1de4d" +uuid = "bb5d69b7-63fc-4a16-80bd-7e42200c7bdb" +version = "0.1.1" [[deps.MbedTLS]] -deps = ["Dates", "MbedTLS_jll", "MozillaCACerts_jll", "Random", "Sockets"] -git-tree-sha1 = "03a9b9718f5682ecb107ac9f7308991db4ce395b" +deps = ["Dates", "MbedTLS_jll", "MozillaCACerts_jll", "NetworkOptions", "Random", "Sockets"] +git-tree-sha1 = "c067a280ddc25f196b5e7df3877c6b226d390aaf" uuid = "739be429-bea8-5141-9913-cc70e7f3736d" -version = "1.1.7" +version = "1.1.9" [[deps.MbedTLS_jll]] deps = ["Artifacts", "Libdl"] uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" -version = "2.28.2+0" +version = "2.28.2+1" [[deps.Measures]] git-tree-sha1 = "c13304c81eec1ed3af7fc20e75fb6b26092a1102" @@ -1346,7 +1364,7 @@ version = "0.7.7" [[deps.MozillaCACerts_jll]] uuid = "14a3606d-f60d-562e-9121-12d972cd8159" -version = "2022.10.11" +version = "2023.1.10" [[deps.MuladdMacro]] git-tree-sha1 = "cac9cc5499c25554cba55cd3c30543cff5ca4fab" @@ -1355,9 +1373,9 @@ version = "0.2.4" [[deps.MultivariatePolynomials]] deps = ["ChainRulesCore", "DataStructures", "LinearAlgebra", "MutableArithmetics"] -git-tree-sha1 = "eaa98afe2033ffc0629f9d0d83961d66a021dfcc" +git-tree-sha1 = "6ffb234d6d7c866a75c1879d2099049d3a35a83a" uuid = "102ac46a-7ee4-5c85-9060-abc95bfdeaa3" -version = "0.4.7" +version = "0.5.3" [[deps.MultivariateStats]] deps = ["Arpack", "LinearAlgebra", "SparseArrays", "Statistics", "StatsAPI", "StatsBase"] @@ -1367,9 +1385,9 @@ version = "0.10.2" [[deps.MutableArithmetics]] deps = ["LinearAlgebra", "SparseArrays", "Test"] -git-tree-sha1 = "964cb1a7069723727025ae295408747a0b36a854" +git-tree-sha1 = "806eea990fb41f9b36f1253e5697aa645bf6a9f8" uuid = "d8a4904e-b15c-11e9-3269-09a3773c0cb0" -version = "1.3.0" +version = "1.4.0" [[deps.NLSolversBase]] deps = ["DiffResults", "Distributed", "FiniteDiff", "ForwardDiff"] @@ -1395,18 +1413,6 @@ git-tree-sha1 = "019f12e9a1a7880459d0173c182e6a99365d7ac1" uuid = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" version = "4.5.1" -[[deps.NNlib]] -deps = ["Adapt", "Atomix", "ChainRulesCore", "GPUArraysCore", "KernelAbstractions", "LinearAlgebra", "Pkg", "Random", "Requires", "Statistics"] -git-tree-sha1 = "99e6dbb50d8a96702dc60954569e9fe7291cc55d" -uuid = "872c559c-99b0-510c-b3b7-b6c96a88d5cd" -version = "0.8.20" - - [deps.NNlib.extensions] - NNlibAMDGPUExt = "AMDGPU" - - [deps.NNlib.weakdeps] - AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" - [[deps.NaNMath]] deps = ["OpenLibm_jll"] git-tree-sha1 = "0877504529a3e5c3343c6f8b4c0381e57e4387e4" @@ -1415,30 +1421,57 @@ version = "1.0.2" [[deps.NearestNeighbors]] deps = ["Distances", "StaticArrays"] -git-tree-sha1 = "2c3726ceb3388917602169bed973dbc97f1b51a8" +git-tree-sha1 = "ded64ff6d4fdd1cb68dfcbb818c69e144a5b2e4c" uuid = "b8a86587-4115-5ab1-83bc-aa920d37bbce" -version = "0.4.13" +version = "0.4.16" [[deps.NetworkOptions]] uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" version = "1.2.0" [[deps.NonlinearSolve]] -deps = ["ArrayInterface", "DiffEqBase", "EnumX", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "LinearSolve", "RecursiveArrayTools", "Reexport", "SciMLBase", "SimpleNonlinearSolve", "SnoopPrecompile", "SparseArrays", "SparseDiffTools", "StaticArraysCore", "UnPack"] -git-tree-sha1 = "a6000c813371cd3cd9cbbdf8a356fc3a97138d92" +deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "EnumX", "FastBroadcast", "FastClosures", "FiniteDiff", "ForwardDiff", "LazyArrays", "LineSearches", "LinearAlgebra", "LinearSolve", "MaybeInplace", "PrecompileTools", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SimpleNonlinearSolve", "SparseArrays", "SparseDiffTools", "StaticArrays", "UnPack"] +git-tree-sha1 = "72b036b728461272ae1b1c3f7096cb4c319d8793" uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" -version = "1.6.0" +version = "3.4.0" + + [deps.NonlinearSolve.extensions] + NonlinearSolveBandedMatricesExt = "BandedMatrices" + NonlinearSolveFastLevenbergMarquardtExt = "FastLevenbergMarquardt" + NonlinearSolveFixedPointAccelerationExt = "FixedPointAcceleration" + NonlinearSolveLeastSquaresOptimExt = "LeastSquaresOptim" + NonlinearSolveMINPACKExt = "MINPACK" + NonlinearSolveNLsolveExt = "NLsolve" + NonlinearSolveSIAMFANLEquationsExt = "SIAMFANLEquations" + NonlinearSolveSpeedMappingExt = "SpeedMapping" + NonlinearSolveSymbolicsExt = "Symbolics" + NonlinearSolveZygoteExt = "Zygote" + + [deps.NonlinearSolve.weakdeps] + BandedMatrices = "aae01518-5342-5314-be14-df237901396f" + FastLevenbergMarquardt = "7a0df574-e128-4d35-8cbd-3d84502bf7ce" + FixedPointAcceleration = "817d07cb-a79a-5c30-9a31-890123675176" + LeastSquaresOptim = "0fc2ff8b-aaa3-5acd-a817-1944a5e08891" + MINPACK = "4854310b-de5a-5eb6-a2a5-c1dee2bd17f9" + NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" + SIAMFANLEquations = "084e46ad-d928-497d-ad5e-07fa361a48c4" + SpeedMapping = "f1835b91-879b-4a3f-a438-e4baacf14412" + Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" + Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" [[deps.Observables]] -git-tree-sha1 = "6862738f9796b3edc1c09d0890afce4eca9e7e93" +git-tree-sha1 = "7438a59546cf62428fc9d1bc94729146d37a7225" uuid = "510215fc-4207-5dde-b226-833fc4488ee2" -version = "0.5.4" +version = "0.5.5" [[deps.OffsetArrays]] -deps = ["Adapt"] -git-tree-sha1 = "82d7c9e310fe55aa54996e6f7f94674e2a38fcb4" +git-tree-sha1 = "6a731f2b5c03157418a20c12195eb4b74c8f8621" uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" -version = "1.12.9" +version = "1.13.0" +weakdeps = ["Adapt"] + + [deps.OffsetArrays.extensions] + OffsetArraysAdaptExt = "Adapt" [[deps.Ogg_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -1447,20 +1480,20 @@ uuid = "e7412a2a-1a6e-54c0-be00-318e2571c051" version = "1.3.5+1" [[deps.OpenBLAS32_jll]] -deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "2fb9ee2dc14d555a6df2a714b86b7125178344c2" +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl"] +git-tree-sha1 = "6065c4cff8fee6c6770b277af45d5082baacdba1" uuid = "656ef2d0-ae68-5445-9ca0-591084a874a2" -version = "0.3.21+0" +version = "0.3.24+0" [[deps.OpenBLAS_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" -version = "0.3.21+4" +version = "0.3.23+2" [[deps.OpenLibm_jll]] deps = ["Artifacts", "Libdl"] uuid = "05823500-19ac-5b8b-9628-191a04bc5112" -version = "0.8.1+0" +version = "0.8.1+2" [[deps.OpenSSL]] deps = ["BitFlags", "Dates", "MozillaCACerts_jll", "OpenSSL_jll", "Sockets"] @@ -1470,9 +1503,9 @@ version = "1.4.1" [[deps.OpenSSL_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] -git-tree-sha1 = "1aa4b74f80b01c6bc2b89992b861b5f210e665b5" +git-tree-sha1 = "cc6e1927ac521b659af340e0ca45828a3ffc748f" uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" -version = "1.1.21+0" +version = "3.0.12+0" [[deps.OpenSpecFun_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] @@ -1482,9 +1515,9 @@ version = "0.5.5+0" [[deps.Optim]] deps = ["Compat", "FillArrays", "ForwardDiff", "LineSearches", "LinearAlgebra", "NLSolversBase", "NaNMath", "Parameters", "PositiveFactorizations", "Printf", "SparseArrays", "StatsBase"] -git-tree-sha1 = "e3a6546c1577bfd701771b477b794a52949e7594" +git-tree-sha1 = "01f85d9269b13fedc61e63cc72ee2213565f7a72" uuid = "429524aa-4258-5aef-a3af-852621145aeb" -version = "1.7.6" +version = "1.7.8" [[deps.Opus_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -1493,26 +1526,32 @@ uuid = "91d4177d-7536-5919-b921-800302f37372" version = "1.3.2+0" [[deps.OrderedCollections]] -git-tree-sha1 = "d321bf2de576bf25ec4d3e4360faca399afca282" +git-tree-sha1 = "dfdf5519f235516220579f949664f1bf44e741c5" uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" -version = "1.6.0" +version = "1.6.3" [[deps.OrdinaryDiffEq]] -deps = ["Adapt", "ArrayInterface", "DataStructures", "DiffEqBase", "DocStringExtensions", "ExponentialUtilities", "FastBroadcast", "FastClosures", "FiniteDiff", "ForwardDiff", "FunctionWrappersWrappers", "IfElse", "LineSearches", "LinearAlgebra", "LinearSolve", "Logging", "LoopVectorization", "MacroTools", "MuladdMacro", "NLsolve", "NonlinearSolve", "Polyester", "PreallocationTools", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLNLSolve", "SimpleNonlinearSolve", "SimpleUnPack", "SparseArrays", "SparseDiffTools", "StaticArrayInterface", "StaticArrays", "TruncatedStacktraces"] -git-tree-sha1 = "6ffebfa8971546bace3fc312f9a703795f79f5b9" +deps = ["ADTypes", "Adapt", "ArrayInterface", "DataStructures", "DiffEqBase", "DocStringExtensions", "ExponentialUtilities", "FastBroadcast", "FastClosures", "FillArrays", "FiniteDiff", "ForwardDiff", "FunctionWrappersWrappers", "IfElse", "InteractiveUtils", "LineSearches", "LinearAlgebra", "LinearSolve", "Logging", "LoopVectorization", "MacroTools", "MuladdMacro", "NonlinearSolve", "Polyester", "PreallocationTools", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SimpleNonlinearSolve", "SimpleUnPack", "SparseArrays", "SparseDiffTools", "StaticArrayInterface", "StaticArrays", "TruncatedStacktraces"] +git-tree-sha1 = "e50bc309307871b5f2ec10075c4faf8ca018068f" uuid = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" -version = "6.51.2" +version = "6.67.0" [[deps.PCRE2_jll]] deps = ["Artifacts", "Libdl"] uuid = "efcefdf7-47ab-520b-bdef-62a2eaa19f15" -version = "10.42.0+0" +version = "10.42.0+1" [[deps.PDMats]] deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"] -git-tree-sha1 = "67eae2738d63117a196f497d7db789821bce61d1" +git-tree-sha1 = "949347156c25054de2db3b166c52ac4728cbad65" uuid = "90014a1f-27ba-587c-ab20-58faa44d9150" -version = "0.11.17" +version = "0.11.31" + +[[deps.PackageExtensionCompat]] +git-tree-sha1 = "fb28e33b8a95c4cee25ce296c817d89cc2e53518" +uuid = "65ce6f38-6b18-4e1d-a461-8949797d7930" +version = "1.0.2" +weakdeps = ["Requires", "TOML"] [[deps.Parameters]] deps = ["OrderedCollections", "UnPack"] @@ -1522,9 +1561,9 @@ version = "0.12.3" [[deps.Parsers]] deps = ["Dates", "PrecompileTools", "UUIDs"] -git-tree-sha1 = "a5aef8d4a6e8d81f171b2bd4be5265b01384c74c" +git-tree-sha1 = "8489905bcdbcfac64d1daa51ca07c0d8f0283821" uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" -version = "2.5.10" +version = "2.8.1" [[deps.Pipe]] git-tree-sha1 = "6842804e7867b115ca9de748a0cf6b364523c16d" @@ -1540,7 +1579,7 @@ version = "0.42.2+0" [[deps.Pkg]] deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -version = "1.9.0" +version = "1.10.0" [[deps.PlotThemes]] deps = ["PlotUtils", "Statistics"] @@ -1550,15 +1589,15 @@ version = "3.1.0" [[deps.PlotUtils]] deps = ["ColorSchemes", "Colors", "Dates", "PrecompileTools", "Printf", "Random", "Reexport", "Statistics"] -git-tree-sha1 = "f92e1315dadf8c46561fb9396e525f7200cdc227" +git-tree-sha1 = "862942baf5663da528f66d24996eb6da85218e76" uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043" -version = "1.3.5" +version = "1.4.0" [[deps.Plots]] deps = ["Base64", "Contour", "Dates", "Downloads", "FFMPEG", "FixedPointNumbers", "GR", "JLFzf", "JSON", "LaTeXStrings", "Latexify", "LinearAlgebra", "Measures", "NaNMath", "Pkg", "PlotThemes", "PlotUtils", "PrecompileTools", "Preferences", "Printf", "REPL", "Random", "RecipesBase", "RecipesPipeline", "Reexport", "RelocatableFolders", "Requires", "Scratch", "Showoff", "SparseArrays", "Statistics", "StatsBase", "UUIDs", "UnicodeFun", "UnitfulLatexify", "Unzip"] -git-tree-sha1 = "ceb1ec8d4fbeb02f8817004837d924583707951b" +git-tree-sha1 = "ccee59c6e48e6f2edf8a5b64dc817b6729f99eb5" uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" -version = "1.38.15" +version = "1.39.0" [deps.Plots.extensions] FileIOExt = "FileIO" @@ -1582,9 +1621,9 @@ version = "0.4.4" [[deps.Polyester]] deps = ["ArrayInterface", "BitTwiddlingConvenienceFunctions", "CPUSummary", "IfElse", "ManualMemory", "PolyesterWeave", "Requires", "Static", "StaticArrayInterface", "StrideArraysCore", "ThreadingUtilities"] -git-tree-sha1 = "0fe4e7c4d8ff4c70bfa507f0dd96fa161b115777" +git-tree-sha1 = "fca25670784a1ae44546bcb17288218310af2778" uuid = "f517fe37-dbe3-4b94-8317-1923a5111588" -version = "0.7.3" +version = "0.7.9" [[deps.PolyesterWeave]] deps = ["BitTwiddlingConvenienceFunctions", "CPUSummary", "IfElse", "Static", "ThreadingUtilities"] @@ -1593,26 +1632,28 @@ uuid = "1d0040c9-8b98-4ee7-8388-3f51789ca0ad" version = "0.2.1" [[deps.Polynomials]] -deps = ["LinearAlgebra", "RecipesBase"] -git-tree-sha1 = "3aa2bb4982e575acd7583f01531f241af077b163" +deps = ["LinearAlgebra", "RecipesBase", "Setfield", "SparseArrays"] +git-tree-sha1 = "a9c7a523d5ed375be3983db190f6a5874ae9286d" uuid = "f27b6e38-b328-58d1-80ce-0feddd5e7a45" -version = "3.2.13" +version = "4.0.6" [deps.Polynomials.extensions] PolynomialsChainRulesCoreExt = "ChainRulesCore" + PolynomialsFFTWExt = "FFTW" PolynomialsMakieCoreExt = "MakieCore" PolynomialsMutableArithmeticsExt = "MutableArithmetics" [deps.Polynomials.weakdeps] ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341" MakieCore = "20f20a25-4f0e-4fdf-b5d1-57303727442b" MutableArithmetics = "d8a4904e-b15c-11e9-3269-09a3773c0cb0" [[deps.PooledArrays]] deps = ["DataAPI", "Future"] -git-tree-sha1 = "a6062fe4063cdafe78f4a0a81cfffb89721b30e7" +git-tree-sha1 = "36d8b4b899628fb92c2749eb488d884a926614d3" uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720" -version = "1.4.2" +version = "1.4.3" [[deps.PositiveFactorizations]] deps = ["LinearAlgebra"] @@ -1621,10 +1662,10 @@ uuid = "85a6dd25-e78a-55b7-8502-1745935b8125" version = "0.2.4" [[deps.PreallocationTools]] -deps = ["Adapt", "ArrayInterface", "ForwardDiff", "Requires"] -git-tree-sha1 = "f739b1b3cc7b9949af3b35089931f2b58c289163" +deps = ["Adapt", "ArrayInterface", "ForwardDiff"] +git-tree-sha1 = "13078a8afc9f88ede295c17c3c673eb52c05b0b4" uuid = "d236fae5-4411-538c-8e31-a6e3d9e00b46" -version = "0.4.12" +version = "0.4.16" [deps.PreallocationTools.extensions] PreallocationToolsReverseDiffExt = "ReverseDiff" @@ -1634,33 +1675,33 @@ version = "0.4.12" [[deps.PrecompileTools]] deps = ["Preferences"] -git-tree-sha1 = "9673d39decc5feece56ef3940e5dafba15ba0f81" +git-tree-sha1 = "03b4c25b43cb84cee5c90aa9b5ea0a78fd848d2f" uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" -version = "1.1.2" +version = "1.2.0" [[deps.Preconditioners]] deps = ["AlgebraicMultigrid", "LimitedLDLFactorizations", "LinearAlgebra", "SparseArrays"] -git-tree-sha1 = "00187593573e2bbc3c9d8b1f0488f324e6be30b2" +git-tree-sha1 = "a02fc23058e6264b0f73523e99e2dd1a20232dff" uuid = "af69fa37-3177-5a40-98ee-561f696e4fcd" -version = "0.6.0" +version = "0.6.1" [[deps.Preferences]] deps = ["TOML"] -git-tree-sha1 = "7eb1686b4f04b82f96ed7a4ea5890a4f0c7a09f1" +git-tree-sha1 = "00805cd429dcb4870060ff49ef443486c262e38e" uuid = "21216c6a-2e73-6563-6e65-726566657250" -version = "1.4.0" +version = "1.4.1" [[deps.PrettyTables]] -deps = ["Crayons", "Formatting", "LaTeXStrings", "Markdown", "Reexport", "StringManipulation", "Tables"] -git-tree-sha1 = "213579618ec1f42dea7dd637a42785a608b1ea9c" +deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "Reexport", "StringManipulation", "Tables"] +git-tree-sha1 = "88b895d13d53b5577fd53379d913b9ab9ac82660" uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d" -version = "2.2.4" +version = "2.3.1" [[deps.Primes]] deps = ["IntegerMathUtils"] -git-tree-sha1 = "311a2aa90a64076ea0fac2ad7492e914e6feeb81" +git-tree-sha1 = "1d05623b5952aed1307bf8b43bec8b8d1ef94b6e" uuid = "27ebfcd6-29c5-5fa9-bf4b-fb8fc14df3ae" -version = "0.5.3" +version = "0.5.5" [[deps.Printf]] deps = ["Unicode"] @@ -1672,21 +1713,21 @@ uuid = "9abbd945-dff8-562f-b5e8-e1ebf5ef1b79" [[deps.ProgressMeter]] deps = ["Distributed", "Printf"] -git-tree-sha1 = "d7a7aef8f8f2d537104f170139553b14dfe39fe9" +git-tree-sha1 = "00099623ffee15972c16111bcf84c58a0051257c" uuid = "92933f4c-e287-5a05-a399-4b506db050ca" -version = "1.7.2" +version = "1.9.0" -[[deps.Qt5Base_jll]] -deps = ["Artifacts", "CompilerSupportLibraries_jll", "Fontconfig_jll", "Glib_jll", "JLLWrappers", "Libdl", "Libglvnd_jll", "OpenSSL_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libxcb_jll", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_keysyms_jll", "Xorg_xcb_util_renderutil_jll", "Xorg_xcb_util_wm_jll", "Zlib_jll", "xkbcommon_jll"] -git-tree-sha1 = "0c03844e2231e12fda4d0086fd7cbe4098ee8dc5" -uuid = "ea2cea3b-5b76-57ae-a6ef-0a8af62496e1" -version = "5.15.3+2" +[[deps.Qt6Base_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Fontconfig_jll", "Glib_jll", "JLLWrappers", "Libdl", "Libglvnd_jll", "OpenSSL_jll", "Vulkan_Loader_jll", "Xorg_libSM_jll", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Xorg_libxcb_jll", "Xorg_xcb_util_cursor_jll", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_keysyms_jll", "Xorg_xcb_util_renderutil_jll", "Xorg_xcb_util_wm_jll", "Zlib_jll", "libinput_jll", "xkbcommon_jll"] +git-tree-sha1 = "37b7bb7aabf9a085e0044307e1717436117f2b3b" +uuid = "c0090381-4147-56d7-9ebc-da0b1113ec56" +version = "6.5.3+1" [[deps.QuadGK]] deps = ["DataStructures", "LinearAlgebra"] -git-tree-sha1 = "6ec7ac8412e83d57e313393220879ede1740f9ee" +git-tree-sha1 = "9ebcd48c498668c7fa0e97a9cae873fbee7bfee1" uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc" -version = "2.8.2" +version = "2.9.1" [[deps.QuantEcon]] deps = ["DSP", "DataStructures", "Distributions", "FFTW", "Graphs", "LinearAlgebra", "Markdown", "NLopt", "Optim", "Pkg", "Primes", "Random", "SparseArrays", "SpecialFunctions", "Statistics", "StatsBase", "Test"] @@ -1723,20 +1764,20 @@ deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" [[deps.Random]] -deps = ["SHA", "Serialization"] +deps = ["SHA"] uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" [[deps.Random123]] deps = ["Random", "RandomNumbers"] -git-tree-sha1 = "552f30e847641591ba3f39fd1bed559b9deb0ef3" +git-tree-sha1 = "c860e84651f58ce240dd79e5d9e055d55234c35a" uuid = "74087812-796a-5b5d-8853-05524746bad3" -version = "1.6.1" +version = "1.6.2" [[deps.RandomExtensions]] deps = ["Random", "SparseArrays"] -git-tree-sha1 = "062986376ce6d394b23d5d90f01d81426113a3c9" +git-tree-sha1 = "b8a399e95663485820000f26b6a43c794e166a49" uuid = "fb686558-2515-59ef-acaa-46db3789a887" -version = "0.4.3" +version = "0.4.4" [[deps.RandomNumbers]] deps = ["Random", "Requires"] @@ -1754,12 +1795,6 @@ weakdeps = ["FixedPointNumbers"] [deps.Ratios.extensions] RatiosFixedPointNumbersExt = "FixedPointNumbers" -[[deps.RealDot]] -deps = ["LinearAlgebra"] -git-tree-sha1 = "9f0a1b71baaf7650f4fa8a1d168c7fb6ee41f0c9" -uuid = "c1ae055f-0cd5-4b69-90a6-9a35b1a98df9" -version = "0.1.0" - [[deps.RecipesBase]] deps = ["PrecompileTools"] git-tree-sha1 = "5c3d09cc4f31f5fc6af001c250bf1278733100ff" @@ -1773,26 +1808,30 @@ uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" version = "0.6.12" [[deps.RecursiveArrayTools]] -deps = ["Adapt", "ArrayInterface", "DocStringExtensions", "GPUArraysCore", "IteratorInterfaceExtensions", "LinearAlgebra", "RecipesBase", "Requires", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"] -git-tree-sha1 = "02ef02926f30d53b94be443bfaea010c47f6b556" +deps = ["Adapt", "ArrayInterface", "DocStringExtensions", "GPUArraysCore", "IteratorInterfaceExtensions", "LinearAlgebra", "RecipesBase", "Requires", "SparseArrays", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"] +git-tree-sha1 = "27ee1c03e732c488ecce1a25f0d7da9b5d936574" uuid = "731186ca-8d62-57ce-b412-fbd966d074cd" -version = "2.38.5" +version = "3.3.3" [deps.RecursiveArrayTools.extensions] + RecursiveArrayToolsFastBroadcastExt = "FastBroadcast" RecursiveArrayToolsMeasurementsExt = "Measurements" + RecursiveArrayToolsMonteCarloMeasurementsExt = "MonteCarloMeasurements" RecursiveArrayToolsTrackerExt = "Tracker" RecursiveArrayToolsZygoteExt = "Zygote" [deps.RecursiveArrayTools.weakdeps] + FastBroadcast = "7034ab61-46d4-4ed7-9d0f-46aef9175898" Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" + MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" [[deps.RecursiveFactorization]] -deps = ["LinearAlgebra", "LoopVectorization", "Polyester", "SnoopPrecompile", "StrideArraysCore", "TriangularSolve"] -git-tree-sha1 = "9088515ad915c99026beb5436d0a09cd8c18163e" +deps = ["LinearAlgebra", "LoopVectorization", "Polyester", "PrecompileTools", "StrideArraysCore", "TriangularSolve"] +git-tree-sha1 = "8bc86c78c7d8e2a5fe559e3721c0f9c9e303b2ed" uuid = "f2c3362d-daeb-58d1-803e-2bc74f2840b4" -version = "0.2.18" +version = "0.2.21" [[deps.Reexport]] git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" @@ -1800,16 +1839,28 @@ uuid = "189a3867-3050-52da-a836-e630ba90ab69" version = "1.2.2" [[deps.RegressionTables]] -deps = ["Compat", "Distributions", "FixedEffectModels", "Formatting", "GLM", "Statistics", "StatsBase", "StatsModels", "UnPack"] -git-tree-sha1 = "129bad054effa2b5cb3e2cded441ad316f918b2e" +deps = ["Distributions", "Formatting", "Statistics", "StatsAPI", "StatsBase", "StatsModels"] +git-tree-sha1 = "06c8c14778b921c7d0d588b57315efc6624ab883" uuid = "d519eb52-b820-54da-95a6-98e1306fdade" -version = "0.5.9" +version = "0.6.1" + + [deps.RegressionTables.extensions] + RegressionTablesFixedEffectModelsExt = "FixedEffectModels" + RegressionTablesGLFixedEffectModelsExt = "GLFixedEffectModels" + RegressionTablesGLMExt = "GLM" + RegressionTablesMixedModelsExt = "MixedModels" + + [deps.RegressionTables.weakdeps] + FixedEffectModels = "9d5cd8c9-2029-5cab-9928-427838db53e3" + GLFixedEffectModels = "bafb0ae5-e5f5-5100-81b6-6a55d777c812" + GLM = "38e38edf-8417-5370-95a0-9cbb8c7f171a" + MixedModels = "ff71e718-51f3-5ec2-a782-8ffcbfa3c316" [[deps.RelocatableFolders]] deps = ["SHA", "Scratch"] -git-tree-sha1 = "90bc7a7c96410424509e4263e277e43250c05691" +git-tree-sha1 = "ffdaf70d81cf6ff22c2b6e733c900c3321cab864" uuid = "05181044-ff0b-4ac5-8273-598c1e38db00" -version = "1.0.0" +version = "1.0.1" [[deps.Requires]] deps = ["UUIDs"] @@ -1837,30 +1888,38 @@ version = "0.4.0+0" [[deps.Roots]] deps = ["ChainRulesCore", "CommonSolve", "Printf", "Setfield"] -git-tree-sha1 = "de432823e8aab4dd1a985be4be768f95acf152d4" +git-tree-sha1 = "0f1d92463a020321983d04c110f476c274bafe2e" uuid = "f2b01f46-fcfa-551c-844a-d8ac1e96c665" -version = "2.0.17" +version = "2.0.22" [deps.Roots.extensions] RootsForwardDiffExt = "ForwardDiff" RootsIntervalRootFindingExt = "IntervalRootFinding" RootsSymPyExt = "SymPy" + RootsSymPyPythonCallExt = "SymPyPythonCall" [deps.Roots.weakdeps] ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" IntervalRootFinding = "d2bf35a9-74e0-55ec-b149-d360ff49b807" SymPy = "24249f21-da20-56a4-8eb1-6a02cf4ae2e6" + SymPyPythonCall = "bc8888f7-b21e-4b7c-a06a-5d9c9496438c" [[deps.RuntimeGeneratedFunctions]] deps = ["ExprTools", "SHA", "Serialization"] -git-tree-sha1 = "237edc1563bbf078629b4f8d194bd334e97907cf" +git-tree-sha1 = "6aacc5eefe8415f47b3e34214c1d79d2674a0ba2" uuid = "7e49a35a-f44a-4d26-94aa-eba1b4ca6b47" -version = "0.5.11" +version = "0.5.12" [[deps.SHA]] uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" version = "0.7.0" +[[deps.SIMD]] +deps = ["PrecompileTools"] +git-tree-sha1 = "d8911cc125da009051fb35322415641d02d9e37f" +uuid = "fdea26ae-647d-5447-a871-4b548cad5224" +version = "3.4.6" + [[deps.SIMDTypes]] git-tree-sha1 = "330289636fb8107c5f32088d2741e9fd7a061a5c" uuid = "94e857df-77ce-4151-89e5-788b33177be4" @@ -1868,45 +1927,56 @@ version = "0.1.0" [[deps.SLEEFPirates]] deps = ["IfElse", "Static", "VectorizationBase"] -git-tree-sha1 = "4b8586aece42bee682399c4c4aee95446aa5cd19" +git-tree-sha1 = "3aac6d68c5e57449f5b9b865c9ba50ac2970c4cf" uuid = "476501e8-09a2-5ece-8869-fb82de89a1fa" -version = "0.6.39" +version = "0.6.42" [[deps.SPRAL_jll]] deps = ["Artifacts", "CompilerSupportLibraries_jll", "Hwloc_jll", "JLLWrappers", "Libdl", "METIS_jll", "libblastrampoline_jll"] -git-tree-sha1 = "6dc840d44f2081ac112d29f1d7b9446054d6e763" +git-tree-sha1 = "d1ca34081034a9c6903cfbe068a952a739c2aa5c" uuid = "319450e9-13b8-58e8-aa9f-8fd1420848ab" -version = "2023.3.29+0" +version = "2023.8.2+0" [[deps.SciMLBase]] -deps = ["ADTypes", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "PrecompileTools", "Preferences", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLOperators", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables", "TruncatedStacktraces"] -git-tree-sha1 = "ddf57a23d610d30d0c4bd01132f4646a2a77d171" +deps = ["ADTypes", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "FillArrays", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "PrecompileTools", "Preferences", "Printf", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLOperators", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables", "TruncatedStacktraces"] +git-tree-sha1 = "09324a0ae70c52a45b91b236c62065f78b099c37" uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462" -version = "1.92.5" - -[[deps.SciMLNLSolve]] -deps = ["DiffEqBase", "LineSearches", "NLsolve", "Reexport", "SciMLBase"] -git-tree-sha1 = "2d00015fa0a190220dc5605406b85073f6634391" -uuid = "e9a6253c-8580-4d32-9898-8661bb511710" -version = "0.1.7" +version = "2.15.2" + + [deps.SciMLBase.extensions] + SciMLBaseChainRulesCoreExt = "ChainRulesCore" + SciMLBasePartialFunctionsExt = "PartialFunctions" + SciMLBasePyCallExt = "PyCall" + SciMLBasePythonCallExt = "PythonCall" + SciMLBaseRCallExt = "RCall" + SciMLBaseZygoteExt = "Zygote" + + [deps.SciMLBase.weakdeps] + ChainRules = "082447d4-558c-5d27-93f4-14fc19e9eca2" + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + PartialFunctions = "570af359-4316-4cb7-8c74-252c00c2016b" + PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" + PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d" + RCall = "6f49c342-dc21-5d91-9882-a32aef131414" + Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" [[deps.SciMLOperators]] deps = ["ArrayInterface", "DocStringExtensions", "Lazy", "LinearAlgebra", "Setfield", "SparseArrays", "StaticArraysCore", "Tricks"] -git-tree-sha1 = "6a657a73322170eec86fb427661dbee079b85bff" +git-tree-sha1 = "51ae235ff058a64815e0a2c34b1db7578a06813d" uuid = "c0aeaf25-5076-4817-a8d5-81caf7dfa961" -version = "0.2.12" +version = "0.3.7" [[deps.Scratch]] deps = ["Dates"] -git-tree-sha1 = "30449ee12237627992a99d5e30ae63e4d78cd24a" +git-tree-sha1 = "3bac05bc7e74a75fd9cba4295cde4045d9fe2386" uuid = "6c6a2e73-6563-6170-7368-637461726353" -version = "1.2.0" +version = "1.2.1" [[deps.SentinelArrays]] deps = ["Dates", "Random"] -git-tree-sha1 = "04bdff0b09c65ff3e06a05e3eb7b120223da3d39" +git-tree-sha1 = "0e7508ff27ba32f26cd459474ca2ede1bc10991f" uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c" -version = "1.4.0" +version = "1.4.1" [[deps.Serialization]] uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" @@ -1938,14 +2008,16 @@ uuid = "777ac1f9-54b0-4bf8-805c-2214025038e7" version = "1.1.0" [[deps.SimpleNonlinearSolve]] -deps = ["ArrayInterface", "DiffEqBase", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "PrecompileTools", "Reexport", "Requires", "SciMLBase", "StaticArraysCore"] -git-tree-sha1 = "7c55a3e65aad4ce6e610409cdd564b8d590b9726" +deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "MaybeInplace", "PrecompileTools", "Reexport", "SciMLBase", "StaticArraysCore"] +git-tree-sha1 = "8d672bd91dc432fb286b6d4bcf1a5dc417e932a3" uuid = "727e6d20-b764-4bd8-a329-72de5adea6c7" -version = "0.1.15" -weakdeps = ["NNlib"] +version = "1.2.0" [deps.SimpleNonlinearSolve.extensions] - SimpleBatchedNonlinearSolveExt = "NNlib" + SimpleNonlinearSolvePolyesterForwardDiffExt = "PolyesterForwardDiff" + + [deps.SimpleNonlinearSolve.weakdeps] + PolyesterForwardDiff = "98d1487c-24ca-40b6-b7ab-df2af84e126b" [[deps.SimpleTraits]] deps = ["InteractiveUtils", "MacroTools"] @@ -1958,30 +2030,35 @@ git-tree-sha1 = "58e6353e72cde29b90a69527e56df1b5c3d8c437" uuid = "ce78b400-467f-4804-87d8-8f486da07d0a" version = "1.1.0" -[[deps.SnoopPrecompile]] -deps = ["Preferences"] -git-tree-sha1 = "e760a70afdcd461cf01a575947738d359234665c" -uuid = "66db9d55-30c0-4569-8b51-7e840670fc0c" -version = "1.0.3" - [[deps.Sockets]] uuid = "6462fe0b-24de-5631-8697-dd941f90decc" [[deps.SortingAlgorithms]] deps = ["DataStructures"] -git-tree-sha1 = "a4ada03f999bd01b3a25dcaa30b2d929fe537e00" +git-tree-sha1 = "66e0a8e672a0bdfca2c3f5937efb8538b9ddc085" uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c" -version = "1.1.0" +version = "1.2.1" [[deps.SparseArrays]] deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"] uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +version = "1.10.0" [[deps.SparseDiffTools]] -deps = ["Adapt", "ArrayInterface", "Compat", "DataStructures", "FiniteDiff", "ForwardDiff", "Graphs", "LinearAlgebra", "Requires", "SparseArrays", "StaticArrays", "VertexSafeGraphs"] -git-tree-sha1 = "e19ac47477c9a8fcca06dab5e5471417d5d9d723" +deps = ["ADTypes", "Adapt", "ArrayInterface", "Compat", "DataStructures", "FiniteDiff", "ForwardDiff", "Graphs", "LinearAlgebra", "PackageExtensionCompat", "Random", "Reexport", "SciMLOperators", "Setfield", "SparseArrays", "StaticArrayInterface", "StaticArrays", "Tricks", "UnPack", "VertexSafeGraphs"] +git-tree-sha1 = "c281e11db4eacb36a292a054bac83c5a0aca2a26" uuid = "47a9eef4-7e08-11e9-0b38-333d64bd3804" -version = "1.31.0" +version = "2.15.0" + + [deps.SparseDiffTools.extensions] + SparseDiffToolsEnzymeExt = "Enzyme" + SparseDiffToolsSymbolicsExt = "Symbolics" + SparseDiffToolsZygoteExt = "Zygote" + + [deps.SparseDiffTools.weakdeps] + Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" + Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" + Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" [[deps.Sparspak]] deps = ["Libdl", "LinearAlgebra", "Logging", "OffsetArrays", "Printf", "SparseArrays", "Test"] @@ -1989,16 +2066,11 @@ git-tree-sha1 = "342cf4b449c299d8d1ceaf00b7a49f4fbc7940e7" uuid = "e56a9233-b9d6-4f03-8d0f-1825330902ac" version = "0.3.9" -[[deps.SpatialIndexing]] -git-tree-sha1 = "bacf5065cd7c0d6449b8bba6fa8e75b3087356b0" -uuid = "d4ead438-fe20-5cc5-a293-4fd39a41b74c" -version = "0.1.5" - [[deps.SpecialFunctions]] deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] -git-tree-sha1 = "ef28127915f4229c971eb43f3fc075dd3fe91880" +git-tree-sha1 = "e2cfc4012a19088254b3950b85c3c1d8882d864d" uuid = "276daf66-3868-5448-9aa4-cd146d93841b" -version = "2.2.0" +version = "2.3.1" weakdeps = ["ChainRulesCore"] [deps.SpecialFunctions.extensions] @@ -2006,15 +2078,15 @@ weakdeps = ["ChainRulesCore"] [[deps.Static]] deps = ["IfElse"] -git-tree-sha1 = "dbde6766fc677423598138a5951269432b0fcc90" +git-tree-sha1 = "f295e0a1da4ca425659c57441bcb59abb035a4bc" uuid = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" -version = "0.8.7" +version = "0.8.8" [[deps.StaticArrayInterface]] -deps = ["ArrayInterface", "Compat", "IfElse", "LinearAlgebra", "Requires", "SnoopPrecompile", "SparseArrays", "Static", "SuiteSparse"] -git-tree-sha1 = "33040351d2403b84afce74dae2e22d3f5b18edcb" +deps = ["ArrayInterface", "Compat", "IfElse", "LinearAlgebra", "PrecompileTools", "Requires", "SparseArrays", "Static", "SuiteSparse"] +git-tree-sha1 = "5d66818a39bb04bf328e92bc933ec5b4ee88e436" uuid = "0d7ed370-da01-4f52-bd93-41d350b8b718" -version = "1.4.0" +version = "1.5.0" weakdeps = ["OffsetArrays", "StaticArrays"] [deps.StaticArrayInterface.extensions] @@ -2022,32 +2094,37 @@ weakdeps = ["OffsetArrays", "StaticArrays"] StaticArrayInterfaceStaticArraysExt = "StaticArrays" [[deps.StaticArrays]] -deps = ["LinearAlgebra", "Random", "StaticArraysCore", "Statistics"] -git-tree-sha1 = "832afbae2a45b4ae7e831f86965469a24d1d8a83" +deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"] +git-tree-sha1 = "42d5373c10272d14ef49cc68ffc22df3b93c549a" uuid = "90137ffa-7385-5640-81b9-e52037218182" -version = "1.5.26" +version = "1.8.2" +weakdeps = ["ChainRulesCore", "Statistics"] + + [deps.StaticArrays.extensions] + StaticArraysChainRulesCoreExt = "ChainRulesCore" + StaticArraysStatisticsExt = "Statistics" [[deps.StaticArraysCore]] -git-tree-sha1 = "6b7ba252635a5eff6a0b0664a41ee140a1c9e72a" +git-tree-sha1 = "36b3d696ce6366023a0ea192b4cd442268995a0d" uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" -version = "1.4.0" +version = "1.4.2" [[deps.Statistics]] deps = ["LinearAlgebra", "SparseArrays"] uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" -version = "1.9.0" +version = "1.10.0" [[deps.StatsAPI]] deps = ["LinearAlgebra"] -git-tree-sha1 = "45a7769a04a3cf80da1c1c7c60caf932e6f4c9f7" +git-tree-sha1 = "1ff449ad350c9c4cbc756624d6f8a8c3ef56d3ed" uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0" -version = "1.6.0" +version = "1.7.0" [[deps.StatsBase]] deps = ["DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"] -git-tree-sha1 = "d1bf48bfcc554a3761a133fe3a9bb01488e06916" +git-tree-sha1 = "1d77abd07f617c4868c33d4f5b9e1dbb2643c9cf" uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" -version = "0.33.21" +version = "0.34.2" [[deps.StatsFuns]] deps = ["HypergeometricFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"] @@ -2064,72 +2141,81 @@ version = "1.3.0" InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" [[deps.StatsModels]] -deps = ["DataAPI", "DataStructures", "LinearAlgebra", "Printf", "REPL", "ShiftedArrays", "SparseArrays", "StatsBase", "StatsFuns", "Tables"] -git-tree-sha1 = "a5e15f27abd2692ccb61a99e0854dfb7d48017db" +deps = ["DataAPI", "DataStructures", "LinearAlgebra", "Printf", "REPL", "ShiftedArrays", "SparseArrays", "StatsAPI", "StatsBase", "StatsFuns", "Tables"] +git-tree-sha1 = "5cf6c4583533ee38639f73b880f35fc85f2941e0" uuid = "3eaba693-59b7-5ba5-a881-562e759f1c8d" -version = "0.6.33" +version = "0.7.3" [[deps.StatsPlots]] deps = ["AbstractFFTs", "Clustering", "DataStructures", "Distributions", "Interpolations", "KernelDensity", "LinearAlgebra", "MultivariateStats", "NaNMath", "Observables", "Plots", "RecipesBase", "RecipesPipeline", "Reexport", "StatsBase", "TableOperations", "Tables", "Widgets"] -git-tree-sha1 = "14ef622cf28b05e38f8af1de57bc9142b03fbfe3" +git-tree-sha1 = "9115a29e6c2cf66cf213ccc17ffd61e27e743b24" uuid = "f3b207a7-027a-5e70-b257-86293d7955fd" -version = "0.15.5" +version = "0.15.6" [[deps.StochasticDiffEq]] -deps = ["Adapt", "ArrayInterface", "DataStructures", "DiffEqBase", "DiffEqNoiseProcess", "DocStringExtensions", "FillArrays", "FiniteDiff", "ForwardDiff", "JumpProcesses", "LevyArea", "LinearAlgebra", "Logging", "MuladdMacro", "NLsolve", "OrdinaryDiffEq", "Random", "RandomNumbers", "RecursiveArrayTools", "Reexport", "SciMLBase", "SparseArrays", "SparseDiffTools", "StaticArrays", "UnPack"] -git-tree-sha1 = "073da86200349ddf4ef8bc3e3f3acd62e1d554f7" +deps = ["Adapt", "ArrayInterface", "DataStructures", "DiffEqBase", "DiffEqNoiseProcess", "DocStringExtensions", "FiniteDiff", "ForwardDiff", "JumpProcesses", "LevyArea", "LinearAlgebra", "Logging", "MuladdMacro", "NLsolve", "OrdinaryDiffEq", "Random", "RandomNumbers", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SparseArrays", "SparseDiffTools", "StaticArrays", "UnPack"] +git-tree-sha1 = "753219de57ac7aab0feb88871d3c51e0eb5e3b03" uuid = "789caeaf-c7a9-5a7d-9973-96adeb23e2a0" -version = "6.60.0" +version = "6.64.0" [[deps.StrideArraysCore]] deps = ["ArrayInterface", "CloseOpenIntervals", "IfElse", "LayoutPointers", "ManualMemory", "SIMDTypes", "Static", "StaticArrayInterface", "ThreadingUtilities"] -git-tree-sha1 = "602a8bef17c744f1de965979398597dfa50e1a2f" +git-tree-sha1 = "d6415f66f3d89c615929af907fdc6a3e17af0d8c" uuid = "7792a7ef-975c-4747-a70f-980b88e8d1da" -version = "0.4.15" +version = "0.5.2" [[deps.StringManipulation]] -git-tree-sha1 = "46da2434b41f41ac3594ee9816ce5541c6096123" +deps = ["PrecompileTools"] +git-tree-sha1 = "a04cabe79c5f01f4d723cc6704070ada0b9d46d5" uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e" -version = "0.3.0" - -[[deps.StructArrays]] -deps = ["Adapt", "DataAPI", "GPUArraysCore", "StaticArraysCore", "Tables"] -git-tree-sha1 = "521a0e828e98bb69042fec1809c1b5a680eb7389" -uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" -version = "0.6.15" +version = "0.3.4" [[deps.SuiteSparse]] deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"] uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" [[deps.SuiteSparse_jll]] -deps = ["Artifacts", "Libdl", "Pkg", "libblastrampoline_jll"] +deps = ["Artifacts", "Libdl", "libblastrampoline_jll"] uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" -version = "5.10.1+6" +version = "7.2.1+1" [[deps.SymbolicIndexingInterface]] -deps = ["DocStringExtensions"] -git-tree-sha1 = "f8ab052bfcbdb9b48fad2c80c873aa0d0344dfe5" +git-tree-sha1 = "9336430df9a96f7d85268304b6c3b93f92fb7ff2" uuid = "2efcf032-c050-4f8e-a9bb-153293bab1f5" -version = "0.2.2" +version = "0.3.2" [[deps.SymbolicUtils]] -deps = ["AbstractTrees", "Bijections", "ChainRulesCore", "Combinatorics", "ConstructionBase", "DataStructures", "DocStringExtensions", "DynamicPolynomials", "IfElse", "LabelledArrays", "LinearAlgebra", "MultivariatePolynomials", "NaNMath", "Setfield", "SparseArrays", "SpecialFunctions", "StaticArrays", "TimerOutputs", "Unityper"] -git-tree-sha1 = "5cb1f963f82e7b81305102dd69472fcd3e0e1483" +deps = ["AbstractTrees", "Bijections", "ChainRulesCore", "Combinatorics", "ConstructionBase", "DataStructures", "DocStringExtensions", "DynamicPolynomials", "IfElse", "LabelledArrays", "LinearAlgebra", "MultivariatePolynomials", "NaNMath", "Setfield", "SparseArrays", "SpecialFunctions", "StaticArrays", "SymbolicIndexingInterface", "TimerOutputs", "Unityper"] +git-tree-sha1 = "849b1dfb1680a9e9f2c6023f79a49b694fb6d0da" uuid = "d1185830-fcd6-423d-90d6-eec64667417b" -version = "1.0.5" +version = "1.5.0" [[deps.Symbolics]] -deps = ["ArrayInterface", "ConstructionBase", "DataStructures", "DiffRules", "Distributions", "DocStringExtensions", "DomainSets", "Groebner", "IfElse", "LaTeXStrings", "LambertW", "Latexify", "Libdl", "LinearAlgebra", "MacroTools", "Markdown", "NaNMath", "RecipesBase", "Reexport", "Requires", "RuntimeGeneratedFunctions", "SciMLBase", "Setfield", "SparseArrays", "SpecialFunctions", "StaticArrays", "SymbolicUtils", "TreeViews"] -git-tree-sha1 = "fce1fd0b13f860128c8b8aab0bab475eeeeb7994" +deps = ["ArrayInterface", "Bijections", "ConstructionBase", "DataStructures", "DiffRules", "Distributions", "DocStringExtensions", "DomainSets", "DynamicPolynomials", "Groebner", "IfElse", "LaTeXStrings", "LambertW", "Latexify", "Libdl", "LinearAlgebra", "LogExpFunctions", "MacroTools", "Markdown", "NaNMath", "PrecompileTools", "RecipesBase", "Reexport", "Requires", "RuntimeGeneratedFunctions", "SciMLBase", "Setfield", "SparseArrays", "SpecialFunctions", "StaticArrays", "SymbolicIndexingInterface", "SymbolicUtils"] +git-tree-sha1 = "29856d1168412550fcd74f76ea5560bc2cac06ee" uuid = "0c5d862f-8b57-4792-8d23-62f2024744c7" -version = "5.1.0" +version = "5.15.1" + + [deps.Symbolics.extensions] + SymbolicsPreallocationToolsExt = ["ForwardDiff", "PreallocationTools"] + SymbolicsSymPyExt = "SymPy" + + [deps.Symbolics.weakdeps] + ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" + PreallocationTools = "d236fae5-4411-538c-8e31-a6e3d9e00b46" + SymPy = "24249f21-da20-56a4-8eb1-6a02cf4ae2e6" [[deps.TOML]] deps = ["Dates"] uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" version = "1.0.3" +[[deps.TZJData]] +deps = ["Artifacts"] +git-tree-sha1 = "d39314cdbaf5b90a047db33858626f8d1cc973e1" +uuid = "dc5dba14-91b3-4cab-a142-028a31da12f7" +version = "1.0.0+2023c" + [[deps.TableOperations]] deps = ["SentinelArrays", "Tables", "Test"] git-tree-sha1 = "e383c87cf2a1dc41fa30c093b2a19877c83e1bc1" @@ -2137,10 +2223,10 @@ uuid = "ab02a1b2-a7df-11e8-156e-fb1833f50b87" version = "1.2.0" [[deps.TableShowUtils]] -deps = ["DataValues", "Dates", "JSON", "Markdown", "Test"] -git-tree-sha1 = "14c54e1e96431fb87f0d2f5983f090f1b9d06457" +deps = ["DataValues", "Dates", "JSON", "Markdown", "Unicode"] +git-tree-sha1 = "2a41a3dedda21ed1184a47caab56ed9304e9a038" uuid = "5e66a065-1f0a-5976-b372-e0b8c017ca10" -version = "0.2.5" +version = "0.2.6" [[deps.TableTraits]] deps = ["IteratorInterfaceExtensions"] @@ -2155,10 +2241,10 @@ uuid = "382cd787-c1b6-5bf2-a167-d5b971a19bda" version = "1.0.2" [[deps.Tables]] -deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "OrderedCollections", "TableTraits", "Test"] -git-tree-sha1 = "1544b926975372da01227b382066ab70e574a3ec" +deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "OrderedCollections", "TableTraits"] +git-tree-sha1 = "cb76cf677714c095e535e3501ac7954732aeea2d" uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" -version = "1.10.1" +version = "1.11.1" [[deps.Tar]] deps = ["ArgTools", "SHA"] @@ -2177,15 +2263,19 @@ uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [[deps.ThreadingUtilities]] deps = ["ManualMemory"] -git-tree-sha1 = "c97f60dd4f2331e1a495527f80d242501d2f9865" +git-tree-sha1 = "eda08f7e9818eb53661b3deb74e3159460dfbc27" uuid = "8290d209-cae3-49c0-8002-c8c24d57dab5" -version = "0.5.1" +version = "0.5.2" [[deps.TimeZones]] -deps = ["Dates", "Downloads", "InlineStrings", "LazyArtifacts", "Mocking", "Printf", "RecipesBase", "Scratch", "Unicode"] -git-tree-sha1 = "cdaa0c2a4449724aded839550eca7d7240bb6938" +deps = ["Artifacts", "Dates", "Downloads", "InlineStrings", "LazyArtifacts", "Mocking", "Printf", "Scratch", "TZJData", "Unicode", "p7zip_jll"] +git-tree-sha1 = "89e64d61ef3cd9e80f7fc12b7d13db2d75a23c03" uuid = "f269a46b-ccf7-5d73-abea-4c690281aa53" -version = "1.10.0" +version = "1.13.0" +weakdeps = ["RecipesBase"] + + [deps.TimeZones.extensions] + TimeZonesRecipesBaseExt = "RecipesBase" [[deps.TimerOutputs]] deps = ["ExprTools", "Printf"] @@ -2194,38 +2284,35 @@ uuid = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f" version = "0.5.23" [[deps.TranscodingStreams]] -deps = ["Random", "Test"] -git-tree-sha1 = "9a6ae7ed916312b41236fcef7e0af564ef934769" +git-tree-sha1 = "1fbeaaca45801b4ba17c251dd8603ef24801dd84" uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" -version = "0.9.13" +version = "0.10.2" +weakdeps = ["Random", "Test"] -[[deps.TreeViews]] -deps = ["Test"] -git-tree-sha1 = "8d0d7a3fe2f30d6a7f833a5f19f7c7a5b396eae6" -uuid = "a2a6695c-b41b-5b7d-aed9-dbfdeacea5d7" -version = "0.3.0" + [deps.TranscodingStreams.extensions] + TestExt = ["Test", "Random"] [[deps.TriangularSolve]] deps = ["CloseOpenIntervals", "IfElse", "LayoutPointers", "LinearAlgebra", "LoopVectorization", "Polyester", "Static", "VectorizationBase"] -git-tree-sha1 = "31eedbc0b6d07c08a700e26d31298ac27ef330eb" +git-tree-sha1 = "fadebab77bf3ae041f77346dd1c290173da5a443" uuid = "d5829a12-d9aa-46ab-831f-fb7c9ab06edf" -version = "0.1.19" +version = "0.1.20" [[deps.Tricks]] -git-tree-sha1 = "aadb748be58b492045b4f56166b5188aa63ce549" +git-tree-sha1 = "eae1bb484cd63b36999ee58be2de6c178105112f" uuid = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775" -version = "0.1.7" +version = "0.1.8" [[deps.TruncatedStacktraces]] deps = ["InteractiveUtils", "MacroTools", "Preferences"] -git-tree-sha1 = "7bc1632a4eafbe9bd94cf1a784a9a4eb5e040a91" +git-tree-sha1 = "ea3e54c2bdde39062abf5a9758a23735558705e1" uuid = "781d530d-4396-4725-bb49-402e4bee1e77" -version = "1.3.0" +version = "1.4.0" [[deps.URIs]] -git-tree-sha1 = "074f993b0ca030848b897beff716d93aca60f06a" +git-tree-sha1 = "67db6cc7b3821e19ebe75791a9dd19c9b1188f2b" uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" -version = "1.4.2" +version = "1.5.1" [[deps.UUIDs]] deps = ["Random", "SHA"] @@ -2246,15 +2333,17 @@ uuid = "1cfade01-22cf-5700-b092-accc4b62d6e1" version = "0.4.1" [[deps.Unitful]] -deps = ["ConstructionBase", "Dates", "LinearAlgebra", "Random"] -git-tree-sha1 = "ba4aa36b2d5c98d6ed1f149da916b3ba46527b2b" +deps = ["Dates", "LinearAlgebra", "Random"] +git-tree-sha1 = "3c793be6df9dd77a0cf49d80984ef9ff996948fa" uuid = "1986cc42-f94f-5a68-af5c-568840ba703d" -version = "1.14.0" +version = "1.19.0" [deps.Unitful.extensions] + ConstructionBaseUnitfulExt = "ConstructionBase" InverseFunctionsUnitfulExt = "InverseFunctions" [deps.Unitful.weakdeps] + ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9" InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" [[deps.UnitfulLatexify]] @@ -2265,20 +2354,9 @@ version = "1.6.3" [[deps.Unityper]] deps = ["ConstructionBase"] -git-tree-sha1 = "d5f4ec8c22db63bd3ccb239f640e895cfde145aa" +git-tree-sha1 = "25008b734a03736c41e2a7dc314ecb95bd6bbdb0" uuid = "a7c27f48-0311-42f6-a7f8-2c11e75eb415" -version = "0.1.2" - -[[deps.UnsafeAtomics]] -git-tree-sha1 = "6331ac3440856ea1988316b46045303bef658278" -uuid = "013be700-e6cd-48c3-b4a1-df204f14c38f" -version = "0.2.1" - -[[deps.UnsafeAtomicsLLVM]] -deps = ["LLVM", "UnsafeAtomics"] -git-tree-sha1 = "ea37e6066bf194ab78f4e747f5245261f17a7175" -uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249" -version = "0.1.2" +version = "0.1.6" [[deps.Unzip]] git-tree-sha1 = "ca0969166a028236229f63514992fc073799bb78" @@ -2287,15 +2365,15 @@ version = "0.2.0" [[deps.Vcov]] deps = ["Combinatorics", "GroupedArrays", "LinearAlgebra", "StatsAPI", "StatsBase", "Tables"] -git-tree-sha1 = "7391d297ff5bff38c7158f0e04aaf2f4974b74ba" +git-tree-sha1 = "22491492d601448b0fef54afe8a5bdfd67282965" uuid = "ec2bfdc2-55df-4fc9-b9ae-4958c2cf2486" -version = "0.7.1" +version = "0.8.1" [[deps.VectorizationBase]] deps = ["ArrayInterface", "CPUSummary", "HostCPUFeatures", "IfElse", "LayoutPointers", "Libdl", "LinearAlgebra", "SIMDTypes", "Static", "StaticArrayInterface"] -git-tree-sha1 = "b182207d4af54ac64cbc71797765068fdeff475d" +git-tree-sha1 = "7209df901e6ed7489fe9b7aa3e46fb788e15db85" uuid = "3d5dd08c-fd9d-11e8-17fa-ed2836048c2f" -version = "0.21.64" +version = "0.21.65" [[deps.VertexSafeGraphs]] deps = ["Graphs"] @@ -2303,17 +2381,23 @@ git-tree-sha1 = "8351f8d73d7e880bfc042a8b6922684ebeafb35c" uuid = "19fa3120-7c27-5ec5-8db8-b0b0aa330d6f" version = "0.2.0" +[[deps.Vulkan_Loader_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Wayland_jll", "Xorg_libX11_jll", "Xorg_libXrandr_jll", "xkbcommon_jll"] +git-tree-sha1 = "2f0486047a07670caad3a81a075d2e518acc5c59" +uuid = "a44049a8-05dd-5a78-86c9-5fde0876e88c" +version = "1.3.243+0" + [[deps.Wayland_jll]] -deps = ["Artifacts", "Expat_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg", "XML2_jll"] -git-tree-sha1 = "ed8d92d9774b077c53e1da50fd81a36af3744c1c" +deps = ["Artifacts", "EpollShim_jll", "Expat_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg", "XML2_jll"] +git-tree-sha1 = "7558e29847e99bc3f04d6569e82d0f5c54460703" uuid = "a2964d1f-97da-50d4-b82a-358c7fce9d89" -version = "1.21.0+0" +version = "1.21.0+1" [[deps.Wayland_protocols_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "4528479aa01ee1b3b4cd0e6faef0e04cf16466da" +git-tree-sha1 = "93f43ab61b16ddfb2fd3bb13b3ce241cafb0e6c9" uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91" -version = "1.25.0+0" +version = "1.31.0+0" [[deps.WeakRefStrings]] deps = ["DataAPI", "InlineStrings", "Parsers"] @@ -2329,9 +2413,9 @@ version = "0.6.6" [[deps.WoodburyMatrices]] deps = ["LinearAlgebra", "SparseArrays"] -git-tree-sha1 = "de67fa59e33ad156a590055375a30b23c40299d3" +git-tree-sha1 = "5f24e158cf4cee437052371455fe361f526da062" uuid = "efce3f68-66dc-5838-9240-27a6d6f5f9b6" -version = "0.5.5" +version = "0.5.6" [[deps.WorkerUtilities]] git-tree-sha1 = "cd1659ba0d57b71a464a29e64dbc67cfe83d54e7" @@ -2339,10 +2423,10 @@ uuid = "76eceee3-57b5-4d4a-8e66-0e911cebbf60" version = "1.6.1" [[deps.XML2_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "Zlib_jll"] -git-tree-sha1 = "93c41695bc1c08c46c5899f4fe06d6ead504bb73" +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Zlib_jll"] +git-tree-sha1 = "801cbe47eae69adc50f36c3caec4758d2650741b" uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a" -version = "2.10.3+0" +version = "2.12.2+0" [[deps.XSLT_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgcrypt_jll", "Libgpg_error_jll", "Libiconv_jll", "Pkg", "XML2_jll", "Zlib_jll"] @@ -2350,17 +2434,35 @@ git-tree-sha1 = "91844873c4085240b95e795f692c4cec4d805f8a" uuid = "aed1982a-8fda-507f-9586-7b0439959a61" version = "1.1.34+0" +[[deps.XZ_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "522b8414d40c4cbbab8dee346ac3a09f9768f25d" +uuid = "ffd25f8a-64ca-5728-b0f7-c24cf3aae800" +version = "5.4.5+0" + +[[deps.Xorg_libICE_jll]] +deps = ["Libdl", "Pkg"] +git-tree-sha1 = "e5becd4411063bdcac16be8b66fc2f9f6f1e8fe5" +uuid = "f67eecfb-183a-506d-b269-f58e52b52d7c" +version = "1.0.10+1" + +[[deps.Xorg_libSM_jll]] +deps = ["Libdl", "Pkg", "Xorg_libICE_jll"] +git-tree-sha1 = "4a9d9e4c180e1e8119b5ffc224a7b59d3a7f7e18" +uuid = "c834827a-8449-5923-a945-d239c165b7dd" +version = "1.2.3+0" + [[deps.Xorg_libX11_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll", "Xorg_xtrans_jll"] -git-tree-sha1 = "5be649d550f3f4b95308bf0183b82e2582876527" +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libxcb_jll", "Xorg_xtrans_jll"] +git-tree-sha1 = "afead5aba5aa507ad5a3bf01f58f82c8d1403495" uuid = "4f6342f7-b3d2-589e-9d20-edeb45f2b2bc" -version = "1.6.9+4" +version = "1.8.6+0" [[deps.Xorg_libXau_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "4e490d5c960c314f33885790ed410ff3a94ce67e" +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "6035850dcc70518ca32f012e46015b9beeda49d8" uuid = "0c0b7dd1-d40b-584c-a123-a41640f87eec" -version = "1.0.9+4" +version = "1.0.11+0" [[deps.Xorg_libXcursor_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXfixes_jll", "Xorg_libXrender_jll"] @@ -2369,10 +2471,10 @@ uuid = "935fb764-8cf2-53bf-bb30-45bb1f8bf724" version = "1.2.0+4" [[deps.Xorg_libXdmcp_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "4fe47bd2247248125c428978740e18a681372dd4" +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "34d526d318358a859d7de23da945578e8e8727b7" uuid = "a3789734-cfe1-5b06-b2d0-1dd0d9d62d05" -version = "1.1.3+4" +version = "1.1.4+0" [[deps.Xorg_libXext_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"] @@ -2411,22 +2513,28 @@ uuid = "ea2f1a96-1ddc-540d-b46f-429655e07cfa" version = "0.9.10+4" [[deps.Xorg_libpthread_stubs_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "6783737e45d3c59a4a4c4091f5f88cdcf0908cbb" +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "8fdda4c692503d44d04a0603d9ac0982054635f9" uuid = "14d82f49-176c-5ed1-bb49-ad3f5cbd8c74" -version = "0.1.0+3" +version = "0.1.1+0" [[deps.Xorg_libxcb_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "XSLT_jll", "Xorg_libXau_jll", "Xorg_libXdmcp_jll", "Xorg_libpthread_stubs_jll"] -git-tree-sha1 = "daf17f441228e7a3833846cd048892861cff16d6" +deps = ["Artifacts", "JLLWrappers", "Libdl", "XSLT_jll", "Xorg_libXau_jll", "Xorg_libXdmcp_jll", "Xorg_libpthread_stubs_jll"] +git-tree-sha1 = "b4bfde5d5b652e22b9c790ad00af08b6d042b97d" uuid = "c7cfdc94-dc32-55de-ac96-5a1b8d977c5b" -version = "1.13.0+3" +version = "1.15.0+0" [[deps.Xorg_libxkbfile_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"] -git-tree-sha1 = "926af861744212db0eb001d9e40b5d16292080b2" +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll"] +git-tree-sha1 = "730eeca102434283c50ccf7d1ecdadf521a765a4" uuid = "cc61e674-0454-545c-8b26-ed2c68acab7a" -version = "1.1.0+4" +version = "1.1.2+0" + +[[deps.Xorg_xcb_util_cursor_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_jll", "Xorg_xcb_util_renderutil_jll"] +git-tree-sha1 = "04341cb870f29dcd5e39055f895c39d016e18ccd" +uuid = "e920d4aa-a673-5f3a-b3d7-f755a4d47c43" +version = "0.1.4+0" [[deps.Xorg_xcb_util_image_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"] @@ -2459,27 +2567,27 @@ uuid = "c22f9ab0-d5fe-5066-847c-f4bb1cd4e361" version = "0.4.1+1" [[deps.Xorg_xkbcomp_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxkbfile_jll"] -git-tree-sha1 = "4bcbf660f6c2e714f87e960a171b119d06ee163b" +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libxkbfile_jll"] +git-tree-sha1 = "330f955bc41bb8f5270a369c473fc4a5a4e4d3cb" uuid = "35661453-b289-5fab-8a00-3d9160c6a3a4" -version = "1.4.2+4" +version = "1.4.6+0" [[deps.Xorg_xkeyboard_config_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xkbcomp_jll"] -git-tree-sha1 = "5c8424f8a67c3f2209646d4425f3d415fee5931d" +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_xkbcomp_jll"] +git-tree-sha1 = "691634e5453ad362044e2ad653e79f3ee3bb98c3" uuid = "33bec58e-1273-512f-9401-5d533626f822" -version = "2.27.0+4" +version = "2.39.0+0" [[deps.Xorg_xtrans_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "79c31e7844f6ecf779705fbc12146eb190b7d845" +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "e92a1a012a10506618f10b7047e478403a046c77" uuid = "c5fb5394-a638-5e4d-96e5-b29de1b5cf10" -version = "1.4.0+3" +version = "1.5.0+0" [[deps.Zlib_jll]] deps = ["Libdl"] uuid = "83775a58-1f1d-513f-b197-d71354ab007a" -version = "1.2.13+0" +version = "1.2.13+1" [[deps.Zstd_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl"] @@ -2487,33 +2595,23 @@ git-tree-sha1 = "49ce682769cd5de6c72dcf1b94ed7790cd08974c" uuid = "3161d3a3-bdf6-5164-811a-617609db77b4" version = "1.5.5+0" -[[deps.Zygote]] -deps = ["AbstractFFTs", "ChainRules", "ChainRulesCore", "DiffRules", "Distributed", "FillArrays", "ForwardDiff", "GPUArrays", "GPUArraysCore", "IRTools", "InteractiveUtils", "LinearAlgebra", "LogExpFunctions", "MacroTools", "NaNMath", "PrecompileTools", "Random", "Requires", "SparseArrays", "SpecialFunctions", "Statistics", "ZygoteRules"] -git-tree-sha1 = "5be3ddb88fc992a7d8ea96c3f10a49a7e98ebc7b" -uuid = "e88e6eb3-aa80-5325-afca-941959d7151f" -version = "0.6.62" - - [deps.Zygote.extensions] - ZygoteColorsExt = "Colors" - ZygoteDistancesExt = "Distances" - ZygoteTrackerExt = "Tracker" - - [deps.Zygote.weakdeps] - Colors = "5ae59095-9a9b-59fe-a467-6f913c188581" - Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7" - Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" - -[[deps.ZygoteRules]] -deps = ["ChainRulesCore", "MacroTools"] -git-tree-sha1 = "977aed5d006b840e2e40c0b48984f7463109046d" -uuid = "700de1a5-db45-46bc-99cf-38207098b444" -version = "0.2.3" +[[deps.eudev_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "gperf_jll"] +git-tree-sha1 = "431b678a28ebb559d224c0b6b6d01afce87c51ba" +uuid = "35ca27e7-8b34-5b7f-bca9-bdc33f59eb06" +version = "3.2.9+0" [[deps.fzf_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] -git-tree-sha1 = "868e669ccb12ba16eaf50cb2957ee2ff61261c56" +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "a68c9655fbe6dfcab3d972808f1aafec151ce3f8" uuid = "214eeab7-80f7-51ab-84ad-2988db7cef09" -version = "0.29.0+0" +version = "0.43.0+0" + +[[deps.gperf_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "3516a5630f741c9eecb3720b1ec9d8edc3ecc033" +uuid = "1a1c6b14-54f6-533d-8383-74cd7377aa70" +version = "3.1.1+0" [[deps.libaom_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -2530,7 +2628,13 @@ version = "0.15.1+0" [[deps.libblastrampoline_jll]] deps = ["Artifacts", "Libdl"] uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" -version = "5.8.0+0" +version = "5.8.0+1" + +[[deps.libevdev_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "141fe65dc3efabb0b1d5ba74e91f6ad26f84cc22" +uuid = "2db6ffa8-e38f-5e21-84af-90c45d0032cc" +version = "1.11.0+0" [[deps.libfdk_aac_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -2538,11 +2642,17 @@ git-tree-sha1 = "daacc84a041563f965be61859a36e17c4e4fcd55" uuid = "f638f0a6-7fb0-5443-88ba-1cc74229b280" version = "2.0.2+0" +[[deps.libinput_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "eudev_jll", "libevdev_jll", "mtdev_jll"] +git-tree-sha1 = "ad50e5b90f222cfe78aa3d5183a20a12de1322ce" +uuid = "36db933b-70db-51c0-b978-0f229ee0e533" +version = "1.18.0+0" + [[deps.libpng_jll]] -deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"] -git-tree-sha1 = "94d180a6d2b5e55e447e2d27a29ed04fe79eb30c" +deps = ["Artifacts", "JLLWrappers", "Libdl", "Zlib_jll"] +git-tree-sha1 = "93284c28274d9e75218a416c65ec49d0e0fcdf3d" uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f" -version = "1.6.38+0" +version = "1.6.40+0" [[deps.libvorbis_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Ogg_jll", "Pkg"] @@ -2550,15 +2660,21 @@ git-tree-sha1 = "b910cb81ef3fe6e78bf6acee440bda86fd6ae00c" uuid = "f27f6e37-5d2b-51aa-960f-b287f2bc3b7a" version = "1.3.7+1" +[[deps.mtdev_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "814e154bdb7be91d78b6802843f76b6ece642f11" +uuid = "009596ad-96f7-51b1-9f1b-5ce2d5e8a71e" +version = "1.1.6+0" + [[deps.nghttp2_jll]] deps = ["Artifacts", "Libdl"] uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" -version = "1.48.0+0" +version = "1.52.0+1" [[deps.p7zip_jll]] deps = ["Artifacts", "Libdl"] uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" -version = "17.4.0+0" +version = "17.4.0+2" [[deps.x264_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -2574,6 +2690,6 @@ version = "3.5.0+0" [[deps.xkbcommon_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll", "Wayland_protocols_jll", "Xorg_libxcb_jll", "Xorg_xkeyboard_config_jll"] -git-tree-sha1 = "9ebfc140cc56e8c2156a15ceac2f0302e327ac0a" +git-tree-sha1 = "9c304562909ab2bab0262639bd4f444d7bc2be37" uuid = "d8fb68d0-12a3-5cfd-a85a-d49703b185fd" -version = "1.4.1+0" +version = "1.4.1+1" diff --git a/lectures/Project.toml b/lectures/Project.toml index b1987bf5..1e00c810 100644 --- a/lectures/Project.toml +++ b/lectures/Project.toml @@ -1,17 +1,15 @@ name = "quantecon-notebooks-julia" authors = ["quantecon "] -version = "0.8.1" +version = "0.10.0" [deps] Arpack = "7d9fca2a-8960-54d3-9f78-7d1dccf2cb97" BandedMatrices = "aae01518-5342-5314-be14-df237901396f" BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" -BlackBoxOptim = "a134a8b2-14d6-55f6-9291-3336d3ab0209" CategoricalArrays = "324d7699-5711-5eae-9e2f-1d82baa6b597" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" DataFramesMeta = "1313f7d8-7da2-5740-9ea0-a2ca25f37964" DataInterpolations = "82cc6244-b520-54b8-b5a6-8a565e85f1d0" -DiffEqOperators = "9fdde737-9c7f-55bf-ade8-46b3f136cc48" Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" Expectations = "2fe49d83-0758-5602-8f54-1f90ad0d522b" FastGaussQuadrature = "442a2c76-b920-505d-bb47-c5924d526838" @@ -27,7 +25,6 @@ JuMP = "4076af6c-e467-56ae-b986-b466b2749572" KernelDensity = "5ab0869b-81aa-558d-bb23-cbf5423bbe9b" LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316" -LeastSquaresOptim = "0fc2ff8b-aaa3-5acd-a817-1944a5e08891" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" LinearMaps = "7a12625a-238d-50fd-b39a-03d52299707e" LoopVectorization = "bdcacae8-1622-11e9-2a5c-532679323890" @@ -54,4 +51,3 @@ StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd" StochasticDiffEq = "789caeaf-c7a9-5a7d-9973-96adeb23e2a0" Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" -Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" diff --git a/lectures/_config.yml b/lectures/_config.yml index 966d57d6..33c4da49 100644 --- a/lectures/_config.yml +++ b/lectures/_config.yml @@ -88,7 +88,7 @@ sphinx: rediraffe_redirects: index_toc.md: intro.md tojupyter_default_lang: julia - tojupyter_lang_synonyms: ['julia-1.9'] + tojupyter_lang_synonyms: ['julia-1.10'] tojupyter_static_file_path: ["source/_static", "_static"] tojupyter_target_html: true tojupyter_urlpath: "https://julia.quantecon.org/" @@ -98,5 +98,5 @@ sphinx: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 tojupyter_images_markdown: true diff --git a/lectures/about_lectures.md b/lectures/about_lectures.md index 0adf01a8..bce53881 100644 --- a/lectures/about_lectures.md +++ b/lectures/about_lectures.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (about)= diff --git a/lectures/continuous_time/covid_sde.md b/lectures/continuous_time/covid_sde.md index c0576465..fae1e19b 100644 --- a/lectures/continuous_time/covid_sde.md +++ b/lectures/continuous_time/covid_sde.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (covid_sde)= diff --git a/lectures/continuous_time/seir_model.md b/lectures/continuous_time/seir_model.md index c36fdb06..5cc01c4c 100644 --- a/lectures/continuous_time/seir_model.md +++ b/lectures/continuous_time/seir_model.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (seir_model)= diff --git a/lectures/dynamic_programming/career.md b/lectures/dynamic_programming/career.md index 3427a329..d850e558 100644 --- a/lectures/dynamic_programming/career.md +++ b/lectures/dynamic_programming/career.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (career)= diff --git a/lectures/dynamic_programming/coleman_policy_iter.md b/lectures/dynamic_programming/coleman_policy_iter.md index 2139ff21..cd1de243 100644 --- a/lectures/dynamic_programming/coleman_policy_iter.md +++ b/lectures/dynamic_programming/coleman_policy_iter.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (coleman_policy_iter)= diff --git a/lectures/dynamic_programming/discrete_dp.md b/lectures/dynamic_programming/discrete_dp.md index 0e0c5857..b7df784b 100644 --- a/lectures/dynamic_programming/discrete_dp.md +++ b/lectures/dynamic_programming/discrete_dp.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (discrete_dp)= diff --git a/lectures/dynamic_programming/egm_policy_iter.md b/lectures/dynamic_programming/egm_policy_iter.md index c5327d6b..35d64061 100644 --- a/lectures/dynamic_programming/egm_policy_iter.md +++ b/lectures/dynamic_programming/egm_policy_iter.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (egm_policy_iter)= diff --git a/lectures/dynamic_programming/ifp.md b/lectures/dynamic_programming/ifp.md index 5b38c984..29a60008 100644 --- a/lectures/dynamic_programming/ifp.md +++ b/lectures/dynamic_programming/ifp.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (ifp)= diff --git a/lectures/dynamic_programming/jv.md b/lectures/dynamic_programming/jv.md index f103f6f5..58485e32 100644 --- a/lectures/dynamic_programming/jv.md +++ b/lectures/dynamic_programming/jv.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (jv)= diff --git a/lectures/dynamic_programming/lqcontrol.md b/lectures/dynamic_programming/lqcontrol.md index 2e0e97a8..7867f5e7 100644 --- a/lectures/dynamic_programming/lqcontrol.md +++ b/lectures/dynamic_programming/lqcontrol.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (lqc)= diff --git a/lectures/dynamic_programming/mccall_model.md b/lectures/dynamic_programming/mccall_model.md index e9f2a3cd..40cc4285 100644 --- a/lectures/dynamic_programming/mccall_model.md +++ b/lectures/dynamic_programming/mccall_model.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (mccall)= diff --git a/lectures/dynamic_programming/mccall_model_with_separation.md b/lectures/dynamic_programming/mccall_model_with_separation.md index 357e3438..a1a05ff3 100644 --- a/lectures/dynamic_programming/mccall_model_with_separation.md +++ b/lectures/dynamic_programming/mccall_model_with_separation.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (mccall_with_sep)= diff --git a/lectures/dynamic_programming/odu.md b/lectures/dynamic_programming/odu.md index 0abca506..08db5a86 100644 --- a/lectures/dynamic_programming/odu.md +++ b/lectures/dynamic_programming/odu.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (odu)= diff --git a/lectures/dynamic_programming/optgrowth.md b/lectures/dynamic_programming/optgrowth.md index 1afcbc65..94ec3f62 100644 --- a/lectures/dynamic_programming/optgrowth.md +++ b/lectures/dynamic_programming/optgrowth.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (optgrowth)= diff --git a/lectures/dynamic_programming/perm_income.md b/lectures/dynamic_programming/perm_income.md index 1fa228e1..765ddcd6 100644 --- a/lectures/dynamic_programming/perm_income.md +++ b/lectures/dynamic_programming/perm_income.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (perm_income)= diff --git a/lectures/dynamic_programming/perm_income_cons.md b/lectures/dynamic_programming/perm_income_cons.md index 6b880d27..e4accdf0 100644 --- a/lectures/dynamic_programming/perm_income_cons.md +++ b/lectures/dynamic_programming/perm_income_cons.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (perm_income_cons)= diff --git a/lectures/dynamic_programming/robustness.md b/lectures/dynamic_programming/robustness.md index 38ed5ab9..37ef6fb0 100644 --- a/lectures/dynamic_programming/robustness.md +++ b/lectures/dynamic_programming/robustness.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (rob)= diff --git a/lectures/dynamic_programming/smoothing.md b/lectures/dynamic_programming/smoothing.md index 4fe147b0..31514075 100644 --- a/lectures/dynamic_programming/smoothing.md +++ b/lectures/dynamic_programming/smoothing.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (smoothing)= diff --git a/lectures/dynamic_programming/wald_friedman.md b/lectures/dynamic_programming/wald_friedman.md index 3413dd26..033f5382 100644 --- a/lectures/dynamic_programming/wald_friedman.md +++ b/lectures/dynamic_programming/wald_friedman.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (wald_friedman)= @@ -509,7 +509,7 @@ function simulation(problem) return return_output ? (alpha, beta, outcomes, costs, trials) : nothing end -function Problem(d0 = Beta(1, 1), d1 = Beta(9, 9), +function Problem(;d0 = Beta(1, 1), d1 = Beta(9, 9), L0 = 2, L1 = 2, c = 0.2, p = 0.5, n = 100, return_output = false) @@ -524,7 +524,7 @@ tags: [remove-cell] @testset "Verifying Output" begin Random.seed!(0) (;d0, d1, L0, L1, c) = Problem() - alpha, beta, outcomes, costs, trials = simulation(Problem(return_output = true)) + alpha, beta, outcomes, costs, trials = simulation(Problem(;return_output = true)) #test alpha ≈ 0.57428237 #test beta ≈ 0.352510338 choices = first.(choice.((clamp(beta - eps(), 0, 1), @@ -551,7 +551,7 @@ tags: [remove-cell] @testset "Comparative Statics" begin Random.seed!(0) (;d0, d1, L0, L1, c) = Problem() - alpha, beta, outcomes, costs, trials = simulation(Problem(c = 2c, return_output = true)) + alpha, beta, outcomes, costs, trials = simulation(Problem(;c = 2c, return_output = true)) #test alpha ≈ 0.53551172 atol = 1e-3 #test beta ≈ 0.41244737 atol = 1e-3 #test mean(outcomes) ≈ 0.39 atol = 1e-2 @@ -582,7 +582,7 @@ Before you look, think about what will happen: ```{code-cell} julia Random.seed!(0); -simulation(Problem(c = 0.4)); +simulation(Problem(;c = 0.4)); ``` Notice what happens? diff --git a/lectures/dynamic_programming_squared/amss.md b/lectures/dynamic_programming_squared/amss.md index e9fee44a..1bc4fee1 100644 --- a/lectures/dynamic_programming_squared/amss.md +++ b/lectures/dynamic_programming_squared/amss.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (opt_tax_amss)= @@ -1036,14 +1036,14 @@ function solve_time1_bellman(model::Model{TR}, μgrid::AbstractArray) where {TR xprimes = repeat(x, 1, S) xgrid[s_, :] = x for sprime = 1:S - splc = CubicSpline(c[:, sprime][end:-1:1], x[end:-1:1]) - spln = CubicSpline(n[:, sprime][end:-1:1], x[end:-1:1]) - splx = CubicSpline(xprimes[:, sprime][end:-1:1], x[end:-1:1]) + splc = CubicSpline(c[:, sprime][end:-1:1], x[end:-1:1];extrapolate=true) + spln = CubicSpline(n[:, sprime][end:-1:1], x[end:-1:1];extrapolate=true) + splx = CubicSpline(xprimes[:, sprime][end:-1:1], x[end:-1:1];extrapolate=true) cf[s_, sprime] = y -> splc(y) nf[s_, sprime] = y -> spln(y) xprimef[s_, sprime] = y -> splx(y) end - splV = CubicSpline(V[end:-1:1], x[end:-1:1]) + splV = CubicSpline(V[end:-1:1], x[end:-1:1];extrapolate=true) Vf[s_] = y -> splV(y) end diff --git a/lectures/dynamic_programming_squared/dyn_stack.md b/lectures/dynamic_programming_squared/dyn_stack.md index e8c1d5d7..6a0f08f8 100644 --- a/lectures/dynamic_programming_squared/dyn_stack.md +++ b/lectures/dynamic_programming_squared/dyn_stack.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (dyn_stack)= diff --git a/lectures/dynamic_programming_squared/lqramsey.md b/lectures/dynamic_programming_squared/lqramsey.md index d42e659e..9aef62cb 100644 --- a/lectures/dynamic_programming_squared/lqramsey.md +++ b/lectures/dynamic_programming_squared/lqramsey.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (lqramsey)= diff --git a/lectures/dynamic_programming_squared/opt_tax_recur.md b/lectures/dynamic_programming_squared/opt_tax_recur.md index 2a6aea2e..93571209 100644 --- a/lectures/dynamic_programming_squared/opt_tax_recur.md +++ b/lectures/dynamic_programming_squared/opt_tax_recur.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (opt_tax_recur)= diff --git a/lectures/getting_started_julia/fundamental_types.md b/lectures/getting_started_julia/fundamental_types.md index 27134997..57e5848a 100644 --- a/lectures/getting_started_julia/fundamental_types.md +++ b/lectures/getting_started_julia/fundamental_types.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (fundamental_types)= diff --git a/lectures/getting_started_julia/getting_started.md b/lectures/getting_started_julia/getting_started.md index 01b518f8..88a6ef11 100644 --- a/lectures/getting_started_julia/getting_started.md +++ b/lectures/getting_started_julia/getting_started.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (getting_started)= diff --git a/lectures/getting_started_julia/introduction_to_types.md b/lectures/getting_started_julia/introduction_to_types.md index f756c3b2..63298324 100644 --- a/lectures/getting_started_julia/introduction_to_types.md +++ b/lectures/getting_started_julia/introduction_to_types.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (introduction_to_types)= diff --git a/lectures/getting_started_julia/julia_by_example.md b/lectures/getting_started_julia/julia_by_example.md index 18f8383a..6ba241f7 100644 --- a/lectures/getting_started_julia/julia_by_example.md +++ b/lectures/getting_started_julia/julia_by_example.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (julia_by_example)= diff --git a/lectures/getting_started_julia/julia_essentials.md b/lectures/getting_started_julia/julia_essentials.md index 29f54f4f..1a06f3ed 100644 --- a/lectures/getting_started_julia/julia_essentials.md +++ b/lectures/getting_started_julia/julia_essentials.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (julia_essentials)= diff --git a/lectures/introduction_dynamics/ar1_processes.md b/lectures/introduction_dynamics/ar1_processes.md index 72994099..dd010ab2 100644 --- a/lectures/introduction_dynamics/ar1_processes.md +++ b/lectures/introduction_dynamics/ar1_processes.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (ar1)= diff --git a/lectures/introduction_dynamics/finite_markov.md b/lectures/introduction_dynamics/finite_markov.md index b42d5ebe..66995304 100644 --- a/lectures/introduction_dynamics/finite_markov.md +++ b/lectures/introduction_dynamics/finite_markov.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (mc)= diff --git a/lectures/introduction_dynamics/kalman.md b/lectures/introduction_dynamics/kalman.md index 545aa472..522f9670 100644 --- a/lectures/introduction_dynamics/kalman.md +++ b/lectures/introduction_dynamics/kalman.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (kalman)= diff --git a/lectures/introduction_dynamics/linear_models.md b/lectures/introduction_dynamics/linear_models.md index 4cb70fd5..06199f4d 100644 --- a/lectures/introduction_dynamics/linear_models.md +++ b/lectures/introduction_dynamics/linear_models.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (lssm)= diff --git a/lectures/introduction_dynamics/scalar_dynam.md b/lectures/introduction_dynamics/scalar_dynam.md index 54a39f94..145f1532 100644 --- a/lectures/introduction_dynamics/scalar_dynam.md +++ b/lectures/introduction_dynamics/scalar_dynam.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (scalar_dynam)= diff --git a/lectures/introduction_dynamics/short_path.md b/lectures/introduction_dynamics/short_path.md index 1f77d93f..b6b60456 100644 --- a/lectures/introduction_dynamics/short_path.md +++ b/lectures/introduction_dynamics/short_path.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (short_path)= diff --git a/lectures/introduction_dynamics/wealth_dynamics.md b/lectures/introduction_dynamics/wealth_dynamics.md index d94f8043..88a8da89 100644 --- a/lectures/introduction_dynamics/wealth_dynamics.md +++ b/lectures/introduction_dynamics/wealth_dynamics.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (wd)= diff --git a/lectures/more_julia/data_statistical_packages.md b/lectures/more_julia/data_statistical_packages.md index c557eb7a..47c78737 100644 --- a/lectures/more_julia/data_statistical_packages.md +++ b/lectures/more_julia/data_statistical_packages.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (data_statistical_packages)= diff --git a/lectures/more_julia/general_packages.md b/lectures/more_julia/general_packages.md index e126c136..df61cc13 100644 --- a/lectures/more_julia/general_packages.md +++ b/lectures/more_julia/general_packages.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (general_packages)= diff --git a/lectures/more_julia/generic_programming.md b/lectures/more_julia/generic_programming.md index bdeec031..f7d4fdc4 100644 --- a/lectures/more_julia/generic_programming.md +++ b/lectures/more_julia/generic_programming.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (generic_programming)= diff --git a/lectures/more_julia/optimization_solver_packages.md b/lectures/more_julia/optimization_solver_packages.md index 5d272770..af179d55 100644 --- a/lectures/more_julia/optimization_solver_packages.md +++ b/lectures/more_julia/optimization_solver_packages.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (optimization_solver_packages)= @@ -35,7 +35,7 @@ In this lecture we introduce a few of the Julia libraries that we've found parti tags: [hide-output] --- using LinearAlgebra, Statistics -using ForwardDiff, Zygote, Optim, JuMP, Ipopt, BlackBoxOptim, Roots, NLsolve, LeastSquaresOptim +using ForwardDiff, Optim, JuMP, Ipopt, Roots, NLsolve using Optim: converged, maximum, maximizer, minimizer, iterations #some extra functions ``` @@ -222,80 +222,17 @@ dsqrt(x) = ForwardDiff.derivative(squareroot, x) dsqrt(2.0) ``` -### Zygote.jl +### Reverse-Mode AD Unlike forward-mode auto-differentiation, reverse-mode is very difficult to implement efficiently, and there are many variations on the best approach. Many reverse-mode packages are connected to machine-learning packages, since the efficient gradients of $R^N \to R$ loss functions are necessary for the gradient descent optimization algorithms used in machine learning. -One recent package is [Zygote.jl](https://github.com/FluxML/Zygote.jl), which is used in the Flux.jl framework. +At this point, Julia does not have a single consistently usable reverse-mode AD package without rough edges, but a few key ones to consider are: -```{code-cell} julia -using Zygote - -h(x, y) = 3x^2 + 2x + 1 + y * x - y -gradient(h, 3.0, 5.0) -``` - -Here we see that Zygote has a gradient function as the interface, which returns a tuple. - -You could create this as an operator if you wanted to., - -```{code-cell} julia -D(f) = x -> gradient(f, x)[1] # returns first in tuple - -D_sin = D(sin) -D_sin(4.0) -``` - -For functions of one (Julia) variable, we can find the by simply using the `'` after a function name - -```{code-cell} julia -using Statistics -p(x) = mean(abs, x) -p'([1.0, 3.0, -2.0]) -``` - -Or, using the complicated iterative function we defined for the squareroot, - -```{code-cell} julia -squareroot'(2.0) -``` - -Zygote supports combinations of vectors and scalars as the function parameters. - -```{code-cell} julia -h(x, n) = (sum(x .^ n))^(1 / n) -gradient(h, [1.0, 4.0, 6.0], 2.0) -``` - -The gradients can be very high dimensional. For example, to do a simple nonlinear optimization problem -with 1 million dimensions, solved in a few seconds. - -```{code-cell} julia -using Optim, LinearAlgebra -N = 1000000 -y = rand(N) -lambda = 0.01 -obj(x) = sum((x .- y) .^ 2) + lambda * norm(x) - -x_iv = rand(N) -function g!(G, x) - G .= obj'(x) -end - -results = optimize(obj, g!, x_iv, LBFGS()) # or ConjugateGradient() -println("minimum = $(results.minimum) with in " * - "$(results.iterations) iterations") -``` - -Caution: while Zygote is the most exciting reverse-mode AD implementation in Julia, it has many rough edges. - -- If you write a function, take its gradient, and then modify the function, you need to call `Zygote.refresh()` or else the gradient will be out of sync. This may not apply for Julia 1.3+. -- It provides no features for getting Jacobians, so you would have to ask for each row of the Jacobian separately. That said, you - probably want to use `ForwardDiff.jl` for Jacobians if the dimension of the output is similar to the dimension of the input. -- You cannot, in the current release, use mutating functions (e.g. modify a value in an array/etc.) although that feature is in progress. -- Compiling can be very slow for complicated functions. +- [ReverseDiff.jl](https://github.com/JuliaDiff/ReverseDiff.jl), a relatively dependable but limited package. Not really intended for standard ML-pipline usage +- [Zygote.jl](https://github.com/FluxML/Zygote.jl), which is flexible but buggy and less reliable. In a slow process of deprecation, but often the primary alternative. +- [Enzyme.jl](https://enzyme.mit.edu/julia/stable/), which is the most promising (and supports both forward and reverse mode). However, the usage is more tailored for scientific machine learning and scalar functions rather than fast GPU kernels, and it relies on a innovative (but not fully stable) approach to compilation. ## Optimization @@ -482,17 +419,6 @@ println("x = ", value(x), " y = ", value(y)) Another package for doing global optimization without derivatives is [BlackBoxOptim.jl](https://github.com/robertfeldt/BlackBoxOptim.jl). -To see an example from the documentation - -```{code-cell} julia -using BlackBoxOptim - -function rosenbrock2d(x) - return (1.0 - x[1])^2 + 100.0 * (x[2] - x[1]^2)^2 -end - -results = bboptimize(rosenbrock2d; SearchRange = (-5.0, 5.0), NumDimensions = 2); -``` An example for [parallel execution](https://github.com/robertfeldt/BlackBoxOptim.jl/blob/master/examples/rosenbrock_parallel.jl) of the objective is provided. @@ -586,46 +512,6 @@ If $M = N$ and we know a root $F(x^*) = 0$ to the system of equations exists, th An implementation of NLS is given in [LeastSquaresOptim.jl](https://github.com/matthieugomez/LeastSquaresOptim.jl). -From the documentation - -```{code-cell} julia -using LeastSquaresOptim -function rosenbrock(x) - [1 - x[1], 100 * (x[2] - x[1]^2)] -end -LeastSquaresOptim.optimize(rosenbrock, zeros(2), Dogleg()) -``` - -**Note:** Because there is a name clash between `Optim.jl` and this package, to use both we need to qualify the use of the `optimize` function (i.e. `LeastSquaresOptim.optimize`). - -Here, by default it will use AD with `ForwardDiff.jl` to calculate the Jacobian, -but you could also provide your own calculation of the Jacobian (analytical or using finite differences) and/or calculate the function inplace. - -```{code-cell} julia -function rosenbrock_f!(out, x) - out[1] = 1 - x[1] - out[2] = 100 * (x[2] - x[1]^2) -end -LeastSquaresOptim.optimize!(LeastSquaresProblem(x = zeros(2), - f! = rosenbrock_f!, - output_length = 2)) - -# if you want to use gradient -function rosenbrock_g!(J, x) - J[1, 1] = -1 - J[1, 2] = 0 - J[2, 1] = -200 * x[1] - J[2, 2] = 100 -end -LeastSquaresOptim.optimize!(LeastSquaresProblem(x = zeros(2), - f! = rosenbrock_f!, - g! = rosenbrock_g!, - output_length = 2)) -``` - -## Additional Notes - -Watch [this video](https://www.youtube.com/watch?v=vAp6nUMrKYg&feature=youtu.be) from one of Julia's creators on automatic differentiation. ## Exercises diff --git a/lectures/multi_agent_models/aiyagari.md b/lectures/multi_agent_models/aiyagari.md index 11ae13bb..7cfd8054 100644 --- a/lectures/multi_agent_models/aiyagari.md +++ b/lectures/multi_agent_models/aiyagari.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (aiyagari)= diff --git a/lectures/multi_agent_models/arellano.md b/lectures/multi_agent_models/arellano.md index 8b0fb7cb..28dd86bc 100644 --- a/lectures/multi_agent_models/arellano.md +++ b/lectures/multi_agent_models/arellano.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (arellano)= diff --git a/lectures/multi_agent_models/harrison_kreps.md b/lectures/multi_agent_models/harrison_kreps.md index 156ac748..70e35213 100644 --- a/lectures/multi_agent_models/harrison_kreps.md +++ b/lectures/multi_agent_models/harrison_kreps.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (harrison_kreps)= diff --git a/lectures/multi_agent_models/lake_model.md b/lectures/multi_agent_models/lake_model.md index 1e87f825..b0e43fdd 100644 --- a/lectures/multi_agent_models/lake_model.md +++ b/lectures/multi_agent_models/lake_model.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (lake_model)= diff --git a/lectures/multi_agent_models/lucas_model.md b/lectures/multi_agent_models/lucas_model.md index b5239a57..ac282a27 100644 --- a/lectures/multi_agent_models/lucas_model.md +++ b/lectures/multi_agent_models/lucas_model.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (lucas_asset)= diff --git a/lectures/multi_agent_models/markov_asset.md b/lectures/multi_agent_models/markov_asset.md index 27bc9878..68723095 100644 --- a/lectures/multi_agent_models/markov_asset.md +++ b/lectures/multi_agent_models/markov_asset.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (mass)= diff --git a/lectures/multi_agent_models/markov_perf.md b/lectures/multi_agent_models/markov_perf.md index a7b61d10..e70da347 100644 --- a/lectures/multi_agent_models/markov_perf.md +++ b/lectures/multi_agent_models/markov_perf.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (markov_perf)= diff --git a/lectures/multi_agent_models/matsuyama.md b/lectures/multi_agent_models/matsuyama.md index 3153335a..b0ac9108 100644 --- a/lectures/multi_agent_models/matsuyama.md +++ b/lectures/multi_agent_models/matsuyama.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (matsuyama)= diff --git a/lectures/multi_agent_models/rational_expectations.md b/lectures/multi_agent_models/rational_expectations.md index 4c3d9fe1..9a752c52 100644 --- a/lectures/multi_agent_models/rational_expectations.md +++ b/lectures/multi_agent_models/rational_expectations.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (ree)= diff --git a/lectures/multi_agent_models/schelling.md b/lectures/multi_agent_models/schelling.md index 868aed51..3ef8929a 100644 --- a/lectures/multi_agent_models/schelling.md +++ b/lectures/multi_agent_models/schelling.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (schelling)= diff --git a/lectures/multi_agent_models/uncertainty_traps.md b/lectures/multi_agent_models/uncertainty_traps.md index a637b118..dbfc2343 100644 --- a/lectures/multi_agent_models/uncertainty_traps.md +++ b/lectures/multi_agent_models/uncertainty_traps.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (uncertainty_traps)= diff --git a/lectures/software_engineering/need_for_speed.md b/lectures/software_engineering/need_for_speed.md index 22ff0864..b54b0112 100644 --- a/lectures/software_engineering/need_for_speed.md +++ b/lectures/software_engineering/need_for_speed.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (types_methods)= diff --git a/lectures/software_engineering/testing.md b/lectures/software_engineering/testing.md index 955cf081..3d3824b4 100644 --- a/lectures/software_engineering/testing.md +++ b/lectures/software_engineering/testing.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (testing)= diff --git a/lectures/software_engineering/tools_editors.md b/lectures/software_engineering/tools_editors.md index 7291bb65..07e62c1c 100644 --- a/lectures/software_engineering/tools_editors.md +++ b/lectures/software_engineering/tools_editors.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (tools_editors)= diff --git a/lectures/software_engineering/version_control.md b/lectures/software_engineering/version_control.md index 270ee489..2dfc8788 100644 --- a/lectures/software_engineering/version_control.md +++ b/lectures/software_engineering/version_control.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (version_control)= diff --git a/lectures/status.md b/lectures/status.md index f1780a67..d87f405c 100644 --- a/lectures/status.md +++ b/lectures/status.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- # Execution Statistics diff --git a/lectures/time_series_models/additive_functionals.md b/lectures/time_series_models/additive_functionals.md index 5d4bde7c..fc836e92 100644 --- a/lectures/time_series_models/additive_functionals.md +++ b/lectures/time_series_models/additive_functionals.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (additive_functionals)= diff --git a/lectures/time_series_models/arma.md b/lectures/time_series_models/arma.md index 2edcefb7..35498a51 100644 --- a/lectures/time_series_models/arma.md +++ b/lectures/time_series_models/arma.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (arma)= diff --git a/lectures/time_series_models/classical_filtering.md b/lectures/time_series_models/classical_filtering.md index 1666ab21..87df5026 100644 --- a/lectures/time_series_models/classical_filtering.md +++ b/lectures/time_series_models/classical_filtering.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (classical_filtering)= diff --git a/lectures/time_series_models/estspec.md b/lectures/time_series_models/estspec.md index 83d5cd78..9f468e9f 100644 --- a/lectures/time_series_models/estspec.md +++ b/lectures/time_series_models/estspec.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (estspec)= diff --git a/lectures/time_series_models/lu_tricks.md b/lectures/time_series_models/lu_tricks.md index 24856a5b..c517f5eb 100644 --- a/lectures/time_series_models/lu_tricks.md +++ b/lectures/time_series_models/lu_tricks.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (lu_tricks)= diff --git a/lectures/time_series_models/multiplicative_functionals.md b/lectures/time_series_models/multiplicative_functionals.md index 575c421e..6f114691 100644 --- a/lectures/time_series_models/multiplicative_functionals.md +++ b/lectures/time_series_models/multiplicative_functionals.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (multiplicative_functionals)= diff --git a/lectures/tools_and_techniques/geom_series.md b/lectures/tools_and_techniques/geom_series.md index 362026c5..814be925 100644 --- a/lectures/tools_and_techniques/geom_series.md +++ b/lectures/tools_and_techniques/geom_series.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (mc)= diff --git a/lectures/tools_and_techniques/iterative_methods_sparsity.md b/lectures/tools_and_techniques/iterative_methods_sparsity.md index 48fe8f1d..58d5dcd8 100644 --- a/lectures/tools_and_techniques/iterative_methods_sparsity.md +++ b/lectures/tools_and_techniques/iterative_methods_sparsity.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (iterative_methods_sparsity)= @@ -1299,35 +1299,4 @@ function stationary_psi(p) end p = default_params(; N = 10, M = 5) @btime stationary_psi($p); -``` - -As a final demonstration, consider calculating the full evolution of the $psi(t)$ Markov chain. For the constant -$Q'$ matrix, the solution to this system of equations is $\psi(t) = \exp(Q') \psi(0)$ - -Matrix-free Krylov methods using a technique called [exponential integration](https://en.wikipedia.org/wiki/Exponential_integrator) can solve this for high-dimensional problems. - -For this, we can set up a `MatrixFreeOperator` for our `Q_T_mul!` function (equivalent to the `LinearMap`, but with some additional requirements for the ODE solver) and use the [LinearExponential](http://docs.juliadiffeq.org/latest/solvers/ode_solve.html#Exponential-Methods-for-Linear-and-Affine-Problems-1) time-stepping method. - -```{code-cell} julia -using OrdinaryDiffEq, DiffEqOperators - -function solve_transition_dynamics(p, t) - (; N, M) = p - - psi_0 = [1.0; fill(0.0, N^M - 1)] - O! = MatrixFreeOperator((dpsi, psi, p, t) -> Q_T_mul!(dpsi, psi, p), (p, 0.0), - size = (N^M, N^M), opnorm = (p) -> 1.25) - - # define the corresponding ODE problem - prob = ODEProblem(O!, psi_0, (0.0, t[end]), p) - return solve(prob, LinearExponential(krylov = :simple), tstops = t) -end -t = 0.0:5.0:100.0 -p = default_params(; N = 10, M = 6) -sol = solve_transition_dynamics(p, t) -v = solve_bellman(p) -plot(t, [dot(sol(tval), v) for tval in t], xlabel = L"t", label = L"E_t(v)") -``` - -The above plot (1) calculates the full dynamics of the Markov chain from the $n_m = 1$ for all $m$ initial condition; (2) solves the dynamics of a system of a million ODEs; and (3) uses the calculation of the Bellman equation to find the expected valuation during that transition. The entire process takes less than 30 seconds. - +``` \ No newline at end of file diff --git a/lectures/tools_and_techniques/linear_algebra.md b/lectures/tools_and_techniques/linear_algebra.md index 10f9689e..ddc3eb14 100644 --- a/lectures/tools_and_techniques/linear_algebra.md +++ b/lectures/tools_and_techniques/linear_algebra.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (linear_algebra)= diff --git a/lectures/tools_and_techniques/lln_clt.md b/lectures/tools_and_techniques/lln_clt.md index 63a17b22..22c09344 100644 --- a/lectures/tools_and_techniques/lln_clt.md +++ b/lectures/tools_and_techniques/lln_clt.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (lln_clt)= diff --git a/lectures/tools_and_techniques/numerical_linear_algebra.md b/lectures/tools_and_techniques/numerical_linear_algebra.md index 19d93766..f4cda6f9 100644 --- a/lectures/tools_and_techniques/numerical_linear_algebra.md +++ b/lectures/tools_and_techniques/numerical_linear_algebra.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (numerical_linear_algebra)= @@ -494,7 +494,7 @@ Af = qr(A) Q = Af.Q R = [Af.R; zeros(N - M, M)] # Stack with zeros @show Q * R ≈ A -x = R \ Q' * b # simplified QR solution for least squares +x = R \ Matrix(Q)' * b # simplified QR solution for least squares ``` This stacks the `R` with zeros, but the more specialized algorithm would not multiply directly diff --git a/lectures/tools_and_techniques/orth_proj.md b/lectures/tools_and_techniques/orth_proj.md index 92d5e7b5..fb730798 100644 --- a/lectures/tools_and_techniques/orth_proj.md +++ b/lectures/tools_and_techniques/orth_proj.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (orth_proj)= diff --git a/lectures/tools_and_techniques/stationary_densities.md b/lectures/tools_and_techniques/stationary_densities.md index ffc3292e..4d903c2b 100644 --- a/lectures/tools_and_techniques/stationary_densities.md +++ b/lectures/tools_and_techniques/stationary_densities.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (statd)= diff --git a/lectures/troubleshooting.md b/lectures/troubleshooting.md index 94277480..febb508b 100644 --- a/lectures/troubleshooting.md +++ b/lectures/troubleshooting.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (troubleshooting)= diff --git a/lectures/zreferences.md b/lectures/zreferences.md index 54a244a3..3b982ed8 100644 --- a/lectures/zreferences.md +++ b/lectures/zreferences.md @@ -6,7 +6,7 @@ jupytext: kernelspec: display_name: Julia language: julia - name: julia-1.9 + name: julia-1.10 --- (references)= From 6d3b0934e5cdd41cd63ebc9b7a8042c7464eba69 Mon Sep 17 00:00:00 2001 From: Annabella Stoll-Dansereau <38112312+annabellasd@users.noreply.github.com> Date: Thu, 4 Jan 2024 00:01:20 -0800 Subject: [PATCH 15/26] Multi agent models update (#276) * Updated formatting and code changes for the multi_agent models * Julia 1.10 support --------- Co-authored-by: Jesse Perla --- .JuliaFormatter.toml | 2 +- README.md | 4 + lectures/Manifest.toml | 40 +- lectures/continuous_time/covid_sde.md | 1 - lectures/continuous_time/seir_model.md | 1 - lectures/multi_agent_models/aiyagari.md | 142 +++-- lectures/multi_agent_models/arellano.md | 132 ++--- lectures/multi_agent_models/harrison_kreps.md | 46 +- lectures/multi_agent_models/lake_model.md | 507 +++++++++--------- lectures/multi_agent_models/lucas_model.md | 97 ++-- lectures/multi_agent_models/markov_asset.md | 286 ++++------ lectures/multi_agent_models/markov_perf.md | 169 +++--- lectures/multi_agent_models/matsuyama.md | 142 ++--- .../rational_expectations.md | 77 +-- lectures/multi_agent_models/schelling.md | 10 +- .../multi_agent_models/uncertainty_traps.md | 106 ++-- .../numerical_linear_algebra.md | 11 +- 17 files changed, 860 insertions(+), 913 deletions(-) diff --git a/.JuliaFormatter.toml b/.JuliaFormatter.toml index 309ba66c..6a50b834 100644 --- a/.JuliaFormatter.toml +++ b/.JuliaFormatter.toml @@ -1,4 +1,4 @@ style = "sciml" -margin = 84 +margin = 80 yas_style_nesting = true annotate_untyped_fields_with_any = false \ No newline at end of file diff --git a/README.md b/README.md index bf018b82..13c53b4b 100644 --- a/README.md +++ b/README.md @@ -58,10 +58,14 @@ julia format_myst.jl lectures/getting_started_julia/getting_started.md ``` As a helper, you can call a shell script to do it for an entire folder + ```bash bash format_all_directory.sh lectures/dynamic_programming ``` + or to also do the unicode substitutions + +```bash bash format_all_directory.sh lectures/dynamic_programming true ``` diff --git a/lectures/Manifest.toml b/lectures/Manifest.toml index 5202eeb7..40cf09b2 100644 --- a/lectures/Manifest.toml +++ b/lectures/Manifest.toml @@ -417,9 +417,9 @@ version = "1.9.1" [[deps.DiffEqBase]] deps = ["ArrayInterface", "DataStructures", "DocStringExtensions", "EnumX", "EnzymeCore", "FastBroadcast", "ForwardDiff", "FunctionWrappers", "FunctionWrappersWrappers", "LinearAlgebra", "Logging", "Markdown", "MuladdMacro", "Parameters", "PreallocationTools", "PrecompileTools", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Static", "StaticArraysCore", "Statistics", "Tricks", "TruncatedStacktraces"] -git-tree-sha1 = "53159da9fef2dd92815499e18f93b699ed54f397" +git-tree-sha1 = "044648af911974c3928058c1f8c83f159dece274" uuid = "2b5f629d-d688-5b77-993f-72d75c75574e" -version = "6.145.5" +version = "6.145.6" [deps.DiffEqBase.extensions] DiffEqBaseChainRulesCoreExt = "ChainRulesCore" @@ -624,9 +624,9 @@ version = "2.0.0" [[deps.FileIO]] deps = ["Pkg", "Requires", "UUIDs"] -git-tree-sha1 = "299dc33549f68299137e51e6d49a13b5b1da9673" +git-tree-sha1 = "c5c28c245101bd59154f649e19b038d15901b5dc" uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" -version = "1.16.1" +version = "1.16.2" [[deps.FilePathsBase]] deps = ["Compat", "Dates", "Mmap", "Printf", "Test", "UUIDs"] @@ -1265,9 +1265,9 @@ version = "1.0.3" [[deps.LoopVectorization]] deps = ["ArrayInterface", "CPUSummary", "CloseOpenIntervals", "DocStringExtensions", "HostCPUFeatures", "IfElse", "LayoutPointers", "LinearAlgebra", "OffsetArrays", "PolyesterWeave", "PrecompileTools", "SIMDTypes", "SLEEFPirates", "Static", "StaticArrayInterface", "ThreadingUtilities", "UnPack", "VectorizationBase"] -git-tree-sha1 = "0f5648fbae0d015e3abe5867bca2b362f67a5894" +git-tree-sha1 = "fc712dd664097440f19a91a704299cca02134ca0" uuid = "bdcacae8-1622-11e9-2a5c-532679323890" -version = "0.12.166" +version = "0.12.168" weakdeps = ["ChainRulesCore", "ForwardDiff", "SpecialFunctions"] [deps.LoopVectorization.extensions] @@ -1313,12 +1313,6 @@ git-tree-sha1 = "d2a140e551c9ec9028483e3c7d1244f417567ac0" uuid = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" version = "1.24.0" -[[deps.MathProgBase]] -deps = ["LinearAlgebra", "SparseArrays"] -git-tree-sha1 = "9abbe463a1e9fc507f12a69e7f29346c2cdc472c" -uuid = "fdba3010-5040-5b88-9595-932c9decdf73" -version = "0.7.8" - [[deps.MatrixFactorizations]] deps = ["ArrayLayouts", "LinearAlgebra", "Printf", "Random"] git-tree-sha1 = "78f6e33434939b0ac9ba1df81e6d005ee85a7396" @@ -1396,10 +1390,14 @@ uuid = "d41bc354-129a-5804-8e4c-c37616107c6c" version = "7.8.3" [[deps.NLopt]] -deps = ["MathOptInterface", "MathProgBase", "NLopt_jll"] -git-tree-sha1 = "5a7e32c569200a8a03c3d55d286254b0321cd262" +deps = ["NLopt_jll"] +git-tree-sha1 = "19d2a1c8a3c5b5a459f54a10e54de630c4a05701" uuid = "76087f3c-5699-56af-9a33-bf431cd00edd" -version = "0.6.5" +version = "1.0.0" +weakdeps = ["MathOptInterface"] + + [deps.NLopt.extensions] + NLoptMathOptInterfaceExt = ["MathOptInterface"] [[deps.NLopt_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] @@ -1663,9 +1661,9 @@ version = "0.2.4" [[deps.PreallocationTools]] deps = ["Adapt", "ArrayInterface", "ForwardDiff"] -git-tree-sha1 = "13078a8afc9f88ede295c17c3c673eb52c05b0b4" +git-tree-sha1 = "64bb68f76f789f5fe5930a80af310f19cdafeaed" uuid = "d236fae5-4411-538c-8e31-a6e3d9e00b46" -version = "0.4.16" +version = "0.4.17" [deps.PreallocationTools.extensions] PreallocationToolsReverseDiffExt = "ReverseDiff" @@ -1731,9 +1729,9 @@ version = "2.9.1" [[deps.QuantEcon]] deps = ["DSP", "DataStructures", "Distributions", "FFTW", "Graphs", "LinearAlgebra", "Markdown", "NLopt", "Optim", "Pkg", "Primes", "Random", "SparseArrays", "SpecialFunctions", "Statistics", "StatsBase", "Test"] -git-tree-sha1 = "4f989614763519b089f4127063c1795d7a412753" +git-tree-sha1 = "034293b29fdbcae73aeb7ca0b2755e693f04701b" uuid = "fcd29c91-0bd7-5a09-975d-7ac3f643a60c" -version = "0.16.5" +version = "0.16.6" [[deps.Query]] deps = ["DataValues", "IterableTables", "MacroTools", "QueryOperators", "Statistics"] @@ -2095,9 +2093,9 @@ weakdeps = ["OffsetArrays", "StaticArrays"] [[deps.StaticArrays]] deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"] -git-tree-sha1 = "42d5373c10272d14ef49cc68ffc22df3b93c549a" +git-tree-sha1 = "4e17a790909b17f7bf1496e3aec138cf01b60b3b" uuid = "90137ffa-7385-5640-81b9-e52037218182" -version = "1.8.2" +version = "1.9.0" weakdeps = ["ChainRulesCore", "Statistics"] [deps.StaticArrays.extensions] diff --git a/lectures/continuous_time/covid_sde.md b/lectures/continuous_time/covid_sde.md index fae1e19b..9ba314db 100644 --- a/lectures/continuous_time/covid_sde.md +++ b/lectures/continuous_time/covid_sde.md @@ -605,4 +605,3 @@ In this case, there are significant differences between the early and late death This bleak simulation has assumed that no individuals has long-term immunity and that there will be no medical advancements on that time horizon - both of which are unlikely to be true. Nevertheless, it suggests that the timing of lifting lockdown has a more profound impact after 18 months if we allow stochastic shocks imperfect immunity. - diff --git a/lectures/continuous_time/seir_model.md b/lectures/continuous_time/seir_model.md index 5cc01c4c..c0a36aa9 100644 --- a/lectures/continuous_time/seir_model.md +++ b/lectures/continuous_time/seir_model.md @@ -517,4 +517,3 @@ Despite its richness, the model above is fully deterministic. The policy $\bar{ One way that randomness can lead to aggregate fluctuations is the granularity that comes through the discreteness of individuals. This topic, the connection between SDEs and the Langevin equations typically used in the approximation of chemical reactions in well-mixed media is explored in further lectures on continuous time Markov chains. Instead, in the {doc}`next lecture `, we will concentrate on randomness that comes from aggregate changes in behavior or policy. - diff --git a/lectures/multi_agent_models/aiyagari.md b/lectures/multi_agent_models/aiyagari.md index 7cfd8054..0253cfaa 100644 --- a/lectures/multi_agent_models/aiyagari.md +++ b/lectures/multi_agent_models/aiyagari.md @@ -195,6 +195,7 @@ The object also includes a default set of parameters that we'll adopt unless oth ```{code-cell} julia using LinearAlgebra, Statistics +using LaTeXStrings, Plots, QuantEcon ``` ```{code-cell} julia @@ -205,30 +206,27 @@ using Test, Random ``` ```{code-cell} julia -using LaTeXStrings, Parameters, Plots, QuantEcon - -``` - -```{code-cell} julia -Household = @with_kw (r = 0.01, - w = 1.0, - σ = 1.0, - β = 0.96, - z_chain = MarkovChain([0.9 0.1; 0.1 0.9], [0.1; 1.0]), - a_min = 1e-10, - a_max = 18.0, - a_size = 200, - a_vals = range(a_min, a_max, length = a_size), - z_size = length(z_chain.state_values), - n = a_size * z_size, - s_vals = gridmake(a_vals, z_chain.state_values), - s_i_vals = gridmake(1:a_size, 1:z_size), - u = σ == 1 ? x -> log(x) : x -> (x^(1 - σ) - 1) / (1 - σ), - R = setup_R!(fill(-Inf, n, a_size), a_vals, s_vals, r, w, u), - # -Inf is the utility of dying (0 consumption) - Q = setup_Q!(zeros(n, a_size, n), s_i_vals, z_chain)) - -function setup_Q!(Q, s_i_vals, z_chain) +function Household(; r = 0.01, + w = 1.0, + sigma = 1.0, + beta = 0.96, + z_chain = MarkovChain([0.9 0.1; 0.1 0.9], [0.1; 1.0]), + a_min = 1e-10, + a_max = 18.0, + a_size = 200, + a_vals = range(a_min, a_max, length = a_size), + # -Inf is the utility of dying (0 consumption) + u = sigma == 1 ? x -> log(x) : + x -> (x^(1 - sigma) - 1) / (1 - sigma)) + + # Create grids + z_size = length(z_chain.state_values) + n = a_size * z_size + s_vals = gridmake(a_vals, z_chain.state_values) + s_i_vals = gridmake(1:a_size, 1:z_size) + + # Fill in the Q and R + Q = zeros(n, a_size, n) for next_s_i in 1:size(Q, 3) for a_i in 1:size(Q, 2) for s_i in 1:size(Q, 1) @@ -241,10 +239,8 @@ function setup_Q!(Q, s_i_vals, z_chain) end end end - return Q -end -function setup_R!(R, a_vals, s_vals, r, w, u) + R = fill(-Inf, n, a_size) for new_a_i in 1:size(R, 2) a_new = a_vals[new_a_i] for s_i in 1:size(R, 1) @@ -256,7 +252,8 @@ function setup_R!(R, a_vals, s_vals, r, w, u) end end end - return R + return (; r, w, sigma, beta, z_chain, a_min, a_max, a_size, a_vals, z_size, + n, s_vals, s_i_vals, u, R, Q) end ``` @@ -271,16 +268,16 @@ Random.seed!(42); ```{code-cell} julia # Create an instance of Household -am = Household(a_max = 20.0, r = 0.03, w = 0.956) +am = Household(; a_max = 20.0, r = 0.03, w = 0.956) # Use the instance to build a discrete dynamic program -am_ddp = DiscreteDP(am.R, am.Q, am.β) +am_ddp = DiscreteDP(am.R, am.Q, am.beta) # Solve using policy function iteration results = solve(am_ddp, PFI) # Simplify names -(;z_size, a_size, n, a_vals) = am +(; z_size, a_size, n, a_vals) = am z_vals = am.z_chain.state_values # Get all optimal actions across the set of @@ -298,10 +295,10 @@ plot!(xlabel = "current assets", ylabel = "next period assets", grid = false) tags: [remove-cell] --- @testset begin - #test a_vals[4] ≈ 0.3015075377869347 - #test a_star[4] ≈ 0.2010050252246231 - #test results.v[4] ≈ -27.48291672016239 - #test z_vals ≈ [0.1, 1.0] + @test a_vals[4] ≈ 0.3015075377869347 + @test a_star[4] ≈ 0.2010050252246231 + @test results.v[4] ≈ -27.48291672016239 + @test z_vals ≈ [0.1, 1.0] end ``` @@ -323,29 +320,16 @@ Random.seed!(42); ``` ```{code-cell} julia -# Firms' parameters -const A = 1 -const N = 1 -const α = 0.33 -const β = 0.96 -const δ = 0.05 - -function r_to_w(r) - return A * (1 - α) * (A * α / (r + δ)) ^ (α / (1 - α)) -end -function rd(K) - return A * α * (N / K) ^ (1 - α) - δ -end - -function prices_to_capital_stock(am, r) +# Calculate supply of capital for a given r +function prices_to_capital_stock(r; beta, A, N, alpha, delta, a_max) + # Create an instance of Household given the parameters - # Set up problem - w = r_to_w(r) - (;a_vals, s_vals, u) = am - setup_R!(am.R, a_vals, s_vals, r, w, u) + # Calculate the equilibrium wages + w = A * (1 - alpha) * (A * alpha / (r + delta))^(alpha / (1 - alpha)) + am = Household(; beta, a_max, w, r) - aiyagari_ddp = DiscreteDP(am.R, am.Q, am.β) + aiyagari_ddp = DiscreteDP(am.R, am.Q, am.beta) # Compute the optimal policy results = solve(aiyagari_ddp, PFI) @@ -354,33 +338,39 @@ function prices_to_capital_stock(am, r) stationary_probs = stationary_distributions(results.mc)[:, 1][1] # Return K - return dot(am.s_vals[:, 1], stationary_probs) + K = dot(am.s_vals[:, 1], stationary_probs) + + # Return capital + return K end -# Create an instance of Household -am = Household(β = β, a_max = 20.0) +# Inverse Demand for capital +function r_inverse_demand(K; A, N, alpha, delta) + return A * alpha * (N / K)^(1 - alpha) - delta +end # Create a grid of r values at which to compute demand and supply of capital r_vals = range(0.005, 0.04, length = 20) -# Compute supply of capital -k_vals = prices_to_capital_stock.(Ref(am), r_vals) +# Firms' parameters +A = 1 +N = 1 +alpha = 0.33 +beta = 0.96 +delta = 0.05 +a_max = 20.0 -# Plot against demand for capital by firms -demand = rd.(k_vals) -labels = ["demand for capital" "supply of capital"] -plot(k_vals, [demand r_vals], label = labels, lw = 2, alpha = 0.6) -plot!(xlabel = "capital", ylabel = "interest rate", xlim = (2, 14), ylim = (0.0, 0.1)) -``` +prices_to_capital_stock(r_vals[1]; A, N, alpha, beta, delta, a_max) -```{code-cell} julia ---- -tags: [remove-cell] ---- -@testset begin - #test k_vals[4] ≈ 3.920775511050653 - #test demand[4] ≈ 0.08211578674946372 - #test r_vals[4] ≈ 0.010526315789473684 -end -``` +# Compute supply of capital +k_vals = prices_to_capital_stock.(r_vals; A, N, alpha, beta, delta, a_max) + +r_inverse_demand_vals = r_inverse_demand.(k_vals; A, N, alpha, delta) +# Plot against demand for capital by firms +labels = ["demand for capital" "supply of capital"] +plot(k_vals, [r_inverse_demand_vals r_vals], label = labels, lw = 2, + alpha = 0.6) +plot!(xlabel = "capital", ylabel = "interest rate", xlim = (2, 14), + ylim = (0.0, 0.1)) +``` \ No newline at end of file diff --git a/lectures/multi_agent_models/arellano.md b/lectures/multi_agent_models/arellano.md index 28dd86bc..41805bcc 100644 --- a/lectures/multi_agent_models/arellano.md +++ b/lectures/multi_agent_models/arellano.md @@ -301,7 +301,7 @@ The code can be found below: tags: [hide-output] --- using LinearAlgebra, Statistics -using LaTeXStrings, Parameters, QuantEcon, DataFrames, Plots, Random +using LaTeXStrings, QuantEcon, DataFrames, Plots, Random ``` ```{code-cell} julia @@ -312,25 +312,25 @@ using Test ``` ```{code-cell} julia -function ArellanoEconomy(;β = .953, - γ = 2., - r = 0.017, - ρ = 0.945, - η = 0.025, - θ = 0.282, - ny = 21, - nB = 251) +function ArellanoEconomy(; beta = 0.953, + gamma = 2.0, + r = 0.017, + rho = 0.945, + eta = 0.025, + theta = 0.282, + ny = 21, + nB = 251) # create grids - Bgrid = collect(range(-.4, .4, length = nB)) - mc = tauchen(ny, ρ, η) - Π = mc.p + Bgrid = collect(range(-0.4, 0.4, length = nB)) + mc = tauchen(ny, rho, eta) + Pi = mc.p ygrid = exp.(mc.state_values) - ydefgrid = min.(.969 * mean(ygrid), ygrid) + ydefgrid = min.(0.969 * mean(ygrid), ygrid) # define value functions # notice ordered different than Python to take - # advantage of column major layout of Julia) + # advantage of column major layout of Julia vf = zeros(nB, ny) vd = zeros(1, ny) vc = zeros(nB, ny) @@ -338,13 +338,12 @@ function ArellanoEconomy(;β = .953, q = ones(nB, ny) .* (1 / (1 + r)) defprob = zeros(nB, ny) - return (β = β, γ = γ, r = r, ρ = ρ, η = η, θ = θ, ny = ny, - nB = nB, ygrid = ygrid, ydefgrid = ydefgrid, - Bgrid = Bgrid, Π = Π, vf = vf, vd = vd, vc = vc, - policy = policy, q = q, defprob = defprob) + return (; beta, gamma, r, rho, eta, theta, ny, + nB, ygrid, ydefgrid, Bgrid, Pi, vf, vd, vc, + policy, q, defprob) end -u(ae, c) = c^(1 - ae.γ) / (1 - ae.γ) +u(ae, c) = c^(1 - ae.gamma) / (1 - ae.gamma) function one_step_update!(ae, EV, @@ -352,16 +351,17 @@ function one_step_update!(ae, EVc) # unpack stuff - @unpack β, γ, r, ρ, η, θ, ny, nB = ae - @unpack ygrid, ydefgrid, Bgrid, Π, vf, vd, vc, policy, q, defprob = ae - zero_ind = searchsortedfirst(Bgrid, 0.) + (; beta, gamma, r, rho, eta, theta, ny, nB) = ae + (; ygrid, ydefgrid, Bgrid, Pi, vf, vd, vc, policy, q, defprob) = ae + zero_ind = searchsortedfirst(Bgrid, 0.0) for iy in 1:ny y = ae.ygrid[iy] ydef = ae.ydefgrid[iy] # value of being in default with income y - defval = u(ae, ydef) + β * (θ * EVc[zero_ind, iy] + (1-θ) * EVd[1, iy]) + defval = u(ae, ydef) + + beta * (theta * EVc[zero_ind, iy] + (1 - theta) * EVd[1, iy]) ae.vd[1, iy] = defval for ib in 1:nB @@ -369,15 +369,14 @@ function one_step_update!(ae, current_max = -1e14 pol_ind = 0 - for ib_next=1:nB - c = max(y - ae.q[ib_next, iy]*Bgrid[ib_next] + B, 1e-14) - m = u(ae, c) + β * EV[ib_next, iy] + for ib_next in 1:nB + c = max(y - ae.q[ib_next, iy] * Bgrid[ib_next] + B, 1e-14) + m = u(ae, c) + beta * EV[ib_next, iy] if m > current_max current_max = m pol_ind = ib_next end - end # update value and policy functions @@ -390,14 +389,14 @@ end function compute_prices!(ae) # unpack parameters - @unpack β, γ, r, ρ, η, θ, ny, nB = ae + (; beta, gamma, r, rho, eta, theta, ny, nB) = ae # create default values with a matching size vd_compat = repeat(ae.vd, nB) default_states = vd_compat .> ae.vc # update default probabilities and prices - copyto!(ae.defprob, default_states * ae.Π') + copyto!(ae.defprob, default_states * ae.Pi') copyto!(ae.q, (1 .- ae.defprob) / (1 + r)) return end @@ -405,13 +404,13 @@ end function vfi!(ae; tol = 1e-8, maxit = 10000) # unpack stuff - @unpack β, γ, r, ρ, η, θ, ny, nB = ae - @unpack ygrid, ydefgrid, Bgrid, Π, vf, vd, vc, policy, q, defprob = ae - Πt = Π' + (; beta, gamma, r, rho, eta, theta, ny, nB) = ae + (; ygrid, ydefgrid, Bgrid, Pi, vf, vd, vc, policy, q, defprob) = ae + Pit = Pi' # Iteration stuff it = 0 - dist = 10. + dist = 10.0 # allocate memory for update V_upd = similar(ae.vf) @@ -420,11 +419,11 @@ function vfi!(ae; tol = 1e-8, maxit = 10000) it += 1 # compute expectations for this iterations - # (we need Π' because of order value function dimensions) + # (we need Pi' because of order value function dimensions) copyto!(V_upd, ae.vf) - EV = ae.vf * Πt - EVd = ae.vd * Πt - EVc = ae.vc * Πt + EV = ae.vf * Pit + EVd = ae.vd * Pit + EVc = ae.vc * Pit # update value function one_step_update!(ae, EV, EVd, EVc) @@ -443,20 +442,19 @@ end function QuantEcon.simulate(ae, capT = 5000; y_init = mean(ae.ygrid), - B_init = mean(ae.Bgrid), - ) + B_init = mean(ae.Bgrid),) # get initial indices - zero_index = searchsortedfirst(ae.Bgrid, 0.) + zero_index = searchsortedfirst(ae.Bgrid, 0.0) y_init_ind = searchsortedfirst(ae.ygrid, y_init) B_init_ind = searchsortedfirst(ae.Bgrid, B_init) # create a QE MarkovChain - mc = MarkovChain(ae.Π) + mc = MarkovChain(ae.Pi) y_sim_indices = simulate(mc, capT + 1; init = y_init_ind) # allocate and fill output - y_sim_val = zeros(capT+1) + y_sim_val = zeros(capT + 1) B_sim_val, q_sim_val = similar(y_sim_val), similar(y_sim_val) B_sim_indices = fill(0, capT + 1) default_status = fill(false, capT + 1) @@ -478,7 +476,7 @@ function QuantEcon.simulate(ae, default_status[t + 1] = true y_sim_val[t] = ae.ydefgrid[y_sim_indices[t]] B_sim_indices[t + 1] = zero_index - B_sim_val[t+1] = 0. + B_sim_val[t + 1] = 0.0 q_sim_val[t] = ae.q[zero_index, y_sim_indices[t]] else default_status[t] = false @@ -488,15 +486,15 @@ function QuantEcon.simulate(ae, q_sim_val[t] = ae.q[B_sim_indices[t + 1], y_sim_indices[t]] end - # if you are in default + # if you are in default else B_sim_indices[t + 1] = zero_index - B_sim_val[t+1] = 0. + B_sim_val[t + 1] = 0.0 y_sim_val[t] = ae.ydefgrid[y_sim_indices[t]] q_sim_val[t] = ae.q[zero_index, y_sim_indices[t]] - # with probability θ exit default status - default_status[t + 1] = rand() ≥ ae.θ + # with probability theta exit default status + default_status[t + 1] = rand() >= ae.theta end end @@ -591,14 +589,14 @@ using DataFrames, Plots Compute the value function, policy and equilibrium prices ```{code-cell} julia -ae = ArellanoEconomy(β = .953, # time discount rate - γ = 2., # risk aversion - r = 0.017, # international interest rate - ρ = .945, # persistence in output - η = 0.025, # st dev of output shock - θ = 0.282, # prob of regaining access - ny = 21, # number of points in y grid - nB = 251) # number of points in B grid +ae = ArellanoEconomy(beta = 0.953, # time discount rate + gamma = 2.0, # risk aversion + r = 0.017, # international interest rate + rho = 0.945, # persistence in output + eta = 0.025, # st dev of output shock + theta = 0.282, # prob of regaining access + ny = 21, # number of points in y grid + nB = 251) # number of points in B grid # now solve the model on the grid. vfi!(ae) @@ -625,9 +623,9 @@ iy_high, iy_low = map(x -> searchsortedfirst(ae.ygrid, x), (high, low)) x = zeros(0) q_low = zeros(0) q_high = zeros(0) -for i in 1:ae.nB +for i in 1:(ae.nB) b = ae.Bgrid[i] - if -0.35 ≤ b ≤ 0 # to match fig 3 of Arellano + if -0.35 <= b <= 0 # to match fig 3 of Arellano push!(x, b) push!(q_low, ae.q[i, iy_low]) push!(q_high, ae.q[i, iy_high]) @@ -638,7 +636,8 @@ end plot(x, q_low, label = "Low") plot!(x, q_high, label = "High") plot!(title = L"Bond price schedule $q(y, B^\prime)$", - xlabel = L"B^\prime", ylabel = L"q", legend_title = L"y", legend = :topleft) + xlabel = L"B^\prime", ylabel = L"q", legend_title = L"y", + legend = :topleft) ``` ```{code-cell} julia @@ -658,17 +657,18 @@ Draw a plot of the value functions plot(ae.Bgrid, ae.vf[:, iy_low], label = "Low") plot!(ae.Bgrid, ae.vf[:, iy_high], label = "High") plot!(xlabel = L"B", ylabel = L"V(y,B)", title = "Value functions", - legend_title=L"y", legend = :topleft) + legend_title = L"y", legend = :topleft) ``` Draw a heat map for default probability ```{code-cell} julia -heatmap(ae.Bgrid[1:end-1], - ae.ygrid[2:end], - reshape(clamp.(vec(ae.defprob[1:end - 1, 1:end - 1]), 0, 1), 250, 20)') +heatmap(ae.Bgrid[1:(end - 1)], + ae.ygrid[2:end], + reshape(clamp.(vec(ae.defprob[1:(end - 1), 1:(end - 1)]), 0, 1), 250, + 20)') plot!(xlabel = L"B^\prime", ylabel = L"y", title = "Probability of default", - legend = :topleft) + legend = :topleft) ``` Plot a time series of major variables simulated from the model @@ -696,10 +696,12 @@ plots = plot(layout = (3, 1), size = (700, 800)) # Plot the three variables, and for each each variable shading the period(s) of default # in grey for i in 1:3 - plot!(plots[i], 1:T, y_vals[i], title = titles[i], xlabel = "time", label = "", lw = 2) + plot!(plots[i], 1:T, y_vals[i], title = titles[i], xlabel = "time", + label = "", lw = 2) for j in 1:length(def_start) plot!(plots[i], [def_start[j], def_end[j]], fill(maximum(y_vals[i]), 2), - fillrange = [extrema(y_vals[i])...], fcolor = :grey, falpha = 0.3, label = "") + fillrange = [extrema(y_vals[i])...], fcolor = :grey, falpha = 0.3, + label = "") end end diff --git a/lectures/multi_agent_models/harrison_kreps.md b/lectures/multi_agent_models/harrison_kreps.md index 70e35213..2517dfdf 100644 --- a/lectures/multi_agent_models/harrison_kreps.md +++ b/lectures/multi_agent_models/harrison_kreps.md @@ -290,12 +290,12 @@ Here's a function that can be used to compute these values using LinearAlgebra function price_single_beliefs(transition, dividend_payoff; - β=.75) + beta = 0.75) # First compute inverse piece - imbq_inv = inv(I - β * transition) + imbq_inv = inv(I - beta * transition) # Next compute prices - prices = β * ((imbq_inv * transition) * dividend_payoff) + prices = beta * ((imbq_inv * transition) * dividend_payoff) return prices end @@ -416,28 +416,28 @@ Here's code to solve for $\bar p$, $\hat p_a$ and $\hat p_b$ using the iterative ```{code-cell} julia function price_optimistic_beliefs(transitions, dividend_payoff; - β=.75, max_iter=50000, - tol=1e-16) + beta = 0.75, max_iter = 50000, + tol = 1e-16) # We will guess an initial price vector of [0, 0] - p_new = [0,0] - p_old = [10.0,10.0] + p_new = [0, 0] + p_old = [10.0, 10.0] # We know this is a contraction mapping, so we can iterate to conv - for i ∈ 1:max_iter + for i in 1:max_iter p_old = p_new temp = [maximum((q * p_old) + (q * dividend_payoff)) - for q in transitions] - p_new = β * temp + for q in transitions] + p_new = beta * temp # If we succed in converging, break out of for loop - if maximum(sqrt, ((p_new - p_old).^2)) < 1e-12 + if maximum(sqrt, ((p_new - p_old) .^ 2)) < 1e-12 break end end - temp=[minimum((q * p_old) + (q * dividend_payoff)) for q in transitions] - ptwiddle = β * temp + temp = [minimum((q * p_old) + (q * dividend_payoff)) for q in transitions] + ptwiddle = beta * temp phat_a = [p_new[1], ptwiddle[2]] phat_b = [ptwiddle[1], p_new[2]] @@ -484,22 +484,21 @@ Constraints on short sales prevent that. Here's code to solve for $\check p$ using iteration ```{code-cell} julia -function price_pessimistic_beliefs(transitions, - dividend_payoff; - β=.75, max_iter=50000, - tol=1e-16) +function price_pessimistic_beliefs(transitions, dividend_payoff; beta = 0.75, + max_iter = 50000, tol = 1e-16) # We will guess an initial price vector of [0, 0] p_new = [0, 0] p_old = [10.0, 10.0] # We know this is a contraction mapping, so we can iterate to conv - for i ∈ 1:max_iter + for i in 1:max_iter p_old = p_new - temp=[minimum((q * p_old) + (q* dividend_payoff)) for q in transitions] - p_new = β * temp + temp = [minimum((q * p_old) + (q * dividend_payoff)) + for q in transitions] + p_new = beta * temp # If we succed in converging, break out of for loop - if maximum(sqrt, ((p_new - p_old).^2)) < 1e-12 + if maximum(sqrt, ((p_new - p_old) .^ 2)) < 1e-12 break end end @@ -567,7 +566,8 @@ labels = ["p_a", "p_b", "p_optimistic", "p_pessimistic"] for (transition, label) in zip(transitions, labels) println(label) println(repeat("=", 20)) - s0, s1 = round.(price_single_beliefs(transition, dividendreturn), digits=2) + s0, s1 = round.(price_single_beliefs(transition, dividendreturn), + digits = 2) println("State 0: $s0") println("State 1: $s1") println(repeat("-", 20)) @@ -594,7 +594,7 @@ heterogeneous beliefs. opt_beliefs = price_optimistic_beliefs([qa, qb], dividendreturn) labels = ["p_optimistic", "p_hat_a", "p_hat_b"] -for (p, label) ∈ zip(opt_beliefs, labels) +for (p, label) in zip(opt_beliefs, labels) println(label) println(repeat("=", 20)) s0, s1 = round.(p, digits = 2) diff --git a/lectures/multi_agent_models/lake_model.md b/lectures/multi_agent_models/lake_model.md index b0e43fdd..c8aee14f 100644 --- a/lectures/multi_agent_models/lake_model.md +++ b/lectures/multi_agent_models/lake_model.md @@ -196,9 +196,8 @@ Here's the code: --- tags: [hide-output] --- -using LinearAlgebra, Statistics -using Distributions, Expectations, NLsolve, Parameters, Plots -using QuantEcon, Roots, Random +using LinearAlgebra, Statistics, Distributions +using NLsolve, Plots, QuantEcon, Roots, Random ``` ```{code-cell} julia @@ -208,49 +207,36 @@ tags: [remove-cell] using Test ``` -```{code-cell} julia - -``` +Reusable functions for simulating linear maps and finding their fixed points ```{code-cell} julia -LakeModel = @with_kw (λ = 0.283, α = 0.013, b = 0.0124, d = 0.00822) - -function transition_matrices(lm) - (;λ, α, b, d) = lm - g = b - d - A = [(1 - λ) * (1 - d) + b (1 - d) * α + b - (1 - d) * λ (1 - d) * (1 - α)] - Â = A ./ (1 + g) - return (A = A, Â = Â) +function simulate_linear(A, x_0, T) + X = zeros(length(x_0), T + 1) + X[:, 1] = x_0 + for t in 2:(T + 1) + X[:, t] = A * X[:, t - 1] + end + return X end -function rate_steady_state(lm) - (;Â) = transition_matrices(lm) - sol = fixedpoint(x -> Â * x, fill(0.5, 2)) - converged(sol) || error("Failed to converge in $(result.iterations) iterations") +function linear_steady_state(A, x_0 = ones(size(A, 1)) / size(A, 1)) + sol = fixedpoint(x -> A * x, x_0) + converged(sol) || error("Failed to converge in $(sol.iterations) iter") return sol.zero end +``` -function simulate_stock_path(lm, X0, T) - (;A) = transition_matrices(lm) - X_path = zeros(eltype(X0), 2, T) - X = copy(X0) - for t in 1:T - X_path[:, t] = X - X = A * X - end - return X_path -end +```{code-cell} julia +function LakeModel(; lambda = 0.283, alpha = 0.013, b = 0.0124, d = 0.00822) + # calculate transition matrices + g = b - d + A = [(1 - lambda) * (1 - d)+b (1 - d) * alpha+b + (1 - d)*lambda (1 - d)*(1 - alpha)] + A_hat = A ./ (1 + g) -function simulate_rate_path(lm, x0, T) - (;Â) = transition_matrices(lm) - x_path = zeros(eltype(x0), 2, T) - x = copy(x0) - for t in 1:T - x_path[:, t] = x - x = Â * x - end - return x_path + # Solve for fixed point to find the steady-state u and e + x_bar = linear_steady_state(A_hat) + return (; lambda, alpha, b, d, A, A_hat, x_bar) end ``` @@ -258,24 +244,22 @@ Let's observe these matrices for the baseline model ```{code-cell} julia lm = LakeModel() -A, Â = transition_matrices(lm) -A +lm.A ``` ```{code-cell} julia -Â +lm.A_hat ``` And a revised model ```{code-cell} julia -lm = LakeModel(α = 2.0) -A, Â = transition_matrices(lm) -A +lm = LakeModel(; alpha = 0.2) +lm.A ``` ```{code-cell} julia -Â +lm.A_hat ``` ```{code-cell} julia @@ -283,8 +267,8 @@ Â tags: [remove-cell] --- @testset begin - @test lm.α ≈ 2.0 - @test A[1][1] ≈ 0.7235062600000001 + @test lm.alpha ≈ 0.2 + @test lm.A[1][1] ≈ 0.7235062600000001 end ``` @@ -303,15 +287,18 @@ U_0 = u_0 * N_0 E_0 = e_0 * N_0 X_0 = [U_0; E_0] -X_path = simulate_stock_path(lm, X_0, T) +X_path = simulate_linear(lm.A, X_0, T - 1) x1 = X_path[1, :] x2 = X_path[2, :] -x3 = dropdims(sum(X_path, dims = 1), dims = 1) +x3 = sum(X_path, dims = 1)' -plt_unemp = plot(title = "Unemployment", 1:T, x1, color = :blue, lw = 2, grid = true, label = "") -plt_emp = plot(title = "Employment", 1:T, x2, color = :blue, lw = 2, grid = true, label = "") -plt_labor = plot(title = "Labor force", 1:T, x3, color = :blue, lw = 2, grid = true, label = "") +plt_unemp = plot(title = "Unemployment", 1:T, x1, color = :blue, lw = 2, + grid = true, label = "") +plt_emp = plot(title = "Employment", 1:T, x2, color = :blue, lw = 2, + grid = true, label = "") +plt_labor = plot(title = "Labor force", 1:T, x3, color = :blue, lw = 2, + grid = true, label = "") plot(plt_unemp, plt_emp, plt_labor, layout = (3, 1), size = (800, 600)) ``` @@ -343,8 +330,7 @@ This is the case for our default parameters: ```{code-cell} julia lm = LakeModel() -A, Â = transition_matrices(lm) -e, f = eigvals(Â) +e, f = eigvals(lm.A_hat) abs(e), abs(f) ``` @@ -362,21 +348,23 @@ Let's look at the convergence of the unemployment and employment rate to steady ```{code-cell} julia lm = LakeModel() -e_0 = 0.92 # initial employment rate -u_0 = 1 - e_0 # initial unemployment rate -T = 50 # simulation length +e_0 = 0.92 # initial employment rate +u_0 = 1 - e_0 # initial unemployment rate +T = 50 # simulation length -xbar = rate_steady_state(lm) +u_bar, e_bar = lm.x_bar x_0 = [u_0; e_0] -x_path = simulate_rate_path(lm, x_0, T) - -plt_unemp = plot(title ="Unemployment rate", 1:T, x_path[1, :],color = :blue, lw = 2, - alpha = 0.5, grid = true, label = "") -plot!(plt_unemp, [xbar[1]], color=:red, linetype = :hline, linestyle = :dash, lw = 2, label = "") -plt_emp = plot(title = "Employment rate", 1:T, x_path[2, :],color = :blue, lw = 2, alpha = 0.5, - grid = true, label = "") -plot!(plt_emp, [xbar[2]], color=:red, linetype = :hline, linestyle = :dash, lw = 2, label = "") -plot(plt_unemp, plt_emp, layout = (2, 1), size=(700,500)) +x_path = simulate_linear(lm.A_hat, x_0, T - 1) + +plt_unemp = plot(title = "Unemployment rate", 1:T, x_path[1, :], color = :blue, + lw = 2, alpha = 0.5, grid = true, label = "") +plot!(plt_unemp, [u_bar], color = :red, linetype = :hline, linestyle = :dash, + lw = 2, label = "") +plt_emp = plot(title = "Employment rate", 1:T, x_path[2, :], color = :blue, + lw = 2, alpha = 0.5, grid = true, label = "") +plot!(plt_emp, [e_bar], color = :red, linetype = :hline, linestyle = :dash, + lw = 2, label = "") +plot(plt_unemp, plt_emp, layout = (2, 1), size = (700, 500)) ``` ```{code-cell} julia @@ -480,35 +468,33 @@ MarkovChain type to investigate this. Let's plot the path of the sample averages over 5,000 periods ```{code-cell} julia -using QuantEcon, Roots, Random -``` - -```{code-cell} julia -lm = LakeModel(d = 0, b = 0) +lm = LakeModel(; d = 0, b = 0) T = 5000 # Simulation length -(;α, λ) = lm -P = [(1 - λ) λ - α (1 - α)] +(; alpha, lambda) = lm +P = [(1-lambda) lambda + alpha (1-alpha)] ``` ```{code-cell} julia Random.seed!(42) +u_bar, e_bar = lm.x_bar mc = MarkovChain(P, [0; 1]) # 0=unemployed, 1=employed -xbar = rate_steady_state(lm) - -s_path = simulate(mc, T; init=2) -s̄_e = cumsum(s_path) ./ (1:T) -s̄_u = 1 .- s̄_e -s_bars = [s̄_u s̄_e] -plt_unemp = plot(title = "Percent of time unemployed", 1:T, s_bars[:,1],color = :blue, lw = 2, - alpha = 0.5, label = "", grid = true) -plot!(plt_unemp, [xbar[1]], linetype = :hline, linestyle = :dash, color=:red, lw = 2, label = "") -plt_emp = plot(title = "Percent of time employed", 1:T, s_bars[:,2],color = :blue, lw = 2, - alpha = 0.5, label = "", grid = true) -plot!(plt_emp, [xbar[2]], linetype = :hline, linestyle = :dash, color=:red, lw = 2, label = "") -plot(plt_unemp, plt_emp, layout = (2, 1), size=(700,500)) +s_path = simulate(mc, T; init = 2) +s_bar_e = cumsum(s_path) ./ (1:T) +s_bar_u = 1 .- s_bar_e +s_bars = [s_bar_u s_bar_e] + +plt_unemp = plot(title = "Percent of time unemployed", 1:T, s_bars[:, 1], + color = :blue, lw = 2, alpha = 0.5, label = "", grid = true) +plot!(plt_unemp, [u_bar], linetype = :hline, linestyle = :dash, color = :red, + lw = 2, label = "") +plt_emp = plot(title = "Percent of time employed", 1:T, s_bars[:, 2], + color = :blue, lw = 2, alpha = 0.5, label = "", grid = true) +plot!(plt_emp, [e_bar], linetype = :hline, linestyle = :dash, color = :red, + lw = 2, label = "") +plot(plt_unemp, plt_emp, layout = (2, 1), size = (700, 500)) ``` ```{code-cell} julia @@ -516,8 +502,8 @@ plot(plt_unemp, plt_emp, layout = (2, 1), size=(700,500)) tags: [remove-cell] --- @testset begin - #test xbar[1] ≈ 0.04391891891891919 - #test s_bars[end,end] ≈ 0.957 + @test u_bar ≈ 0.04391891891891919 + @test s_bars[end,end] ≈ 0.9488 end ``` @@ -630,160 +616,190 @@ Following {cite}`davis2006flow`, we set $\alpha$, the hazard rate of leaving emp We will make use of (with some tweaks) the code we wrote in the {doc}`McCall model lecture <../dynamic_programming/mccall_model>`, embedded below for convenience. ```{code-cell} julia -function solve_mccall_model(mcm; U_iv = 1.0, V_iv = ones(length(mcm.w)), tol = 1e-5, +function solve_mccall_model(mcm; U_iv = 1.0, V_iv = ones(length(mcm.w)), + tol = 1e-5, iter = 2_000) - (;α, β, σ, c, γ, w, E, u) = mcm + (; alpha, beta, sigma, c, gamma, w, w_probs, u) = mcm - # necessary objects - u_w = u.(w, σ) - u_c = u(c, σ) + # pre-calculate utilities + u_w = u.(w, sigma) + u_c = u(c, sigma) # Bellman operator T. Fixed point is x* s.t. T(x*) = x* function T(x) - V = x[1:end-1] + V = x[1:(end - 1)] U = x[end] - [u_w + β * ((1 - α) * V .+ α * U); u_c + β * (1 - γ) * U + β * γ * E * max.(U, V)] + return [u_w + beta * ((1 - alpha) * V .+ alpha * U); + u_c + beta * (1 - gamma) * U + + beta * gamma * dot(w_probs, max.(U, V))] end # value function iteration x_iv = [V_iv; U_iv] # initial x val xstar = fixedpoint(T, x_iv, iterations = iter, xtol = tol, m = 0).zero - V = xstar[1:end-1] + V = xstar[1:(end - 1)] U = xstar[end] # compute the reservation wage w_barindex = searchsortedfirst(V .- U, 0.0) if w_barindex >= length(w) # if this is true, you never want to accept - w̄ = Inf + w_bar = Inf else - w̄ = w[w_barindex] # otherwise, return the number + w_bar = w[w_barindex] # otherwise, return the number end # return a NamedTuple, so we can select values by name - return (V = V, U = U, w̄ = w̄) + return (; V, U, w_bar) end ``` And the McCall object ```{code-cell} julia -# a default utility function -u(c, σ) = c > 0 ? (c^(1 - σ) - 1) / (1 - σ) : -10e-6 - -# model constructor -McCallModel = @with_kw (α = 0.2, - β = 0.98, # discount rate - γ = 0.7, - c = 6.0, # unemployment compensation - σ = 2.0, - u = u, # utility function - w = range(10, 20, length = 60), # wage values - E = Expectation(BetaBinomial(59, 600, 400))) # distribution over wage values +function McCallModel(; alpha, beta, gamma, c, sigma, w, w_probs, + u = (c, sigma) -> c > 0 ? + (c^(1 - sigma) - 1) / (1 - sigma) : + -10e-6) + return (; alpha, beta, gamma, c, sigma, u, w, w_probs) +end ``` Now let's compute and plot welfare, employment, unemployment, and tax revenue as a function of the unemployment compensation rate ```{code-cell} julia -# some global variables that will stay constant -α = 0.013 -α_q = (1 - (1 - α)^3) -b_param = 0.0124 -d_param = 0.00822 -β = 0.98 -γ = 1.0 -σ = 2.0 - -# the default wage distribution: a discretized log normal -log_wage_mean, wage_grid_size, max_wage = 20, 200, 170 -w_vec = range(1e-3, max_wage, length = wage_grid_size + 1) - -logw_dist = Normal(log(log_wage_mean), 1) -cdf_logw = cdf.(logw_dist, log.(w_vec)) -pdf_logw = cdf_logw[2:end] - cdf_logw[1:end-1] - -p_vec = pdf_logw ./ sum(pdf_logw) -w_vec = (w_vec[1:end-1] + w_vec[2:end]) / 2 - -E = expectation(Categorical(p_vec)) # expectation object - -function compute_optimal_quantities(c, τ) - mcm = McCallModel(α = α_q, - β = β, - γ = γ, - c = c - τ, # post-tax compensation - σ = σ, - w = w_vec .- τ, # post-tax wages - E = E) # expectation operator - - (;V, U, w̄) = solve_mccall_model(mcm) - indicator = wage -> wage > w̄ - λ = γ * E * indicator.(w_vec .- τ) - - return w̄, λ, V, U +function compute_optimal_quantities(c_pretax, tau; w_probs, sigma, gamma, beta, + alpha, w_pretax) + mcm = McCallModel(; alpha, beta, gamma, sigma, w_probs, + c = c_pretax - tau, # post-tax compensation + w = w_pretax .- tau) + + (; V, U, w_bar) = solve_mccall_model(mcm) + accept_wage = w_pretax .- tau .> w_bar + + # sum up proportion accepting the wages + lambda = gamma * dot(w_probs, accept_wage) + return w_bar, lambda, V, U end -function compute_steady_state_quantities(c, τ) - w̄, λ_param, V, U = compute_optimal_quantities(c, τ) +function compute_steady_state_quantities(c_pretax, tau; w_probs, sigma, gamma, + beta, alpha, w_pretax, b, d) + w_bar, lambda, V, U = compute_optimal_quantities(c_pretax, tau; w_probs, + sigma, + gamma, beta, alpha, + w_pretax) # compute steady state employment and unemployment rates - lm = LakeModel(λ = λ_param, α = α_q, b = b_param, d = d_param) - x = rate_steady_state(lm) - u_rate, e_rate = x + lm = LakeModel(; lambda, alpha, b, d) + u_rate, e_rate = lm.x_bar # compute steady state welfare - indicator(wage) = wage > w̄ - decisions = indicator.(w_vec .- τ) - w = (E * (V .* decisions)) / (E * decisions) + accept_wage = w_pretax .- tau .> w_bar + w = (dot(w_probs, V .* accept_wage)) / dot(w_probs, accept_wage) welfare = e_rate .* w + u_rate .* U return u_rate, e_rate, welfare end -function find_balanced_budget_tax(c) +function find_balanced_budget_tax(c_pretax; w_probs, sigma, gamma, beta, alpha, + w_pretax, b, d) function steady_state_budget(t) - u_rate, e_rate, w = compute_steady_state_quantities(c, t) - return t - u_rate * c + u_rate, e_rate, w = compute_steady_state_quantities(c_pretax, t; + w_probs, sigma, + gamma, beta, alpha, + w_pretax, b, d) + return t - u_rate * c_pretax end - τ = find_zero(steady_state_budget, (0.0, 0.9c)) - return τ + tau = find_zero(steady_state_budget, (0.0, 0.9 * c_pretax)) + return tau end +``` -# levels of unemployment insurance we wish to study -Nc = 60 -c_vec = range(5, 140, length = Nc) - -tax_vec = zeros(Nc) -unempl_vec = similar(tax_vec) -empl_vec = similar(tax_vec) -welfare_vec = similar(tax_vec) - -for i in 1:Nc - t = find_balanced_budget_tax(c_vec[i]) - u_rate, e_rate, welfare = compute_steady_state_quantities(c_vec[i], t) - tax_vec[i] = t - unempl_vec[i] = u_rate - empl_vec[i] = e_rate - welfare_vec[i] = welfare +Helper function to calculate for various unemployment insurance levels + +```{code-cell} julia +function calculate_equilibriums(c_pretax; w_probs, sigma, gamma, beta, alpha, + w_pretax, b, d) + tau_vec = similar(c_pretax) + u_vec = similar(c_pretax) + e_vec = similar(c_pretax) + welfare_vec = similar(c_pretax) + + for (i, c_pre) in enumerate(c_pretax) + tau = find_balanced_budget_tax(c_pre; w_probs, sigma, gamma, beta, + alpha, w_pretax, b, d) + u_rate, e_rate, welfare = compute_steady_state_quantities(c_pre, tau; + w_probs, + sigma, + gamma, beta, + alpha, + w_pretax, + b, d) + tau_vec[i] = tau + u_vec[i] = u_rate + e_vec[i] = e_rate + welfare_vec[i] = welfare + end + return tau_vec, u_vec, e_vec, welfare_vec end +``` -plt_unemp = plot(title = "Unemployment", c_vec, unempl_vec, color = :blue, lw = 2, alpha=0.7, - label = "",grid = true) -plt_tax = plot(title = "Tax", c_vec, tax_vec, color = :blue, lw = 2, alpha=0.7, label = "", - grid = true) -plt_emp = plot(title = "Employment", c_vec, empl_vec, color = :blue, lw = 2, alpha=0.7, label = "", - grid = true) -plt_welf = plot(title = "Welfare", c_vec, welfare_vec, color = :blue, lw = 2, alpha=0.7, label = "", - grid = true) +Parameters for our experiment + +```{code-cell} julia +alpha_base = 0.013 +alpha = (1 - (1 - alpha_base)^3) +b = 0.0124 +d = 0.00822 +beta = 0.98 +gamma = 1.0 +sigma = 2.0 + +# the default wage distribution: a discretized log normal +log_wage_mean, wage_grid_size, max_wage = 20, 200, 170 +w_pretax = range(1e-3, max_wage, length = wage_grid_size + 1) +logw_dist = Normal(log(log_wage_mean), 1) +cdf_logw = cdf.(logw_dist, log.(w_pretax)) +pdf_logw = cdf_logw[2:end] - cdf_logw[1:(end - 1)] +w_probs = pdf_logw ./ sum(pdf_logw) # probabilities +w_pretax = (w_pretax[1:(end - 1)] + w_pretax[2:end]) / 2 -plot(plt_unemp, plt_emp, plt_tax, plt_welf, layout = (2,2), size = (800, 700)) +# levels of unemployment insurance we wish to study +c_pretax = range(5, 140, length = 60) +tau_vec, u_vec, e_vec, welfare_vec = calculate_equilibriums(c_pretax; w_probs, + sigma, gamma, beta, + alpha, w_pretax, b, + d) + +# plots +plt_unemp = plot(title = "Unemployment", c_pretax, u_vec, color = :blue, + lw = 2, alpha = 0.7, label = "", grid = true) +plt_tax = plot(title = "Tax", c_pretax, tau_vec, color = :blue, lw = 2, + alpha = 0.7, label = "", grid = true) +plt_emp = plot(title = "Employment", c_pretax, e_vec, color = :blue, lw = 2, + alpha = 0.7, label = "", grid = true) +plt_welf = plot(title = "Welfare", c_pretax, welfare_vec, color = :blue, lw = 2, + alpha = 0.7, label = "", grid = true) + +plot(plt_unemp, plt_emp, plt_tax, plt_welf, layout = (2, 2), size = (800, 700)) ``` Welfare first increases and then decreases as unemployment benefits rise. The level that maximizes steady state welfare is approximately 62. +```{code-cell} julia +--- +tags: [remove-cell] +--- +@testset begin + @test tau_vec[2] ≈ 0.859664806251665 + @test u_vec[10] ≈ 0.22587607040020583 + @test e_vec[4] ≈ 0.8527180941230578 +end +``` + ## Exercises ### Exercise 1 @@ -830,7 +846,7 @@ steady state values to x0 ```{code-cell} julia lm = LakeModel() -x0 = rate_steady_state(lm) +x0 = lm.x_bar println("Initial Steady State: $x0") ``` @@ -844,14 +860,10 @@ T = 50 New legislation changes $\lambda$ to $0.2$ ```{code-cell} julia -lm = LakeModel(λ = 0.2) -``` - -```{code-cell} julia -xbar = rate_steady_state(lm) # new steady state -X_path = simulate_stock_path(lm, x0 * N0, T) -x_path = simulate_rate_path(lm, x0, T) -println("New Steady State: $xbar") +lm = LakeModel(; lambda = 0.2) +X_path = simulate_linear(lm.A, x0 * N0, T - 1) +x_path = simulate_linear(lm.A_hat, x0, T - 1) +println("New Steady State: $(lm.x_bar)") ``` Now plot stocks @@ -859,14 +871,14 @@ Now plot stocks ```{code-cell} julia x1 = X_path[1, :] x2 = X_path[2, :] -x3 = dropdims(sum(X_path, dims = 1), dims = 1) +x3 = sum(X_path, dims = 1)' -plt_unemp = plot(title = "Unemployment", 1:T, x1, color = :blue, grid = true, label = "", - bg_inside = :lightgrey) -plt_emp = plot(title = "Employment", 1:T, x2, color = :blue, grid = true, label = "", - bg_inside = :lightgrey) -plt_labor = plot(title = "Labor force", 1:T, x3, color = :blue, grid = true, label = "", - bg_inside = :lightgrey) +plt_unemp = plot(title = "Unemployment", 1:T, x1, color = :blue, grid = true, + label = "", bg_inside = :lightgrey) +plt_emp = plot(title = "Employment", 1:T, x2, color = :blue, grid = true, + label = "", bg_inside = :lightgrey) +plt_labor = plot(title = "Labor force", 1:T, x3, color = :blue, grid = true, + label = "", bg_inside = :lightgrey) plot(plt_unemp, plt_emp, plt_labor, layout = (3, 1), size = (800, 600)) ``` @@ -876,23 +888,23 @@ plot(plt_unemp, plt_emp, plt_labor, layout = (3, 1), size = (800, 600)) tags: [remove-cell] --- @testset begin - #test x1[1] ≈ 8.266626766923284 - #test x2[2] ≈ 91.43632870031433 - #test x3[3] ≈ 100.83774723999996 + @test x3[21] ≈ 108.70045145781441 + @test x2[12] ≈ 93.05432951806618 end ``` And how the rates evolve ```{code-cell} julia -plt_unemp = plot(title = "Unemployment rate", 1:T, x_path[1,:], color = :blue, grid = true, - label = "", bg_inside = :lightgrey) -plot!(plt_unemp, [xbar[1]], linetype = :hline, linestyle = :dash, color =:red, label = "") - -plt_emp = plot(title = "Employment rate", 1:T, x_path[2,:], color = :blue, grid = true, - label = "", bg_inside = :lightgrey) -plot!(plt_emp, [xbar[2]], linetype = :hline, linestyle = :dash, color =:red, label = "") +plt_unemp = plot(title = "Unemployment rate", 1:T, x_path[1, :], color = :blue, + grid = true, label = "", bg_inside = :lightgrey) +plot!(plt_unemp, [u_bar], linetype = :hline, linestyle = :dash, color = :red, + label = "") +plt_emp = plot(title = "Employment rate", 1:T, x_path[2, :], color = :blue, + grid = true, label = "", bg_inside = :lightgrey) +plot!(plt_emp, [e_bar], linetype = :hline, linestyle = :dash, color = :red, + label = "") plot(plt_unemp, plt_emp, layout = (2, 1), size = (800, 600)) ``` @@ -901,8 +913,8 @@ plot(plt_unemp, plt_emp, layout = (2, 1), size = (800, 600)) tags: [remove-cell] --- @testset begin - #test x_path[1,3] ≈ 0.09471014989625384 - #test x_path[2,7] ≈ 0.8936171021324064 + @test x_path[1,3] ≈ 0.09471014989625384 + @test x_path[2,7] ≈ 0.8936171021324064 end ``` @@ -921,7 +933,7 @@ state ```{code-cell} julia lm = LakeModel() -x0 = rate_steady_state(lm) +x0 = lm.x_bar ``` ```{code-cell} julia @@ -929,23 +941,23 @@ x0 = rate_steady_state(lm) tags: [remove-cell] --- @testset begin - #test x0[1] ≈ 0.08266626766923285 + @test x0[1] ≈ 0.08266626766923285 end ``` Here are the other parameters: ```{code-cell} julia -b̂ = 0.003 -T̂ = 20 +b_hat = 0.003 +T_hat = 20 ``` Let's increase $b$ to the new value and simulate for 20 periods ```{code-cell} julia -lm = LakeModel(b=b̂) -X_path1 = simulate_stock_path(lm, x0 * N0, T̂) # simulate stocks -x_path1 = simulate_rate_path(lm, x0, T̂) # simulate rates +lm = LakeModel(; b = b_hat) +X_path1 = simulate_linear(lm.A, x0 * N0, T_hat - 1) +x_path1 = simulate_linear(lm.A_hat, x0, T_hat - 1) ``` Now we reset $b$ to the original value and then, using the state @@ -953,9 +965,9 @@ after 20 periods for the new initial conditions, we simulate for the additional 30 periods ```{code-cell} julia -lm = LakeModel(b = 0.0124) -X_path2 = simulate_stock_path(lm, X_path1[:, end-1], T-T̂+1) # simulate stocks -x_path2 = simulate_rate_path(lm, x_path1[:, end-1], T-T̂+1) # simulate rates +lm = LakeModel(; b = 0.0124) +X_path2 = simulate_linear(lm.A, X_path1[:, end - 1], T - T_hat) +x_path2 = simulate_linear(lm.A_hat, x_path1[:, end - 1], T - T_hat) ``` Finally we combine these two paths and plot @@ -966,20 +978,20 @@ X_path = hcat(X_path1, X_path2[:, 2:end]) ``` ```{code-cell} julia -x1 = X_path[1,:] -x2 = X_path[2,:] -x3 = dropdims(sum(X_path, dims = 1), dims = 1) +x1 = X_path[1, :] +x2 = X_path[2, :] +x3 = sum(X_path, dims = 1)' -plt_unemp = plot(title = "Unemployment", 1:T, x1, color = :blue, lw = 2, alpha = 0.7, - grid = true, label = "", bg_inside = :lightgrey) +plt_unemp = plot(title = "Unemployment", 1:T, x1, color = :blue, lw = 2, + alpha = 0.7, grid = true, label = "", bg_inside = :lightgrey) plot!(plt_unemp, ylims = extrema(x1) .+ (-1, 1)) -plt_emp = plot(title = "Employment", 1:T, x2, color = :blue, lw = 2, alpha = 0.7, grid = true, - label = "", bg_inside = :lightgrey) +plt_emp = plot(title = "Employment", 1:T, x2, color = :blue, lw = 2, + alpha = 0.7, grid = true, label = "", bg_inside = :lightgrey) plot!(plt_emp, ylims = extrema(x2) .+ (-1, 1)) -plt_labor = plot(title = "Labor force", 1:T, x3, color = :blue, alpha = 0.7, grid = true, - label = "", bg_inside = :lightgrey) +plt_labor = plot(title = "Labor force", 1:T, x3, color = :blue, alpha = 0.7, + grid = true, label = "", bg_inside = :lightgrey) plot!(plt_labor, ylims = extrema(x3) .+ (-1, 1)) plot(plt_unemp, plt_emp, plt_labor, layout = (3, 1), size = (800, 600)) ``` @@ -989,23 +1001,24 @@ plot(plt_unemp, plt_emp, plt_labor, layout = (3, 1), size = (800, 600)) tags: [remove-cell] --- @testset begin - #test x1[1] ≈ 8.266626766923284 - #test x2[2] ≈ 92.11681873319097 - #test x3[3] ≈ 98.95872483999996 + @test x1[1] ≈ 8.266626766923284 + @test x2[2] ≈ 92.11681873319097 + @test x3[3] ≈ 98.95872483999996 end ``` And the rates ```{code-cell} julia -plt_unemp = plot(title = "Unemployment Rate", 1:T, x_path[1,:], color = :blue, grid = true, - label = "", bg_inside = :lightgrey, lw = 2) -plot!(plt_unemp, [x0[1]], linetype = :hline, linestyle = :dash, color =:red, label = "", lw = 2) - -plt_emp = plot(title = "Employment Rate", 1:T, x_path[2,:], color = :blue, grid = true, - label = "", bg_inside = :lightgrey, lw = 2) -plot!(plt_emp, [x0[2]], linetype = :hline, linestyle = :dash, color =:red, label = "", lw = 2) - +plt_unemp = plot(title = "Unemployment Rate", 1:T, x_path[1, :], color = :blue, + grid = true, label = "", bg_inside = :lightgrey, lw = 2) +plot!(plt_unemp, [x0[1]], linetype = :hline, linestyle = :dash, color = :red, + label = "", lw = 2) + +plt_emp = plot(title = "Employment Rate", 1:T, x_path[2, :], color = :blue, + grid = true, label = "", bg_inside = :lightgrey, lw = 2) +plot!(plt_emp, [x0[2]], linetype = :hline, linestyle = :dash, color = :red, + label = "", lw = 2) plot(plt_unemp, plt_emp, layout = (2, 1), size = (800, 600)) ``` @@ -1014,8 +1027,8 @@ plot(plt_unemp, plt_emp, layout = (2, 1), size = (800, 600)) tags: [remove-cell] --- @testset begin - #test x_path[1,3] ≈ 0.06791408368459205 - #test x_path[2,7] ≈ 0.9429334437639298 + @test x_path[1,3] ≈ 0.06791408368459205 + @test x_path[2,7] ≈ 0.9429334437639298 end ``` diff --git a/lectures/multi_agent_models/lucas_model.md b/lectures/multi_agent_models/lucas_model.md index ac282a27..50082321 100644 --- a/lectures/multi_agent_models/lucas_model.md +++ b/lectures/multi_agent_models/lucas_model.md @@ -386,69 +386,54 @@ using Test ``` ```{code-cell} julia -using LinearAlgebra, Statistics -using Distributions, Interpolations, LaTeXStrings, Parameters, Plots, Random +using LinearAlgebra, Statistics, Random +using Distributions, Interpolations, LaTeXStrings, Plots, NLsolve ``` ```{code-cell} julia -# model -function LucasTree(;γ = 2.0, - β = 0.95, - α = 0.9, - σ = 0.1, - grid_size = 100) - - ϕ = LogNormal(0.0, σ) - shocks = rand(ϕ, 500) +function LucasTree(; gamma = 2.0, + beta = 0.95, + alpha = 0.9, + sigma = 0.1, + grid_size = 100, + num_z = 500) + phi = LogNormal(0.0, sigma) + z = rand(phi, num_z) # build a grid with mass around stationary distribution - ssd = σ / sqrt(1 - α^2) - grid_min, grid_max = exp(-4ssd), exp(4ssd) + ssd = sigma / sqrt(1 - alpha^2) + grid_min = exp(-4 * ssd) + grid_max = exp(4 * ssd) grid = range(grid_min, grid_max, length = grid_size) - # set h(y) = β * int u'(G(y,z)) G(y,z) ϕ(dz) + # set h(y) = beta * int u'(G(y,z)) G(y,z) phi(dz) h = similar(grid) for (i, y) in enumerate(grid) - h[i] = β * mean((y^α .* shocks).^(1 - γ)) + h[i] = beta * mean((y^alpha .* z) .^ (1 - gamma)) end - return (γ = γ, β = β, α = α, σ = σ, ϕ = ϕ, grid = grid, shocks = shocks, h = h) -end - -# approximate Lucas operator, which returns the updated function Tf on the grid -function lucas_operator(lt, f) - - # unpack input - (;grid, α, β, h) = lt - z = lt.shocks - - Af = LinearInterpolation(grid, f, extrapolation_bc=Line()) - - Tf = [ h[i] + β * mean(Af.(grid[i]^α .* z)) for i in 1:length(grid) ] - return Tf + return (; gamma, beta, alpha, sigma, phi, grid, z, h) end # get equilibrium price for Lucas tree -function solve_lucas_model(lt; - tol = 1e-6, - max_iter = 500) - - (;grid, γ) = lt - - i = 0 - f = zero(grid) # Initial guess of f - error = tol + 1 - - while (error > tol) && (i < max_iter) - f_new = lucas_operator(lt, f) - error = maximum(abs, f_new - f) - f = f_new - i += 1 +function solve_lucas_model(lt; ftol = 1e-8, iterations = 500) + (; grid, gamma, alpha, beta, h, z) = lt + + # approximate Lucas operator, which returns the updated function Tf on the grid + function T(f) + Af = linear_interpolation(grid, f, extrapolation_bc = Line()) + # Using z for monte-carlo integration + Tf = [h[i] + beta * mean(Af.(grid[i]^alpha .* z)) + for i in 1:length(grid)] + return Tf end - # p(y) = f(y) * y ^ γ - price = f .* grid.^γ + sol = fixedpoint(T, zero(grid); ftol, iterations) + converged(sol) || error("Failed to converge in $(sol.iterations) iter") + f = sol.zero + + price = f .* grid .^ gamma # f(y)*y^gamma return price end @@ -459,7 +444,7 @@ An example of usage is given in the docstring and repeated here ```{code-cell} julia Random.seed!(42) # For reproducible results. -tree = LucasTree(γ = 2.0, β = 0.95, α = 0.90, σ = 0.1) +tree = LucasTree(; gamma = 2.0, beta = 0.95, alpha = 0.90, sigma = 0.1) price_vals = solve_lucas_model(tree); ``` @@ -468,9 +453,9 @@ price_vals = solve_lucas_model(tree); tags: [remove-cell] --- @testset begin - #test price_vals[57] ≈ 44.5077566916004 - #test price_vals[78] ≈ 68.42956586308563 - #test price_vals[13] ≈ 9.880376662058682 + @test price_vals[57] ≈ 41.35601991726328 + @test price_vals[78] ≈ 63.474988006734925 + @test price_vals[13] ≈ 9.24450665849126 end ``` @@ -519,11 +504,11 @@ Random.seed!(42); ```{code-cell} julia plot() -for β in (.95, 0.98) - tree = LucasTree(;β = β) +for beta in (0.95, 0.98) + tree = LucasTree(; beta) grid = tree.grid price_vals = solve_lucas_model(tree) - plot!(grid, price_vals, lw = 2, label = L"\beta = %$β") + plot!(grid, price_vals, lw = 2, label = L"\beta = %$beta") end plot!(xlabel = L"y", ylabel = "price", legend = :topleft) @@ -535,9 +520,9 @@ tags: [remove-cell] --- @testset begin # For the 0.98, since the other one is overwritten. Random.seed!(42) - price_vals = solve_lucas_model(LucasTree(β = 0.98)) - #test price_vals[20] ≈ 35.00073581199659 - #test price_vals[57] ≈ 124.32987344509688 + price_vals = solve_lucas_model(LucasTree(beta = 0.98)) + @test price_vals[20] ≈ 32.17514173843709 + @test price_vals[57] ≈ 113.89100588660085 end ``` diff --git a/lectures/multi_agent_models/markov_asset.md b/lectures/multi_agent_models/markov_asset.md index 68723095..ccf296ba 100644 --- a/lectures/multi_agent_models/markov_asset.md +++ b/lectures/multi_agent_models/markov_asset.md @@ -290,13 +290,12 @@ The next figure shows a simulation, where --- tags: [remove-cell] --- -using Test, Random +using Test ``` ```{code-cell} julia -using LinearAlgebra, Statistics -using LaTeXStrings, Parameters, Plots, QuantEcon - +using LinearAlgebra, Statistics, Random +using LaTeXStrings, Plots, QuantEcon, NLsolve ``` ```{code-cell} julia @@ -317,7 +316,7 @@ d_series = cumprod(g_series) # assumes d_0 = 1 series = [x_series g_series d_series log.(d_series)] labels = [L"X_t" L"g_t" L"d_t" L"ln(d_t)"] -plot(series, layout = 4, labels = labels) +plot(series; layout = 4, labels) ``` ```{code-cell} julia @@ -325,10 +324,9 @@ plot(series, layout = 4, labels = labels) tags: [remove-cell] --- @testset begin - #test x_series[4] ≈ -0.669642857142857 - #test g_series[5] ≈ 0.4094841251523643 - #test d_series[9] ≈ 0.03514706070454392 # Near the inflection point. - #test log.(d_series)[72] ≈ -29.24107142857142 # Something near the end. + @test x_series[4] ≈ -0.22321428571428567 + @test g_series[6] ≈ 1.2500884211272658 + @test d_series[9] ≈ 0.5118913634883987 end ``` @@ -404,20 +402,15 @@ Here's the code, including a test of the spectral radius condition ```{code-cell} julia n = 25 # size of state space -β = 0.9 +beta = 0.9 mc = tauchen(n, 0.96, 0.02) K = mc.p .* exp.(mc.state_values)' -v = (I - β * K) \ (β * K * ones(n, 1)) +v = (I - beta * K) \ (beta * K * ones(n, 1)) -plot(mc.state_values, - v, - lw = 2, - ylabel = "price-dividend ratio", - xlabel = "state", - alpha = 0.7, - label = L"v") +plot(mc.state_values, v; lw = 2, ylabel = "price-dividend ratio", + xlabel = L"X_t", alpha = 0.7, label = L"v") ``` ```{code-cell} julia @@ -425,10 +418,8 @@ plot(mc.state_values, tags: [remove-cell] --- @testset begin - #test v[2] ≈ 3.4594684257743284 atol = 1e-7 - #test v[1] ≈ 3.2560393349907755 - #test v[5] ≈ 4.526909446326235 - #test K[8] ≈ 8.887213530262768e-10 + @test v[2] ≈ 3.4594684257743284 + @test K[8] ≈ 8.887213530262768e-10 end ``` @@ -536,45 +527,27 @@ Assuming that the spectral radius of $J$ is strictly less than $\beta^{-1}$, thi v = (I - \beta J)^{-1} \beta J {\mathbb 1} ``` -We will define a function tree_price to solve for $v$ given parameters stored in +We will define a function `tree_price` to solve for $v$ given parameters stored in the AssetPriceModel objects +The default Markov Chain for will be a discretized AR(1) with $\rho = 0.9, \sigma = 0.02$ and discretized into 25 states using Tauchen's method. + ```{code-cell} julia -# A default Markov chain for the state process -ρ = 0.9 -σ = 0.02 -n = 25 -default_mc = tauchen(n, ρ, σ) - -AssetPriceModel = @with_kw (β = 0.96, - γ = 2.0, - mc = default_mc, - n = size(mc.p)[1], - g = exp) - -# test stability of matrix Q -function test_stability(ap, Q) - sr = maximum(abs, eigvals(Q)) - if sr ≥ 1 / ap.β - msg = "Spectral radius condition failed with radius = $sr" - throw(ArgumentError(msg)) - end +function AssetPriceModel(; beta = 0.96, gamma = 2.0, g = exp, + mc = tauchen(25, 0.9, 0.02)) + return (; beta, gamma, mc, g) end # price/dividend ratio of the Lucas tree -function tree_price(ap; γ = ap.γ) - # Simplify names, set up matrices - (;β, mc) = ap - P, y = mc.p, mc.state_values - y = reshape(y, 1, ap.n) - J = P .* ap.g.(y).^(1 - γ) - - # Make sure that a unique solution exists - test_stability(ap, J) +function tree_price(ap) + (; beta, mc, gamma, g) = ap + P = mc.p + y = mc.state_values' + J = P .* g.(y) .^ (1 - gamma) + @assert maximum(abs, eigvals(J)) < 1 / beta # check stability # Compute v - v = (I - β * J) \ sum(β * J, dims = 2) - + v = (I - beta * J) \ sum(beta * J, dims = 2) return v end ``` @@ -583,25 +556,16 @@ Here's a plot of $v$ as a function of the state for several values of $\gamma$, with a positively correlated Markov process and $g(x) = \exp(x)$ ```{code-cell} julia -γs = [1.2, 1.4, 1.6, 1.8, 2.0] -ap = AssetPriceModel() -states = ap.mc.state_values - -lines = [] -labels = [] - -for γ in γs - v = tree_price(ap, γ = γ) - label = L"\gamma = %$γ" - push!(labels, label) - push!(lines, v) +gammas = [1.2, 1.4, 1.6, 1.8, 2.0] +p = plot(title = "Price-dividend ratio as a function of the state", + xlabel = L"X_t", ylabel = "price-dividend ratio") + +for gamma in gammas + ap = AssetPriceModel(; gamma) + states = ap.mc.state_values + plot!(states, tree_price(ap); label = L"\gamma = %$gamma") end - -plot(lines, - labels = reshape(labels, 1, length(labels)), - title = "Price-dividend ratio as a function of the state", - ylabel = "price-dividend ratio", - xlabel = "state") +p ``` ```{code-cell} julia @@ -609,10 +573,10 @@ plot(lines, tags: [remove-cell] --- @testset begin - #test lines[2][4] ≈ 33.36574362637905 - #test lines[3][12] ≈ 28.52560591264372 - #test lines[4][18] ≈ 22.38597470787489 - #test lines[5][24] ≈ 15.81947255704859 + ap = AssetPriceModel() + v = tree_price(ap) + @test v[5] ≈ 74.54830456854316 + @test v[16] ≈ 29.426651157109678 end ``` @@ -687,24 +651,23 @@ yields the solution p = (I - \beta M)^{-1} \beta M \zeta {\mathbb 1} ``` -The above is implemented in the function consol_price +The above is implemented in the function `consol_price` ```{code-cell} julia -function consol_price(ap, ζ) - # Simplify names, set up matrices - (;β, γ, mc, g, n) = ap - P, y = mc.p, mc.state_values - y = reshape(y, 1, n) - M = P .* g.(y).^(-γ) - - # Make sure that a unique solution exists - test_stability(ap, M) +function consol_price(ap, zeta) + (; beta, gamma, mc, g) = ap + P = mc.p + y = mc.state_values' + M = P .* g.(y) .^ (-gamma) + @assert maximum(abs, eigvals(M)) < 1 / beta # Compute price - return (I - β * M) \ sum(β * ζ * M, dims = 2) + return (I - beta * M) \ sum(beta * zeta * M, dims = 2) end ``` +Note that the `sum(Q, dims=2)` is equivalent to `Q * ones(size(Q)[1], 1)`. + ### Pricing an Option to Purchase the Consol Let's now price options of varying maturity that give the right to purchase a consol at a price $p_S$. @@ -771,52 +734,46 @@ T w = \max \{ \beta M w,\; p - p_S {\mathbb 1} \} $$ -Start at some initial $w$ and iterate to convergence with $T$. +Start at some initial $w$ and iterate to convergence with $T$, or use a fixed point algorithm. We can find the solution with the following function call_option ```{code-cell} julia # price of perpetual call on consol bond -function call_option(ap, ζ, p_s, ϵ = 1e-7) - - # Simplify names, set up matrices - (;β, γ, mc, g, n) = ap - P, y = mc.p, mc.state_values - y = reshape(y, 1, n) - M = P .* g.(y).^(-γ) - - # Make sure that a unique console price exists - test_stability(ap, M) - - # Compute option price - p = consol_price(ap, ζ) - w = zeros(ap.n, 1) - error = ϵ + 1 - while (error > ϵ) - # Maximize across columns - w_new = max.(β * M * w, p .- p_s) - # Find maximal difference of each component and update - error = maximum(abs, w - w_new) - w = w_new - end - - return w +function call_option(ap, zeta, p_s) + (; beta, gamma, mc, g) = ap + P = mc.p + y = mc.state_values' + M = P .* g.(y) .^ (-gamma) + @assert maximum(abs, eigvals(M)) < 1 / beta + + # Find consol prices + p = consol_price(ap, zeta) + + # Operator for fixed point, using consol prices + T(w) = max.(beta * M * w, p .- p_s) + + # Compute option price as fixed point + sol = fixedpoint(T, zeros(length(y), 1)) + converged(sol) || error("Failed to converge in $(sol.iterations) iter") + return sol.zero end ``` Here's a plot of $w$ compared to the consol price when $P_S = 40$ ```{code-cell} julia -ap = AssetPriceModel(β=0.9) -ζ = 1.0 +ap = AssetPriceModel(; beta = 0.9) +zeta = 1.0 strike_price = 40.0 x = ap.mc.state_values -p = consol_price(ap, ζ) -w = call_option(ap, ζ, strike_price) +p = consol_price(ap, zeta) +w = call_option(ap, zeta, strike_price) -plot(x, p, color = "blue", lw = 2, xlabel = "state", label = "consol price") -plot!(x, w, color = "green", lw = 2, label = "value of call option") +plot(x, p, color = "blue", lw = 2, xlabel = L"X_t", label = "consol price") +plot!(x, w, color = "green", lw = 2, + label = "value of call option with strike at $strike_price") ``` ```{code-cell} julia @@ -824,8 +781,8 @@ plot!(x, w, color = "green", lw = 2, label = "value of call option") tags: [remove-cell] --- @testset begin - #test p[17] ≈ 9.302197030956606 - #test w[20] ≈ 0.46101660813737866 + @test p[17] ≈ 9.302197030956606 + @test w[20] ≈ 0.4610168409491948 end ``` @@ -836,15 +793,6 @@ where the consol prices is high --- will eventually be visited. The reason is that $\beta=0.9$, so the future is discounted relatively rapidly -```{code-cell} julia ---- -tags: [remove-cell] ---- -@testset begin - #test x[2] ≈ -0.126178653628809 - #test p[5] ≈ 52.85568616593254 -end -``` ### Risk Free Rates @@ -899,9 +847,9 @@ Consider the following primitives n = 5 P = fill(0.0125, n, n) + (0.95 - 0.0125)I s = [1.05, 1.025, 1.0, 0.975, 0.95] -γ = 2.0 -β = 0.94 -ζ = 1.0 +gamma = 2.0 +beta = 0.94 +zeta = 1.0 ``` Let $g$ be defined by $g(x) = x$ (that is, $g$ is the identity map). @@ -961,25 +909,25 @@ Is one higher than the other? Can you give intuition? ```{code-cell} julia n = 5 -P = fill(0.0125, n, n) + (0.95 - 0.0125)I +P = fill(0.0125, n, n) + (0.95 - 0.0125) * I s = [0.95, 0.975, 1.0, 1.025, 1.05] # state values mc = MarkovChain(P, s) - -γ = 2.0 -β = 0.94 -ζ = 1.0 +g = x -> x # identity +gamma = 2.0 +beta = 0.94 +zeta = 1.0 p_s = 150.0 ``` Next we'll create an instance of AssetPriceModel to feed into the functions. ```{code-cell} julia -ap = AssetPriceModel(β = β, mc = mc, γ = γ, g = x -> x) +ap = AssetPriceModel(; beta, mc, gamma, g) ``` +Lucas tree prices are ```{code-cell} julia -v = tree_price(ap) -println("Lucas Tree Prices: $v\n") +tree_price(ap) ``` ```{code-cell} julia @@ -987,17 +935,18 @@ println("Lucas Tree Prices: $v\n") tags: [remove-cell] --- @testset begin - #test v[2] ≈ 21.935706611219704 + v = tree_price(ap) + @test v[2] ≈ 21.935706611219704 end ``` +Consol Bond Prices ```{code-cell} julia -v_consol = consol_price(ap, 1.0) -println("Consol Bond Prices: $(v_consol)\n") +consol_price(ap, 1.0) ``` ```{code-cell} julia -w = call_option(ap, ζ, p_s) +w = call_option(ap, zeta, p_s) ``` ```{code-cell} julia @@ -1005,8 +954,8 @@ w = call_option(ap, ζ, p_s) tags: [remove-cell] --- @testset begin - #test v_consol[1] ≈ 753.8710047641985 - #test w[2][1] ≈ 176.83933430191294 + @test consol_price(ap, 1.0)[1] ≈ 753.8710047641985 + @test w[2] ≈ 176.83933430191294 end ``` @@ -1015,23 +964,20 @@ end Here's a suitable function: ```{code-cell} julia -function finite_horizon_call_option(ap, ζ, p_s, k) - - # Simplify names, set up matrices - (;β, γ, mc) = ap - P, y = mc.p, mc.state_values - y = y' - M = P .* ap.g.(y).^(- γ) - - # Make sure that a unique console price exists - test_stability(ap, M) +function finite_horizon_call_option(ap, zeta, p_s, k) + (; beta, gamma, mc) = ap + P = mc.p + y = mc.state_values' + M = P .* ap.g.(y) .^ (-gamma) + @assert maximum(abs, eigvals(M)) < 1 / beta # Compute option price - p = consol_price(ap, ζ) - w = zeros(ap.n, 1) + p = consol_price(ap, zeta) + + w = zeros(length(y), 1) for i in 1:k # Maximize across columns - w = max.(β * M * w, p .- p_s) + w = max.(beta * M * w, p .- p_s) end return w @@ -1043,30 +989,18 @@ end tags: [remove-cell] --- @testset begin - #test p[3] ≈ 70.00064625026326 - #test w[2] ≈ 176.83933430191294 + @test finite_horizon_call_option(ap, zeta, p_s, 5)[3] ≈ 31.798938780647198 end ``` ```{code-cell} julia -lines = [] -labels = [] +p = plot(title = "Value Finite Horizon Call Option", xlabel = L"t", + ylabel = "value") for k in [5, 25] - w = finite_horizon_call_option(ap, ζ, p_s, k) - push!(lines, w) - push!(labels, L"k = %$k") -end -plot(lines, labels = reshape(labels, 1, length(labels))) -``` - -```{code-cell} julia ---- -tags: [remove-cell] ---- -@testset begin - #test lines[1][4] ≈ 29.859285398252347 - #test lines[2][2] ≈ 147.00074548801277 + w = finite_horizon_call_option(ap, zeta, p_s, k) + plot!(w; label = L"k = %$k") end +p ``` Not surprisingly, the option has greater value with larger $k$. diff --git a/lectures/multi_agent_models/markov_perf.md b/lectures/multi_agent_models/markov_perf.md index e70da347..3f062158 100644 --- a/lectures/multi_agent_models/markov_perf.md +++ b/lectures/multi_agent_models/markov_perf.md @@ -432,28 +432,28 @@ using QuantEcon, LinearAlgebra # parameters a0 = 10.0 a1 = 2.0 -β = 0.96 -γ = 12.0 +beta = 0.96 +gamma = 12.0 # in LQ form -A = I + zeros(3, 3) +A = I + zeros(3, 3) B1 = [0.0, 1.0, 0.0] B2 = [0.0, 0.0, 1.0] -R1 = [ 0.0 -a0 / 2.0 0.0; - -a0 / 2.0 a1 a1 / 2.0; - 0.0 a1 / 2.0 0.0] +R1 = [0.0 -a0/2.0 0.0; + -a0/2.0 a1 a1/2.0; + 0.0 a1/2.0 0.0] -R2 = [ 0.0 0.0 -a0 / 2.0; - 0.0 0.0 a1 / 2.0; - -a0 / 2.0 a1 / 2.0 a1] +R2 = [0.0 0.0 -a0/2.0; + 0.0 0.0 a1/2.0; + -a0/2.0 a1/2.0 a1] -Q1 = Q2 = γ +Q1 = Q2 = gamma S1 = S2 = W1 = W2 = M1 = M2 = 0.0 # solve using QE's nnash function F1, F2, P1, P2 = nnash(A, B1, B2, R1, R2, Q1, Q2, S1, S2, W1, W2, M1, M2, - beta=β) + beta = beta) # display policies println("Computed policies for firm 1 and firm 2:") @@ -480,8 +480,8 @@ In particular, let's take F2 as computed above, plug it into {eq}`eq_mpe_p1p` an We hope that the resulting policy will agree with F1 as computed above ```{code-cell} julia -Λ1 = A - (B2 * F2) -lq1 = QuantEcon.LQ(Q1, R1, Λ1, B1, bet=β) +Lambda1 = A - (B2 * F2) +lq1 = QuantEcon.LQ(Q1, R1, Lambda1, B1, bet = beta) P1_ih, F1_ih, d = stationary_values(lq1) F1_ih ``` @@ -493,7 +493,7 @@ tags: [remove-cell] @testset begin @test P1_ih[2, 2] ≈ 5.441368459897164 @test d ≈ 0.0 - @test Λ1[1, 1] ≈ 1.0 && Λ1[3, 2] ≈ -0.07584666305807419 + @test Lambda1[1, 1] ≈ 1.0 && Lambda1[3, 2] ≈ -0.07584666305807419 @test F1_ih ≈ [-0.6684661291052371 0.29512481789806305 0.07584666292394007] @test isapprox(F1, F1_ih, atol=1e-7) # Make sure the test below comes up true. end @@ -504,7 +504,7 @@ This is close enough for rock and roll, as they say in the trade. Indeed, isapprox agrees with our assessment ```{code-cell} julia -isapprox(F1, F1_ih, atol=1e-7) +isapprox(F1, F1_ih, atol = 1e-7) ``` ### Dynamics @@ -522,22 +522,21 @@ The following program ```{code-cell} julia using LaTeXStrings, Plots - AF = A - B1 * F1 - B2 * F2 n = 20 x = zeros(3, n) x[:, 1] = [1 1 1] -for t in 1:n-1 - x[:, t+1] = AF * x[:, t] +for t in 1:(n - 1) + x[:, t + 1] = AF * x[:, t] end q1 = x[2, :] q2 = x[3, :] q = q1 + q2 # total output, MPE p = a0 .- a1 * q # price, MPE -plt = plot(q, color=:blue, lw=2, alpha=0.75, label="total output") -plot!(plt, p, color=:green, lw=2, alpha=0.75, label="price") -plot!(plt, title="Output and prices, duopoly MPE") +plt = plot(q, color = :blue, lw = 2, alpha = 0.75, label = "total output") +plot!(plt, p, color = :green, lw = 2, alpha = 0.75, label = "price") +plot!(plt, title = "Output and prices, duopoly MPE") ``` ```{code-cell} julia @@ -651,9 +650,9 @@ The exercise is to calculate these matrices and compute the following figures. The first figure shows the dynamics of inventories for each firm when the parameters are ```{code-cell} julia -δ = 0.02 -D = [ -1 0.5; - 0.5 -1] +delta = 0.02 +D = [-1 0.5; + 0.5 -1] b = [25, 25] c1 = c2 = [1, -2, 1] e1 = e2 = [10, 10, 3] @@ -683,28 +682,28 @@ First let's compute the duopoly MPE under the stated parameters # parameters a0 = 10.0 a1 = 2.0 -β = 0.96 -γ = 12.0 +beta = 0.96 +gamma = 12.0 # in LQ form A = I + zeros(3, 3) B1 = [0.0, 1.0, 0.0] B2 = [0.0, 0.0, 1.0] -R1 = [ 0.0 -a0 / 2.0 0.0; - -a0 / 2.0 a1 a1 / 2.0; - 0.0 a1 / 2.0 0.0] +R1 = [0.0 -a0/2.0 0.0; + -a0/2.0 a1 a1/2.0; + 0.0 a1/2.0 0.0] -R2 = [ 0.0 0.0 -a0 / 2.0; - 0.0 0.0 a1 / 2.0; - -a0 / 2.0 a1 / 2.0 a1] +R2 = [0.0 0.0 -a0/2.0; + 0.0 0.0 a1/2.0; + -a0/2.0 a1/2.0 a1] -Q1 = Q2 = γ +Q1 = Q2 = gamma S1 = S2 = W1 = W2 = M1 = M2 = 0.0 # solve using QE's nnash function F1, F2, P1, P2 = nnash(A, B1, B2, R1, R2, Q1, Q2, S1, S2, W1, W2, M1, M2, - beta=β) + beta = beta) ``` ```{code-cell} julia @@ -783,9 +782,9 @@ resulting dynamics of $\{q_t\}$, starting at $q_0 = 2.0$. tags: [hide-output] --- R = a1 -Q = γ +Q = gamma A = B = 1 -lq_alt = QuantEcon.LQ(Q, R, A, B, bet=β) +lq_alt = QuantEcon.LQ(Q, R, A, B, bet=beta) P, F, d = stationary_values(lq_alt) q̄ = a0 / (2.0 * a1) qm = zeros(n) @@ -814,15 +813,19 @@ end Let's have a look at the different time paths ```{code-cell} julia -plt_q = plot(qm, color=:blue, lw=2, alpha=0.75, label="monopolist output") -plot!(plt_q, q, color=:green, lw=2, alpha=0.75, label="MPE total output") -plot!(plt_q, xlabel="time", ylabel="output", ylim=(2,4),legend=:topright) +plt_q = plot(qm, color = :blue, lw = 2, alpha = 0.75, + label = "monopolist output") +plot!(plt_q, q, color = :green, lw = 2, alpha = 0.75, + label = "MPE total output") +plot!(plt_q, xlabel = "time", ylabel = "output", ylim = (2, 4), + legend = :topright) -plt_p = plot(pm, color=:blue, lw=2, alpha=0.75, label="monopolist price") -plot!(plt_p, p, color=:green, lw=2, alpha=0.75, label="MPE price") -plot!(plt_p, xlabel="time", ylabel="price",legend=:topright) +plt_p = plot(pm, color = :blue, lw = 2, alpha = 0.75, + label = "monopolist price") +plot!(plt_p, p, color = :green, lw = 2, alpha = 0.75, label = "MPE price") +plot!(plt_p, xlabel = "time", ylabel = "price", legend = :topright) -plot(plt_q, plt_p, layout=(2,1), size=(700,600)) +plot(plt_q, plt_p, layout = (2, 1), size = (700, 600)) ``` ### Exercise 2 @@ -830,13 +833,13 @@ plot(plt_q, plt_p, layout=(2,1), size=(700,600)) We treat the case $\delta = 0.02$ ```{code-cell} julia -δ = 0.02 -D = [-1 0.5; +delta = 0.02 +D = [-1 0.5; 0.5 -1] b = [25, 25] c1 = c2 = [1, -2, 1] e1 = e2 = [10, 10, 3] -δ_1 = 1-δ +delta_1 = 1 - delta ``` Recalling that the control and state are @@ -860,42 +863,42 @@ we set up the matrices as follows: ```{code-cell} julia # create matrices needed to compute the Nash feedback equilibrium -A = [δ_1 0 -δ_1 * b[1]; - 0 δ_1 -δ_1 * b[2]; - 0 0 1] - -B1 = δ_1 * [1 -D[1, 1]; - 0 -D[2, 1]; - 0 0] -B2 = δ_1 * [0 -D[1, 2]; - 1 -D[2, 2]; - 0 0] - -R1 = -[0.5 * c1[3] 0 0.5 * c1[2]; - 0 0 0; - 0.5 * c1[2] 0 c1[1]] - -R2 = -[0 0 0; - 0 0.5 * c2[3] 0.5*c2[2]; - 0 0.5 * c2[2] c2[1]] - -Q1 = [-0.5*e1[3] 0; - 0 D[1, 1]] -Q2 = [-0.5*e2[3] 0; - 0 D[2, 2]] +A = [delta_1 0 -delta_1*b[1]; + 0 delta_1 -delta_1*b[2]; + 0 0 1] + +B1 = delta_1 * [1 -D[1, 1]; + 0 -D[2, 1]; + 0 0] +B2 = delta_1 * [0 -D[1, 2]; + 1 -D[2, 2]; + 0 0] + +R1 = -[0.5*c1[3] 0 0.5*c1[2]; + 0 0 0; + 0.5*c1[2] 0 c1[1]] + +R2 = -[0 0 0; + 0 0.5*c2[3] 0.5*c2[2]; + 0 0.5*c2[2] c2[1]] + +Q1 = [-0.5*e1[3] 0; + 0 D[1, 1]] +Q2 = [-0.5*e2[3] 0; + 0 D[2, 2]] S1 = zeros(2, 2) S2 = copy(S1) -W1 = [ 0.0 0.0; - 0.0 0.0; - -0.5 * e1[2] b[1] / 2.0] -W2 = [ 0.0 0.0; - 0.0 0.0; - -0.5 * e2[2] b[2] / 2.0] +W1 = [0.0 0.0; + 0.0 0.0; + -0.5*e1[2] b[1]/2.0] +W2 = [0.0 0.0; + 0.0 0.0; + -0.5*e2[2] b[2]/2.0] -M1 = [0.0 0.0; - 0.0 D[1, 2] / 2.0] +M1 = [0.0 0.0; + 0.0 D[1, 2]/2.0] M2 = copy(M1) ``` @@ -943,16 +946,16 @@ corresponding to $\delta = 0.02$ AF = A - B1 * F1 - B2 * F2 n = 25 x = zeros(3, n) -x[:, 1] = [2 0 1] -for t in 1:(n-1) - x[:, t+1] = AF * x[:, t] +x[:, 1] = [2 0 1] +for t in 1:(n - 1) + x[:, t + 1] = AF * x[:, t] end I1 = x[1, :] I2 = x[2, :] -plot(I1, color=:blue, lw=2, alpha=0.75, label="inventories, firm 1") -plot!(I2, color=:green, lw=2, alpha=0.75, label="inventories, firm 2") -plot!(title=L"\delta = 0.02") +plot(I1, color = :blue, lw = 2, alpha = 0.75, label = "inventories, firm 1") +plot!(I2, color = :green, lw = 2, alpha = 0.75, label = "inventories, firm 2") +plot!(title = L"\delta = 0.02") ``` ```{code-cell} julia diff --git a/lectures/multi_agent_models/matsuyama.md b/lectures/multi_agent_models/matsuyama.md index b0ac9108..ab0a1611 100644 --- a/lectures/multi_agent_models/matsuyama.md +++ b/lectures/multi_agent_models/matsuyama.md @@ -336,13 +336,12 @@ using Test ``` ```{code-cell} julia -using LinearAlgebra, Statistics -using Plots, Parameters +using LinearAlgebra, Statistics, Plots ``` ```{code-cell} julia -function h_j(j, nk, s1, s2, θ, δ, ρ) +function h_j(j, nk, s1, s2, theta, delta, rho) # Find out who's h we are evaluating if j == 1 sj = s1 @@ -354,8 +353,8 @@ function h_j(j, nk, s1, s2, θ, δ, ρ) # Coefficients on the quadratic a x^2 + b x + c = 0 a = 1.0 - b = ((ρ + 1 / ρ) * nk - sj - sk) - c = (nk * nk - (sj * nk) / ρ - sk * ρ * nk) + b = ((rho + 1 / rho) * nk - sj - sk) + c = (nk * nk - (sj * nk) / rho - sk * rho * nk) # Positive solution of quadratic form root = (-b + sqrt(b * b - 4 * a * c)) / (2 * a) @@ -363,41 +362,49 @@ function h_j(j, nk, s1, s2, θ, δ, ρ) return root end -DLL(n1, n2, s1_ρ, s2_ρ, s1, s2, θ, δ, ρ) = - (n1 ≤ s1_ρ) && (n2 ≤ s2_ρ) +function DLL(n1, n2, s1_rho, s2_rho, s1, s2, theta, delta, rho) + (n1 <= s1_rho) && (n2 <= s2_rho) +end -DHH(n1, n2, s1_ρ, s2_ρ, s1, s2, θ, δ, ρ) = - (n1 ≥ h_j(1, n2, s1, s2, θ, δ, ρ)) && (n2 ≥ h_j(2, n1, s1, s2, θ, δ, ρ)) +function DHH(n1, n2, s1_rho, s2_rho, s1, s2, theta, delta, rho) + (n1 >= h_j(1, n2, s1, s2, theta, delta, rho)) && + (n2 >= h_j(2, n1, s1, s2, theta, delta, rho)) +end -DHL(n1, n2, s1_ρ, s2_ρ, s1, s2, θ, δ, ρ) = - (n1 ≥ s1_ρ) && (n2 ≤ h_j(2, n1, s1, s2, θ, δ, ρ)) +function DHL(n1, n2, s1_rho, s2_rho, s1, s2, theta, delta, rho) + (n1 >= s1_rho) && (n2 <= h_j(2, n1, s1, s2, theta, delta, rho)) +end -DLH(n1, n2, s1_ρ, s2_ρ, s1, s2, θ, δ, ρ) = - (n1 ≤ h_j(1, n2, s1, s2, θ, δ, ρ)) && (n2 ≥ s2_ρ) +function DLH(n1, n2, s1_rho, s2_rho, s1, s2, theta, delta, rho) + (n1 <= h_j(1, n2, s1, s2, theta, delta, rho)) && (n2 >= s2_rho) +end -function one_step(n1, n2, s1_ρ, s2_ρ, s1, s2, θ, δ, ρ) +function one_step(n1, n2, s1_rho, s2_rho, s1, s2, theta, delta, rho) # Depending on where we are, evaluate the right branch - if DLL(n1, n2, s1_ρ, s2_ρ, s1, s2, θ, δ, ρ) - n1_tp1 = δ * (θ * s1_ρ + (1 - θ) * n1) - n2_tp1 = δ * (θ * s2_ρ + (1 - θ) * n2) - elseif DHH(n1, n2, s1_ρ, s2_ρ, s1, s2, θ, δ, ρ) - n1_tp1 = δ * n1 - n2_tp1 = δ * n2 - elseif DHL(n1, n2, s1_ρ, s2_ρ, s1, s2, θ, δ, ρ) - n1_tp1 = δ * n1 - n2_tp1 = δ * (θ * h_j(2, n1, s1, s2, θ, δ, ρ) + (1 - θ) * n2) - elseif DLH(n1, n2, s1_ρ, s2_ρ, s1, s2, θ, δ, ρ) - n1_tp1 = δ * (θ * h_j(1, n2, s1, s2, θ, δ, ρ) + (1 - θ) * n1) - n2_tp1 = δ * n2 + if DLL(n1, n2, s1_rho, s2_rho, s1, s2, theta, delta, rho) + n1_tp1 = delta * (theta * s1_rho + (1 - theta) * n1) + n2_tp1 = delta * (theta * s2_rho + (1 - theta) * n2) + elseif DHH(n1, n2, s1_rho, s2_rho, s1, s2, theta, delta, rho) + n1_tp1 = delta * n1 + n2_tp1 = delta * n2 + elseif DHL(n1, n2, s1_rho, s2_rho, s1, s2, theta, delta, rho) + n1_tp1 = delta * n1 + n2_tp1 = delta * (theta * h_j(2, n1, s1, s2, theta, delta, rho) + + (1 - theta) * n2) + elseif DLH(n1, n2, s1_rho, s2_rho, s1, s2, theta, delta, rho) + n1_tp1 = delta * (theta * h_j(1, n2, s1, s2, theta, delta, rho) + + (1 - theta) * n1) + n2_tp1 = delta * n2 end return n1_tp1, n2_tp1 end -new_n1n2(n1_0, n2_0, s1_ρ, s2_ρ, s1, s2, θ, δ, ρ) = - one_step(n1_0, n2_0, s1_ρ, s2_ρ, s1, s2, θ, δ, ρ) +function new_n1n2(n1_0, n2_0, s1_rho, s2_rho, s1, s2, theta, delta, rho) + one_step(n1_0, n2_0, s1_rho, s2_rho, s1, s2, theta, delta, rho) +end -function pers_till_sync(n1_0, n2_0, s1_ρ, s2_ρ, s1, s2, θ, δ, ρ, +function pers_till_sync(n1_0, n2_0, s1_rho, s2_rho, s1, s2, theta, delta, rho, maxiter, npers) # Initialize the status of synchronization @@ -407,16 +414,17 @@ function pers_till_sync(n1_0, n2_0, s1_ρ, s2_ρ, s1, s2, θ, δ, ρ, nsync = 0 - while (~synchronized) && (iters < maxiter) + while (!synchronized) && (iters < maxiter) # Increment the number of iterations and get next values iters += 1 - n1_t, n2_t = new_n1n2(n1_0, n2_0, s1_ρ, s2_ρ, s1, s2, θ, δ, ρ) + n1_t, n2_t = new_n1n2(n1_0, n2_0, s1_rho, s2_rho, s1, s2, theta, delta, + rho) # Check whether same in this period if abs(n1_t - n2_t) < 1e-8 nsync += 1 - # If not, then reset the nsync counter + # If not, then reset the nsync counter else nsync = 0 end @@ -432,20 +440,21 @@ function pers_till_sync(n1_0, n2_0, s1_ρ, s2_ρ, s1, s2, θ, δ, ρ, return synchronized, pers_2_sync end -function create_attraction_basis(s1_ρ, s2_ρ, s1, s2, θ, δ, ρ, +function create_attraction_basis(s1_rho, s2_rho, s1, s2, theta, delta, rho, maxiter, npers, npts) # Create unit range with npts synchronized, pers_2_sync = false, 0 - unit_range = range(0.0, 1.0, length = npts) + unit_range = range(0.0, 1.0, length = npts) # Allocate space to store time to sync time_2_sync = zeros(npts, npts) # Iterate over initial conditions for (i, n1_0) in enumerate(unit_range) for (j, n2_0) in enumerate(unit_range) - synchronized, pers_2_sync = pers_till_sync(n1_0, n2_0, s1_ρ, s2_ρ, - s1, s2, θ, δ, ρ, - maxiter, npers) + synchronized, pers_2_sync = pers_till_sync(n1_0, n2_0, s1_rho, + s2_rho, s1, s2, theta, + delta, rho, maxiter, + npers) time_2_sync[i, j] = pers_2_sync end end @@ -453,18 +462,17 @@ function create_attraction_basis(s1_ρ, s2_ρ, s1, s2, θ, δ, ρ, end # model -function MSGSync(s1 = 0.5, θ = 2.5, δ = 0.7, ρ = 0.2) +function MSGSync(s1 = 0.5, theta = 2.5, delta = 0.7, rho = 0.2) # Store other cutoffs and parameters we use s2 = 1 - s1 - s1_ρ = min((s1 - ρ * s2) / (1 - ρ), 1) - s2_ρ = 1 - s1_ρ + s1_rho = min((s1 - rho * s2) / (1 - rho), 1) + s2_rho = 1 - s1_rho - return (s1 = s1, s2 = s2, s1_ρ = s1_ρ, s2_ρ = s2_ρ, θ = θ, δ = δ, ρ = ρ) + return (; s1, s2, s1_rho, s2_rho, theta, delta, rho) end function simulate_n(model, n1_0, n2_0, T) - # Unpack parameters - @unpack s1, s2, θ, δ, ρ, s1_ρ, s2_ρ = model + (; s1, s2, theta, delta, rho, s1_rho, s2_rho) = model # Allocate space n1 = zeros(T) @@ -474,30 +482,28 @@ function simulate_n(model, n1_0, n2_0, T) for t in 1:T # Get next values n1[t], n2[t] = n1_0, n2_0 - n1_0, n2_0 = new_n1n2(n1_0, n2_0, s1_ρ, s2_ρ, s1, s2, θ, δ, ρ) + n1_0, n2_0 = new_n1n2(n1_0, n2_0, s1_rho, s2_rho, s1, s2, theta, delta, + rho) end return n1, n2 end -function pers_till_sync(model, n1_0, n2_0, - maxiter = 500, npers = 3) - # Unpack parameters - @unpack s1, s2, θ, δ, ρ, s1_ρ, s2_ρ = model +function pers_till_sync(model, n1_0, n2_0, maxiter = 500, npers = 3) + (; s1, s2, theta, delta, rho, s1_rho, s2_rho) = model - return pers_till_sync(n1_0, n2_0, s1_ρ, s2_ρ, s1, s2, - θ, δ, ρ, maxiter, npers) + return pers_till_sync(n1_0, n2_0, s1_rho, s2_rho, s1, s2, + theta, delta, rho, maxiter, npers) end function create_attraction_basis(model; maxiter = 250, npers = 3, npts = 50) - # Unpack parameters - @unpack s1, s2, θ, δ, ρ, s1_ρ, s2_ρ = model + (; s1, s2, theta, delta, rho, s1_rho, s2_rho) = model - ab = create_attraction_basis(s1_ρ, s2_ρ, s1, s2, θ, δ, - ρ, maxiter, npers, npts) + ab = create_attraction_basis(s1_rho, s2_rho, s1, s2, theta, delta, + rho, maxiter, npers, npts) return ab end ``` @@ -513,8 +519,9 @@ The time series share parameters but differ in their initial condition. Here's the function ```{code-cell} julia -function plot_timeseries(n1_0, n2_0, s1 = 0.5, θ = 2.5, δ = 0.7, ρ = 0.2) - model = MSGSync(s1, θ, δ, ρ) +function plot_timeseries(n1_0, n2_0, s1 = 0.5, theta = 2.5, delta = 0.7, + rho = 0.2) + model = MSGSync(s1, theta, delta, rho) n1, n2 = simulate_n(model, n1_0, n2_0, 25) return [n1 n2] end @@ -569,20 +576,21 @@ Replicate the figure {ref}`shown above ` by coloring initial conditions ### Exercise 1 ```{code-cell} julia -function plot_attraction_basis(s1 = 0.5, θ = 2.5, δ = 0.7, ρ = 0.2; npts = 250) +function plot_attraction_basis(s1 = 0.5, theta = 2.5, delta = 0.7, rho = 0.2; + npts = 250) # Create attraction basis - unitrange = range(0, 1, length = npts) - model = MSGSync(s1, θ, δ, ρ) - ab = create_attraction_basis(model,npts=npts) + unitrange = range(0, 1, length = npts) + model = MSGSync(s1, theta, delta, rho) + ab = create_attraction_basis(model, npts = npts) plt = Plots.heatmap(ab, legend = false) end ``` ```{code-cell} julia params = [[0.5, 2.5, 0.7, 0.2], - [0.5, 2.5, 0.7, 0.4], - [0.5, 2.5, 0.7, 0.6], - [0.5, 2.5, 0.7, 0.8]] + [0.5, 2.5, 0.7, 0.4], + [0.5, 2.5, 0.7, 0.6], + [0.5, 2.5, 0.7, 0.8]] plots = (plot_attraction_basis(p...) for p in params) plot(plots..., size = (1000, 1000)) @@ -593,13 +601,13 @@ plot(plots..., size = (1000, 1000)) tags: [remove-cell] --- function plot_attraction_basis(s1 = 0.5, - θ = 2.5, - δ = 0.7, - ρ = 0.2; + theta = 2.5, + delta = 0.7, + rho = 0.2; npts = 250) # Create attraction basis unitrange = range(0, 1, length = npts) - model = MSGSync(s1, θ, δ, ρ) + model = MSGSync(s1, theta, delta, rho) ab = create_attraction_basis(model, npts = npts) end diff --git a/lectures/multi_agent_models/rational_expectations.md b/lectures/multi_agent_models/rational_expectations.md index 9a752c52..19654114 100644 --- a/lectures/multi_agent_models/rational_expectations.md +++ b/lectures/multi_agent_models/rational_expectations.md @@ -595,7 +595,7 @@ using Test ``` ```{code-cell} julia -using QuantEcon, Printf, LinearAlgebra +using QuantEcon, LinearAlgebra ``` To map a problem into a {doc}`discounted optimal linear control problem <../dynamic_programming/lqcontrol>`, we need to define. @@ -662,34 +662,36 @@ Here's our solution # model parameters a0 = 100 a1 = 0.05 -β = 0.95 -γ = 10.0 +beta = 0.95 +gamma = 10.0 # beliefs -κ0 = 95.5 -κ1 = 0.95 +kappa0 = 95.5 +kappa1 = 0.95 # formulate the LQ problem -A = [1 0 0 - 0 κ1 κ0 - 0 0 1] +A = [1 0 0 + 0 kappa1 kappa0 + 0 0 1] B = [1.0, 0.0, 0.0] -R = [ 0 a1/2 -a0/2 - a1/2 0 0 - -a0/2 0 0] +R = [0 a1/2 -a0/2 + a1/2 0 0 + -a0/2 0 0] -Q = 0.5 * γ +Q = 0.5 * gamma # solve for the optimal policy -lq = QuantEcon.LQ(Q, R, A, B; bet = β) +lq = QuantEcon.LQ(Q, R, A, B; bet = beta) P, F, d = stationary_values(lq) -hh = h0, h1, h2 = -F[3], 1 - F[1], -F[2] - -@printf("F = [%.3f, %.3f, %.3f]\n", F[1], F[2], F[3]) -@printf("(h0, h1, h2) = [%.3f, %.3f, %.3f]\n", h0, h1, h2) +# unpack results +h0 = -F[3] +h1 = 1 - F[1] +h2 = -F[2] +@show F +@show h0, h1, h2; ``` ```{code-cell} julia @@ -748,16 +750,18 @@ candidates = ([94.0886298678, 0.923409232937], [95.0818452486, 0.952459076301]) for (k0, k1) in candidates - A = [1 0 0 + A = [1 0 0 0 k1 k0 - 0 0 1] - lq = QuantEcon.LQ(Q, R, A, B; bet=β) + 0 0 1] + lq = QuantEcon.LQ(Q, R, A, B; bet = beta) P, F, d = stationary_values(lq) - hh = h0, h1, h2 = -F[3], 1 - F[1], -F[2] + h0 = -F[3] + h1 = 1 - F[1] + h2 = -F[2] if isapprox(k0, h0; atol = 1e-4) && isapprox(k1, h1 + h2; atol = 1e-4) - @printf("Equilibrium pair = (%.6f, %.6f)\n", k0, k1) - @printf("(h0, h1, h2) = [%.6f, %.6f, %.6f]\n", h0, h1, h2) + println("Equilibrium pair = ($k0, $k1)") + @show h0, h1, h2 end end ``` @@ -830,18 +834,19 @@ $\kappa_0 = -F_1$ and $\kappa_1 = 1-F_0$ A = I + zeros(2, 2) B = [1.0, 0.0] -R = [ a1 / 2.0 -a0 / 2.0 - -a0 / 2.0 0.0] +R = [a1/2.0 -a0/2.0 + -a0/2.0 0.0] -Q = γ / 2.0 +Q = gamma / 2.0 # solve for the optimal policy -lq = QuantEcon.LQ(Q, R, A, B; bet=β) +lq = QuantEcon.LQ(Q, R, A, B; bet = beta) P, F, d = stationary_values(lq) # print the results -κ0, κ1 = -F[2], 1 - F[1] -println("κ0=$κ0\tκ1=$κ1") +kappa0 = -F[2] +kappa1 = 1 - F[1] +@show kappa0, kappa1; ``` ```{code-cell} julia @@ -849,8 +854,8 @@ println("κ0=$κ0\tκ1=$κ1") tags: [remove-cell] --- @testset begin - @test κ0 ≈ 95.081845248600 rtol = 4 - @test κ1 ≈ 0.952459076301 rtol = 4 + @test kappa0 ≈ 95.081845248600 rtol = 4 + @test kappa1 ≈ 0.952459076301 rtol = 4 end ``` @@ -876,18 +881,18 @@ The problem can be solved as follows A = I + zeros(2, 2) B = [1.0, 0.0] -R = [ a1 -a0 / 2.0 - -a0 / 2.0 0.0] +R = [a1 -a0/2.0 + -a0/2.0 0.0] -Q = γ / 2.0 +Q = gamma / 2.0 # solve for the optimal policy -lq = QuantEcon.LQ(Q, R, A, B; bet=β) +lq = QuantEcon.LQ(Q, R, A, B; bet = beta) P, F, d = stationary_values(lq) # print the results m0, m1 = -F[2], 1 - F[1] -println("m0=$m0\tm1=$m1") +@show m0, m1; ``` ```{code-cell} julia diff --git a/lectures/multi_agent_models/schelling.md b/lectures/multi_agent_models/schelling.md index 3ef8929a..3bfc53b9 100644 --- a/lectures/multi_agent_models/schelling.md +++ b/lectures/multi_agent_models/schelling.md @@ -8,7 +8,6 @@ kernelspec: language: julia name: julia-1.10 --- - (schelling)= ```{raw} html
@@ -148,7 +147,7 @@ using Test, Random ``` ```{code-cell} julia -using Parameters, Plots, LinearAlgebra, Statistics +using Plots, LinearAlgebra, Statistics ``` @@ -160,7 +159,7 @@ Random.seed!(42); ``` ```{code-cell} julia -Agent = @with_kw (kind, location = rand(2)) +Agent(; kind, location = rand(2)) = (; kind, location) draw_location!(a) = a.location .= rand(2) @@ -179,7 +178,7 @@ function is_happy(a) # partialsortperm(get_distance.(Ref(a), agents), # 1:neighborhood_size)) - return share ≥ preference + return share >= preference end function update!(a) @@ -205,7 +204,8 @@ function plot_distribution(agents) end end - p = scatter(x_vals_0, y_vals_0, color = :orange, markersize = 8, alpha = 0.6) + p = scatter(x_vals_0, y_vals_0, color = :orange, markersize = 8, + alpha = 0.6) scatter!(x_vals_1, y_vals_1, color = :green, markersize = 8, alpha = 0.6) return plot!(legend = :none) end diff --git a/lectures/multi_agent_models/uncertainty_traps.md b/lectures/multi_agent_models/uncertainty_traps.md index dbfc2343..b2a8d799 100644 --- a/lectures/multi_agent_models/uncertainty_traps.md +++ b/lectures/multi_agent_models/uncertainty_traps.md @@ -231,22 +231,26 @@ using Test, Random ```{code-cell} julia using LinearAlgebra, Statistics -using DataFrames, LaTeXStrings, Parameters, Plots +using DataFrames, LaTeXStrings, Plots ``` ```{code-cell} julia -UncertaintyTrapEcon = @with_kw (a = 1.5, # risk aversion - γ_x = 0.5, # production shock precision - ρ = 0.99, # correlation coefficient for θ - σ_θ = 0.5, # standard dev. of θ shock - num_firms = 100, # number of firms - σ_F = 1.5, # standard dev. of fixed costs - c = -420.0, # external opportunity cost - μ_init = 0.0, # initial value for μ - γ_init = 4.0, # initial value for γ - θ_init = 0.0, # initial value for θ - σ_x = sqrt(a / γ_x)) # standard dev. of shock +function # standard dev. of shock +UncertaintyTrapEcon(; a = 1.5, # risk aversion + gamma_x = 0.5, # production shock precision + rho = 0.99, # correlation coefficient for theta + sigma_theta = 0.5, # standard dev. of theta shock + num_firms = 100, # number of firms + sigma_F = 1.5, # standard dev. of fixed costs + c = -420.0, # external opportunity cost + mu_init = 0.0, # initial value for mu + gamma_init = 4.0, # initial value for gamma + theta_init = 0.0, # initial value for theta + sigma_x = sqrt(a / gamma_x)) # standard dev. of shock + (; a, gamma_x, rho, sigma_theta, num_firms, sigma_F, c, mu_init, gamma_init, + theta_init, sigma_x) +end ``` In the results below we use this code to simulate time series for the major variables. @@ -360,18 +364,19 @@ different values of $M$ ```{code-cell} julia econ = UncertaintyTrapEcon() -@unpack ρ, σ_θ, γ_x = econ # simplify names +(; rho, sigma_theta, gamma_x) = econ # simplify names -# grid for γ and γ_{t+1} -γ = range(1e-10, 3, length = 200) +# grid for gamma and gamma_{t+1} +gamma = range(1e-10, 3, length = 200) M_range = 0:6 -γp = 1 ./ (ρ^2 ./ (γ .+ γ_x .* M_range') .+ σ_θ^2) +gammap = 1 ./ (rho^2 ./ (gamma .+ gamma_x .* M_range') .+ sigma_theta^2) labels = ["0" "1" "2" "3" "4" "5" "6"] -plot(γ, γ, lw = 2, label = "45 Degree") -plot!(γ, γp, lw = 2, label = labels) -plot!(xlabel = L"\gamma", ylabel = L"\gamma^\prime", legend_title = L"M", legend = :bottomright) +plot(gamma, gamma, lw = 2, label = "45 Degree") +plot!(gamma, gammap, lw = 2, label = labels) +plot!(xlabel = L"\gamma", ylabel = L"\gamma^\prime", legend_title = L"M", + legend = :bottomright) ``` ```{code-cell} julia @@ -379,9 +384,9 @@ plot!(xlabel = L"\gamma", ylabel = L"\gamma^\prime", legend_title = L"M", legend tags: [remove-cell] --- @testset begin - @test γp[2,2] ≈ 0.46450522950184053 - @test γp[3,3] ≈ 0.8323524432613787 - @test γp[5,5] ≈ 1.3779664509290432 + @test gammap[2,2] ≈ 0.46450522950184053 + @test gammap[3,3] ≈ 0.8323524432613787 + @test gammap[5,5] ≈ 1.3779664509290432 end ``` @@ -396,49 +401,53 @@ is, the number of active firms and average output ```{code-cell} julia function simulate(uc, capT = 2_000) # unpack parameters - @unpack a, γ_x, ρ, σ_θ, num_firms, σ_F, c, μ_init, γ_init, θ_init, σ_x = uc + (; a, gamma_x, rho, sigma_theta, num_firms, sigma_F, c, mu_init, gamma_init, theta_init, sigma_x) = uc # draw standard normal shocks w_shocks = randn(capT) # aggregate functions - # auxiliary function ψ - function ψ(γ, μ, F) - temp1 = -a * (μ - F) - temp2 = 0.5 * a^2 / (γ + γ_x) + # auxiliary function psi + function psi(gamma, mu, F) + temp1 = -a * (mu - F) + temp2 = 0.5 * a^2 / (gamma + gamma_x) return (1 - exp(temp1 + temp2)) / a - c end # compute X, M - function gen_aggregates(γ, μ, θ) - F_vals = σ_F * randn(num_firms) - M = sum(ψ.(Ref(γ), Ref(μ), F_vals) .> 0) # counts number of active firms - if any(ψ(γ, μ, f) > 0 for f in F_vals) # ∃ an active firm - x_vals = θ .+ σ_x * randn(M) + function gen_aggregates(gamma, mu, theta) + F_vals = sigma_F * randn(num_firms) + M = sum(psi.(Ref(gamma), Ref(mu), F_vals) .> 0) # counts number of active firms + if any(psi(gamma, mu, f) > 0 for f in F_vals) # there is an active firm + x_vals = theta .+ sigma_x * randn(M) X = mean(x_vals) else X = 0.0 end - return (X = X, M = M) + return (; X, M) end # initialize dataframe - X_init, M_init = gen_aggregates(γ_init, μ_init, θ_init) - df = DataFrame(γ = γ_init, μ = μ_init, θ = θ_init, X = X_init, M = M_init) + X_init, M_init = gen_aggregates(gamma_init, mu_init, theta_init) + df = DataFrame(gamma = gamma_init, mu = mu_init, theta = theta_init, + X = X_init, M = M_init) # update dataframe for t in 2:capT # unpack old variables - θ_old, γ_old, μ_old, X_old, M_old = (df.θ[end], df.γ[end], df.μ[end], df.X[end], df.M[end]) + theta_old, gamma_old, mu_old, X_old, M_old = (df.theta[end], + df.gamma[end], df.mu[end], + df.X[end], df.M[end]) # define new beliefs - θ = ρ * θ_old + σ_θ * w_shocks[t-1] - μ = (ρ * (γ_old * μ_old + M_old * γ_x * X_old))/(γ_old + M_old * γ_x) - γ = 1 / (ρ^2 / (γ_old + M_old * γ_x) + σ_θ^2) + theta = rho * theta_old + sigma_theta * w_shocks[t - 1] + mu = (rho * (gamma_old * mu_old + M_old * gamma_x * X_old)) / + (gamma_old + M_old * gamma_x) + gamma = 1 / (rho^2 / (gamma_old + M_old * gamma_x) + sigma_theta^2) # compute new aggregates - X, M = gen_aggregates(γ, μ, θ) - push!(df, (γ = γ, μ = μ, θ = θ, X = X, M = M)) + X, M = gen_aggregates(gamma, mu, theta) + push!(df, (; gamma, mu, theta, X, M)) end # return @@ -459,19 +468,20 @@ Random.seed!(42); # set random seed for reproducible results ```{code-cell} julia df = simulate(econ) -plot(eachindex(df.μ), df.μ, lw = 2, label = L"\mu") -plot!(eachindex(df.θ), df.θ, lw = 2, label = L"\theta") -plot!(xlabel = L"x", ylabel = L"y", legend_title = "Variable", legend = :bottomright) +plot(eachindex(df.mu), df.mu, lw = 2, label = L"\mu") +plot!(eachindex(df.theta), df.theta, lw = 2, label = L"\theta") +plot!(xlabel = L"x", ylabel = L"y", legend_title = "Variable", + legend = :bottomright) ``` Now let's plot the whole thing together ```{code-cell} julia -len = eachindex(df.θ) -yvals = [df.θ, df.μ, df.γ, df.M] +len = eachindex(df.theta) +yvals = [df.theta, df.mu, df.gamma, df.M] vars = [L"\theta", L"\mu", L"\gamma", L"M"] -plt = plot(layout = (4,1), size = (600, 600)) +plt = plot(layout = (4, 1), size = (600, 600)) for i in 1:4 plot!(plt[i], len, yvals[i], xlabel = L"t", ylabel = vars[i], label = "") @@ -484,7 +494,7 @@ plot(plt) --- tags: [remove-cell] --- -mdf = DataFrame(t = eachindex(df.θ), θ = df.θ, μ = df.μ, γ = df.γ, M = df.M) +mdf = DataFrame(t = eachindex(df.theta), theta = df.theta, mu = df.mu, gamma = df.gamma, M = df.M) @testset begin @test stack(mdf, collect(2:5))[:value][3] ≈ -0.49742498224730913 atol = 1e-3 diff --git a/lectures/tools_and_techniques/numerical_linear_algebra.md b/lectures/tools_and_techniques/numerical_linear_algebra.md index f4cda6f9..b4f81c25 100644 --- a/lectures/tools_and_techniques/numerical_linear_algebra.md +++ b/lectures/tools_and_techniques/numerical_linear_algebra.md @@ -54,7 +54,7 @@ The theme of this lecture, and numerical linear algebra in general, comes down t --- tags: [hide-output] --- -using LinearAlgebra, Statistics, BenchmarkTools, SparseArrays, Random, Parameters +using LinearAlgebra, Statistics, BenchmarkTools, SparseArrays, Random Random.seed!(42); # seed random numbers for reproducibility ``` @@ -491,14 +491,11 @@ To manually use the QR decomposition in solving linear least squares: ```{code-cell} julia Af = qr(A) -Q = Af.Q -R = [Af.R; zeros(N - M, M)] # Stack with zeros -@show Q * R ≈ A -x = R \ Matrix(Q)' * b # simplified QR solution for least squares +@show Af.Q * Af.R ≈ A +x = Af.R \ (Matrix(Af.Q)' * b) # simplified QR solution for least squares ``` -This stacks the `R` with zeros, but the more specialized algorithm would not multiply directly -in that way. +See [here](https://discourse.julialang.org/t/qr-decomposition-with-julia-how-to/92508/8) for more, thought keep in mind that more specialized algorithm would be more efficient. In some cases, if an LU is not available for a particular matrix structure, the QR factorization can also be used to solve systems of equations (i.e., not just LLS). This tends to be about 2 times slower than the LU From fb08ab2f1347e45aa87c66734f6570fc6100d6f0 Mon Sep 17 00:00:00 2001 From: annabellasd Date: Mon, 25 Sep 2023 20:20:43 -0800 Subject: [PATCH 16/26] updated lectures --- lectures/continuous_time/covid_sde.md | 121 +++++++++++++------------ lectures/continuous_time/seir_model.md | 81 +++++++++-------- 2 files changed, 103 insertions(+), 99 deletions(-) diff --git a/lectures/continuous_time/covid_sde.md b/lectures/continuous_time/covid_sde.md index 9ba314db..5020de7d 100644 --- a/lectures/continuous_time/covid_sde.md +++ b/lectures/continuous_time/covid_sde.md @@ -230,40 +230,41 @@ First, construct our $F$ from {eq}`dfcvsde` and $G$ from {eq}`dG` ```{code-cell} julia function F(x, p, t) - s, i, r, d, R₀, δ = x - (;γ, R̄₀, η, σ, ξ, θ, δ_bar) = p - - return [-γ*R₀*s*i; # ds/dt - γ*R₀*s*i - γ*i; # di/dt - (1-δ)*γ*i; # dr/dt - δ*γ*i; # dd/dt - η*(R̄₀(t, p) - R₀);# dR₀/dt - θ*(δ_bar - δ); # dδ/dt - ] + s, i, r, d, R_0, delta = x + (; gamma, R_bar_0, eta, sigma, xi, theta, delta_bar) = p + + return [-gamma * R_0 * s * i; # ds/dt + gamma * R_0 * s * i - gamma * i; # di/dt + (1 - delta) * gamma * i; # dr/dt + delta * gamma * i; # dd/dt + eta * (R_bar_0(t, p) - R_0); # dR_0/dt + theta * (delta_bar - delta); # ddelta/dt + ] end function G(x, p, t) - s, i, r, d, R₀, δ = x - (;γ, R̄₀, η, σ, ξ, θ, δ_bar) = p + s, i, r, d, R_0, delta = x + (; gamma, R_bar_0, eta, sigma, xi, theta, delta_bar) = p - return [0; 0; 0; 0; σ*sqrt(R₀); ξ*sqrt(δ * (1-δ))] + return [0; 0; 0; 0; sigma * sqrt(R_0); xi * sqrt(delta * (1 - delta))] end ``` Next create a settings generator, and then define a [SDEProblem](https://docs.sciml.ai/stable/tutorials/sde_example/#Example-2:-Systems-of-SDEs-with-Diagonal-Noise-1) with Diagonal Noise. ```{code-cell} julia -p_gen = @with_kw (T = 550.0, γ = 1.0 / 18, η = 1.0 / 20, - R₀_n = 1.6, R̄₀ = (t, p) -> p.R₀_n, δ_bar = 0.01, - σ = 0.03, ξ = 0.004, θ = 0.2, N = 3.3E8) -p = p_gen() # use all defaults +p_gen(; T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, + R_0_n = 1.6, R_bar_0 = (t, p) -> p.R_0_n, delta_bar = 0.01, + sigma = 0.03, xi = 0.004, theta = 0.2, N = 3.3E8) = (; T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N) + +p = p_gen() # use all defaults i_0 = 25000 / p.N r_0 = 0.0 d_0 = 0.0 s_0 = 1.0 - i_0 - r_0 - d_0 -R̄₀_0 = 0.5 # starting in lockdown -δ_0 = p.δ_bar -x_0 = [s_0, i_0, r_0, d_0, R̄₀_0, δ_0] +R_bar_0_0 = 0.5 # starting in lockdown +delta_0 = p.delta_bar +x_0 = [s_0, i_0, r_0, d_0, R_bar_0_0, delta_0] prob = SDEProblem(F, G, x_0, (0, p.T), p) ``` @@ -370,29 +371,29 @@ We will shut down the shocks to the mortality rate (i.e. $\xi = 0$) to focus on Consider $\eta = 1/50$ and $\eta = 1/20$, where we start at the same initial condition of $R_0(0) = 0.5$. ```{code-cell} julia -function generate_η_experiment(η; p_gen = p_gen, trajectories = 100, - saveat = 1.0, x_0 = x_0, T = 120.0) - p = p_gen(η = η, ξ = 0.0) +function generate_eta_experiment(eta; p_gen, trajectories = 100, saveat = 1.0, x_0, T = 120.0) + p = p_gen(eta = eta, xi = 0.0) ensembleprob = EnsembleProblem(SDEProblem(F, G, x_0, (0, T), p)) - sol = solve(ensembleprob, SOSRI(), EnsembleThreads(), - trajectories = trajectories, saveat = saveat) + sol = solve(ensembleprob, SOSRI(), EnsembleThreads(), trajectories = trajectories, saveat = saveat) return EnsembleSummary(sol) end # Evaluate two different lockdown scenarios -η_1 = 1/50 -η_2 = 1/20 -summ_1 = generate_η_experiment(η_1) -summ_2 = generate_η_experiment(η_2) -plot(summ_1, idxs = (4,5), +eta_1 = 1 / 50 +eta_2 = 1 / 20 +summ_1 = generate_eta_experiment(eta_1) +summ_2 = generate_eta_experiment(eta_2) + +plot(summ_1, idxs = (4, 5), title = ["Proportion Dead" L"R_0"], ylabel = [L"d(t)" L"R_0(t)"], xlabel = L"t", legend = [:topleft :bottomright], - labels = L"Middle 95% Quantile, $\eta = %$η_1$", + labels = L"Middle 95% Quantile, $\eta = %$eta_1$", layout = (2, 1), size = (900, 900), fillalpha = 0.5) -plot!(summ_2, idxs = (4,5), + +plot!(summ_2, idxs = (4, 5), legend = [:topleft :bottomright], - labels = L"Middle 95% Quantile, $\eta = %$η_2$", size = (900, 900), fillalpha = 0.5) + labels = L"Middle 95% Quantile, $\eta = %$eta_2$", size = (900, 900), fillalpha = 0.5) ``` While the the mean of the $d(t)$ increases, unsurprisingly, we see that the 95% quantile for later time periods is also much larger - even after the $R_0$ has converged. @@ -411,24 +412,24 @@ Since empirical estimates of $R_0(t)$ discussed in {cite}`NBERw27128` and other We start the model with 100,000 active infections. ```{code-cell} julia -R₀_L = 0.5 # lockdown -η_experiment = 1.0/10 -σ_experiment = 0.04 -R̄₀_lift_early(t, p) = t < 30.0 ? R₀_L : 2.0 -R̄₀_lift_late(t, p) = t < 120.0 ? R₀_L : 2.0 +R_0_L = 0.5 # lockdown +eta_experiment = 1.0 / 10 +sigma_experiment = 0.04 -p_early = p_gen(R̄₀ = R̄₀_lift_early, η = η_experiment, σ = σ_experiment) -p_late = p_gen(R̄₀ = R̄₀_lift_late, η = η_experiment, σ = σ_experiment) +R_bar_0_lift_early(t, p) = t < 30.0 ? R_0_L : 2.0 +R_bar_0_lift_late(t, p) = t < 120.0 ? R_0_L : 2.0 +p_early = p_gen(R_bar_0 = R_bar_0_lift_early, eta = eta_experiment, sigma = sigma_experiment) +p_late = p_gen(R_bar_0 = R_bar_0_lift_late, eta = eta_experiment, sigma = sigma_experiment) # initial conditions i_0 = 100000 / p_early.N r_0 = 0.0 d_0 = 0.0 s_0 = 1.0 - i_0 - r_0 - d_0 -δ_0 = p_early.δ_bar +delta_0 = p_early.delta_bar -x_0 = [s_0, i_0, r_0, d_0, R₀_L, δ_0] # start in lockdown +x_0 = [s_0, i_0, r_0, d_0, R_0_L, delta_0] # start in lockdown prob_early = SDEProblem(F, G, x_0, (0, p_early.T), p_early) prob_late = SDEProblem(F, G, x_0, (0, p_late.T), p_late) ``` @@ -438,13 +439,13 @@ Simulating for a single realization of the shocks, we see the results are qualit ```{code-cell} julia sol_early = solve(prob_early, SOSRI()) sol_late = solve(prob_late, SOSRI()) -plot(sol_early, vars = [5, 1,2,4], +plot(sol_early, vars = [5, 1, 2, 4], title = [L"R_0" "Susceptible" "Infected" "Dead"], layout = (2, 2), size = (900, 600), ylabel = [L"R_0(t)" L"s(t)" L"i(t)" L"d(t)"], xlabel = L"t", legend = [:bottomright :topright :topright :topleft], label = ["Early" "Early" "Early" "Early"]) -plot!(sol_late, vars = [5, 1,2,4], +plot!(sol_late, vars = [5, 1, 2, 4], legend = [:bottomright :topright :topright :topleft], label = ["Late" "Late" "Late" "Late"], xlabel = L"t") ``` @@ -535,24 +536,26 @@ We will redo the "Ending Lockdown" simulation from above, where the only differe ```{code-cell} julia function F_reinfect(x, p, t) - s, i, r, d, R₀, δ = x - (;γ, R̄₀, η, σ, ξ, θ, δ_bar, ν) = p - - return [-γ*R₀*s*i + ν*r; # ds/dt - γ*R₀*s*i - γ*i; # di/dt - (1-δ)*γ*i - ν*r # dr/dt - δ*γ*i; # dd/dt - η*(R̄₀(t, p) - R₀);# dR₀/dt - θ*(δ_bar - δ); # dδ/dt - ] + s, i, r, d, R_0, delta = x + (;gamma, R_bar_0, eta, sigma, xi, theta, delta_bar, nu) = p + + return [ + -gamma * R_0 * s * i + nu * r; # ds/dt + gamma * R_0 * s * i - gamma * i; # di/dt + (1 - delta) * gamma * i - nu * r; # dr/dt + delta * gamma * i; # dd/dt + eta * (R_bar_0(t, p) - R_0); # dR_0/dt + theta * (delta_bar - delta); # ddelta/dt + ] end -p_re_gen = @with_kw ( T = 550.0, γ = 1.0 / 18, η = 1.0 / 20, - R₀_n = 1.6, R̄₀ = (t, p) -> p.R₀_n, - δ_bar = 0.01, σ = 0.03, ξ = 0.004, θ = 0.2, N = 3.3E8, ν = 1/360) +p_re_gen(; T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, + R_0_n = 1.6, R_bar_0 = (t, p) -> p.R_0_n, + delta_bar = 0.01, sigma = 0.03, xi = 0.004, theta = 0.2, + N = 3.3E8, nu = 1/360) = (; T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N, nu) -p_re_early = p_re_gen(R̄₀ = R̄₀_lift_early, η = η_experiment, σ = σ_experiment) -p_re_late = p_re_gen(R̄₀ = R̄₀_lift_late, η = η_experiment, σ = σ_experiment) +p_re_early = p_re_gen(R_bar_0 = R_bar_0 _lift_early, eta = eta_experiment, sigma = sigma_experiment) +p_re_late = p_re_gen(R_bar_0 = R_bar_0 _lift_late, eta = eta_experiment, sigma = sigma_experiment) trajectories = 400 saveat = 1.0 diff --git a/lectures/continuous_time/seir_model.md b/lectures/continuous_time/seir_model.md index c0a36aa9..ea698d06 100644 --- a/lectures/continuous_time/seir_model.md +++ b/lectures/continuous_time/seir_model.md @@ -171,13 +171,13 @@ We begin by implementing a simple version of this model with a constant $R_0$ an First, define the system of equations ```{code-cell} julia -function F_simple(x, p, t; γ = 1/18, R₀ = 3.0, σ = 1/5.2) +function F_simple(x, p, t; gamma = 1/18, R_0 = 3.0, sigma = 1/5.2) s, e, i, r = x - return [-γ*R₀*s*i; # ds/dt = -γR₀si - γ*R₀*s*i - σ*e;# de/dt = γR₀si -σe - σ*e - γ*i; # di/dt = σe -γi - γ*i; # dr/dt = γi + return [-gamma * R_0 * s * i; # ds/dt + gamma * R_0 * s * i - sigma * e; # de/dt + sigma * e - gamma * i; # di/dt + gamma * i; # dr/dt ] end ``` @@ -195,7 +195,7 @@ tspan = (0.0, 350.0) # ≈ 350 days prob = ODEProblem(F_simple, x_0, tspan) ``` -With this, choose an ODE algorithm and solve the initial value problem. A good default algorithm for non-stiff ODEs of this sort might be `Tsit5()`, which is the Tsitouras 5/4 Runge-Kutta method). +With this, choose an ODE algorithm and solve the initial value problem. A good default algorithm for non-stiff ODEs of this sort might be `Tsit5()`, which is the Tsitouras 5/4 Runge-Kutta method. ```{code-cell} julia sol = solve(prob, Tsit5()) @@ -242,7 +242,7 @@ While we could integrate the deaths given the solution to the model ex-post, it This is a common trick when solving systems of ODEs. While equivalent in principle to using the appropriate quadrature scheme, this becomes especially convenient when adaptive time-stepping algorithms are used to solve the ODEs (i.e. there is not a regular time grid). Note that when doing so, $d(0) = \int_0^0 \delta \gamma i(\tau) d \tau = 0$ is the initial condition. -The system {eq}`seir_system` and the supplemental equations can be written in vector form $x := [s, e, i, r, R₀, c, d]$ with parameter tuple $p := (\sigma, \gamma, \eta, \delta, \bar{R}_0(\cdot))$ +The system {eq}`seir_system` and the supplemental equations can be written in vector form $x := [s, e, i, r, R_0, c, d]$ with parameter tuple $p := (\sigma, \gamma, \eta, \delta, \bar{R}_0(\cdot))$ Note that in those parameters, the targeted reproduction number, $\bar{R}_0(t)$, is an exogenous function. @@ -289,35 +289,36 @@ First, construct our $F$ from {eq}`dfcv` ```{code-cell} julia function F(x, p, t) - s, e, i, r, R₀, c, d = x - (;σ, γ, R̄₀, η, δ) = p - - return [-γ*R₀*s*i; # ds/dt - γ*R₀*s*i - σ*e; # de/dt - σ*e - γ*i; # di/dt - γ*i; # dr/dt - η*(R̄₀(t, p) - R₀);# dR₀/dt - σ*e; # dc/dt - δ*γ*i; # dd/dt + s, e, i, r, R_0, c, d = x + (;sigma, gamma, R_0_bar, eta, delta) = p + + return [-gamma * R_0 * s * i; # ds/dt + gamma * R_0 * s * i - sigma * e; # de/dt + sigma * e - γ*i; # di/dt + gamma * i; # dr/dt + eta * (R_bar_0(t, p) - R_0); # dR_0/dt + sigma * e; # dc/dt + delta * gamma * i; # dd/dt ] end; + ``` This function takes the vector `x` of states in the system and extracts the fixed parameters passed into the `p` object. -The only confusing part of the notation is the `R̄₀(t, p)` which evaluates the `p.R̄₀` at this time (and also allows it to depend on the `p` parameter). +The only confusing part of the notation is the `R_0(t, p)` which evaluates the `p.R_bar_0` at this time (and also allows it to depend on the `p` parameter). ### Parameters - +#####HERE ENDED The baseline parameters are put into a named tuple generator (see previous lectures using [Parameters.jl](https://github.com/mauro3/Parameters.jl)) with default values discussed above. ```{code-cell} julia -p_gen = @with_kw ( T = 550.0, γ = 1.0 / 18, σ = 1 / 5.2, η = 1.0 / 20, - R₀_n = 1.6, δ = 0.01, N = 3.3E8, - R̄₀ = (t, p) -> p.R₀_n); +p_gen(T = 550.0, gamma = 1.0 / 18, sigma = 1 / 5.2, eta = 1.0 / 20, + R_0_n = 1.6, delta = 0.01, N = 3.3E8, + R_0_bar = (t, p) -> p.R_0_n) = (T, gamma, sigma, eta, R_0_n, delta, N, R_0_bar) ``` -Note that the default $\bar{R}_0(t)$ function always equals $R_{0n}$ -- a parameterizable natural level of $R_0$ used only by the `R̄₀` function +Note that the default $\bar{R}_0(t)$ function always equals $R_{0n}$ -- a parameterizable natural level of $R_0$ used only by the `R_hat_0` function Setting initial conditions, we choose a fixed $s, i, e, r$, as well as $R_0(0) = R_{0n}$ and $m(0) = 0.01$ @@ -328,7 +329,7 @@ i_0 = 1E-7 e_0 = 4.0 * i_0 s_0 = 1.0 - i_0 - e_0 -x_0 = [s_0, e_0, i_0, 0.0, p.R₀_n, 0.0, 0.0] +x_0 = [s_0, e_0, i_0, 0.0, p.R_0_n, 0.0, 0.0] tspan = (0.0, p.T) prob = ODEProblem(F, x_0, tspan, p) ``` @@ -372,9 +373,9 @@ Let's start with the case where $\bar{R}_0(t) = R_{0n}$ is constant. We calculate the time path of infected people under different assumptions of $R_{0n}$: ```{code-cell} julia -R₀_n_vals = range(1.6, 3.0, length = 6) -sols = [solve(ODEProblem(F, x_0, tspan, p_gen(R₀_n = R₀_n)), - Tsit5(), saveat=0.5) for R₀_n in R₀_n_vals]; +R_0_n_vals = range(1.6, 3.0, length = 6) +sols = [solve(ODEProblem(F, x_0, tspan, p_gen(R_0_n = R_0_n)), + Tsit5(), saveat=0.5) for R_0_n in R_0_n_vals]; ``` Here we chose `saveat=0.5` to get solutions that were evenly spaced every `0.5`. @@ -384,7 +385,7 @@ Changing the saved points is just a question of storage/interpolation, and does Let's plot current cases as a fraction of the population. ```{code-cell} julia -labels = permutedims([L"R_0 = %$r" for r in R₀_n_vals]) +labels = permutedims([L"R_0 = %$r" for r in R_0_n_vals]) infecteds = [sol[3,:] for sol in sols] plot(infecteds, label=labels, legend=:topleft, lw = 2, xlabel = L"t", ylabel = L"i(t)", title = "Current Cases") @@ -413,21 +414,21 @@ In the simple case, where $\bar{R}_0(t) = R_{0n}$ is independent of the state, t We will examine the case where $R_0(0) = 3$ and then it falls to $R_{0n} = 1.6$ due to the progressive adoption of stricter mitigation measures. -The parameter `η` controls the rate, or the speed at which restrictions are +The parameter `eta` controls the rate, or the speed at which restrictions are imposed. We consider several different rates: ```{code-cell} julia -η_vals = [1/5, 1/10, 1/20, 1/50, 1/100] -labels = permutedims([L"\eta = %$η" for η in η_vals]); +eta_vals = [1/5, 1/10, 1/20, 1/50, 1/100] +labels = permutedims([L"\eta = %$eta" for eta in eta_vals]); ``` Let's calculate the time path of infected people, current cases, and mortality ```{code-cell} julia x_0 = [s_0, e_0, i_0, 0.0, 3.0, 0.0, 0.0] -sols = [solve(ODEProblem(F, x_0, tspan, p_gen(η=η)), Tsit5(), saveat=0.5) for η in η_vals]; +sols = [solve(ODEProblem(F, x_0, tspan, p_gen(eta=eta)), Tsit5(), saveat=0.5) for eta in eta_vals]; ``` Next, plot the $R_0$ over time: @@ -468,11 +469,11 @@ The parameters considered here start the model with 25,000 active infections and 75,000 agents already exposed to the virus and thus soon to be contagious. ```{code-cell} julia -R₀_L = 0.5 # lockdown -R̄₀_lift_early(t, p) = t < 30.0 ? R₀_L : 2.0 -R̄₀_lift_late(t, p) = t < 120.0 ? R₀_L : 2.0 -p_early = p_gen(R̄₀= R̄₀_lift_early, η = 10.0) -p_late = p_gen(R̄₀= R̄₀_lift_late, η = 10.0) +R_0_L = 0.5 # lockdown +R_bar_0_lift_early(t, p) = t < 30.0 ? R_0_L : 2.0 +R_bar_0_lift_late(t, p) = t < 120.0 ? R_0_L : 2.0 +p_early = p_gen(R_bar_0= R_bar_0_lift_early, eta = 10.0) +p_late = p_gen(R_bar_0= R_bar_0_lift_late, eta = 10.0) # initial conditions @@ -480,9 +481,9 @@ i_0 = 25000 / p_early.N e_0 = 75000 / p_early.N s_0 = 1.0 - i_0 - e_0 -x_0 = [s_0, e_0, i_0, 0.0, R₀_L, 0.0, 0.0] # start in lockdown +x_0 = [s_0, e_0, i_0, 0.0, R_0_L, 0.0, 0.0] # start in lockdown -# create two problems, with rapid movement of R₀(t) towards R̄₀(t) +# create two problems, with rapid movement of R_0(t) towards R_hat_0(t) prob_early = ODEProblem(F, x_0, tspan, p_early) prob_late = ODEProblem(F, x_0, tspan, p_late) ``` @@ -501,7 +502,7 @@ plot!(sol_late, vars = [7], label = "Lift Late", xlabel = L"t") Next we examine the daily deaths, $\frac{d D(t)}{dt} = N \delta \gamma i(t)$. ```{code-cell} julia -flow_deaths(sol, p) = p.N * p.δ * p.γ * sol[3,:] +flow_deaths(sol, p) = p.N * p.delta * p.gamma * sol[3,:] plot(sol_early.t, flow_deaths(sol_early, p_early), title = "Flow Deaths", label = "Lift Early") plot!(sol_late.t, flow_deaths(sol_late, p_late), label = "Lift Late", xlabel = L"t") From 6771b78f0a11dca2838c2567f5f531cd8dee3957 Mon Sep 17 00:00:00 2001 From: annabellasd Date: Mon, 25 Sep 2023 20:27:31 -0800 Subject: [PATCH 17/26] Update seir_model.md --- lectures/continuous_time/seir_model.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lectures/continuous_time/seir_model.md b/lectures/continuous_time/seir_model.md index ea698d06..f5c9dd92 100644 --- a/lectures/continuous_time/seir_model.md +++ b/lectures/continuous_time/seir_model.md @@ -294,7 +294,7 @@ function F(x, p, t) return [-gamma * R_0 * s * i; # ds/dt gamma * R_0 * s * i - sigma * e; # de/dt - sigma * e - γ*i; # di/dt + sigma * e - gamma * i; # di/dt gamma * i; # dr/dt eta * (R_bar_0(t, p) - R_0); # dR_0/dt sigma * e; # dc/dt From 68c3dc7b32aa36b5c1f2f2bfc5c492ca13ede671 Mon Sep 17 00:00:00 2001 From: annabellasd Date: Thu, 28 Sep 2023 12:50:20 -0800 Subject: [PATCH 18/26] update --- lectures/continuous_time/covid_sde.md | 2 +- lectures/continuous_time/seir_model.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lectures/continuous_time/covid_sde.md b/lectures/continuous_time/covid_sde.md index 5020de7d..d22f3e76 100644 --- a/lectures/continuous_time/covid_sde.md +++ b/lectures/continuous_time/covid_sde.md @@ -371,7 +371,7 @@ We will shut down the shocks to the mortality rate (i.e. $\xi = 0$) to focus on Consider $\eta = 1/50$ and $\eta = 1/20$, where we start at the same initial condition of $R_0(0) = 0.5$. ```{code-cell} julia -function generate_eta_experiment(eta; p_gen, trajectories = 100, saveat = 1.0, x_0, T = 120.0) +function generate_eta_experiment(eta; p_gen = p_gen, trajectories = 100, saveat = 1.0, x_0 = x_0, T = 120.0) p = p_gen(eta = eta, xi = 0.0) ensembleprob = EnsembleProblem(SDEProblem(F, G, x_0, (0, T), p)) sol = solve(ensembleprob, SOSRI(), EnsembleThreads(), trajectories = trajectories, saveat = saveat) diff --git a/lectures/continuous_time/seir_model.md b/lectures/continuous_time/seir_model.md index f5c9dd92..1d4a2549 100644 --- a/lectures/continuous_time/seir_model.md +++ b/lectures/continuous_time/seir_model.md @@ -290,7 +290,7 @@ First, construct our $F$ from {eq}`dfcv` ```{code-cell} julia function F(x, p, t) s, e, i, r, R_0, c, d = x - (;sigma, gamma, R_0_bar, eta, delta) = p + (;sigma, gamma, R_bar_0, eta, delta) = p return [-gamma * R_0 * s * i; # ds/dt gamma * R_0 * s * i - sigma * e; # de/dt @@ -313,9 +313,9 @@ The only confusing part of the notation is the `R_0(t, p)` which evaluates the ` The baseline parameters are put into a named tuple generator (see previous lectures using [Parameters.jl](https://github.com/mauro3/Parameters.jl)) with default values discussed above. ```{code-cell} julia -p_gen(T = 550.0, gamma = 1.0 / 18, sigma = 1 / 5.2, eta = 1.0 / 20, +p_gen(;T = 550.0, gamma = 1.0 / 18, sigma = 1 / 5.2, eta = 1.0 / 20, R_0_n = 1.6, delta = 0.01, N = 3.3E8, - R_0_bar = (t, p) -> p.R_0_n) = (T, gamma, sigma, eta, R_0_n, delta, N, R_0_bar) + R_bar_0 = (t, p) -> p.R_0_n) = (;T, gamma, sigma, eta, R_0_n, delta, N, R_bar_0) ``` Note that the default $\bar{R}_0(t)$ function always equals $R_{0n}$ -- a parameterizable natural level of $R_0$ used only by the `R_hat_0` function From 0684e1bd0732ba5cd59fa091ab802aa624347567 Mon Sep 17 00:00:00 2001 From: annabellasd Date: Thu, 28 Sep 2023 18:04:25 -0800 Subject: [PATCH 19/26] Update covid_sde.md --- lectures/continuous_time/covid_sde.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lectures/continuous_time/covid_sde.md b/lectures/continuous_time/covid_sde.md index d22f3e76..28f8a1a5 100644 --- a/lectures/continuous_time/covid_sde.md +++ b/lectures/continuous_time/covid_sde.md @@ -554,8 +554,8 @@ p_re_gen(; T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, delta_bar = 0.01, sigma = 0.03, xi = 0.004, theta = 0.2, N = 3.3E8, nu = 1/360) = (; T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N, nu) -p_re_early = p_re_gen(R_bar_0 = R_bar_0 _lift_early, eta = eta_experiment, sigma = sigma_experiment) -p_re_late = p_re_gen(R_bar_0 = R_bar_0 _lift_late, eta = eta_experiment, sigma = sigma_experiment) +p_re_early = p_re_gen(R_bar_0 = R_bar_0_lift_early, eta = eta_experiment, sigma = sigma_experiment) +p_re_late = p_re_gen(R_bar_0 = R_bar_0_lift_late, eta = eta_experiment, sigma = sigma_experiment) trajectories = 400 saveat = 1.0 From 3ccec392724e4d6f69fcbe9ba72686d42a508671 Mon Sep 17 00:00:00 2001 From: annabellasd Date: Wed, 4 Oct 2023 20:36:52 -0800 Subject: [PATCH 20/26] Update covid_sde.md --- lectures/continuous_time/covid_sde.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lectures/continuous_time/covid_sde.md b/lectures/continuous_time/covid_sde.md index 28f8a1a5..7fd14170 100644 --- a/lectures/continuous_time/covid_sde.md +++ b/lectures/continuous_time/covid_sde.md @@ -387,12 +387,12 @@ summ_2 = generate_eta_experiment(eta_2) plot(summ_1, idxs = (4, 5), title = ["Proportion Dead" L"R_0"], ylabel = [L"d(t)" L"R_0(t)"], xlabel = L"t", - legend = [:topleft :bottomright], + legend = :topleft, labels = L"Middle 95% Quantile, $\eta = %$eta_1$", layout = (2, 1), size = (900, 900), fillalpha = 0.5) plot!(summ_2, idxs = (4, 5), - legend = [:topleft :bottomright], + legend = :topleft, labels = L"Middle 95% Quantile, $\eta = %$eta_2$", size = (900, 900), fillalpha = 0.5) ``` From 909c87931f1cf08a15cae532db243cf310d2315c Mon Sep 17 00:00:00 2001 From: annabellasd Date: Thu, 5 Oct 2023 20:54:04 -0800 Subject: [PATCH 21/26] spacing updates --- lectures/continuous_time/covid_sde.md | 22 +++++++++++----------- lectures/continuous_time/seir_model.md | 14 +++++++------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lectures/continuous_time/covid_sde.md b/lectures/continuous_time/covid_sde.md index 7fd14170..6f685e16 100644 --- a/lectures/continuous_time/covid_sde.md +++ b/lectures/continuous_time/covid_sde.md @@ -231,20 +231,20 @@ First, construct our $F$ from {eq}`dfcvsde` and $G$ from {eq}`dG` ```{code-cell} julia function F(x, p, t) s, i, r, d, R_0, delta = x - (; gamma, R_bar_0, eta, sigma, xi, theta, delta_bar) = p + (;gamma, R_bar_0, eta, sigma, xi, theta, delta_bar) = p return [-gamma * R_0 * s * i; # ds/dt gamma * R_0 * s * i - gamma * i; # di/dt - (1 - delta) * gamma * i; # dr/dt - delta * gamma * i; # dd/dt + (1 - delta) * gamma * i; # dr/dt + delta * gamma * i; # dd/dt eta * (R_bar_0(t, p) - R_0); # dR_0/dt - theta * (delta_bar - delta); # ddelta/dt + theta * (delta_bar - delta); # ddelta/dt ] end function G(x, p, t) s, i, r, d, R_0, delta = x - (; gamma, R_bar_0, eta, sigma, xi, theta, delta_bar) = p + (;gamma, R_bar_0, eta, sigma, xi, theta, delta_bar) = p return [0; 0; 0; 0; sigma * sqrt(R_0); xi * sqrt(delta * (1 - delta))] end @@ -253,9 +253,9 @@ end Next create a settings generator, and then define a [SDEProblem](https://docs.sciml.ai/stable/tutorials/sde_example/#Example-2:-Systems-of-SDEs-with-Diagonal-Noise-1) with Diagonal Noise. ```{code-cell} julia -p_gen(; T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, +p_gen(;T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, R_0_n = 1.6, R_bar_0 = (t, p) -> p.R_0_n, delta_bar = 0.01, - sigma = 0.03, xi = 0.004, theta = 0.2, N = 3.3E8) = (; T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N) + sigma = 0.03, xi = 0.004, theta = 0.2, N = 3.3E8) = (;T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N) p = p_gen() # use all defaults i_0 = 25000 / p.N @@ -549,13 +549,13 @@ function F_reinfect(x, p, t) ] end -p_re_gen(; T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, +p_re_gen(;T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, R_0_n = 1.6, R_bar_0 = (t, p) -> p.R_0_n, delta_bar = 0.01, sigma = 0.03, xi = 0.004, theta = 0.2, - N = 3.3E8, nu = 1/360) = (; T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N, nu) + N = 3.3E8, nu = 1/360) = (;T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N, nu) -p_re_early = p_re_gen(R_bar_0 = R_bar_0_lift_early, eta = eta_experiment, sigma = sigma_experiment) -p_re_late = p_re_gen(R_bar_0 = R_bar_0_lift_late, eta = eta_experiment, sigma = sigma_experiment) +p_re_early = p_re_gen(R_bar_0 = R_bar_0_lift_early, eta = eta_experiment, sigma = sigma_experiment) +p_re_late = p_re_gen(R_bar_0 = R_bar_0_lift_late, eta = eta_experiment, sigma = sigma_experiment) trajectories = 400 saveat = 1.0 diff --git a/lectures/continuous_time/seir_model.md b/lectures/continuous_time/seir_model.md index 1d4a2549..b40418c8 100644 --- a/lectures/continuous_time/seir_model.md +++ b/lectures/continuous_time/seir_model.md @@ -293,8 +293,8 @@ function F(x, p, t) (;sigma, gamma, R_bar_0, eta, delta) = p return [-gamma * R_0 * s * i; # ds/dt - gamma * R_0 * s * i - sigma * e; # de/dt - sigma * e - gamma * i; # di/dt + gamma * R_0 * s * i - sigma * e; # de/dt + sigma * e - gamma * i; # di/dt gamma * i; # dr/dt eta * (R_bar_0(t, p) - R_0); # dR_0/dt sigma * e; # dc/dt @@ -306,7 +306,7 @@ end; This function takes the vector `x` of states in the system and extracts the fixed parameters passed into the `p` object. -The only confusing part of the notation is the `R_0(t, p)` which evaluates the `p.R_bar_0` at this time (and also allows it to depend on the `p` parameter). +The only confusing part of the notation is the `R_bar_0(t, p)` which evaluates the `p.R_bar_0` at this time (and also allows it to depend on the `p` parameter). ### Parameters #####HERE ENDED @@ -318,7 +318,7 @@ p_gen(;T = 550.0, gamma = 1.0 / 18, sigma = 1 / 5.2, eta = 1.0 / 20, R_bar_0 = (t, p) -> p.R_0_n) = (;T, gamma, sigma, eta, R_0_n, delta, N, R_bar_0) ``` -Note that the default $\bar{R}_0(t)$ function always equals $R_{0n}$ -- a parameterizable natural level of $R_0$ used only by the `R_hat_0` function +Note that the default $\bar{R}_0(t)$ function always equals $R_{0n}$ -- a parameterizable natural level of $R_0$ used only by the `R_bar_0` function Setting initial conditions, we choose a fixed $s, i, e, r$, as well as $R_0(0) = R_{0n}$ and $m(0) = 0.01$ @@ -472,8 +472,8 @@ and 75,000 agents already exposed to the virus and thus soon to be contagious. R_0_L = 0.5 # lockdown R_bar_0_lift_early(t, p) = t < 30.0 ? R_0_L : 2.0 R_bar_0_lift_late(t, p) = t < 120.0 ? R_0_L : 2.0 -p_early = p_gen(R_bar_0= R_bar_0_lift_early, eta = 10.0) -p_late = p_gen(R_bar_0= R_bar_0_lift_late, eta = 10.0) +p_early = p_gen(R_bar_0 = R_bar_0_lift_early, eta = 10.0) +p_late = p_gen(R_bar_0 = R_bar_0_lift_late, eta = 10.0) # initial conditions @@ -483,7 +483,7 @@ s_0 = 1.0 - i_0 - e_0 x_0 = [s_0, e_0, i_0, 0.0, R_0_L, 0.0, 0.0] # start in lockdown -# create two problems, with rapid movement of R_0(t) towards R_hat_0(t) +# create two problems, with rapid movement of R_0(t) towards R_bar_0(t) prob_early = ODEProblem(F, x_0, tspan, p_early) prob_late = ODEProblem(F, x_0, tspan, p_late) ``` From acba4663393674bcddfc9bc75128a6d14c5c3398 Mon Sep 17 00:00:00 2001 From: annabellasd Date: Mon, 9 Oct 2023 19:32:32 -0800 Subject: [PATCH 22/26] updated --- format_myst.jl | 4 +- lectures/dynamic_programming_squared/amss.md | 270 +++++++++--------- .../dynamic_programming_squared/dyn_stack.md | 112 ++++---- .../dynamic_programming_squared/lqramsey.md | 105 ++++--- .../opt_tax_recur.md | 214 +++++++------- 5 files changed, 348 insertions(+), 357 deletions(-) diff --git a/format_myst.jl b/format_myst.jl index 0e24e1dd..fcf44d03 100644 --- a/format_myst.jl +++ b/format_myst.jl @@ -58,7 +58,9 @@ function format_myst(input_file_path, output_file_path, extra_replacements = fal replacements = Dict("α" => "alpha", "β" => "beta", "γ" => "gamma", "≤" => "<=", "≥" => ">=", "Σ" => "Sigma", "σ" => "sigma","μ"=>"mu","ϕ"=>"phi","ψ"=>"psi","ϵ"=>"epsilon", "δ"=>"delta","θ" => "theta","ζ"=>"zeta","X̄" => "X_bar","p̄" => "p_bar","x̂" => "x_hat","λ"=>"lambda", - "ρ"=>"rho","u′" => "u_prime" , "f′"=>"f_prime"," ∂u∂c"=>"dudc","Π"=>"Pi","π"=>"pi"," ξ"=>"Xi","c̄"=>"c_bar","w̄"=>"w_bar") + "ρ"=>"rho","u′" => "u_prime" , "f′"=>"f_prime"," ∂u∂c"=>"dudc","Π"=>"Pi","π"=>"pi","ξ"=>"xi","c̄"=>"c_bar", + "w̄"=>"w_bar","Θ" => "Theta", "Ξ" =>"Xi", "Q̃" => "Q_tilde","R̃" => "R_tilde","Ã" => "A_tilde", "B̃" => "B_tilde", + "P̃" => "P_tilde","F̃" => "F_tilde","d̃" => "d_tilde") # Replace the code blocks in the content and handle exceptions try diff --git a/lectures/dynamic_programming_squared/amss.md b/lectures/dynamic_programming_squared/amss.md index 1bc4fee1..a3afd086 100644 --- a/lectures/dynamic_programming_squared/amss.md +++ b/lectures/dynamic_programming_squared/amss.md @@ -404,10 +404,10 @@ import QuantEcon.simulate mutable struct Model{TF <: AbstractFloat, TM <: AbstractMatrix{TF}, TV <: AbstractVector{TF}} - β::TF - Π::TM + beta::TF + Pi::TM G::TV - Θ::TV + Theta::TV transfers::Bool U::Function Uc::Function @@ -426,19 +426,19 @@ struct SequentialAllocation{TP <: Model, S::TI cFB::TV nFB::TV - ΞFB::TV + XiFB::TV zFB::TV end function SequentialAllocation(model::Model) - β, Π, G, Θ = model.β, model.Π, model.G, model.Θ - mc = MarkovChain(Π) - S = size(Π, 1) # Number of states + beta, Pi, G, Theta = model.beta, model.Pi, model.G, model.Theta + mc = MarkovChain(Pi) + S = size(Pi, 1) # Number of states # Now find the first best allocation - cFB, nFB, ΞFB, zFB = find_first_best(model, S, 1) + cFB, nFB, XiFB, zFB = find_first_best(model, S, 1) - return SequentialAllocation(model, mc, S, cFB, nFB, ΞFB, zFB) + return SequentialAllocation(model, mc, S, cFB, nFB, XiFB, zFB) end @@ -446,13 +446,13 @@ function find_first_best(model::Model, S::Integer, version::Integer) if version != 1 && version != 2 throw(ArgumentError("version must be 1 or 2")) end - β, Θ, Uc, Un, G, Π = - model.β, model.Θ, model.Uc, model.Un, model.G, model.Π + beta, Theta, Uc, Un, G, Pi = + model.beta, model.Theta, model.Uc, model.Un, model.G, model.Pi function res!(out, z) c = z[1:S] n = z[S+1:end] - out[1:S] = Θ .* Uc.(c, n) + Un.(c, n) - out[S+1:end] = Θ .* n .- c .- G + out[1:S] = Theta .* Uc.(c, n) + Un.(c, n) + out[S+1:end] = Theta .* n .- c .- G end res = nlsolve(res!, 0.5 * ones(2 * S)) @@ -463,32 +463,32 @@ function find_first_best(model::Model, S::Integer, version::Integer) if version == 1 cFB = res.zero[1:S] nFB = res.zero[S+1:end] - ΞFB = Uc(cFB, nFB) # Multiplier on the resource constraint - zFB = vcat(cFB, nFB, ΞFB) - return cFB, nFB, ΞFB, zFB + XiFB = Uc(cFB, nFB) # Multiplier on the resource constraint + zFB = vcat(cFB, nFB, XiFB) + return cFB, nFB, XiFB, zFB elseif version == 2 cFB = res.zero[1:S] nFB = res.zero[S+1:end] IFB = Uc(cFB, nFB) .* cFB + Un(cFB, nFB) .* nFB - xFB = \(LinearAlgebra.I - β * Π, IFB) + xFB = \(LinearAlgebra.I - beta * Pi, IFB) zFB = [vcat(cFB[s], xFB[s], xFB) for s in 1:S] return cFB, nFB, IFB, xFB, zFB end end -function time1_allocation(pas::SequentialAllocation, μ::Real) +function time1_allocation(pas::SequentialAllocation, mu::Real) model, S = pas.model, pas.S - Θ, β, Π, G, Uc, Ucc, Un, Unn = - model.Θ, model.β, model.Π, model.G, + Theta, beta, Pi, G, Uc, Ucc, Un, Unn = + model.Theta, model.beta, model.Pi, model.G, model.Uc, model.Ucc, model.Un, model.Unn function FOC!(out, z::Vector) c = z[1:S] n = z[S+1:2S] - Ξ = z[2S+1:end] - out[1:S] = Uc.(c, n) - μ * (Ucc.(c, n) .* c + Uc.(c, n)) - Ξ # FOC c - out[S+1:2S] = Un.(c, n) - μ * (Unn(c, n) .* n .+ Un.(c, n)) + Θ .* Ξ # FOC n - out[2S+1:end] = Θ .* n - c .- G # resource constraint + Xi = z[2S+1:end] + out[1:S] = Uc.(c, n) - mu * (Ucc.(c, n) .* c + Uc.(c, n)) - Xi # FOC c + out[S+1:2S] = Un.(c, n) - mu * (Unn(c, n) .* n .+ Un.(c, n)) + Theta .* Xi # FOC n + out[2S+1:end] = Theta .* n - c .- G # resource constraint return out end # Find the root of the FOC @@ -497,35 +497,35 @@ function time1_allocation(pas::SequentialAllocation, μ::Real) error("Could not find LS allocation.") end z = res.zero - c, n, Ξ = z[1:S], z[S+1:2S], z[2S+1:end] + c, n, Xi = z[1:S], z[S+1:2S], z[2S+1:end] # Now compute x I = Uc(c, n) .* c + Un(c, n) .* n - x = \(LinearAlgebra.I - β * model.Π, I) - return c, n, x, Ξ + x = \(LinearAlgebra.I - beta * model.Pi, I) + return c, n, x, Xi end function time0_allocation(pas::SequentialAllocation, B_::AbstractFloat, s_0::Integer) model = pas.model - Π, Θ, G, β = model.Π, model.Θ, model.G, model.β + Pi, Theta, G, beta = model.Pi, model.Theta, model.G, model.beta Uc, Ucc, Un, Unn = model.Uc, model.Ucc, model.Un, model.Unn # First order conditions of planner's problem function FOC!(out, z) - μ, c, n, Ξ = z[1], z[2], z[3], z[4] - xprime = time1_allocation(pas, μ)[3] + mu, c, n, Xi = z[1], z[2], z[3], z[4] + xprime = time1_allocation(pas, mu)[3] out .= vcat( - Uc(c, n) .* (c - B_) + Un(c, n) .* n + β * dot(Π[s_0, :], xprime), - Uc(c, n) .- μ * (Ucc(c, n) .* (c - B_) + Uc(c, n)) .- Ξ, - Un(c, n) .- μ * (Unn(c, n) .* n + Un(c, n)) + Θ[s_0] .* Ξ, - (Θ .* n .- c .- G)[s_0] + Uc(c, n) .* (c - B_) + Un(c, n) .* n + beta * dot(Pi[s_0, :], xprime), + Uc(c, n) .- mu * (Ucc(c, n) .* (c - B_) + Uc(c, n)) .- Xi, + Un(c, n) .- mu * (Unn(c, n) .* n + Un(c, n)) + Theta[s_0] .* Xi, + (Theta .* n .- c .- G)[s_0] ) end # Find root - res = nlsolve(FOC!, [0.0, pas.cFB[s_0], pas.nFB[s_0], pas.ΞFB[s_0]]) + res = nlsolve(FOC!, [0.0, pas.cFB[s_0], pas.nFB[s_0], pas.XiFB[s_0]]) if res.f_converged == false error("Could not find time 0 LS allocation.") end @@ -533,18 +533,18 @@ function time0_allocation(pas::SequentialAllocation, end -function time1_value(pas::SequentialAllocation, μ::Real) +function time1_value(pas::SequentialAllocation, mu::Real) model = pas.model - c, n, x, Ξ = time1_allocation(pas, μ) + c, n, x, Xi = time1_allocation(pas, mu) U_val = model.U.(c, n) - V = \(LinearAlgebra.I - model.β*model.Π, U_val) + V = \(LinearAlgebra.I - model.beta*model.Pi, U_val) return c, n, x, V end function Τ(model::Model, c::Union{Real,Vector}, n::Union{Real,Vector}) Uc, Un = model.Uc.(c, n), model.Un.(c, n) - return 1. .+ Un./(model.Θ .* Uc) + return 1. .+ Un./(model.Theta .* Uc) end @@ -554,7 +554,7 @@ function simulate(pas::SequentialAllocation, sHist::Union{Vector, Nothing}=nothing) model = pas.model - Π, β, Uc = model.Π, model.β, model.Uc + Pi, beta, Uc = model.Pi, model.beta, model.Uc if isnothing(sHist) sHist = QuantEcon.simulate(pas.mc, T, init=s_0) @@ -563,25 +563,25 @@ function simulate(pas::SequentialAllocation, nHist = zeros(T) Bhist = zeros(T) ΤHist = zeros(T) - μHist = zeros(T) + muHist = zeros(T) RHist = zeros(T-1) # time 0 - μ, cHist[1], nHist[1], _ = time0_allocation(pas, B_, s_0) + mu, cHist[1], nHist[1], _ = time0_allocation(pas, B_, s_0) ΤHist[1] = Τ(pas.model, cHist[1], nHist[1])[s_0] Bhist[1] = B_ - μHist[1] = μ + muHist[1] = mu # time 1 onward for t in 2:T - c, n, x, Ξ = time1_allocation(pas,μ) + c, n, x, Xi = time1_allocation(pas,mu) u_c = Uc(c,n) s = sHist[t] ΤHist[t] = Τ(pas.model, c, n)[s] - Eu_c = dot(Π[sHist[t-1],:], u_c) + Eu_c = dot(Pi[sHist[t-1],:], u_c) cHist[t], nHist[t], Bhist[t] = c[s], n[s], x[s] / u_c[s] - RHist[t-1] = Uc(cHist[t-1], nHist[t-1]) / (β * Eu_c) - μHist[t] = μ + RHist[t-1] = Uc(cHist[t-1], nHist[t-1]) / (beta * Eu_c) + muHist[t] = mu end - return cHist, nHist, Bhist, ΤHist, sHist, μHist, RHist + return cHist, nHist, Bhist, ΤHist, sHist, muHist, RHist end @@ -603,7 +603,7 @@ end function BellmanEquation(model::Model, xgrid::AbstractVector, policies0::Vector) - S = size(model.Π, 1) # number of states + S = size(model.Pi, 1) # number of states xbar = [minimum(xgrid), maximum(xgrid)] time_0 = false cf, nf, xprimef = policies0 @@ -618,19 +618,19 @@ function get_policies_time1(T::BellmanEquation, i_x::Integer, x::AbstractFloat, s::Integer, Vf::AbstractArray) model, S = T.model, T.S - β, Θ, G, Π = model.β, model.Θ, model.G, model.Π + beta, Theta, G, Pi = model.beta, model.Theta, model.G, model.Pi U, Uc, Un = model.U, model.Uc, model.Un function objf(z::Vector, grad) c, xprime = z[1], z[2:end] n=c+G[s] Vprime = [Vf[sprime](xprime[sprime]) for sprime in 1:S] - return -(U(c, n) + β * dot(Π[s, :], Vprime)) + return -(U(c, n) + beta * dot(Pi[s, :], Vprime)) end function cons(z::Vector, grad) c, xprime = z[1], z[2:end] n=c+G[s] - return x - Uc(c, n) * c - Un(c, n) * n - β * dot(Π[s, :], xprime) + return x - Uc(c, n) * c - Un(c, n) * n - beta * dot(Pi[s, :], xprime) end lb = vcat(0, T.xbar[1] * ones(S)) ub = vcat(1 - G[s], T.xbar[2] * ones(S)) @@ -657,18 +657,18 @@ end function get_policies_time0(T::BellmanEquation, B_::AbstractFloat, s0::Integer, Vf::Array) model, S = T.model, T.S - β, Θ, G, Π = model.β, model.Θ, model.G, model.Π + beta, Theta, G, Pi = model.beta, model.Theta, model.G, model.Pi U, Uc, Un = model.U, model.Uc, model.Un function objf(z, grad) c, xprime = z[1], z[2:end] n = c+G[s0] Vprime = [Vf[sprime](xprime[sprime]) for sprime in 1:S] - return -(U(c, n) + β * dot(Π[s0, :], Vprime)) + return -(U(c, n) + beta * dot(Pi[s0, :], Vprime)) end function cons(z::Vector, grad) c, xprime = z[1], z[2:end] n = c + G[s0] - return -Uc(c, n) * (c - B_) - Un(c, n) * n - β * dot(Π[s0, :], xprime) + return -Uc(c, n) * (c - B_) - Un(c, n) * n - beta * dot(Pi[s0, :], xprime) end lb = vcat(0, T.xbar[1] * ones(S)) ub = vcat(1-G[s0], T.xbar[2] * ones(S)) @@ -985,53 +985,53 @@ struct RecursiveAllocation{TP <: Model, mc::MarkovChain S::TI T::BellmanEquation_Recursive - μgrid::TVg + mugrid::TVg xgrid::TVg Vf::Array policies::TT end -function RecursiveAllocation(model::Model, μgrid::AbstractArray) +function RecursiveAllocation(model::Model, mugrid::AbstractArray) G = model.G - S = size(model.Π, 1) # number of states - mc = MarkovChain(model.Π) + S = size(model.Pi, 1) # number of states + mc = MarkovChain(model.Pi) # now find the first best allocation - Vf, policies, T, xgrid = solve_time1_bellman(model, μgrid) + Vf, policies, T, xgrid = solve_time1_bellman(model, mugrid) T.time_0 = true # Bellman equation now solves time 0 problem - return RecursiveAllocation(model, mc, S, T, μgrid, xgrid, Vf, policies) + return RecursiveAllocation(model, mc, S, T, mugrid, xgrid, Vf, policies) end -function solve_time1_bellman(model::Model{TR}, μgrid::AbstractArray) where {TR <: Real} - Π = model.Π - S = size(model.Π, 1) +function solve_time1_bellman(model::Model{TR}, mugrid::AbstractArray) where {TR <: Real} + Pi = model.Pi + S = size(model.Pi, 1) # First get initial fit from lucas stockey solution. # Need to change things to be ex_ante PP = SequentialAllocation(model) function incomplete_allocation(PP::SequentialAllocation, - μ_::AbstractFloat, + mu_::AbstractFloat, s_::Integer) - c, n, x, V = time1_value(PP, μ_) - return c, n, dot(Π[s_, :], x), dot(Π[s_, :], V) + c, n, x, V = time1_value(PP, mu_) + return c, n, dot(Pi[s_, :], x), dot(Pi[s_, :], V) end cf = Array{Function}(undef, S, S) nf = Array{Function}(undef, S, S) xprimef = Array{Function}(undef, S, S) Vf = Vector{Function}(undef, S) - xgrid = Array{TR}(undef, S, length(μgrid)) + xgrid = Array{TR}(undef, S, length(mugrid)) for s_ in 1:S - c = Array{TR}(undef, length(μgrid), S) - n = Array{TR}(undef, length(μgrid), S) - x = Array{TR}(undef, length(μgrid)) - V = Array{TR}(undef, length(μgrid)) - for (i_μ, μ) in enumerate(μgrid) - c[i_μ, :], n[i_μ, :], x[i_μ], V[i_μ] = - incomplete_allocation(PP, μ, s_) + c = Array{TR}(undef, length(mugrid), S) + n = Array{TR}(undef, length(mugrid), S) + x = Array{TR}(undef, length(mugrid)) + V = Array{TR}(undef, length(mugrid)) + for (i_mu, mu) in enumerate(mugrid) + c[i_mu, :], n[i_mu, :], x[i_mu], V[i_mu] = + incomplete_allocation(PP, mu, s_) end xprimes = repeat(x, 1, S) xgrid[s_, :] = x @@ -1051,7 +1051,7 @@ function solve_time1_bellman(model::Model{TR}, μgrid::AbstractArray) where {TR # Create xgrid xbar = [maximum(minimum(xgrid)), minimum(maximum(xgrid))] - xgrid = range(xbar[1], xbar[2], length = length(μgrid)) + xgrid = range(xbar[1], xbar[2], length = length(mugrid)) # Now iterate on Bellman equation T = BellmanEquation_Recursive(model, xgrid, policies) @@ -1113,7 +1113,7 @@ function Tau(pab::RecursiveAllocation, n::AbstractArray) model = pab.model Uc, Un = model.Uc(c, n), model.Un(c, n) - return 1. .+ Un ./ (model.Θ .* Uc) + return 1. .+ Un ./ (model.Theta .* Uc) end Tau(pab::RecursiveAllocation, c::Real, n::Real) = Tau(pab, [c], [n]) @@ -1133,7 +1133,7 @@ function simulate(pab::RecursiveAllocation, B_::TF, s_0::Integer, T::Integer, sHist::Vector=simulate(pab.mc, T, init=s_0)) where {TF <: AbstractFloat} model, mc, Vf, S = pab.model, pab.mc, pab.Vf, pab.S - Π, Uc = model.Π, model.Uc + Pi, Uc = model.Pi, model.Uc cf, nf, xprimef, TTf = pab.policies cHist = Array{TF}(undef, T) @@ -1142,13 +1142,13 @@ function simulate(pab::RecursiveAllocation, xHist = Array{TF}(undef, T) TauHist = Array{TF}(undef, T) THist = Array{TF}(undef, T) - μHist = Array{TF}(undef, T) + muHist = Array{TF}(undef, T) #time0 cHist[1], nHist[1], xHist[1], THist[1] = time0_allocation(pab, B_, s_0) TauHist[1] = Tau(pab, cHist[1], nHist[1])[s_0] Bhist[1] = B_ - μHist[1] = Vf[s_0](xHist[1]) + muHist[1] = Vf[s_0](xHist[1]) #time 1 onward for t in 2:T @@ -1165,14 +1165,14 @@ function simulate(pab::RecursiveAllocation, Tau_val = Tau(pab, c, n)[s] u_c = Uc(c, n) - Eu_c = dot(Π[s_, :], u_c) + Eu_c = dot(Pi[s_, :], u_c) - μHist[t] = Vf[s](xprime[s]) + muHist[t] = Vf[s](xprime[s]) cHist[t], nHist[t], Bhist[t], TauHist[t] = c[s], n[s], x/Eu_c, Tau_val xHist[t], THist[t] = xprime[s], TT[s] end - return cHist, nHist, Bhist, xHist, TauHist, THist, μHist, sHist + return cHist, nHist, Bhist, xHist, TauHist, THist, muHist, sHist end @@ -1180,7 +1180,7 @@ function BellmanEquation_Recursive(model::Model{TF}, xgrid::AbstractVector{TF}, policies0::Array) where {TF <: AbstractFloat} - S = size(model.Π, 1) # number of states + S = size(model.Pi, 1) # number of states xbar = [minimum(xgrid), maximum(xgrid)] time_0 = false z0 = Array{Array}(undef, length(xgrid), S) @@ -1209,33 +1209,33 @@ function get_policies_time1(T::BellmanEquation_Recursive, Vf::AbstractArray{Function}, xbar::AbstractVector) model, S = T.model, T.S - β, Θ, G, Π = model.β, model.Θ, model.G, model.Π + beta, Theta, G, Pi = model.beta, model.Theta, model.G, model.Pi U,Uc,Un = model.U, model.Uc, model.Un - S_possible = sum(Π[s_, :].>0) - sprimei_possible = findall(Π[s_, :].>0) + S_possible = sum(Pi[s_, :].>0) + sprimei_possible = findall(Pi[s_, :].>0) function objf(z, grad) c, xprime = z[1:S_possible], z[S_possible+1:2S_possible] - n = (c .+ G[sprimei_possible]) ./ Θ[sprimei_possible] + n = (c .+ G[sprimei_possible]) ./ Theta[sprimei_possible] Vprime = [Vf[sprimei_possible[si]](xprime[si]) for si in 1:S_possible] - return -dot(Π[s_, sprimei_possible], U.(c, n) + β * Vprime) + return -dot(Pi[s_, sprimei_possible], U.(c, n) + beta * Vprime) end function cons(out, z, grad) c, xprime, TT = z[1:S_possible], z[S_possible + 1:2S_possible], z[2S_possible + 1:3S_possible] - n = (c .+ G[sprimei_possible]) ./ Θ[sprimei_possible] + n = (c .+ G[sprimei_possible]) ./ Theta[sprimei_possible] u_c = Uc.(c, n) - Eu_c = dot(Π[s_, sprimei_possible], u_c) - out .= x * u_c/Eu_c - u_c .* (c - TT) - Un(c, n) .* n - β * xprime + Eu_c = dot(Pi[s_, sprimei_possible], u_c) + out .= x * u_c/Eu_c - u_c .* (c - TT) - Un(c, n) .* n - beta * xprime end function cons_no_trans(out, z, grad) c, xprime = z[1:S_possible], z[S_possible + 1:2S_possible] - n = (c .+ G[sprimei_possible]) ./ Θ[sprimei_possible] + n = (c .+ G[sprimei_possible]) ./ Theta[sprimei_possible] u_c = Uc.(c, n) - Eu_c = dot(Π[s_, sprimei_possible], u_c) - out .= x * u_c / Eu_c - u_c .* c - Un(c, n) .* n - β * xprime + Eu_c = dot(Pi[s_, sprimei_possible], u_c) + out .= x * u_c / Eu_c - u_c .* c - Un(c, n) .* n - beta * xprime end if model.transfers == true @@ -1302,19 +1302,19 @@ function get_policies_time0(T::BellmanEquation_Recursive, Vf::AbstractArray{Function}, xbar::AbstractVector) model = T.model - β, Θ, G = model.β, model.Θ, model.G + beta, Theta, G = model.beta, model.Theta, model.G U, Uc, Un = model.U, model.Uc, model.Un function objf(z, grad) c, xprime = z[1], z[2] - n = (c + G[s0]) / Θ[s0] - return -(U(c, n) + β * Vf[s0](xprime)) + n = (c + G[s0]) / Theta[s0] + return -(U(c, n) + beta * Vf[s0](xprime)) end function cons(z,grad) c, xprime, TT = z[1], z[2], z[3] - n = (c + G[s0]) / Θ[s0] - return -Uc(c, n) * (c - B_ - TT) - Un(c, n) * n - β * xprime + n = (c + G[s0]) / Theta[s0] + return -Uc(c, n) * (c - B_ - TT) - Un(c, n) * n - beta * xprime end cons_no_trans(z, grad) = cons(vcat(z, 0), grad) @@ -1430,29 +1430,29 @@ This utility function is implemented in the following constructor ```{code-cell} julia function crra_utility(; - β = 0.9, - σ = 2.0, - γ = 2.0, - Π = 0.5 * ones(2, 2), + beta = 0.9, + sigma = 2.0, + gamma = 2.0, + Pi = 0.5 * ones(2, 2), G = [0.1, 0.2], - Θ = ones(Float64, 2), + Theta = ones(Float64, 2), transfers = false ) function U(c, n) - if σ == 1.0 + if sigma == 1.0 U = log(c) else - U = (c.^(1.0 - σ) - 1.0) / (1.0 - σ) + U = (c.^(1.0 - sigma) - 1.0) / (1.0 - sigma) end - return U - n.^(1 + γ) / (1 + γ) + return U - n.^(1 + gamma) / (1 + gamma) end # Derivatives of utility function - Uc(c,n) = c.^(-σ) - Ucc(c,n) = -σ * c.^(-σ - 1.0) - Un(c,n) = -n.^γ - Unn(c,n) = -γ * n.^(γ - 1.0) + Uc(c,n) = c.^(-sigma) + Ucc(c,n) = -sigma * c.^(-sigma - 1.0) + Un(c,n) = -n.^gamma + Unn(c,n) = -gamma * n.^(gamma - 1.0) n_less_than_one = false - return Model(β, Π, G, Θ, transfers, + return Model(beta, Pi, G, Theta, transfers, U, Uc, Ucc, Un, Unn, n_less_than_one) end ``` @@ -1469,22 +1469,22 @@ triangle denote war. ```{code-cell} julia time_example = crra_utility(G=[0.1, 0.1, 0.1, 0.2, 0.1, 0.1], - Θ = ones(6)) # Θ can in principle be random + Theta = ones(6)) # Theta can in principle be random -time_example.Π = [ 0.0 1.0 0.0 0.0 0.0 0.0; +time_example.Pi = [ 0.0 1.0 0.0 0.0 0.0 0.0; 0.0 0.0 1.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.5 0.5 0.0; 0.0 0.0 0.0 0.0 0.0 1.0; 0.0 0.0 0.0 0.0 0.0 1.0; 0.0 0.0 0.0 0.0 0.0 1.0] -# Initialize μgrid for value function iteration -μgrid = range(-0.7, 0.01, length = 200) +# Initialize mugrid for value function iteration +mugrid = range(-0.7, 0.01, length = 200) time_example.transfers = true # Government can use transfers time_sequential = SequentialAllocation(time_example) # Solve sequential problem -time_bellman = RecursiveAllocation(time_example, μgrid) +time_bellman = RecursiveAllocation(time_example, mugrid) sHist_h = [1, 2, 3, 4, 6, 6, 6] sHist_l = [1, 2, 3, 5, 6, 6, 6] @@ -1500,16 +1500,16 @@ titles = hcat("Consumption", "Labor Supply", "Government Debt", "Tax Rate", "Government Spending", "Output") sim_seq_l_plot = hcat(sim_seq_l[1:3]..., sim_seq_l[4], time_example.G[sHist_l], - time_example.Θ[sHist_l] .* sim_seq_l[2]) + time_example.Theta[sHist_l] .* sim_seq_l[2]) sim_bel_l_plot = hcat(sim_bel_l[1:3]..., sim_bel_l[5], time_example.G[sHist_l], - time_example.Θ[sHist_l] .* sim_bel_l[2]) + time_example.Theta[sHist_l] .* sim_bel_l[2]) sim_seq_h_plot = hcat(sim_seq_h[1:3]..., sim_seq_h[4], time_example.G[sHist_h], - time_example.Θ[sHist_h] .* sim_seq_h[2]) + time_example.Theta[sHist_h] .* sim_seq_h[2]) sim_bel_h_plot = hcat(sim_bel_h[1:3]..., sim_bel_h[5], time_example.G[sHist_h], - time_example.Θ[sHist_h] .* sim_bel_h[2]) + time_example.Theta[sHist_h] .* sim_bel_h[2]) p = plot(size = (920, 750), layout =(3, 2), xaxis=(0:6), grid=false, titlefont=Plots.font("sans-serif", 10)) plot!(p, title = titles) @@ -1574,20 +1574,20 @@ $$ In accordance, we will re-define our utility function ```{code-cell} julia -function log_utility(;β = 0.9, - ψ = 0.69, - Π = 0.5 * ones(2, 2), +function log_utility(;beta = 0.9, + psi = 0.69, + Pi = 0.5 * ones(2, 2), G = [0.1, 0.2], - Θ = ones(2), + Theta = ones(2), transfers = false) # Derivatives of utility function - U(c,n) = log(c) + ψ * log(1 - n) + U(c,n) = log(c) + psi * log(1 - n) Uc(c,n) = 1 ./ c Ucc(c,n) = -c.^(-2.0) - Un(c,n) = -ψ ./ (1.0 .- n) - Unn(c,n) = -ψ ./ (1.0 .- n).^2.0 + Un(c,n) = -psi ./ (1.0 .- n) + Unn(c,n) = -psi ./ (1.0 .- n).^2.0 n_less_than_one = true - return Model(β, Π, G, Θ, transfers, + return Model(beta, Pi, G, Theta, transfers, U, Uc, Ucc, Un, Unn, n_less_than_one) end ``` @@ -1604,7 +1604,7 @@ log_example = log_utility() log_example.transfers = true # Government can use transfers log_sequential = SequentialAllocation(log_example) # Solve sequential problem -log_bellman = RecursiveAllocation(log_example, μgrid) # Solve recursive problem +log_bellman = RecursiveAllocation(log_example, mugrid) # Solve recursive problem T = 20 sHist = [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1] @@ -1614,9 +1614,9 @@ sim_seq = simulate(log_sequential, 0.5, 1, T, sHist) sim_bel = simulate(log_bellman, 0.5, 1, T, sHist) sim_seq_plot = hcat(sim_seq[1:3]..., - sim_seq[4], log_example.G[sHist], log_example.Θ[sHist] .* sim_seq[2]) + sim_seq[4], log_example.G[sHist], log_example.Theta[sHist] .* sim_seq[2]) sim_bel_plot = hcat(sim_bel[1:3]..., - sim_bel[5], log_example.G[sHist], log_example.Θ[sHist] .* sim_bel[2]) + sim_bel[5], log_example.G[sHist], log_example.Theta[sHist] .* sim_bel[2]) #plot policies p = plot(size = (920, 750), layout = grid(3, 2), @@ -1656,9 +1656,9 @@ sim_seq_long = simulate(log_sequential, 0.5, 1, T_long) sHist_long = sim_seq_long[end-2] sim_bel_long = simulate(log_bellman, 0.5, 1, T_long, sHist_long) sim_seq_long_plot = hcat(sim_seq_long[1:4]..., - log_example.G[sHist_long], log_example.Θ[sHist_long] .* sim_seq_long[2]) + log_example.G[sHist_long], log_example.Theta[sHist_long] .* sim_seq_long[2]) sim_bel_long_plot = hcat(sim_bel_long[1:3]..., sim_bel_long[5], - log_example.G[sHist_long], log_example.Θ[sHist_long] .* sim_bel_long[2]) + log_example.G[sHist_long], log_example.Theta[sHist_long] .* sim_bel_long[2]) p = plot(size = (920, 750), layout = (3, 2), xaxis=(0:50:T_long), grid=false, titlefont=Plots.font("sans-serif", 10)) diff --git a/lectures/dynamic_programming_squared/dyn_stack.md b/lectures/dynamic_programming_squared/dyn_stack.md index 6a0f08f8..9542d8f6 100644 --- a/lectures/dynamic_programming_squared/dyn_stack.md +++ b/lectures/dynamic_programming_squared/dyn_stack.md @@ -929,16 +929,10 @@ We define named tuples and default values for the model and solver settings, and instantiate one copy of each ```{code-cell} julia -model = @with_kw (a0 = 10, - a1 = 2, - β = 0.96, - γ = 120., - n = 300) +model(;a0 = 10, a1 = 2, beta = 0.96, gamma = 120., n = 300) = (; a0, a1, beta, gamma, n) # things like tolerances, etc. -settings = @with_kw (tol0 = 1e-8, - tol1 = 1e-16, - tol2 = 1e-2) +settings(;tol0 = 1e-8,tol1 = 1e-16,tol2 = 1e-2) = (;tol0, tol1, tol2) defaultModel = model(); defaultSettings = settings(); @@ -947,12 +941,12 @@ defaultSettings = settings(); Now we can compute the actual policy using the LQ routine from QuantEcon.jl ```{code-cell} julia -@unpack a0, a1, β, γ, n = defaultModel -@unpack tol0, tol1, tol2 = defaultSettings +(;a0, a1, beta, gamma, n) = defaultModel +(;tol0, tol1, tol2) = defaultSettings -βs = [β^x for x = 0:n-1] +betas = [beta^x for x = 0:n-1] Alhs = I + zeros(4, 4); -Alhs[4, :] = [β * a0 / (2 * γ), -β * a1 / (2 * γ), -β * a1 / γ, β] # Euler equation coefficients +Alhs[4, :] = [beta * a0 / (2 * gamma), -beta * a1 / (2 * gamma), -beta * a1 / gamma, beta] # Euler equation coefficients Arhs = I + zeros(4, 4); Arhs[3, 4] = 1.; Alhsinv = inv(Alhs); @@ -960,8 +954,8 @@ Alhsinv = inv(Alhs); A = Alhsinv * Arhs; B = Alhsinv * [0, 1, 0, 0,]; R = [0 -a0/2 0 0; -a0/2 a1 a1/2 0; 0 a1/2 0 0; 0 0 0 0]; -Q = γ; -lq = QuantEcon.LQ(Q, R, A, B, bet=β); +Q = gamma; +lq = QuantEcon.LQ(Q, R, A, B, bet=beta); P, F, d = stationary_values(lq) P22 = P[4:end, 4:end]; @@ -970,17 +964,17 @@ P22inv = inv(P22); H_0_0 = -P22inv * P21; # simulate forward -π_leader = zeros(n); +pi_leader = zeros(n); z0 = [1, 1, 1]; x0 = H_0_0 * z0; y0 = vcat(z0, x0); Random.seed!(1) # for reproducibility yt, ut = compute_sequence(lq, y0, n); -π_matrix = R + F' * Q * F; +pi_matrix = R + F' * Q * F; for t in 1:n - π_leader[t] = -(yt[:, t]' * π_matrix * yt[:, t]); + pi_leader[t] = -(yt[:, t]' * pi_matrix * yt[:, t]); end println("Computed policy for Stackelberg leader: $F") @@ -1017,7 +1011,7 @@ We'll compute it two ways (they give identical answers -- just a check on coding and thinking) ```{code-cell} julia -v_leader_forward = sum(βs .* π_leader); +v_leader_forward = sum(betas .* pi_leader); v_leader_direct = -yt[:, 1]' * P * yt[:, 1]; println("v_leader_forward (forward sim) is $v_leader_forward") @@ -1034,7 +1028,7 @@ tags: [remove-cell] ```{code-cell} julia # manually check whether P is an approximate fixed point -P_next = (R + F' * Q * F + β * (A - B * F)' * P * (A - B * F)); +P_next = (R + F' * Q * F + beta * (A - B * F)' * P * (A - B * F)); all(P - P_next .< tol0) ``` @@ -1049,7 +1043,7 @@ tags: [remove-cell] # manually checks whether two different ways of computing the # value function give approximately the same answer v_expanded = -((y0' * R * y0 + ut[:, 1]' * Q * ut[:, 1] + - β * (y0' * (A - B * F)' * P * (A - B * F) * y0))); + beta * (y0' * (A - B * F)' * P * (A - B * F) * y0))); (v_leader_direct - v_expanded < tol0)[1, 1] ``` @@ -1102,14 +1096,14 @@ We check that the recursive **Big** $K$ **, little** $k$ formulation of the foll $\vec q_1$ that we computed when we solved the Stackelberg problem ```{code-cell} julia -Ã = I + zeros(5, 5); -Ã[1:4, 1:4] .= A - B * F; -R̃ = [0 0 0 0 -a0/2; 0 0 0 0 a1/2; 0 0 0 0 0; 0 0 0 0 0; -a0/2 a1/2 0 0 a1]; -Q̃ = Q; -B̃ = [0, 0, 0, 0, 1]; - -lq_tilde = QuantEcon.LQ(Q̃, R̃, Ã, B̃, bet=β); -P̃, F̃, d̃ = stationary_values(lq_tilde); +A_tilde = I + zeros(5, 5); +A_tilde[1:4, 1:4] .= A - B * F; +R_tilde = [0 0 0 0 -a0/2; 0 0 0 0 a1/2; 0 0 0 0 0; 0 0 0 0 0; -a0/2 a1/2 0 0 a1]; +Q_tilde = Q; +B_tilde = [0, 0, 0, 0, 1]; + +lq_tilde = QuantEcon.LQ(Q_tilde, R_tilde, A_tilde, B_tilde, bet=beta); +P_tilde, F_tilde, d_tilde = stationary_values(lq_tilde); y0_tilde = vcat(y0, y0[3]); yt_tilde = compute_sequence(lq_tilde, y0_tilde, n)[1]; ``` @@ -1159,7 +1153,7 @@ Can you spot what features of $\tilde F$ imply this? Hint: remember the components of $X_t$ ```{code-cell} julia -F̃ # policy function in the follower's problem +F_tilde # policy function in the follower's problem ``` ```{code-cell} julia @@ -1167,43 +1161,43 @@ P # value function in the Stackelberg problem ``` ```{code-cell} julia -P̃ # value function in the follower's problem +P_tilde # value function in the follower's problem ``` ```{code-cell} julia # manually check that P is an approximate fixed point -all((P - ((R + F' * Q * F) + β * (A - B * F)' * P * (A - B * F)) .< tol0)) +all((P - ((R + F' * Q * F) + beta * (A - B * F)' * P * (A - B * F)) .< tol0)) ``` ```{code-cell} julia --- tags: [remove-cell] --- -#test all((P - ((R + F' * Q * F) + β * (A - B * F)' * P * (A - B * F)) .< tol0)) +#test all((P - ((R + F' * Q * F) + beta * (A - B * F)' * P * (A - B * F)) .< tol0)) ``` ```{code-cell} julia # compute `P_guess` using `F_tilde_star` -F̃_star = -[0, 0, 0, 1, 0]'; +F_tilde_star = -[0, 0, 0, 1, 0]'; P_guess = zeros(5, 5); for i in 1:1000 - P_guess = ((R̃ + F̃_star' * Q̃ * F̃_star) + - β * (Ã - B̃ * F̃_star)' * P_guess - * (Ã - B̃ * F̃_star)); + P_guess = ((R_tilde + F_tilde_star' * Q_tilde * F_tilde_star) + + beta * (A_tilde - B_tilde * F_tilde_star)' * P_guess + * (A_tilde - B_tilde * F_tilde_star)); end ``` ```{code-cell} julia # value function in the follower's problem --(y0_tilde' * P̃ * y0_tilde)[1, 1] +-(y0_tilde' * P_tilde * y0_tilde)[1, 1] ``` ```{code-cell} julia --- tags: [remove-cell] --- -@test -(y0_tilde' * P̃ * y0_tilde)[1, 1] ≈ 112.65590740578173 +@test -(y0_tilde' * P_tilde * y0_tilde)[1, 1] ≈ 112.65590740578173 ``` ```{code-cell} julia @@ -1220,8 +1214,8 @@ tags: [remove-cell] ```{code-cell} julia # c policy using policy iteration algorithm -F_iter = (β * inv(Q + β * B̃' * P_guess * B̃) - * B̃' * P_guess * Ã); +F_iter = (beta * inv(Q + beta * B_tilde' * P_guess * B_tilde) + * B_tilde' * P_guess * A_tilde); P_iter = zeros(5, 5); dist_vec = zeros(5, 5); @@ -1229,22 +1223,22 @@ for i in 1:100 # compute P_iter dist_vec = similar(P_iter) for j in 1:1000 - P_iter = (R̃ + F_iter' * Q * F_iter) + β * - (Ã - B̃ * F_iter)' * P_iter * - (Ã - B̃ * F_iter); + P_iter = (R_tilde + F_iter' * Q * F_iter) + beta * + (A_tilde - B_tilde * F_iter)' * P_iter * + (A_tilde - B_tilde * F_iter); # update F_iter - F_iter = β * inv(Q + β * B̃' * P_iter * B̃) * - B̃' * P_iter * Ã; + F_iter = beta * inv(Q + beta * B_tilde' * P_iter * B_tilde) * + B_tilde' * P_iter * A_tilde; - dist_vec = P_iter - ((R̃ + F_iter' * Q * F_iter) + - β * (Ã - B̃ * F_iter)' * P_iter * - (Ã - B̃ * F_iter)); + dist_vec = P_iter - ((R_tilde + F_iter' * Q * F_iter) + + beta * (A_tilde - B_tilde * F_iter)' * P_iter * + (A_tilde - B_tilde * F_iter)); end end if maximum(abs.(dist_vec)) < 1e-8 - dist_vec2 = F_iter - (β * inv(Q + β * B̃' * P_iter * B̃) * B̃' * P_iter * Ã) + dist_vec2 = F_iter - (beta * inv(Q + beta * B_tilde' * P_iter * B_tilde) * B_tilde' * P_iter * A_tilde) if maximum(abs.(dist_vec2)) < 1e-8 @show F_iter else @@ -1260,7 +1254,7 @@ yt_tilde_star = zeros(n, 5); yt_tilde_star[1, :] = y0_tilde; for t in 1:n-1 - yt_tilde_star[t+1, :] = (Ã - B̃ * F̃_star) * yt_tilde_star[t, :]; + yt_tilde_star[t+1, :] = (A_tilde - B_tilde * F_tilde_star) * yt_tilde_star[t, :]; end plot([yt_tilde_star[:, 5], yt_tilde[3, :]], labels = [L"\tilde{q}" L"q"]) @@ -1317,13 +1311,13 @@ B1 = [0, 0, 1]; B2 = [0, 1, 0]; R1 = [0 0 -a0/2; 0 0 a1/2; -a0/2 a1/2 a1]; R2 = [0 -a0/2 0; -a0/2 a1 a1/2; 0 a1/2 0]; -Q1 = Q2 = γ; +Q1 = Q2 = gamma; S1 = S2 = W1 = W2 = M1 = M2 = 0.; # solve using nnash from QE F1, F2, P1, P2 = nnash(A, B1, B2, R1, R2, Q1, Q2, S1, S2, W1, W2, M1, M2, - beta = β, + beta = beta, tol = tol1); # simulate forward @@ -1370,11 +1364,11 @@ tags: [remove-cell] # compute values u1 = -F1 * z; u2 = -F2 * z; -π_1 = (p .* q1)' - γ * u1.^2; -π_2 = (p .* q2)' - γ * u2.^2; +pi_1 = (p .* q1)' - gamma * u1.^2; +pi_2 = (p .* q2)' - gamma * u2.^2; -v1_forward = π_1 * βs; -v2_forward = π_2 * βs; +v1_forward = pi_1 * betas; +v2_forward = pi_2 * betas; v1_direct = -z[:, 1]' * P1 * z[:, 1]; v2_direct = -z[:, 1]' * P2 * z[:, 1]; @@ -1395,8 +1389,8 @@ tags: [remove-cell] ```{code-cell} julia # sanity check -Λ_1 = A - B2 * F2; -lq1 = QuantEcon.LQ(Q1, R1, Λ_1, B1, bet = β); +Lambda_1 = A - B2 * F2; +lq1 = QuantEcon.LQ(Q1, R1, Lambda_1, B1, bet = beta); P1_ih, F1_ih, d = stationary_values(lq1); v2_direct_alt = -z[:, 1]' * P1_ih * z[:, 1] + d; @@ -1411,7 +1405,7 @@ vt_follower = zeros(n); for t in 1:n vt_MPE[t] = -z[:, t]' * P1 * z[:, t]; - vt_follower[t] = -yt_tilde[:, t]' * P̃ * yt_tilde[:, t]; + vt_follower[t] = -yt_tilde[:, t]' * P_tilde * yt_tilde[:, t]; end plot([vt_MPE, vt_leader, vt_follower], labels = ["MPE" "Stackelberg leader" "Stackelberg follower"], diff --git a/lectures/dynamic_programming_squared/lqramsey.md b/lectures/dynamic_programming_squared/lqramsey.md index 9aef62cb..a9cb6519 100644 --- a/lectures/dynamic_programming_squared/lqramsey.md +++ b/lectures/dynamic_programming_squared/lqramsey.md @@ -599,7 +599,7 @@ struct DiscreteStochProcess{TF <: AbstractFloat} <: AbstractStochProcess end struct Economy{TF <: AbstractFloat, SP <: AbstractStochProcess} - β::TF + beta::TF Sg::Matrix{TF} Sd::Matrix{TF} Sb::Matrix{TF} @@ -613,7 +613,7 @@ function compute_exog_sequences(econ, x) g, d, b, s = [dropdims(S * x, dims = 1) for S in (Sg, Sd, Sb, Ss)] #= solve for Lagrange multiplier in the govt budget constraint - In fact we solve for ν = λ / (1 + 2*λ). Here ν is the + In fact we solve for ν = lambda / (1 + 2*lambda). Here ν is the solution to a quadratic equation a(ν^2 - ν) + b = 0 where a and b are expected discounted sums of quadratic forms of the state. =# Sm = Sb - Sd - Ss @@ -631,17 +631,17 @@ function compute_allocation(econ, Sm, ν, x, b) c = dropdims(Sc * x, dims = 1) l = dropdims(Sl * x, dims = 1) p = dropdims((Sb - Sc) * x, dims = 1) # Price without normalization - τ = 1 .- l ./ (b .- c) - rvn = l .* τ + tau = 1 .- l ./ (b .- c) + rvn = l .* tau - return Sc, Sl, c, l, p, τ, rvn + return Sc, Sl, c, l, p, tau, rvn end function compute_ν(a0, b0) disc = a0^2 - 4a0 * b0 - if disc ≥ 0 + if disc >= 0 ν = 0.5 *(a0 - sqrt(disc)) / a0 else println("There is no Ramsey equilibrium for these parameters.") @@ -658,17 +658,17 @@ function compute_ν(a0, b0) end -function compute_Π(B, R, rvn, g, ξ) - π = B[2:end] - R[1:end-1] .* B[1:end-1] - rvn[1:end-1] + g[1:end-1] - Π = cumsum(π .* ξ) - return π, Π +function compute_Pi(B, R, rvn, g,Xi) + pi = B[2:end] - R[1:end-1] .* B[1:end-1] - rvn[1:end-1] + g[1:end-1] + Pi = cumsum(pi .*Xi) + return pi, Pi end function compute_paths(econ::Economy{<:AbstractFloat, <:DiscreteStochProcess}, T) # simplify notation - @unpack β, Sg, Sd, Sb, Ss = econ - @unpack P, x_vals = econ.proc + (;beta, Sg, Sd, Sb, Ss) = econ + (;P, x_vals) = econ.proc mc = MarkovChain(P) state = simulate(mc, T, init=1) @@ -679,7 +679,7 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:DiscreteStochProcess}, T # compute a0, b0 ns = size(P, 1) - F = I - β.*P + F = I - beta.*P a0 = (F \ ((Sm * x_vals)'.^2))[1] ./ 2 H = ((Sb - Sd + Sg) * x_vals) .* ((Sg - Ss)*x_vals) b0 = (F \ H')[1] ./ 2 @@ -688,29 +688,27 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:DiscreteStochProcess}, T ν = compute_ν(a0, b0) # Solve for the allocation given ν and x - Sc, Sl, c, l, p, τ, rvn = compute_allocation(econ, Sm, ν, x, b) + Sc, Sl, c, l, p, tau, rvn = compute_allocation(econ, Sm, ν, x, b) # compute remaining variables H = ((Sb - Sc) * x_vals) .* ((Sl - Sg) * x_vals) - (Sl * x_vals).^2 temp = dropdims(F * H', dims = 2) B = temp[state] ./ p H = dropdims(P[state, :] * ((Sb - Sc) * x_vals)', dims = 2) - R = p ./ (β .* H) + R = p ./ (beta .* H) temp = dropdims(P[state, :] *((Sb - Sc) * x_vals)', dims = 2) - ξ = p[2:end] ./ temp[1:end-1] + Xi = p[2:end] ./ temp[1:end-1] - # compute π - π, Π = compute_Π(B, R, rvn, g, ξ) + # compute pi + pi, Pi = compute_Pi(B, R, rvn, g,Xi) - return (g = g, d = d, b = b, s = s, c = c, - l = l, p = p, τ = τ, rvn = rvn, B = B, - R = R, π = π, Π = Π, ξ = ξ) + return (;g, d, b, s, c, l, p, tau, rvn, B, R, pi, Pi, Xi) end function compute_paths(econ::Economy{<:AbstractFloat, <:ContStochProcess}, T) # simplify notation - @unpack β, Sg, Sd, Sb, Ss = econ - @unpack A, C = econ.proc + (;beta, Sg, Sd, Sb, Ss) = econ + (;A, C) = econ.proc # generate an initial condition x0 satisfying x0 = A x0 nx, nx = size(A) @@ -733,37 +731,34 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:ContStochProcess}, T) # compute a0 and b0 H = Sm'Sm - a0 = 0.5 * var_quadratic_sum(A, C, H, β, x0) + a0 = 0.5 * var_quadratic_sum(A, C, H, beta, x0) H = (Sb - Sd + Sg)'*(Sg + Ss) - b0 = 0.5 * var_quadratic_sum(A, C, H, β, x0) + b0 = 0.5 * var_quadratic_sum(A, C, H, beta, x0) # compute lagrange multiplier ν = compute_ν(a0, b0) # solve for the allocation given ν and x - Sc, Sl, c, l, p, τ, rvn = compute_allocation(econ, Sm, ν, x, b) + Sc, Sl, c, l, p, tau, rvn = compute_allocation(econ, Sm, ν, x, b) # compute remaining variables H = Sl'Sl - (Sb - Sc)' *(Sl - Sg) L = zeros(T) for t in eachindex(L) - L[t] = var_quadratic_sum(A, C, H, β, x[:, t]) + L[t] = var_quadratic_sum(A, C, H, beta, x[:, t]) end B = L ./ p - Rinv = dropdims(β .* (Sb- Sc)*A*x, dims = 1) ./ p + Rinv = dropdims(beta .* (Sb- Sc)*A*x, dims = 1) ./ p R = 1 ./ Rinv AF1 = (Sb - Sc) * x[:, 2:end] AF2 = (Sb - Sc) * A * x[:, 1:end-1] - ξ = AF1 ./ AF2 - ξ = dropdims(ξ, dims = 1) + Xi = AF1 ./ AF2 + Xi = dropdims(Xi, dims = 1) - # compute π - π, Π = compute_Π(B, R, rvn, g, ξ) + # compute pi + pi, Pi = compute_Pi(B, R, rvn, g,Xi) - return (g = g, d = d, b = b, s = s, - c = c, l = l, p = p, τ = τ, - rvn = rvn, B = B, R = R, - π = π, Π = Π, ξ = ξ) + return(;g, d, b, s, c, l, p, tau, rvn, B, R, pi, Pi, Xi) end function gen_fig_1(path) @@ -784,7 +779,7 @@ function gen_fig_1(path) plt_4 = plot(path.rvn, lw=2, label=L"\tau_t l_t") plot!(plt_4, path.g, lw=2, label=L"g_t") - plot!(plt_4, path.π, lw=2, label=L"\pi_t") + plot!(plt_4, path.pi, lw=2, label=L"\pi_t") plot!(plt_4, xlabel="Time", grid=true) plot(plt_1, plt_2, plt_3, plt_4, layout=(2,2), size = (800,600)) @@ -794,7 +789,7 @@ function gen_fig_2(path) T = length(path.c) - paths = [path.ξ, path.Π] + paths = [path.Xi, path.Pi] labels = [L"\xi_t", L"\Pi_t"] plt_1 = plot() plt_2 = plot() @@ -847,17 +842,17 @@ using Random Random.seed!(42) # parameters -β = 1 / 1.05 -ρ, mg = .7, .35 -A = [ρ mg*(1 - ρ); 0.0 1.0] -C = [sqrt(1 - ρ^2) * mg / 10 0.0; 0 0] +beta = 1 / 1.05 +rho, mg = .7, .35 +A = [rho mg*(1 - rho); 0.0 1.0] +C = [sqrt(1 - rho^2) * mg / 10 0.0; 0 0] Sg = [1.0 0.0] Sd = [0.0 0.0] Sb = [0 2.135] Ss = [0.0 0.0] proc = ContStochProcess(A, C) -econ = Economy(β, Sg, Sd, Sb, Ss, proc) +econ = Economy(beta, Sg, Sd, Sb, Ss, proc) T = 50 path = compute_paths(econ, T) @@ -874,10 +869,10 @@ tags: [remove-cell] #test path.c[36] ≈ 0.6291101011610297 atol = 1e-3 #test path.B[9] ≈ 0.07442403655989423 atol = 1e-3 #test path.rvn[27] ≈ 0.35013269833342753 atol = 1e-3 - #test path.π[31] ≈ -0.05846215388377568 atol = 1e-3 + #test path.pi[31] ≈ -0.05846215388377568 atol = 1e-3 #test path.R[43] ≈ 1.0437715852385672 atol = 1e-3 - #test path.ξ[43] ≈ 1.001895202392805 atol = 1e-3 - #test path.Π[43] ≈ -0.4185282208457552 atol = 1e-3 # plot tests + #test path.xi[43] ≈ 1.001895202392805 atol = 1e-3 + #test path.Pi[43] ≈ -0.4185282208457552 atol = 1e-3 # plot tests end ``` @@ -911,7 +906,7 @@ Random.seed!(42); ```{code-cell} julia # Parameters -β = 1 / 1.05 +beta = 1 / 1.05 P = [0.8 0.2 0.0 0.0 0.5 0.5 0.0 0.0 1.0] @@ -929,7 +924,7 @@ Sb = [0.0 0.0 1.0 0.0 0.0] Ss = [0.0 0.0 0.0 1.0 0.0] proc = DiscreteStochProcess(P, x_vals) -econ = Economy(β, Sg, Sd, Sb, Ss, proc) +econ = Economy(beta, Sg, Sd, Sb, Ss, proc) T = 15 path = compute_paths(econ, T) @@ -949,7 +944,7 @@ tags: [remove-cell] #test path.c[2] ≈ 0.6147870853305598 #@test path.R ≈ [1.05, 1.05, 1.05, 1.05, 1.05, 1.0930974212983846, 1.05, 1.05, 1.05, 1.05, # 1.05, 1.05, 1.05, 1.05, 1.05] - #@test path.ξ ≈ [1.0, 1.0, 1.0, 1.0, 1.0, 0.9589548368586813, 1.0, 1.0, 1.0, 1.0, 1.0, + #@test path.xi ≈ [1.0, 1.0, 1.0, 1.0, 1.0, 0.9589548368586813, 1.0, 1.0, 1.0, 1.0, 1.0, # 1.0, 1.0, 1.0] end ``` @@ -997,21 +992,21 @@ Random.seed!(42); tags: [hide-output] --- # parameters -β = 1 / 1.05 -ρ, mg = .95, .35 -A = [0. 0. 0. ρ mg*(1-ρ); +beta = 1 / 1.05 +rho, mg = .95, .35 +A = [0. 0. 0. rho mg*(1-rho); 1. 0. 0. 0. 0.; 0. 1. 0. 0. 0.; 0. 0. 1. 0. 0.; 0. 0. 0. 0. 1.] C = zeros(5, 5) -C[1, 1] = sqrt(1 - ρ^2) * mg / 8 +C[1, 1] = sqrt(1 - rho^2) * mg / 8 Sg = [1. 0. 0. 0. 0.] Sd = [0. 0. 0. 0. 0.] Sb = [0. 0. 0. 0. 2.135] Ss = [0. 0. 0. 0. 0.] proc = ContStochProcess(A, C) -econ = Economy(β, Sg, Sd, Sb, Ss, proc) +econ = Economy(beta, Sg, Sd, Sb, Ss, proc) T = 50 path = compute_paths(econ, T) @@ -1028,7 +1023,7 @@ tags: [remove-cell] #test path.rvn[7] ≈ 0.35146870025913474 #test path.c[2] ≈ 0.6259521929536346 #test path.R[5][1] ≈ 1.0501742289013196 - #test path.ξ[10] ≈ 1.002202281639002 + #test path.xi[10] ≈ 1.002202281639002 end ``` diff --git a/lectures/dynamic_programming_squared/opt_tax_recur.md b/lectures/dynamic_programming_squared/opt_tax_recur.md index 93571209..a8e0efb2 100644 --- a/lectures/dynamic_programming_squared/opt_tax_recur.md +++ b/lectures/dynamic_programming_squared/opt_tax_recur.md @@ -726,10 +726,10 @@ import QuantEcon: simulate mutable struct Model{TF <: AbstractFloat, TM <: AbstractMatrix{TF}, TV <: AbstractVector{TF}} - β::TF - Π::TM + beta::TF + Pi::TM G::TV - Θ::TV + Theta::TV transfers::Bool U::Function Uc::Function @@ -747,31 +747,31 @@ import QuantEcon: simulate S::TI cFB::TV nFB::TV - ΞFB::TV + XiFB::TV zFB::TV end function SequentialAllocation(model) - β, Π, G, Θ = model.β, model.Π, model.G, model.Θ - mc = MarkovChain(Π) - S = size(Π, 1) # Number of states + beta, Pi, G, Theta = model.beta, model.Pi, model.G, model.Theta + mc = MarkovChain(Pi) + S = size(Pi, 1) # Number of states # now find the first best allocation - cFB, nFB, ΞFB, zFB = find_first_best(model, S, 1) + cFB, nFB, XiFB, zFB = find_first_best(model, S, 1) - return SequentialAllocation(model, mc, S, cFB, nFB, ΞFB, zFB) + return SequentialAllocation(model, mc, S, cFB, nFB, XiFB, zFB) end function find_first_best(model, S, version) if version != 1 && version != 2 throw(ArgumentError("version must be 1 or 2")) end - β, Θ, Uc, Un, G, Π = - model.β, model.Θ, model.Uc, model.Un, model.G, model.Π + beta, Theta, Uc, Un, G, Pi = + model.beta, model.Theta, model.Uc, model.Un, model.G, model.Pi function res!(out, z) c = z[1:S] n = z[S+1:end] - out[1:S] = Θ .* Uc(c, n) + Un(c, n) - out[S+1:end] = Θ .* n - c - G + out[1:S] = Theta .* Uc(c, n) + Un(c, n) + out[S+1:end] = Theta .* n - c - G end res = nlsolve(res!, 0.5 * ones(2 * S)) @@ -782,31 +782,31 @@ function find_first_best(model, S, version) if version == 1 cFB = res.zero[1:S] nFB = res.zero[S+1:end] - ΞFB = Uc(cFB, nFB) # Multiplier on the resource constraint - zFB = vcat(cFB, nFB, ΞFB) - return cFB, nFB, ΞFB, zFB + XiFB = Uc(cFB, nFB) # Multiplier on the resource constraint + zFB = vcat(cFB, nFB, XiFB) + return cFB, nFB, XiFB, zFB elseif version == 2 cFB = res.zero[1:S] nFB = res.zero[S+1:end] IFB = Uc(cFB, nFB) .* cFB + Un(cFB, nFB) .* nFB - xFB = \(I - β * Π, IFB) + xFB = \(I - beta * Pi, IFB) zFB = [vcat(cFB[s], xFB[s], xFB) for s in 1:S] return cFB, nFB, IFB, xFB, zFB end end -function time1_allocation(pas::SequentialAllocation, μ) +function time1_allocation(pas::SequentialAllocation, mu) model, S = pas.model, pas.S - Θ, β, Π, G, Uc, Ucc, Un, Unn = - model.Θ, model.β, model.Π, model.G, + Theta, beta, Pi, G, Uc, Ucc, Un, Unn = + model.Theta, model.beta, model.Pi, model.G, model.Uc, model.Ucc, model.Un, model.Unn function FOC!(out, z) c = z[1:S] n = z[S+1:2S] - Ξ = z[2S+1:end] - out[1:S] = Uc(c, n) .- μ * (Ucc(c, n) .* c .+ Uc(c, n)) .- Ξ # FOC c - out[S+1:2S] = Un(c, n) .- μ * (Unn(c, n) .* n .+ Un(c, n)) + Θ .* Ξ # FOC n - out[2S+1:end] = Θ .* n - c - G # Resource constraint + Xi = z[2S+1:end] + out[1:S] = Uc(c, n) .- mu * (Ucc(c, n) .* c .+ Uc(c, n)) .- Xi # FOC c + out[S+1:2S] = Un(c, n) .- mu * (Unn(c, n) .* n .+ Un(c, n)) + Theta .* Xi # FOC n + out[2S+1:end] = Theta .* n - c - G # Resource constraint return out end # Find the root of the FOC @@ -815,56 +815,56 @@ function time1_allocation(pas::SequentialAllocation, μ) error("Could not find LS allocation.") end z = res.zero - c, n, Ξ = z[1:S], z[S+1:2S], z[2S+1:end] + c, n, Xi = z[1:S], z[S+1:2S], z[2S+1:end] # Now compute x Inv = Uc(c, n) .* c + Un(c, n) .* n - x = \(I - β * model.Π, Inv) - return c, n, x, Ξ + x = \(I - beta * model.Pi, Inv) + return c, n, x, Xi end function time0_allocation(pas::SequentialAllocation, B_, s_0) model = pas.model - Π, Θ, G, β = model.Π, model.Θ, model.G, model.β + Pi, Theta, G, beta = model.Pi, model.Theta, model.G, model.beta Uc, Ucc, Un, Unn = model.Uc, model.Ucc, model.Un, model.Unn # First order conditions of planner's problem function FOC!(out, z) - μ, c, n, Ξ = z[1], z[2], z[3], z[4] - xprime = time1_allocation(pas, μ)[3] + mu, c, n, Xi = z[1], z[2], z[3], z[4] + xprime = time1_allocation(pas, mu)[3] out .= vcat( - Uc(c, n) .* (c - B_) .+ Un(c, n) .* n + β * dot(Π[s_0, :], xprime), - Uc(c, n) .- μ * (Ucc(c, n) .* (c - B_) + Uc(c, n)) - Ξ, - Un(c, n) .- μ * (Unn(c, n) .* n .+ Un(c, n)) + Θ[s_0] .* Ξ, - (Θ .* n .- c - G)[s_0] + Uc(c, n) .* (c - B_) .+ Un(c, n) .* n + beta * dot(Pi[s_0, :], xprime), + Uc(c, n) .- mu * (Ucc(c, n) .* (c - B_) + Uc(c, n)) - Xi, + Un(c, n) .- mu * (Unn(c, n) .* n .+ Un(c, n)) + Theta[s_0] .* Xi, + (Theta .* n .- c - G)[s_0] ) end # Find root - res = nlsolve(FOC!, [0.0, pas.cFB[s_0], pas.nFB[s_0], pas.ΞFB[s_0]]) + res = nlsolve(FOC!, [0.0, pas.cFB[s_0], pas.nFB[s_0], pas.XiFB[s_0]]) if res.f_converged == false error("Could not find time 0 LS allocation.") end return (res.zero...,) end -function time1_value(pas::SequentialAllocation, μ) +function time1_value(pas::SequentialAllocation, mu) model = pas.model - c, n, x, Ξ = time1_allocation(pas, μ) + c, n, x, Xi = time1_allocation(pas, mu) U_val = model.U.(c, n) - V = \(I - model.β*model.Π, U_val) + V = \(I - model.beta*model.Pi, U_val) return c, n, x, V end function Τ(model, c, n) Uc, Un = model.Uc.(c, n), model.Un.(c, n) - return 1 .+ Un ./ (model.Θ .* Uc) + return 1 .+ Un ./ (model.Theta .* Uc) end function simulate(pas::SequentialAllocation, B_, s_0, T, sHist = nothing) model = pas.model - Π, β, Uc = model.Π, model.β, model.Uc + Pi, beta, Uc = model.Pi, model.beta, model.Uc if isnothing(sHist) sHist = QuantEcon.simulate(pas.mc, T, init=s_0) @@ -873,25 +873,25 @@ function simulate(pas::SequentialAllocation, B_, s_0, T, sHist = nothing) nHist = similar(cHist) Bhist = similar(cHist) ΤHist = similar(cHist) - μHist = similar(cHist) + muHist = similar(cHist) RHist = zeros(T-1) # time 0 - μ, cHist[1], nHist[1], _ = time0_allocation(pas, B_, s_0) + mu, cHist[1], nHist[1], _ = time0_allocation(pas, B_, s_0) ΤHist[1] = Τ(pas.model, cHist[1], nHist[1])[s_0] Bhist[1] = B_ - μHist[1] = μ + muHist[1] = mu # time 1 onward for t in 2:T - c, n, x, Ξ = time1_allocation(pas,μ) + c, n, x, Xi = time1_allocation(pas,mu) u_c = Uc(c,n) s = sHist[t] ΤHist[t] = Τ(pas.model, c, n)[s] - Eu_c = dot(Π[sHist[t-1],:], u_c) + Eu_c = dot(Pi[sHist[t-1],:], u_c) cHist[t], nHist[t], Bhist[t] = c[s], n[s], x[s] / u_c[s] - RHist[t-1] = Uc(cHist[t-1], nHist[t-1]) / (β * Eu_c) - μHist[t] = μ + RHist[t-1] = Uc(cHist[t-1], nHist[t-1]) / (beta * Eu_c) + muHist[t] = mu end - return cHist, nHist, Bhist, ΤHist, sHist, μHist, RHist + return cHist, nHist, Bhist, ΤHist, sHist, muHist, RHist end mutable struct BellmanEquation{TP <: Model, @@ -911,7 +911,7 @@ end end function BellmanEquation(model, xgrid, policies0) - S = size(model.Π, 1) # Number of states + S = size(model.Pi, 1) # Number of states xbar = collect(extrema(xgrid)) time_0 = false cf, nf, xprimef = policies0 @@ -924,19 +924,19 @@ end function get_policies_time1(T, i_x, x, s, Vf) model, S = T.model, T.S - β, Θ, G, Π = model.β, model.Θ, model.G, model.Π + beta, Theta, G, Pi = model.beta, model.Theta, model.G, model.Pi U, Uc, Un = model.U, model.Uc, model.Un function objf(z, grad) c, xprime = z[1], z[2:end] n = c + G[s] Vprime = [Vf[sprime](xprime[sprime]) for sprime in 1:S] - return -(U(c, n) + β * dot(Π[s, :], Vprime)) + return -(U(c, n) + beta * dot(Pi[s, :], Vprime)) end function cons(z, grad) c, xprime = z[1], z[2:end] n = c+G[s] - return x - Uc(c, n) * c - Un(c, n) * n - β * dot(Π[s, :], xprime) + return x - Uc(c, n) * c - Un(c, n) * n - beta * dot(Pi[s, :], xprime) end lb = vcat(0, T.xbar[1] * ones(S)) ub = vcat(1 - G[s], T.xbar[2] * ones(S)) @@ -962,18 +962,18 @@ end function get_policies_time0(T, B_, s0, Vf) model, S = T.model, T.S - β, Θ, G, Π = model.β, model.Θ, model.G, model.Π + beta, Theta, G, Pi = model.beta, model.Theta, model.G, model.Pi U, Uc, Un = model.U, model.Uc, model.Un function objf(z, grad) c, xprime = z[1], z[2:end] n = c + G[s0] Vprime = [Vf[sprime](xprime[sprime]) for sprime in 1:S] - return -(U(c, n) + β * dot(Π[s0, :], Vprime)) + return -(U(c, n) + beta * dot(Pi[s0, :], Vprime)) end function cons(z, grad) c, xprime = z[1], z[2:end] n = c + G[s0] - return -Uc(c, n) * (c - B_) - Un(c, n) * n - β * dot(Π[s0, :], xprime) + return -Uc(c, n) * (c - B_) - Un(c, n) * n - beta * dot(Pi[s0, :], xprime) end lb = vcat(0, T.xbar[1] * ones(S)) ub = vcat(1-G[s0], T.xbar[2] * ones(S)) @@ -1295,41 +1295,41 @@ The above steps are implemented in a type called RecursiveAllocation --- tags: [output_scroll] --- - struct RecursiveAllocation{TP <: Model, TI <: Integer, +struct RecursiveAllocation{TP <: Model, TI <: Integer, TVg <: AbstractVector, TVv <: AbstractVector, TVp <: AbstractArray} model::TP mc::MarkovChain S::TI T::BellmanEquation - μgrid::TVg + mugrid::TVg xgrid::TVg Vf::TVv policies::TVp end -function RecursiveAllocation(model, μgrid) - mc = MarkovChain(model.Π) +function RecursiveAllocation(model, mugrid) + mc = MarkovChain(model.Pi) G = model.G - S = size(model.Π, 1) # Number of states + S = size(model.Pi, 1) # Number of states # Now find the first best allocation - Vf, policies, T, xgrid = solve_time1_bellman(model, μgrid) + Vf, policies, T, xgrid = solve_time1_bellman(model, mugrid) T.time_0 = true # Bellman equation now solves time 0 problem - return RecursiveAllocation(model, mc, S, T, μgrid, xgrid, Vf, policies) + return RecursiveAllocation(model, mc, S, T, mugrid, xgrid, Vf, policies) end -function solve_time1_bellman(model, μgrid) - μgrid0 = μgrid - S = size(model.Π, 1) +function solve_time1_bellman(model, mugrid) + mugrid0 = mugrid + S = size(model.Pi, 1) # First get initial fit PP = SequentialAllocation(model) - c = zeros(length(μgrid), 2) + c = zeros(length(mugrid), 2) n = similar(c) x = similar(c) V = similar(c) - for (i, μ) in enumerate(μgrid0) - c[i, :], n[i, :], x[i, :], V[i, :] = time1_value(PP, μ) + for (i, mu) in enumerate(mugrid0) + c[i, :], n[i, :], x[i, :], V[i, :] = time1_value(PP, mu) end Vf = Vector{AbstractInterpolation}(undef, 2) cf = similar(Vf) @@ -1346,7 +1346,7 @@ function solve_time1_bellman(model, μgrid) policies = [cf, nf, xprimef] # Create xgrid xbar = [maximum(minimum(x, dims = 1)), minimum(maximum(x, dims = 1))] - xgrid = range(xbar[1], xbar[2], length = length(μgrid0)) + xgrid = range(xbar[1], xbar[2], length = length(mugrid0)) # Now iterate on bellman equation T = BellmanEquation(model, xgrid, policies) diff = 1.0 @@ -1410,19 +1410,19 @@ end function simulate(pab::RecursiveAllocation, B_, s_0, T, sHist = QuantEcon.simulate(mc, s_0, T)) model, S, policies = pab.model, pab.S, pab.policies - β, Π, Uc = model.β, model.Π, model.Uc + beta, Pi, Uc = model.beta, model.Pi, model.Uc cf, nf, xprimef = policies[1], policies[2], policies[3] cHist = zeros(T) nHist = similar(cHist) Bhist = similar(cHist) ΤHist = similar(cHist) - μHist = similar(cHist) + muHist = similar(cHist) RHist = zeros(T - 1) # time 0 cHist[1], nHist[1], xprime = time0_allocation(pab, B_, s_0) ΤHist[1] = Τ(pab.model, cHist[1], nHist[1])[s_0] Bhist[1] = B_ - μHist[1] = 0.0 + muHist[1] = 0.0 # time 1 onward for t in 2:T s, x = sHist[t], xprime[sHist[t]] @@ -1431,12 +1431,12 @@ function simulate(pab::RecursiveAllocation, B_, s_0, T, xprime = [xprimef[s, sprime](x) for sprime in 1:S] ΤHist[t] = Τ(pab.model, c, n)[s] u_c = Uc(c, n) - Eu_c = dot(Π[sHist[t-1], :], u_c) - μHist[t] = pab.Vf[s](x) - RHist[t-1] = Uc(cHist[t-1], nHist[t-1]) / (β * Eu_c) + Eu_c = dot(Pi[sHist[t-1], :], u_c) + muHist[t] = pab.Vf[s](x) + RHist[t-1] = Uc(cHist[t-1], nHist[t-1]) / (beta * Eu_c) cHist[t], nHist[t], Bhist[t] = c[s], n, x / u_c[s] end - return cHist, nHist, Bhist, ΤHist, sHist, μHist, RHist + return cHist, nHist, Bhist, ΤHist, sHist, muHist, RHist end ``` @@ -1490,29 +1490,29 @@ This utility function is implemented in the type CRRAutility ```{code-cell} julia function crra_utility(; - β = 0.9, - σ = 2.0, - γ = 2.0, - Π = 0.5 * ones(2, 2), + beta = 0.9, + sigma = 2.0, + gamma = 2.0, + Pi = 0.5 * ones(2, 2), G = [0.1, 0.2], - Θ = ones(2), + Theta = ones(2), transfers = false ) function U(c, n) - if σ == 1.0 + if sigma == 1.0 U = log(c) else - U = (c.^(1.0 .- σ) .- 1.0) / (1.0 - σ) + U = (c.^(1.0 .- sigma) .- 1.0) / (1.0 - sigma) end - return U .- n.^(1 + γ) / (1 + γ) + return U .- n.^(1 + gamma) / (1 + gamma) end # Derivatives of utility function - Uc(c,n) = c.^(-σ) - Ucc(c,n) = -σ * c.^(-σ - 1.0) - Un(c,n) = -n.^γ - Unn(c,n) = -γ * n.^(γ - 1.0) + Uc(c,n) = c.^(-sigma) + Ucc(c,n) = -sigma * c.^(-sigma - 1.0) + Un(c,n) = -n.^gamma + Unn(c,n) = -gamma * n.^(gamma - 1.0) n_less_than_one = false - return Model(β, Π, G, Θ, transfers, + return Model(beta, Pi, G, Theta, transfers, U, Uc, Ucc, Un, Unn, n_less_than_one) end ``` @@ -1529,9 +1529,9 @@ using Random Random.seed!(42) # For reproducible results. M_time_example = crra_utility(G=[0.1, 0.1, 0.1, 0.2, 0.1, 0.1], - Θ=ones(6)) # Θ can in principle be random + Theta=ones(6)) # Theta can in principle be random -M_time_example.Π = [0.0 1.0 0.0 0.0 0.0 0.0; +M_time_example.Pi = [0.0 1.0 0.0 0.0 0.0 0.0; 0.0 0.0 1.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.5 0.5 0.0; 0.0 0.0 0.0 0.0 0.0 1.0; @@ -1556,9 +1556,9 @@ titles = hcat("Consumption", "Output") sim_seq_l_plot = [sim_seq_l[1:4]..., M_time_example.G[sHist_l], - M_time_example.Θ[sHist_l].*sim_seq_l[2]] + M_time_example.Theta[sHist_l].*sim_seq_l[2]] sim_seq_h_plot = [sim_seq_h[1:4]..., M_time_example.G[sHist_h], - M_time_example.Θ[sHist_h].*sim_seq_h[2]] + M_time_example.Theta[sHist_h].*sim_seq_h[2]] #plots = plot(layout=(3,2), size=(800,600)) @@ -1579,7 +1579,7 @@ tags: [remove-cell] --- @testset begin @test M_time_example.G[sHist_l] ≈ [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] - #test M_time_example.Θ[sHist_l] .* sim_seq_l[2] ≈ [1.026385289423105, 0.9945696863679917, + #test M_time_example.Theta[sHist_l] .* sim_seq_l[2] ≈ [1.026385289423105, 0.9945696863679917, # 0.9945696863679917, 0.9945696863679917, # 0.9945696863679917, 0.9945696863679917, # 0.9945696863679917] @@ -1701,7 +1701,7 @@ Random.seed!(42); # For reproducible results. ``` ```{code-cell} julia -M2 = crra_utility(G=[0.15], Π=ones(1, 1), Θ=[1.0]) +M2 = crra_utility(G=[0.15], Pi=ones(1, 1), Theta=[1.0]) PP_seq_time0 = SequentialAllocation(M2) # solve sequential problem @@ -1819,20 +1819,20 @@ $$ We will write a new constructor LogUtility to represent this utility function ```{code-cell} julia -function log_utility(;β = 0.9, - ψ = 0.69, - Π = 0.5 * ones(2, 2), +function log_utility(;beta = 0.9, + psi = 0.69, + Pi = 0.5 * ones(2, 2), G = [0.1, 0.2], - Θ = ones(2), + Theta = ones(2), transfers = false) # Derivatives of utility function - U(c,n) = log(c) + ψ * log(1 - n) + U(c,n) = log(c) + psi * log(1 - n) Uc(c,n) = 1 ./ c Ucc(c,n) = -c.^(-2.0) - Un(c,n) = -ψ ./ (1.0 .- n) - Unn(c,n) = -ψ ./ (1.0 .- n).^2.0 + Un(c,n) = -psi ./ (1.0 .- n) + Unn(c,n) = -psi ./ (1.0 .- n).^2.0 n_less_than_one = true - return Model(β, Π, G, Θ, transfers, + return Model(beta, Pi, G, Theta, transfers, U, Uc, Ucc, Un, Unn, n_less_than_one) end ``` @@ -1853,9 +1853,9 @@ Random.seed!(42); # For reproducible results. ```{code-cell} julia M1 = log_utility() -μ_grid = range(-0.6, 0.0, length = 200) +mu_grid = range(-0.6, 0.0, length = 200) PP_seq = SequentialAllocation(M1) # Solve sequential problem -PP_bel = RecursiveAllocation(M1, μ_grid) # Solve recursive problem +PP_bel = RecursiveAllocation(M1, mu_grid) # Solve recursive problem T = 20 sHist = [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1] @@ -1865,8 +1865,8 @@ sim_seq = simulate(PP_seq, 0.5, 1, T, sHist) sim_bel = simulate(PP_bel, 0.5, 1, T, sHist) # Plot policies -sim_seq_plot = [sim_seq[1:4]..., M1.G[sHist], M1.Θ[sHist].*sim_seq[2]] -sim_bel_plot = [sim_bel[1:4]..., M1.G[sHist], M1.Θ[sHist].*sim_bel[2]] +sim_seq_plot = [sim_seq[1:4]..., M1.G[sHist], M1.Theta[sHist].*sim_seq[2]] +sim_bel_plot = [sim_bel[1:4]..., M1.G[sHist], M1.Theta[sHist].*sim_bel[2]] titles = hcat("Consumption", "Labor Supply", From 50e6b2608e96e2407f0b27a5cc8d6a1f2f0d22a6 Mon Sep 17 00:00:00 2001 From: annabellasd Date: Tue, 10 Oct 2023 18:24:39 -0800 Subject: [PATCH 23/26] updating merge continous time files last --- lectures/continuous_time/covid_sde.md | 125 ++++++++++++------------- lectures/continuous_time/seir_model.md | 81 ++++++++-------- 2 files changed, 101 insertions(+), 105 deletions(-) diff --git a/lectures/continuous_time/covid_sde.md b/lectures/continuous_time/covid_sde.md index 6f685e16..9ba314db 100644 --- a/lectures/continuous_time/covid_sde.md +++ b/lectures/continuous_time/covid_sde.md @@ -230,41 +230,40 @@ First, construct our $F$ from {eq}`dfcvsde` and $G$ from {eq}`dG` ```{code-cell} julia function F(x, p, t) - s, i, r, d, R_0, delta = x - (;gamma, R_bar_0, eta, sigma, xi, theta, delta_bar) = p - - return [-gamma * R_0 * s * i; # ds/dt - gamma * R_0 * s * i - gamma * i; # di/dt - (1 - delta) * gamma * i; # dr/dt - delta * gamma * i; # dd/dt - eta * (R_bar_0(t, p) - R_0); # dR_0/dt - theta * (delta_bar - delta); # ddelta/dt - ] + s, i, r, d, R₀, δ = x + (;γ, R̄₀, η, σ, ξ, θ, δ_bar) = p + + return [-γ*R₀*s*i; # ds/dt + γ*R₀*s*i - γ*i; # di/dt + (1-δ)*γ*i; # dr/dt + δ*γ*i; # dd/dt + η*(R̄₀(t, p) - R₀);# dR₀/dt + θ*(δ_bar - δ); # dδ/dt + ] end function G(x, p, t) - s, i, r, d, R_0, delta = x - (;gamma, R_bar_0, eta, sigma, xi, theta, delta_bar) = p + s, i, r, d, R₀, δ = x + (;γ, R̄₀, η, σ, ξ, θ, δ_bar) = p - return [0; 0; 0; 0; sigma * sqrt(R_0); xi * sqrt(delta * (1 - delta))] + return [0; 0; 0; 0; σ*sqrt(R₀); ξ*sqrt(δ * (1-δ))] end ``` Next create a settings generator, and then define a [SDEProblem](https://docs.sciml.ai/stable/tutorials/sde_example/#Example-2:-Systems-of-SDEs-with-Diagonal-Noise-1) with Diagonal Noise. ```{code-cell} julia -p_gen(;T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, - R_0_n = 1.6, R_bar_0 = (t, p) -> p.R_0_n, delta_bar = 0.01, - sigma = 0.03, xi = 0.004, theta = 0.2, N = 3.3E8) = (;T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N) - -p = p_gen() # use all defaults +p_gen = @with_kw (T = 550.0, γ = 1.0 / 18, η = 1.0 / 20, + R₀_n = 1.6, R̄₀ = (t, p) -> p.R₀_n, δ_bar = 0.01, + σ = 0.03, ξ = 0.004, θ = 0.2, N = 3.3E8) +p = p_gen() # use all defaults i_0 = 25000 / p.N r_0 = 0.0 d_0 = 0.0 s_0 = 1.0 - i_0 - r_0 - d_0 -R_bar_0_0 = 0.5 # starting in lockdown -delta_0 = p.delta_bar -x_0 = [s_0, i_0, r_0, d_0, R_bar_0_0, delta_0] +R̄₀_0 = 0.5 # starting in lockdown +δ_0 = p.δ_bar +x_0 = [s_0, i_0, r_0, d_0, R̄₀_0, δ_0] prob = SDEProblem(F, G, x_0, (0, p.T), p) ``` @@ -371,29 +370,29 @@ We will shut down the shocks to the mortality rate (i.e. $\xi = 0$) to focus on Consider $\eta = 1/50$ and $\eta = 1/20$, where we start at the same initial condition of $R_0(0) = 0.5$. ```{code-cell} julia -function generate_eta_experiment(eta; p_gen = p_gen, trajectories = 100, saveat = 1.0, x_0 = x_0, T = 120.0) - p = p_gen(eta = eta, xi = 0.0) +function generate_η_experiment(η; p_gen = p_gen, trajectories = 100, + saveat = 1.0, x_0 = x_0, T = 120.0) + p = p_gen(η = η, ξ = 0.0) ensembleprob = EnsembleProblem(SDEProblem(F, G, x_0, (0, T), p)) - sol = solve(ensembleprob, SOSRI(), EnsembleThreads(), trajectories = trajectories, saveat = saveat) + sol = solve(ensembleprob, SOSRI(), EnsembleThreads(), + trajectories = trajectories, saveat = saveat) return EnsembleSummary(sol) end # Evaluate two different lockdown scenarios -eta_1 = 1 / 50 -eta_2 = 1 / 20 -summ_1 = generate_eta_experiment(eta_1) -summ_2 = generate_eta_experiment(eta_2) - -plot(summ_1, idxs = (4, 5), +η_1 = 1/50 +η_2 = 1/20 +summ_1 = generate_η_experiment(η_1) +summ_2 = generate_η_experiment(η_2) +plot(summ_1, idxs = (4,5), title = ["Proportion Dead" L"R_0"], ylabel = [L"d(t)" L"R_0(t)"], xlabel = L"t", - legend = :topleft, - labels = L"Middle 95% Quantile, $\eta = %$eta_1$", + legend = [:topleft :bottomright], + labels = L"Middle 95% Quantile, $\eta = %$η_1$", layout = (2, 1), size = (900, 900), fillalpha = 0.5) - -plot!(summ_2, idxs = (4, 5), - legend = :topleft, - labels = L"Middle 95% Quantile, $\eta = %$eta_2$", size = (900, 900), fillalpha = 0.5) +plot!(summ_2, idxs = (4,5), + legend = [:topleft :bottomright], + labels = L"Middle 95% Quantile, $\eta = %$η_2$", size = (900, 900), fillalpha = 0.5) ``` While the the mean of the $d(t)$ increases, unsurprisingly, we see that the 95% quantile for later time periods is also much larger - even after the $R_0$ has converged. @@ -412,24 +411,24 @@ Since empirical estimates of $R_0(t)$ discussed in {cite}`NBERw27128` and other We start the model with 100,000 active infections. ```{code-cell} julia -R_0_L = 0.5 # lockdown -eta_experiment = 1.0 / 10 -sigma_experiment = 0.04 +R₀_L = 0.5 # lockdown +η_experiment = 1.0/10 +σ_experiment = 0.04 +R̄₀_lift_early(t, p) = t < 30.0 ? R₀_L : 2.0 +R̄₀_lift_late(t, p) = t < 120.0 ? R₀_L : 2.0 -R_bar_0_lift_early(t, p) = t < 30.0 ? R_0_L : 2.0 -R_bar_0_lift_late(t, p) = t < 120.0 ? R_0_L : 2.0 +p_early = p_gen(R̄₀ = R̄₀_lift_early, η = η_experiment, σ = σ_experiment) +p_late = p_gen(R̄₀ = R̄₀_lift_late, η = η_experiment, σ = σ_experiment) -p_early = p_gen(R_bar_0 = R_bar_0_lift_early, eta = eta_experiment, sigma = sigma_experiment) -p_late = p_gen(R_bar_0 = R_bar_0_lift_late, eta = eta_experiment, sigma = sigma_experiment) # initial conditions i_0 = 100000 / p_early.N r_0 = 0.0 d_0 = 0.0 s_0 = 1.0 - i_0 - r_0 - d_0 -delta_0 = p_early.delta_bar +δ_0 = p_early.δ_bar -x_0 = [s_0, i_0, r_0, d_0, R_0_L, delta_0] # start in lockdown +x_0 = [s_0, i_0, r_0, d_0, R₀_L, δ_0] # start in lockdown prob_early = SDEProblem(F, G, x_0, (0, p_early.T), p_early) prob_late = SDEProblem(F, G, x_0, (0, p_late.T), p_late) ``` @@ -439,13 +438,13 @@ Simulating for a single realization of the shocks, we see the results are qualit ```{code-cell} julia sol_early = solve(prob_early, SOSRI()) sol_late = solve(prob_late, SOSRI()) -plot(sol_early, vars = [5, 1, 2, 4], +plot(sol_early, vars = [5, 1,2,4], title = [L"R_0" "Susceptible" "Infected" "Dead"], layout = (2, 2), size = (900, 600), ylabel = [L"R_0(t)" L"s(t)" L"i(t)" L"d(t)"], xlabel = L"t", legend = [:bottomright :topright :topright :topleft], label = ["Early" "Early" "Early" "Early"]) -plot!(sol_late, vars = [5, 1, 2, 4], +plot!(sol_late, vars = [5, 1,2,4], legend = [:bottomright :topright :topright :topleft], label = ["Late" "Late" "Late" "Late"], xlabel = L"t") ``` @@ -536,26 +535,24 @@ We will redo the "Ending Lockdown" simulation from above, where the only differe ```{code-cell} julia function F_reinfect(x, p, t) - s, i, r, d, R_0, delta = x - (;gamma, R_bar_0, eta, sigma, xi, theta, delta_bar, nu) = p - - return [ - -gamma * R_0 * s * i + nu * r; # ds/dt - gamma * R_0 * s * i - gamma * i; # di/dt - (1 - delta) * gamma * i - nu * r; # dr/dt - delta * gamma * i; # dd/dt - eta * (R_bar_0(t, p) - R_0); # dR_0/dt - theta * (delta_bar - delta); # ddelta/dt - ] + s, i, r, d, R₀, δ = x + (;γ, R̄₀, η, σ, ξ, θ, δ_bar, ν) = p + + return [-γ*R₀*s*i + ν*r; # ds/dt + γ*R₀*s*i - γ*i; # di/dt + (1-δ)*γ*i - ν*r # dr/dt + δ*γ*i; # dd/dt + η*(R̄₀(t, p) - R₀);# dR₀/dt + θ*(δ_bar - δ); # dδ/dt + ] end -p_re_gen(;T = 550.0, gamma = 1.0 / 18, eta = 1.0 / 20, - R_0_n = 1.6, R_bar_0 = (t, p) -> p.R_0_n, - delta_bar = 0.01, sigma = 0.03, xi = 0.004, theta = 0.2, - N = 3.3E8, nu = 1/360) = (;T, gamma, eta, R_0_n, R_bar_0, delta_bar, sigma, xi, theta, N, nu) +p_re_gen = @with_kw ( T = 550.0, γ = 1.0 / 18, η = 1.0 / 20, + R₀_n = 1.6, R̄₀ = (t, p) -> p.R₀_n, + δ_bar = 0.01, σ = 0.03, ξ = 0.004, θ = 0.2, N = 3.3E8, ν = 1/360) -p_re_early = p_re_gen(R_bar_0 = R_bar_0_lift_early, eta = eta_experiment, sigma = sigma_experiment) -p_re_late = p_re_gen(R_bar_0 = R_bar_0_lift_late, eta = eta_experiment, sigma = sigma_experiment) +p_re_early = p_re_gen(R̄₀ = R̄₀_lift_early, η = η_experiment, σ = σ_experiment) +p_re_late = p_re_gen(R̄₀ = R̄₀_lift_late, η = η_experiment, σ = σ_experiment) trajectories = 400 saveat = 1.0 diff --git a/lectures/continuous_time/seir_model.md b/lectures/continuous_time/seir_model.md index b40418c8..c0a36aa9 100644 --- a/lectures/continuous_time/seir_model.md +++ b/lectures/continuous_time/seir_model.md @@ -171,13 +171,13 @@ We begin by implementing a simple version of this model with a constant $R_0$ an First, define the system of equations ```{code-cell} julia -function F_simple(x, p, t; gamma = 1/18, R_0 = 3.0, sigma = 1/5.2) +function F_simple(x, p, t; γ = 1/18, R₀ = 3.0, σ = 1/5.2) s, e, i, r = x - return [-gamma * R_0 * s * i; # ds/dt - gamma * R_0 * s * i - sigma * e; # de/dt - sigma * e - gamma * i; # di/dt - gamma * i; # dr/dt + return [-γ*R₀*s*i; # ds/dt = -γR₀si + γ*R₀*s*i - σ*e;# de/dt = γR₀si -σe + σ*e - γ*i; # di/dt = σe -γi + γ*i; # dr/dt = γi ] end ``` @@ -195,7 +195,7 @@ tspan = (0.0, 350.0) # ≈ 350 days prob = ODEProblem(F_simple, x_0, tspan) ``` -With this, choose an ODE algorithm and solve the initial value problem. A good default algorithm for non-stiff ODEs of this sort might be `Tsit5()`, which is the Tsitouras 5/4 Runge-Kutta method. +With this, choose an ODE algorithm and solve the initial value problem. A good default algorithm for non-stiff ODEs of this sort might be `Tsit5()`, which is the Tsitouras 5/4 Runge-Kutta method). ```{code-cell} julia sol = solve(prob, Tsit5()) @@ -242,7 +242,7 @@ While we could integrate the deaths given the solution to the model ex-post, it This is a common trick when solving systems of ODEs. While equivalent in principle to using the appropriate quadrature scheme, this becomes especially convenient when adaptive time-stepping algorithms are used to solve the ODEs (i.e. there is not a regular time grid). Note that when doing so, $d(0) = \int_0^0 \delta \gamma i(\tau) d \tau = 0$ is the initial condition. -The system {eq}`seir_system` and the supplemental equations can be written in vector form $x := [s, e, i, r, R_0, c, d]$ with parameter tuple $p := (\sigma, \gamma, \eta, \delta, \bar{R}_0(\cdot))$ +The system {eq}`seir_system` and the supplemental equations can be written in vector form $x := [s, e, i, r, R₀, c, d]$ with parameter tuple $p := (\sigma, \gamma, \eta, \delta, \bar{R}_0(\cdot))$ Note that in those parameters, the targeted reproduction number, $\bar{R}_0(t)$, is an exogenous function. @@ -289,36 +289,35 @@ First, construct our $F$ from {eq}`dfcv` ```{code-cell} julia function F(x, p, t) - s, e, i, r, R_0, c, d = x - (;sigma, gamma, R_bar_0, eta, delta) = p - - return [-gamma * R_0 * s * i; # ds/dt - gamma * R_0 * s * i - sigma * e; # de/dt - sigma * e - gamma * i; # di/dt - gamma * i; # dr/dt - eta * (R_bar_0(t, p) - R_0); # dR_0/dt - sigma * e; # dc/dt - delta * gamma * i; # dd/dt + s, e, i, r, R₀, c, d = x + (;σ, γ, R̄₀, η, δ) = p + + return [-γ*R₀*s*i; # ds/dt + γ*R₀*s*i - σ*e; # de/dt + σ*e - γ*i; # di/dt + γ*i; # dr/dt + η*(R̄₀(t, p) - R₀);# dR₀/dt + σ*e; # dc/dt + δ*γ*i; # dd/dt ] end; - ``` This function takes the vector `x` of states in the system and extracts the fixed parameters passed into the `p` object. -The only confusing part of the notation is the `R_bar_0(t, p)` which evaluates the `p.R_bar_0` at this time (and also allows it to depend on the `p` parameter). +The only confusing part of the notation is the `R̄₀(t, p)` which evaluates the `p.R̄₀` at this time (and also allows it to depend on the `p` parameter). ### Parameters -#####HERE ENDED + The baseline parameters are put into a named tuple generator (see previous lectures using [Parameters.jl](https://github.com/mauro3/Parameters.jl)) with default values discussed above. ```{code-cell} julia -p_gen(;T = 550.0, gamma = 1.0 / 18, sigma = 1 / 5.2, eta = 1.0 / 20, - R_0_n = 1.6, delta = 0.01, N = 3.3E8, - R_bar_0 = (t, p) -> p.R_0_n) = (;T, gamma, sigma, eta, R_0_n, delta, N, R_bar_0) +p_gen = @with_kw ( T = 550.0, γ = 1.0 / 18, σ = 1 / 5.2, η = 1.0 / 20, + R₀_n = 1.6, δ = 0.01, N = 3.3E8, + R̄₀ = (t, p) -> p.R₀_n); ``` -Note that the default $\bar{R}_0(t)$ function always equals $R_{0n}$ -- a parameterizable natural level of $R_0$ used only by the `R_bar_0` function +Note that the default $\bar{R}_0(t)$ function always equals $R_{0n}$ -- a parameterizable natural level of $R_0$ used only by the `R̄₀` function Setting initial conditions, we choose a fixed $s, i, e, r$, as well as $R_0(0) = R_{0n}$ and $m(0) = 0.01$ @@ -329,7 +328,7 @@ i_0 = 1E-7 e_0 = 4.0 * i_0 s_0 = 1.0 - i_0 - e_0 -x_0 = [s_0, e_0, i_0, 0.0, p.R_0_n, 0.0, 0.0] +x_0 = [s_0, e_0, i_0, 0.0, p.R₀_n, 0.0, 0.0] tspan = (0.0, p.T) prob = ODEProblem(F, x_0, tspan, p) ``` @@ -373,9 +372,9 @@ Let's start with the case where $\bar{R}_0(t) = R_{0n}$ is constant. We calculate the time path of infected people under different assumptions of $R_{0n}$: ```{code-cell} julia -R_0_n_vals = range(1.6, 3.0, length = 6) -sols = [solve(ODEProblem(F, x_0, tspan, p_gen(R_0_n = R_0_n)), - Tsit5(), saveat=0.5) for R_0_n in R_0_n_vals]; +R₀_n_vals = range(1.6, 3.0, length = 6) +sols = [solve(ODEProblem(F, x_0, tspan, p_gen(R₀_n = R₀_n)), + Tsit5(), saveat=0.5) for R₀_n in R₀_n_vals]; ``` Here we chose `saveat=0.5` to get solutions that were evenly spaced every `0.5`. @@ -385,7 +384,7 @@ Changing the saved points is just a question of storage/interpolation, and does Let's plot current cases as a fraction of the population. ```{code-cell} julia -labels = permutedims([L"R_0 = %$r" for r in R_0_n_vals]) +labels = permutedims([L"R_0 = %$r" for r in R₀_n_vals]) infecteds = [sol[3,:] for sol in sols] plot(infecteds, label=labels, legend=:topleft, lw = 2, xlabel = L"t", ylabel = L"i(t)", title = "Current Cases") @@ -414,21 +413,21 @@ In the simple case, where $\bar{R}_0(t) = R_{0n}$ is independent of the state, t We will examine the case where $R_0(0) = 3$ and then it falls to $R_{0n} = 1.6$ due to the progressive adoption of stricter mitigation measures. -The parameter `eta` controls the rate, or the speed at which restrictions are +The parameter `η` controls the rate, or the speed at which restrictions are imposed. We consider several different rates: ```{code-cell} julia -eta_vals = [1/5, 1/10, 1/20, 1/50, 1/100] -labels = permutedims([L"\eta = %$eta" for eta in eta_vals]); +η_vals = [1/5, 1/10, 1/20, 1/50, 1/100] +labels = permutedims([L"\eta = %$η" for η in η_vals]); ``` Let's calculate the time path of infected people, current cases, and mortality ```{code-cell} julia x_0 = [s_0, e_0, i_0, 0.0, 3.0, 0.0, 0.0] -sols = [solve(ODEProblem(F, x_0, tspan, p_gen(eta=eta)), Tsit5(), saveat=0.5) for eta in eta_vals]; +sols = [solve(ODEProblem(F, x_0, tspan, p_gen(η=η)), Tsit5(), saveat=0.5) for η in η_vals]; ``` Next, plot the $R_0$ over time: @@ -469,11 +468,11 @@ The parameters considered here start the model with 25,000 active infections and 75,000 agents already exposed to the virus and thus soon to be contagious. ```{code-cell} julia -R_0_L = 0.5 # lockdown -R_bar_0_lift_early(t, p) = t < 30.0 ? R_0_L : 2.0 -R_bar_0_lift_late(t, p) = t < 120.0 ? R_0_L : 2.0 -p_early = p_gen(R_bar_0 = R_bar_0_lift_early, eta = 10.0) -p_late = p_gen(R_bar_0 = R_bar_0_lift_late, eta = 10.0) +R₀_L = 0.5 # lockdown +R̄₀_lift_early(t, p) = t < 30.0 ? R₀_L : 2.0 +R̄₀_lift_late(t, p) = t < 120.0 ? R₀_L : 2.0 +p_early = p_gen(R̄₀= R̄₀_lift_early, η = 10.0) +p_late = p_gen(R̄₀= R̄₀_lift_late, η = 10.0) # initial conditions @@ -481,9 +480,9 @@ i_0 = 25000 / p_early.N e_0 = 75000 / p_early.N s_0 = 1.0 - i_0 - e_0 -x_0 = [s_0, e_0, i_0, 0.0, R_0_L, 0.0, 0.0] # start in lockdown +x_0 = [s_0, e_0, i_0, 0.0, R₀_L, 0.0, 0.0] # start in lockdown -# create two problems, with rapid movement of R_0(t) towards R_bar_0(t) +# create two problems, with rapid movement of R₀(t) towards R̄₀(t) prob_early = ODEProblem(F, x_0, tspan, p_early) prob_late = ODEProblem(F, x_0, tspan, p_late) ``` @@ -502,7 +501,7 @@ plot!(sol_late, vars = [7], label = "Lift Late", xlabel = L"t") Next we examine the daily deaths, $\frac{d D(t)}{dt} = N \delta \gamma i(t)$. ```{code-cell} julia -flow_deaths(sol, p) = p.N * p.delta * p.gamma * sol[3,:] +flow_deaths(sol, p) = p.N * p.δ * p.γ * sol[3,:] plot(sol_early.t, flow_deaths(sol_early, p_early), title = "Flow Deaths", label = "Lift Early") plot!(sol_late.t, flow_deaths(sol_late, p_late), label = "Lift Late", xlabel = L"t") From bd7d74f6a059bef40d7d42e9dcf7522385371edb Mon Sep 17 00:00:00 2001 From: annabellasd Date: Mon, 6 Nov 2023 15:26:19 -0800 Subject: [PATCH 24/26] Updated with Trang's Comments --- lectures/dynamic_programming_squared/amss.md | 10 ++-- .../dynamic_programming_squared/dyn_stack.md | 7 ++- .../dynamic_programming_squared/lqramsey.md | 55 +++++++++---------- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/lectures/dynamic_programming_squared/amss.md b/lectures/dynamic_programming_squared/amss.md index a3afd086..6c63b9f1 100644 --- a/lectures/dynamic_programming_squared/amss.md +++ b/lectures/dynamic_programming_squared/amss.md @@ -542,7 +542,7 @@ function time1_value(pas::SequentialAllocation, mu::Real) end -function Τ(model::Model, c::Union{Real,Vector}, n::Union{Real,Vector}) +function T(model::Model, c::Union{Real,Vector}, n::Union{Real,Vector}) Uc, Un = model.Uc.(c, n), model.Un.(c, n) return 1. .+ Un./(model.Theta .* Uc) end @@ -562,12 +562,12 @@ function simulate(pas::SequentialAllocation, cHist = zeros(T) nHist = zeros(T) Bhist = zeros(T) - ΤHist = zeros(T) + THist = zeros(T) muHist = zeros(T) RHist = zeros(T-1) # time 0 mu, cHist[1], nHist[1], _ = time0_allocation(pas, B_, s_0) - ΤHist[1] = Τ(pas.model, cHist[1], nHist[1])[s_0] + THist[1] = T(pas.model, cHist[1], nHist[1])[s_0] Bhist[1] = B_ muHist[1] = mu # time 1 onward @@ -575,13 +575,13 @@ function simulate(pas::SequentialAllocation, c, n, x, Xi = time1_allocation(pas,mu) u_c = Uc(c,n) s = sHist[t] - ΤHist[t] = Τ(pas.model, c, n)[s] + THist[t] = T(pas.model, c, n)[s] Eu_c = dot(Pi[sHist[t-1],:], u_c) cHist[t], nHist[t], Bhist[t] = c[s], n[s], x[s] / u_c[s] RHist[t-1] = Uc(cHist[t-1], nHist[t-1]) / (beta * Eu_c) muHist[t] = mu end - return cHist, nHist, Bhist, ΤHist, sHist, muHist, RHist + return cHist, nHist, Bhist, THist, sHist, muHist, RHist end diff --git a/lectures/dynamic_programming_squared/dyn_stack.md b/lectures/dynamic_programming_squared/dyn_stack.md index 9542d8f6..36012503 100644 --- a/lectures/dynamic_programming_squared/dyn_stack.md +++ b/lectures/dynamic_programming_squared/dyn_stack.md @@ -929,7 +929,7 @@ We define named tuples and default values for the model and solver settings, and instantiate one copy of each ```{code-cell} julia -model(;a0 = 10, a1 = 2, beta = 0.96, gamma = 120., n = 300) = (; a0, a1, beta, gamma, n) +model(;a0 = 10, a1 = 2, beta = 0.96, gamma = 120., n = 300) = (; a0, a1, beta, gamma, n) # things like tolerances, etc. settings(;tol0 = 1e-8,tol1 = 1e-16,tol2 = 1e-2) = (;tol0, tol1, tol2) @@ -1166,7 +1166,7 @@ P_tilde # value function in the follower's problem ```{code-cell} julia # manually check that P is an approximate fixed point -all((P - ((R + F' * Q * F) + beta * (A - B * F)' * P * (A - B * F)) .< tol0)) +all((P - ((R + F' * Q * F) + beta * (A - B * F)' * P * (A - B * F)) .< tol0)) ``` ```{code-cell} julia @@ -1410,7 +1410,8 @@ end plot([vt_MPE, vt_leader, vt_follower], labels = ["MPE" "Stackelberg leader" "Stackelberg follower"], title = "MPE vs Stackelberg Values", - xlabel = L"t") + xlabel = L"t", + legend = :outertopright) ``` ```{code-cell} julia diff --git a/lectures/dynamic_programming_squared/lqramsey.md b/lectures/dynamic_programming_squared/lqramsey.md index a9cb6519..3fefa1b7 100644 --- a/lectures/dynamic_programming_squared/lqramsey.md +++ b/lectures/dynamic_programming_squared/lqramsey.md @@ -613,8 +613,8 @@ function compute_exog_sequences(econ, x) g, d, b, s = [dropdims(S * x, dims = 1) for S in (Sg, Sd, Sb, Ss)] #= solve for Lagrange multiplier in the govt budget constraint - In fact we solve for ν = lambda / (1 + 2*lambda). Here ν is the - solution to a quadratic equation a(ν^2 - ν) + b = 0 where + In fact we solve for nu = lambda / (1 + 2*lambda). Here nu is the + solution to a quadratic equation a(nu^2 - nu) + b = 0 where a and b are expected discounted sums of quadratic forms of the state. =# Sm = Sb - Sd - Ss @@ -622,12 +622,11 @@ function compute_exog_sequences(econ, x) end -function compute_allocation(econ, Sm, ν, x, b) - Sg, Sd, Sb, Ss = econ.Sg, econ.Sd, econ.Sb, econ.Ss - - # solve for the allocation given ν and x - Sc = 0.5 .* (Sb + Sd - Sg - ν .* Sm) - Sl = 0.5 .* (Sb - Sd + Sg - ν .* Sm) +function compute_allocation(econ, Sm, nu, x, b) + (;Sg, Sd, Sb, Ss) = econ + # solve for the allocation given nu and x + Sc = 0.5 .* (Sb + Sd - Sg - nu .* Sm) + Sl = 0.5 .* (Sb - Sd + Sg - nu .* Sm) c = dropdims(Sc * x, dims = 1) l = dropdims(Sl * x, dims = 1) p = dropdims((Sb - Sc) * x, dims = 1) # Price without normalization @@ -638,29 +637,29 @@ function compute_allocation(econ, Sm, ν, x, b) end -function compute_ν(a0, b0) +function compute_nu(a0, b0) disc = a0^2 - 4a0 * b0 if disc >= 0 - ν = 0.5 *(a0 - sqrt(disc)) / a0 + nu = 0.5 *(a0 - sqrt(disc)) / a0 else println("There is no Ramsey equilibrium for these parameters.") error("Government spending (economy.g) too low") end # Test that the Lagrange multiplier has the right sign - if ν * (0.5 - ν) < 0 + if nu * (0.5 - nu) < 0 print("Negative multiplier on the government budget constraint.") error("Government spending (economy.g) too low") end - return ν + return nu end -function compute_Pi(B, R, rvn, g,Xi) +function compute_Pi(B, R, rvn, g,xi) pi = B[2:end] - R[1:end-1] .* B[1:end-1] - rvn[1:end-1] + g[1:end-1] - Pi = cumsum(pi .*Xi) + Pi = cumsum(pi .*xi) return pi, Pi end @@ -685,10 +684,10 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:DiscreteStochProcess}, T b0 = (F \ H')[1] ./ 2 # compute lagrange multiplier - ν = compute_ν(a0, b0) + nu = compute_nu(a0, b0) - # Solve for the allocation given ν and x - Sc, Sl, c, l, p, tau, rvn = compute_allocation(econ, Sm, ν, x, b) + # Solve for the allocation given nu and x + Sc, Sl, c, l, p, tau, rvn = compute_allocation(econ, Sm, nu, x, b) # compute remaining variables H = ((Sb - Sc) * x_vals) .* ((Sl - Sg) * x_vals) - (Sl * x_vals).^2 @@ -697,12 +696,12 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:DiscreteStochProcess}, T H = dropdims(P[state, :] * ((Sb - Sc) * x_vals)', dims = 2) R = p ./ (beta .* H) temp = dropdims(P[state, :] *((Sb - Sc) * x_vals)', dims = 2) - Xi = p[2:end] ./ temp[1:end-1] + xi = p[2:end] ./ temp[1:end-1] # compute pi - pi, Pi = compute_Pi(B, R, rvn, g,Xi) + pi, Pi = compute_Pi(B, R, rvn, g, xi) - return (;g, d, b, s, c, l, p, tau, rvn, B, R, pi, Pi, Xi) + return (;g, d, b, s, c, l, p, tau, rvn, B, R, pi, Pi, xi) end function compute_paths(econ::Economy{<:AbstractFloat, <:ContStochProcess}, T) @@ -736,10 +735,10 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:ContStochProcess}, T) b0 = 0.5 * var_quadratic_sum(A, C, H, beta, x0) # compute lagrange multiplier - ν = compute_ν(a0, b0) + nu = compute_nu(a0, b0) - # solve for the allocation given ν and x - Sc, Sl, c, l, p, tau, rvn = compute_allocation(econ, Sm, ν, x, b) + # solve for the allocation given nu and x + Sc, Sl, c, l, p, tau, rvn = compute_allocation(econ, Sm, nu, x, b) # compute remaining variables H = Sl'Sl - (Sb - Sc)' *(Sl - Sg) @@ -752,13 +751,13 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:ContStochProcess}, T) R = 1 ./ Rinv AF1 = (Sb - Sc) * x[:, 2:end] AF2 = (Sb - Sc) * A * x[:, 1:end-1] - Xi = AF1 ./ AF2 - Xi = dropdims(Xi, dims = 1) + xi = AF1 ./ AF2 + xi = dropdims(xi, dims = 1) # compute pi - pi, Pi = compute_Pi(B, R, rvn, g,Xi) + pi, Pi = compute_Pi(B, R, rvn, g, xi) - return(;g, d, b, s, c, l, p, tau, rvn, B, R, pi, Pi, Xi) + return(;g, d, b, s, c, l, p, tau, rvn, B, R, pi, Pi, xi) end function gen_fig_1(path) @@ -789,7 +788,7 @@ function gen_fig_2(path) T = length(path.c) - paths = [path.Xi, path.Pi] + paths = [path.xi, path.Pi] labels = [L"\xi_t", L"\Pi_t"] plt_1 = plot() plt_2 = plot() From 6a00325423d6afb2460c81e478dc45e03fe10e09 Mon Sep 17 00:00:00 2001 From: annabellasd Date: Thu, 9 Nov 2023 09:21:23 -0800 Subject: [PATCH 25/26] double Tau functions fixed --- lectures/dynamic_programming_squared/amss.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lectures/dynamic_programming_squared/amss.md b/lectures/dynamic_programming_squared/amss.md index 6c63b9f1..d5dbb1ef 100644 --- a/lectures/dynamic_programming_squared/amss.md +++ b/lectures/dynamic_programming_squared/amss.md @@ -542,7 +542,7 @@ function time1_value(pas::SequentialAllocation, mu::Real) end -function T(model::Model, c::Union{Real,Vector}, n::Union{Real,Vector}) +function Omega(model::Model, c::Union{Real,Vector}, n::Union{Real,Vector}) Uc, Un = model.Uc.(c, n), model.Un.(c, n) return 1. .+ Un./(model.Theta .* Uc) end @@ -562,12 +562,12 @@ function simulate(pas::SequentialAllocation, cHist = zeros(T) nHist = zeros(T) Bhist = zeros(T) - THist = zeros(T) + OmegaHist = zeros(T) muHist = zeros(T) RHist = zeros(T-1) # time 0 mu, cHist[1], nHist[1], _ = time0_allocation(pas, B_, s_0) - THist[1] = T(pas.model, cHist[1], nHist[1])[s_0] + OmegaHist[1] = Omega(pas.model, cHist[1], nHist[1])[s_0] Bhist[1] = B_ muHist[1] = mu # time 1 onward @@ -575,13 +575,13 @@ function simulate(pas::SequentialAllocation, c, n, x, Xi = time1_allocation(pas,mu) u_c = Uc(c,n) s = sHist[t] - THist[t] = T(pas.model, c, n)[s] + OmegaHist[t] = Omega(pas.model, c, n)[s] Eu_c = dot(Pi[sHist[t-1],:], u_c) cHist[t], nHist[t], Bhist[t] = c[s], n[s], x[s] / u_c[s] RHist[t-1] = Uc(cHist[t-1], nHist[t-1]) / (beta * Eu_c) muHist[t] = mu end - return cHist, nHist, Bhist, THist, sHist, muHist, RHist + return cHist, nHist, Bhist, OmegaHist, sHist, muHist, RHist end From f39c5dde24b45cee96920fb491f00f3dbccbc922 Mon Sep 17 00:00:00 2001 From: Jesse Perla Date: Thu, 4 Jan 2024 11:06:11 -0800 Subject: [PATCH 26/26] Ran formatter and a few minor changes --- lectures/dynamic_programming_squared/amss.md | 304 +++++++++--------- .../dynamic_programming_squared/dyn_stack.md | 158 +++++---- .../dynamic_programming_squared/lqramsey.md | 162 ++++------ .../opt_tax_recur.md | 189 +++++------ 4 files changed, 371 insertions(+), 442 deletions(-) diff --git a/lectures/dynamic_programming_squared/amss.md b/lectures/dynamic_programming_squared/amss.md index d5dbb1ef..5ae14997 100644 --- a/lectures/dynamic_programming_squared/amss.md +++ b/lectures/dynamic_programming_squared/amss.md @@ -44,11 +44,6 @@ In this lecture, we We begin with an introduction to the model. - -```{code-cell} julia -using LinearAlgebra, Statistics -``` - ## Competitive Equilibrium with Distorting Taxes Many but not all features of the economy are identical to those of {doc}`the Lucas-Stokey economy <../dynamic_programming_squared/opt_tax_recur>`. @@ -390,13 +385,15 @@ on optimal taxation with state-contingent debt sequential allocation implementa --- tags: [remove-cell] --- -using Test, Random +using Test ``` ```{code-cell} julia --- tags: [output_scroll] --- + +using LinearAlgebra, Statistics, Random using QuantEcon, NLsolve, NLopt import QuantEcon.simulate @@ -417,7 +414,6 @@ mutable struct Model{TF <: AbstractFloat, n_less_than_one::Bool end - struct SequentialAllocation{TP <: Model, TI <: Integer, TV <: AbstractVector} @@ -430,7 +426,6 @@ struct SequentialAllocation{TP <: Model, zFB::TV end - function SequentialAllocation(model::Model) beta, Pi, G, Theta = model.beta, model.Pi, model.G, model.Theta mc = MarkovChain(Pi) @@ -962,6 +957,7 @@ The recursive formulation is implemented as follows ```{code-cell} julia +# Interpolations.jl doesn't support irregular grids for splines using DataInterpolations mutable struct BellmanEquation_Recursive{TP <: Model, TI <: Integer, TR <: Real} @@ -976,11 +972,10 @@ mutable struct BellmanEquation_Recursive{TP <: Model, TI <: Integer, TR <: Real} zFB::Vector{Vector{TR}} end - struct RecursiveAllocation{TP <: Model, - TI <: Integer, - TVg <: AbstractVector, - TT <: Tuple} + TI <: Integer, + TVg <: AbstractVector, + TT <: Tuple} model::TP mc::MarkovChain S::TI @@ -991,7 +986,6 @@ struct RecursiveAllocation{TP <: Model, policies::TT end - function RecursiveAllocation(model::Model, mugrid::AbstractArray) G = model.G S = size(model.Pi, 1) # number of states @@ -1002,8 +996,8 @@ function RecursiveAllocation(model::Model, mugrid::AbstractArray) return RecursiveAllocation(model, mc, S, T, mugrid, xgrid, Vf, policies) end - -function solve_time1_bellman(model::Model{TR}, mugrid::AbstractArray) where {TR <: Real} +function solve_time1_bellman(model::Model{TR}, + mugrid::AbstractArray) where {TR <: Real} Pi = model.Pi S = size(model.Pi, 1) @@ -1012,8 +1006,8 @@ function solve_time1_bellman(model::Model{TR}, mugrid::AbstractArray) where {TR PP = SequentialAllocation(model) function incomplete_allocation(PP::SequentialAllocation, - mu_::AbstractFloat, - s_::Integer) + mu_::AbstractFloat, + s_::Integer) c, n, x, V = time1_value(PP, mu_) return c, n, dot(Pi[s_, :], x), dot(Pi[s_, :], V) end @@ -1030,20 +1024,24 @@ function solve_time1_bellman(model::Model{TR}, mugrid::AbstractArray) where {TR x = Array{TR}(undef, length(mugrid)) V = Array{TR}(undef, length(mugrid)) for (i_mu, mu) in enumerate(mugrid) - c[i_mu, :], n[i_mu, :], x[i_mu], V[i_mu] = - incomplete_allocation(PP, mu, s_) + c[i_mu, :], n[i_mu, :], x[i_mu], V[i_mu] = incomplete_allocation(PP, + mu, + s_) end xprimes = repeat(x, 1, S) xgrid[s_, :] = x - for sprime = 1:S - splc = CubicSpline(c[:, sprime][end:-1:1], x[end:-1:1];extrapolate=true) - spln = CubicSpline(n[:, sprime][end:-1:1], x[end:-1:1];extrapolate=true) - splx = CubicSpline(xprimes[:, sprime][end:-1:1], x[end:-1:1];extrapolate=true) + for sprime in 1:S + splc = CubicSpline(c[:, sprime][end:-1:1], x[end:-1:1]; + extrapolate = true) + spln = CubicSpline(n[:, sprime][end:-1:1], x[end:-1:1]; + extrapolate = true) + splx = CubicSpline(xprimes[:, sprime][end:-1:1], x[end:-1:1]; + extrapolate = true) cf[s_, sprime] = y -> splc(y) nf[s_, sprime] = y -> spln(y) xprimef[s_, sprime] = y -> splx(y) end - splV = CubicSpline(V[end:-1:1], x[end:-1:1];extrapolate=true) + splV = CubicSpline(V[end:-1:1], x[end:-1:1]; extrapolate = true) Vf[s_] = y -> splV(y) end @@ -1061,9 +1059,11 @@ function solve_time1_bellman(model::Model{TR}, mugrid::AbstractArray) where {TR Vfnew, policies = fit_policy_function(T, PF, xgrid) diff = 0.0 - for s=1:S - diff = max(diff, maximum(abs, (Vf[s].(xgrid) - Vfnew[s].(xgrid)) ./ - Vf[s].(xgrid))) + for s in 1:S + diff = max(diff, + maximum(abs, + (Vf[s].(xgrid) - Vfnew[s].(xgrid)) ./ + Vf[s].(xgrid))) end println("diff = $diff") @@ -1073,10 +1073,11 @@ function solve_time1_bellman(model::Model{TR}, mugrid::AbstractArray) where {TR return Vf, policies, T, xgrid end - function fit_policy_function(T::BellmanEquation_Recursive, PF::Function, - xgrid::AbstractVector{TF}) where {TF <: AbstractFloat} + xgrid::AbstractVector{TF}) where { + TF <: + AbstractFloat} S = T.S # preallocation PFvec = Array{TF}(undef, 4S + 1, length(xgrid)) @@ -1090,9 +1091,9 @@ function fit_policy_function(T::BellmanEquation_Recursive, for (i_x, x) in enumerate(xgrid) PFvec[:, i_x] = PF(i_x, x, s_) end - splV = CubicSpline(PFvec[1,:], xgrid) + splV = CubicSpline(PFvec[1, :], xgrid) Vf[s_] = y -> splV(y) - for sprime=1:S + for sprime in 1:S splc = CubicSpline(PFvec[1 + sprime, :], xgrid) spln = CubicSpline(PFvec[1 + S + sprime, :], xgrid) splxprime = CubicSpline(PFvec[1 + 2S + sprime, :], xgrid) @@ -1107,18 +1108,16 @@ function fit_policy_function(T::BellmanEquation_Recursive, return Vf, policies end - function Tau(pab::RecursiveAllocation, - c::AbstractArray, - n::AbstractArray) + c::AbstractArray, + n::AbstractArray) model = pab.model Uc, Un = model.Uc(c, n), model.Un(c, n) - return 1. .+ Un ./ (model.Theta .* Uc) + return 1.0 .+ Un ./ (model.Theta .* Uc) end Tau(pab::RecursiveAllocation, c::Real, n::Real) = Tau(pab, [c], [n]) - function time0_allocation(pab::RecursiveAllocation, B_::Real, s0::Integer) T, Vf = pab.T, pab.Vf xbar = T.xbar @@ -1128,10 +1127,12 @@ function time0_allocation(pab::RecursiveAllocation, B_::Real, s0::Integer) return c0, n0, xprime0, T0 end - function simulate(pab::RecursiveAllocation, B_::TF, s_0::Integer, T::Integer, - sHist::Vector=simulate(pab.mc, T, init=s_0)) where {TF <: AbstractFloat} + sHist::Vector = simulate(pab.mc, T, init = s_0)) where { + TF <: + AbstractFloat + } model, mc, Vf, S = pab.model, pab.mc, pab.Vf, pab.S Pi, Uc = model.Pi, model.Uc cf, nf, xprimef, TTf = pab.policies @@ -1145,22 +1146,24 @@ function simulate(pab::RecursiveAllocation, muHist = Array{TF}(undef, T) #time0 - cHist[1], nHist[1], xHist[1], THist[1] = time0_allocation(pab, B_, s_0) + cHist[1], nHist[1], xHist[1], THist[1] = time0_allocation(pab, B_, s_0) TauHist[1] = Tau(pab, cHist[1], nHist[1])[s_0] Bhist[1] = B_ muHist[1] = Vf[s_0](xHist[1]) #time 1 onward for t in 2:T - s_, x, s = sHist[t-1], xHist[t-1], sHist[t] + s_, x, s = sHist[t - 1], xHist[t - 1], sHist[t] c = Array{TF}(undef, S) n = Array{TF}(undef, S) xprime = Array{TF}(undef, S) TT = Array{TF}(undef, S) - for sprime=1:S - c[sprime], n[sprime], xprime[sprime], TT[sprime] = - cf[s_, sprime](x), nf[s_, sprime](x), - xprimef[s_, sprime](x), TTf[s_, sprime](x) + for sprime in 1:S + c[sprime], n[sprime], xprime[sprime], TT[sprime] = cf[s_, sprime](x), + nf[s_, sprime](x), + xprimef[s_, + sprime](x), + TTf[s_, sprime](x) end Tau_val = Tau(pab, c, n)[s] @@ -1169,17 +1172,15 @@ function simulate(pab::RecursiveAllocation, muHist[t] = Vf[s](xprime[s]) - cHist[t], nHist[t], Bhist[t], TauHist[t] = c[s], n[s], x/Eu_c, Tau_val + cHist[t], nHist[t], Bhist[t], TauHist[t] = c[s], n[s], x / Eu_c, Tau_val xHist[t], THist[t] = xprime[s], TT[s] end return cHist, nHist, Bhist, xHist, TauHist, THist, muHist, sHist end - function BellmanEquation_Recursive(model::Model{TF}, xgrid::AbstractVector{TF}, policies0::Array) where {TF <: AbstractFloat} - S = size(model.Pi, 1) # number of states xbar = [minimum(xgrid), maximum(xgrid)] time_0 = false @@ -1190,18 +1191,18 @@ function BellmanEquation_Recursive(model::Model{TF}, cs = Array{TF}(undef, S) ns = Array{TF}(undef, S) xprimes = Array{TF}(undef, S) - for j = 1:S - cs[j], ns[j], xprimes[j] = cf[s, j](x), nf[s, j](x), xprimef[s, j](x) + for j in 1:S + cs[j], ns[j], xprimes[j] = cf[s, j](x), nf[s, j](x), + xprimef[s, j](x) end z0[i_x, s] = vcat(cs, ns, xprimes, zeros(S)) end end cFB, nFB, IFB, xFB, zFB = find_first_best(model, S, 2) - return BellmanEquation_Recursive(model, S, xbar, time_0, z0, cFB, nFB, xFB, zFB) + return BellmanEquation_Recursive(model, S, xbar, time_0, z0, cFB, nFB, xFB, + zFB) end - - function get_policies_time1(T::BellmanEquation_Recursive, i_x::Integer, x::Real, @@ -1210,28 +1211,28 @@ function get_policies_time1(T::BellmanEquation_Recursive, xbar::AbstractVector) model, S = T.model, T.S beta, Theta, G, Pi = model.beta, model.Theta, model.G, model.Pi - U,Uc,Un = model.U, model.Uc, model.Un + U, Uc, Un = model.U, model.Uc, model.Un - S_possible = sum(Pi[s_, :].>0) - sprimei_possible = findall(Pi[s_, :].>0) + S_possible = sum(Pi[s_, :] .> 0) + sprimei_possible = findall(Pi[s_, :] .> 0) function objf(z, grad) - c, xprime = z[1:S_possible], z[S_possible+1:2S_possible] + c, xprime = z[1:S_possible], z[(S_possible + 1):(2S_possible)] n = (c .+ G[sprimei_possible]) ./ Theta[sprimei_possible] Vprime = [Vf[sprimei_possible[si]](xprime[si]) for si in 1:S_possible] return -dot(Pi[s_, sprimei_possible], U.(c, n) + beta * Vprime) end function cons(out, z, grad) - c, xprime, TT = - z[1:S_possible], z[S_possible + 1:2S_possible], z[2S_possible + 1:3S_possible] + c, xprime, TT = z[1:S_possible], z[(S_possible + 1):(2S_possible)], + z[(2S_possible + 1):(3S_possible)] n = (c .+ G[sprimei_possible]) ./ Theta[sprimei_possible] u_c = Uc.(c, n) Eu_c = dot(Pi[s_, sprimei_possible], u_c) - out .= x * u_c/Eu_c - u_c .* (c - TT) - Un(c, n) .* n - beta * xprime + out .= x * u_c / Eu_c - u_c .* (c - TT) - Un(c, n) .* n - beta * xprime end function cons_no_trans(out, z, grad) - c, xprime = z[1:S_possible], z[S_possible + 1:2S_possible] + c, xprime = z[1:S_possible], z[(S_possible + 1):(2S_possible)] n = (c .+ G[sprimei_possible]) ./ Theta[sprimei_possible] u_c = Uc.(c, n) Eu_c = dot(Pi[s_, sprimei_possible], u_c) @@ -1239,14 +1240,15 @@ function get_policies_time1(T::BellmanEquation_Recursive, end if model.transfers == true - lb = vcat(zeros(S_possible), ones(S_possible)*xbar[1], zeros(S_possible)) + lb = vcat(zeros(S_possible), ones(S_possible) * xbar[1], + zeros(S_possible)) if model.n_less_than_one == true ub = vcat(ones(S_possible) - G[sprimei_possible], - ones(S_possible) * xbar[2], ones(S_possible)) + ones(S_possible) * xbar[2], ones(S_possible)) else ub = vcat(100 * ones(S_possible), - ones(S_possible) * xbar[2], - 100 * ones(S_possible)) + ones(S_possible) * xbar[2], + 100 * ones(S_possible)) end init = vcat(T.z0[i_x, s_][sprimei_possible], T.z0[i_x, s_][2S .+ sprimei_possible], @@ -1254,9 +1256,10 @@ function get_policies_time1(T::BellmanEquation_Recursive, opt = Opt(:LN_COBYLA, 3S_possible) equality_constraint!(opt, cons, zeros(S_possible)) else - lb = vcat(zeros(S_possible), ones(S_possible)*xbar[1]) + lb = vcat(zeros(S_possible), ones(S_possible) * xbar[1]) if model.n_less_than_one == true - ub = vcat(ones(S_possible)-G[sprimei_possible], ones(S_possible)*xbar[2]) + ub = vcat(ones(S_possible) - G[sprimei_possible], + ones(S_possible) * xbar[2]) else ub = vcat(ones(S_possible), ones(S_possible) * xbar[2]) end @@ -1279,15 +1282,16 @@ function get_policies_time1(T::BellmanEquation_Recursive, (minf, minx, ret) = NLopt.optimize(opt, init) if ret != :SUCCESS && ret != :ROUNDOFF_LIMITED && ret != :MAXEVAL_REACHED && - ret != :FTOL_REACHED && ret != :MAXTIME_REACHED + ret != :FTOL_REACHED && ret != :MAXTIME_REACHED error("optimization failed: ret = $ret") end T.z0[i_x, s_][sprimei_possible] = minx[1:S_possible] - T.z0[i_x, s_][S .+ sprimei_possible] = minx[1:S_possible] .+ G[sprimei_possible] - T.z0[i_x, s_][2S .+ sprimei_possible] = minx[S_possible .+ 1:2S_possible] + T.z0[i_x, s_][S .+ sprimei_possible] = minx[1:S_possible] .+ + G[sprimei_possible] + T.z0[i_x, s_][2S .+ sprimei_possible] = minx[(S_possible .+ 1):(2S_possible)] if model.transfers == true - T.z0[i_x, s_][3S .+ sprimei_possible] = minx[2S_possible + 1:3S_possible] + T.z0[i_x, s_][3S .+ sprimei_possible] = minx[(2S_possible + 1):(3S_possible)] else T.z0[i_x, s_][3S .+ sprimei_possible] = zeros(S) end @@ -1295,7 +1299,6 @@ function get_policies_time1(T::BellmanEquation_Recursive, return vcat(-minf, T.z0[i_x, s_]) end - function get_policies_time0(T::BellmanEquation_Recursive, B_::Real, s0::Integer, @@ -1311,7 +1314,7 @@ function get_policies_time0(T::BellmanEquation_Recursive, return -(U(c, n) + beta * Vf[s0](xprime)) end - function cons(z,grad) + function cons(z, grad) c, xprime, TT = z[1], z[2], z[3] n = (c + G[s0]) / Theta[s0] return -Uc(c, n) * (c - B_ - TT) - Un(c, n) * n - beta * xprime @@ -1326,13 +1329,13 @@ function get_policies_time0(T::BellmanEquation_Recursive, ub = [100.0, xbar[2], 100.0] end init = vcat(T.zFB[s0][1], T.zFB[s0][3], T.zFB[s0][4]) - init = [0.95124922, -1.15926816, 0.0] + init = [0.95124922, -1.15926816, 0.0] opt = Opt(:LN_COBYLA, 3) equality_constraint!(opt, cons) else lb = [0.0, xbar[1]] if model.n_less_than_one == true - ub = [1-G[s0], xbar[2]] + ub = [1 - G[s0], xbar[2]] else ub = [100, xbar[2]] end @@ -1344,7 +1347,6 @@ function get_policies_time0(T::BellmanEquation_Recursive, init[init .> ub] = ub[init .> ub] init[init .< lb] = lb[init .< lb] - min_objective!(opt, objf) lower_bounds!(opt, lb) upper_bounds!(opt, ub) @@ -1354,14 +1356,14 @@ function get_policies_time0(T::BellmanEquation_Recursive, (minf, minx, ret) = NLopt.optimize(opt, init) if ret != :SUCCESS && ret != :ROUNDOFF_LIMITED && ret != :MAXEVAL_REACHED && - ret != :FTOL_REACHED - error("optimization failed: ret = $ret") + ret != :FTOL_REACHED + error("optimization failed: ret = $ret") end if model.transfers == true - return -minf, minx[1], minx[1]+G[s0], minx[2], minx[3] + return -minf, minx[1], minx[1] + G[s0], minx[2], minx[3] else - return -minf, minx[1], minx[1]+G[s0], minx[2], 0 + return -minf, minx[1], minx[1] + G[s0], minx[2], 0 end end ``` @@ -1429,31 +1431,30 @@ We assume the same utility parameters as in the {doc}`Lucas-Stokey economy <../d This utility function is implemented in the following constructor ```{code-cell} julia -function crra_utility(; - beta = 0.9, - sigma = 2.0, - gamma = 2.0, - Pi = 0.5 * ones(2, 2), - G = [0.1, 0.2], - Theta = ones(Float64, 2), - transfers = false - ) +function CRRAModel(; + beta = 0.9, + sigma = 2.0, + gamma = 2.0, + Pi = 0.5 * ones(2, 2), + G = [0.1, 0.2], + Theta = ones(Float64, 2), + transfers = false) function U(c, n) if sigma == 1.0 U = log(c) else - U = (c.^(1.0 - sigma) - 1.0) / (1.0 - sigma) + U = (c .^ (1.0 - sigma) - 1.0) / (1.0 - sigma) end - return U - n.^(1 + gamma) / (1 + gamma) + return U - n .^ (1 + gamma) / (1 + gamma) end # Derivatives of utility function - Uc(c,n) = c.^(-sigma) - Ucc(c,n) = -sigma * c.^(-sigma - 1.0) - Un(c,n) = -n.^gamma - Unn(c,n) = -gamma * n.^(gamma - 1.0) + Uc(c, n) = c .^ (-sigma) + Ucc(c, n) = -sigma * c .^ (-sigma - 1.0) + Un(c, n) = -n .^ gamma + Unn(c, n) = -gamma * n .^ (gamma - 1.0) n_less_than_one = false return Model(beta, Pi, G, Theta, transfers, - U, Uc, Ucc, Un, Unn, n_less_than_one) + U, Uc, Ucc, Un, Unn, n_less_than_one) end ``` @@ -1468,10 +1469,10 @@ Paths with circles are histories in which there is peace, while those with triangle denote war. ```{code-cell} julia -time_example = crra_utility(G=[0.1, 0.1, 0.1, 0.2, 0.1, 0.1], - Theta = ones(6)) # Theta can in principle be random +time_example = CRRAModel(;G = [0.1, 0.1, 0.1, 0.2, 0.1, 0.1], + Theta = ones(6)) # Theta can in principle be random -time_example.Pi = [ 0.0 1.0 0.0 0.0 0.0 0.0; +time_example.Pi = [0.0 1.0 0.0 0.0 0.0 0.0; 0.0 0.0 1.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.5 0.5 0.0; 0.0 0.0 0.0 0.0 0.0 1.0; @@ -1489,10 +1490,10 @@ time_bellman = RecursiveAllocation(time_example, mugrid) sHist_h = [1, 2, 3, 4, 6, 6, 6] sHist_l = [1, 2, 3, 5, 6, 6, 6] -sim_seq_h = simulate(time_sequential, 1., 1, 7, sHist_h) -sim_bel_h = simulate(time_bellman, 1., 1, 7, sHist_h) -sim_seq_l = simulate(time_sequential, 1., 1, 7, sHist_l) -sim_bel_l = simulate(time_bellman, 1., 1, 7, sHist_l) +sim_seq_h = simulate(time_sequential, 1.0, 1, 7, sHist_h) +sim_bel_h = simulate(time_bellman, 1.0, 1, 7, sHist_h) +sim_seq_l = simulate(time_sequential, 1.0, 1, 7, sHist_l) +sim_bel_l = simulate(time_bellman, 1.0, 1, 7, sHist_l) using Plots @@ -1510,14 +1511,18 @@ sim_seq_h_plot = hcat(sim_seq_h[1:3]..., sim_seq_h[4], sim_bel_h_plot = hcat(sim_bel_h[1:3]..., sim_bel_h[5], time_example.G[sHist_h], time_example.Theta[sHist_h] .* sim_bel_h[2]) -p = plot(size = (920, 750), layout =(3, 2), - xaxis=(0:6), grid=false, titlefont=Plots.font("sans-serif", 10)) +p = plot(size = (920, 750), layout = (3, 2), + xaxis = (0:6), grid = false, titlefont = Plots.font("sans-serif", 10)) plot!(p, title = titles) -for i=1:6 - plot!(p[i], 0:6, sim_seq_l_plot[:, i], marker=:circle, color=:black, lab="") - plot!(p[i], 0:6, sim_bel_l_plot[:, i], marker=:circle, color=:red, lab="") - plot!(p[i], 0:6, sim_seq_h_plot[:, i], marker=:utriangle, color=:black, lab="") - plot!(p[i], 0:6, sim_bel_h_plot[:, i], marker=:utriangle, color=:red, lab="") +for i in 1:6 + plot!(p[i], 0:6, sim_seq_l_plot[:, i], marker = :circle, color = :black, + lab = "") + plot!(p[i], 0:6, sim_bel_l_plot[:, i], marker = :circle, color = :red, + lab = "") + plot!(p[i], 0:6, sim_seq_h_plot[:, i], marker = :utriangle, color = :black, + lab = "") + plot!(p[i], 0:6, sim_bel_h_plot[:, i], marker = :utriangle, color = :red, + lab = "") end p ``` @@ -1574,21 +1579,21 @@ $$ In accordance, we will re-define our utility function ```{code-cell} julia -function log_utility(;beta = 0.9, - psi = 0.69, - Pi = 0.5 * ones(2, 2), - G = [0.1, 0.2], - Theta = ones(2), - transfers = false) +function log_utility(; beta = 0.9, + psi = 0.69, + Pi = 0.5 * ones(2, 2), + G = [0.1, 0.2], + Theta = ones(2), + transfers = false) # Derivatives of utility function - U(c,n) = log(c) + psi * log(1 - n) - Uc(c,n) = 1 ./ c - Ucc(c,n) = -c.^(-2.0) - Un(c,n) = -psi ./ (1.0 .- n) - Unn(c,n) = -psi ./ (1.0 .- n).^2.0 + U(c, n) = log(c) + psi * log(1 - n) + Uc(c, n) = 1 ./ c + Ucc(c, n) = -c .^ (-2.0) + Un(c, n) = -psi ./ (1.0 .- n) + Unn(c, n) = -psi ./ (1.0 .- n) .^ 2.0 n_less_than_one = true return Model(beta, Pi, G, Theta, transfers, - U, Uc, Ucc, Un, Unn, n_less_than_one) + U, Uc, Ucc, Un, Unn, n_less_than_one) end ``` @@ -1614,22 +1619,26 @@ sim_seq = simulate(log_sequential, 0.5, 1, T, sHist) sim_bel = simulate(log_bellman, 0.5, 1, T, sHist) sim_seq_plot = hcat(sim_seq[1:3]..., - sim_seq[4], log_example.G[sHist], log_example.Theta[sHist] .* sim_seq[2]) + sim_seq[4], log_example.G[sHist], + log_example.Theta[sHist] .* sim_seq[2]) sim_bel_plot = hcat(sim_bel[1:3]..., - sim_bel[5], log_example.G[sHist], log_example.Theta[sHist] .* sim_bel[2]) + sim_bel[5], log_example.G[sHist], + log_example.Theta[sHist] .* sim_bel[2]) #plot policies p = plot(size = (920, 750), layout = grid(3, 2), - xaxis=(0:T), grid=false, titlefont=Plots.font("sans-serif", 10)) + xaxis = (0:T), grid = false, titlefont = Plots.font("sans-serif", 10)) labels = fill(("", ""), 6) labels[3] = ("Complete Market", "Incomplete Market") plot!(p, title = titles) -for i = vcat(collect(1:4), 6) - plot!(p[i], sim_seq_plot[:, i], marker=:circle, color=:black, lab=labels[i][1]) - plot!(p[i], sim_bel_plot[:, i], marker=:utriangle, color=:blue, lab=labels[i][2], - legend=:bottomright) +for i in vcat(collect(1:4), 6) + plot!(p[i], sim_seq_plot[:, i], marker = :circle, color = :black, + lab = labels[i][1]) + plot!(p[i], sim_bel_plot[:, i], marker = :utriangle, color = :blue, + lab = labels[i][2], + legend = :bottomright) end -plot!(p[5], sim_seq_plot[:, 5], marker=:circle, color=:blue, lab="") +plot!(p[5], sim_seq_plot[:, 5], marker = :circle, color = :blue, lab = "") ``` When the government experiences a prolonged period of peace, it is able to reduce @@ -1653,38 +1662,29 @@ Random.seed!(42) ```{code-cell} julia T_long = 200 sim_seq_long = simulate(log_sequential, 0.5, 1, T_long) -sHist_long = sim_seq_long[end-2] +sHist_long = sim_seq_long[end - 2] sim_bel_long = simulate(log_bellman, 0.5, 1, T_long, sHist_long) sim_seq_long_plot = hcat(sim_seq_long[1:4]..., - log_example.G[sHist_long], log_example.Theta[sHist_long] .* sim_seq_long[2]) + log_example.G[sHist_long], + log_example.Theta[sHist_long] .* sim_seq_long[2]) sim_bel_long_plot = hcat(sim_bel_long[1:3]..., sim_bel_long[5], - log_example.G[sHist_long], log_example.Theta[sHist_long] .* sim_bel_long[2]) + log_example.G[sHist_long], + log_example.Theta[sHist_long] .* sim_bel_long[2]) -p = plot(size = (920, 750), layout = (3, 2), xaxis=(0:50:T_long), grid=false, - titlefont=Plots.font("sans-serif", 10)) +p = plot(size = (920, 750), layout = (3, 2), xaxis = (0:50:T_long), + grid = false, + titlefont = Plots.font("sans-serif", 10)) plot!(p, title = titles) -for i = 1:6 - plot!(p[i], sim_seq_long_plot[:, i], color=:black, linestyle=:solid, lab=labels[i][1]) - plot!(p[i], sim_bel_long_plot[:, i], color=:blue, linestyle=:dot, lab=labels[i][2], - legend=:bottomright) +for i in 1:6 + plot!(p[i], sim_seq_long_plot[:, i], color = :black, linestyle = :solid, + lab = labels[i][1]) + plot!(p[i], sim_bel_long_plot[:, i], color = :blue, linestyle = :dot, + lab = labels[i][2], + legend = :bottomright) end p ``` -```{code-cell} julia ---- -tags: [remove-cell] ---- -@testset begin - # @test sim_seq_long_plot[50, 3] ≈ 0.3951985593686047 - # @test sim_bel_long_plot[50, 3] ≈ 0.05684753244006188 atol = 1e-2 - # @test sim_seq_long_plot[100, 4] ≈ 0.340233842670859 - # @test sim_bel_long_plot[100, 4] ≈ 0.2093423366870517 atol = 1e-3 - # @test sim_seq_long_plot[200, 2] ≈ 0.5839693539786998 - # @test sim_bel_long_plot[200, 2] ≈ 0.6324036099550768 atol = 1e-3 -end -``` - [^fn_a]: In an allocation that solves the Ramsey problem and that levies distorting taxes on labor, why would the government ever want to hand revenues back to the private sector? It would not in an economy with state-contingent debt, since diff --git a/lectures/dynamic_programming_squared/dyn_stack.md b/lectures/dynamic_programming_squared/dyn_stack.md index 36012503..4527a9d8 100644 --- a/lectures/dynamic_programming_squared/dyn_stack.md +++ b/lectures/dynamic_programming_squared/dyn_stack.md @@ -914,7 +914,8 @@ dynamic program as outlined above ```{code-cell} julia -using LaTeXStrings, QuantEcon, Plots, LinearAlgebra, Statistics, Parameters, Random +using LaTeXStrings, QuantEcon, Plots, LinearAlgebra, Statistics, + Random ``` @@ -929,10 +930,12 @@ We define named tuples and default values for the model and solver settings, and instantiate one copy of each ```{code-cell} julia -model(;a0 = 10, a1 = 2, beta = 0.96, gamma = 120., n = 300) = (; a0, a1, beta, gamma, n) +function model(; a0 = 10, a1 = 2, beta = 0.96, gamma = 120.0, n = 300) + return (; a0, a1, beta, gamma, n) +end # things like tolerances, etc. -settings(;tol0 = 1e-8,tol1 = 1e-16,tol2 = 1e-2) = (;tol0, tol1, tol2) +settings(; tol0 = 1e-8, tol1 = 1e-16, tol2 = 1e-2) = (; tol0, tol1, tol2) defaultModel = model(); defaultSettings = settings(); @@ -941,21 +944,26 @@ defaultSettings = settings(); Now we can compute the actual policy using the LQ routine from QuantEcon.jl ```{code-cell} julia -(;a0, a1, beta, gamma, n) = defaultModel -(;tol0, tol1, tol2) = defaultSettings +(; a0, a1, beta, gamma, n) = defaultModel +(; tol0, tol1, tol2) = defaultSettings -betas = [beta^x for x = 0:n-1] +betas = [beta^x for x in 0:(n - 1)] Alhs = I + zeros(4, 4); -Alhs[4, :] = [beta * a0 / (2 * gamma), -beta * a1 / (2 * gamma), -beta * a1 / gamma, beta] # Euler equation coefficients +Alhs[4, :] = [ + beta * a0 / (2 * gamma), + -beta * a1 / (2 * gamma), + -beta * a1 / gamma, + beta, +] # Euler equation coefficients Arhs = I + zeros(4, 4); -Arhs[3, 4] = 1.; +Arhs[3, 4] = 1.0; Alhsinv = inv(Alhs); A = Alhsinv * Arhs; -B = Alhsinv * [0, 1, 0, 0,]; +B = Alhsinv * [0, 1, 0, 0]; R = [0 -a0/2 0 0; -a0/2 a1 a1/2 0; 0 a1/2 0 0; 0 0 0 0]; Q = gamma; -lq = QuantEcon.LQ(Q, R, A, B, bet=beta); +lq = QuantEcon.LQ(Q, R, A, B, bet = beta); P, F, d = stationary_values(lq) P22 = P[4:end, 4:end]; @@ -974,7 +982,7 @@ yt, ut = compute_sequence(lq, y0, n); pi_matrix = R + F' * Q * F; for t in 1:n - pi_leader[t] = -(yt[:, t]' * pi_matrix * yt[:, t]); + pi_leader[t] = -(yt[:, t]' * pi_matrix * yt[:, t]) end println("Computed policy for Stackelberg leader: $F") @@ -984,7 +992,7 @@ println("Computed policy for Stackelberg leader: $F") --- tags: [remove-cell] --- -#test F ≈ [-1.580044538772657, 0.29461312747031404, 0.6748093760774972, 6.539705936147515]' +@test F ≈ [-1.580044538772657, 0.29461312747031404, 0.6748093760774972, 6.539705936147515]' ``` ### Implied Time Series for Price and Quantities @@ -995,12 +1003,12 @@ The following code plots the price and quantities q_leader = yt[2, 1:end]; q_follower = yt[3, 1:end]; q = q_leader + q_follower; -p = a0 .- a1*q; +p = a0 .- a1 * q; -plot(1:n+1, [q_leader, q_follower, p], - title = "Output and Prices, Stackelberg Duopoly", - labels = ["leader output" "follower output" "price"], - xlabel = L"t") +plot(1:(n + 1), [q_leader, q_follower, p], + title = "Output and Prices, Stackelberg Duopoly", + labels = ["leader output" "follower output" "price"], + xlabel = L"t") ``` ### Value of Stackelberg Leader @@ -1022,8 +1030,8 @@ println("v_leader_direct is $v_leader_direct") --- tags: [remove-cell] --- -#test v_leader_forward ≈ 150.0316212532547 -#test v_leader_direct ≈ 150.03237147548967 +@test v_leader_forward ≈ 150.0316212532547 +@test v_leader_direct ≈ 150.03237147548967 ``` ```{code-cell} julia @@ -1036,14 +1044,14 @@ all(P - P_next .< tol0) --- tags: [remove-cell] --- -#test all(P - P_next .< tol0) +@test all(P - P_next .< tol0) ``` ```{code-cell} julia # manually checks whether two different ways of computing the # value function give approximately the same answer v_expanded = -((y0' * R * y0 + ut[:, 1]' * Q * ut[:, 1] + - beta * (y0' * (A - B * F)' * P * (A - B * F) * y0))); + beta * (y0' * (A - B * F)' * P * (A - B * F) * y0))); (v_leader_direct - v_expanded < tol0)[1, 1] ``` @@ -1051,7 +1059,7 @@ v_expanded = -((y0' * R * y0 + ut[:, 1]' * Q * ut[:, 1] + --- tags: [remove-cell] --- -#test (v_leader_direct - v_expanded < tol0)[1, 1] +@test (v_leader_direct - v_expanded < tol0)[1, 1] ``` ## Exhibiting Time Inconsistency of Stackelberg Plan @@ -1079,11 +1087,13 @@ for t in 1:n vt_reset_leader[t] = -yt_reset[:, t]' * P * yt_reset[:, t] end -p1 = plot(1:n+1, [(-F * yt)', (-F * yt_reset)'], labels = ["Stackelberg Leader" L"Continuation Leader at $t$"], - title = "Leader Control Variable", xlabel = L"t"); -p2 = plot(1:n+1, [yt[4, :], yt_reset[4, :]], title = "Follower Control Variable", xlabel = L"t", legend = false); +p1 = plot(1:(n + 1), [(-F * yt)', (-F * yt_reset)'], + labels = ["Stackelberg Leader" L"Continuation Leader at $t$"], + title = "Leader Control Variable", xlabel = L"t"); +p2 = plot(1:(n + 1), [yt[4, :], yt_reset[4, :]], + title = "Follower Control Variable", xlabel = L"t", legend = false); p3 = plot(1:n, [vt_leader, vt_reset_leader], legend = false, - xlabel = L"t", title = "Leader Value Function"); + xlabel = L"t", title = "Leader Value Function"); plot(p1, p2, p3, layout = (3, 1), size = (800, 600)) ``` @@ -1102,7 +1112,7 @@ R_tilde = [0 0 0 0 -a0/2; 0 0 0 0 a1/2; 0 0 0 0 0; 0 0 0 0 0; -a0/2 a1/2 0 0 a1] Q_tilde = Q; B_tilde = [0, 0, 0, 0, 1]; -lq_tilde = QuantEcon.LQ(Q_tilde, R_tilde, A_tilde, B_tilde, bet=beta); +lq_tilde = QuantEcon.LQ(Q_tilde, R_tilde, A_tilde, B_tilde, bet = beta); P_tilde, F_tilde, d_tilde = stationary_values(lq_tilde); y0_tilde = vcat(y0, y0[3]); yt_tilde = compute_sequence(lq_tilde, y0_tilde, n)[1]; @@ -1111,7 +1121,7 @@ yt_tilde = compute_sequence(lq_tilde, y0_tilde, n)[1]; ```{code-cell} julia # checks that the recursive formulation of the follower's problem gives # the same solution as the original Stackelberg problem -plot(1:n+1, [yt_tilde[5, :], yt_tilde[3, :]], labels = [L"\tilde{q}" L"q"]) +plot(1:(n + 1), [yt_tilde[5, :], yt_tilde[3, :]], labels = [L"\tilde{q}" L"q"]) ``` Note: Variables with `_tilde` are obtained from solving the follower's @@ -1126,7 +1136,7 @@ max(abs(yt_tilde[5] - yt_tilde[3])) --- tags: [remove-cell] --- -#test max(abs(yt_tilde[5] - yt_tilde[3])) ≈ 0. atol = 1e-15 +@test max(abs(yt_tilde[5] - yt_tilde[3])) ≈ 0. atol = 1e-15 ``` ```{code-cell} julia @@ -1138,7 +1148,7 @@ yt[:, 1][end] - (yt_tilde[:, 2] - yt_tilde[:, 1])[end] < tol0 --- tags: [remove-cell] --- -#test yt[:, 1][end] - (yt_tilde[:, 2] - yt_tilde[:, 1])[end] < tol0 +@test yt[:, 1][end] - (yt_tilde[:, 2] - yt_tilde[:, 1])[end] < tol0 ``` ### Explanation of Alignment @@ -1173,7 +1183,7 @@ all((P - ((R + F' * Q * F) + beta * (A - B * F)' * P * (A - B * F)) .< tol0)) --- tags: [remove-cell] --- -#test all((P - ((R + F' * Q * F) + beta * (A - B * F)' * P * (A - B * F)) .< tol0)) +@test all((P - ((R + F' * Q * F) + beta * (A - B * F)' * P * (A - B * F)) .< tol0)) ``` ```{code-cell} julia @@ -1184,7 +1194,7 @@ P_guess = zeros(5, 5); for i in 1:1000 P_guess = ((R_tilde + F_tilde_star' * Q_tilde * F_tilde_star) + beta * (A_tilde - B_tilde * F_tilde_star)' * P_guess - * (A_tilde - B_tilde * F_tilde_star)); + * (A_tilde - B_tilde * F_tilde_star)) end ``` @@ -1215,7 +1225,7 @@ tags: [remove-cell] ```{code-cell} julia # c policy using policy iteration algorithm F_iter = (beta * inv(Q + beta * B_tilde' * P_guess * B_tilde) - * B_tilde' * P_guess * A_tilde); + * B_tilde' * P_guess * A_tilde); P_iter = zeros(5, 5); dist_vec = zeros(5, 5); @@ -1223,27 +1233,30 @@ for i in 1:100 # compute P_iter dist_vec = similar(P_iter) for j in 1:1000 - P_iter = (R_tilde + F_iter' * Q * F_iter) + beta * - (A_tilde - B_tilde * F_iter)' * P_iter * - (A_tilde - B_tilde * F_iter); + P_iter = (R_tilde + F_iter' * Q * F_iter) + + beta * + (A_tilde - B_tilde * F_iter)' * P_iter * + (A_tilde - B_tilde * F_iter) # update F_iter F_iter = beta * inv(Q + beta * B_tilde' * P_iter * B_tilde) * - B_tilde' * P_iter * A_tilde; + B_tilde' * P_iter * A_tilde dist_vec = P_iter - ((R_tilde + F_iter' * Q * F_iter) + - beta * (A_tilde - B_tilde * F_iter)' * P_iter * - (A_tilde - B_tilde * F_iter)); + beta * (A_tilde - B_tilde * F_iter)' * P_iter * + (A_tilde - B_tilde * F_iter)) end end if maximum(abs.(dist_vec)) < 1e-8 - dist_vec2 = F_iter - (beta * inv(Q + beta * B_tilde' * P_iter * B_tilde) * B_tilde' * P_iter * A_tilde) - if maximum(abs.(dist_vec2)) < 1e-8 - @show F_iter - else - println("The policy didn't converge: try increasing the number of outer loop iterations") - end + dist_vec2 = F_iter - + (beta * inv(Q + beta * B_tilde' * P_iter * B_tilde) * B_tilde' * + P_iter * A_tilde) + if maximum(abs.(dist_vec2)) < 1e-8 + @show F_iter + else + println("The policy didn't converge: try increasing the number of outer loop iterations") + end else println("The policy didn't converge: try increasing the number of inner loop iterations") end @@ -1253,22 +1266,23 @@ end yt_tilde_star = zeros(n, 5); yt_tilde_star[1, :] = y0_tilde; -for t in 1:n-1 - yt_tilde_star[t+1, :] = (A_tilde - B_tilde * F_tilde_star) * yt_tilde_star[t, :]; +for t in 1:(n - 1) + yt_tilde_star[t + 1, :] = (A_tilde - B_tilde * F_tilde_star) * + yt_tilde_star[t, :] end plot([yt_tilde_star[:, 5], yt_tilde[3, :]], labels = [L"\tilde{q}" L"q"]) ``` ```{code-cell} julia -maximum(abs.(yt_tilde_star[:, 5] - yt_tilde[3, 1:end-1])) +maximum(abs.(yt_tilde_star[:, 5] - yt_tilde[3, 1:(end - 1)])) ``` ```{code-cell} julia --- tags: [remove-cell] --- -#test maximum(abs.(yt_tilde_star[:, 5] - yt_tilde[3, 1:end-1])) < 1e-15 +@test maximum(abs.(yt_tilde_star[:, 5] - yt_tilde[3, 1:end-1])) < 1e-15 ``` ## Markov Perfect Equilibrium @@ -1312,20 +1326,20 @@ B2 = [0, 1, 0]; R1 = [0 0 -a0/2; 0 0 a1/2; -a0/2 a1/2 a1]; R2 = [0 -a0/2 0; -a0/2 a1 a1/2; 0 a1/2 0]; Q1 = Q2 = gamma; -S1 = S2 = W1 = W2 = M1 = M2 = 0.; +S1 = S2 = W1 = W2 = M1 = M2 = 0.0; # solve using nnash from QE F1, F2, P1, P2 = nnash(A, B1, B2, R1, R2, Q1, Q2, - S1, S2, W1, W2, M1, M2, - beta = beta, - tol = tol1); + S1, S2, W1, W2, M1, M2, + beta = beta, + tol = tol1); # simulate forward AF = A - B1 * F1 - B2 * F2; z = zeros(3, n); z[:, 1] .= 1; -for t in 1:n-1 - z[:, t+1] = AF * z[:, t] +for t in 1:(n - 1) + z[:, t + 1] = AF * z[:, t] end println("Policy for F1 is $F1") @@ -1336,8 +1350,8 @@ println("Policy for F2 is $F2") --- tags: [remove-cell] --- -#test round(F1[1], digits = 4) == -0.227 -#test round(F2[2], digits = 4) == 0.0945 +@test round(F1[1], digits = 4) == -0.227 +@test round(F2[2], digits = 4) == 0.0945 ``` ```{code-cell} julia @@ -1345,7 +1359,8 @@ q1 = z[2, :]; q2 = z[3, :]; q = q1 + q2; # total output, MPE p = a0 .- a1 * q; # total price, MPE -plot([q, p], labels = ["total ouput" "total price"], title = "Output and prices, duopoly MPE", xlabel = L"t") +plot([q, p], labels = ["total ouput" "total price"], + title = "Output and prices, duopoly MPE", xlabel = L"t") ``` ```{code-cell} julia @@ -1364,8 +1379,8 @@ tags: [remove-cell] # compute values u1 = -F1 * z; u2 = -F2 * z; -pi_1 = (p .* q1)' - gamma * u1.^2; -pi_2 = (p .* q2)' - gamma * u2.^2; +pi_1 = (p .* q1)' - gamma * u1 .^ 2; +pi_2 = (p .* q2)' - gamma * u2 .^ 2; v1_forward = pi_1 * betas; v2_forward = pi_2 * betas; @@ -1381,10 +1396,10 @@ println("Firm 2: Direct is $v2_direct, Forward is $(v2_forward[1])"); --- tags: [remove-cell] --- -#test round(v1_direct, digits = 4) == 133.3296 -#test round(v2_direct, digits = 4) == 133.3296 -#test round(v1_forward[1], digits = 4) == 133.3303 -#test round(v2_forward[1], digits = 4) == 133.3303 +@test round(v1_direct, digits = 3) == 133.329 +@test round(v2_direct, digits = 3) == 133.329 +@test round(v1_forward[1], digits = 3) == 133.330 +@test round(v2_forward[1], digits = 3) == 133.330 ``` ```{code-cell} julia @@ -1404,14 +1419,15 @@ vt_MPE = zeros(n); vt_follower = zeros(n); for t in 1:n - vt_MPE[t] = -z[:, t]' * P1 * z[:, t]; - vt_follower[t] = -yt_tilde[:, t]' * P_tilde * yt_tilde[:, t]; + vt_MPE[t] = -z[:, t]' * P1 * z[:, t] + vt_follower[t] = -yt_tilde[:, t]' * P_tilde * yt_tilde[:, t] end -plot([vt_MPE, vt_leader, vt_follower], labels = ["MPE" "Stackelberg leader" "Stackelberg follower"], - title = "MPE vs Stackelberg Values", - xlabel = L"t", - legend = :outertopright) +plot([vt_MPE, vt_leader, vt_follower], + labels = ["MPE" "Stackelberg leader" "Stackelberg follower"], + title = "MPE vs Stackelberg Values", + xlabel = L"t", + legend = :outertopright) ``` ```{code-cell} julia @@ -1423,7 +1439,7 @@ println("vt_MPE(y0) = $(vt_MPE[1])"); ```{code-cell} julia # total difference in value b/t Stackelberg and MPE -vt_leader[1] + vt_follower[1] - 2*vt_MPE[1] +vt_leader[1] + vt_follower[1] - 2 * vt_MPE[1] ``` ```{code-cell} julia diff --git a/lectures/dynamic_programming_squared/lqramsey.md b/lectures/dynamic_programming_squared/lqramsey.md index 3fefa1b7..84a22866 100644 --- a/lectures/dynamic_programming_squared/lqramsey.md +++ b/lectures/dynamic_programming_squared/lqramsey.md @@ -582,8 +582,7 @@ using Test ``` ```{code-cell} julia -using LaTeXStrings, QuantEcon, Plots, LinearAlgebra, Parameters - +using LaTeXStrings, QuantEcon, Plots, LinearAlgebra abstract type AbstractStochProcess end @@ -592,7 +591,6 @@ struct ContStochProcess{TF <: AbstractFloat} <: AbstractStochProcess C::Matrix{TF} end - struct DiscreteStochProcess{TF <: AbstractFloat} <: AbstractStochProcess P::Matrix{TF} x_vals::Matrix{TF} @@ -621,9 +619,8 @@ function compute_exog_sequences(econ, x) return g, d, b, s, Sm end - function compute_allocation(econ, Sm, nu, x, b) - (;Sg, Sd, Sb, Ss) = econ + (; Sg, Sd, Sb, Ss) = econ # solve for the allocation given nu and x Sc = 0.5 .* (Sb + Sd - Sg - nu .* Sm) Sl = 0.5 .* (Sb - Sd + Sg - nu .* Sm) @@ -636,12 +633,11 @@ function compute_allocation(econ, Sm, nu, x, b) return Sc, Sl, c, l, p, tau, rvn end - function compute_nu(a0, b0) disc = a0^2 - 4a0 * b0 if disc >= 0 - nu = 0.5 *(a0 - sqrt(disc)) / a0 + nu = 0.5 * (a0 - sqrt(disc)) / a0 else println("There is no Ramsey equilibrium for these parameters.") error("Government spending (economy.g) too low") @@ -656,21 +652,21 @@ function compute_nu(a0, b0) return nu end - -function compute_Pi(B, R, rvn, g,xi) - pi = B[2:end] - R[1:end-1] .* B[1:end-1] - rvn[1:end-1] + g[1:end-1] - Pi = cumsum(pi .*xi) +function compute_Pi(B, R, rvn, g, xi) + pi = B[2:end] - R[1:(end - 1)] .* B[1:(end - 1)] - rvn[1:(end - 1)] + + g[1:(end - 1)] + Pi = cumsum(pi .* xi) return pi, Pi end - -function compute_paths(econ::Economy{<:AbstractFloat, <:DiscreteStochProcess}, T) +function compute_paths(econ::Economy{<:AbstractFloat, <:DiscreteStochProcess}, + T) # simplify notation - (;beta, Sg, Sd, Sb, Ss) = econ - (;P, x_vals) = econ.proc + (; beta, Sg, Sd, Sb, Ss) = econ + (; P, x_vals) = econ.proc mc = MarkovChain(P) - state = simulate(mc, T, init=1) + state = simulate(mc, T, init = 1) x = x_vals[:, state] # Compute exogenous sequence @@ -678,9 +674,9 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:DiscreteStochProcess}, T # compute a0, b0 ns = size(P, 1) - F = I - beta.*P - a0 = (F \ ((Sm * x_vals)'.^2))[1] ./ 2 - H = ((Sb - Sd + Sg) * x_vals) .* ((Sg - Ss)*x_vals) + F = I - beta .* P + a0 = (F \ ((Sm * x_vals)' .^ 2))[1] ./ 2 + H = ((Sb - Sd + Sg) * x_vals) .* ((Sg - Ss) * x_vals) b0 = (F \ H')[1] ./ 2 # compute lagrange multiplier @@ -690,24 +686,24 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:DiscreteStochProcess}, T Sc, Sl, c, l, p, tau, rvn = compute_allocation(econ, Sm, nu, x, b) # compute remaining variables - H = ((Sb - Sc) * x_vals) .* ((Sl - Sg) * x_vals) - (Sl * x_vals).^2 + H = ((Sb - Sc) * x_vals) .* ((Sl - Sg) * x_vals) - (Sl * x_vals) .^ 2 temp = dropdims(F * H', dims = 2) B = temp[state] ./ p H = dropdims(P[state, :] * ((Sb - Sc) * x_vals)', dims = 2) R = p ./ (beta .* H) - temp = dropdims(P[state, :] *((Sb - Sc) * x_vals)', dims = 2) - xi = p[2:end] ./ temp[1:end-1] + temp = dropdims(P[state, :] * ((Sb - Sc) * x_vals)', dims = 2) + xi = p[2:end] ./ temp[1:(end - 1)] # compute pi pi, Pi = compute_Pi(B, R, rvn, g, xi) - return (;g, d, b, s, c, l, p, tau, rvn, B, R, pi, Pi, xi) + return (; g, d, b, s, c, l, p, tau, rvn, B, R, pi, Pi, xi) end function compute_paths(econ::Economy{<:AbstractFloat, <:ContStochProcess}, T) # simplify notation - (;beta, Sg, Sd, Sb, Ss) = econ - (;A, C) = econ.proc + (; beta, Sg, Sd, Sb, Ss) = econ + (; A, C) = econ.proc # generate an initial condition x0 satisfying x0 = A x0 nx, nx = size(A) @@ -722,7 +718,7 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:ContStochProcess}, T) w = randn(nw, T) x[:, 1] = x0 for t in 2:T - x[:, t] = A *x[:, t-1] + C * w[:, t] + x[:, t] = A * x[:, t - 1] + C * w[:, t] end # compute exogenous sequence @@ -731,7 +727,7 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:ContStochProcess}, T) # compute a0 and b0 H = Sm'Sm a0 = 0.5 * var_quadratic_sum(A, C, H, beta, x0) - H = (Sb - Sd + Sg)'*(Sg + Ss) + H = (Sb - Sd + Sg)' * (Sg + Ss) b0 = 0.5 * var_quadratic_sum(A, C, H, beta, x0) # compute lagrange multiplier @@ -741,51 +737,50 @@ function compute_paths(econ::Economy{<:AbstractFloat, <:ContStochProcess}, T) Sc, Sl, c, l, p, tau, rvn = compute_allocation(econ, Sm, nu, x, b) # compute remaining variables - H = Sl'Sl - (Sb - Sc)' *(Sl - Sg) + H = Sl'Sl - (Sb - Sc)' * (Sl - Sg) L = zeros(T) for t in eachindex(L) L[t] = var_quadratic_sum(A, C, H, beta, x[:, t]) end B = L ./ p - Rinv = dropdims(beta .* (Sb- Sc)*A*x, dims = 1) ./ p + Rinv = dropdims(beta .* (Sb - Sc) * A * x, dims = 1) ./ p R = 1 ./ Rinv AF1 = (Sb - Sc) * x[:, 2:end] - AF2 = (Sb - Sc) * A * x[:, 1:end-1] - xi = AF1 ./ AF2 - xi = dropdims(xi, dims = 1) + AF2 = (Sb - Sc) * A * x[:, 1:(end - 1)] + xi = AF1 ./ AF2 + xi = dropdims(xi, dims = 1) # compute pi pi, Pi = compute_Pi(B, R, rvn, g, xi) - return(;g, d, b, s, c, l, p, tau, rvn, B, R, pi, Pi, xi) + return (; g, d, b, s, c, l, p, tau, rvn, B, R, pi, Pi, xi) end function gen_fig_1(path) T = length(path.c) - plt_1 = plot(path.rvn, lw=2, label = L"\tau_t l_t") - plot!(plt_1, path.g, lw=2, label= L"g_t") - plot!(plt_1, path.c, lw=2, label= L"c_t") - plot!(xlabel="Time", grid=true) + plt_1 = plot(path.rvn, lw = 2, label = L"\tau_t l_t") + plot!(plt_1, path.g, lw = 2, label = L"g_t") + plot!(plt_1, path.c, lw = 2, label = L"c_t") + plot!(xlabel = "Time", grid = true) - plt_2 = plot(path.rvn, lw=2, label=L"\tau_t l_t") - plot!(plt_2, path.g, lw=2, label=L"g_t") - plot!(plt_2, path.B[2:end], lw=2, label=L"B_{t+1}") - plot!(xlabel="Time", grid=true) + plt_2 = plot(path.rvn, lw = 2, label = L"\tau_t l_t") + plot!(plt_2, path.g, lw = 2, label = L"g_t") + plot!(plt_2, path.B[2:end], lw = 2, label = L"B_{t+1}") + plot!(xlabel = "Time", grid = true) - plt_3 = plot(path.R, lw=2, label=L"R_{t-1}") - plot!(plt_3, xlabel="Time", grid=true) + plt_3 = plot(path.R, lw = 2, label = L"R_{t-1}") + plot!(plt_3, xlabel = "Time", grid = true) - plt_4 = plot(path.rvn, lw=2, label=L"\tau_t l_t") - plot!(plt_4, path.g, lw=2, label=L"g_t") - plot!(plt_4, path.pi, lw=2, label=L"\pi_t") - plot!(plt_4, xlabel="Time", grid=true) + plt_4 = plot(path.rvn, lw = 2, label = L"\tau_t l_t") + plot!(plt_4, path.g, lw = 2, label = L"g_t") + plot!(plt_4, path.pi, lw = 2, label = L"\pi_t") + plot!(plt_4, xlabel = "Time", grid = true) - plot(plt_1, plt_2, plt_3, plt_4, layout=(2,2), size = (800,600)) + plot(plt_1, plt_2, plt_3, plt_4, layout = (2, 2), size = (800, 600)) end function gen_fig_2(path) - T = length(path.c) paths = [path.xi, path.Pi] @@ -795,9 +790,10 @@ function gen_fig_2(path) plots = [plt_1, plt_2] for (plot, path, label) in zip(plots, paths, labels) - plot!(plot, 2:T, path, lw=2, label=label, xlabel="Time", grid=true) + plot!(plot, 2:T, path, lw = 2, label = label, xlabel = "Time", + grid = true) end - plot(plt_1, plt_2, layout=(2,1), size = (600,500)) + plot(plt_1, plt_2, layout = (2, 1), size = (600, 500)) end ``` @@ -842,9 +838,9 @@ Random.seed!(42) # parameters beta = 1 / 1.05 -rho, mg = .7, .35 +rho, mg = 0.7, 0.35 A = [rho mg*(1 - rho); 0.0 1.0] -C = [sqrt(1 - rho^2) * mg / 10 0.0; 0 0] +C = [sqrt(1 - rho^2) * mg/10 0.0; 0 0] Sg = [1.0 0.0] Sd = [0.0 0.0] Sb = [0 2.135] @@ -858,22 +854,6 @@ path = compute_paths(econ, T) gen_fig_1(path) ``` -```{code-cell} julia ---- -tags: [remove-cell] ---- -@testset begin - #test path.p[3] ≈ 1.5395294981420302 atol = 1e-3 # randomness check. - #test path.g[31] ≈ 0.366487070014081 atol = 1e-3 # stuff we plot - #test path.c[36] ≈ 0.6291101011610297 atol = 1e-3 - #test path.B[9] ≈ 0.07442403655989423 atol = 1e-3 - #test path.rvn[27] ≈ 0.35013269833342753 atol = 1e-3 - #test path.pi[31] ≈ -0.05846215388377568 atol = 1e-3 - #test path.R[43] ≈ 1.0437715852385672 atol = 1e-3 - #test path.xi[43] ≈ 1.001895202392805 atol = 1e-3 - #test path.Pi[43] ≈ -0.4185282208457552 atol = 1e-3 # plot tests -end -``` The legends on the figures indicate the variables being tracked. @@ -907,16 +887,16 @@ Random.seed!(42); # Parameters beta = 1 / 1.05 P = [0.8 0.2 0.0 - 0.0 0.5 0.5 - 0.0 0.0 1.0] + 0.0 0.5 0.5 + 0.0 0.0 1.0] # Possible states of the world # Each column is a state of the world. The rows are [g d b s 1] x_vals = [0.5 0.5 0.25; - 0.0 0.0 0.0; - 2.2 2.2 2.2; - 0.0 0.0 0.0; - 1.0 1.0 1.0] + 0.0 0.0 0.0; + 2.2 2.2 2.2; + 0.0 0.0 0.0; + 1.0 1.0 1.0] Sg = [1.0 0.0 0.0 0.0 0.0] Sd = [0.0 1.0 0.0 0.0 0.0] Sb = [0.0 0.0 1.0 0.0 0.0] @@ -930,23 +910,6 @@ path = compute_paths(econ, T) gen_fig_1(path) ``` -```{code-cell} julia ---- -tags: [remove-cell] ---- -@testset begin - #test path.p[3] ≈ 1.5852129146694405 - #test path.B[13] ≈ 0.003279632025474284 - #@test path.g ≈ [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, 0.25, - # 0.25, 0.25] - #test path.rvn[7] ≈ 0.3188722725349599 - #test path.c[2] ≈ 0.6147870853305598 - #@test path.R ≈ [1.05, 1.05, 1.05, 1.05, 1.05, 1.0930974212983846, 1.05, 1.05, 1.05, 1.05, - # 1.05, 1.05, 1.05, 1.05, 1.05] - #@test path.xi ≈ [1.0, 1.0, 1.0, 1.0, 1.0, 0.9589548368586813, 1.0, 1.0, 1.0, 1.0, 1.0, - # 1.0, 1.0, 1.0] -end -``` The call `gen_fig_2(path)` generates @@ -1011,21 +974,6 @@ T = 50 path = compute_paths(econ, T) ``` -```{code-cell} julia ---- -tags: [remove-cell] ---- -@testset begin - #test path.p[3] ≈ 1.524261187305079 - #test path.B[13] ≈ -0.053219518947408805 - #test path.g[7] ≈ 0.36908804521710115 - #test path.rvn[7] ≈ 0.35146870025913474 - #test path.c[2] ≈ 0.6259521929536346 - #test path.R[5][1] ≈ 1.0501742289013196 - #test path.xi[10] ≈ 1.002202281639002 -end -``` - ```{code-cell} julia gen_fig_1(path) ``` diff --git a/lectures/dynamic_programming_squared/opt_tax_recur.md b/lectures/dynamic_programming_squared/opt_tax_recur.md index a8e0efb2..b58ab291 100644 --- a/lectures/dynamic_programming_squared/opt_tax_recur.md +++ b/lectures/dynamic_programming_squared/opt_tax_recur.md @@ -1490,30 +1490,29 @@ This utility function is implemented in the type CRRAutility ```{code-cell} julia function crra_utility(; - beta = 0.9, - sigma = 2.0, - gamma = 2.0, - Pi = 0.5 * ones(2, 2), - G = [0.1, 0.2], - Theta = ones(2), - transfers = false - ) + beta = 0.9, + sigma = 2.0, + gamma = 2.0, + Pi = 0.5 * ones(2, 2), + G = [0.1, 0.2], + Theta = ones(2), + transfers = false) function U(c, n) if sigma == 1.0 U = log(c) else - U = (c.^(1.0 .- sigma) .- 1.0) / (1.0 - sigma) + U = (c .^ (1.0 .- sigma) .- 1.0) / (1.0 - sigma) end - return U .- n.^(1 + gamma) / (1 + gamma) + return U .- n .^ (1 + gamma) / (1 + gamma) end # Derivatives of utility function - Uc(c,n) = c.^(-sigma) - Ucc(c,n) = -sigma * c.^(-sigma - 1.0) - Un(c,n) = -n.^gamma - Unn(c,n) = -gamma * n.^(gamma - 1.0) + Uc(c, n) = c .^ (-sigma) + Ucc(c, n) = -sigma * c .^ (-sigma - 1.0) + Un(c, n) = -n .^ gamma + Unn(c, n) = -gamma * n .^ (gamma - 1.0) n_less_than_one = false return Model(beta, Pi, G, Theta, transfers, - U, Uc, Ucc, Un, Unn, n_less_than_one) + U, Uc, Ucc, Un, Unn, n_less_than_one) end ``` @@ -1528,15 +1527,15 @@ We can now plot the Ramsey tax under both realizations of time $t = 3$ governme using Random Random.seed!(42) # For reproducible results. -M_time_example = crra_utility(G=[0.1, 0.1, 0.1, 0.2, 0.1, 0.1], - Theta=ones(6)) # Theta can in principle be random +M_time_example = crra_utility(G = [0.1, 0.1, 0.1, 0.2, 0.1, 0.1], + Theta = ones(6)) # Theta can in principle be random M_time_example.Pi = [0.0 1.0 0.0 0.0 0.0 0.0; - 0.0 0.0 1.0 0.0 0.0 0.0; - 0.0 0.0 0.0 0.5 0.5 0.0; - 0.0 0.0 0.0 0.0 0.0 1.0; - 0.0 0.0 0.0 0.0 0.0 1.0; - 0.0 0.0 0.0 0.0 0.0 1.0] + 0.0 0.0 1.0 0.0 0.0 0.0; + 0.0 0.0 0.0 0.5 0.5 0.0; + 0.0 0.0 0.0 0.0 0.0 1.0; + 0.0 0.0 0.0 0.0 0.0 1.0; + 0.0 0.0 0.0 0.0 0.0 1.0] PP_seq_time = SequentialAllocation(M_time_example) # Solve sequential problem @@ -1556,38 +1555,23 @@ titles = hcat("Consumption", "Output") sim_seq_l_plot = [sim_seq_l[1:4]..., M_time_example.G[sHist_l], - M_time_example.Theta[sHist_l].*sim_seq_l[2]] + M_time_example.Theta[sHist_l] .* sim_seq_l[2]] sim_seq_h_plot = [sim_seq_h[1:4]..., M_time_example.G[sHist_h], - M_time_example.Theta[sHist_h].*sim_seq_h[2]] - + M_time_example.Theta[sHist_h] .* sim_seq_h[2]] #plots = plot(layout=(3,2), size=(800,600)) plots = [plot(), plot(), plot(), plot(), plot(), plot()] -for i = 1:6 - plot!(plots[i], sim_seq_l_plot[i], color=:black, lw=2, - marker=:circle, markersize=2, label="") - plot!(plots[i], sim_seq_h_plot[i], color=:red, lw=2, - marker=:circle, markersize=2, label="") - plot!(plots[i], title=titles[i], grid=true) +for i in 1:6 + plot!(plots[i], sim_seq_l_plot[i], color = :black, lw = 2, + marker = :circle, markersize = 2, label = "") + plot!(plots[i], sim_seq_h_plot[i], color = :red, lw = 2, + marker = :circle, markersize = 2, label = "") + plot!(plots[i], title = titles[i], grid = true) end -plot(plots[1], plots[2], plots[3], plots[4], plots[5], plots[6], layout=(3,2), size=(800,600)) +plot(plots[1], plots[2], plots[3], plots[4], plots[5], plots[6], + layout = (3, 2), size = (800, 600)) ``` -```{code-cell} julia ---- -tags: [remove-cell] ---- -@testset begin - @test M_time_example.G[sHist_l] ≈ [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] - #test M_time_example.Theta[sHist_l] .* sim_seq_l[2] ≈ [1.026385289423105, 0.9945696863679917, - # 0.9945696863679917, 0.9945696863679917, - # 0.9945696863679917, 0.9945696863679917, - # 0.9945696863679917] - @test M_time_example.G[sHist_h] ≈ [0.1, 0.1, 0.1, 0.2, 0.1, 0.1, 0.1] - #test sim_seq_l[end] ≈ [1.0361020796451619, 1.111111111111111, 1.052459380877434, - # 1.111111111111111, 1.111111111111111, 1.111111111111111] -end -``` **Tax smoothing** @@ -1628,11 +1612,11 @@ The following plot illustrates how the government lowers the interest rate at time 0 by raising consumption ```{code-cell} julia -plot(sim_seq_l[end], color=:black, lw=2, - marker=:circle, markersize=2, label="") -plot!(sim_seq_h[end], color=:red, lw=2, - marker=:circle, markersize=2, label="") -plot!(title="Gross Interest Rate", grid=true) +plot(sim_seq_l[end], color = :black, lw = 2, + marker = :circle, markersize = 2, label = "") +plot!(sim_seq_h[end], color = :red, lw = 2, + marker = :circle, markersize = 2, label = "") +plot!(title = "Gross Interest Rate", grid = true) ``` ### Government Saving @@ -1701,35 +1685,25 @@ Random.seed!(42); # For reproducible results. ``` ```{code-cell} julia -M2 = crra_utility(G=[0.15], Pi=ones(1, 1), Theta=[1.0]) +M2 = crra_utility(G = [0.15], Pi = ones(1, 1), Theta = [1.0]) PP_seq_time0 = SequentialAllocation(M2) # solve sequential problem B_vec = range(-1.5, 1.0, length = 100) taxpolicy = Matrix(hcat([simulate(PP_seq_time0, B_, 1, 2)[4] for B_ in B_vec]...)') -interest_rate = Matrix(hcat([simulate(PP_seq_time0, B_, 1, 3)[end] for B_ in B_vec]...)') +interest_rate = Matrix(hcat([simulate(PP_seq_time0, B_, 1, 3)[end] + for B_ in B_vec]...)') titles = ["Tax Rate" "Gross Interest Rate"] labels = [[L"Time , $t = 0$" L"Time , $t \geq 0$"], ""] -plots = plot(layout=(2,1), size =(700,600)) +plots = plot(layout = (2, 1), size = (700, 600)) for (i, series) in enumerate((taxpolicy, interest_rate)) - plot!(plots[i], B_vec, series, linewidth=2, label=labels[i]) - plot!(plots[i], title=titles[i], grid=true, legend=:topleft) + plot!(plots[i], B_vec, series, linewidth = 2, label = labels[i]) + plot!(plots[i], title = titles[i], grid = true, legend = :topleft) end plot(plots) ``` -```{code-cell} julia ---- -tags: [remove-cell] ---- -@testset begin - #test B_vec[3] ≈ -1.4494949494949494 - #test taxpolicy[2, 2] ≈ 0.0020700125847712414 - #test interest_rate[3, 1] ≈ 1.113064964490116 -end -``` - The figure indicates that if the government enters with positive debt, it sets a tax rate at $t=0$ that is less than all later tax rates. @@ -1781,9 +1755,10 @@ B1_vec = hcat([simulate(PP_seq_time0, B_, 1, 2)[3][2] for B_ in B_vec]...)' # Compute the optimal policy if the government could reset tau1_reset = Matrix(hcat([simulate(PP_seq_time0, B1, 1, 1)[4] for B1 in B1_vec]...)') -plot(B_vec, taxpolicy[:, 2], linewidth=2, label=L"\tau_1") -plot!(B_vec, tau1_reset, linewidth=2, label=L"\tau_1^R") -plot!(title="Tax Rate", xlabel="Initial Government Debt", legend=:topleft, grid=true) +plot(B_vec, taxpolicy[:, 2], linewidth = 2, label = L"\tau_1") +plot!(B_vec, tau1_reset, linewidth = 2, label = L"\tau_1^R") +plot!(title = "Tax Rate", xlabel = "Initial Government Debt", legend = :topleft, + grid = true) ``` The tax rates in the figure are equal for only two values of initial government debt. @@ -1819,21 +1794,21 @@ $$ We will write a new constructor LogUtility to represent this utility function ```{code-cell} julia -function log_utility(;beta = 0.9, - psi = 0.69, - Pi = 0.5 * ones(2, 2), - G = [0.1, 0.2], - Theta = ones(2), - transfers = false) +function log_utility(; beta = 0.9, + psi = 0.69, + Pi = 0.5 * ones(2, 2), + G = [0.1, 0.2], + Theta = ones(2), + transfers = false) # Derivatives of utility function - U(c,n) = log(c) + psi * log(1 - n) - Uc(c,n) = 1 ./ c - Ucc(c,n) = -c.^(-2.0) - Un(c,n) = -psi ./ (1.0 .- n) - Unn(c,n) = -psi ./ (1.0 .- n).^2.0 + U(c, n) = log(c) + psi * log(1 - n) + Uc(c, n) = 1 ./ c + Ucc(c, n) = -c .^ (-2.0) + Un(c, n) = -psi ./ (1.0 .- n) + Unn(c, n) = -psi ./ (1.0 .- n) .^ 2.0 n_less_than_one = true return Model(beta, Pi, G, Theta, transfers, - U, Uc, Ucc, Un, Unn, n_less_than_one) + U, Uc, Ucc, Un, Unn, n_less_than_one) end ``` @@ -1853,7 +1828,7 @@ Random.seed!(42); # For reproducible results. ```{code-cell} julia M1 = log_utility() -mu_grid = range(-0.6, 0.0, length = 200) +mu_grid = range(-0.6, 0.0, length = 200) PP_seq = SequentialAllocation(M1) # Solve sequential problem PP_bel = RecursiveAllocation(M1, mu_grid) # Solve recursive problem @@ -1865,8 +1840,8 @@ sim_seq = simulate(PP_seq, 0.5, 1, T, sHist) sim_bel = simulate(PP_bel, 0.5, 1, T, sHist) # Plot policies -sim_seq_plot = [sim_seq[1:4]..., M1.G[sHist], M1.Theta[sHist].*sim_seq[2]] -sim_bel_plot = [sim_bel[1:4]..., M1.G[sHist], M1.Theta[sHist].*sim_bel[2]] +sim_seq_plot = [sim_seq[1:4]..., M1.G[sHist], M1.Theta[sHist] .* sim_seq[2]] +sim_bel_plot = [sim_bel[1:4]..., M1.G[sHist], M1.Theta[sHist] .* sim_bel[2]] titles = hcat("Consumption", "Labor Supply", @@ -1874,36 +1849,26 @@ titles = hcat("Consumption", "Tax Rate", "Government Spending", "Output") -labels = [["Sequential", "Recursive"], ["",""], ["",""], ["",""], ["",""], ["",""]] -plots=plot(layout=(3,2), size=(850,780)) - -for i = 1:6 - plot!(plots[i], sim_seq_plot[i], color=:black, lw=2, marker=:circle, - markersize=2, label=labels[i][1]) - plot!(plots[i], sim_bel_plot[i], color=:blue, lw=2, marker=:xcross, - markersize=2, label=labels[i][2]) - plot!(plots[i], title=titles[i], grid=true, legend=:topright) +labels = [ + ["Sequential", "Recursive"], + ["", ""], + ["", ""], + ["", ""], + ["", ""], + ["", ""], +] +plots = plot(layout = (3, 2), size = (850, 780)) + +for i in 1:6 + plot!(plots[i], sim_seq_plot[i], color = :black, lw = 2, marker = :circle, + markersize = 2, label = labels[i][1]) + plot!(plots[i], sim_bel_plot[i], color = :blue, lw = 2, marker = :xcross, + markersize = 2, label = labels[i][2]) + plot!(plots[i], title = titles[i], grid = true, legend = :topright) end plot(plots) ``` -```{code-cell} julia ---- -tags: [remove-cell] ---- -@testset begin - #test sim_seq_plot[1][14] ≈ 0.38396935397869975 - #test sim_seq_plot[2][14] ≈ 0.5839693539786998 - #test sim_seq_plot[3][14] ≈ 0.3951985593686047 - #test sim_seq_plot[4][14] ≈ 0.3631746680706347 - #test sim_seq_plot[5][14] ≈ 0.2 - #test sim_seq_plot[6][14] ≈ 0.5839693539786998 - #test sim_bel_plot[3][5] ≈ 0.5230509296608254 atol = 1e-3 - #test sim_bel_plot[5][7] ≈ 0.1 - #test sim_bel_plot[2][3] ≈ 0.5402933557593538 atol = 1e-3 -end -``` - As should be expected, the recursive and sequential solutions produce almost identical allocations.