2020-02-02 21:52:44 +01:00
|
|
|
function json = cherrypick(infile, outfold, eqtags, noresids, json)
|
2019-03-14 11:04:10 +01:00
|
|
|
|
|
|
|
% Extract some equations in infile (mod file used for estimation)
|
|
|
|
% and write them in outfile (mod file used for simulation).
|
|
|
|
%
|
|
|
|
% INPUTS
|
|
|
|
% - infile [string] Name of the mod file where all the equations used for estimation are available.
|
|
|
|
% - outfold [string] Name of the folder where the generated files are saveda subset of the equations is to be printed.
|
|
|
|
% - eqtags [cell] Equation tags of the selected equations.
|
|
|
|
% - noresids [logical] Removes estimation residuals (not to be used in simulation) if true.
|
2020-02-02 21:52:44 +01:00
|
|
|
% - json [char] Content of a JSON file.
|
2019-03-14 11:04:10 +01:00
|
|
|
%
|
|
|
|
% OUTPUTS
|
2020-02-02 21:52:44 +01:00
|
|
|
% - json [char] Content of a JSON file.
|
2019-03-14 11:04:10 +01:00
|
|
|
%
|
|
|
|
% SPECIAL REQUIREMENTS
|
|
|
|
% It is expected that the file infile.mod has already been run, and
|
|
|
|
% that the associated JSON output is available.
|
|
|
|
|
2021-02-04 15:43:10 +01:00
|
|
|
% Copyright © 2019-2021 Dynare Team
|
2019-03-14 11:04:10 +01:00
|
|
|
%
|
|
|
|
% 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
|
2021-06-09 17:33:48 +02:00
|
|
|
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
2019-03-14 11:04:10 +01:00
|
|
|
|
|
|
|
global M_
|
|
|
|
|
|
|
|
% Set default value
|
2020-02-02 21:52:44 +01:00
|
|
|
if nargin<4 || isempty(noresids)
|
2019-03-14 11:04:10 +01:00
|
|
|
noresids = true;
|
|
|
|
end
|
|
|
|
|
|
|
|
% Delete outfold subdirectory if it already exists
|
|
|
|
if exist(outfold, 'dir')
|
|
|
|
rmdir(outfold, 's');
|
|
|
|
end
|
|
|
|
|
|
|
|
% Create the subdirectoty where the generated files will be saved.
|
|
|
|
mkdir(outfold);
|
|
|
|
|
|
|
|
% Check that infile.mod and the related JSON output exist.
|
|
|
|
if ~exist(sprintf('%s.mod', infile), 'file')
|
|
|
|
error('Cannot find %s.mod.', infile)
|
|
|
|
end
|
|
|
|
if ~exist(sprintf('%s/model/json', infile), 'dir')
|
|
|
|
error('Cannot find %s/model/json folder. Did you run %s.mod with the json option?', infile, infile);
|
|
|
|
end
|
|
|
|
|
2019-04-02 18:06:47 +02:00
|
|
|
% Check if some variables have to be renamed.
|
|
|
|
rename = M_.equations_tags(strcmp('rename',M_.equations_tags(:,2)),[1,3]);
|
|
|
|
isrename = ~isempty(rename);
|
|
|
|
|
2020-02-02 21:52:44 +01:00
|
|
|
if nargin<5
|
|
|
|
% Load json file (original mod file)
|
|
|
|
json = loadjson_(sprintf('%s/model/json/modfile-original.json', M_.dname));
|
|
|
|
end
|
2019-03-22 11:29:59 +01:00
|
|
|
|
2019-03-14 11:04:10 +01:00
|
|
|
% Create a new file.
|
|
|
|
fid = fopen(sprintf('%s/model.inc', outfold), 'w');
|
|
|
|
|
|
|
|
plist = {};
|
|
|
|
elist = {};
|
|
|
|
xlist = {};
|
|
|
|
|
|
|
|
for i=1:length(eqtags)
|
2019-03-21 17:33:07 +01:00
|
|
|
rhs = [];
|
|
|
|
lhs = [];
|
2019-03-22 11:29:59 +01:00
|
|
|
% Get equation number.
|
2020-02-02 21:14:23 +01:00
|
|
|
eqnum = get_equation_number_by_tag(eqtags{i}, M_);
|
2019-03-14 11:04:10 +01:00
|
|
|
% Get the original equation.
|
2020-02-02 21:52:44 +01:00
|
|
|
[LHS, RHS] = get_lhs_and_rhs(eqtags{i}, M_, true, json);
|
2019-03-14 11:04:10 +01:00
|
|
|
% Get the parameters, endogenous and exogenous variables in the current equation.
|
2020-01-22 16:03:50 +01:00
|
|
|
[pnames, ~, xnames] = get_variables_and_parameters_in_equation(LHS, RHS, M_);
|
2020-01-29 18:34:26 +01:00
|
|
|
lhs_expression = LHS;
|
2020-01-22 16:03:50 +01:00
|
|
|
LHS = get_variables_and_parameters_in_expression(LHS);
|
|
|
|
enames = LHS;
|
|
|
|
if length(LHS)>1
|
|
|
|
error('Expressions with more than one variable on the LHS are not allowed.')
|
|
|
|
end
|
|
|
|
LHS = LHS{1};
|
2019-04-02 18:06:47 +02:00
|
|
|
if isrename
|
|
|
|
[variable_has_to_be_renamed, id] = ismember(eqnum, [rename{:,1}]);
|
|
|
|
if variable_has_to_be_renamed
|
2020-01-31 18:46:27 +01:00
|
|
|
TMP = strsplit(rename{id,2}, ',');
|
|
|
|
for j=1:length(TMP)
|
|
|
|
tmp = strsplit(TMP{j}, '->');
|
|
|
|
lhs_expression = exactstrrep(lhs_expression, tmp{1}, tmp{2});
|
|
|
|
RHS = exactstrrep(RHS, tmp{1}, tmp{2});
|
|
|
|
rep = strcmp(tmp{1}, enames);
|
|
|
|
if any(rep)
|
|
|
|
enames(rep) = tmp(2);
|
|
|
|
end
|
|
|
|
rep = strcmp(tmp{1}, xnames);
|
|
|
|
if any(rep)
|
|
|
|
xnames(rep) = tmp(2);
|
|
|
|
end
|
2019-04-02 18:06:47 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2019-03-14 11:04:10 +01:00
|
|
|
% Remove residual from equation if required.
|
|
|
|
if noresids
|
|
|
|
exogenous_variables_to_be_removed = ~ismember(xnames, M_.simulation_exo_names);
|
|
|
|
if any(exogenous_variables_to_be_removed)
|
|
|
|
switch sum(exogenous_variables_to_be_removed)
|
|
|
|
case 1
|
2021-02-04 15:43:10 +01:00
|
|
|
RHS = regexprep(RHS, sprintf('\\ *\\+\\ *%s', xnames{exogenous_variables_to_be_removed}), '');
|
2019-04-02 15:40:43 +02:00
|
|
|
RHS = regexprep(RHS, sprintf('%s', xnames{exogenous_variables_to_be_removed}), '');
|
2019-03-14 11:04:10 +01:00
|
|
|
case 0
|
|
|
|
% Nothing to do.
|
|
|
|
otherwise
|
|
|
|
error('Cannot remove more than one exogenous variable in an equation (%s).', eqtags{i})
|
|
|
|
end
|
|
|
|
xnames = setdiff(xnames, xnames{exogenous_variables_to_be_removed});
|
|
|
|
end
|
|
|
|
end
|
|
|
|
% Unroll expectation terms if any.
|
|
|
|
isvar = regexp(RHS, 'var_expectation\(model_name = (?<name>\w+)\)', 'names');
|
|
|
|
ispac = regexp(RHS, 'pac_expectation\(model_name = (?<name>\w+)\)', 'names');
|
|
|
|
if ~isempty(isvar)
|
2019-03-21 17:33:07 +01:00
|
|
|
rhs = write_expectations(eqtags{i}, isvar.name, 'var');
|
2019-05-20 14:44:28 +02:00
|
|
|
lhs = sprintf('%s_VE', eqtags{i});
|
2019-03-21 17:33:07 +01:00
|
|
|
RHS = strrep(RHS, sprintf('var_expectation(model_name = %s)', isvar.name), lhs);
|
2020-01-22 16:03:50 +01:00
|
|
|
end
|
|
|
|
if ~isempty(ispac)
|
|
|
|
[rhs, growthneutralitycorrection] = write_expectations(eqtags{i}, ispac.name, 'pac');
|
|
|
|
lhs = sprintf('%s_PE', eqtags{i});
|
|
|
|
RHS = strrep(RHS, sprintf('pac_expectation(model_name = %s)', ispac.name), lhs);
|
|
|
|
if ~isempty(growthneutralitycorrection)
|
|
|
|
RHS = sprintf('%s + %s', RHS, growthneutralitycorrection);
|
2019-03-21 17:33:07 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
% Print equation for unrolled PAC/VAR-expectation and update
|
|
|
|
% list of parameters and endogenous variables (if any).
|
|
|
|
if ~isempty(rhs)
|
2019-03-28 11:18:42 +01:00
|
|
|
% Note that the call to get_variables_and_parameters_in_equation()
|
|
|
|
% will not return the lhs variable in expectation_enames since
|
|
|
|
% the name is created on the fly and is not a member of M_.endo_names.
|
2020-01-30 19:21:50 +01:00
|
|
|
expectation_pnames = get_variables_and_parameters_in_equation('', rhs, M_);
|
2020-01-22 16:03:50 +01:00
|
|
|
expectation_enames = get_variables_and_parameters_in_expression(lhs);
|
2020-01-30 19:21:50 +01:00
|
|
|
expectation_xnames = get_variables_and_parameters_in_expression(rhs);
|
2019-03-21 17:33:07 +01:00
|
|
|
pnames = union(pnames, expectation_pnames);
|
2020-01-30 19:21:50 +01:00
|
|
|
xnames = union(xnames, setdiff(expectation_xnames, expectation_pnames));
|
2019-03-21 17:33:07 +01:00
|
|
|
enames = union(enames, expectation_enames);
|
2019-07-19 21:33:13 +02:00
|
|
|
fprintf(fid, '[name=''%s'']\n', lhs);
|
2019-03-21 17:33:07 +01:00
|
|
|
fprintf(fid, '%s = %s;\n\n', lhs, rhs);
|
2020-01-22 16:03:50 +01:00
|
|
|
else
|
2020-01-30 19:21:50 +01:00
|
|
|
pRHS = get_variables_and_parameters_in_equation('', RHS, M_);
|
|
|
|
xRHS = get_variables_and_parameters_in_expression(RHS);
|
|
|
|
xnames = union(xnames, setdiff(xRHS, pRHS));
|
2020-01-22 16:03:50 +01:00
|
|
|
pnames = union(pnames, pRHS);
|
2019-03-21 17:33:07 +01:00
|
|
|
end
|
|
|
|
% Update pnames, enames and xnames if PAC with growth neutrality correction.
|
|
|
|
if ~isempty(ispac) && ~isempty(growthneutralitycorrection)
|
|
|
|
[growthneutralitycorrection_pnames, ...
|
|
|
|
growthneutralitycorrection_enames, ...
|
|
|
|
growthneutralitycorrection_xnames] = get_variables_and_parameters_in_equation('', growthneutralitycorrection, M_);
|
|
|
|
if ~isempty(growthneutralitycorrection_pnames)
|
|
|
|
pnames = union(pnames, growthneutralitycorrection_pnames);
|
|
|
|
end
|
|
|
|
if ~isempty(growthneutralitycorrection_enames)
|
2020-01-22 16:03:50 +01:00
|
|
|
xnames = union(xnames, growthneutralitycorrection_enames);
|
2019-03-21 17:33:07 +01:00
|
|
|
end
|
|
|
|
if ~isempty(growthneutralitycorrection_xnames)
|
|
|
|
xnames = union(xnames, growthneutralitycorrection_xnames);
|
2019-03-14 11:04:10 +01:00
|
|
|
end
|
|
|
|
end
|
2019-03-22 11:29:59 +01:00
|
|
|
% Print tags
|
2020-02-02 21:52:44 +01:00
|
|
|
if iscell(json.model)
|
|
|
|
tfields = fieldnames(json.model{eqnum}.tags);
|
|
|
|
tags = sprintf('%s=''%s''', tfields{1}, json.model{eqnum}.tags.(tfields{1}));
|
2020-01-28 16:36:40 +01:00
|
|
|
for j=2:length(tfields)
|
2020-02-02 21:52:44 +01:00
|
|
|
if ~isempty(json.model{eqnum}.tags.(tfields{j}))
|
|
|
|
tags = sprintf('%s, %s=''%s''', tags, tfields{j}, json.model{eqnum}.tags.(tfields{j}));
|
2020-01-28 16:36:40 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
2020-02-02 21:52:44 +01:00
|
|
|
tfields = fieldnames(json.model.tags);
|
|
|
|
tags = sprintf('%s=''%s''', tfields{1}, json.model.tags.(tfields{1}));
|
2020-01-28 16:36:40 +01:00
|
|
|
for j=2:length(tfields)
|
2020-02-02 21:52:44 +01:00
|
|
|
if ~isempty(json.model.tags.(tfields{j}))
|
|
|
|
tags = sprintf('%s, %s=''%s''', tags, tfields{j}, json.model.tags.(tfields{j}));
|
2020-01-28 16:36:40 +01:00
|
|
|
end
|
2019-03-22 11:29:59 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
fprintf(fid, '[%s]\n', tags);
|
2019-03-14 11:04:10 +01:00
|
|
|
% Print equation.
|
2020-01-29 18:34:26 +01:00
|
|
|
fprintf(fid, '%s = %s;\n\n', lhs_expression, RHS);
|
2019-03-14 11:04:10 +01:00
|
|
|
% Update lists of parameters, endogenous variables and exogenous variables.
|
|
|
|
plist = union(plist, pnames);
|
|
|
|
elist = union(elist, enames);
|
|
|
|
xlist = union(xlist, xnames);
|
|
|
|
end
|
|
|
|
fclose(fid);
|
|
|
|
|
2019-03-22 14:39:40 +01:00
|
|
|
% Export parameters
|
2019-04-26 18:46:34 +02:00
|
|
|
if ~isempty(plist)
|
|
|
|
fid = fopen(sprintf('%s/parameters.inc', outfold), 'w');
|
|
|
|
fprintf(fid, 'parameters %s;', sprintf('%s ', plist{:}));
|
|
|
|
fclose(fid);
|
|
|
|
end
|
2019-03-14 11:04:10 +01:00
|
|
|
|
2019-03-22 14:39:40 +01:00
|
|
|
% Export endogegnous variables
|
2019-03-14 11:04:10 +01:00
|
|
|
fid = fopen(sprintf('%s/endogenous.inc', outfold), 'w');
|
2020-01-30 20:31:21 +01:00
|
|
|
printlistofvariables(fid, 'endo', elist, M_, elist);
|
2019-03-14 11:04:10 +01:00
|
|
|
fclose(fid);
|
|
|
|
|
2019-03-22 14:39:40 +01:00
|
|
|
% Export exogenous variables
|
2019-04-26 18:46:34 +02:00
|
|
|
if ~isempty(xlist)
|
|
|
|
fid = fopen(sprintf('%s/exogenous.inc', outfold), 'w');
|
2020-01-30 20:31:21 +01:00
|
|
|
printlistofvariables(fid, 'exo', xlist, M_, xlist);
|
2019-04-26 18:46:34 +02:00
|
|
|
fclose(fid);
|
|
|
|
end
|
2019-03-22 14:39:40 +01:00
|
|
|
|
2019-04-02 07:11:32 +02:00
|
|
|
% Export parameter values
|
2019-04-26 18:46:34 +02:00
|
|
|
if ~isempty(plist)
|
|
|
|
fid = fopen(sprintf('%s/parameter-values.inc', outfold), 'w');
|
|
|
|
for i=1:length(plist)
|
|
|
|
id = strcmp(plist{i}, M_.param_names);
|
|
|
|
if any(id)
|
|
|
|
fprintf(fid, '%s = %s;\n', plist{i}, num2str(M_.params(id), 16));
|
|
|
|
end
|
2019-04-02 07:11:32 +02:00
|
|
|
end
|
2019-04-26 18:46:34 +02:00
|
|
|
fclose(fid);
|
2019-04-02 07:11:32 +02:00
|
|
|
end
|
2019-03-22 14:39:40 +01:00
|
|
|
|
2019-04-02 18:06:47 +02:00
|
|
|
function printlistofvariables(fid, kind, list, DynareModel, vappend)
|
2019-03-22 14:39:40 +01:00
|
|
|
if isfield(DynareModel, sprintf('%s_partitions', kind))
|
|
|
|
% Some endogenous variables are tagged.
|
|
|
|
switch kind
|
|
|
|
case 'exo'
|
|
|
|
tfields = fieldnames(DynareModel.exo_partitions);
|
|
|
|
vlist = 'varexo';
|
|
|
|
vnames = DynareModel.exo_names;
|
|
|
|
partitions = DynareModel.exo_partitions;
|
|
|
|
case 'endo'
|
|
|
|
tfields = fieldnames(DynareModel.endo_partitions);
|
|
|
|
vlist = 'var';
|
|
|
|
vnames = DynareModel.endo_names(1:DynareModel.orig_endo_nbr);
|
|
|
|
partitions = DynareModel.endo_partitions;
|
|
|
|
otherwise
|
|
|
|
error('Illegal value for second input argument.')
|
|
|
|
end
|
|
|
|
for i = 1:length(list)
|
|
|
|
id = strmatch(list{i}, vnames, 'exact');
|
|
|
|
if ~isempty(id)
|
|
|
|
tags = '';
|
|
|
|
for j=1:length(tfields)
|
|
|
|
if ~isempty(partitions.(tfields{j}){id})
|
|
|
|
tags = sprintf('%s, %s=''%s''', tags, tfields{j}, partitions.(tfields{j}){id});
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if ~isempty(tags)
|
|
|
|
tags = sprintf('(%s)', tags(3:end));
|
|
|
|
end
|
2019-04-02 18:06:47 +02:00
|
|
|
elseif ~isempty(strmatch(list{i}, vappend, 'exact'))
|
2019-04-02 21:31:45 +02:00
|
|
|
% Nothing to do, this variable was renamed by cherrypick
|
|
|
|
tags = '';
|
2019-03-25 17:42:01 +01:00
|
|
|
else
|
2019-05-20 14:44:28 +02:00
|
|
|
if isequal(kind, 'endo') && (isequal(list{i}(end-2:end), '_PE') || isequal(list{i}(end-2:end), '_VE'))
|
|
|
|
if isequal(list{i}(end-2:end), '_PE')
|
2019-05-04 08:50:13 +02:00
|
|
|
tags = sprintf('(expectation_kind=''%s'')', 'pac');
|
2019-04-02 22:57:45 +02:00
|
|
|
else
|
2019-05-04 08:50:13 +02:00
|
|
|
tags = sprintf('(expectation_kind=''%s'')', 'var');
|
2019-04-02 22:57:45 +02:00
|
|
|
end
|
2019-03-22 14:39:40 +01:00
|
|
|
else
|
2019-03-25 17:42:01 +01:00
|
|
|
error('Unknown variable.')
|
2019-03-22 14:39:40 +01:00
|
|
|
end
|
|
|
|
end
|
2019-03-25 17:42:01 +01:00
|
|
|
if isempty(tags)
|
|
|
|
vlist = sprintf('%s\n\t%s', vlist, list{i});
|
|
|
|
else
|
|
|
|
vlist = sprintf('%s\n\t%s %s', vlist, list{i}, tags);
|
|
|
|
end
|
2019-03-22 14:39:40 +01:00
|
|
|
end
|
|
|
|
fprintf(fid, '%s;', vlist);
|
|
|
|
else
|
|
|
|
switch kind
|
|
|
|
case 'exo'
|
2019-04-11 10:42:50 +02:00
|
|
|
vlist = 'varexo';
|
2019-03-22 14:39:40 +01:00
|
|
|
case 'endo'
|
2019-04-11 10:42:50 +02:00
|
|
|
vlist = 'var';
|
2019-03-22 14:39:40 +01:00
|
|
|
otherwise
|
|
|
|
error('Illegal value for second input argument.')
|
|
|
|
end
|
2019-04-11 10:42:50 +02:00
|
|
|
for i=1:length(list)
|
|
|
|
vlist = sprintf('%s\n\t%s', vlist, list{i});
|
|
|
|
end
|
|
|
|
fprintf(fid, '%s;', vlist);
|
2021-02-04 15:43:10 +01:00
|
|
|
end
|