From 6f754825fa2741ba7b68c9d51e776007b1ce0edd Mon Sep 17 00:00:00 2001 From: Adriano Meligrana <68152031+Tortar@users.noreply.github.com> Date: Thu, 28 Nov 2024 23:18:40 +0100 Subject: [PATCH] Use threads local sums of C_h and I_h to reduce memory consumption (#33) --- .github/workflows/documentation.yml | 2 +- .github/workflows/test.yml | 10 +- docs/src/index.md | 2 +- src/markets/search_and_matching.jl | 86 ++-- .../deterministic/initialize_deterministic.jl | 3 +- test/deterministic/one_epoch_deterministic.jl | 461 +++++++++--------- test/deterministic/one_run_deterministic.jl | 36 +- test/markets/search_and_matching.jl | 187 +++---- 8 files changed, 390 insertions(+), 397 deletions(-) diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index acbea42..b3eef9a 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -28,7 +28,7 @@ jobs: - uses: julia-actions/setup-julia@v2 with: version: '1.10' - - uses: julia-actions/cache@v1 + - uses: julia-actions/cache@v2 - name: Install Dependencies run: | julia --project=./docs -e ' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f9da739..e4b906c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,13 +16,13 @@ jobs: arch: - x64 steps: - - uses: actions/checkout@v2 - - uses: julia-actions/setup-julia@v1 + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - - uses: actions/cache@v1 + - uses: actions/cache@v2 env: cache-name: cache-artifacts with: @@ -33,4 +33,6 @@ jobs: ${{ runner.os }}-test- ${{ runner.os }}- - uses: julia-actions/julia-buildpkg@v1 - - uses: julia-actions/julia-runtest@v1 \ No newline at end of file + - uses: julia-actions/julia-runtest@v1 + env: + JULIA_NUM_THREADS: 2 diff --git a/docs/src/index.md b/docs/src/index.md index 577798e..415e7db 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -58,6 +58,7 @@ Copyright 2024- Banca d'Italia and the authors. - [Aldo Glielmo](https://github.com/AldoGl) <[aldo.glielmo@bancaditalia.it](mailto:aldo.glielmo@bancaditalia.it)> - [Mitja Devetak](https://github.com/Devetak) <[m888itja@gmail.com](mailto:m888itja@gmail.com)> +- [Adriano Meligrana](https://github.com/Tortar) <[adrianomeligrana@proton.me](mailto:adrianomeligrana@proton.me)> ## Other collaborators and contributors @@ -67,7 +68,6 @@ Copyright 2024- Banca d'Italia and the authors. - [Andrea Gentili](https://www.bankit.art/people/andrea-gentili) for suggesting the name of the pakege - [Arnau Quera-Bofarull](https://github.com/arnauqb) for help in the deployment of the documentation - [Steven Hoekstra](https://github.com/SGHoekstra) for fixing a bug in a script -- [Adriano Meligrana](https://github.com/Tortar) for fixing a bug in a script ## Disclaimer diff --git a/src/markets/search_and_matching.jl b/src/markets/search_and_matching.jl index 8ad170c..f5c14c4 100644 --- a/src/markets/search_and_matching.jl +++ b/src/markets/search_and_matching.jl @@ -35,20 +35,20 @@ function search_and_matching!(model, multi_threading = false) c_G_g, Q_d_i_g, Q_d_m_g, - C_h_g, - I_h_g, + C_h_t, + I_h_t, C_j_g, C_l_g, P_bar_h_g, P_bar_CF_h_g, P_j_g, - P_l_g = initialize_variables_retail_market(firms, rotw, prop, agg, w_act, w_inact, gov, bank) + P_l_g = initialize_variables_retail_market(firms, rotw, prop, agg, w_act, w_inact, gov, bank, multi_threading) G = size(prop.products.b_HH_g, 1) # number of goods # Loop over all goods (internal and foreign) - function loopBody(g) + function loopBody(i, g) F_g = findall(G_f .== g) S_fg = copy(S_f) S_fg_ = copy(S_f_) @@ -72,6 +72,7 @@ function search_and_matching!(model, multi_threading = false) ) perform_retail_market!( + i, g, agg, gov, @@ -88,8 +89,8 @@ function search_and_matching!(model, multi_threading = false) c_G_g, Q_d_i_g, Q_d_m_g, - C_h_g, - I_h_g, + C_h_t, + I_h_t, C_j_g, C_l_g, P_bar_h_g, @@ -107,12 +108,12 @@ function search_and_matching!(model, multi_threading = false) if multi_threading - Threads.@threads for g in 1:G - loopBody(g) + Threads.@threads :static for g in 1:G + loopBody(Threads.threadid(), g) end else for g in 1:G - loopBody(g) + loopBody(1, g) end end @@ -128,8 +129,8 @@ function search_and_matching!(model, multi_threading = false) I_i_g, P_bar_i_g, DM_i_g, - C_h_g, - I_h_g, + C_h_t, + I_h_t, Q_d_i_g, Q_d_m_g, C_j_g, @@ -154,8 +155,8 @@ function update_aggregate_variables!( I_i_g, P_bar_i_g, DM_i_g, - C_h_g, - I_h_g, + C_h_t, + I_h_t, Q_d_i_g, Q_d_m_g, C_j_g, @@ -179,8 +180,8 @@ function update_aggregate_variables!( Q_d_i = vec(sum(Q_d_i_g, dims = 2)) Q_d_m = vec(sum(Q_d_m_g, dims = 2)) - C_h = sum(C_h_g, dims = 2) - I_h = sum(I_h_g, dims = 2) + C_h = sum(C_h_t, dims = 2) + I_h = sum(I_h_t, dims = 2) gov.C_j = sum(C_j_g) rotw.C_l = sum(C_l_g) @@ -229,7 +230,7 @@ function update_aggregate_variables!( end -function initialize_variables_retail_market(firms, rotw, prop, agg, w_act, w_inact, gov, bank) +function initialize_variables_retail_market(firms, rotw, prop, agg, w_act, w_inact, gov, bank, multi_threading) # ... Initialize all the variables ... # change some variables according to arguments of matlab function @@ -256,8 +257,8 @@ function initialize_variables_retail_market(firms, rotw, prop, agg, w_act, w_ina Q_d_i_g = zeros(size(firms.Y_i)..., G) Q_d_m_g = zeros(size(rotw.Y_m)..., G) - C_h_g = zeros(H, G) - I_h_g = zeros(H, G) + C_h_t = zeros(H, multi_threading ? Threads.nthreads() : 1) + I_h_t = zeros(H, multi_threading ? Threads.nthreads() : 1) C_j_g = zeros(1, G) C_l_g = zeros(1, G) @@ -280,8 +281,8 @@ function initialize_variables_retail_market(firms, rotw, prop, agg, w_act, w_ina c_G_g, Q_d_i_g, Q_d_m_g, - C_h_g, - I_h_g, + C_h_t, + I_h_t, C_j_g, C_l_g, P_bar_h_g, @@ -344,10 +345,10 @@ function perform_firms_market!( DM_nominal_ig = zeros(size(DM_d_ig)) # firms that have demand for good "g" participate as buyers - I_g = findall(DM_d_ig .> 0) + I_g = findall(DM_d_ig .> 0.0) # keep firms that have positive stock of good "g" - filter!(i -> S_fg[i] > 0, F_g) + filter!(i -> S_fg[i] > 0.0, F_g) # continue exchanges until either demand or supply terminates @@ -367,22 +368,22 @@ function perform_firms_market!( if S_fg[f] > DM_d_ig[i] S_fg[f] -= DM_d_ig[i] DM_nominal_ig[i] += DM_d_ig[i] * P_f[f] - DM_d_ig[i] = 0 + DM_d_ig[i] = 0.0 else DM_d_ig[i] -= S_fg[f] - DM_nominal_ig[i] += S_fg[f] .* P_f[f] - S_fg[f] = 0 + DM_nominal_ig[i] += S_fg[f] * P_f[f] + S_fg[f] = 0.0 delete!(F_g_sampler, e) isempty(F_g_sampler) && break end end - filter!(i -> DM_d_ig[i] > 0, I_g) + filter!(i -> DM_d_ig[i] > 0.0, I_g) end if !isempty(I_g) DM_d_ig_ = copy(DM_d_ig) F_g = findall(G_f .== g) - filter!(i -> S_fg_[i] > 0 && S_f[i] > 0, F_g) + filter!(i -> S_fg_[i] > 0.0 && S_f[i] > 0.0, F_g) # weights according to size and price F_g_sampler = create_weighted_sampler(P_f, S_f, F_g) @@ -397,16 +398,16 @@ function perform_firms_market!( if S_fg_[f] > DM_d_ig_[i] S_fg[f] -= DM_d_ig_[i] S_fg_[f] -= DM_d_ig_[i] - DM_d_ig_[i] = 0 + DM_d_ig_[i] = 0.0 else DM_d_ig_[i] -= S_fg_[f] S_fg[f] -= S_fg_[f] - S_fg_[f] = 0 + S_fg_[f] = 0.0 delete!(F_g_sampler, e) isempty(F_g_sampler) && break end end - filter!(i -> DM_d_ig_[i] > 0, I_g) + filter!(i -> DM_d_ig_[i] > 0.0, I_g) end end @@ -427,6 +428,7 @@ end Perform the retail market exchange process """ function perform_retail_market!( + i, g, agg, gov, @@ -443,8 +445,8 @@ function perform_retail_market!( c_G_g, Q_d_i_g, Q_d_m_g, - C_h_g, - I_h_g, + C_h_t, + I_h_t, C_j_g, C_l_g, P_bar_h_g, @@ -470,7 +472,7 @@ function perform_retail_market!( C_real_hg = zeros(size(C_d_hg)) H_g = findall(C_d_hg .> 0.0) - filter!(i -> S_fg[i] > 0, F_g) + filter!(i -> S_fg[i] > 0.0, F_g) # weights according to size and price F_g_sampler = create_weighted_sampler(P_f, S_f, F_g) @@ -485,22 +487,22 @@ function perform_retail_market!( if S_fg[f] > C_d_hg[h] / P_f[f] S_fg[f] -= C_d_hg[h] / P_f[f] C_real_hg[h] += C_d_hg[h] / P_f[f] - C_d_hg[h] = 0 + C_d_hg[h] = 0.0 else C_d_hg[h] -= S_fg[f] * P_f[f] C_real_hg[h] += S_fg[f] - S_fg[f] = 0 + S_fg[f] = 0.0 delete!(F_g_sampler, e) isempty(F_g_sampler) && break end end - filter!(h -> C_d_hg[h] > 0, H_g) + filter!(h -> C_d_hg[h] > 0.0, H_g) end if !isempty(H_g) C_d_hg_ = copy(C_d_hg) F_g = findall(G_f .== g) - filter!(i -> S_fg_[i] > 0 && S_f[i] > 0, F_g) + filter!(i -> S_fg_[i] > 0.0 && S_f[i] > 0.0, F_g) # weights according to size and price F_g_sampler = create_weighted_sampler(P_f, S_f, F_g) @@ -515,16 +517,16 @@ function perform_retail_market!( if S_fg_[f] > C_d_hg_[h] / P_f[f] S_fg[f] -= C_d_hg_[h] / P_f[f] S_fg_[f] -= C_d_hg_[h] / P_f[f] - C_d_hg_[h] = 0 + C_d_hg_[h] = 0.0 else C_d_hg_[h] -= S_fg_[f] * P_f[f] S_fg[f] -= S_fg_[f] - S_fg_[f] = 0 + S_fg_[f] = 0.0 delete!(F_g_sampler, e) isempty(F_g_sampler) && break end end - filter!(h -> C_d_hg_[h] > 0, H_g) + filter!(h -> C_d_hg_[h] > 0.0, H_g) end end @@ -538,8 +540,8 @@ function perform_retail_market!( @~ Q_d_i_g[:, g] .= @view(S_f[1:I]) .- @view(S_fg[1:I]) @~ Q_d_m_g[:, g] .= @view(S_f[(I + 1):end]) .- @view(S_fg[(I + 1):end]) - @~ C_h_g[:, g] .= b - @~ I_h_g[:, g] .= d + @~ C_h_t[:, i] .+= b + @~ I_h_t[:, i] .+= d C_j_g[g] = sum(@~ c_G_g[g] .* gov.C_d_j) - sum(@view(C_d_hg[(H + L + 1):(H + L + J)])) C_l_g[g] = sum(@~ c_E_g[g] .* rotw.C_d_l) - sum(@view(C_d_hg[(H + 1):(H + L)])) diff --git a/test/deterministic/initialize_deterministic.jl b/test/deterministic/initialize_deterministic.jl index 04330a5..80c6c22 100644 --- a/test/deterministic/initialize_deterministic.jl +++ b/test/deterministic/initialize_deterministic.jl @@ -1,6 +1,7 @@ @testset "initialize deterministic" begin - T = 3 + dir = @__DIR__ + T = 3 parameters = BeforeIT.AUSTRIA2010Q1.parameters initial_conditions = BeforeIT.AUSTRIA2010Q1.initial_conditions diff --git a/test/deterministic/one_epoch_deterministic.jl b/test/deterministic/one_epoch_deterministic.jl index 12ccd9a..2ce0d77 100644 --- a/test/deterministic/one_epoch_deterministic.jl +++ b/test/deterministic/one_epoch_deterministic.jl @@ -1,243 +1,232 @@ @testset "one epoch deterministic" begin - dir = @__DIR__ parameters = BeforeIT.AUSTRIA2010Q1.parameters initial_conditions = BeforeIT.AUSTRIA2010Q1.initial_conditions - T = 1 - model = BeforeIT.init_model(parameters, initial_conditions, T;) - - gov = model.gov # government - cb = model.cb # central bank - rotw = model.rotw # rest of the world - firms = model.firms # firms - bank = model.bank # bank - w_act = model.w_act # active workers - w_inact = model.w_inact # inactive workers - agg = model.agg # aggregates - prop = model.prop # model properties - - prop = model.prop - agg.Y_e, agg.gamma_e, agg.pi_e = BeforeIT.growth_inflation_expectations(model) - - @test isapprox(agg.Y_e, 134929.5631) - @test isapprox(agg.gamma_e, 0.0021822, rtol = 1e-4) - - agg.epsilon_Y_EA, agg.epsilon_E, agg.epsilon_I = BeforeIT.epsilon(prop.C) - - rotw.Y_EA, rotw.gamma_EA, rotw.pi_EA = BeforeIT.growth_inflation_EA(rotw, model) - - @test isapprox(rotw.gamma_EA, 0.0016278, rtol = 1e-5) - @test isapprox(rotw.Y_EA, 2358680.8201, rtol = 1e-5) - @test isapprox(rotw.pi_EA, 0.0033723, rtol = 1e-5) - - # set central bank rate via the Taylor rule - cb.r_bar = BeforeIT.central_bank_rate(cb, model) - @test isapprox(cb.r_bar, 0.0017616, rtol = 1e-4) - - # update rate on loans and morgages - bank.r = BeforeIT.bank_rate(bank, model) - - @test isapprox(bank.r, 0.028476, rtol = 1e-4) - - Q_s_i, I_d_i, DM_d_i, N_d_i, Pi_e_i, DL_d_i, K_e_i, L_e_i, P_i = - BeforeIT.firms_expectations_and_decisions(firms, model) - - firms.Q_s_i .= Q_s_i - firms.I_d_i .= I_d_i - firms.DM_d_i .= DM_d_i - firms.N_d_i .= N_d_i - firms.Pi_e_i .= Pi_e_i - firms.P_i .= P_i - firms.DL_d_i .= DL_d_i - firms.K_e_i .= K_e_i - firms.L_e_i .= L_e_i - - @test isapprox(mean(Q_s_i), 220.0311, rtol = 1e-6) - @test isapprox(mean(I_d_i), 21.6029, rtol = 1e-5) - @test isapprox(mean(DM_d_i), 110.8158, rtol = 1e-5) - @test isapprox(mean(N_d_i), 6.2436, rtol = 1e-5) - @test isapprox(mean(Pi_e_i), 17.5269, rtol = 1e-5) - @test isapprox(mean(DL_d_i), 6.3063, rtol = 1e-5) - @test isapprox(mean(K_e_i), 1265.3191, rtol = 1e-5) - @test isapprox(mean(L_e_i), 360.694, rtol = 1e-5) - @test isapprox(mean(firms.P_i), 1.0031, rtol = 1e-4) - - firms.DL_i = BeforeIT.search_and_matching_credit(firms, model) # actual new loans obtained - - @test isapprox(mean(firms.DL_i[firms.DL_i .> 0]), 95.9791, rtol = 1e-6) - - - N_i, Oh = BeforeIT.search_and_matching_labour(firms, model) - firms.N_i .= N_i - w_act.O_h .= Oh - - - firms.w_i .= BeforeIT.firms_wages(firms) - firms.Y_i .= BeforeIT.firms_production(firms) - - # @test isapprox(mean(V_i), 0.0, rtol = 1e-6) - @test isapprox(mean(firms.w_i), 6.6122, rtol = 1e-5) - @test isapprox(mean(firms.Y_i), 220.0311, rtol = 1e-6) - - # update wages for workers - BeforeIT.update_workers_wages!(w_act, firms.w_i) - - - - @test isapprox(mean(model.w_act.w_h), 7.5221, rtol = 1e-5) - - gov.sb_other, gov.sb_inact = BeforeIT.gov_social_benefits(gov, model) - - @test isapprox(gov.sb_other, 0.59157, rtol = 1e-5) - @test isapprox(gov.sb_inact, 2.2434, rtol = 1e-4) - - Pi_e_k = BeforeIT.bank_expected_profits(bank, model) - bank.Pi_e_k = Pi_e_k - @test isapprox(Pi_e_k, 6510.4793, rtol = 1e-5) - - C_d_h, I_d_h = BeforeIT.households_budget_act(w_act, model) - w_act.C_d_h .= C_d_h - w_act.I_d_h .= I_d_h - C_d_h, I_d_h = BeforeIT.households_budget_inact(w_inact, model) - w_inact.C_d_h .= C_d_h - w_inact.I_d_h .= I_d_h - C_d_h, I_d_h = BeforeIT.households_budget(firms, model) - firms.C_d_h .= C_d_h - firms.I_d_h .= I_d_h - bank.C_d_h, bank.I_d_h = BeforeIT.households_budget(bank, model) - - C_d_h_sum = sum(w_act.C_d_h) + sum(w_inact.C_d_h) + sum(firms.C_d_h) + bank.C_d_h - I_d_h_sum = sum(w_act.I_d_h) + sum(w_inact.I_d_h) + sum(firms.I_d_h) + bank.I_d_h - - @test isapprox(C_d_h_sum, 35538.3159, rtol = 1e-9, atol = 1e-9) - @test isapprox(I_d_h_sum, 2950.5957, rtol = 1e-6, atol = 1e-9) - - C_G, C_d_j = BeforeIT.gov_expenditure(gov, model) - gov.C_G = C_G - gov.C_d_j .= C_d_j - - @test isapprox(mean(gov.C_G), 14783.2494, rtol = 1e-6, atol = 1e-9) - @test isapprox(mean(gov.C_d_j), 95.0572, rtol = 1e-6, atol = 1e-9) - - C_E, Y_I, C_d_l, Y_m, P_m = BeforeIT.rotw_import_export(rotw, model) - rotw.C_E = C_E - rotw.Y_I = Y_I - rotw.C_d_l .= C_d_l - rotw.Y_m .= Y_m - rotw.P_m .= P_m - - @test isapprox(mean(rotw.C_E), 34246.8702, rtol = 1e-6, atol = 1e-9) - @test isapprox(mean(rotw.C_d_l), 110.1048, rtol = 1e-6, atol = 1e-9) - @test isapprox(rotw.Y_I, 33214.9736, rtol = 1e-6, atol = 1e-9) - @test isapprox(mean(rotw.Y_m), 535.7254, rtol = 1e-6, atol = 1e-9) - @test isapprox(mean(rotw.P_m), 1.0031, rtol = 1e-4, atol = 1e-9) - - BeforeIT.search_and_matching!(model, false) - - C_h_sum = sum(w_act.C_h) + sum(w_inact.C_h) + sum(firms.C_h) + bank.C_h - I_h_sum = sum(w_act.I_h) + sum(w_inact.I_h) + sum(firms.I_h) + bank.I_h - K_h_sum = sum(w_act.K_h) + sum(w_inact.K_h) + sum(firms.K_h) + bank.K_h - @test isapprox(C_h_sum, 35136.4805, rtol = 1e-8, atol = 1e-9) - @test isapprox(I_h_sum, 2699.6511, rtol = 1e-7, atol = 1e-9) - @test isapprox(K_h_sum, 408076.5511, rtol = 1e-8, atol = 1e-9) - - - @test isapprox(mean(firms.Q_d_i), 220.092, rtol = 1e-6) - @test isapprox(mean(firms.Q_i), 216.6644, rtol = 1e-6) - @test isapprox(mean(rotw.Q_d_m), 527.2969, rtol = 1e-6) - @test isapprox(mean(rotw.Q_m), 527.2969, rtol = 1e-7) - @test isapprox(mean(firms.I_i), 21.6029, rtol = 1e-5) - @test isapprox(mean(firms.DM_i), 110.7829, rtol = 1e-6) - @test isapprox(mean(firms.P_CF_i), 1.0031, rtol = 1e-4) - @test isapprox(mean(firms.P_bar_i), 1.0031, rtol = 1e-4) - @test isapprox(gov.C_j, 14370.3493, rtol = 1e-8) - @test isapprox(gov.P_j, 1.0031, rtol = 1e-4) - - K_i, M_i, DS_i, S_i = BeforeIT.firms_stocks(firms) - firms.K_i .= K_i - firms.M_i .= M_i - firms.DS_i .= DS_i - firms.S_i .= S_i - - @test isapprox(mean(firms.K_i), 1261.4216, rtol = 1e-6) - @test isapprox(mean(firms.M_i), 130.0548, rtol = 1e-6) - @test isapprox(mean(firms.DS_i), 3.3667, atol = 1e-5) - @test isapprox(mean(firms.S_i), 3.3667, atol = 1e-5) - - # update firms profits - firms.Pi_i .= BeforeIT.firms_profits(firms, model) - @test isapprox(mean(firms.Pi_i), 17.5491, rtol = 1e-2) - - # update bank profits - bank.Pi_k = BeforeIT.bank_profits(bank, model) - @test isapprox(bank.Pi_k, 6486.6381, rtol = 1e-8) - - # update bank equity - bank.E_k = BeforeIT.bank_equity(bank, model) - @test isapprox(bank.E_k, 90742.39, rtol = 1e-9) - - # update actual income of all households - w_act.Y_h .= BeforeIT.households_income_act(w_act, model) - w_inact.Y_h .= BeforeIT.households_income_inact(w_inact, model) - - firms.Y_h .= BeforeIT.households_income(firms, model) - bank.Y_h = BeforeIT.households_income(bank, model) - - # update savings (deposits) of all households - w_act.D_h .= BeforeIT.households_deposits(w_act, model) - w_inact.D_h .= BeforeIT.households_deposits(w_inact, model) - firms.D_h .= BeforeIT.households_deposits(firms, model) - bank.D_h = BeforeIT.households_deposits(bank, model) - - - Y_h_sum = sum(w_act.Y_h) + sum(w_inact.Y_h) + sum(firms.Y_h) + bank.Y_h - D_h_sum = sum(w_act.D_h) + sum(w_inact.D_h) + sum(firms.D_h) + bank.D_h - @test isapprox(Y_h_sum, 45032.3263, rtol = 1e-2) - @test isapprox(D_h_sum, 221816.6764, rtol = 1e-3) - - # compute central bank profits - E_CB = BeforeIT.central_bank_equity(cb, model) - Pi_CB = E_CB - cb.E_CB - cb.E_CB = E_CB - @test isapprox(Pi_CB, 1866.3821, rtol = 1e-7) - - # compute gov revenues (Y_G), surplus/deficit (Pi_G) and debt (L_H) - gov.Y_G = BeforeIT.gov_revenues(model) - @test isapprox(gov.Y_G, 28783.0089, rtol = 1e-2) - - # compute gov deficit/surplus - L_G = BeforeIT.gov_loans(gov, model) - Pi_G = L_G - gov.L_G - gov.L_G = L_G - @test isapprox(Pi_G, 3140.6916, rtol = 1e-2) - @test isapprox(gov.L_G, 235751.5916, rtol = 1e-4) - - - # compute firms deposits, loans and equity - D_i = BeforeIT.firms_deposits(firms, model) - DD_i = D_i .- firms.D_i - firms.D_i .= D_i - - firms.L_i .= BeforeIT.firms_loans(firms, model) - - - firms.E_i .= BeforeIT.firms_equity(firms, model) - - @test isapprox(mean(DD_i), -14.8245, rtol = 1e-2) - @test isapprox(mean(firms.D_i), 71.7925, rtol = 1e-3) - @test isapprox(mean(firms.L_i), 367.0003, rtol = 1e-7) - @test isapprox(mean(firms.E_i), 1103.945, rtol = 1e-2) - - # check central bank equity - @test isapprox(cb.E_CB, 108046.2821, rtol = 1e-2) - - # update net credit/debit position of rest of the world - rotw.D_RoW = BeforeIT.rotw_deposits(rotw, model) - @test isapprox(rotw.D_RoW, -644.0817, rtol = 1e-7) - - # update bank net credit/debit position - bank.D_k = BeforeIT.bank_deposits(bank, model) - @test isapprox(bank.D_k, 128349.3912, rtol = 1e-3) + for multi_threading in [false, true] + model = BeforeIT.init_model(parameters, initial_conditions, T) + + gov = model.gov # government + cb = model.cb # central bank + rotw = model.rotw # rest of the world + firms = model.firms # firms + bank = model.bank # bank + w_act = model.w_act # active workers + w_inact = model.w_inact # inactive workers + agg = model.agg # aggregates + prop = model.prop # model properties + + prop = model.prop + agg.Y_e, agg.gamma_e, agg.pi_e = BeforeIT.growth_inflation_expectations(model) + + @test isapprox(agg.Y_e, 134929.5631) + @test isapprox(agg.gamma_e, 0.0021822, rtol = 1e-4) + + agg.epsilon_Y_EA, agg.epsilon_E, agg.epsilon_I = BeforeIT.epsilon(prop.C) + + rotw.Y_EA, rotw.gamma_EA, rotw.pi_EA = BeforeIT.growth_inflation_EA(rotw, model) + + @test isapprox(rotw.gamma_EA, 0.0016278, rtol = 1e-5) + @test isapprox(rotw.Y_EA, 2358680.8201, rtol = 1e-5) + @test isapprox(rotw.pi_EA, 0.0033723, rtol = 1e-5) + + # set central bank rate via the Taylor rule + cb.r_bar = BeforeIT.central_bank_rate(cb, model) + @test isapprox(cb.r_bar, 0.0017616, rtol = 1e-4) + + # update rate on loans and morgages + bank.r = BeforeIT.bank_rate(bank, model) + @test isapprox(bank.r, 0.028476, rtol = 1e-4) + + Q_s_i, I_d_i, DM_d_i, N_d_i, Pi_e_i, DL_d_i, K_e_i, L_e_i, P_i = + BeforeIT.firms_expectations_and_decisions(firms, model) + + firms.Q_s_i .= Q_s_i + firms.I_d_i .= I_d_i + firms.DM_d_i .= DM_d_i + firms.N_d_i .= N_d_i + firms.Pi_e_i .= Pi_e_i + firms.P_i .= P_i + firms.DL_d_i .= DL_d_i + firms.K_e_i .= K_e_i + firms.L_e_i .= L_e_i + + @test isapprox(mean(Q_s_i), 220.0311, rtol = 1e-6) + @test isapprox(mean(I_d_i), 21.6029, rtol = 1e-5) + @test isapprox(mean(DM_d_i), 110.8158, rtol = 1e-5) + @test isapprox(mean(N_d_i), 6.2436, rtol = 1e-5) + @test isapprox(mean(Pi_e_i), 17.5269, rtol = 1e-5) + @test isapprox(mean(DL_d_i), 6.3063, rtol = 1e-5) + @test isapprox(mean(K_e_i), 1265.3191, rtol = 1e-5) + @test isapprox(mean(L_e_i), 360.694, rtol = 1e-5) + @test isapprox(mean(firms.P_i), 1.0031, rtol = 1e-4) + + firms.DL_i = BeforeIT.search_and_matching_credit(firms, model) # actual new loans obtained + @test isapprox(mean(firms.DL_i[firms.DL_i .> 0]), 95.9791, rtol = 1e-6) + + N_i, Oh = BeforeIT.search_and_matching_labour(firms, model) + firms.N_i .= N_i + w_act.O_h .= Oh + + firms.w_i .= BeforeIT.firms_wages(firms) + firms.Y_i .= BeforeIT.firms_production(firms) + + # @test isapprox(mean(V_i), 0.0, rtol = 1e-6) + @test isapprox(mean(firms.w_i), 6.6122, rtol = 1e-5) + @test isapprox(mean(firms.Y_i), 220.0311, rtol = 1e-6) + + # update wages for workers + BeforeIT.update_workers_wages!(w_act, firms.w_i) + + @test isapprox(mean(model.w_act.w_h), 7.5221, rtol = 1e-5) + + gov.sb_other, gov.sb_inact = BeforeIT.gov_social_benefits(gov, model) + + @test isapprox(gov.sb_other, 0.59157, rtol = 1e-5) + @test isapprox(gov.sb_inact, 2.2434, rtol = 1e-4) + + Pi_e_k = BeforeIT.bank_expected_profits(bank, model) + bank.Pi_e_k = Pi_e_k + @test isapprox(Pi_e_k, 6510.4793, rtol = 1e-5) + + C_d_h, I_d_h = BeforeIT.households_budget_act(w_act, model) + w_act.C_d_h .= C_d_h + w_act.I_d_h .= I_d_h + C_d_h, I_d_h = BeforeIT.households_budget_inact(w_inact, model) + w_inact.C_d_h .= C_d_h + w_inact.I_d_h .= I_d_h + C_d_h, I_d_h = BeforeIT.households_budget(firms, model) + firms.C_d_h .= C_d_h + firms.I_d_h .= I_d_h + bank.C_d_h, bank.I_d_h = BeforeIT.households_budget(bank, model) + + C_d_h_sum = sum(w_act.C_d_h) + sum(w_inact.C_d_h) + sum(firms.C_d_h) + bank.C_d_h + I_d_h_sum = sum(w_act.I_d_h) + sum(w_inact.I_d_h) + sum(firms.I_d_h) + bank.I_d_h + + @test isapprox(C_d_h_sum, 35538.3159, rtol = 1e-9, atol = 1e-9) + @test isapprox(I_d_h_sum, 2950.5957, rtol = 1e-6, atol = 1e-9) + + C_G, C_d_j = BeforeIT.gov_expenditure(gov, model) + gov.C_G = C_G + gov.C_d_j .= C_d_j + + @test isapprox(mean(gov.C_G), 14783.2494, rtol = 1e-6, atol = 1e-9) + @test isapprox(mean(gov.C_d_j), 95.0572, rtol = 1e-6, atol = 1e-9) + + C_E, Y_I, C_d_l, Y_m, P_m = BeforeIT.rotw_import_export(rotw, model) + rotw.C_E = C_E + rotw.Y_I = Y_I + rotw.C_d_l .= C_d_l + rotw.Y_m .= Y_m + rotw.P_m .= P_m + + @test isapprox(mean(rotw.C_E), 34246.8702, rtol = 1e-6, atol = 1e-9) + @test isapprox(mean(rotw.C_d_l), 110.1048, rtol = 1e-6, atol = 1e-9) + @test isapprox(rotw.Y_I, 33214.9736, rtol = 1e-6, atol = 1e-9) + @test isapprox(mean(rotw.Y_m), 535.7254, rtol = 1e-6, atol = 1e-9) + @test isapprox(mean(rotw.P_m), 1.0031, rtol = 1e-4, atol = 1e-9) + + BeforeIT.search_and_matching!(model, multi_threading) + + C_h_sum = sum(w_act.C_h) + sum(w_inact.C_h) + sum(firms.C_h) + bank.C_h + I_h_sum = sum(w_act.I_h) + sum(w_inact.I_h) + sum(firms.I_h) + bank.I_h + K_h_sum = sum(w_act.K_h) + sum(w_inact.K_h) + sum(firms.K_h) + bank.K_h + @test isapprox(C_h_sum, 35136.4805, rtol = 1e-8, atol = 1e-9) + @test isapprox(I_h_sum, 2699.6511, rtol = 1e-7, atol = 1e-9) + @test isapprox(K_h_sum, 408076.5511, rtol = 1e-8, atol = 1e-9) + + @test isapprox(mean(firms.Q_d_i), 220.092, rtol = 1e-6) + @test isapprox(mean(firms.Q_i), 216.6644, rtol = 1e-6) + @test isapprox(mean(rotw.Q_d_m), 527.2969, rtol = 1e-6) + @test isapprox(mean(rotw.Q_m), 527.2969, rtol = 1e-7) + @test isapprox(mean(firms.I_i), 21.6029, rtol = 1e-5) + @test isapprox(mean(firms.DM_i), 110.7829, rtol = 1e-6) + @test isapprox(mean(firms.P_CF_i), 1.0031, rtol = 1e-4) + @test isapprox(mean(firms.P_bar_i), 1.0031, rtol = 1e-4) + @test isapprox(gov.C_j, 14370.3493, rtol = 1e-8) + @test isapprox(gov.P_j, 1.0031, rtol = 1e-4) + + K_i, M_i, DS_i, S_i = BeforeIT.firms_stocks(firms) + firms.K_i .= K_i + firms.M_i .= M_i + firms.DS_i .= DS_i + firms.S_i .= S_i + + @test isapprox(mean(firms.K_i), 1261.4216, rtol = 1e-6) + @test isapprox(mean(firms.M_i), 130.0548, rtol = 1e-6) + @test isapprox(mean(firms.DS_i), 3.3667, atol = 1e-5) + @test isapprox(mean(firms.S_i), 3.3667, atol = 1e-5) + + # update firms profits + firms.Pi_i .= BeforeIT.firms_profits(firms, model) + @test isapprox(mean(firms.Pi_i), 17.5491, rtol = 1e-2) + + # update bank profits + bank.Pi_k = BeforeIT.bank_profits(bank, model) + @test isapprox(bank.Pi_k, 6486.6381, rtol = 1e-8) + + # update bank equity + bank.E_k = BeforeIT.bank_equity(bank, model) + @test isapprox(bank.E_k, 90742.39, rtol = 1e-9) + + # update actual income of all households + w_act.Y_h .= BeforeIT.households_income_act(w_act, model) + w_inact.Y_h .= BeforeIT.households_income_inact(w_inact, model) + + firms.Y_h .= BeforeIT.households_income(firms, model) + bank.Y_h = BeforeIT.households_income(bank, model) + + # update savings (deposits) of all households + w_act.D_h .= BeforeIT.households_deposits(w_act, model) + w_inact.D_h .= BeforeIT.households_deposits(w_inact, model) + firms.D_h .= BeforeIT.households_deposits(firms, model) + bank.D_h = BeforeIT.households_deposits(bank, model) + + Y_h_sum = sum(w_act.Y_h) + sum(w_inact.Y_h) + sum(firms.Y_h) + bank.Y_h + D_h_sum = sum(w_act.D_h) + sum(w_inact.D_h) + sum(firms.D_h) + bank.D_h + @test isapprox(Y_h_sum, 45032.3263, rtol = 1e-2) + @test isapprox(D_h_sum, 221816.6764, rtol = 1e-3) + + # compute central bank profits + E_CB = BeforeIT.central_bank_equity(cb, model) + Pi_CB = E_CB - cb.E_CB + cb.E_CB = E_CB + @test isapprox(Pi_CB, 1866.3821, rtol = 1e-7) + + # compute gov revenues (Y_G), surplus/deficit (Pi_G) and debt (L_H) + gov.Y_G = BeforeIT.gov_revenues(model) + @test isapprox(gov.Y_G, 28783.0089, rtol = 1e-2) + + # compute gov deficit/surplus + L_G = BeforeIT.gov_loans(gov, model) + Pi_G = L_G - gov.L_G + gov.L_G = L_G + @test isapprox(Pi_G, 3140.6916, rtol = 1e-2) + @test isapprox(gov.L_G, 235751.5916, rtol = 1e-4) + + # compute firms deposits, loans and equity + D_i = BeforeIT.firms_deposits(firms, model) + DD_i = D_i .- firms.D_i + firms.D_i .= D_i + + firms.L_i .= BeforeIT.firms_loans(firms, model) + firms.E_i .= BeforeIT.firms_equity(firms, model) + + @test isapprox(mean(DD_i), -14.8245, rtol = 1e-2) + @test isapprox(mean(firms.D_i), 71.7925, rtol = 1e-3) + @test isapprox(mean(firms.L_i), 367.0003, rtol = 1e-7) + @test isapprox(mean(firms.E_i), 1103.945, rtol = 1e-2) + + # check central bank equity + @test isapprox(cb.E_CB, 108046.2821, rtol = 1e-2) + + # update net credit/debit position of rest of the world + rotw.D_RoW = BeforeIT.rotw_deposits(rotw, model) + @test isapprox(rotw.D_RoW, -644.0817, rtol = 1e-7) + + # update bank net credit/debit position + bank.D_k = BeforeIT.bank_deposits(bank, model) + @test isapprox(bank.D_k, 128349.3912, rtol = 1e-3) + end end diff --git a/test/deterministic/one_run_deterministic.jl b/test/deterministic/one_run_deterministic.jl index 47594a2..373e73f 100644 --- a/test/deterministic/one_run_deterministic.jl +++ b/test/deterministic/one_run_deterministic.jl @@ -1,34 +1,26 @@ @testset "run deterministic" begin T = 3 - dir = @__DIR__ - parameters = BeforeIT.AUSTRIA2010Q1.parameters initial_conditions = BeforeIT.AUSTRIA2010Q1.initial_conditions - parameters1 = deepcopy(parameters) - parameters2 = deepcopy(parameters) - initial_conditions1 = deepcopy(initial_conditions) - initial_conditions2 = deepcopy(initial_conditions) - - model = BeforeIT.init_model(parameters1, initial_conditions1, T;) - data = BeforeIT.init_data(model) - for t in 1:(T - 1) - BeforeIT.run_one_epoch!(model; multi_threading = false) - BeforeIT.update_data!(data, model) - end - - - model2 = BeforeIT.init_model(parameters2, initial_conditions2, T;) - data2 = BeforeIT.init_data(model2) - - for t in 1:(T - 1) - BeforeIT.run_one_epoch!(model2; multi_threading = false) - BeforeIT.update_data!(data2, model2) + function run_deterministic(parameters, initial_conditions, T, m) + model = BeforeIT.init_model(parameters, initial_conditions, T;) + data = BeforeIT.init_data(model) + for t in 1:(T - 1) + BeforeIT.run_one_epoch!(model; multi_threading = m) + BeforeIT.update_data!(data, model) + end + return model, data end + model, data = run_deterministic(parameters, initial_conditions, T, false) + model2, data2 = run_deterministic(parameters, initial_conditions, T, false) + model3, data3 = run_deterministic(parameters, initial_conditions, T, true) + # loop over the data fields and compare them for field in fieldnames(typeof(data)) - @test isapprox(getproperty(data, field), getproperty(data2, field), rtol = 0.001) + @test isapprox(getproperty(data, field), getproperty(data2, field), rtol = 0.00001) + @test isapprox(getproperty(data2, field), getproperty(data3, field), rtol = 0.00001) end end diff --git a/test/markets/search_and_matching.jl b/test/markets/search_and_matching.jl index e0f1240..adbcefb 100644 --- a/test/markets/search_and_matching.jl +++ b/test/markets/search_and_matching.jl @@ -2,100 +2,107 @@ using BeforeIT, Test, MAT, StatsBase using Random @testset "search and matching" begin + T = 1 Random.seed!(1) parameters = BeforeIT.AUSTRIA2010Q1.parameters initial_conditions = BeforeIT.AUSTRIA2010Q1.initial_conditions - - T = 1 - model = BeforeIT.init_model(parameters, initial_conditions, T;) - - gov = model.gov # government - cb = model.cb # central bank - rotw = model.rotw # rest of the world - firms = model.firms # firms - bank = model.bank # bank - w_act = model.w_act # active workers - w_inact = model.w_inact # inactive workers - agg = model.agg # aggregates - prop = model.prop # model properties - - BeforeIT.finance_insolvent_firms!(firms, bank, model) - - agg.Y_e, agg.gamma_e, agg.pi_e = BeforeIT.growth_inflation_expectations(model) - - agg.epsilon_Y_EA, agg.epsilon_E, agg.epsilon_I = BeforeIT.epsilon(prop.C) - - rotw.Y_EA, rotw.gamma_EA, rotw.pi_EA = BeforeIT.growth_inflation_EA(rotw, model) - - cb.r_bar = BeforeIT.central_bank_rate(cb, model) - - bank.r = BeforeIT.bank_rate(bank, model) - - Q_s_i, I_d_i, DM_d_i, N_d_i, Pi_e_i, DL_d_i, K_e_i, L_e_i, P_i = - BeforeIT.firms_expectations_and_decisions(firms, model) - - firms.Q_s_i .= Q_s_i - firms.I_d_i .= I_d_i - firms.DM_d_i .= DM_d_i - firms.N_d_i .= N_d_i - firms.Pi_e_i .= Pi_e_i - firms.P_i .= P_i - firms.DL_d_i .= DL_d_i - firms.K_e_i .= K_e_i - firms.L_e_i .= L_e_i - - firms.DL_i .= BeforeIT.search_and_matching_credit(firms, model) - - N_i, Oh = BeforeIT.search_and_matching_labour(firms, model) - firms.N_i .= N_i - w_act.O_h .= Oh - - firms.w_i .= BeforeIT.firms_wages(firms) - firms.Y_i .= BeforeIT.firms_production(firms) - - BeforeIT.update_workers_wages!(w_act, firms.w_i) - - gov.sb_other, gov.sb_inact = BeforeIT.gov_social_benefits(gov, model) - - bank.Pi_e_k = BeforeIT.bank_expected_profits(bank, model) - - C_d_h, I_d_h = BeforeIT.households_budget_act(w_act, model) - w_act.C_d_h .= C_d_h - w_act.I_d_h .= I_d_h - C_d_h, I_d_h = BeforeIT.households_budget_inact(w_inact, model) - w_inact.C_d_h .= C_d_h - w_inact.I_d_h .= I_d_h - C_d_h, I_d_h = BeforeIT.households_budget(firms, model) - firms.C_d_h .= C_d_h - firms.I_d_h .= I_d_h - bank.C_d_h, bank.I_d_h = BeforeIT.households_budget(bank, model) - - C_G, C_d_j = BeforeIT.gov_expenditure(gov, model) - gov.C_G = C_G - gov.C_d_j .= C_d_j - - C_E, Y_I, C_d_l, Y_m, P_m = BeforeIT.rotw_import_export(rotw, model) - rotw.C_E = C_E - rotw.Y_I = Y_I - rotw.C_d_l .= C_d_l - rotw.Y_m .= Y_m - rotw.P_m .= P_m - - BeforeIT.search_and_matching!(model, false) + + function run_search_and_matching(parameters, initial_conditions, T, m) + model = BeforeIT.init_model(parameters, initial_conditions, T;) + + gov = model.gov # government + cb = model.cb # central bank + rotw = model.rotw # rest of the world + firms = model.firms # firms + bank = model.bank # bank + w_act = model.w_act # active workers + w_inact = model.w_inact # inactive workers + agg = model.agg # aggregates + prop = model.prop # model properties + + BeforeIT.finance_insolvent_firms!(firms, bank, model) + + agg.Y_e, agg.gamma_e, agg.pi_e = BeforeIT.growth_inflation_expectations(model) + + agg.epsilon_Y_EA, agg.epsilon_E, agg.epsilon_I = BeforeIT.epsilon(prop.C) + + rotw.Y_EA, rotw.gamma_EA, rotw.pi_EA = BeforeIT.growth_inflation_EA(rotw, model) + + cb.r_bar = BeforeIT.central_bank_rate(cb, model) + + bank.r = BeforeIT.bank_rate(bank, model) + + Q_s_i, I_d_i, DM_d_i, N_d_i, Pi_e_i, DL_d_i, K_e_i, L_e_i, P_i = + BeforeIT.firms_expectations_and_decisions(firms, model) + + firms.Q_s_i .= Q_s_i + firms.I_d_i .= I_d_i + firms.DM_d_i .= DM_d_i + firms.N_d_i .= N_d_i + firms.Pi_e_i .= Pi_e_i + firms.P_i .= P_i + firms.DL_d_i .= DL_d_i + firms.K_e_i .= K_e_i + firms.L_e_i .= L_e_i + + firms.DL_i .= BeforeIT.search_and_matching_credit(firms, model) + + N_i, Oh = BeforeIT.search_and_matching_labour(firms, model) + firms.N_i .= N_i + w_act.O_h .= Oh + + firms.w_i .= BeforeIT.firms_wages(firms) + firms.Y_i .= BeforeIT.firms_production(firms) + + BeforeIT.update_workers_wages!(w_act, firms.w_i) + + gov.sb_other, gov.sb_inact = BeforeIT.gov_social_benefits(gov, model) + + bank.Pi_e_k = BeforeIT.bank_expected_profits(bank, model) + + C_d_h, I_d_h = BeforeIT.households_budget_act(w_act, model) + w_act.C_d_h .= C_d_h + w_act.I_d_h .= I_d_h + C_d_h, I_d_h = BeforeIT.households_budget_inact(w_inact, model) + w_inact.C_d_h .= C_d_h + w_inact.I_d_h .= I_d_h + C_d_h, I_d_h = BeforeIT.households_budget(firms, model) + firms.C_d_h .= C_d_h + firms.I_d_h .= I_d_h + bank.C_d_h, bank.I_d_h = BeforeIT.households_budget(bank, model) + + C_G, C_d_j = BeforeIT.gov_expenditure(gov, model) + gov.C_G = C_G + gov.C_d_j .= C_d_j + + C_E, Y_I, C_d_l, Y_m, P_m = BeforeIT.rotw_import_export(rotw, model) + rotw.C_E = C_E + rotw.Y_I = Y_I + rotw.C_d_l .= C_d_l + rotw.Y_m .= Y_m + rotw.P_m .= P_m + + BeforeIT.search_and_matching!(model, m) + return bank, w_act, w_inact, firms, gov, rotw + end # NOTE: as a test we use the expected values and standard deviations of the - # original implementation, with tolerance = 3*(standard deviation) - @test isapprox(mean([bank.I_h, w_act.I_h..., w_inact.I_h..., firms.I_h...]), - 0.32975, atol = 3*0.0025351) - @test isapprox(mean([bank.C_h, w_act.C_h..., w_inact.C_h..., firms.C_h...]), - 3.973, atol = 3*0.029366) - @test isapprox(mean(firms.I_i), 20.5075, atol = 3*0.12763) - @test isapprox(mean(firms.DM_i), 109.3163, atol = 3*0.68033) - @test isapprox(mean(firms.P_bar_i), 1.0031, atol = 3*0.0044726) - @test isapprox(mean(firms.P_CF_i), 1.0031, atol = 3*0.0044726) - @test isapprox(gov.C_j, 14752.2413, atol = 3*126.7441) - @test isapprox(rotw.C_l, 34188.1258, atol = 3*666.275) - @test isapprox(mean(firms.Q_d_i), 216.2474, atol = 3*1.2275) - @test isapprox(mean(rotw.Q_d_m), 535.7522, atol = 3*9.6082) + # original implementation, with tolerance = 3*(standard deviation) for + # both single-threaded and multi-threaded execution + for m in [true, false] + bank, w_act, w_inact, firms, gov, rotw = run_search_and_matching(parameters, initial_conditions, T, m) + @test isapprox(mean([bank.I_h, w_act.I_h..., w_inact.I_h..., firms.I_h...]), + 0.32975, atol = 3*0.0025351) + @test isapprox(mean([bank.C_h, w_act.C_h..., w_inact.C_h..., firms.C_h...]), + 3.973, atol = 3*0.029366) + @test isapprox(mean(firms.I_i), 20.5075, atol = 3*0.12763) + @test isapprox(mean(firms.DM_i), 109.3163, atol = 3*0.68033) + @test isapprox(mean(firms.P_bar_i), 1.0031, atol = 3*0.0044726) + @test isapprox(mean(firms.P_CF_i), 1.0031, atol = 3*0.0044726) + @test isapprox(gov.C_j, 14752.2413, atol = 3*126.7441) + @test isapprox(rotw.C_l, 34188.1258, atol = 3*666.275) + @test isapprox(mean(firms.Q_d_i), 216.2474, atol = 3*1.2275) + @test isapprox(mean(rotw.Q_d_m), 535.7522, atol = 3*9.6082) + end end