Skip to content

Commit 4314b8a

Browse files
authored
Small typos and better layout (#205)
1 parent ed2475c commit 4314b8a

File tree

1 file changed

+33
-30
lines changed

1 file changed

+33
-30
lines changed

lectures/introduction_dynamics/wealth_dynamics.md

Lines changed: 33 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ We do this to more easily explore the implications of different specifications o
6363
At the same time, all of the techniques discussed here can be plugged into models that use optimization to obtain savings rules.
6464

6565
```{code-cell} julia
66-
using Distributions, Plots, LaTeXStrings, LinearAlgebra, BenchmarkTools, LoopVectorization
66+
using Distributions, Plots, LaTeXStrings, LinearAlgebra, BenchmarkTools
67+
using LoopVectorization
6768
```
6869

6970
## Lorenz Curves and the Gini Coefficient
@@ -351,17 +352,14 @@ function wealth_dynamics_model(; # all named arguments
351352
z_stationary_dist = Normal(z_mean, sqrt(z_var))
352353
353354
@assert α <= 1 # check stability condition that wealth does not diverge
354-
return (;w_hat, s_0, c_y, μ_y, σ_y, c_r, μ_r, σ_r, a, b, σ_z, z_mean, z_var,
355-
z_stationary_dist, exp_z_mean, R_mean, y_mean, α)
356-
end
357-
358-
# example of model with all default values
359-
wealth_dynamics_model()
355+
return (;w_hat, s_0, c_y, μ_y, σ_y, c_r, μ_r, σ_r, a, b, σ_z, z_mean,
356+
z_var,z_stationary_dist, exp_z_mean, R_mean, y_mean, α)
357+
end
360358
```
361359

362360
## Simulating Wealth Dynamics
363361

364-
To implement this process, we will write a funciton which simulates an entire path for an agent or the wealth distribution.
362+
To implement this process, we will write a function which simulates an entire path for an agent or the wealth distribution.
365363

366364
The `p` argument is a named-tuple or struct consist with the `wealth_dynamics_model` function above.
367365

@@ -429,7 +427,7 @@ function f2(x)
429427
temp = (x >= 0.0) ? x : -x
430428
return val + temp
431429
end
432-
f3(x) = 2.0 + ( (x >= 0.0) ? x : -x) # needs parenthesis for order of operations
430+
f3(x) = 2.0 + ( (x >= 0.0) ? x : -x)
433431
@show f1(0.8), f2(0.8), f3(0.8)
434432
@show f1(1.8), f2(1.8), f3(1.8);
435433
```
@@ -452,9 +450,9 @@ function simulate_panel(N, T, p)
452450
R_shock = randn(N)
453451
w_shock = randn(N)
454452
@turbo for i in 1:N
455-
zp[i] = a*z[i] + b + σ_z * z_shock[i]
456-
R[i] = (w[i] >= w_hat) ? c_r * exp(zp[i]) + exp(μ_r + σ_r*R_shock[i]) : 0.0
457-
wp[i] = c_y*exp(zp[i]) + exp(μ_y + σ_y*w_shock[i]) + R[i] * s_0*w[i]
453+
zp[i] = a*z[i] + b + σ_z*z_shock[i]
454+
R[i] = (w[i] >= w_hat) ? c_r*exp(zp[i]) + exp(μ_r + σ_r*R_shock[i]) : 0.0
455+
wp[i] = c_y*exp(zp[i]) + exp(μ_y + σ_y*w_shock[i]) + R[i]*s_0*w[i]
458456
end
459457
# Step forward
460458
w .= wp
@@ -470,10 +468,8 @@ We have used a look with a few modifications to help with efficiency. To summar
470468
- replaced the `if` with the ternary interface
471469
- preallocated a `zp, wp, R` to store intermediate values for the calculations.
472470
- swapped the `w, z` and `wp, zp` to step forward each period rather than savings all of the simulation paths. This is sufficient since we will only plot statistics of the terminal distribution rather than in the transition.
473-
- replaced the `randn()` at each simulation step with a draw of random values for all agents, i.e. `randn(N)`. This will make parallelization possible.
474471
- annotated with the `@turbo` macro uses a package to speed up the inner loop. This is discussed in more detail below.
475-
476-
Using this function, we can iterate forward from a distribution of wealth and income
472+
- replaced the `randn()` at each simulation step with a draw of random values for all agents, i.e. `z_shock, R_shock, w_shock`. This will make parallelization with `@turbo` possible.
477473

478474
To use this function, we pass in parameters and can access the resulting wealth distribution and inequality measures.
479475

@@ -482,7 +478,8 @@ p = wealth_dynamics_model()
482478
N = 100_000
483479
T = 500
484480
res = simulate_panel(N, T, p)
485-
@show median(res.w), mean(res.w), res.gini;
481+
@show median(res.w)
482+
@show res.gini;
486483
```
487484

488485
Now we investigate how the Lorenz curves associated with the wealth distribution change as return to savings varies.
@@ -491,15 +488,18 @@ The code below simulates the wealth distribution, Lorenz curve, and gini for mul
491488

492489
```{code-cell} julia
493490
494-
μ_r_vals = LinRange(0.0, 0.075, 7)
495-
results = map(μ_r -> simulate_panel(N, T, wealth_dynamics_model(;μ_r)), μ_r_vals);
491+
μ_r_vals = LinRange(0.0, 0.075, 5)
492+
results = map(μ_r -> simulate_panel(N, T, wealth_dynamics_model(;μ_r)),
493+
μ_r_vals);
496494
```
497495

498496
Using these results, we can plot the Lorenz curves for each value of $\mu_r$ and compare to perfect equality.
499497

500498
```{code-cell} julia
501-
plt = plot(results[1].F, results[1].F, label = "equality", legend = :topleft, ylabel="Lorenz Curve")
502-
[plot!(plt, res.F, res.L, label = L"\psi^*, \mu_r = %$(round(μ_r; sigdigits=1))")
499+
plt = plot(results[1].F, results[1].F, label = "equality", legend = :topleft,
500+
ylabel="Lorenz Curve")
501+
[plot!(plt, res.F, res.L,
502+
label = L"\psi^*, \mu_r = %$(round(μ_r;sigdigits=1))")
503503
for (μ_r, res) in zip(μ_r_vals, results)]
504504
plt
505505
```
@@ -518,10 +518,13 @@ Let's finish this section by investigating what happens when we change the
518518
volatility term $\sigma_r$ in financial returns.
519519

520520
```{code-cell} julia
521-
σ_r_vals = LinRange(0.35, 0.53, 7)
522-
results = map(σ_r -> simulate_panel(N, T, wealth_dynamics_model(;σ_r)), σ_r_vals);
523-
plt = plot(results[1].F, results[1].F, label = "equality", legend = :topleft, ylabel="Lorenz Curve")
524-
[plot!(plt, res.F, res.L, label = L"\psi^*, \sigma_r = %$(round(σ_r; sigdigits=2))")
521+
σ_r_vals = LinRange(0.35, 0.53, 5)
522+
results = map(σ_r -> simulate_panel(N, T, wealth_dynamics_model(;σ_r)),
523+
σ_r_vals);
524+
plt = plot(results[1].F, results[1].F, label = "equality", legend = :topleft,
525+
ylabel="Lorenz Curve")
526+
[plot!(plt, res.F, res.L,
527+
label = L"\psi^*, \sigma_r = %$(round(σ_r; sigdigits=2))")
525528
for (σ_r, res) in zip(σ_r_vals, results)]
526529
plt
527530
```
@@ -570,7 +573,7 @@ function simulate_panel_no_turbo(N, T, p)
570573
571574
for t in 1:T
572575
@inbounds for i in 1:N
573-
zp[i] = a*z[i] + b + σ_z * randn() # no need to preallocate the randn(N) if avoiding @turbo
576+
zp[i] = a*z[i] + b + σ_z * randn()
574577
R[i] = (w[i] >= w_hat) ? c_r * exp(zp[i]) + exp(μ_r + σ_r*randn()) : 0.0
575578
wp[i] = c_y*exp(zp[i]) + exp(μ_y + σ_y*randn()) + R[i] * s_0*w[i]
576579
end
@@ -607,7 +610,7 @@ function simulate_panel_vectorized(N, T, p)
607610
w = y_0 # start at mean of income process
608611
z = z_0
609612
for t in 1:T
610-
w, z = step_wealth_vectorized(w, z, p) # steps forward, discarding results
613+
w, z = step_wealth_vectorized(w, z, p) # steps forward
611614
end
612615
sort!(w) # sorts the wealth so we can calculate gini/lorenz
613616
F, L = lorenz(w)
@@ -628,12 +631,12 @@ T = 200
628631
The results displayed above are done with the server compiling these notes, and is likely not representative. For example, on one of our machines the results are
629632

630633
```{code-block} none
631-
192.621 ms (1218 allocations: 463.90 MiB)
632-
592.451 ms (18 allocations: 6.10 MiB)
633-
589.632 ms (6412 allocations: 2.39 GiB)
634+
282.244 ms (1218 allocations: 463.90 MiB)
635+
576.120 ms (18 allocations: 6.10 MiB)
636+
836.909 ms (6412 allocations: 2.39 GiB)
634637
```
635638

636-
The performance will depend on the availability of SIMD and AVX512 on your processor and your number of threads for the `tturbo` version. `LoopVectorization.jl` can also parallelize over threads and multiple processes by replacing with the `@tturbo` macro, but this does not seem to significantly improve performance in this case.
639+
The performance will depend on the availability of [SIMD](https://en.wikipedia.org/wiki/Single_instruction,_multiple_data) and [AVX512](https://en.wikipedia.org/wiki/AVX-512) on your processor. `LoopVectorization.jl` can also parallelize over threads and multiple processes by replacing with the `@tturbo` macro, but this does not seem to significantly improve performance in this case.
637640
<!--
638641
# DECIDED AGAINST INCLUSION AFTER SEEING PERFORMANCE OF LOOPVECTORIZATION VERSION
639642

0 commit comments

Comments
 (0)