aggregate.m 9.03 KB
Newer Older
1
function aggregate(ofile, dynopt, rootfolder, varargin)
2
3
4

% Agregates cherry-picked models.

5
% Copyright (C) 2019-2021 Dynare Team
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
%
% 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/>.

22
MAX_NUMBER_OF_ELEMENTS = 10000;
23
24
25

warning off MATLAB:subscripting:noSubscriptsSpecified

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
if ~isempty(dynopt)
    % Should be a list of options for the preprocessor in a cell
    % array.
    firstline = '// --+ options:';
    if iscell(dynopt)
        for i = 1:length(dynopt)
            firstline = sprintf('%s %s', firstline, dynopt{i});
        end
        firstline = sprintf('%s %s', firstline, '+--');
    else
        error('Second argument has to be a cell array (list of options for dynare preprocessor).')
    end
else
    firstline = '';
end

42
43
44
45

% Get parameters.
for i=1:length(varargin)
    fid = fopen(sprintf('%s/parameters.inc', varargin{i}));
46
47
48
49
50
    if fid<0
        % No parameters in the cherrypicked (sub)model, go to the
        % next cherrypicked model.
        continue
    end
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    statement = fgetl(fid);
    if exist('plist', 'var')
        plist = union(plist, strsplit(statement, {'parameters', ' ', ';'}));
    else
        plist = strsplit(statement, {'parameters', ' ', ';'});
    end
    plist(cellfun(@(x) all(isempty(x)), plist)) = [];
    fclose(fid);
end

% Get equations
eqlist = cell(MAX_NUMBER_OF_ELEMENTS, 4);
tagnum = 1;
eqnum = 0;
for i=1:length(varargin)
66
67
68
69
70
71
72
73
74
75
76
    % Store all non-empty lines of model.inc in the “model” cell-array
    fid = fopen(sprintf('%s/model.inc', varargin{i}));
    model = {};
    while ~feof(fid)
        line = fgetl(fid);
        if ~isempty(line)
            model{end+1} = line;
        end
    end
    fclose(fid);

77
78
79
80
81
82
    eqtag = false;
    for j=1:length(model)
        if isequationtag(model{j})
            if eqtag
                error('An equation tag must be followed by an equation.')
            end
83
84
85
86
87
            % Ensure that the equation tag name matches the LHS variable.
            eqtagname = regexp(model{j}, 'name=''(\w*)''', 'match');
            [lhs, ~] = getequation(model{j+1});
            endovar = getendovar(lhs);
            eqtagname_ = strcat('name=''', endovar{1}, '''');
88
89
90
91
92
93
            if ~isempty(eqtagname)
                if ~isequal(eqtagname{1}, eqtagname_)
                    model{j} = strrep(model{j}, eqtagname{1}, eqtagname_);
                end
            else
                model{j} = eqtagname_;
94
            end
95
96
97
98
            % Add equation tag with block name.
            if ~isempty(rootfolder)
                model{j} = strcat('[blockname=''',  getblockname(varargin{i}, rootfolder), ''',', model{j}(2:end));
            end
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
            eqlist{tagnum,4} = model{j};
            eqtag = true;
        else
            eqnum = eqnum+1;
            [lhs, rhs] = getequation(model{j});
            endovar = getendovar(lhs);
            eqlist{eqnum,1} = endovar{1};
            eqlist{eqnum,2} = lhs;
            eqlist{eqnum,3} = rhs;
            eqtag = false;
            tagnum = tagnum+1;
        end
    end
end
eqlist = eqlist(1:eqnum,:);
114
[~, idx] = unique(eqlist(:,1), 'stable');
115
eqlist = eqlist(idx, :);
116

117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
% Get endogenous variables.
elist = cell(MAX_NUMBER_OF_ELEMENTS, 2);
enum = 0;
for i=1:length(varargin)
    fid = fopen(sprintf('%s/endogenous.inc', varargin{i}));
    cline = fgetl(fid);
    while ischar(cline)
        if ~isequal(cline, 'var')
            enum = enum+1;
            cline = regexprep(cline, '\t', '');
            cline = regexprep(cline, ';', '');
            [v, t] = getvarandtag(cline);
            elist(enum,1) = {v};
            elist(enum,2) = {t};
        end
        cline = fgetl(fid);
    end
    fclose(fid);
end
elist = elist(1:enum,:);
137
[~, idx] = unique(elist(:,1), 'stable');
138
elist = elist(idx,:);
139
140
141
142
143
144

% Get exogenous variables.
xlist = cell(MAX_NUMBER_OF_ELEMENTS, 2);
xnum = 0;
for i=1:length(varargin)
    fid = fopen(sprintf('%s/exogenous.inc', varargin{i}));
145
146
147
148
149
    if fid<0
        % No exogenous variables in the cherrypicked (sub)model, go to the
        % next cherrypicked model.
        continue
    end
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
    cline = fgetl(fid);
    while ischar(cline)
        if ~isequal(cline, 'varexo')
            xnum = xnum+1;
            cline = regexprep(cline, '\t', '');
            cline = regexprep(cline, ';', '');
            [v, t] = getvarandtag(cline);
            xlist(xnum,1) = {v};
            xlist(xnum,2) = {t};
        end
        cline = fgetl(fid);
    end
    fclose(fid);
end
xlist = xlist(1:xnum,:);
165
[~, idx] = unique(xlist(:,1), 'stable');
166
xlist = xlist(idx,:);
167

168
169
170
171
% Get parameter values.
calibration = '';
for i=1:length(varargin)
    fid = fopen(sprintf('%s/parameter-values.inc', varargin{i}));
172
173
174
175
176
    if fid<0
        % No calibrations in the cherrypicked (sub)model, go to the
        % next cherrypicked model.
        continue
    end
177
178
179
180
181
182
183
184
    cline = fgetl(fid);
    while ischar(cline)
        calibration = sprintf('%s\n%s', calibration, cline);
        cline = fgetl(fid);
    end
    fclose(fid);
end

185
186
187
188
189
190
191
192
% Move the endogenous variables which are not LHS of an equation
% into the set of exogenous variables.
[~, i1] = intersect(elist(:,1), eqlist(:,1));
if ~isequal(length(i1),rows(eqlist))
    error('Something is wrong with the endogenous variables.')
end
i2 = setdiff(1:rows(elist), i1);
xlist = [xlist; elist(i2,:)];
193
194
[~,idx] = unique(xlist(:,1));          % Ensure that the exogenous variable names are unique.
xlist = [xlist(idx,1) xlist(idx,2)];   % We do not test that the tags are the same.
195
196
elist = elist(i1,:);

197
% Remove endogenous variables from list of exogenous variables (if any).
198
199
200
201
202
xlist1 = xlist(:,1);
xlist2 = xlist(:,2);
[xlist1, id] = setdiff(xlist1, elist(:,1));
xlist2 = xlist2(id);
xlist = [xlist1, xlist2];
203

204
205
206
207
208
209
210
211
212
213
% Print all cherry-picked models in one mod-file.
[filepath, filename, fileext] = fileparts(ofile);
if ~isempty(filepath) && ~exist(filepath, 'dir')
    mkdir(filepath);
end
if isempty(filepath)
    fid = fopen(sprintf('%s%s', filename, fileext), 'w');
else
    fid = fopen(sprintf('%s%s%s%s', filepath, filesep(), filename, fileext), 'w');
end
214
215
216
if ~isempty(firstline)
    fprintf(fid, '%s\n\n', firstline);
end
217
218
fprintf(fid, 'var\n');
for i=1:rows(elist)
Stéphane Adjemian's avatar
Stéphane Adjemian committed
219
    if size(elist,2)==1 || isempty(elist{i,2})
220
221
222
223
224
        fprintf(fid, '\t%s\n', elist{i,1});
    else
        fprintf(fid, '\t%s %s\n', elist{i,1}, elist{i,2});
    end
end
225
226
227
228
229
230
231
232
233
234
235
236
237
if ~isempty(plist)
    fprintf(fid, ';\n\n');
    fprintf(fid, 'parameters\n');
    for i=1:length(plist)
        fprintf(fid, '\t%s\n', plist{i});
    end
    fprintf(fid, ';\n\n');
    fprintf(fid, calibration);
end
if ~isempty(xlist)
    fprintf(fid, '\n\n');
    fprintf(fid, 'varexo\n');
    for i=1:rows(xlist)
Stéphane Adjemian's avatar
Stéphane Adjemian committed
238
        if size(xlist,2)==1 || isempty(xlist{i,2})
239
240
241
242
            fprintf(fid, '\t%s\n', xlist{i,1});
        else
            fprintf(fid, '\t%s %s\n', xlist{i,1}, xlist{i,2});
        end
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
    end
end
fprintf(fid, ';\n\n');
fprintf(fid, 'model;\n\n');
for i=1:rows(eqlist)
    if isempty(eqlist{i,4})
        fprintf(fid, '\t%s = %s;\n\n', eqlist{i,2}, eqlist{i,3});
    else
        fprintf(fid, '\t%s\n', eqlist{i,4});
        fprintf(fid, '\t%s = %s;\n\n', eqlist{i,2}, eqlist{i,3});
    end
end
fprintf(fid, 'end;');
fclose(fid);

Stéphane Adjemian's avatar
Stéphane Adjemian committed
258
warning on MATLAB:subscripting:noSubscriptsSpecified
259
260
261
262
263
264
265
266
267
268
269
270


function b = isequationtag(str)
    b = true;
    if isempty(regexp(str, '\[.*\]','once'))
        b = false;
    end

function [lhs, rhs] = getequation(str)
    terms = strsplit(str, {'=',';'});
    terms(cellfun(@(x) all(isempty(x)), terms)) = [];
    terms(1) = {strrep(terms{1}, ' ', '')};
271
    lhs = regexp(terms{1}, '^(diff\([\-]*(log|diff)\([\-\+\*\/\w]*\)\)|(log|diff)\([\(\-\+\*\/\)\w]*\)|\w*)', 'match');
272
273
    if ~isempty(lhs)
        lhs = lhs{1};
274
275
276
        if isequal(lhs, 'log')
           error('Malformed equation: log of log or diff are not allowed.')
        end
277
278
279
280
281
282
        rhs = terms{2};
    else
        error('Malformed equation.')
    end

function v = getendovar(lhs)
283
    v = strsplit(lhs, {'diff','log','(',')', '+', '-', '*', '/'});
284
    v(cellfun(@(x) all(isempty(x)), v)) = [];
285
286
287
    if length(v)>1
        error('Malformed equation: no more than one endogenous variable can be used on the LHS.')
    end
288
289
290
291
292
293
294
295
296
297

function [v, t] = getvarandtag(str)
    tmp = regexp(str, '(?<name>\w+)\s*(?<tag>\(.*\))', 'names');
    if isempty(tmp)
        tmp = regexp(str, '(?<name>\w+)\s*', 'names');
        v = tmp.name;
        t = '';
    else
        v = tmp.name;
        t = tmp.tag;
298
299
300
    end

function blkname = getblockname(str, ROOT_FOLDER)
301
    str = strrep(str, '/', filesep());
302
303
    str = strrep(str, [ROOT_FOLDER filesep() 'blocks' filesep()], '');
    idx = strfind(str, filesep());
304
    blkname = str(1:idx(1)-1);