diff --git a/matlab/default_option_values.m b/matlab/default_option_values.m index 31ae49b6181c42fd221cb9d35217928ab8385a04..d35985c52d4212159054c61c6308e133452272de 100644 --- a/matlab/default_option_values.m +++ b/matlab/default_option_values.m @@ -326,6 +326,7 @@ options_.no_homotopy = false; % Perfect foresight with expectation errors options_.pfwee.terminal_steady_state_as_guess_value = false; +options_.pfwee.constant_simulation_length = false; % Solution options_.order = 2; diff --git a/matlab/perfect-foresight-models/perfect_foresight_with_expectation_errors_solver.m b/matlab/perfect-foresight-models/perfect_foresight_with_expectation_errors_solver.m index a3eca07ad29d6b822df22128330bca847dda6636..acb98c154a103cb90bac415e6bccfe12821804df 100644 --- a/matlab/perfect-foresight-models/perfect_foresight_with_expectation_errors_solver.m +++ b/matlab/perfect-foresight-models/perfect_foresight_with_expectation_errors_solver.m @@ -1,6 +1,6 @@ function perfect_foresight_with_expectation_errors_solver -% Copyright (C) 2021 Dynare Team +% Copyright © 2021-2022 Dynare Team % % This file is part of Dynare. % @@ -23,8 +23,8 @@ global M_ oo_ options_ initial_steady_state = oo_.steady_state; initial_exo_steady_state = oo_.exo_steady_state; -% Same for periods (it will be modified before calling perfect_foresight_solver) -periods = options_.periods +% Same for periods (it will be modified before calling perfect_foresight_solver if constants_simulation_length option is false) +periods = options_.periods; % Retrieve initial paths built by pfwee_setup % (the versions in oo_ will be truncated before calling perfect_foresight_solver) @@ -33,25 +33,40 @@ exo_simul = oo_.exo_simul; % Start main loop around informational periods info_period = 1; +increment = 0; while info_period <= periods % Compute terminal steady state as anticipated oo_.exo_steady_state = oo_.pfwee.terminal_info(:, info_period); steady_state_prev = oo_.steady_state; [oo_.steady_state,~,info] = evaluate_steady_state(steady_state_prev, M_, options_, oo_, true); - options_.periods = periods - info_period + 1; + if options_.pfwee.constant_simulation_length && increment > 0 + endo_simul = [ endo_simul NaN(M_.endo_nbr, increment)]; + exo_simul = [ exo_simul; NaN(increment, M_.exo_nbr)]; + end + oo_.endo_simul = endo_simul(:, info_period:end); % Take initial conditions + guess values from previous simulation + if options_.pfwee.constant_simulation_length + sim_length = periods; + else + sim_length = periods - info_period + 1; + end if options_.pfwee.terminal_steady_state_as_guess_value % Overwrite guess value with terminal steady state - oo_.endo_simul(:, M_.maximum_lag+(1:periods-info_period+1)) = repmat(oo_.steady_state, 1, periods-info_period+1); + oo_.endo_simul(:, M_.maximum_lag+(1:sim_length)) = repmat(oo_.steady_state, 1, sim_length); elseif info_period == 1 % Use initial steady state as guess value for first simulation if not using terminal steady state oo_.endo_simul(:, M_.maximum_lag+(1:periods)) = repmat(initial_steady_state, 1, periods); + elseif options_.pfwee.constant_simulation_length && increment > M_.maximum_lead + % Use initial steady state as guess value for simulation periods that don’t yet have an initial guess (i.e. are NaNs) + oo_.endo_simul(:, M_.maximum_lag+periods-(0:increment-M_.maximum_lead-1)) = repmat(initial_steady_state, 1, increment-M_.maximum_lead); end oo_.endo_simul(:, end-M_.maximum_lead+1:end) = repmat(oo_.steady_state, 1, M_.maximum_lead); oo_.exo_simul = exo_simul(info_period:end, :); oo_.exo_simul(M_.maximum_lag+(1:periods-info_period+1), :) = oo_.pfwee.shocks_info(:, info_period:end, info_period)'; - oo_.exo_simul(end-M_.maximum_lead+1:end, :) = repmat(oo_.exo_steady_state, M_.maximum_lead, 1); + oo_.exo_simul(M_.maximum_lag+periods-info_period+2:end) = repmat(oo_.exo_steady_state, sim_length+M_.maximum_lead-(periods-info_period+1), 1); + + options_.periods = sim_length; perfect_foresight_solver; diff --git a/preprocessor b/preprocessor index a431682697504bdc79ec8d574fda615917f3591c..acaabd59dad311e44f6d8c3913d8eb239cbf31ec 160000 --- a/preprocessor +++ b/preprocessor @@ -1 +1 @@ -Subproject commit a431682697504bdc79ec8d574fda615917f3591c +Subproject commit acaabd59dad311e44f6d8c3913d8eb239cbf31ec diff --git a/tests/Makefile.am b/tests/Makefile.am index fd5c2a426260e22403165d71fd60bfb056cf162b..726fefc02a4f24e4458e79ac6262cd049c1cd5b1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -389,6 +389,7 @@ MODFILES = \ deterministic_simulations/rbc_det_stack_solve_algo_7_exo_lag.mod \ deterministic_simulations/rbc_det_stack_solve_algo_7_exo_lead.mod \ deterministic_simulations/pfwee.mod \ + deterministic_simulations/pfwee_constant_sim_length.mod \ lmmcp/rbc.mod \ lmmcp/sw_lmmcp.mod \ lmmcp/sw_newton.mod \ diff --git a/tests/deterministic_simulations/pfwee_constant_sim_length.mod b/tests/deterministic_simulations/pfwee_constant_sim_length.mod new file mode 100644 index 0000000000000000000000000000000000000000..250b4e6733f7f86803f4762635f7b8aef9524605 --- /dev/null +++ b/tests/deterministic_simulations/pfwee_constant_sim_length.mod @@ -0,0 +1,103 @@ +// Tests perfect_foresight_with_expectation_errors_{setup,solver} with constant_simulation_length option + +var c k; +varexo x; + +parameters alph gam delt bet aa; +alph=0.5; +gam=0.5; +delt=0.02; +bet=0.05; +aa=0.5; + + +model; +c + k - aa*x*k(-1)^alph - (1-delt)*k(-1); +c^(-gam) - (1+bet)^(-1)*(aa*alph*x(+1)*k^(alph-1) + 1 - delt)*c(+1)^(-gam); +end; + +initval; +x = 1; +k = ((delt+bet)/(1.0*aa*alph))^(1/(alph-1)); +c = aa*k^alph-delt*k; +end; + +steady; + +check; + +// First simulation with default options +perfect_foresight_with_expectation_errors_setup(periods = 7, datafile = 'pfwee.csv'); +perfect_foresight_with_expectation_errors_solver(constant_simulation_length); +pfwee1 = oo_.endo_simul; + +// Second simulation with alternative guess values +perfect_foresight_with_expectation_errors_setup(periods = 7, datafile = 'pfwee.csv'); +perfect_foresight_with_expectation_errors_solver(terminal_steady_state_as_guess_value, constant_simulation_length); +pfwee2 = oo_.endo_simul; + +// Now compute the solution by hand to verify the results + +perfect_foresight_setup; + +initial_steady_state = oo_.steady_state; + +// Information arriving in period 1 (temp shock now) +oo_.exo_simul(2,1) = 1.2; +perfect_foresight_solver; + +// Information arriving in period 2 (temp shock now + permanent shock in future) +oo_.exo_simul(3,1) = 1.3; +oo_.exo_steady_state = 1.1; +oo_.exo_simul(9:10, 1) = repmat(oo_.exo_steady_state', 2, 1); +oo_.steady_state = evaluate_steady_state(oo_.steady_state, M_, options_, oo_, true); +oo_.endo_simul(:, 10) = oo_.steady_state; +saved_endo = oo_.endo_simul(:, 1); +saved_exo = oo_.exo_simul(1, :); +oo_.endo_simul = oo_.endo_simul(:, 2:end); +oo_.exo_simul = oo_.exo_simul(2:end, :); +perfect_foresight_solver; +oo_.endo_simul = [ saved_endo oo_.endo_simul ]; +oo_.exo_simul = [ saved_exo; oo_.exo_simul ]; + +// Information arriving in period 3 (temp shock now + permanent shock in future) +oo_.exo_simul(4,1) = 1.4; +oo_.exo_steady_state = 1.2; +oo_.exo_simul(9:11, 1) = repmat(oo_.exo_steady_state', 3, 1); +oo_.steady_state = evaluate_steady_state(oo_.steady_state, M_, options_, oo_, true); +oo_.endo_simul(:, 11) = oo_.steady_state; +saved_endo = oo_.endo_simul(:, 1:2); +saved_exo = oo_.exo_simul(1:2, :); +oo_.endo_simul = oo_.endo_simul(:, 3:end); +oo_.exo_simul = oo_.exo_simul(3:end, :); +perfect_foresight_solver; +oo_.endo_simul = [ saved_endo oo_.endo_simul ]; +oo_.exo_simul = [ saved_exo; oo_.exo_simul ]; + +// Information arriving in period 6 (permanent shock arriving now) +oo_.exo_simul(7,1) = 1.1; +oo_.exo_simul(8,1) = 1.1; +oo_.exo_steady_state = 1.1; +oo_.exo_simul(9:14, 1) = repmat(oo_.exo_steady_state', 6, 1); +oo_.steady_state = evaluate_steady_state(oo_.steady_state, M_, options_, oo_, true); +oo_.endo_simul(:, 12:13) = repmat(initial_steady_state, 1, 2); +oo_.endo_simul(:, 14) = oo_.steady_state; +saved_endo = oo_.endo_simul(:, 1:5); +saved_exo = oo_.exo_simul(1:5, :); +oo_.endo_simul = oo_.endo_simul(:, 6:end); +oo_.exo_simul = oo_.exo_simul(6:end, :); +perfect_foresight_solver; +oo_.endo_simul = [ saved_endo oo_.endo_simul ]; +oo_.exo_simul = [ saved_exo; oo_.exo_simul ]; + +% We should have strict equality with first pfwee simulation, because algorithm +% and guess values are exactly the same. +if any(any(pfwee1-oo_.endo_simul ~= 0)) + error('Error in perfect_foresight_with_expectation_errors') +end + +% For the 2nd simulation, since the guess values are different, there are some +% numerical differences +if max(max(abs(pfwee2-oo_.endo_simul))) > 40*options_.dynatol.f + error('Error in perfect_foresight_with_expectation_errors + terminal_steady_state_as_guess_value') +end