🐛 Fix wrong third-order computation in pruned state space system
Related to #1706 ✅ Add unit test for pruned state space up to order 3 // Changed tolerance in new testtime-shift
parent
f69cd14983
commit
f4dc2ee743
|
@ -1,33 +1,54 @@
|
|||
% By Willi Mutschler, September 26, 2016. Email: willi@mutschler.eu
|
||||
% Quadruplication Matrix as defined by
|
||||
% Meijer (2005) - Matrix algebra for higher order moments. Linear Algebra and its Applications, 410,pp. 112–134
|
||||
function [DP6,DP6inv] = Q6_plication(p)
|
||||
% Computes the 6-way duplication Matrix DP6 (and its Moore-Penrose inverse)
|
||||
% such that for any p-dimensional vector x:
|
||||
% y=kron(kron(kron(kron(kron(x,x),x,x),x),x)=DP6*z
|
||||
% where z is of dimension np=p*(p+1)*(p+2)*(p+3)*(p+4)*(p+5)/(1*2*3*4*5*6)
|
||||
% and is obtained from y by removing each second and later occurence of the
|
||||
% same element. This is a generalization of the Duplication matrix.
|
||||
% Reference: Meijer (2005) - Matrix algebra for higher order moments.
|
||||
% Linear Algebra and its Applications, 410,pp. 112-134
|
||||
% =========================================================================
|
||||
% INPUTS
|
||||
% * p [integer] size of vector
|
||||
% -------------------------------------------------------------------------
|
||||
% OUTPUTS
|
||||
% * DP6 [p^6 by np] 6-way duplication matrix
|
||||
% * DP6inv [np by np] Moore-Penrose inverse of DP6
|
||||
% -------------------------------------------------------------------------
|
||||
% This function is called by
|
||||
% * pruned_state_space_system.m
|
||||
% -------------------------------------------------------------------------
|
||||
% This function calls
|
||||
% * binom_coef (embedded)
|
||||
% * mue (embedded)
|
||||
% * uperm
|
||||
% =========================================================================
|
||||
% Copyright (C) 2020 Dynare Team
|
||||
%
|
||||
% Inputs:
|
||||
% p: size of vector
|
||||
% Outputs:
|
||||
% QP: quadruplication matrix
|
||||
% QPinv: Moore-Penrose inverse of QP
|
||||
% This file is part of Dynare.
|
||||
%
|
||||
|
||||
function [DP6,DP6inv] = Q6_plication(p,progress)
|
||||
if nargin <2
|
||||
progress =0;
|
||||
end
|
||||
reverseStr = ''; counti=1;
|
||||
% 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/>.
|
||||
% =========================================================================
|
||||
np = p*(p+1)*(p+2)*(p+3)*(p+4)*(p+5)/(1*2*3*4*5*6);
|
||||
DP6 = spalloc(p^6,p*(p+1)*(p+2)*(p+3)*(p+4)*(p+5)/(1*2*3*4*5*6),p^6);
|
||||
|
||||
DP6 = spalloc(p^6,np,p^6);
|
||||
counti=1;
|
||||
for i1=1:p
|
||||
for i2=i1:p
|
||||
for i3=i2:p
|
||||
for i4=i3:p
|
||||
for i5=i4:p
|
||||
for i6=i5:p
|
||||
if progress && (rem(counti,100)== 0)
|
||||
msg = sprintf(' Q6-plication Matrix Processed %d/%d', counti, np); fprintf([reverseStr, msg]); reverseStr = repmat(sprintf('\b'), 1, length(msg));
|
||||
elseif progress && (counti==np)
|
||||
msg = sprintf(' Q6-plication Matrix Processed %d/%d\n', counti, np); fprintf([reverseStr, msg]); reverseStr = repmat(sprintf('\b'), 1, length(msg));
|
||||
end
|
||||
idx = uperm([i6 i5 i4 i3 i2 i1]);
|
||||
for r = 1:size(idx,1)
|
||||
ii1 = idx(r,1); ii2= idx(r,2); ii3=idx(r,3); ii4=idx(r,4); ii5=idx(r,5); ii6=idx(r,6);
|
||||
|
@ -45,11 +66,13 @@ end
|
|||
DP6inv = (transpose(DP6)*DP6)\transpose(DP6);
|
||||
|
||||
function m = mue(p,i1,i2,i3,i4,i5,i6)
|
||||
% Auxiliary expression, see page 122 of Meijer (2005)
|
||||
m = binom_coef(p,6,1) - binom_coef(p,1,i1+1) - binom_coef(p,2,i2+1) - binom_coef(p,3,i3+1) - binom_coef(p,4,i4+1) - binom_coef(p,5,i5+1) - binom_coef(p,6,i6+1);
|
||||
m = round(m);
|
||||
end
|
||||
|
||||
function N = binom_coef(p,q,i)
|
||||
% Auxiliary expression for binomial coefficients, see page 119 of Meijer (2005)
|
||||
t = q; r =p+q-i;
|
||||
if t==0
|
||||
N=1;
|
||||
|
|
|
@ -1,19 +1,27 @@
|
|||
%
|
||||
% bivmom.m Date: 1/11/2004
|
||||
% This Matlab program computes the product moment of X_1^{p_1}X_2^{p_2},
|
||||
% where X_1 and X_2 are standard bivariate normally distributed.
|
||||
function [y,dy] = bivmom(p,rho)
|
||||
% Computes the product moment (and its derivative with respect to standard
|
||||
% errors and correlation parameters) of X_1^{p_1}X_2^{p_2}, where X_1 and X_2
|
||||
% are standard bivariate normally distributed.
|
||||
% n : dimension of X
|
||||
% rho: correlation coefficient between X_1 and X_2
|
||||
% Reference: Kotz, Balakrishnan, and Johnson (2000), Continuous Multivariate
|
||||
% Distributions, Vol. 1, p.261
|
||||
% Note that there is a typo in Eq.(46.25), there should be an extra rho in front
|
||||
% of the equation.
|
||||
% Usage: bivmom(p,rho)
|
||||
%
|
||||
% Retrieved from http://www-2.rotman.utoronto.ca/~kan/papers/prodmom.zip
|
||||
% This function is part of replication codes of the following paper:
|
||||
% =========================================================================
|
||||
% INPUTS
|
||||
% p [2 by 1] powers of X_{1} and X_{2}
|
||||
% rho [1 by 1] correlation coefficient between X_1 and X_2
|
||||
% -------------------------------------------------------------------------
|
||||
% OUTPUTS
|
||||
% y [1 by 1] product moment E[X_1^{p_1}X_2^{p_2}]
|
||||
% dy [1 by 1] derivative of y wrt to rho
|
||||
% -------------------------------------------------------------------------
|
||||
% This function is based upon bivmom.m which is part of replication codes
|
||||
% of the following paper:
|
||||
% Kan, R.: "From moments of sum to moments of product." Journal of
|
||||
% Multivariate Analysis, 2008, vol. 99, issue 3, pages 542-554.
|
||||
% bivmom.m can be retrieved from http://www-2.rotman.utoronto.ca/~kan/papers/prodmom.zip
|
||||
% Further references:
|
||||
% Kotz, Balakrishnan, and Johnson (2000), Continuous Multivariate Distributions, Vol. 1, p.261
|
||||
% Note that there is a typo in Eq.(46.25), there should be an extra rho in front
|
||||
% of the equation.
|
||||
% =========================================================================
|
||||
% Copyright (C) 2008-2015 Raymond Kan <kan@chass.utoronto.ca>
|
||||
% Copyright (C) 2019-2020 Dynare Team
|
||||
|
@ -33,7 +41,6 @@
|
|||
% You should have received a copy of the GNU General Public License
|
||||
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
% =========================================================================
|
||||
function [y,dy] = bivmom(p,rho)
|
||||
s1 = p(1);
|
||||
s2 = p(2);
|
||||
rho2 = rho^2;
|
||||
|
|
|
@ -15,12 +15,13 @@ function k = commutation(n, m, sparseflag)
|
|||
% This function is called by
|
||||
% * get_perturbation_params_derivs.m (previously getH.m)
|
||||
% * get_identification_jacobians.m (previously getJJ.m)
|
||||
% * pruned_state_space_system.m
|
||||
% -------------------------------------------------------------------------
|
||||
% This function calls
|
||||
% * vec (embedded)
|
||||
% =========================================================================
|
||||
% Copyright (C) 1997 Tom Minka <minka@microsoft.com>
|
||||
% Copyright (C) 2019 Dynare Team
|
||||
% Copyright (C) 2019-2020 Dynare Team
|
||||
%
|
||||
% This file is part of Dynare.
|
||||
%
|
||||
|
@ -47,24 +48,12 @@ if nargin < 3
|
|||
sparseflag = 0;
|
||||
end
|
||||
|
||||
if 0
|
||||
% first method
|
||||
i = 1:(n*m);
|
||||
a = reshape(i, n, m);
|
||||
j = vec(transpose(a));
|
||||
k = zeros(n*m,n*m);
|
||||
for r = i
|
||||
k(r, j(r)) = 1;
|
||||
end
|
||||
if sparseflag
|
||||
k = reshape(kron(vec(speye(n)), speye(m)), n*m, n*m);
|
||||
else
|
||||
% second method
|
||||
k = reshape(kron(vec(eye(n)), eye(m)), n*m, n*m);
|
||||
end
|
||||
|
||||
if sparseflag ~= 0
|
||||
k = sparse(k);
|
||||
end
|
||||
|
||||
function V = vec(A)
|
||||
V = A(:);
|
||||
end
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
function [MEAN, dMEAN, REDUCEDFORM, dREDUCEDFORM, DYNAMIC, dDYNAMIC, MOMENTS, dMOMENTS, dSPECTRUM, dMINIMAL, derivatives_info] = get_identification_jacobians(estim_params, M, oo, options, options_ident, indpmodel, indpstderr, indpcorr, indvobs)
|
||||
function [MEAN, dMEAN, REDUCEDFORM, dREDUCEDFORM, DYNAMIC, dDYNAMIC, MOMENTS, dMOMENTS, dSPECTRUM, dSPECTRUM_NO_MEAN, dMINIMAL, derivatives_info] = get_identification_jacobians(estim_params, M, oo, options, options_ident, indpmodel, indpstderr, indpcorr, indvobs)
|
||||
% function [MEAN, dMEAN, REDUCEDFORM, dREDUCEDFORM, DYNAMIC, dDYNAMIC, MOMENTS, dMOMENTS, dSPECTRUM, dMINIMAL, derivatives_info] = get_identification_jacobians(estim_params, M, oo, options, options_ident, indpmodel, indpstderr, indpcorr, indvobs)
|
||||
% previously getJJ.m in Dynare 4.5
|
||||
% Sets up the Jacobians needed for identification analysis
|
||||
|
@ -54,7 +54,14 @@ function [MEAN, dMEAN, REDUCEDFORM, dREDUCEDFORM, DYNAMIC, dDYNAMIC, MOMENTS, dM
|
|||
% * order==1: corresponds to Iskrev (2010)'s J matrix
|
||||
% * order==2: corresponds to Mutschler (2015)'s \bar{M}_2 matrix, i.e. theoretical moments from the pruned state space system
|
||||
%
|
||||
% dSPECTRUM: [totparam_nbr by totparam_nbr] in DR order. Gram matrix of Jacobian (wrt all params) of spectral density for VAROBS variables, where
|
||||
% dSPECTRUM: [totparam_nbr by totparam_nbr] in DR order. Gram matrix of Jacobian (wrt all params) of mean and of spectral density for VAROBS variables, where
|
||||
% spectral density at frequency w: f(w) = (2*pi)^(-1)*H(exp(-i*w))*E[Inov*Inov']*ctranspose(H(exp(-i*w)) with H being the Transfer function
|
||||
% dSPECTRUM = dMEAN*dMEAN + int_{-\pi}^\pi transpose(df(w)/dp')*(df(w)/dp') dw
|
||||
% * order==1: corresponds to Qu and Tkachenko (2012)'s G matrix, where Inov and H are computed from linear state space system
|
||||
% * order==2: corresponds to Mutschler (2015)'s G_2 matrix, where Inov and H are computed from second-order pruned state space system
|
||||
% * order==3: Inov and H are computed from third-order pruned state space system
|
||||
%
|
||||
% dSPECTRUM_NO_MEAN:[totparam_nbr by totparam_nbr] in DR order. Gram matrix of Jacobian (wrt all params) of spectral density for VAROBS variables, where
|
||||
% spectral density at frequency w: f(w) = (2*pi)^(-1)*H(exp(-i*w))*E[Inov*Inov']*ctranspose(H(exp(-i*w)) with H being the Transfer function
|
||||
% dSPECTRUM = int_{-\pi}^\pi transpose(df(w)/dp')*(df(w)/dp') dw
|
||||
% * order==1: corresponds to Qu and Tkachenko (2012)'s G matrix, where Inov and H are computed from linear state space system
|
||||
|
@ -81,11 +88,11 @@ function [MEAN, dMEAN, REDUCEDFORM, dREDUCEDFORM, DYNAMIC, dDYNAMIC, MOMENTS, dM
|
|||
% * get_minimal_state_representation
|
||||
% * duplication
|
||||
% * dyn_vech
|
||||
% * fjaco
|
||||
% * get_perturbation_params_derivs (previously getH)
|
||||
% * get_all_parameters
|
||||
% * fjaco
|
||||
% * lyapunov_symm
|
||||
% * identification_numerical_objective (previously thet2tau)
|
||||
% * pruned_state_space_system
|
||||
% * vec
|
||||
% =========================================================================
|
||||
% Copyright (C) 2010-2020 Dynare Team
|
||||
|
@ -220,22 +227,9 @@ elseif order == 3
|
|||
end
|
||||
|
||||
% Get (pruned) state space representation:
|
||||
options.options_ident.indvobs = indvobs;
|
||||
options.options_ident.indpmodel = indpmodel;
|
||||
options.options_ident.indpstderr = indpstderr;
|
||||
options.options_ident.indpcorr = indpcorr;
|
||||
oo.dr = pruned_state_space_system(M, options, oo.dr);
|
||||
MEAN = oo.dr.pruned.E_y; dMEAN = oo.dr.pruned.dE_y;
|
||||
A = oo.dr.pruned.A; dA = oo.dr.pruned.dA;
|
||||
B = oo.dr.pruned.B; dB = oo.dr.pruned.dB;
|
||||
C = oo.dr.pruned.C; dC = oo.dr.pruned.dC;
|
||||
D = oo.dr.pruned.D; dD = oo.dr.pruned.dD;
|
||||
c = oo.dr.pruned.c; dc = oo.dr.pruned.dc;
|
||||
d = oo.dr.pruned.d; dd = oo.dr.pruned.dd;
|
||||
Varinov = oo.dr.pruned.Varinov; dVarinov = oo.dr.pruned.dVarinov;
|
||||
Om_z = oo.dr.pruned.Om_z; dOm_z = oo.dr.pruned.dOm_z;
|
||||
Om_y = oo.dr.pruned.Om_y; dOm_y = oo.dr.pruned.dOm_y;
|
||||
|
||||
pruned = pruned_state_space_system(M, options, oo.dr, indvobs, nlags, useautocorr, 1);
|
||||
MEAN = pruned.E_y;
|
||||
dMEAN = pruned.dE_y;
|
||||
%storage for Jacobians used in dsge_likelihood.m for analytical Gradient and Hession of likelihood (only at order=1)
|
||||
derivatives_info = struct();
|
||||
if order == 1
|
||||
|
@ -247,12 +241,19 @@ if order == 1
|
|||
end
|
||||
|
||||
%% Compute dMOMENTS
|
||||
%Note that our state space system for computing second moments is the following:
|
||||
% zhat = A*zhat(-1) + B*xi, where zhat = z - E(z)
|
||||
% yhat = C*zhat(-1) + D*xi, where yhat = y - E(y)
|
||||
if ~no_identification_moments
|
||||
MOMENTS = identification_numerical_objective(xparam1, 1, estim_params, M, oo, options, indpmodel, indpstderr, indpcorr, indvobs, useautocorr, nlags, grid_nbr); %[outputflag=1]
|
||||
MOMENTS = [MEAN; MOMENTS];
|
||||
if ~no_identification_moments
|
||||
if useautocorr
|
||||
E_yy = pruned.Corr_y; dE_yy = pruned.dCorr_y;
|
||||
E_yyi = pruned.Corr_yi; dE_yyi = pruned.dCorr_yi;
|
||||
else
|
||||
E_yy = pruned.Var_y; dE_yy = pruned.dVar_y;
|
||||
E_yyi = pruned.Var_yi; dE_yyi = pruned.dVar_yi;
|
||||
end
|
||||
MOMENTS = [MEAN; dyn_vech(E_yy)];
|
||||
for i=1:nlags
|
||||
MOMENTS = [MOMENTS; vec(E_yyi(:,:,i))];
|
||||
end
|
||||
|
||||
if kronflag == -1
|
||||
%numerical derivative of autocovariogram
|
||||
dMOMENTS = fjaco(str2func('identification_numerical_objective'), xparam1, 1, estim_params, M, oo, options, indpmodel, indpstderr, indpcorr, indvobs, useautocorr, nlags, grid_nbr); %[outputflag=1]
|
||||
|
@ -260,58 +261,10 @@ if ~no_identification_moments
|
|||
else
|
||||
dMOMENTS = zeros(obs_nbr + obs_nbr*(obs_nbr+1)/2 + nlags*obs_nbr^2 , totparam_nbr);
|
||||
dMOMENTS(1:obs_nbr,:) = dMEAN; %add Jacobian of first moments of VAROBS variables
|
||||
% Denote Ezz0 = E[zhat*zhat'], then the following Lyapunov equation defines the autocovariagram: Ezz0 -A*Ezz0*A' = B*Sig_xi*B' = Om_z
|
||||
[Ezz0,u] = lyapunov_symm(A, Om_z, options.lyapunov_fixed_point_tol, options.qz_criterium, options.lyapunov_complex_threshold, 1, options.debug);
|
||||
stationary_vars = (1:length(indvobs))';
|
||||
if ~isempty(u)
|
||||
x = abs(C*u);
|
||||
stationary_vars = find(all(x < options.Schur_vec_tol,2));
|
||||
end
|
||||
Eyy0 = NaN*ones(obs_nbr,obs_nbr);
|
||||
Eyy0(stationary_vars,stationary_vars) = C(stationary_vars,:)*Ezz0*C(stationary_vars,:)' + Om_y(stationary_vars,stationary_vars);
|
||||
%here method=1 is used, whereas all other calls of lyapunov_symm use method=2. The reason is that T and U are persistent, and input matrix A is the same, so using option 2 for all the rest of iterations spares a lot of computing time while not repeating Schur every time
|
||||
indzeros = find(abs(Eyy0) < 1e-12); %find values that are numerical zero
|
||||
Eyy0(indzeros) = 0;
|
||||
if useautocorr
|
||||
sdy = sqrt(diag(Eyy0)); %theoretical standard deviation
|
||||
sdy = sdy(stationary_vars);
|
||||
sy = sdy*sdy'; %cross products of standard deviations
|
||||
end
|
||||
|
||||
for jp = 1:totparam_nbr
|
||||
if jp <= (stderrparam_nbr+corrparam_nbr)
|
||||
%Note that for stderr and corr parameters, the derivatives of the system matrices are zero, i.e. dA=dB=dC=dD=0
|
||||
dEzz0 = lyapunov_symm(A,dOm_z(:,:,jp),options.lyapunov_fixed_point_tol,options.qz_criterium,options.lyapunov_complex_threshold,2,options.debug); %here method=2 is used to spare a lot of computing time while not repeating Schur every time
|
||||
dEyy0 = C*dEzz0*C' + dOm_y(:,:,jp);
|
||||
else %model parameters
|
||||
dEzz0 = lyapunov_symm(A,dOm_z(:,:,jp)+dA(:,:,jp)*Ezz0*A'+A*Ezz0*dA(:,:,jp)',options.lyapunov_fixed_point_tol,options.qz_criterium,options.lyapunov_complex_threshold,2,options.debug); %here method=2 is used to spare a lot of computing time while not repeating Schur every time
|
||||
dEyy0 = dC(:,:,jp)*Ezz0*C' + C*dEzz0*C' + C*Ezz0*dC(:,:,jp)' + dOm_y(:,:,jp);
|
||||
end
|
||||
%indzeros = find(abs(dEyy0) < 1e-12);
|
||||
%dEyy0(indzeros) = 0;
|
||||
if useautocorr
|
||||
dsy = 1/2./sdy.*diag(dEyy0);
|
||||
dsy = dsy*sdy'+sdy*dsy';
|
||||
dEyy0corr = (dEyy0.*sy-dsy.*Eyy0)./(sy.*sy);
|
||||
dEyy0corr = dEyy0corr-diag(diag(dEyy0corr))+diag(diag(dEyy0));
|
||||
dMOMENTS(obs_nbr+1 : obs_nbr+obs_nbr*(obs_nbr+1)/2 , jp) = dyn_vech(dEyy0corr); %focus only on VAROBS variables
|
||||
else
|
||||
dMOMENTS(obs_nbr+1 : obs_nbr+obs_nbr*(obs_nbr+1)/2 , jp) = dyn_vech(dEyy0); %focus only on VAROBS variables
|
||||
end
|
||||
tmpEyyi = A*Ezz0*C(stationary_vars,:)' + B*Varinov*D(stationary_vars,:)';
|
||||
%we could distinguish between stderr and corr params, but this has no real speed effect as we multipliy with zeros
|
||||
dtmpEyyi = dA(:,:,jp)*Ezz0*C' + A*dEzz0*C' + A*Ezz0*dC(:,:,jp)' + dB(:,:,jp)*Varinov*D' + B*dVarinov(:,:,jp)*D' + B*Varinov*dD(:,:,jp)';
|
||||
Ai = eye(size(A,1)); %this is A^0
|
||||
dAi = zeros(size(A,1),size(A,1)); %this is d(A^0)
|
||||
dMOMENTS(obs_nbr+1 : obs_nbr+obs_nbr*(obs_nbr+1)/2 , jp) = dyn_vech(dE_yy(:,:,jp));
|
||||
for i = 1:nlags
|
||||
Eyyi = C(stationary_vars,:)*Ai*tmpEyyi;
|
||||
dEyyi = dC(:,:,jp)*Ai*tmpEyyi + C*dAi*tmpEyyi + C*Ai*dtmpEyyi;
|
||||
if useautocorr
|
||||
dEyyi = (dEyyi.*sy-dsy.*Eyyi)./(sy.*sy);
|
||||
end
|
||||
dMOMENTS(obs_nbr + obs_nbr*(obs_nbr+1)/2 + (i-1)*obs_nbr^2 + 1 : obs_nbr + obs_nbr*(obs_nbr+1)/2 + i*obs_nbr^2, jp) = vec(dEyyi); %focus only on VAROBS variables
|
||||
dAi = dAi*A + Ai*dA(:,:,jp); %note that this is d(A^(i-1))
|
||||
Ai = Ai*A; %note that this is A^(i-1)
|
||||
dMOMENTS(obs_nbr + obs_nbr*(obs_nbr+1)/2 + (i-1)*obs_nbr^2 + 1 : obs_nbr + obs_nbr*(obs_nbr+1)/2 + i*obs_nbr^2, jp) = vec(dE_yyi(:,:,i,jp));
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -357,7 +310,7 @@ if ~no_identification_spectrum
|
|||
freqs = (0 : pi/(grid_nbr/2):pi); % we focus only on positive frequencies
|
||||
tpos = exp( sqrt(-1)*freqs); %positive Fourier frequencies
|
||||
tneg = exp(-sqrt(-1)*freqs); %negative Fourier frequencies
|
||||
IA = eye(size(A,1));
|
||||
IA = eye(size(pruned.A,1));
|
||||
if kronflag == -1
|
||||
%numerical derivative of spectral density
|
||||
dOmega_tmp = fjaco(str2func('identification_numerical_objective'), xparam1, 2, estim_params, M, oo, options, indpmodel, indpstderr, indpcorr, indvobs, useautocorr, nlags, grid_nbr); %[outputflag=2]
|
||||
|
@ -366,68 +319,63 @@ if ~no_identification_spectrum
|
|||
kk = kk+1;
|
||||
dOmega = dOmega_tmp(1 + (kk-1)*obs_nbr^2 : kk*obs_nbr^2,:);
|
||||
if ig == 1 % add zero frequency once
|
||||
dSPECTRUM = dOmega'*dOmega;
|
||||
dSPECTRUM_NO_MEAN = dOmega'*dOmega;
|
||||
else % due to symmetry to negative frequencies we can add positive frequencies twice
|
||||
dSPECTRUM = dSPECTRUM + 2*(dOmega'*dOmega);
|
||||
dSPECTRUM_NO_MEAN = dSPECTRUM_NO_MEAN + 2*(dOmega'*dOmega);
|
||||
end
|
||||
end
|
||||
elseif kronflag == 1
|
||||
%use Kronecker products
|
||||
dA = reshape(dA,size(dA,1)*size(dA,2),size(dA,3));
|
||||
dB = reshape(dB,size(dB,1)*size(dB,2),size(dB,3));
|
||||
dC = reshape(dC,size(dC,1)*size(dC,2),size(dC,3));
|
||||
dD = reshape(dD,size(dD,1)*size(dD,2),size(dD,3));
|
||||
dVarinov = reshape(dVarinov,size(dVarinov,1)*size(dVarinov,2),size(dVarinov,3));
|
||||
K_obs_exo = commutation(obs_nbr,size(Varinov,1));
|
||||
dA = reshape(pruned.dA,size(pruned.dA,1)*size(pruned.dA,2),size(pruned.dA,3));
|
||||
dB = reshape(pruned.dB,size(pruned.dB,1)*size(pruned.dB,2),size(pruned.dB,3));
|
||||
dC = reshape(pruned.dC,size(pruned.dC,1)*size(pruned.dC,2),size(pruned.dC,3));
|
||||
dD = reshape(pruned.dD,size(pruned.dD,1)*size(pruned.dD,2),size(pruned.dD,3));
|
||||
dVarinov = reshape(pruned.dVarinov,size(pruned.dVarinov,1)*size(pruned.dVarinov,2),size(pruned.dVarinov,3));
|
||||
K_obs_exo = commutation(obs_nbr,size(pruned.Varinov,1));
|
||||
for ig=1:length(freqs)
|
||||
z = tneg(ig);
|
||||
zIminusA = (z*IA - A);
|
||||
zIminusA = (z*IA - pruned.A);
|
||||
zIminusAinv = zIminusA\IA;
|
||||
Transferfct = D + C*zIminusAinv*B; % Transfer function
|
||||
Transferfct = pruned.D + pruned.C*zIminusAinv*pruned.B; % Transfer function
|
||||
dzIminusA = -dA;
|
||||
dzIminusAinv = kron(-(transpose(zIminusA)\IA),zIminusAinv)*dzIminusA; %this takes long
|
||||
dTransferfct = dD + DerivABCD(C,dC,zIminusAinv,dzIminusAinv,B,dB); %also long
|
||||
dTransferfct = dD + DerivABCD(pruned.C,dC,zIminusAinv,dzIminusAinv,pruned.B,dB); %this takes long
|
||||
dTransferfct_conjt = K_obs_exo*conj(dTransferfct);
|
||||
dOmega = (1/(2*pi))*DerivABCD(Transferfct,dTransferfct,Varinov,dVarinov,Transferfct',dTransferfct_conjt); %also long
|
||||
dOmega = (1/(2*pi))*DerivABCD(Transferfct,dTransferfct,pruned.Varinov,dVarinov,Transferfct',dTransferfct_conjt); %also long
|
||||
if ig == 1 % add zero frequency once
|
||||
dSPECTRUM = dOmega'*dOmega;
|
||||
dSPECTRUM_NO_MEAN = dOmega'*dOmega;
|
||||
else % due to symmetry to negative frequencies we can add positive frequencies twice
|
||||
dSPECTRUM = dSPECTRUM + 2*(dOmega'*dOmega);
|
||||
dSPECTRUM_NO_MEAN = dSPECTRUM_NO_MEAN + 2*(dOmega'*dOmega);
|
||||
end
|
||||
end
|
||||
%put back into tensor notation
|
||||
dA = reshape(dA,size(A,1),size(A,2),totparam_nbr);
|
||||
dB = reshape(dB,size(B,1),size(B,2),totparam_nbr);
|
||||
dC = reshape(dC,size(C,1),size(C,2),totparam_nbr);
|
||||
dD = reshape(dD,size(D,1),size(D,2),totparam_nbr);
|
||||
dVarinov = reshape(dVarinov,size(Varinov,1),size(Varinov,2),totparam_nbr);
|
||||
elseif (kronflag==0) || (kronflag==-2)
|
||||
for ig = 1:length(freqs)
|
||||
IzminusA = tpos(ig)*IA - A;
|
||||
invIzminusA = IzminusA\eye(size(A,1));
|
||||
Transferfct = D + C*invIzminusA*B;
|
||||
IzminusA = tpos(ig)*IA - pruned.A;
|
||||
invIzminusA = IzminusA\eye(size(pruned.A,1));
|
||||
Transferfct = pruned.D + pruned.C*invIzminusA*pruned.B;
|
||||
dOmega = zeros(obs_nbr^2,totparam_nbr);
|
||||
for j = 1:totparam_nbr
|
||||
if j <= stderrparam_nbr+corrparam_nbr %stderr and corr parameters: only dSig is nonzero
|
||||
dOmega_tmp = Transferfct*dVarinov(:,:,j)*Transferfct';
|
||||
dOmega_tmp = Transferfct*pruned.dVarinov(:,:,j)*Transferfct';
|
||||
else %model parameters
|
||||
dinvIzminusA = -invIzminusA*(-dA(:,:,j))*invIzminusA;
|
||||
dTransferfct = dD(:,:,j) + dC(:,:,j)*invIzminusA*B + C*dinvIzminusA*B + C*invIzminusA*dB(:,:,j);
|
||||
dOmega_tmp = dTransferfct*Varinov*Transferfct' + Transferfct*dVarinov(:,:,j)*Transferfct' + Transferfct*Varinov*dTransferfct';
|
||||
dinvIzminusA = -invIzminusA*(-pruned.dA(:,:,j))*invIzminusA;
|
||||
dTransferfct = pruned.dD(:,:,j) + pruned.dC(:,:,j)*invIzminusA*pruned.B + pruned.C*dinvIzminusA*pruned.B + pruned.C*invIzminusA*pruned.dB(:,:,j);
|
||||
dOmega_tmp = dTransferfct*pruned.Varinov*Transferfct' + Transferfct*pruned.dVarinov(:,:,j)*Transferfct' + Transferfct*pruned.Varinov*dTransferfct';
|
||||
end
|
||||
dOmega(:,j) = (1/(2*pi))*dOmega_tmp(:);
|
||||
end
|
||||
if ig == 1 % add zero frequency once
|
||||
dSPECTRUM = dOmega'*dOmega;
|
||||
dSPECTRUM_NO_MEAN = dOmega'*dOmega;
|
||||
else % due to symmetry to negative frequencies we can add positive frequencies twice
|
||||
dSPECTRUM = dSPECTRUM + 2*(dOmega'*dOmega);
|
||||
dSPECTRUM_NO_MEAN = dSPECTRUM_NO_MEAN + 2*(dOmega'*dOmega);
|
||||
end
|
||||
end
|
||||
end
|
||||
% Normalize Matrix and add steady state Jacobian, note that G is real and symmetric by construction
|
||||
dSPECTRUM = 2*pi*dSPECTRUM./(2*length(freqs)-1) + dMEAN'*dMEAN;
|
||||
dSPECTRUM = real(dSPECTRUM);
|
||||
dSPECTRUM_NO_MEAN = real(2*pi*dSPECTRUM_NO_MEAN./(2*length(freqs)-1));
|
||||
dSPECTRUM = dSPECTRUM_NO_MEAN + dMEAN'*dMEAN;
|
||||
else
|
||||
dSPECTRUM_NO_MEAN = [];
|
||||
dSPECTRUM = [];
|
||||
end
|
||||
|
||||
|
@ -442,14 +390,14 @@ if ~no_identification_minimal
|
|||
dMINIMAL = [];
|
||||
else
|
||||
% Derive and check minimal state vector of first-order
|
||||
SYS.A = oo.dr.ghx(oo.dr.pruned.indx,:);
|
||||
SYS.dA = oo.dr.derivs.dghx(oo.dr.pruned.indx,:,:);
|
||||
SYS.B = oo.dr.ghu(oo.dr.pruned.indx,:);
|
||||
SYS.dB = oo.dr.derivs.dghu(oo.dr.pruned.indx,:,:);
|
||||
SYS.C = oo.dr.ghx(oo.dr.pruned.indy,:);
|
||||
SYS.dC = oo.dr.derivs.dghx(oo.dr.pruned.indy,:,:);
|
||||
SYS.D = oo.dr.ghu(oo.dr.pruned.indy,:);
|
||||
SYS.dD = oo.dr.derivs.dghu(oo.dr.pruned.indy,:,:);
|
||||
SYS.A = oo.dr.ghx(pruned.indx,:);
|
||||
SYS.dA = oo.dr.derivs.dghx(pruned.indx,:,:);
|
||||
SYS.B = oo.dr.ghu(pruned.indx,:);
|
||||
SYS.dB = oo.dr.derivs.dghu(pruned.indx,:,:);
|
||||
SYS.C = oo.dr.ghx(pruned.indy,:);
|
||||
SYS.dC = oo.dr.derivs.dghx(pruned.indy,:,:);
|
||||
SYS.D = oo.dr.ghu(pruned.indy,:);
|
||||
SYS.dD = oo.dr.derivs.dghu(pruned.indy,:,:);
|
||||
[CheckCO,minnx,SYS] = get_minimal_state_representation(SYS,1);
|
||||
|
||||
if CheckCO == 0
|
||||
|
|
|
@ -145,6 +145,12 @@ analytic_derivation_mode = options.analytic_derivation_mode;
|
|||
% * -2: numerical two-sided finite difference method to compute numerically dYss, dg1, dg2, dg3, d2Yss and d2g1, the other output arguments are computed analytically as in kronflag=0
|
||||
gstep = options.gstep;
|
||||
order = options.order;
|
||||
if isempty(options.qz_criterium)
|
||||
% set default value for qz_criterium: if there are no unit roots one can use 1.0
|
||||
% If they are possible, you may have have multiple unit roots and the accuracy
|
||||
% decreases when computing the eigenvalues in lyapunov_symm. Hence, we normally use 1+1e-6
|
||||
options = select_qz_criterium_value(options);
|
||||
end
|
||||
qz_criterium = options.qz_criterium;
|
||||
threads_BC = options.threads.kronecker.sparse_hessian_times_B_kronecker_C;
|
||||
|
||||
|
@ -269,6 +275,11 @@ if d2flag
|
|||
KalmanB = ghu;
|
||||
end
|
||||
|
||||
% Store some objects
|
||||
DERIVS.indpmodel = indpmodel;
|
||||
DERIVS.indpstderr = indpstderr;
|
||||
DERIVS.indpcorr = indpcorr;
|
||||
|
||||
if analytic_derivation_mode == -1
|
||||
%% numerical two-sided finite difference method using function get_perturbation_params_derivs_numerical_objective.m (previously thet2tau.m in Dynare 4.5) for
|
||||
% Jacobian (wrt selected stderr, corr and model parameters) of
|
||||
|
|
|
@ -137,7 +137,7 @@ no_identification_spectrum = options_ident.no_identification_spectrum;
|
|||
|
||||
if info(1) == 0 %no errors in solution
|
||||
% Compute parameter Jacobians for identification analysis
|
||||
[MEAN, dMEAN, REDUCEDFORM, dREDUCEDFORM, DYNAMIC, dDYNAMIC, MOMENTS, dMOMENTS, dSPECTRUM, dMINIMAL, derivatives_info] = get_identification_jacobians(estim_params_, M_, oo_, options_, options_ident, indpmodel, indpstderr, indpcorr, indvobs);
|
||||
[MEAN, dMEAN, REDUCEDFORM, dREDUCEDFORM, DYNAMIC, dDYNAMIC, MOMENTS, dMOMENTS, dSPECTRUM, dSPECTRUM_NO_MEAN, dMINIMAL, derivatives_info] = get_identification_jacobians(estim_params_, M_, oo_, options_, options_ident, indpmodel, indpstderr, indpcorr, indvobs);
|
||||
if isempty(dMINIMAL)
|
||||
% Komunjer and Ng is not computed if (1) minimality conditions are not fullfilled or (2) there are more shocks and measurement errors than observables, so we need to reset options
|
||||
no_identification_minimal = 1;
|
||||
|
@ -194,7 +194,7 @@ if info(1) == 0 %no errors in solution
|
|||
options_ident.no_identification_spectrum = 1; %do not recompute dSPECTRUM
|
||||
options_ident.ar = nlags; %store new lag number
|
||||
options_.ar = nlags; %store new lag number
|
||||
[~, ~, ~, ~, ~, ~, MOMENTS, dMOMENTS, ~, ~, ~] = get_identification_jacobians(estim_params_, M_, oo_, options_, options_ident, indpmodel, indpstderr, indpcorr, indvobs);
|
||||
[~, ~, ~, ~, ~, ~, MOMENTS, dMOMENTS, ~, ~, ~, ~] = get_identification_jacobians(estim_params_, M_, oo_, options_, options_ident, indpmodel, indpstderr, indpcorr, indvobs);
|
||||
|
||||
ind_dMOMENTS = (find(max(abs(dMOMENTS'),[],1) > tol_deriv)); %new index with non-zero rows
|
||||
end
|
||||
|
@ -508,6 +508,7 @@ if info(1) == 0 %no errors in solution
|
|||
ide_spectrum.norm_dSPECTRUM = norm_dSPECTRUM;
|
||||
ide_spectrum.tilda_dSPECTRUM = tilda_dSPECTRUM;
|
||||
ide_spectrum.dSPECTRUM = dSPECTRUM;
|
||||
ide_spectrum.dSPECTRUM_NO_MEAN = dSPECTRUM_NO_MEAN;
|
||||
end
|
||||
|
||||
%% Perform identification checks, i.e. find out which parameters are involved
|
||||
|
|
|
@ -30,17 +30,15 @@ function out = identification_numerical_objective(params, outputflag, estim_para
|
|||
% Jacobian of the dynamic model equations, and Y_t selected variables
|
||||
% -------------------------------------------------------------------------
|
||||
% This function is called by
|
||||
% * get_first_order_solution_params_deriv.m (previously getH.m)
|
||||
% * get_identification_jacobians.m (previously getJJ.m)
|
||||
% -------------------------------------------------------------------------
|
||||
% This function calls
|
||||
% * [M.fname,'.dynamic']
|
||||
% * dynare_resolve
|
||||
% * dyn_vech
|
||||
% * lyapunov_symm
|
||||
% * resol
|
||||
% * vec
|
||||
% =========================================================================
|
||||
% Copyright (C) 2011-2019 Dynare Team
|
||||
% Copyright (C) 2011-2020 Dynare Team
|
||||
%
|
||||
% This file is part of Dynare.
|
||||
%
|
||||
|
@ -58,16 +56,6 @@ function out = identification_numerical_objective(params, outputflag, estim_para
|
|||
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
% =========================================================================
|
||||
|
||||
if nargin < 11 || isempty(useautocorr)
|
||||
useautocorr = 0;
|
||||
end
|
||||
if nargin < 12 || isempty(nlags)
|
||||
nlags = 3;
|
||||
end
|
||||
if nargin < 13 || isempty(grid_nbr)
|
||||
grid_nbr = 0;
|
||||
end
|
||||
|
||||
%% Update stderr, corr and model parameters
|
||||
%note that if no estimated_params_block is given, then all stderr and model parameters are selected but no corr parameters
|
||||
if length(params) > length(indpmodel)
|
||||
|
@ -90,50 +78,21 @@ end
|
|||
%% compute Kalman transition matrices and steady state with updated parameters
|
||||
[~,info,M,options,oo] = resol(0,M,options,oo);
|
||||
options = rmfield(options,'options_ident');
|
||||
oo.dr = pruned_state_space_system(M, options, oo.dr);
|
||||
A = oo.dr.pruned.A;
|
||||
B = oo.dr.pruned.B;
|
||||
C = oo.dr.pruned.C(indvar,:);
|
||||
D = oo.dr.pruned.D(indvar,:);
|
||||
Om_z = oo.dr.pruned.Om_z;
|
||||
Om_y = oo.dr.pruned.Om_y(indvar,indvar);
|
||||
Varinov = oo.dr.pruned.Varinov;
|
||||
obs_nbr = size(C,1);
|
||||
pruned = pruned_state_space_system(M, options, oo.dr, indvar, nlags, useautocorr, 0);
|
||||
|
||||
%% out = [vech(cov(Y_t,Y_t)); vec(cov(Y_t,Y_{t-1}); ...; vec(cov(Y_t,Y_{t-nlags})] of indvar variables, in DR order. This is Iskrev (2010)'s J matrix.
|
||||
if outputflag == 1
|
||||
% Denote Ezz0 = E_t(z_t * z_t'), then the following Lyapunov equation defines the autocovariagrom: Ezz0 -A*Ezz*A' = B*Sig_e*B'
|
||||
[Ezz0,u] = lyapunov_symm(A, Om_z, options.lyapunov_fixed_point_tol, options.qz_criterium, options.lyapunov_complex_threshold, 1, options.debug);
|
||||
stationary_vars = (1:size(C,1))';
|
||||
if ~isempty(u)
|
||||
x = abs(C*u);
|
||||
stationary_vars = find(all(x < options.Schur_vec_tol,2));
|
||||
end
|
||||
Eyy0 = NaN*ones(obs_nbr,obs_nbr);
|
||||
Eyy0(stationary_vars,stationary_vars) = C(stationary_vars,:)*Ezz0*C(stationary_vars,:)' + Om_y(stationary_vars,stationary_vars);
|
||||
indzeros = find(abs(Eyy0) < 1e-12); %find values that are numerical zero
|
||||
Eyy0(indzeros) = 0;
|
||||
if outputflag == 1
|
||||
if useautocorr
|
||||
sy = sqrt(diag(Ezz0)); %theoretical standard deviation
|
||||
sy = sy(stationary_vars);
|
||||
sy = sy*sy'; %cross products of standard deviations
|
||||
sy0 = sy-diag(diag(sy))+eye(length(sy));
|
||||
Eyy0corr = NaN*ones(size(C,1),size(C,1));
|
||||
Eyy0corr(stationary_vars,stationary_vars) = Eyy0./sy0;
|
||||
out = dyn_vech(Eyy0corr); %focus only on unique terms
|
||||
out = dyn_vech(pruned.Corr_y);
|
||||
else
|
||||
out = dyn_vech(Eyy0); %focus only on unique terms
|
||||
end
|
||||
% compute autocovariances/autocorrelations of lagged observed variables
|
||||
tmpEyyi = A*Ezz0*C(stationary_vars,:)' + B*Varinov*D(stationary_vars,:)';
|
||||
Ai = eye(size(A,1)); %this is A^0
|
||||
out = dyn_vech(pruned.Var_y);
|
||||
end
|
||||
for i = 1:nlags
|
||||
Eyyi = NaN*ones(obs_nbr,obs_nbr);
|
||||
Eyyi(stationary_vars,stationary_vars) = C(stationary_vars,:)*Ai*tmpEyyi;
|
||||
if useautocorr
|
||||
Eyyi = Eyyi./sy;
|
||||
out = [out;vec(pruned.Corr_yi(:,:,i))];
|
||||
else
|
||||
out = [out;vec(pruned.Var_yi(:,:,i))];
|
||||
end
|
||||
out = [out;vec(Eyyi)];
|
||||
Ai = Ai*A; %note that this is A^(i-1)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -142,13 +101,13 @@ if outputflag == 2
|
|||
% This computes the spectral density g_omega where the interval [-pi;\pi] is discretized by grid_nbr points
|
||||
freqs = (0 : pi/(grid_nbr/2):pi);% we focus only on positive values including the 0 frequency
|
||||
tpos = exp( sqrt(-1)*freqs); %Fourier frequencies
|
||||
IA = eye(size(A,1));
|
||||
var_nbr = size(C,1);
|
||||
IA = eye(size(pruned.A,1));
|
||||
var_nbr = size(pruned.C,1);
|
||||
out = zeros(var_nbr^2*length(freqs),1);
|
||||
kk = 0;
|
||||
for ig = 1:length(freqs)
|
||||
Transferfct = D + C*((tpos(ig)*IA-A)\B);
|
||||
g_omega = (1/(2*pi))*(Transferfct*Varinov*Transferfct'); % note that ' is the conjugate transpose
|
||||
Transferfct = pruned.D + pruned.C*((tpos(ig)*IA-pruned.A)\pruned.B);
|
||||
g_omega = (1/(2*pi))*(Transferfct*pruned.Varinov*Transferfct'); % note that ' is the conjugate transpose
|
||||
kk = kk+1;
|
||||
out(1 + (kk-1)*var_nbr^2 : kk*var_nbr^2) = g_omega(:);
|
||||
end
|
||||
|
|
|
@ -1,10 +1,37 @@
|
|||
function dy = prodmom_deriv(V,ii,nu,dV,dC)
|
||||
% This function builds upon and extends prodmom.m to compute the
|
||||
% derivatives of product moments of normally distributed variables with
|
||||
% respect to standard errors and correlation parameters.
|
||||
% prodmom.m is part of replication codes of the following paper:
|
||||
function [y,dy] = prodmom_deriv(V,ii,nu,dV,dC)
|
||||
% Computes the product moments (and its derivatives with respect to standard
|
||||
% errors and correlation parameters) of normally distributed variables, i.e.
|
||||
% this function computes the product moment of
|
||||
% X_{i_1}^{nu_1}X_{i_2}^{nu_2}...X_{i_m}^{nu_m}, where X_{i_j} are elements
|
||||
% from X ~ N(0_n,V) and V is positive semidefinite.
|
||||
% Example: To get E[X_2X_4^3X_7^2], use prodmom_deriv(V,[2 4 7],[1 3 2])
|
||||
% =========================================================================
|
||||
% INPUTS
|
||||
% V [n by n] covariance matrix of X (needs to be positive semidefinite)
|
||||
% ii [m by 1] vector of i_j
|
||||
% nu [nu_m by 1] power of X_{i_j}
|
||||
% dV [n by n by stderrparam_nbr+corrparam_nbr] derivative of V with respect
|
||||
% to selected standard error (stderr)
|
||||
% and correlation (corr) parameters
|
||||
% dC [n by n by stderrparam_nbr+corrparam_nbr] derivative of Correlation matrix C with respect
|
||||
% to selected standard error (stderr)
|
||||
% and correlation (corr) parameters
|
||||
% -------------------------------------------------------------------------
|
||||
% OUTPUTS
|
||||
% y [1 by 1] product moment E[X_{i_1}^{nu_1}X_{i_2}^{nu_2}...X_{i_m}^{nu_m}]
|
||||
% dy [1 by stderrparam_nbr+corrparam_nbr] derivatives of y wrt to selected
|
||||
% standard error and corr parameters
|
||||
% -------------------------------------------------------------------------
|
||||
% This function is based upon prodmom.m which is part of replication codes
|
||||
% of the following paper:
|
||||
% Kan, R.: "From moments of sum to moments of product." Journal of
|
||||
% Multivariate Analysis, 2008, vol. 99, issue 3, pages 542-554.
|
||||
% prodmom.m can be retrieved from http://www-2.rotman.utoronto.ca/~kan/papers/prodmom.zip
|
||||
% Further references:
|
||||
% Triantafyllopoulos (2003) On the Central Moments of the Multidimensional
|
||||
% Gaussian Distribution, Mathematical Scientist
|
||||
% Kotz, Balakrishnan, and Johnson (2000), Continuous Multivariate
|
||||
% Distributions, Vol. 1, p.261
|
||||
% =========================================================================
|
||||
% Copyright (C) 2008-2015 Raymond Kan <kan@chass.utoronto.ca>
|
||||
% Copyright (C) 2019-2020 Dynare Team
|
||||
|
@ -25,89 +52,118 @@ function dy = prodmom_deriv(V,ii,nu,dV,dC)
|
|||
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
|
||||
% =========================================================================
|
||||
if nargin<3
|
||||
nu = ones(size(ii));
|
||||
nu = ones(size(ii));
|
||||
end
|
||||
s = sum(nu);
|
||||
if s==0
|
||||
dy = zeros(1,1,size(dV,3));
|
||||
return
|
||||
y = 1;
|
||||
if nargout > 1
|
||||
dy = zeros(1,1,size(dV,3));
|
||||
end
|
||||
return
|
||||
end
|
||||
if rem(s,2)==1
|
||||
dy = zeros(1,1,size(dV,3));
|
||||
return
|
||||
y = 0;
|
||||
if nargout > 1
|
||||
dy = zeros(1,1,size(dV,3));
|
||||
end
|
||||
return
|
||||
end
|
||||
nuz = nu==0;
|
||||
nu(nuz) = [];
|
||||
ii(nuz) = [];
|
||||
m = length(ii);
|
||||
V = V(ii,ii);
|
||||
dV = dV(ii,ii,:);
|
||||
if nargout > 1
|
||||
dV = dV(ii,ii,:);
|
||||
end
|
||||
s2 = s/2;
|
||||
%
|
||||
% Use univariate normal results
|
||||
%
|
||||
if m==1
|
||||
dy = s2*V^(s2-1)*dV*prod([1:2:s-1]);
|
||||
dy = reshape(dy,1,size(dV,3));
|
||||
y = V^s2*prod([1:2:s-1]);
|
||||
if nargout > 1
|
||||
dy = s2*V^(s2-1)*dV*prod([1:2:s-1]);
|
||||
dy = reshape(dy,1,size(dV,3));
|
||||
end
|
||||
return
|
||||
end
|
||||
%
|
||||
% Use bivariate normal results when there are only two distinct indices
|
||||
%
|
||||
if m==2
|
||||
rho = V(1,2)/sqrt(V(1,1)*V(2,2));
|
||||
drho = dC(ii(1),ii(2),:);
|
||||
[tmp,dtmp] = bivmom(nu,rho);
|
||||
dy = (nu(1)/2)*V(1,1)^(nu(1)/2-1)*dV(1,1,:) * V(2,2)^(nu(2)/2) * tmp...
|
||||
+ V(1,1)^(nu(1)/2) * (nu(2)/2)*V(2,2)^(nu(2)/2-1)*dV(2,2,:) * tmp...
|
||||
+ V(1,1)^(nu(1)/2) * V(2,2)^(nu(2)/2) * dtmp * drho;
|
||||
dy = reshape(dy,1,size(dV,3));
|
||||
return
|
||||
rho = V(1,2)/sqrt(V(1,1)*V(2,2));
|
||||
if nargout > 1
|
||||
drho = dC(ii(1),ii(2),:);
|
||||
[tmp,dtmp] = bivmom(nu,rho);
|
||||
dy = (nu(1)/2)*V(1,1)^(nu(1)/2-1)*dV(1,1,:) * V(2,2)^(nu(2)/2) * tmp...
|
||||
+ V(1,1)^(nu(1)/2) * (nu(2)/2)*V(2,2)^(nu(2)/2-1)*dV(2,2,:) * tmp...
|
||||
+ V(1,1)^(nu(1)/2) * V(2,2)^(nu(2)/2) * dtmp * drho;
|
||||
dy = reshape(dy,1,size(dV,3));
|
||||
else
|
||||
tmp = bivmom(nu,rho);
|
||||
end
|
||||
y = V(1,1)^(nu(1)/2)*V(2,2)^(nu(2)/2)*tmp;
|
||||
return
|
||||
end
|
||||
%
|
||||
% Regular case
|
||||
%
|
||||
[nu,inu] = sort(nu,2,'descend');
|
||||
V = V(inu,inu); % Extract only the relevant part of V
|
||||
dV = dV(inu,inu,:); % Extract only the relevant part of dV
|
||||
x = zeros(1,m);
|
||||
V = V./2;
|
||||
dV = dV./2;
|
||||
nu2 = nu./2;
|
||||
p = 2;
|
||||
q = nu2*V*nu2';
|
||||
%dq = nu2*dV*nu2';
|
||||
%dq = multiprod(multiprod(nu2,dV),nu2');
|
||||
dq = NaN(size(q,1), size(q,2), size(dV,3));
|
||||
for jp = 1:size(dV,3)
|
||||
dq(:,:,jp) = nu2*dV(:,:,jp)*nu2';
|
||||
y = 0;
|
||||
if nargout > 1
|
||||
dV = dV(inu,inu,:); % Extract only the relevant part of dV
|
||||
dV = dV./2;
|
||||
%dq = nu2*dV*nu2';
|
||||
%dq = multiprod(multiprod(nu2,dV),nu2');
|
||||
dq = NaN(size(q,1), size(q,2), size(dV,3));
|
||||
for jp = 1:size(dV,3)
|
||||
dq(:,:,jp) = nu2*dV(:,:,jp)*nu2';
|
||||
end
|
||||
dy = 0;
|
||||
end
|
||||
dy = 0;
|
||||
for i=1:fix(prod(nu+1)/2)
|
||||
dy = dy+p*s2*q^(s2-1)*dq;
|
||||
y = y+p*q^s2;
|
||||
if nargout > 1
|
||||
dy = dy+p*s2*q^(s2-1)*dq;
|
||||
end
|
||||
for j=1:m
|
||||
if x(j)<nu(j)
|
||||
x(j) = x(j)+1;
|
||||
p = -round(p*(nu(j)+1-x(j))/x(j));
|
||||
%dq = dq-2*(nu2-x)*dV(:,j,:)-dV(j,j,:);
|
||||
%dq = dq-2*multiprod((nu2-x),dV(:,j,:))-dV(j,j,:);
|
||||
for jp=1:size(dV,3)
|
||||
dq(:,:,jp) = dq(:,:,jp)-2*(nu2-x)*dV(:,j,jp)-dV(j,j,jp);
|
||||
end
|
||||
q = q-2*(nu2-x)*V(:,j)-V(j,j);
|
||||
break
|
||||
x(j) = x(j)+1;
|
||||
p = -round(p*(nu(j)+1-x(j))/x(j));
|
||||
q = q-2*(nu2-x)*V(:,j)-V(j,j);
|
||||
if nargout > 1
|
||||
%dq = dq-2*(nu2-x)*dV(:,j,:)-dV(j,j,:);
|
||||
%dq = dq-2*multiprod((nu2-x),dV(:,j,:))-dV(j,j,:);
|
||||
for jp=1:size(dV,3)
|
||||
dq(:,:,jp) = dq(:,:,jp)-2*(nu2-x)*dV(:,j,jp)-dV(j,j,jp);
|
||||
end
|
||||
end
|
||||
break
|
||||
else
|
||||
x(j) = 0;
|
||||
if rem(nu(j),2)==1
|
||||
p = -p;
|
||||
end
|
||||
%dq = dq+2*nu(j)*multiprod((nu2-x),dV(:,j,:))-nu(j)^2*dV(j,j,:);
|
||||
for jp=1:size(dV,3)
|
||||
dq(:,:,jp) = dq(:,:,jp)+2*nu(j)*(nu2-x)*dV(:,j,jp)-nu(j)^2*dV(j,j,jp);
|
||||
end
|
||||
q = q+2*nu(j)*(nu2-x)*V(:,j)-nu(j)^2*V(j,j);
|
||||
x(j) = 0;
|
||||
if rem(nu(j),2)==1
|
||||
p = -p;
|
||||
end
|
||||
if nargout > 1
|
||||
%dq = dq+2*nu(j)*multiprod((nu2-x),dV(:,j,:))-nu(j)^2*dV(j,j,:);
|
||||
for jp=1:size(dV,3)
|
||||
dq(:,:,jp) = dq(:,:,jp)+2*nu(j)*(nu2-x)*dV(:,j,jp)-nu(j)^2*dV(j,j,jp);
|
||||
end
|
||||
end
|
||||
q = q+2*nu(j)*(nu2-x)*V(:,j)-nu(j)^2*V(j,j);
|
||||
end
|
||||
end
|
||||
end
|
||||
dy = dy/prod([1:s2]);
|
||||
dy = reshape(dy,1,size(dV,3));
|
||||
y = y/prod([1:s2]);
|
||||
if nargout > 1
|
||||
dy = dy/prod([1:s2]);
|
||||
dy = reshape(dy,1,size(dV,3));
|
||||
end
|
File diff suppressed because it is too large
Load Diff
|
@ -1,46 +1,54 @@
|
|||
% By Willi Mutschler, September 26, 2016. Email: willi@mutschler.eu
|
||||
% Quadruplication Matrix as defined by
|
||||
% Meijer (2005) - Matrix algebra for higher order moments. Linear Algebra and its Applications, 410,pp. 112–134
|
||||
function [QP,QPinv] = quadruplication(p)
|
||||
% Computes the Quadruplication Matrix QP (and its Moore-Penrose inverse)
|
||||
% such that for any p-dimensional vector x:
|
||||
% y=kron(kron(kron(x,x),x),x)=QP*z
|
||||
% where z is of dimension np=p*(p+1)*(p+2)*(p+3)/2 and is obtained from y
|
||||
% by removing each second and later occurence of the same element.
|
||||
% This is a generalization of the Duplication matrix.
|
||||
% Reference: Meijer (2005) - Matrix algebra for higher order moments.
|
||||
% Linear Algebra and its Applications, 410,pp. 112-134
|
||||
% =========================================================================
|
||||
% INPUTS
|
||||
% * p [integer] size of vector
|
||||
% -------------------------------------------------------------------------
|
||||
% OUTPUTS
|
||||
% * QP [p^4 by np] Quadruplication matrix
|
||||
% * QPinv [np by np] Moore-Penrose inverse of QP
|
||||
% -------------------------------------------------------------------------
|
||||
% This function is called by
|
||||
% * pruned_state_space_system.m
|
||||
% -------------------------------------------------------------------------
|
||||
% This function calls
|
||||
% * mue (embedded)
|
||||
% * uperm
|
||||
% =========================================================================
|
||||
% Copyright (C) 2020 Dynare Team
|
||||
%
|
||||
% Inputs:
|
||||
% p: size of vector
|
||||
% Outputs:
|
||||
% QP: quadruplication matrix
|
||||
% QPinv: Moore-Penrose inverse of QP
|
||||
% This file is part of Dynare.
|
||||
%
|
||||
function [QP,QPinv] = quadruplication(p,progress,sparseflag)
|
||||
|
||||
if nargin <2
|
||||
progress =0;
|
||||
end
|
||||
if nargin < 3
|
||||
sparseflag = 1;
|
||||
end
|
||||
reverseStr = ''; counti=1;
|
||||
% 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/>.
|
||||
% =========================================================================
|
||||
np = p*(p+1)*(p+2)*(p+3)/24;
|
||||
|
||||
if sparseflag
|
||||
QP = spalloc(p^4,p*(p+1)*(p+2)*(p+3)/24,p^4);
|
||||
else
|
||||
QP = zeros(p^4,p*(p+1)*(p+2)*(p+3)/24);
|
||||
end
|
||||
QP = spalloc(p^4,np,p^4);
|
||||
if nargout > 1
|
||||
if sparseflag
|
||||
QPinv = spalloc(p*(p+1)*(p+2)*(p+3)/24,p*(p+1)*(p+2)*(p+3)/24,p^4);
|
||||
else
|
||||
QPinv = zeros(p*(p+1)*(p+2)*(p+3)/24,p*(p+1)*(p+2)*(p+3)/24);
|
||||
end
|
||||
QPinv = spalloc(np,np,p^4);
|
||||
end
|
||||
|
||||
counti = 1;
|
||||
for l=1:p
|
||||
for k=l:p
|
||||
for j=k:p
|
||||
for i=j:p
|
||||
if progress && (rem(counti,100)== 0)
|
||||
msg = sprintf(' Quadruplication Matrix Processed %d/%d', counti, np); fprintf([reverseStr, msg]); reverseStr = repmat(sprintf('\b'), 1, length(msg));
|
||||
elseif progress && (counti==np)
|
||||
msg = sprintf(' Quadruplication Matrix Processed %d/%d\n', counti, np); fprintf([reverseStr, msg]); reverseStr = repmat(sprintf('\b'), 1, length(msg));
|
||||
end
|
||||
idx = uperm([i j k l]);
|
||||
for r = 1:size(idx,1)
|
||||
ii = idx(r,1); jj= idx(r,2); kk=idx(r,3); ll=idx(r,4);
|
||||
|
@ -75,6 +83,7 @@ end
|
|||
%QPinv = (transpose(QP)*QP)\transpose(QP);
|
||||
|
||||
function m = mue(p,i,j,k,l)
|
||||
% Auxiliary expression, see page 118 of Meijer (2005)
|
||||
m = i + (j-1)*p + 1/2*(k-1)*p^2 + 1/6*(l-1)*p^3 - 1/2*j*(j-1) + 1/6*k*(k-1)*(k-2) - 1/24*l*(l-1)*(l-2)*(l-3) - 1/2*(k-1)^2*p + 1/6*(l-1)^3*p - 1/4*(l-1)*(l-2)*p^2 - 1/4*l*(l-1)*p + 1/6*(l-1)*p;
|
||||
m = round(m);
|
||||
end
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
function p = uperm(a)
|
||||
% Return all unique permutations of possibly-repeating array elements
|
||||
% =========================================================================
|
||||
% Copyright (C) 2014 Bruno Luong <brunoluong@yahoo.com>
|
||||
% Copyright (C) 2020 Dynare Team
|
||||
|
|
|
@ -126,6 +126,7 @@ wsOct
|
|||
!/practicing/dataHST.mat
|
||||
!/practicing/data_consRicardoypg.mat
|
||||
!/practicing/datasaver.m
|
||||
!/pruning/Andreasen_et_al_2018_Dynare44Pruning_v2.mat
|
||||
!/utils/printMakeCheckMatlabErrMsg.m
|
||||
!/utils/printMakeCheckOctaveErrMsg.m
|
||||
!/prior_posterior_function/posterior_function_demo.m
|
||||
|
|
|
@ -21,6 +21,7 @@ MODFILES = \
|
|||
analytic_derivatives/fs2000_analytic_derivation.mod \
|
||||
analytic_derivatives/BrockMirman_PertParamsDerivs.mod \
|
||||
analytic_derivatives/burnside_3_order_PertParamsDerivs.mod \
|
||||
pruning/AnSchorfheide_pruned_state_space.mod \
|
||||
measurement_errors/fs2000_corr_me_ml_mcmc/fs2000_corr_ME.mod \
|
||||
TeX/fs2000_corr_ME.mod \
|
||||
estimation/MH_recover/fs2000_recover_tarb.mod \
|
||||
|
@ -716,6 +717,10 @@ analytic_derivatives: m/analytic_derivatives o/analytic_derivatives
|
|||
m/analytic_derivatives: $(patsubst %.mod, %.m.trs, $(filter analytic_derivatives/%.mod, $(MODFILES)))
|
||||
o/analytic_derivatives: $(patsubst %.mod, %.o.trs, $(filter analytic_derivatives/%.mod, $(MODFILES)))
|
||||
|
||||
pruning: m/pruning o/pruning
|
||||
m/pruning: $(patsubst %.mod, %.m.trs, $(filter pruning/%.mod, $(MODFILES)))
|
||||
o/pruning: $(patsubst %.mod, %.o.trs, $(filter pruning/%.mod, $(MODFILES)))
|
||||
|
||||
fs2000: m/fs2000 o/fs2000
|
||||
m/fs2000: $(patsubst %.mod, %.m.trs, $(filter fs2000/%.mod, $(MODFILES)))
|
||||
o/fs2000: $(patsubst %.mod, %.o.trs, $(filter fs2000/%.mod, $(MODFILES)))
|
||||
|
@ -837,6 +842,7 @@ EXTRA_DIST = \
|
|||
gsa/data_ca1.mat \
|
||||
analytic_derivatives/fsdat_simul.m \
|
||||
analytic_derivatives/nBrockMirmanSYM.mat \
|
||||
pruning/Andreasen_et_al_2018_Dynare44Pruning_v2.mat \
|
||||
fs2000/fsdat_simul.m \
|
||||
fs2000/fsdat_simul_dseries.m \
|
||||
fs2000/fsdat_simul_missing_obs.m \
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
% This mod file compares the functionality of Dynare's pruned_state_space.m with the
|
||||
% external Dynare pruning toolbox of Andreasen, Fernández-Villaverde and Rubio-Ramírez (2018):
|
||||
% "The Pruned State-Space System for Non-Linear DSGE Models: Theory and Empirical Applications",
|
||||
% Review of Economic Studies, Volume 85, Issue 1, Pages 1–49.
|
||||
% The model under study is taken from An and Schorfheide (2007): "Bayesian Analysis of DSGE Models",
|
||||
% Econometric Reviews, Volume 26, Issue 2-4, Pages 113-172.
|
||||
% Note that we use version 2 of the toolbox, i.e. the one which is called
|
||||
% "Third-order GMM estimate package for DSGE models (version 2)" and can be
|
||||
% downloaded from https://sites.google.com/site/mandreasendk/home-1
|
||||
%
|
||||
% Created by @wmutschl (Willi Mutschler, willi@mutschler.eu)
|
||||
%
|
||||
% =========================================================================
|
||||
% Copyright (C) 2020 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/>.
|
||||
% =========================================================================
|
||||
|
||||
% set this to 1 if you want to recompute using the Andreasen et al toolbox
|
||||
% otherwise the results are loaded from Andreasen_et_al_2018_Dynare44Pruning_v2.mat
|
||||
@#define Andreasen_et_al_toolbox = 0
|
||||
|
||||
var YGR INFL INT
|
||||
c p R g y z; %if ordering of var is changed comparison code below needs to be adapted
|
||||
varexo e_r e_g e_z;
|
||||
parameters tau nu kap cyst psi1 psi2 rhor rhog rhoz rrst pist gamst;
|
||||
|
||||
tau = 2;
|
||||
nu = 0.1;
|
||||
kap = 0.33;
|
||||
cyst = 0.85;
|
||||
psi1 = 1.5;
|
||||
psi2 = 0.125;
|
||||
rhor = 0.75;
|
||||
rhog = 0.95;
|
||||
rhoz = 0.9;
|
||||
rrst = 1;
|
||||
pist = 3.2;
|
||||
gamst = 0.55;
|
||||
sig_r = .2;
|
||||
sig_g = .6;
|
||||
sig_z = .3;
|
||||
|
||||
model;
|
||||
#pist2 = exp(pist/400);
|
||||
#rrst2 = exp(rrst/400);
|
||||
#bet = 1/rrst2;
|
||||
#phi = tau*(1-nu)/nu/kap/pist2^2;
|
||||
#gst = 1/cyst;
|
||||
#cst = (1-nu)^(1/tau);
|
||||
#yst = cst*gst;
|
||||
#dy = y-y(-1);
|
||||
1 = exp(-tau*c(+1)+tau*c+R-z(+1)-p(+1));
|
||||
(1-nu)/nu/phi/(pist2^2)*(exp(tau*c)-1) = (exp(p)-1)*((1-1/2/nu)*exp(p)+1/2/nu) - bet*(exp(p(+1))-1)*exp(-tau*c(+1)+tau*c+y(+1)-y+p(+1));
|
||||
exp(c-y) = exp(-g) - phi*pist2^2*gst/2*(exp(p)-1)^2;
|
||||
R = rhor*R(-1) + (1-rhor)*psi1*p + (1-rhor)*psi2*(y-g) + e_r;
|
||||
g = rhog*g(-1) + e_g;
|
||||
z = rhoz*z(-1) + e_z;
|
||||
YGR = gamst+100*(dy+z);
|
||||
INFL = pist+400*p;
|
||||
INT = pist+rrst+4*gamst+400*R;
|
||||
end;
|
||||
|
||||
shocks;
|
||||
var e_r = sig_r^2;
|
||||
var e_g = sig_g^2;
|
||||
var e_z = sig_z^2;
|
||||
end;
|
||||
|
||||
steady_state_model;
|
||||
y = 0;
|
||||
R = 0;
|
||||
g = 0;
|
||||
z = 0;
|
||||
c = 0;
|
||||
p = 0;
|
||||
YGR = gamst;
|
||||
INFL = pist;
|
||||
INT = pist + rrst + 4*gamst;
|
||||
end;
|
||||
|
||||
steady; check; model_diagnostics;
|
||||
|
||||
@#for orderApp in [1, 2, 3]
|
||||
stoch_simul(order=@{orderApp},pruning,irf=0,periods=0);
|
||||
pruned_state_space.order_@{orderApp} = pruned_state_space_system(M_, options_, oo_.dr, [], options_.ar, 1, 0);
|
||||
@#if Andreasen_et_al_toolbox
|
||||
addpath('Dynare44Pruning_v2/simAndMoments3order'); %provide path to toolbox
|
||||
optPruning.orderApp = @{orderApp};
|
||||
outAndreasenetal.order_@{orderApp} = RunDynarePruning(optPruning,oo_,M_,[oo_.dr.ghx oo_.dr.ghu]);
|
||||
rmpath('Dynare44Pruning_v2/simAndMoments3order');
|
||||
close all;
|
||||
@#endif
|
||||
@#endfor
|
||||
|
||||
@#if Andreasen_et_al_toolbox
|
||||
delete Andreasen_et_al_2018_Dynare44Pruning_v2.mat;
|
||||
pause(3);
|
||||
save('Andreasen_et_al_2018_Dynare44Pruning_v2.mat', 'outAndreasenetal')
|
||||
pause(3);
|
||||
@#endif
|
||||
|
||||
load('Andreasen_et_al_2018_Dynare44Pruning_v2.mat')
|
||||
|
||||
% Make comparisons only at orders 1 and 2
|
||||
for iorder = 1:3
|
||||
fprintf('ORDER %d:\n',iorder);
|
||||
pruned = pruned_state_space.(sprintf('order_%d',iorder));
|
||||
outAndreasen = outAndreasenetal.(sprintf('order_%d',iorder));
|
||||
%make sure variable ordering is correct
|
||||
if ~isequal(M_.endo_names,[outAndreasen.label_y; outAndreasen.label_v(1:M_.nspred)])
|
||||
error('variable ordering is not the same, change declaration order');
|
||||
end
|
||||
norm_E_yx = norm(pruned.E_y(oo_.dr.inv_order_var) - [outAndreasen.Mean_y; outAndreasen.Mean_v(1:M_.nspred)] , Inf);
|
||||
fprintf('max(sum(abs(E[y;x]''))): %d\n',norm_E_yx);
|
||||
norm_Var_y = norm(pruned.Var_y(oo_.dr.inv_order_var(1:(M_.endo_nbr-M_.nspred)),oo_.dr.inv_order_var(1:(M_.endo_nbr-M_.nspred))) - outAndreasen.Var_y , Inf);
|
||||
fprintf('max(sum(abs(Var[y]''))):: %d\n',norm_Var_y);
|
||||
norm_Var_x = norm(pruned.Var_y(M_.nstatic+(1:M_.nspred),M_.nstatic+(1:M_.nspred)) - outAndreasen.Var_v(1:M_.nspred,1:M_.nspred) , Inf);
|
||||
fprintf('max(sum(abs(Var[x]''))): %d\n',norm_Var_x);
|
||||
norm_Corr_yi1 = norm(pruned.Corr_yi(oo_.dr.inv_order_var(1:(M_.endo_nbr-M_.nspred)),oo_.dr.inv_order_var(1:(M_.endo_nbr-M_.nspred)),1) - outAndreasen.Corr_y(:,:,1) , Inf);
|
||||
fprintf('max(sum(abs(Corr[y,y(-1)]''))): %d\n',norm_Corr_yi1);
|
||||
norm_Corr_yi2 = norm(pruned.Corr_yi(oo_.dr.inv_order_var(1:(M_.endo_nbr-M_.nspred)),oo_.dr.inv_order_var(1:(M_.endo_nbr-M_.nspred)),2) - outAndreasen.Corr_y(:,:,2) , Inf);
|
||||
fprintf('max(sum(abs(Corr[y,y(-2)]''))): %d\n',norm_Corr_yi2);
|
||||
norm_Corr_xi1 = norm(pruned.Corr_yi(M_.nstatic+(1:M_.nspred),M_.nstatic+(1:M_.nspred),1) - outAndreasen.Corr_v(1:M_.nspred,1:M_.nspred,1) , Inf);
|
||||
fprintf('max(sum(abs(Corr[x,x(-1)]''))): %d\n',norm_Corr_xi1);
|
||||
norm_Corr_xi2 = norm(pruned.Corr_yi(M_.nstatic+(1:M_.nspred),M_.nstatic+(1:M_.nspred),2) - outAndreasen.Corr_v(1:M_.nspred,1:M_.nspred,2) , Inf);
|
||||
fprintf('max(sum(abs(Corr[x,x(-2)]''))): %d\n',norm_Corr_xi2);
|
||||
|
||||
if iorder < 3 && any([norm_E_yx norm_Var_y norm_Var_x norm_Corr_yi1 norm_Corr_yi2 norm_Corr_xi1 norm_Corr_xi2] > 1e-5)
|
||||
error('Something wrong with pruned_state_space.m compared to Andreasen et al 2018 Toolbox v2 at order %d.',iorder);
|
||||
end
|
||||
end
|
||||
skipline();
|
||||
fprintf('Note that at third order, there is an error in the computation of Var_z in Andreasen et al (2018)''s toolbox, @wmutschl is in contact to clarify this.\n');
|
||||
fprintf('EXAMPLE:\n')
|
||||
fprintf(' Consider Var[kron(kron(xf,xf),xf)] = E[kron(kron(kron(kron(kron(xf,xf),xf),xf),xf),xf)] - E[kron(kron(xf,xf),xf)]*E[kron(kron(xf,xf),xf)].''\n');
|
||||
fprintf(' Now note that xf=hx*xf(-1)+hu*u is Gaussian, that is E[kron(kron(xf,xf),xf)]=0, and Var[kron(kron(xf,xf),xf)] are the sixth-order product moments\n');
|
||||
fprintf(' which can be computed using the prodmom.m function by providing E[xf*xf''] as covariance matrix.\n');
|
||||
fprintf(' In order to replicate this you have to change UnconditionalMoments_3rd_Lyap.m to also output Var_z.\n')
|
||||
|
||||
dynare_nx = M_.nspred;
|
||||
dynare_E_xf2 = pruned_state_space.order_3.Var_z(1:dynare_nx,1:dynare_nx);
|
||||
dynare_E_xf6 = pruned_state_space.order_3.Var_z((end-dynare_nx^3+1):end,(end-dynare_nx^3+1):end);
|
||||
dynare_E_xf6 = dynare_E_xf6(:);
|
||||
|
||||
Andreasen_nx = M_.nspred+M_.exo_nbr;
|
||||
Andreasen_E_xf2 = outAndreasenetal.order_3.Var_z(1:Andreasen_nx,1:Andreasen_nx);
|
||||
Andreasen_E_xf6 = outAndreasenetal.order_3.Var_z((end-Andreasen_nx^3+1):end,(end-Andreasen_nx^3+1):end);
|
||||
Andreasen_E_xf6 = Andreasen_E_xf6(:);
|
||||
|
||||
fprintf('Second-order product moments of xf and u are the same:\n')
|
||||
norm_E_xf2 = norm(dynare_E_xf2-Andreasen_E_xf2(1:M_.nspred,1:M_.nspred),Inf)
|
||||
norm_E_uu = norm(M_.Sigma_e-Andreasen_E_xf2(M_.nspred+(1:M_.exo_nbr),M_.nspred+(1:M_.exo_nbr)),Inf)
|
||||
|
||||
% Compute unique sixth-order product moments of xf, i.e. unique(E[kron(kron(kron(kron(kron(xf,xf),xf),xf),xf),xf)],'stable')
|
||||
dynare_nx6 = dynare_nx*(dynare_nx+1)/2*(dynare_nx+2)/3*(dynare_nx+3)/4*(dynare_nx+4)/5*(dynare_nx+5)/6;
|
||||
dynare_Q6Px = Q6_plication(dynare_nx);
|
||||
dynare_COMBOS6 = flipud(allVL1(dynare_nx, 6)); %all possible (unique) combinations of powers that sum up to six
|
||||
dynare_true_E_xf6 = zeros(dynare_nx6,1); %only unique entries
|
||||
for j6 = 1:size(dynare_COMBOS6,1)
|
||||
dynare_true_E_xf6(j6) = prodmom(dynare_E_xf2, 1:dynare_nx, dynare_COMBOS6(j6,:));
|
||||
end
|
||||
dynare_true_E_xf6 = dynare_Q6Px*dynare_true_E_xf6; %add duplicate entries
|
||||
norm_dynare_E_xf6 = norm(dynare_true_E_xf6 - dynare_E_xf6, Inf);
|
||||
|
||||
Andreasen_nx6 = Andreasen_nx*(Andreasen_nx+1)/2*(Andreasen_nx+2)/3*(Andreasen_nx+3)/4*(Andreasen_nx+4)/5*(Andreasen_nx+5)/6;
|
||||
Andreasen_Q6Px = Q6_plication(Andreasen_nx);
|
||||
Andreasen_COMBOS6 = flipud(allVL1(Andreasen_nx, 6)); %all possible (unique) combinations of powers that sum up to six
|
||||
Andreasen_true_E_xf6 = zeros(Andreasen_nx6,1); %only unique entries
|
||||
for j6 = 1:size(Andreasen_COMBOS6,1)
|
||||
Andreasen_true_E_xf6(j6) = prodmom(Andreasen_E_xf2, 1:Andreasen_nx, Andreasen_COMBOS6(j6,:));
|
||||
end
|
||||
Andreasen_true_E_xf6 = Andreasen_Q6Px*Andreasen_true_E_xf6; %add duplicate entries
|
||||
norm_Andreasen_E_xf6 = norm(Andreasen_true_E_xf6 - Andreasen_E_xf6, Inf);
|
||||
|
||||
fprintf('Sixth-order product moments of xf and u are not the same!\n');
|
||||
fprintf(' Dynare maximum absolute deviations of sixth-order product moments of xf: %d\n',norm_dynare_E_xf6)
|
||||
fprintf(' Andreasen et al maximum absolute deviations of sixth-order product moments of xf: %d\n',norm_Andreasen_E_xf6)
|
||||
skipline();
|
||||
fprintf('Note that the standard deviations are set quite high to make the numerical differences more apparent.\n');
|
Binary file not shown.
Loading…
Reference in New Issue