Added a routine for writing the problem to be solved to compute the BGP of a model.

- Only works with backward models.
 - Probably doesn't work if the model includes auxiliary variables.
 - Assumes that the trends are multiplicative.
time-shift
Stéphane Adjemia (Scylla) 2019-02-04 10:00:16 +01:00
parent f7b332efa6
commit b7c60ddf59
Signed by untrusted user who does not match committer: stepan
GPG Key ID: A6D44CB9C64CE77B
3 changed files with 250 additions and 1 deletions

168
matlab/+bgp/write.m Normal file
View File

@ -0,0 +1,168 @@
function write(DynareModel)
% Writes the nonlinear problem to be solved for computing the growth
% rates and levels along the Balanced Growth Path. Note that for
% the variables growing along the BGP, the identified levels are
% meaningless, only the relative levels of the growing variables
% sharing the same trend(s) are relevant.
%
% INPUTS
% - DynareModel [struct] Dynare generated stucture describing the model (M_).
%
% OUTPUTS
% None
%
% REMARKS
% - The trends are assumed to be multiplicative.
% Copyright (C) 2019 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
i0 = transpose(DynareModel.lead_lag_incidence(1,:)); % Indices of the lagged variables.
i1 = transpose(DynareModel.lead_lag_incidence(2,:)); % Indices of the current variables.
n0 = length(find(i0)); % Number of lagged variables.
n1 = length(find(i1)); % Number of current variables.
% Create function in mod namespace.
fid = fopen(sprintf('+%s/bgpfun.m', DynareModel.fname), 'w');
% Write header.
fprintf(fid, 'function [F, JAC] = bgpfun(z)\n\n');
fprintf(fid, '%% This file has been generated by dynare (%s).\n\n', datestr(now));
% The function admits a unique vector as input argument. The first
% half of the elements are for the levels of the endogenous
% variables, the second half for the growth factors.
fprintf(fid, 'y = z(1:%u);\n\n', DynareModel.endo_nbr);
fprintf(fid, 'g = z(%u:%u);\n', DynareModel.endo_nbr+1, 2*DynareModel.endo_nbr);
% Define the point where the dynamic model is to be evaluated.
fprintf(fid, 'Y = zeros(%u, 1);\n', 2*(n0+n1));
for i=1:length(i0) % period t equations, lagged variables.
if i0(i)
fprintf(fid, 'Y(%u) = y(%u);\n', i0(i), i);
end
end
for i=1:length(i1) % period t equations, current variables.
if i1(i)
fprintf(fid, 'Y(%u) = y(%u)*g(%u);\n', i1(i), i, i);
end
end
for i=1:length(i0) % period t+1 equaions lagged variables.
if i0(i)
fprintf(fid, 'Y(%u) = y(%u)*g(%u);\n', n0+n1+i0(i), i, i);
end
end
for i=1:length(i1) % period t+1 equations current variables.
if i1(i)
fprintf(fid, 'Y(%u) = y(%u)*g(%u)*g(%u);\n', n0+n1+i1(i), i, i, i);
end
end
fprintf(fid, '\n');
% Define the vector of parameters.
fprintf(fid, 'p = zeros(%u, 1);\n', DynareModel.param_nbr);
for i = 1:DynareModel.param_nbr
fprintf(fid, 'p(%u) = %16.12f;\n', i, DynareModel.params(i));
end
fprintf(fid, '\n');
% Initialize the vector holding the residuals over the two periods.
fprintf(fid, 'F = NaN(%u, 1);\n', 2*DynareModel.endo_nbr);
% Set vector of exogenous variables to 0.
fprintf(fid, 'x = zeros(1, %u);\n\n', DynareModel.exo_nbr);
% Evaluate the residuals and jacobian of the dynamic model in periods t and t+1.
fprintf(fid, 'if nargout>1\n');
fprintf(fid, ' J = zeros(%u, %u);\n', 2*DynareModel.endo_nbr, n0+n1+DynareModel.endo_nbr);
fprintf(fid, ' [F(1:%u), tmp] = %s.dynamic(Y(1:%u), x, p, y, 1);\n', DynareModel.endo_nbr, DynareModel.fname, n1+n0);
fprintf(fid, ' J(1:%u,1:%u) = tmp(:,1:%u);\n', DynareModel.endo_nbr, n0+n1, n0+n1);
fprintf(fid, ' [F(%u:%u), tmp] = %s.dynamic(Y(1+%u:%u), x, p, y, 1);\n', DynareModel.endo_nbr+1, 2*DynareModel.endo_nbr, DynareModel.fname, n1+n0, 2*(n1+n0));
fprintf(fid, ' J(%u:%u,1:%u) = tmp(:,1:%u);\n', DynareModel.endo_nbr+1, 2*DynareModel.endo_nbr, n0+n1, n0+n1);
fprintf(fid, 'else\n');
fprintf(fid, ' F(1:%u) = %s.dynamic(Y(1:%u), x, p, y, 1);\n', DynareModel.endo_nbr, DynareModel.fname, n1+n0);
fprintf(fid, ' F(%u:%u) = %s.dynamic(Y(1+%u:%u), x, p, y, 1);\n', DynareModel.endo_nbr+1, 2*DynareModel.endo_nbr, DynareModel.fname, n1+n0, 2*(n1+n0));
fprintf(fid, 'end\n\n');
% Compute the jacobian if required.
fprintf(fid, 'if nargout>1\n');
fprintf(fid, ' JAC = zeros(%u,%u);\n', 2*DynareModel.endo_nbr, 2*DynareModel.endo_nbr);
% Compute the derivatives of the first block of equations (period t)
% with respect to the endogenous variables.
for i=1:DynareModel.eq_nbr
for j=1:DynareModel.endo_nbr
if i1(j)
if i0(j)
fprintf(fid, ' JAC(%u,%u) = J(%u,%u)+J(%u,%u)*g(%u);\n', i, j, i, i0(j), i, i1(j), j);
else
fprintf(fid, ' JAC(%u,%u) = J(%u,%u)*g(%u);\n', i, j, i, i1(j), j);
end
else
if i0(j)
fprintf(fid, ' JAC(%u,%u) = J(%u,%u);\n', i, j, i, i0(j));
end
end
end
end
% Compute the derivatives of the second block of equations (period t+1)
% with respect to the endogenous variables.
for i=DynareModel.eq_nbr+1:2*DynareModel.eq_nbr
for j=1:DynareModel.endo_nbr
if i1(j)
if i0(j)
fprintf(fid, ' JAC(%u,%u) = J(%u,%u)*g(%u)+J(%u,%u)*g(%u)*g(%u);\n', i, j, i, i0(j), j, i, i1(j), j, j);
else
fprintf(fid, ' JAC(%u,%u) = J(%u,%u)*g(%u)*g(%u);\n', i, j, i, i1(j), j, j);
end
else
if i0(j)
fprintf(fid, ' JAC(%u, %u) = J(%u, %u)*g(%u);\n', i, j, i, i0(j), j);
end
end
end
end
% Compute the derivatives of the first block of equations (period t)
% with respect to the growth factors.
for i=1:DynareModel.eq_nbr
for j=1:DynareModel.endo_nbr
if i1(j)
fprintf(fid, ' J(%u,%u) = J(%u,%u)*y(%u);\n', i, n0+n1+j, i, i1(j), j);
end
end
end
% Compute the derivatives of the second block of equations (period t+1)
% with respect to the endogenous variables.
for i=DynareModel.eq_nbr+1:2*DynareModel.eq_nbr
for j=1:DynareModel.endo_nbr
if i0(j)
fprintf(fid, ' J(%u,%u) = J(%u,%u)+J(%u,%u)*y(%u);\n', i, n0+n1+j, i, n0+n1+j, i, i0(j), j);
end
if i1(j)
fprintf(fid, ' J(%u,%u) = J(%u,%u)+2*J(%u,%u)*y(%u)*g(%u);\n', i, n0+n1+j, i, n0+n1+j, i, i1(j), j, j);
end
end
end
fprintf(fid, ' JAC(:,%u:%u) = J(:,%u:%u);\n', DynareModel.endo_nbr+1, 2*DynareModel.endo_nbr, n0+n1+1, n0+n1+DynareModel.endo_nbr);
fprintf(fid,'end\n');
% Close file.
fclose(fid);

View File

@ -357,7 +357,8 @@ MODFILES = \
observation_trends_and_prefiltering/calib_smoother/Tr_prefilter_loglin_calib_smoother.mod \
observation_trends_and_prefiltering/calib_smoother/Tr_prefil_f_obs_loglin_cal_smoother.mod \
observation_trends_and_prefiltering/ML/Trend_no_prefilter_selected_var.mod \
dynare-command-options/ramst.mod
bgp/solow-1/solow.mod \
dynare-command-options/ramst.mod
PARTICLEFILES = \
particle/dsge_base2.mod \

View File

@ -0,0 +1,80 @@
// This mod file test the bgp.write function by characterizing the Balanced Growth Path of the Solow model. This is done 10000 times in a Monte Carlo loop
// randomizing the initial guess of the nonlinear solver.
var Efficiency
EfficiencyGrowth
Population
PopulationGrowth
Output
PhysicalCapitalStock ;
varexo e_x
e_n ;
parameters alpha
delta
s
rho_x
rho_n
EfficiencyGrowth_ss
PopulationGrowth_ss ;
alpha = .33;
delta = .02;
s = .20;
rho_x = .90;
rho_n = .95;
EfficiencyGrowth_ss = 1.01;
PopulationGrowth_ss = 1.01;
model;
Efficiency = EfficiencyGrowth*Efficiency(-1);
EfficiencyGrowth/EfficiencyGrowth_ss = (EfficiencyGrowth(-1)/EfficiencyGrowth_ss)^(rho_x)*exp(e_x);
Population = PopulationGrowth*Population(-1);
PopulationGrowth/PopulationGrowth_ss = (PopulationGrowth(-1)/PopulationGrowth_ss)^(rho_n)*exp(e_n);
Output = PhysicalCapitalStock(-1)^alpha*(Efficiency*Population)^(1-alpha);
PhysicalCapitalStock = (1-delta)*PhysicalCapitalStock(-1) + s*Output;
end;
verbatim;
bgp.write(M_);
MC = 10000;
KY = NaN(MC,1);
GY = NaN(MC,1);
GK = NaN(MC,1);
EG = NaN(MC,1);
options = optimoptions('fsolve','Display','off','Algorithm','levenberg-marquardt','MaxFunctionEvaluations',1000000,'MaxIterations',100000,'SpecifyObjectiveGradient',true,'FunctionTolerance',1e-8,'StepTolerance',1e-8);
for i=1:MC
y = 1+(rand(6,1)-.5)*.2;
g = ones(6,1);
[y, fval, exitflag] = fsolve(@solow.bgpfun, [y;g], options);
if exitflag>0
KY(i) = y(6)/y(5);
GY(i) = y(11);
GK(i) = y(12);
EG(i) = y(2);
end
end
% Compute the physical capital stock over output ratio along the BGP as
% a function of the deep parameters...
theoretical_long_run_ratio = s*EfficiencyGrowth_ss*PopulationGrowth_ss/(EfficiencyGrowth_ss*PopulationGrowth_ss-1+delta);
% ... and compare to the average ratio in the Monte Carlo
mu = mean(KY(~isnan(KY)));
s2 = var(KY(~isnan(KY)));
nn = sum(isnan(KY))/MC;
disp(sprintf('Theoretical K/Y BGP ratio = %s.', num2str(theoretical_long_run_ratio)));
disp(sprintf('mean(K/Y) = %s.', num2str(mu)));
disp(sprintf('var(K/Y) = %s.', num2str(s2)));
disp(sprintf('Number of failures: %u (over %u problems).', sum(isnan(KY)), MC));
assert(abs(mu-theoretical_long_run_ratio)<1e-8);
assert(s2<1e-16);
assert(abs(mean(GY(~isnan(GY)))-EfficiencyGrowth_ss*PopulationGrowth_ss)<1e-8)
assert(var(GY(~isnan(GY)))<1e-16);
assert(abs(mean(GK(~isnan(GK)))-EfficiencyGrowth_ss*PopulationGrowth_ss)<1e-8)
assert(var(GK(~isnan(GK)))<1e-16);
assert(abs(mean(EG(~isnan(EG)))-EfficiencyGrowth_ss)<1e-8)
assert(var(EG(~isnan(EG)))<1e-16);
end;