1 /*
2 * Copyright © 2003-2020 Dynare Team
3 *
4 * This file is part of Dynare.
5 *
6 * Dynare is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Dynare is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Dynare. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <cassert>
21 #include <iostream>
22 #include <sstream>
23
24 using namespace std;
25
26 #include "ComputingTasks.hh"
27 #include "Statement.hh"
28
29 #pragma GCC diagnostic push
30 #pragma GCC diagnostic ignored "-Wold-style-cast"
31 #include <boost/algorithm/string/trim.hpp>
32 #include <boost/algorithm/string/split.hpp>
33 #include <boost/tokenizer.hpp>
34 #pragma GCC diagnostic pop
35
36 #include <utility>
37 #include <algorithm>
38
SteadyStatement(OptionsList options_list_arg)39 SteadyStatement::SteadyStatement(OptionsList options_list_arg) :
40 options_list{move(options_list_arg)}
41 {
42 }
43
44 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)45 SteadyStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
46 {
47 mod_file_struct.steady_present = true;
48 }
49
50 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const51 SteadyStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
52 {
53 options_list.writeOutput(output);
54 output << "steady;" << endl;
55 }
56
57 void
writeJsonOutput(ostream & output) const58 SteadyStatement::writeJsonOutput(ostream &output) const
59 {
60 output << R"({"statementName": "steady")";
61 if (options_list.getNumberOfOptions())
62 {
63 output << ", ";
64 options_list.writeJsonOutput(output);
65 }
66 output << "}";
67 }
68
CheckStatement(OptionsList options_list_arg)69 CheckStatement::CheckStatement(OptionsList options_list_arg) :
70 options_list{move(options_list_arg)}
71 {
72 }
73
74 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const75 CheckStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
76 {
77 options_list.writeOutput(output);
78 output << "oo_.dr.eigval = check(M_,options_,oo_);" << endl;
79 }
80
81 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)82 CheckStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
83 {
84 mod_file_struct.check_present = true;
85 }
86
87 void
writeJsonOutput(ostream & output) const88 CheckStatement::writeJsonOutput(ostream &output) const
89 {
90 output << R"({"statementName": "check")";
91 if (options_list.getNumberOfOptions())
92 {
93 output << ", ";
94 options_list.writeJsonOutput(output);
95 }
96 output << "}";
97 }
98
ModelInfoStatement(OptionsList options_list_arg)99 ModelInfoStatement::ModelInfoStatement(OptionsList options_list_arg) :
100 options_list{move(options_list_arg)}
101 {
102 }
103
104 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)105 ModelInfoStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
106 {
107 //mod_file_struct.model_info_present = true;
108 }
109
110 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const111 ModelInfoStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
112 {
113 options_list.writeOutput(output);
114 output << "model_info();" << endl;
115 }
116
117 void
writeJsonOutput(ostream & output) const118 ModelInfoStatement::writeJsonOutput(ostream &output) const
119 {
120 output << R"({"statementName": "model_info")";
121 if (options_list.getNumberOfOptions())
122 {
123 output << ", ";
124 options_list.writeJsonOutput(output);
125 }
126 output << "}";
127 }
128
SimulStatement(OptionsList options_list_arg)129 SimulStatement::SimulStatement(OptionsList options_list_arg) :
130 options_list{move(options_list_arg)}
131 {
132 }
133
134 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)135 SimulStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
136 {
137 mod_file_struct.perfect_foresight_solver_present = true;
138 }
139
140 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const141 SimulStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
142 {
143 // Translate the “datafile” option into “initval_file” (see dynare#1663)
144 auto options_list_new = options_list; // Need a copy, because of const
145 if (auto it = options_list_new.string_options.find("datafile");
146 it != options_list_new.string_options.end())
147 {
148 output << "options_.initval_file = true;" << endl
149 << "initvalf('" << it->second << "');" << endl;
150 options_list_new.string_options.erase(it);
151 }
152 options_list_new.writeOutput(output);
153 output << "perfect_foresight_setup;" << endl
154 << "perfect_foresight_solver;" << endl;
155 }
156
157 void
writeJsonOutput(ostream & output) const158 SimulStatement::writeJsonOutput(ostream &output) const
159 {
160 output << R"({"statementName": "simul")";
161 if (options_list.getNumberOfOptions())
162 {
163 output << ", ";
164 options_list.writeJsonOutput(output);
165 }
166 output << "}";
167 }
168
PerfectForesightSetupStatement(OptionsList options_list_arg)169 PerfectForesightSetupStatement::PerfectForesightSetupStatement(OptionsList options_list_arg) :
170 options_list{move(options_list_arg)}
171 {
172 }
173
174 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const175 PerfectForesightSetupStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
176 {
177 auto options_list_new = options_list; // Need a copy, because of const
178 if (auto it = options_list_new.string_options.find("datafile");
179 it != options_list_new.string_options.end())
180 {
181 output << "options_.initval_file = true;" << endl
182 << "initvalf('" << it->second << "');" << endl;
183 options_list_new.string_options.erase(it);
184 }
185 options_list_new.writeOutput(output);
186 output << "perfect_foresight_setup;" << endl;
187 }
188
189 void
writeJsonOutput(ostream & output) const190 PerfectForesightSetupStatement::writeJsonOutput(ostream &output) const
191 {
192 output << R"({"statementName": "perfect_foresight_setup")";
193 if (options_list.getNumberOfOptions())
194 {
195 output << ", ";
196 options_list.writeJsonOutput(output);
197 }
198 output << "}";
199 }
200
PerfectForesightSolverStatement(OptionsList options_list_arg)201 PerfectForesightSolverStatement::PerfectForesightSolverStatement(OptionsList options_list_arg) :
202 options_list(move(options_list_arg))
203 {
204 }
205
206 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)207 PerfectForesightSolverStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
208 {
209 mod_file_struct.perfect_foresight_solver_present = true;
210 // Fill in option_occbin of mod_file_struct
211 if (options_list.num_options.find("occbin") != options_list.num_options.end())
212 mod_file_struct.occbin_option = true;
213 }
214
215 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const216 PerfectForesightSolverStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
217 {
218 options_list.writeOutput(output);
219 output << "perfect_foresight_solver;" << endl;
220 }
221
222 void
writeJsonOutput(ostream & output) const223 PerfectForesightSolverStatement::writeJsonOutput(ostream &output) const
224 {
225 output << R"({"statementName": "perfect_foresight_solver")";
226 if (options_list.getNumberOfOptions())
227 {
228 output << ", ";
229 options_list.writeJsonOutput(output);
230 }
231 output << "}";
232 }
233
PriorPosteriorFunctionStatement(const bool prior_func_arg,OptionsList options_list_arg)234 PriorPosteriorFunctionStatement::PriorPosteriorFunctionStatement(const bool prior_func_arg,
235 OptionsList options_list_arg) :
236 prior_func{prior_func_arg},
237 options_list{move(options_list_arg)}
238 {
239 }
240
241 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)242 PriorPosteriorFunctionStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
243 {
244 if (auto it2 = options_list.string_options.find("function");
245 it2 == options_list.string_options.end() || it2->second.empty())
246 {
247 cerr << "ERROR: both the prior_function and posterior_function commands require the 'function' argument"
248 << endl;
249 exit(EXIT_FAILURE);
250 }
251 }
252
253 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const254 PriorPosteriorFunctionStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
255 {
256 options_list.writeOutput(output);
257 string type = prior_func ? "prior" : "posterior";
258
259 output << "oo_ = execute_prior_posterior_function("
260 << "'" << options_list.string_options.find("function")->second << "', "
261 << "M_, options_, oo_, estim_params_, bayestopt_, dataset_, dataset_info, "
262 << "'" << type << "');" << endl;
263 }
264
265 void
writeJsonOutput(ostream & output) const266 PriorPosteriorFunctionStatement::writeJsonOutput(ostream &output) const
267 {
268 string type = prior_func ? "prior" : "posterior";
269 output << R"({"statementName": "prior_posterior_function", "type": ")" << type << R"(")";
270 if (options_list.getNumberOfOptions())
271 {
272 output << ", ";
273 options_list.writeJsonOutput(output);
274 }
275 output << "}";
276 }
277
PacModelStatement(string name_arg,string aux_model_name_arg,string discount_arg,expr_t growth_arg,double steady_state_growth_rate_number_arg,int steady_state_growth_rate_symb_id_arg,const SymbolTable & symbol_table_arg)278 PacModelStatement::PacModelStatement(string name_arg,
279 string aux_model_name_arg,
280 string discount_arg,
281 expr_t growth_arg,
282 double steady_state_growth_rate_number_arg,
283 int steady_state_growth_rate_symb_id_arg,
284 const SymbolTable &symbol_table_arg) :
285 name{move(name_arg)},
286 aux_model_name{move(aux_model_name_arg)},
287 discount{move(discount_arg)},
288 growth{growth_arg},
289 original_growth{growth_arg},
290 steady_state_growth_rate_number{steady_state_growth_rate_number_arg},
291 steady_state_growth_rate_symb_id{steady_state_growth_rate_symb_id_arg},
292 symbol_table{symbol_table_arg}
293 {
294 }
295
296 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)297 PacModelStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
298 {
299 if (growth)
300 growth->collectVariables(SymbolType::exogenous, mod_file_struct.pac_params);
301 }
302
303 void
overwriteGrowth(expr_t new_growth)304 PacModelStatement::overwriteGrowth(expr_t new_growth)
305 {
306 if (!new_growth || !growth)
307 return;
308
309 growth = new_growth;
310
311 try
312 {
313 growth_info = growth->matchLinearCombinationOfVariables(false);
314 }
315 catch (ExprNode::MatchFailureException &e)
316 {
317 auto gv = dynamic_cast<const VariableNode *>(growth);
318 if (gv)
319 growth_info.emplace_back(gv->symb_id, gv->lag, -1, 1);
320 else
321 {
322 cerr << "Pac growth must be a linear combination of variables" << endl;
323 exit(EXIT_FAILURE);
324 }
325 }
326 }
327
328 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const329 PacModelStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
330 {
331 output << "M_.pac." << name << ".auxiliary_model_name = '" << aux_model_name << "';" << endl
332 << "M_.pac." << name << ".discount_index = " << symbol_table.getTypeSpecificID(discount) + 1 << ";" << endl;
333 if (steady_state_growth_rate_symb_id < 0 && steady_state_growth_rate_number > 0)
334 output << "M_.pac." << name << ".steady_state_growth_rate = "
335 << steady_state_growth_rate_number << ";" << endl;
336 else if (steady_state_growth_rate_symb_id >= 0)
337 output << "M_.pac." << name << ".steady_state_growth_rate = "
338 << symbol_table.getTypeSpecificID(steady_state_growth_rate_symb_id) + 1 << ";" << endl;
339
340 if (growth)
341 {
342 output << "M_.pac." << name << ".growth_str = '";
343 original_growth->writeJsonOutput(output, {}, {}, true);
344 output << "';" << endl;
345 int i = 0;
346 for (auto [growth_symb_id, growth_lag, param_id, constant] : growth_info)
347 {
348 string structname = "M_.pac." + name + ".growth_linear_comb(" + to_string(++i) + ").";
349 if (growth_symb_id >= 0)
350 {
351 string var_field = "endo_id";
352 if (symbol_table.getType(growth_symb_id) == SymbolType::exogenous)
353 {
354 var_field = "exo_id";
355 output << structname << "endo_id = 0;" << endl;
356 }
357 else
358 output << structname << "exo_id = 0;" << endl;
359 try
360 {
361 // case when this is not the highest lag of the growth variable
362 int aux_symb_id = symbol_table.searchAuxiliaryVars(growth_symb_id, growth_lag);
363 output << structname << var_field << " = " << symbol_table.getTypeSpecificID(aux_symb_id) + 1 << ";" << endl
364 << structname << "lag = 0;" << endl;
365 }
366 catch (...)
367 {
368 try
369 {
370 // case when this is the highest lag of the growth variable
371 int tmp_growth_lag = growth_lag + 1;
372 int aux_symb_id = symbol_table.searchAuxiliaryVars(growth_symb_id, tmp_growth_lag);
373 output << structname << var_field << " = " << symbol_table.getTypeSpecificID(aux_symb_id) + 1 << ";" << endl
374 << structname << "lag = -1;" << endl;
375 }
376 catch (...)
377 {
378 // case when there is no aux var for the variable
379 output << structname << var_field << " = "<< symbol_table.getTypeSpecificID(growth_symb_id) + 1 << ";" << endl
380 << structname << "lag = " << growth_lag << ";" << endl;
381 }
382 }
383 }
384 else
385 output << structname << "endo_id = 0;" << endl
386 << structname << "exo_id = 0;" << endl
387 << structname << "lag = 0;" << endl;
388 output << structname << "param_id = "
389 << (param_id == -1 ? 0 : symbol_table.getTypeSpecificID(param_id) + 1) << ";" << endl
390 << structname << "constant = " << constant << ";" << endl;
391 }
392 }
393 }
394
395 void
writeJsonOutput(ostream & output) const396 PacModelStatement::writeJsonOutput(ostream &output) const
397 {
398 output << R"({"statementName": "pac_model",)"
399 << R"("model_name": ")" << name << R"(",)"
400 << R"("auxiliary_model_name": ")" << aux_model_name << R"(",)"
401 << R"("discount_index": )" << symbol_table.getTypeSpecificID(discount) + 1;
402 if (growth)
403 {
404 output << R"(,"growth_str": ")";
405 original_growth->writeJsonOutput(output, {}, {}, true);
406 output << R"(")";
407 }
408 output << "}" << endl;
409 }
410
VarEstimationStatement(OptionsList options_list_arg)411 VarEstimationStatement::VarEstimationStatement(OptionsList options_list_arg) :
412 options_list{move(options_list_arg)}
413 {
414 }
415
416 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)417 VarEstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
418 {
419 if (auto it = options_list.string_options.find("var_estimation.model_name");
420 it == options_list.string_options.end())
421 {
422 cerr << "ERROR: You must provide the model name to the var_estimation statement." << endl;
423 exit(EXIT_FAILURE);
424 }
425 }
426
427 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const428 VarEstimationStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
429 {
430 options_list.writeOutput(output);
431 output << "oo_ = var_estimation(M_, options_, oo_);" << endl;
432 }
433
VarRestrictionsStatement(string var_model_name_arg,map<string,vector<string>> var_map_arg,map<int,map<int,SymbolList>> exclusion_restrictions_arg,equation_restrictions_t equation_restrictions_arg,crossequation_restrictions_t crossequation_restrictions_arg,map<pair<int,int>,double> covariance_number_restriction_arg,map<pair<int,int>,pair<int,int>> covariance_pair_restriction_arg,const SymbolTable & symbol_table_arg)434 VarRestrictionsStatement::VarRestrictionsStatement(string var_model_name_arg,
435 map<string, vector<string>> var_map_arg,
436 map<int, map<int, SymbolList>> exclusion_restrictions_arg,
437 equation_restrictions_t equation_restrictions_arg,
438 crossequation_restrictions_t crossequation_restrictions_arg,
439 map<pair<int, int>, double> covariance_number_restriction_arg,
440 map<pair<int, int>, pair<int, int>> covariance_pair_restriction_arg,
441 const SymbolTable &symbol_table_arg) :
442 var_model_name{move(var_model_name_arg)},
443 var_map{move(var_map_arg)},
444 exclusion_restrictions{move(exclusion_restrictions_arg)},
445 equation_restrictions{move(equation_restrictions_arg)},
446 crossequation_restrictions{move(crossequation_restrictions_arg)},
447 covariance_number_restriction{move(covariance_number_restriction_arg)},
448 covariance_pair_restriction{move(covariance_pair_restriction_arg)},
449 symbol_table{symbol_table_arg}
450 {
451 }
452
453 int
findIdxInVector(const vector<string> & vecvars,const string & var) const454 VarRestrictionsStatement::findIdxInVector(const vector<string> &vecvars, const string &var) const
455 {
456 int idx = 0;
457 bool setflag = false;
458 for (auto itvs = vecvars.begin(); itvs != vecvars.end(); ++itvs, idx++)
459 if (*itvs == var)
460 {
461 setflag = true;
462 break;
463 }
464
465 if (!setflag)
466 {
467 cerr << "ERROR: you are imposing an exclusion restriction on an equation or variable "
468 << var << " that is not contained in VAR " << var_model_name;
469 exit(EXIT_FAILURE);
470 }
471 return idx;
472 }
473
474 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const475 VarRestrictionsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
476 {
477 auto itvs = var_map.find(var_model_name);
478 if (itvs == var_map.end())
479 {
480 cerr << "ERROR: you are imposing restrictions on a VAR named " << var_model_name
481 << " but this VAR has not been declared via the var_model statement." << endl;
482 exit(EXIT_FAILURE);
483 }
484 vector<string> vars = itvs->second;
485
486 string Mstr("M_.var." + var_model_name + ".restrictions.");
487 int nrestrictions = 0;
488
489 // Exclusion Restrictions
490 int idx = 1;
491 for (auto it = exclusion_restrictions.begin();
492 it != exclusion_restrictions.end(); ++it, idx++)
493 {
494 output << Mstr << "exclusion_restrictions{" << idx<< "}.lag = "
495 << it->first << ";" << endl
496 << Mstr << "exclusion_restrictions{" << idx << "}.restrictions = [";
497 for (auto it1 = it->second.begin(); it1 != it->second.end(); ++it1)
498 {
499 if (it1 != it->second.begin())
500 output << " ";
501
502 output << "struct('eq', " << findIdxInVector(vars, symbol_table.getName(it1->first)) + 1
503 << ", 'vars', [";
504 vector<string> excvars = it1->second.getSymbols();
505 for (auto &excvar : excvars)
506 output << findIdxInVector(vars, excvar) + 1 << " ";
507 output << "])";
508 nrestrictions += it1->second.getSize();
509 }
510 output << "];" << endl;
511 }
512
513 // Equation Restrictions
514 idx = 1;
515 for (auto it = equation_restrictions.begin();
516 it != equation_restrictions.end(); ++it, idx++, nrestrictions++)
517 {
518 output << Mstr << "equation_restriction{" << idx << "}.eq = '"
519 << symbol_table.getName(it->first) << "';" << endl
520 << Mstr << "equation_restriction{" << idx << "}.val = "
521 << it->second.second << ";" << endl;
522
523 var_restriction_eq_crosseq_t ls = it->second.first.first;
524 output << Mstr << "equation_restriction{" << idx << "}.ls = '"
525 << symbol_table.getName(ls.first.first) << "';" << endl
526 << Mstr << "equation_restriction{" << idx << "}.lslag = "
527 << ls.first.second.second << ";" << endl
528 << Mstr << "equation_restriction{" << idx << "}.lscoeff = ";
529 ls.second->writeOutput(output);
530 output << ";" << endl;
531
532 var_restriction_eq_crosseq_t rs = it->second.first.second;
533 if (rs.first.first >= 0)
534 {
535 output << Mstr << "equation_restriction{" << idx << "}.rs = '"
536 << symbol_table.getName(rs.first.first) << "';" << endl
537 << Mstr << "equation_restriction{" << idx << "}.rslag = "
538 << rs.first.second.second << ";" << endl
539 << Mstr << "equation_restriction{" << idx << "}.rscoeff = ";
540 rs.second->writeOutput(output);
541 output << ";" << endl;
542 }
543 }
544
545 // Cross Equation Restrictions
546 idx = 1;
547 for (auto it = crossequation_restrictions.begin();
548 it != crossequation_restrictions.end(); ++it, idx++, nrestrictions++)
549 {
550 output << Mstr << "crossequation_restriction{" << idx << "}.val = "
551 << it->second << ";" << endl;
552
553 var_restriction_eq_crosseq_t ls = it->first.first;
554 output << Mstr << "crossequation_restriction{" << idx << "}.lseq = "
555 << findIdxInVector(vars, symbol_table.getName(ls.first.first)) + 1 << ";" << endl
556 << Mstr << "crossequation_restriction{" << idx << "}.lsvar = "
557 << findIdxInVector(vars, symbol_table.getName(ls.first.second.first)) + 1 << ";" << endl
558 << Mstr << "crossequation_restriction{" << idx << "}.lslag = "
559 << ls.first.second.second << ";" << endl
560 << Mstr << "crossequation_restriction{" << idx << "}.lscoeff = ";
561 ls.second->writeOutput(output);
562 output << ";" << endl;
563
564 var_restriction_eq_crosseq_t rs = it->first.second;
565 if (rs.first.first >= 0)
566 {
567 output << Mstr << "crossequation_restriction{" << idx << "}.rseq = "
568 << findIdxInVector(vars, symbol_table.getName(rs.first.first)) + 1 << ";" << endl
569 << Mstr << "crossequation_restriction{" << idx << "}.rsvar = "
570 << findIdxInVector(vars, symbol_table.getName(rs.first.second.first)) + 1 << ";" << endl
571 << Mstr << "crossequation_restriction{" << idx << "}.rslag = "
572 << rs.first.second.second << ";" << endl
573 << Mstr << "crossequation_restriction{" << idx << "}.rscoeff = ";
574 rs.second->writeOutput(output);
575 output << ";" << endl;
576 }
577 }
578
579 // Covariance Const Restrictions
580 idx = 1;
581 for (auto it = covariance_number_restriction.begin();
582 it != covariance_number_restriction.end(); ++it, idx++)
583 output << Mstr << "covariance_const_restriction{" << idx << "}.var1 = '"
584 << symbol_table.getName(it->first.first) << "';" << endl
585 << Mstr << "covariance_const_restriction{" << idx << "}.var2 = '"
586 << symbol_table.getName(it->first.second) << "';" << endl
587 << Mstr << "covariance_const_restriction{" << idx << "}.val = "
588 << it->second << ";" << endl;
589
590 // Covariance Pair Restrictions
591 idx = 1;
592 for (auto it = covariance_pair_restriction.begin();
593 it != covariance_pair_restriction.end(); ++it, idx++)
594 output << Mstr << "covariance_pair_restriction{" << idx << "}.var11 = '"
595 << symbol_table.getName(it->first.first) << "';" << endl
596 << Mstr << "covariance_pair_restriction{" << idx << "}.var12 = '"
597 << symbol_table.getName(it->first.second) << "';" << endl
598 << Mstr << "covariance_pair_restriction{" << idx << "}.var21 = '"
599 << symbol_table.getName(it->second.first) << "';" << endl
600 << Mstr << "covariance_pair_restriction{" << idx << "}.var22 = '"
601 << symbol_table.getName(it->second.second) << "';" << endl;
602
603 output << Mstr << "N = " << nrestrictions << ";" << endl;
604 }
605
StochSimulStatement(SymbolList symbol_list_arg,OptionsList options_list_arg)606 StochSimulStatement::StochSimulStatement(SymbolList symbol_list_arg,
607 OptionsList options_list_arg) :
608 symbol_list{move(symbol_list_arg)},
609 options_list{move(options_list_arg)}
610 {
611 }
612
613 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)614 StochSimulStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
615 {
616 mod_file_struct.stoch_simul_present = true;
617
618 // Fill in option_order of mod_file_struct
619 if (auto it = options_list.num_options.find("order");
620 it != options_list.num_options.end())
621 mod_file_struct.order_option = max(mod_file_struct.order_option, stoi(it->second));
622
623 // Fill in mod_file_struct.partial_information
624 if (auto it = options_list.num_options.find("partial_information");
625 it != options_list.num_options.end() && it->second == "true")
626 mod_file_struct.partial_information = true;
627
628 // Option k_order_solver (implicit when order >= 3)
629 if (auto it = options_list.num_options.find("k_order_solver");
630 (it != options_list.num_options.end() && it->second == "true")
631 || mod_file_struct.order_option >= 3)
632 mod_file_struct.k_order_solver = true;
633
634 if (auto it = options_list.num_options.find("hp_filter"),
635 it1 = options_list.num_options.find("bandpass.indicator"),
636 it2 = options_list.num_options.find("one_sided_hp_filter");
637 (it != options_list.num_options.end() && it1 != options_list.num_options.end())
638 || (it != options_list.num_options.end() && it2 != options_list.num_options.end())
639 || (it1 != options_list.num_options.end() && it2 != options_list.num_options.end()))
640 {
641 cerr << "ERROR: stoch_simul: can only use one of hp, one-sided hp, and bandpass filters"
642 << endl;
643 exit(EXIT_FAILURE);
644 }
645
646 symbol_list.removeDuplicates("stoch_simul", warnings);
647
648 try
649 {
650 symbol_list.checkPass(warnings, { SymbolType::endogenous });
651 }
652 catch (SymbolList::SymbolListException &e)
653 {
654 cerr << "ERROR: stoch_simul: " << e.message << endl;
655 exit(EXIT_FAILURE);
656 }
657 }
658
659 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const660 StochSimulStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
661 {
662 // Ensure that order 3 implies k_order (#844)
663 if (auto it = options_list.num_options.find("order"),
664 it1 = options_list.num_options.find("k_order_solver");
665 (it1 != options_list.num_options.end() && it1->second == "true")
666 || (it != options_list.num_options.end() && stoi(it->second) >= 3))
667 output << "options_.k_order_solver = true;" << endl;
668
669 options_list.writeOutput(output);
670 symbol_list.writeOutput("var_list_", output);
671 output << "[info, oo_, options_, M_] = stoch_simul(M_, options_, oo_, var_list_);" << endl;
672 }
673
674 void
writeJsonOutput(ostream & output) const675 StochSimulStatement::writeJsonOutput(ostream &output) const
676 {
677 output << R"({"statementName": "stoch_simul")";
678 if (options_list.getNumberOfOptions())
679 {
680 output << ", ";
681 options_list.writeJsonOutput(output);
682 }
683 if (!symbol_list.empty())
684 {
685 output << ", ";
686 symbol_list.writeJsonOutput(output);
687 }
688 output << "}";
689 }
690
ForecastStatement(SymbolList symbol_list_arg,OptionsList options_list_arg)691 ForecastStatement::ForecastStatement(SymbolList symbol_list_arg,
692 OptionsList options_list_arg) :
693 symbol_list{move(symbol_list_arg)},
694 options_list{move(options_list_arg)}
695 {
696 }
697
698 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)699 ForecastStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
700 {
701 try
702 {
703 symbol_list.checkPass(warnings, { SymbolType::endogenous });
704 }
705 catch (SymbolList::SymbolListException &e)
706 {
707 cerr << "ERROR: forecast: " << e.message << endl;
708 exit(EXIT_FAILURE);
709 }
710 }
711
712 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const713 ForecastStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
714 {
715 options_list.writeOutput(output);
716 symbol_list.writeOutput("var_list_", output);
717 output << "[oo_.forecast,info] = dyn_forecast(var_list_,M_,options_,oo_,'simul');" << endl;
718 }
719
720 void
writeJsonOutput(ostream & output) const721 ForecastStatement::writeJsonOutput(ostream &output) const
722 {
723 output << R"({"statementName": "forecast")";
724 if (options_list.getNumberOfOptions())
725 {
726 output << ", ";
727 options_list.writeJsonOutput(output);
728 }
729 if (!symbol_list.empty())
730 {
731 output << ", ";
732 symbol_list.writeJsonOutput(output);
733 }
734 output << "}";
735 }
736
RamseyModelStatement(OptionsList options_list_arg)737 RamseyModelStatement::RamseyModelStatement(OptionsList options_list_arg) :
738 options_list{move(options_list_arg)}
739 {
740 }
741
742 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)743 RamseyModelStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
744 {
745 mod_file_struct.ramsey_model_present = true;
746
747 /* Fill in option_order of mod_file_struct
748 Since ramsey model needs one further order of derivation (for example, for 1st order
749 approximation, it needs 2nd derivatives), we add 1 to the order declared by user */
750 if (auto it = options_list.num_options.find("order");
751 it != options_list.num_options.end())
752 {
753 int order = stoi(it->second);
754 if (order > 2)
755 {
756 cerr << "ERROR: ramsey_model: order > 2 is not implemented" << endl;
757 exit(EXIT_FAILURE);
758 }
759 mod_file_struct.order_option = max(mod_file_struct.order_option, order + 1);
760 }
761
762 // Fill in mod_file_struct.partial_information
763 if (auto it = options_list.num_options.find("partial_information");
764 it != options_list.num_options.end() && it->second == "true")
765 mod_file_struct.partial_information = true;
766
767 // Option k_order_solver (implicit when order >= 3)
768 if (auto it = options_list.num_options.find("k_order_solver");
769 (it != options_list.num_options.end() && it->second == "true")
770 || mod_file_struct.order_option >= 3)
771 mod_file_struct.k_order_solver = true;
772
773 // Fill list of instruments
774 if (auto it = options_list.symbol_list_options.find("instruments");
775 it != options_list.symbol_list_options.end())
776 mod_file_struct.instruments = it->second;
777 }
778
779 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const780 RamseyModelStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
781 {
782 // options_.ramsey_policy indicates that a Ramsey model is present in the *.mod file
783 // this affects the computation of the steady state that uses a special algorithm
784 // It should probably rather be a M_ field, but we leave it in options_ for historical reason
785
786 // Ensure that order 3 implies k_order (#844)
787 if (auto it = options_list.num_options.find("order"),
788 it1 = options_list.num_options.find("k_order_solver");
789 (it1 != options_list.num_options.end() && it1->second == "true")
790 || (it != options_list.num_options.end() && stoi(it->second) >= 3))
791 output << "options_.k_order_solver = true;" << endl;
792
793 output << "options_.ramsey_policy = true;" << endl;
794 options_list.writeOutput(output);
795 }
796
797 void
writeJsonOutput(ostream & output) const798 RamseyModelStatement::writeJsonOutput(ostream &output) const
799 {
800 output << R"({"statementName": "ramsey_model")";
801 if (options_list.getNumberOfOptions())
802 {
803 output << ", ";
804 options_list.writeJsonOutput(output);
805 }
806 output << "}";
807 }
808
RamseyConstraintsStatement(const SymbolTable & symbol_table_arg,constraints_t constraints_arg)809 RamseyConstraintsStatement::RamseyConstraintsStatement(const SymbolTable &symbol_table_arg, constraints_t constraints_arg) :
810 symbol_table{symbol_table_arg},
811 constraints{move(constraints_arg)}
812 {
813 }
814
815 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)816 RamseyConstraintsStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
817 {
818 if (!mod_file_struct.ramsey_model_present || !mod_file_struct.ramsey_policy_present)
819 cerr << "ramsey_constraints: can only be used with ramsey_model or ramsey_policy" << endl;
820 }
821
822 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const823 RamseyConstraintsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
824 {
825 output << "M_.ramsey_model_constraints = {" << endl;
826 for (auto it = constraints.begin(); it != constraints.end(); ++it)
827 {
828 if (it != constraints.begin())
829 output << ", ";
830 output << "{" << it->endo + 1 << ", '";
831 switch (it->code)
832 {
833 case BinaryOpcode::less:
834 output << '<';
835 break;
836 case BinaryOpcode::greater:
837 output << '>';
838 break;
839 case BinaryOpcode::lessEqual:
840 output << "<=";
841 break;
842 case BinaryOpcode::greaterEqual:
843 output << ">=";
844 break;
845 default:
846 cerr << "Ramsey constraints: this shouldn't happen." << endl;
847 exit(EXIT_FAILURE);
848 }
849 output << "', '";
850 it->expression->writeOutput(output);
851 output << "'}" << endl;
852 }
853 output << "};" << endl;
854 }
855
856 void
writeJsonOutput(ostream & output) const857 RamseyConstraintsStatement::writeJsonOutput(ostream &output) const
858 {
859 output << R"({"statementName": "ramsey_constraints")"
860 << R"(, "ramsey_model_constraints": [)" << endl;
861 for (auto it = constraints.begin(); it != constraints.end(); ++it)
862 {
863 if (it != constraints.begin())
864 output << ", ";
865 output << R"({"constraint": ")" << symbol_table.getName(it->endo) << " ";
866 switch (it->code)
867 {
868 case BinaryOpcode::less:
869 output << '<';
870 break;
871 case BinaryOpcode::greater:
872 output << '>';
873 break;
874 case BinaryOpcode::lessEqual:
875 output << "<=";
876 break;
877 case BinaryOpcode::greaterEqual:
878 output << ">=";
879 break;
880 default:
881 cerr << "Ramsey constraints: this shouldn't happen." << endl;
882 exit(EXIT_FAILURE);
883 }
884 output << " ";
885 it->expression->writeJsonOutput(output, {}, {});
886 output << R"("})" << endl;
887 }
888 output << "]" << endl;
889 output << "}";
890 }
891
892 RamseyPolicyStatement::RamseyPolicyStatement(const SymbolTable &symbol_table_arg,
893 SymbolList symbol_list_arg,
894 OptionsList options_list_arg) :
895 symbol_table{symbol_table_arg},
896 symbol_list{move(symbol_list_arg)},
897 options_list{move(options_list_arg)}
898 {
899 }
900
901 void
902 RamseyPolicyStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
903 {
904 // ramsey_model_present indicates that the model is augmented with the FOC of the planner problem
905 mod_file_struct.ramsey_model_present = true;
906 // ramsey_policy_present indicates that ramsey_policy instruction for computation of first order approximation
907 // of a stochastic Ramsey problem if present in the *.mod file
908 mod_file_struct.ramsey_policy_present = true;
909
910 /* Fill in option_order of mod_file_struct
911 Since ramsey policy needs one further order of derivation (for example, for 1st order
912 approximation, it needs 2nd derivatives), we add 1 to the order declared by user */
913 if (auto it = options_list.num_options.find("order");
914 it != options_list.num_options.end())
915 {
916 int order = stoi(it->second);
917 if (order > 2)
918 {
919 cerr << "ERROR: ramsey_policy: order > 2 is not implemented" << endl;
920 exit(EXIT_FAILURE);
921 }
922 mod_file_struct.order_option = max(mod_file_struct.order_option, order + 1);
923 }
924
925 // Fill in mod_file_struct.partial_information
926 if (auto it = options_list.num_options.find("partial_information");
927 it != options_list.num_options.end() && it->second == "true")
928 mod_file_struct.partial_information = true;
929
930 // Option k_order_solver (implicit when order >= 3)
931 if (auto it = options_list.num_options.find("k_order_solver");
932 (it != options_list.num_options.end() && it->second == "true")
933 || mod_file_struct.order_option >= 3)
934 mod_file_struct.k_order_solver = true;
935
936 // Fill list of instruments
937 if (auto it = options_list.symbol_list_options.find("instruments");
938 it != options_list.symbol_list_options.end())
939 mod_file_struct.instruments = it->second;
940
941 try
942 {
943 symbol_list.checkPass(warnings, { SymbolType::endogenous });
944 }
945 catch (SymbolList::SymbolListException &e)
946 {
947 cerr << "ERROR: ramsey_policy: " << e.message << endl;
948 exit(EXIT_FAILURE);
949 }
950 }
951
952 void
953 RamseyPolicyStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
954 {
955 // Ensure that order 3 implies k_order (#844)
956 if (auto it = options_list.num_options.find("order"),
957 it1 = options_list.num_options.find("k_order_solver");
958 (it1 != options_list.num_options.end() && it1->second == "true")
959 || (it != options_list.num_options.end() && stoi(it->second) >= 3))
960 output << "options_.k_order_solver = true;" << endl;
961
962 options_list.writeOutput(output);
963 symbol_list.writeOutput("var_list_", output);
964 output << "ramsey_policy(var_list_);" << endl;
965 }
966
967 void
968 RamseyPolicyStatement::writeJsonOutput(ostream &output) const
969 {
970 output << R"({"statementName": "ramsey_policy")";
971 if (options_list.getNumberOfOptions())
972 {
973 output << ", ";
974 options_list.writeJsonOutput(output);
975 }
976 if (!symbol_list.empty())
977 {
978 output << ", ";
979 symbol_list.writeJsonOutput(output);
980 }
981 output << "}";
982 }
983
984 void
985 EvaluatePlannerObjective::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
986 {
987 output << "oo_.planner_objective_value = evaluate_planner_objective(M_, options_, oo_);" << endl;
988 }
989
990 void
991 EvaluatePlannerObjective::writeJsonOutput(ostream &output) const
992 {
993 output << R"({"statementName": "evaluate_planner_objective"})";
994 }
995
996 DiscretionaryPolicyStatement::DiscretionaryPolicyStatement(SymbolList symbol_list_arg,
997 OptionsList options_list_arg) :
998 symbol_list{move(symbol_list_arg)},
999 options_list{move(options_list_arg)}
1000 {
1001 }
1002
1003 void
1004 DiscretionaryPolicyStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
1005 {
1006 mod_file_struct.discretionary_policy_present = true;
1007
1008 if (options_list.symbol_list_options.find("instruments") == options_list.symbol_list_options.end())
1009 {
1010 cerr << "ERROR: discretionary_policy: the instruments option is required." << endl;
1011 exit(EXIT_FAILURE);
1012 }
1013
1014 /* Fill in option_order of mod_file_struct
1015 Since discretionary policy needs one further order of derivation (for example, for 1st order
1016 approximation, it needs 2nd derivatives), we add 1 to the order declared by user */
1017 if (auto it = options_list.num_options.find("order");
1018 it != options_list.num_options.end())
1019 {
1020 int order = stoi(it->second);
1021 if (order > 1)
1022 {
1023 cerr << "ERROR: discretionary_policy: order > 1 is not yet implemented" << endl;
1024 exit(EXIT_FAILURE);
1025 }
1026 mod_file_struct.order_option = max(mod_file_struct.order_option, order + 1);
1027 }
1028
1029 // Fill in mod_file_struct.partial_information
1030 if (auto it = options_list.num_options.find("partial_information");
1031 it != options_list.num_options.end() && it->second == "true")
1032 mod_file_struct.partial_information = true;
1033
1034 // Option k_order_solver (implicit when order >= 3)
1035 if (auto it = options_list.num_options.find("k_order_solver");
1036 (it != options_list.num_options.end() && it->second == "true")
1037 || mod_file_struct.order_option >= 3)
1038 mod_file_struct.k_order_solver = true;
1039
1040 // Fill list of instruments
1041 if (auto it = options_list.symbol_list_options.find("instruments");
1042 it != options_list.symbol_list_options.end())
1043 mod_file_struct.instruments = it->second;
1044
1045 try
1046 {
1047 symbol_list.checkPass(warnings, { SymbolType::endogenous });
1048 }
1049 catch (SymbolList::SymbolListException &e)
1050 {
1051 cerr << "ERROR: discretionary_policy: " << e.message << endl;
1052 exit(EXIT_FAILURE);
1053 }
1054 }
1055
1056 void
1057 DiscretionaryPolicyStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
1058 {
1059 // Ensure that order 3 implies k_order (#844)
1060 if (auto it = options_list.num_options.find("order"),
1061 it1 = options_list.num_options.find("k_order_solver");
1062 (it1 != options_list.num_options.end() && it1->second == "true")
1063 || (it != options_list.num_options.end() && stoi(it->second) >= 3))
1064 output << "options_.k_order_solver = true;" << endl;
1065
1066 options_list.writeOutput(output);
1067 symbol_list.writeOutput("var_list_", output);
1068 output << "[info, oo_, options_, M_] = discretionary_policy(M_, options_, oo_, var_list_);" << endl;
1069 }
1070
1071 void
1072 DiscretionaryPolicyStatement::writeJsonOutput(ostream &output) const
1073 {
1074 output << R"({"statementName": "discretionary_policy")";
1075 if (options_list.getNumberOfOptions())
1076 {
1077 output << ", ";
1078 options_list.writeJsonOutput(output);
1079 }
1080 if (!symbol_list.empty())
1081 {
1082 output << ", ";
1083 symbol_list.writeJsonOutput(output);
1084 }
1085 output << "}";
1086 }
1087
1088 EstimationStatement::EstimationStatement(const SymbolTable &symbol_table_arg,
1089 SymbolList symbol_list_arg,
1090 OptionsList options_list_arg) :
1091 symbol_table{symbol_table_arg},
1092 symbol_list{move(symbol_list_arg)},
1093 options_list{move(options_list_arg)}
1094 {
1095 }
1096
1097 void
1098 EstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
1099 {
1100 mod_file_struct.estimation_present = true;
1101
1102 // Fill in option_order of mod_file_struct
1103 if (auto it = options_list.num_options.find("order");
1104 it != options_list.num_options.end())
1105 {
1106 int order = stoi(it->second);
1107
1108 if (order > 2)
1109 mod_file_struct.k_order_solver = true;
1110
1111 mod_file_struct.order_option = max(mod_file_struct.order_option, order);
1112 }
1113
1114 // Fill in mod_file_struct.partial_information
1115 if (auto it = options_list.num_options.find("partial_information");
1116 it != options_list.num_options.end() && it->second == "true")
1117 mod_file_struct.partial_information = true;
1118
1119 // Fill in mod_file_struct.estimation_analytic_derivation
1120 if (auto it = options_list.num_options.find("analytic_derivation");
1121 it != options_list.num_options.end() && it->second == "1")
1122 mod_file_struct.estimation_analytic_derivation = true;
1123
1124 if (auto it = options_list.num_options.find("dsge_var");
1125 it != options_list.num_options.end())
1126 // Fill in mod_file_struct.dsge_var_calibrated
1127 mod_file_struct.dsge_var_calibrated = it->second;
1128
1129 // Fill in mod_file_struct.dsge_var_estimated
1130 if (options_list.string_options.find("dsge_var") != options_list.string_options.end())
1131 mod_file_struct.dsge_var_estimated = true;
1132
1133 // Fill in mod_file_struct.bayesian_irf_present
1134 if (auto it = options_list.num_options.find("bayesian_irf");
1135 it != options_list.num_options.end() && it->second == "true")
1136 mod_file_struct.bayesian_irf_present = true;
1137
1138 if (options_list.num_options.find("dsge_varlag") != options_list.num_options.end())
1139 if (mod_file_struct.dsge_var_calibrated.empty()
1140 && !mod_file_struct.dsge_var_estimated)
1141 {
1142 cerr << "ERROR: The estimation statement requires a dsge_var option to be passed "
1143 << "if the dsge_varlag option is passed." << endl;
1144 exit(EXIT_FAILURE);
1145 }
1146
1147 if (!mod_file_struct.dsge_var_calibrated.empty()
1148 && mod_file_struct.dsge_var_estimated)
1149 {
1150 cerr << "ERROR: An estimation statement cannot take more than one dsge_var option." << endl;
1151 exit(EXIT_FAILURE);
1152 }
1153
1154 if (options_list.string_options.find("datafile") == options_list.string_options.end()
1155 && !mod_file_struct.estimation_data_statement_present)
1156 {
1157 cerr << "ERROR: The estimation statement requires a data file to be supplied via the datafile option." << endl;
1158 exit(EXIT_FAILURE);
1159 }
1160
1161 if (options_list.string_options.find("mode_file") != options_list.string_options.end()
1162 && mod_file_struct.estim_params_use_calib)
1163 {
1164 cerr << "ERROR: The mode_file option of the estimation statement is incompatible with the use_calibration option of the estimated_params_init block." << endl;
1165 exit(EXIT_FAILURE);
1166 }
1167
1168 /* Check that we are not trying to estimate a parameter appearing in the
1169 planner discount factor (see dynare#1173) */
1170 vector<int> estimated_params_in_planner_discount;
1171 set_intersection(mod_file_struct.estimated_parameters.begin(),
1172 mod_file_struct.estimated_parameters.end(),
1173 mod_file_struct.parameters_in_planner_discount.begin(),
1174 mod_file_struct.parameters_in_planner_discount.end(),
1175 back_inserter(estimated_params_in_planner_discount));
1176 if (!estimated_params_in_planner_discount.empty())
1177 {
1178 cerr << "ERROR: It is not possible to estimate a parameter ("
1179 << symbol_table.getName(estimated_params_in_planner_discount[0])
1180 << ") that appears in the discount factor of the planner (i.e. in the 'planner_discount' option)." << endl;
1181 exit(EXIT_FAILURE);
1182 }
1183
1184 try
1185 {
1186 symbol_list.checkPass(warnings, { SymbolType::endogenous });
1187 }
1188 catch (SymbolList::SymbolListException &e)
1189 {
1190 cerr << "ERROR: estimation: " << e.message << endl;
1191 exit(EXIT_FAILURE);
1192 }
1193 }
1194
1195 void
1196 EstimationStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
1197 {
1198 options_list.writeOutput(output);
1199
1200 // Special treatment for order option and particle filter
1201 if (auto it = options_list.num_options.find("order");
1202 it == options_list.num_options.end())
1203 output << "options_.order = 1;" << endl;
1204 else if (stoi(it->second) >= 2)
1205 {
1206 output << "options_.particle.status = true;" << endl;
1207 if (stoi(it->second) > 2)
1208 output << "options_.k_order_solver = true;" << endl;
1209 }
1210
1211 // Do not check for the steady state in diffuse filter mode (#400)
1212 if (auto it = options_list.num_options.find("diffuse_filter");
1213 it != options_list.num_options.end() && it->second == "true")
1214 output << "options_.steadystate.nocheck = true;" << endl;
1215
1216 symbol_list.writeOutput("var_list_", output);
1217 output << "oo_recursive_=dynare_estimation(var_list_);" << endl;
1218 }
1219
1220 void
1221 EstimationStatement::writeJsonOutput(ostream &output) const
1222 {
1223 output << R"({"statementName": "estimation")";
1224 if (options_list.getNumberOfOptions())
1225 {
1226 output << ", ";
1227 options_list.writeJsonOutput(output);
1228 }
1229 if (!symbol_list.empty())
1230 {
1231 output << ", ";
1232 symbol_list.writeJsonOutput(output);
1233 }
1234 output << "}";
1235 }
1236
1237 DynareSensitivityStatement::DynareSensitivityStatement(OptionsList options_list_arg) :
1238 options_list{move(options_list_arg)}
1239 {
1240 }
1241
1242 void
1243 DynareSensitivityStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
1244 {
1245 if (auto it = options_list.num_options.find("identification");
1246 it != options_list.num_options.end() && it->second == "1")
1247 {
1248 mod_file_struct.identification_present = true;
1249 // The following triggers 3rd order derivatives, see preprocessor#40
1250 mod_file_struct.identification_order = max(mod_file_struct.identification_order, 2);
1251 }
1252 mod_file_struct.sensitivity_present = true;
1253 }
1254
1255 void
1256 DynareSensitivityStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
1257 {
1258 options_list.writeOutput(output, "options_gsa");
1259
1260 /* Ensure that nograph, nodisplay and graph_format are also set in top-level
1261 options_.
1262 \todo factorize this code between identification and dynare_sensitivity,
1263 and provide a generic mechanism for this situation (maybe using regexps) */
1264 if (auto it = options_list.num_options.find("nodisplay");
1265 it != options_list.num_options.end())
1266 output << "options_.nodisplay = " << it->second << ";" << endl;
1267 if (auto it = options_list.num_options.find("nograph");
1268 it != options_list.num_options.end())
1269 output << "options_.nograph = " << it->second << ";" << endl;
1270 if (auto it = options_list.string_options.find("graph_format");
1271 it != options_list.string_options.end())
1272 output << "options_.graph_format = '" << it->second << "';" << endl;
1273
1274 output << "dynare_sensitivity(options_gsa);" << endl;
1275 }
1276
1277 void
1278 DynareSensitivityStatement::writeJsonOutput(ostream &output) const
1279 {
1280 output << R"({"statementName": "dynare_sensitivity")";
1281 if (options_list.getNumberOfOptions())
1282 {
1283 output << ", ";
1284 options_list.writeJsonOutput(output);
1285 }
1286 output << "}";
1287 }
1288
1289 RplotStatement::RplotStatement(SymbolList symbol_list_arg) :
1290 symbol_list{move(symbol_list_arg)}
1291 {
1292 }
1293
1294 void
1295 RplotStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
1296 {
1297 try
1298 {
1299 symbol_list.checkPass(warnings, { SymbolType::endogenous, SymbolType::exogenous});
1300 }
1301 catch (SymbolList::SymbolListException &e)
1302 {
1303 cerr << "ERROR: rplot: " << e.message << endl;
1304 exit(EXIT_FAILURE);
1305 }
1306 }
1307
1308 void
1309 RplotStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
1310 {
1311 symbol_list.writeOutput("var_list_", output);
1312 output << "rplot(var_list_);" << endl;
1313 }
1314
1315 void
1316 RplotStatement::writeJsonOutput(ostream &output) const
1317 {
1318 output << R"({"statementName": "rplot")";
1319 if (!symbol_list.empty())
1320 {
1321 output << ", ";
1322 symbol_list.writeJsonOutput(output);
1323 }
1324 output << "}";
1325 }
1326
1327 void
1328 UnitRootVarsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
1329 {
1330 output << "options_.diffuse_filter = 1;" << endl
1331 << "options_.steadystate.nocheck = 1;" << endl;
1332 }
1333
1334 void
1335 UnitRootVarsStatement::writeJsonOutput(ostream &output) const
1336 {
1337 output << R"({"statementName": "unit_root_vars", )"
1338 << R"("diffuse_filter": 1, )"
1339 << R"("steady_state.nocheck": 1})";
1340 }
1341
1342 PeriodsStatement::PeriodsStatement(int periods_arg) : periods{periods_arg}
1343 {
1344 }
1345
1346 void
1347 PeriodsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
1348 {
1349 output << "options_.periods = " << periods << ";" << endl;
1350 }
1351
1352 void
1353 PeriodsStatement::writeJsonOutput(ostream &output) const
1354 {
1355 output << R"({"statementName": "periods", )"
1356 << R"("periods": )" << periods << "}";
1357 }
1358
1359 DsampleStatement::DsampleStatement(int val1_arg) : val1{val1_arg}, val2{-1}
1360 {
1361 }
1362
1363 DsampleStatement::DsampleStatement(int val1_arg, int val2_arg) : val1{val1_arg}, val2{val2_arg}
1364 {
1365 }
1366
1367 void
1368 DsampleStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
1369 {
1370 if (val2 < 0)
1371 output << "dsample(" << val1 << ");" << endl;
1372 else
1373 output << "dsample(" << val1 << ", " << val2 << ");" << endl;
1374 }
1375
1376 void
1377 DsampleStatement::writeJsonOutput(ostream &output) const
1378 {
1379 output << R"({"statementName": "dsample", )"
1380 << R"("value1": )" << val1 << ", "
1381 << R"("value2": )" << val2 << "}";
1382 }
1383
1384 EstimatedParamsStatement::EstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg,
1385 const SymbolTable &symbol_table_arg) :
1386 estim_params_list{move(estim_params_list_arg)},
1387 symbol_table{symbol_table_arg}
1388 {
1389 }
1390
1391 void
1392 EstimatedParamsStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
1393 {
1394 for (const auto &it : estim_params_list)
1395 {
1396 if (it.name == "dsge_prior_weight")
1397 mod_file_struct.dsge_prior_weight_in_estimated_params = true;
1398
1399 // Handle case of degenerate beta prior
1400 if (it.prior == PriorDistributions::beta)
1401 try
1402 {
1403 if (it.mean->eval(eval_context_t()) == 0.5
1404 && it.std->eval(eval_context_t()) == 0.5)
1405 {
1406 cerr << "ERROR: The prior density is not defined for the beta distribution when the mean = standard deviation = 0.5." << endl;
1407 exit(EXIT_FAILURE);
1408 }
1409 }
1410 catch (ExprNode::EvalException &e)
1411 {
1412 // We don't have enough information to compute the numerical value, skip the test
1413 }
1414 }
1415
1416 // Check that no parameter/endogenous is declared twice in the block
1417 set<string> already_declared;
1418 set<pair<string, string>> already_declared_corr;
1419 for (const auto &it : estim_params_list)
1420 {
1421 if (it.type == 3) // Correlation
1422 {
1423 // Use lexical ordering for the pair of symbols
1424 auto x = it.name < it.name2 ? pair(it.name, it.name2) : pair(it.name2, it.name);
1425
1426 if (already_declared_corr.find(x) == already_declared_corr.end())
1427 already_declared_corr.insert(x);
1428 else
1429 {
1430 cerr << "ERROR: in `estimated_params' block, the correlation between " << it.name << " and " << it.name2 << " is declared twice." << endl;
1431 exit(EXIT_FAILURE);
1432 }
1433 }
1434 else
1435 {
1436 if (already_declared.find(it.name) == already_declared.end())
1437 already_declared.insert(it.name);
1438 else
1439 {
1440 cerr << "ERROR: in `estimated_params' block, the symbol " << it.name << " is declared twice." << endl;
1441 exit(EXIT_FAILURE);
1442 }
1443 }
1444 }
1445
1446 // Fill in mod_file_struct.estimated_parameters (related to #469)
1447 for (const auto &it : estim_params_list)
1448 if (it.type == 2 && it.name != "dsge_prior_weight")
1449 mod_file_struct.estimated_parameters.insert(symbol_table.getID(it.name));
1450 }
1451
1452 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const1453 EstimatedParamsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
1454 {
1455 output << "estim_params_.var_exo = zeros(0, 10);" << endl
1456 << "estim_params_.var_endo = zeros(0, 10);" << endl
1457 << "estim_params_.corrx = zeros(0, 11);" << endl
1458 << "estim_params_.corrn = zeros(0, 11);" << endl
1459 << "estim_params_.param_vals = zeros(0, 10);" << endl;
1460
1461 for (const auto &it : estim_params_list)
1462 {
1463 int symb_id = symbol_table.getTypeSpecificID(it.name) + 1;
1464 SymbolType symb_type = symbol_table.getType(it.name);
1465
1466 switch (it.type)
1467 {
1468 case 1:
1469 if (symb_type == SymbolType::exogenous)
1470 output << "estim_params_.var_exo = [estim_params_.var_exo; ";
1471 else if (symb_type == SymbolType::endogenous)
1472 output << "estim_params_.var_endo = [estim_params_.var_endo; ";
1473 output << symb_id;
1474 break;
1475 case 2:
1476 output << "estim_params_.param_vals = [estim_params_.param_vals; "
1477 << symb_id;
1478 break;
1479 case 3:
1480 if (symb_type == SymbolType::exogenous)
1481 output << "estim_params_.corrx = [estim_params_.corrx; ";
1482 else if (symb_type == SymbolType::endogenous)
1483 output << "estim_params_.corrn = [estim_params_.corrn; ";
1484 output << symb_id << ", " << symbol_table.getTypeSpecificID(it.name2)+1;
1485 break;
1486 }
1487 output << ", ";
1488 it.init_val->writeOutput(output);
1489 output << ", ";
1490 it.low_bound->writeOutput(output);
1491 output << ", ";
1492 it.up_bound->writeOutput(output);
1493 output << ", "
1494 << static_cast<int>(it.prior) << ", ";
1495 it.mean->writeOutput(output);
1496 output << ", ";
1497 it.std->writeOutput(output);
1498 output << ", ";
1499 it.p3->writeOutput(output);
1500 output << ", ";
1501 it.p4->writeOutput(output);
1502 output << ", ";
1503 it.jscale->writeOutput(output);
1504 output << " ];" << endl;
1505 }
1506 }
1507
1508 void
writeJsonOutput(ostream & output) const1509 EstimatedParamsStatement::writeJsonOutput(ostream &output) const
1510 {
1511 output << R"({"statementName": "estimated_params", )"
1512 << R"("params": [)";
1513 for (auto it = estim_params_list.begin(); it != estim_params_list.end(); ++it)
1514 {
1515 if (it != estim_params_list.begin())
1516 output << ", ";
1517 output << "{";
1518 switch (it->type)
1519 {
1520 case 1:
1521 output << R"("var": ")" << it->name << R"(")";
1522 break;
1523 case 2:
1524 output << R"("param": ")" << it->name << R"(")";
1525 break;
1526 case 3:
1527 output << R"("var1": ")" << it->name << R"(",)"
1528 << R"("var2": ")" << it->name2 << R"(")";
1529 break;
1530 }
1531
1532 output << R"(, "init_val": ")";
1533 it->init_val->writeJsonOutput(output, {}, {});
1534 output << R"(", "lower_bound": ")";
1535 it->low_bound->writeJsonOutput(output, {}, {});
1536 output << R"(", "upper_bound": ")";
1537 it->up_bound->writeJsonOutput(output, {}, {});
1538 output << R"(", "prior_distribution": )"
1539 << static_cast<int>(it->prior)
1540 << R"(, "mean": ")";
1541 it->mean->writeJsonOutput(output, {}, {});
1542 output << R"(", "std": ")";
1543 it->std->writeJsonOutput(output, {}, {});
1544 output << R"(", "p3": ")";
1545 it->p3->writeJsonOutput(output, {}, {});
1546 output << R"(", "p4": ")";
1547 it->p4->writeJsonOutput(output, {}, {});
1548 output << R"(", "jscale": ")";
1549 it->jscale->writeJsonOutput(output, {}, {});
1550 output << R"("})" << endl;
1551 }
1552 output << "]"
1553 << "}";
1554 }
1555
EstimatedParamsInitStatement(vector<EstimationParams> estim_params_list_arg,const SymbolTable & symbol_table_arg,const bool use_calibration_arg)1556 EstimatedParamsInitStatement::EstimatedParamsInitStatement(vector<EstimationParams> estim_params_list_arg,
1557 const SymbolTable &symbol_table_arg,
1558 const bool use_calibration_arg) :
1559 estim_params_list{move(estim_params_list_arg)},
1560 symbol_table{symbol_table_arg},
1561 use_calibration{use_calibration_arg}
1562 {
1563 }
1564
1565 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)1566 EstimatedParamsInitStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
1567 {
1568 if (use_calibration)
1569 mod_file_struct.estim_params_use_calib = true;
1570 }
1571
1572 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const1573 EstimatedParamsInitStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
1574 {
1575 if (use_calibration)
1576 output << "options_.use_calibration_initialization = 1;" << endl;
1577
1578 bool skipline = false;
1579
1580 for (const auto &it : estim_params_list)
1581 {
1582 int symb_id = symbol_table.getTypeSpecificID(it.name) + 1;
1583 SymbolType symb_type = symbol_table.getType(it.name);
1584
1585 if (it.type < 3)
1586 {
1587 if (symb_type == SymbolType::exogenous)
1588 {
1589 output << "tmp1 = find(estim_params_.var_exo(:,1)==" << symb_id << ");" << endl;
1590 output << "if isempty(tmp1)" << endl;
1591 output << " disp(sprintf('The standard deviation of %s is not estimated (the value provided in estimated_params_init is not used).', M_.exo_names{" << symb_id << "}))" << endl;
1592 skipline = true;
1593 output << "else" << endl;
1594 output << " estim_params_.var_exo(tmp1,2) = ";
1595 it.init_val->writeOutput(output);
1596 output << ";" << endl;
1597 output << "end" << endl;
1598 }
1599 else if (symb_type == SymbolType::endogenous)
1600 {
1601 output << "tmp1 = find(estim_params_.var_endo(:,1)==" << symb_id << ");" << endl;
1602 output << "if isempty(tmp1)" << endl;
1603 output << " disp(sprintf('The standard deviation of the measurement error on %s is not estimated (the value provided in estimated_params_init is not used).', M_.endo_names{" << symb_id << "}))" << endl;
1604 skipline = true;
1605 output << "else" << endl;
1606 output << " estim_params_.var_endo(tmp1,2) = ";
1607 it.init_val->writeOutput(output);
1608 output << ";" << endl;
1609 output << "end" << endl;
1610 }
1611 else if (symb_type == SymbolType::parameter)
1612 {
1613 output << "tmp1 = find(estim_params_.param_vals(:,1)==" << symb_id << ");" << endl;
1614 output << "if isempty(tmp1)" << endl;
1615 output << " disp(sprintf('Parameter %s is not estimated (the value provided in estimated_params_init is not used).', M_.param_names{" << symb_id << "}))" << endl;
1616 skipline = true;
1617 output << "else" << endl;
1618 output << " estim_params_.param_vals(tmp1,2) = ";
1619 it.init_val->writeOutput(output);
1620 output << ";" << endl;
1621 output << "end" << endl;
1622 }
1623 }
1624 else
1625 {
1626 if (symb_type == SymbolType::exogenous)
1627 {
1628 output << "tmp1 = find((estim_params_.corrx(:,1)==" << symb_id << " & estim_params_.corrx(:,2)==" << symbol_table.getTypeSpecificID(it.name2)+1 << ") | "
1629 << "(estim_params_.corrx(:,2)==" << symb_id << " & estim_params_.corrx(:,1)==" << symbol_table.getTypeSpecificID(it.name2)+1 << "));" << endl;
1630 output << "if isempty(tmp1)" << endl;
1631 output << " disp(sprintf('The correlation between %s and %s is not estimated (the value provided in estimated_params_init is not used).', M_.exo_names{"
1632 << symb_id << "}, M_.exo_names{" << symbol_table.getTypeSpecificID(it.name2)+1 << "}))" << endl;
1633 skipline = true;
1634 output << "else" << endl;
1635 output << " estim_params_.corrx(tmp1,3) = ";
1636 it.init_val->writeOutput(output);
1637 output << ";" << endl;
1638 output << "end" << endl;
1639 }
1640 else if (symb_type == SymbolType::endogenous)
1641 {
1642 output << "tmp1 = find((estim_params_.corrn(:,1)==" << symb_id << " & estim_params_.corrn(:,2)==" << symbol_table.getTypeSpecificID(it.name2)+1 << ") | "
1643 << "(estim_params_.corrn(:,2)==" << symb_id << " & estim_params_.corrn(:,1)==" << symbol_table.getTypeSpecificID(it.name2)+1 << "));" << endl;
1644 output << "if isempty(tmp1)" << endl;
1645 output << " disp(sprintf('The correlation between measurement errors on %s and %s is not estimated (the value provided in estimated_params_init is not used).', M_.endo_names{"
1646 << symb_id << "}, M_.endo_names{" << symbol_table.getTypeSpecificID(it.name2)+1 << "}))" << endl;
1647 skipline = true;
1648 output << "else" << endl;
1649 output << " estim_params_.corrn(tmp1,3) = ";
1650 it.init_val->writeOutput(output);
1651 output << ";" << endl;
1652 output << "end" << endl;
1653 }
1654 }
1655 }
1656 if (skipline == true)
1657 output << "skipline()" << endl;
1658 }
1659
1660 void
writeJsonOutput(ostream & output) const1661 EstimatedParamsInitStatement::writeJsonOutput(ostream &output) const
1662 {
1663 output << R"({"statementName": "estimated_params_init")";
1664
1665 if (use_calibration)
1666 output << R"(, "use_calibration_initialization": 1)";
1667
1668 output << R"(, "params": [)";
1669 for (auto it = estim_params_list.begin(); it != estim_params_list.end(); ++it)
1670 {
1671 if (it != estim_params_list.begin())
1672 output << ", ";
1673 output << "{";
1674 switch (it->type)
1675 {
1676 case 1:
1677 output << R"("var": ")" << it->name << R"(")";
1678 break;
1679 case 2:
1680 output << R"("param": ")" << it->name << R"(")";
1681 break;
1682 case 3:
1683 output << R"("var1": ")" << it->name << R"(",)"
1684 << R"("var2": ")" << it->name2 << R"(")";
1685 break;
1686 }
1687 output << R"(, "init_val": ")";
1688 it->init_val->writeJsonOutput(output, {}, {});
1689 output << R"("})";
1690 }
1691 output << "]"
1692 << "}";
1693 }
1694
EstimatedParamsBoundsStatement(vector<EstimationParams> estim_params_list_arg,const SymbolTable & symbol_table_arg)1695 EstimatedParamsBoundsStatement::EstimatedParamsBoundsStatement(vector<EstimationParams> estim_params_list_arg,
1696 const SymbolTable &symbol_table_arg) :
1697 estim_params_list{move(estim_params_list_arg)},
1698 symbol_table{symbol_table_arg}
1699 {
1700 }
1701
1702 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const1703 EstimatedParamsBoundsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
1704 {
1705 for (const auto &it : estim_params_list)
1706 {
1707 int symb_id = symbol_table.getTypeSpecificID(it.name) + 1;
1708 SymbolType symb_type = symbol_table.getType(it.name);
1709
1710 if (it.type < 3)
1711 {
1712 if (symb_type == SymbolType::exogenous)
1713 {
1714 output << "tmp1 = find(estim_params_.var_exo(:,1)==" << symb_id << ");" << endl;
1715
1716 output << "estim_params_.var_exo(tmp1,3) = ";
1717 it.low_bound->writeOutput(output);
1718 output << ";" << endl;
1719
1720 output << "estim_params_.var_exo(tmp1,4) = ";
1721 it.up_bound->writeOutput(output);
1722 output << ";" << endl;
1723 }
1724 else if (symb_type == SymbolType::endogenous)
1725 {
1726 output << "tmp1 = find(estim_params_.var_endo(:,1)==" << symb_id << ");" << endl;
1727
1728 output << "estim_params_.var_endo(tmp1,3) = ";
1729 it.low_bound->writeOutput(output);
1730 output << ";" << endl;
1731
1732 output << "estim_params_.var_endo(tmp1,4) = ";
1733 it.up_bound->writeOutput(output);
1734 output << ";" << endl;
1735 }
1736 else if (symb_type == SymbolType::parameter)
1737 {
1738 output << "tmp1 = find(estim_params_.param_vals(:,1)==" << symb_id << ");" << endl;
1739
1740 output << "estim_params_.param_vals(tmp1,3) = ";
1741 it.low_bound->writeOutput(output);
1742 output << ";" << endl;
1743
1744 output << "estim_params_.param_vals(tmp1,4) = ";
1745 it.up_bound->writeOutput(output);
1746 output << ";" << endl;
1747 }
1748 }
1749 else
1750 {
1751 if (symb_type == SymbolType::exogenous)
1752 {
1753 output << "tmp1 = find((estim_params_.corrx(:,1)==" << symb_id << " & estim_params_.corrx(:,2)==" << symbol_table.getTypeSpecificID(it.name2)+1 << ") | "
1754 << "(estim_params_.corrx(:,2)==" << symb_id << " & estim_params_.corrx(:,1)==" << symbol_table.getTypeSpecificID(it.name2)+1 << "));" << endl;
1755
1756 output << "estim_params_.corrx(tmp1,4) = ";
1757 it.low_bound->writeOutput(output);
1758 output << ";" << endl;
1759
1760 output << "estim_params_.corrx(tmp1,5) = ";
1761 it.up_bound->writeOutput(output);
1762 output << ";" << endl;
1763 }
1764 else if (symb_type == SymbolType::endogenous)
1765 {
1766 output << "tmp1 = find((estim_params_.corrn(:,1)==" << symb_id << " & estim_params_.corrn(:,2)==" << symbol_table.getTypeSpecificID(it.name2)+1 << ") | "
1767 << "(estim_params_.corrn(:,2)==" << symb_id << " & estim_params_.corrn(:,1)==" << symbol_table.getTypeSpecificID(it.name2)+1 << "));" << endl;
1768
1769 output << "estim_params_.corrn(tmp1,4) = ";
1770 it.low_bound->writeOutput(output);
1771 output << ";" << endl;
1772
1773 output << "estim_params_.corrn(tmp1,5) = ";
1774 it.up_bound->writeOutput(output);
1775 output << ";" << endl;
1776 }
1777 }
1778 }
1779 }
1780
1781 void
writeJsonOutput(ostream & output) const1782 EstimatedParamsBoundsStatement::writeJsonOutput(ostream &output) const
1783 {
1784 output << R"({"statementName": "estimated_params_bounds", )"
1785 << R"("params": [)";
1786
1787 for (auto it = estim_params_list.begin(); it != estim_params_list.end(); ++it)
1788 {
1789 if (it != estim_params_list.begin())
1790 output << ", ";
1791 output << "{";
1792 switch (it->type)
1793 {
1794 case 1:
1795 output << R"("var": ")" << it->name << R"(")";
1796 case 2:
1797 output << R"("param": ")" << it->name << R"(")";
1798 break;
1799 case 3:
1800 output << R"("var1": ")" << it->name << R"(",)"
1801 << R"("var2": ")" << it->name2 << R"(")";
1802 break;
1803 }
1804 output << R"(, "lower_bound": )";
1805 it->low_bound->writeJsonOutput(output, {}, {});
1806 output << R"(, "upper_bound": )";
1807 it->up_bound->writeJsonOutput(output, {}, {});
1808 output << "}";
1809 }
1810 output << "]"
1811 << "}";
1812 }
1813
ObservationTrendsStatement(trend_elements_t trend_elements_arg,const SymbolTable & symbol_table_arg)1814 ObservationTrendsStatement::ObservationTrendsStatement(trend_elements_t trend_elements_arg,
1815 const SymbolTable &symbol_table_arg) :
1816 trend_elements{move(trend_elements_arg)},
1817 symbol_table{symbol_table_arg}
1818 {
1819 }
1820
1821 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const1822 ObservationTrendsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
1823 {
1824 output << "options_.trend_coeff = {};" << endl;
1825 for (const auto &trend_element : trend_elements)
1826 {
1827 SymbolType type = symbol_table.getType(trend_element.first);
1828 if (type == SymbolType::endogenous)
1829 {
1830 output << "tmp1 = strmatch('" << trend_element.first << "',options_.varobs,'exact');" << endl;
1831 output << "options_.trend_coeffs{tmp1} = '";
1832 trend_element.second->writeOutput(output);
1833 output << "';" << endl;
1834 }
1835 else
1836 cerr << "Warning : Non-variable symbol used in observation_trends: " << trend_element.first << endl;
1837 }
1838 }
1839
1840 void
writeJsonOutput(ostream & output) const1841 ObservationTrendsStatement::writeJsonOutput(ostream &output) const
1842 {
1843 output << R"({"statementName": "observation_trends", )"
1844 << R"("trends" : {)";
1845 bool printed = false;
1846 for (const auto &trend_element : trend_elements)
1847 {
1848 if (symbol_table.getType(trend_element.first) == SymbolType::endogenous)
1849 {
1850 if (printed)
1851 output << ", ";
1852 output << R"(")" << trend_element.first << R"(": ")";
1853 trend_element.second->writeJsonOutput(output, {}, {});
1854 output << R"(")" << endl;
1855 printed = true;
1856 }
1857 else
1858 cerr << "Warning : Non-variable symbol used in observation_trends: " << trend_element.first << endl;
1859 }
1860 output << "}"
1861 << "}";
1862 }
1863
OsrParamsStatement(SymbolList symbol_list_arg,const SymbolTable & symbol_table_arg)1864 OsrParamsStatement::OsrParamsStatement(SymbolList symbol_list_arg, const SymbolTable &symbol_table_arg) :
1865 symbol_list{move(symbol_list_arg)},
1866 symbol_table{symbol_table_arg}
1867 {
1868 }
1869
1870 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)1871 OsrParamsStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
1872 {
1873 if (mod_file_struct.osr_params_present)
1874 cerr << "WARNING: You have more than one osr_params statement in the .mod file." << endl;
1875 mod_file_struct.osr_params_present = true;
1876
1877 try
1878 {
1879 symbol_list.checkPass(warnings, { SymbolType::parameter });
1880 }
1881 catch (SymbolList::SymbolListException &e)
1882 {
1883 cerr << "ERROR: osr: " << e.message << endl;
1884 exit(EXIT_FAILURE);
1885 }
1886 }
1887
1888 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const1889 OsrParamsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
1890 {
1891 symbol_list.writeOutput("M_.osr.param_names", output);
1892 output << "M_.osr.param_names = cellstr(M_.osr.param_names);" << endl
1893 << "M_.osr.param_indices = zeros(length(M_.osr.param_names), 1);" << endl;
1894 int i = 0;
1895 vector<string> symbols = symbol_list.get_symbols();
1896 for (auto &symbol : symbols)
1897 output << "M_.osr.param_indices(" << ++i <<") = " << symbol_table.getTypeSpecificID(symbol) + 1 << ";" << endl;
1898 }
1899
1900 void
writeJsonOutput(ostream & output) const1901 OsrParamsStatement::writeJsonOutput(ostream &output) const
1902 {
1903 output << R"({"statementName": "osr_params")";
1904 if (!symbol_list.empty())
1905 {
1906 output << ", ";
1907 symbol_list.writeJsonOutput(output);
1908 }
1909 output << "}";
1910 }
1911
OsrParamsBoundsStatement(vector<OsrParams> osr_params_list_arg)1912 OsrParamsBoundsStatement::OsrParamsBoundsStatement(vector<OsrParams> osr_params_list_arg) :
1913 osr_params_list{move(osr_params_list_arg)}
1914 {
1915 }
1916
1917 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)1918 OsrParamsBoundsStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
1919 {
1920 if (!mod_file_struct.osr_params_present)
1921 {
1922 cerr << "ERROR: you must have an osr_params statement before the osr_params_bounds block." << endl;
1923 exit(EXIT_FAILURE);
1924 }
1925 }
1926
1927 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const1928 OsrParamsBoundsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
1929 {
1930
1931 output << "M_.osr.param_bounds = [-inf(length(M_.osr.param_names), 1), inf(length(M_.osr.param_names), 1)];" << endl;
1932
1933 for (const auto &it : osr_params_list)
1934 {
1935 output << "M_.osr.param_bounds(strcmp(M_.osr.param_names, '" << it.name << "'), :) = [";
1936 it.low_bound->writeOutput(output);
1937 output << ", ";
1938 it.up_bound->writeOutput(output);
1939 output << "];" << endl;
1940 }
1941 }
1942
1943 void
writeJsonOutput(ostream & output) const1944 OsrParamsBoundsStatement::writeJsonOutput(ostream &output) const
1945 {
1946 output << R"({"statementName": "osr_params_bounds")"
1947 << R"(, "bounds": [)";
1948 for (auto it = osr_params_list.begin(); it != osr_params_list.end(); ++it)
1949 {
1950 if (it != osr_params_list.begin())
1951 output << ", ";
1952 output << R"({"parameter": ")" << it->name << R"(",)"
1953 << R"("bounds": [")";
1954 it->low_bound->writeJsonOutput(output, {}, {});
1955 output << R"(", ")";
1956 it->up_bound->writeJsonOutput(output, {}, {});
1957 output << R"("])"
1958 << "}";
1959 }
1960 output << "]"
1961 << "}";
1962 }
1963
OsrStatement(SymbolList symbol_list_arg,OptionsList options_list_arg)1964 OsrStatement::OsrStatement(SymbolList symbol_list_arg,
1965 OptionsList options_list_arg) :
1966 symbol_list{move(symbol_list_arg)},
1967 options_list{move(options_list_arg)}
1968 {
1969 }
1970
1971 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)1972 OsrStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
1973 {
1974 mod_file_struct.osr_present = true;
1975
1976 // Fill in option_order of mod_file_struct
1977 if (auto it = options_list.num_options.find("order");
1978 it != options_list.num_options.end())
1979 mod_file_struct.order_option = max(mod_file_struct.order_option, stoi(it->second));
1980
1981 // Fill in mod_file_struct.partial_information
1982 if (auto it = options_list.num_options.find("partial_information");
1983 it != options_list.num_options.end() && it->second == "true")
1984 mod_file_struct.partial_information = true;
1985
1986 // Option k_order_solver (implicit when order >= 3)
1987 if (auto it = options_list.num_options.find("k_order_solver");
1988 (it != options_list.num_options.end() && it->second == "true")
1989 || mod_file_struct.order_option >= 3)
1990 mod_file_struct.k_order_solver = true;
1991
1992 try
1993 {
1994 symbol_list.checkPass(warnings, { SymbolType::endogenous });
1995 }
1996 catch (SymbolList::SymbolListException &e)
1997 {
1998 cerr << "ERROR: osr: " << e.message << endl;
1999 exit(EXIT_FAILURE);
2000 }
2001 }
2002
2003 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2004 OsrStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2005 {
2006 // Ensure that order 3 implies k_order (#844)
2007 if (auto it = options_list.num_options.find("order"),
2008 it1 = options_list.num_options.find("k_order_solver");
2009 (it1 != options_list.num_options.end() && it1->second == "true")
2010 || (it != options_list.num_options.end() && stoi(it->second) >= 3))
2011 output << "options_.k_order_solver = true;" << endl;
2012
2013 options_list.writeOutput(output);
2014 symbol_list.writeOutput("var_list_", output);
2015 output << "oo_.osr = osr(var_list_,M_.osr.param_names,M_.osr.variable_indices,M_.osr.variable_weights);" << endl;
2016 }
2017
2018 void
writeJsonOutput(ostream & output) const2019 OsrStatement::writeJsonOutput(ostream &output) const
2020 {
2021 output << R"({"statementName": "osr")";
2022 if (options_list.getNumberOfOptions())
2023 {
2024 output << ", ";
2025 options_list.writeJsonOutput(output);
2026 }
2027 if (!symbol_list.empty())
2028 {
2029 output << ", ";
2030 symbol_list.writeJsonOutput(output);
2031 }
2032 output << "}";
2033 }
2034
OptimWeightsStatement(var_weights_t var_weights_arg,covar_weights_t covar_weights_arg,const SymbolTable & symbol_table_arg)2035 OptimWeightsStatement::OptimWeightsStatement(var_weights_t var_weights_arg,
2036 covar_weights_t covar_weights_arg,
2037 const SymbolTable &symbol_table_arg) :
2038 var_weights{move(var_weights_arg)},
2039 covar_weights{move(covar_weights_arg)},
2040 symbol_table{symbol_table_arg}
2041 {
2042 }
2043
2044 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2045 OptimWeightsStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2046 {
2047 mod_file_struct.optim_weights_present = true;
2048 }
2049
2050 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2051 OptimWeightsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2052 {
2053 output << "%" << endl
2054 << "% OPTIM_WEIGHTS" << endl
2055 << "%" << endl
2056 << "M_.osr.variable_weights = sparse(M_.endo_nbr,M_.endo_nbr);" << endl
2057 << "M_.osr.variable_indices = [];" << endl << endl;
2058
2059 for (const auto & [name, value] : var_weights)
2060 {
2061 int id = symbol_table.getTypeSpecificID(name) + 1;
2062 output << "M_.osr.variable_weights(" << id << "," << id << ") = ";
2063 value->writeOutput(output);
2064 output << ";" << endl;
2065 output << "M_.osr.variable_indices = [M_.osr.variable_indices; " << id << "];" << endl;
2066 }
2067
2068 for (const auto & [names, value] : covar_weights)
2069 {
2070 int id1 = symbol_table.getTypeSpecificID(names.first) + 1;
2071 int id2 = symbol_table.getTypeSpecificID(names.second) + 1;
2072 output << "M_.osr.variable_weights(" << id1 << "," << id2 << ") = ";
2073 value->writeOutput(output);
2074 output << ";" << endl;
2075 output << "M_.osr.variable_indices = [M_.osr.variable_indices; " << id1 << "; " << id2 << "];" << endl;
2076 }
2077 }
2078
2079 void
writeJsonOutput(ostream & output) const2080 OptimWeightsStatement::writeJsonOutput(ostream &output) const
2081 {
2082 output << R"({"statementName": "optim_weights", )"
2083 << R"("weights": [)";
2084 for (auto it = var_weights.begin(); it != var_weights.end(); ++it)
2085 {
2086 if (it != var_weights.begin())
2087 output << ", ";
2088 output << R"({"name": ")" << it->first << R"(")"
2089 << R"(, "value": ")";
2090 it->second->writeJsonOutput(output, {}, {});
2091 output << R"("})";
2092 }
2093
2094 for (auto it = covar_weights.begin(); it != covar_weights.end(); ++it)
2095 {
2096 if (it != covar_weights.begin() || !var_weights.empty())
2097 output << ", ";
2098 output << R"({"name1": ")" << it->first.first << R"(")"
2099 << R"(, "name2": ")" << it->first.second << R"(")"
2100 << R"(, "value": ")";
2101 it->second->writeJsonOutput(output, {}, {});
2102 output << R"("})";
2103 }
2104 output << "]"
2105 << "}";
2106 }
2107
DynaSaveStatement(SymbolList symbol_list_arg,string filename_arg)2108 DynaSaveStatement::DynaSaveStatement(SymbolList symbol_list_arg,
2109 string filename_arg) :
2110 symbol_list{move(symbol_list_arg)},
2111 filename{move(filename_arg)}
2112 {
2113 }
2114
2115 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2116 DynaSaveStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2117 {
2118 try
2119 {
2120 symbol_list.checkPass(warnings, { SymbolType::endogenous, SymbolType::exogenous });
2121 }
2122 catch (SymbolList::SymbolListException &e)
2123 {
2124 cerr << "ERROR: dynasave: " << e.message << endl;
2125 exit(EXIT_FAILURE);
2126 }
2127 }
2128
2129 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2130 DynaSaveStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2131 {
2132 symbol_list.writeOutput("var_list_", output);
2133 output << "dynasave('" << filename
2134 << "',var_list_);" << endl;
2135 }
2136
2137 void
writeJsonOutput(ostream & output) const2138 DynaSaveStatement::writeJsonOutput(ostream &output) const
2139 {
2140 output << R"({"statementName": "dynasave", )"
2141 << R"("filename": ")" << filename << R"(")";
2142 if (!symbol_list.empty())
2143 {
2144 output << ", ";
2145 symbol_list.writeJsonOutput(output);
2146 }
2147 output << "}";
2148 }
2149
DynaTypeStatement(SymbolList symbol_list_arg,string filename_arg)2150 DynaTypeStatement::DynaTypeStatement(SymbolList symbol_list_arg,
2151 string filename_arg) :
2152 symbol_list(move(symbol_list_arg)),
2153 filename(move(filename_arg))
2154 {
2155 }
2156
2157 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2158 DynaTypeStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2159 {
2160 try
2161 {
2162 symbol_list.checkPass(warnings, { SymbolType::endogenous, SymbolType::exogenous });
2163 }
2164 catch (SymbolList::SymbolListException &e)
2165 {
2166 cerr << "ERROR: dynatype: " << e.message << endl;
2167 exit(EXIT_FAILURE);
2168 }
2169 }
2170
2171 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2172 DynaTypeStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2173 {
2174 symbol_list.writeOutput("var_list_", output);
2175 output << "dynatype('" << filename
2176 << "',var_list_);" << endl;
2177 }
2178
2179 void
writeJsonOutput(ostream & output) const2180 DynaTypeStatement::writeJsonOutput(ostream &output) const
2181 {
2182 output << R"({"statementName": "dynatype", )"
2183 << R"("filename": ")" << filename << R"(")";
2184 if (!symbol_list.empty())
2185 {
2186 output << ", ";
2187 symbol_list.writeJsonOutput(output);
2188 }
2189 output << "}";
2190 }
2191
ModelComparisonStatement(filename_list_t filename_list_arg,OptionsList options_list_arg)2192 ModelComparisonStatement::ModelComparisonStatement(filename_list_t filename_list_arg,
2193 OptionsList options_list_arg) :
2194 filename_list{move(filename_list_arg)},
2195 options_list{move(options_list_arg)}
2196 {
2197 }
2198
2199 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2200 ModelComparisonStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2201 {
2202 options_list.writeOutput(output);
2203
2204 output << "ModelNames_ = {};" << endl;
2205 output << "ModelPriors_ = [];" << endl;
2206
2207 for (const auto &it : filename_list)
2208 {
2209 output << "ModelNames_ = { ModelNames_{:} '" << it.first << "'};" << endl;
2210 output << "ModelPriors_ = [ ModelPriors_ ; " << it.second << "];" << endl;
2211 }
2212 output << "oo_ = model_comparison(ModelNames_,ModelPriors_,oo_,options_,M_.fname);" << endl;
2213 }
2214
2215 void
writeJsonOutput(ostream & output) const2216 ModelComparisonStatement::writeJsonOutput(ostream &output) const
2217 {
2218 output << R"({"statementName": "model_comparison")";
2219 if (!filename_list.empty())
2220 output << R"(, "filename_list": {)";
2221
2222 for (auto it = filename_list.begin(); it != filename_list.end(); ++it)
2223 {
2224 if (it != filename_list.begin())
2225 output << ", ";
2226 output << R"("name": ")" << it->first << R"(")"
2227 << R"("prior": ")" << it->second << R"(")";
2228 }
2229
2230 if (!filename_list.empty())
2231 output << "}";
2232
2233 if (options_list.getNumberOfOptions())
2234 {
2235 output << ", ";
2236 options_list.writeJsonOutput(output);
2237 }
2238
2239 output << "}";
2240 }
2241
PlannerObjectiveStatement(const StaticModel & model_tree_arg)2242 PlannerObjectiveStatement::PlannerObjectiveStatement(const StaticModel &model_tree_arg) :
2243 model_tree{model_tree_arg}
2244 {
2245 }
2246
2247 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2248 PlannerObjectiveStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2249 {
2250 assert(model_tree.equation_number() == 1);
2251 if (model_tree.exoPresentInEqs())
2252 {
2253 cerr << "ERROR: You cannot include exogenous variables in the planner objective. Please "
2254 << "define an auxiliary endogenous variable like eps_aux=epsilon and use it instead "
2255 << "of the varexo." << endl;
2256 exit(EXIT_FAILURE);
2257 }
2258 mod_file_struct.planner_objective_present = true;
2259 }
2260
2261 const StaticModel &
getPlannerObjective() const2262 PlannerObjectiveStatement::getPlannerObjective() const
2263 {
2264 return model_tree;
2265 }
2266
2267 void
computingPass()2268 PlannerObjectiveStatement::computingPass()
2269 {
2270 model_tree.computingPass(3, 0, {}, false, false, false);
2271 computing_pass_called = true;
2272 }
2273
2274 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2275 PlannerObjectiveStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2276 {
2277 model_tree.writeStaticFile(basename + ".objective", false, false, false, "", {}, {}, false);
2278 }
2279
2280 void
writeJsonOutput(ostream & output) const2281 PlannerObjectiveStatement::writeJsonOutput(ostream &output) const
2282 {
2283 output << R"({"statementName": "planner_objective")"
2284 << ", ";
2285 if (computing_pass_called)
2286 model_tree.writeJsonComputingPassOutput(output, false);
2287 else
2288 model_tree.writeJsonOutput(output);
2289
2290 output << "}";
2291 }
2292
BVARDensityStatement(int maxnlags_arg,OptionsList options_list_arg)2293 BVARDensityStatement::BVARDensityStatement(int maxnlags_arg, OptionsList options_list_arg) :
2294 maxnlags{maxnlags_arg},
2295 options_list{move(options_list_arg)}
2296 {
2297 }
2298
2299 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2300 BVARDensityStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2301 {
2302 mod_file_struct.bvar_present = true;
2303 }
2304
2305 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2306 BVARDensityStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2307 {
2308 options_list.writeOutput(output);
2309 output << "bvar_density(" << maxnlags << ");" << endl;
2310 }
2311
2312 void
writeJsonOutput(ostream & output) const2313 BVARDensityStatement::writeJsonOutput(ostream &output) const
2314 {
2315 output << R"({"statementName": "bvar_density")";
2316 if (options_list.getNumberOfOptions())
2317 {
2318 output << ", ";
2319 options_list.writeJsonOutput(output);
2320 }
2321 output << "}";
2322 }
2323
BVARForecastStatement(int nlags_arg,OptionsList options_list_arg)2324 BVARForecastStatement::BVARForecastStatement(int nlags_arg, OptionsList options_list_arg) :
2325 nlags{nlags_arg},
2326 options_list{move(options_list_arg)}
2327 {
2328 }
2329
2330 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2331 BVARForecastStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2332 {
2333 mod_file_struct.bvar_present = true;
2334 }
2335
2336 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2337 BVARForecastStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2338 {
2339 options_list.writeOutput(output);
2340 output << "bvar_forecast(" << nlags << ");" << endl;
2341 }
2342
2343 void
writeJsonOutput(ostream & output) const2344 BVARForecastStatement::writeJsonOutput(ostream &output) const
2345 {
2346 output << R"({"statementName": "bvar_forecast")";
2347 if (options_list.getNumberOfOptions())
2348 {
2349 output << ", ";
2350 options_list.writeJsonOutput(output);
2351 }
2352 output << "}";
2353 }
2354
SBVARStatement(OptionsList options_list_arg)2355 SBVARStatement::SBVARStatement(OptionsList options_list_arg) :
2356 options_list{move(options_list_arg)}
2357 {
2358 }
2359
2360 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2361 SBVARStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2362 {
2363 mod_file_struct.bvar_present = true;
2364 }
2365
2366 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2367 SBVARStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2368 {
2369 options_list.writeOutput(output);
2370 output << "sbvar(M_,options_);" << endl;
2371 }
2372
2373 void
writeJsonOutput(ostream & output) const2374 SBVARStatement::writeJsonOutput(ostream &output) const
2375 {
2376 output << R"({"statementName": "sbvar")";
2377 if (options_list.getNumberOfOptions())
2378 {
2379 output << ", ";
2380 options_list.writeJsonOutput(output);
2381 }
2382 output << "}";
2383 }
2384
MSSBVAREstimationStatement(OptionsList options_list_arg)2385 MSSBVAREstimationStatement::MSSBVAREstimationStatement(OptionsList options_list_arg) :
2386 options_list{move(options_list_arg)}
2387 {
2388 }
2389
2390 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2391 MSSBVAREstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2392 {
2393 mod_file_struct.bvar_present = true;
2394
2395 if (options_list.num_options.find("ms.create_init") == options_list.num_options.end())
2396 if (options_list.string_options.find("datafile") == options_list.string_options.end()
2397 || options_list.num_options.find("ms.initial_year") == options_list.num_options.end())
2398 {
2399 cerr << "ERROR: If you do not pass no_create_init to ms_estimation, "
2400 << "you must pass the datafile and initial_year options." << endl;
2401 exit(EXIT_FAILURE);
2402 }
2403 }
2404
2405 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2406 MSSBVAREstimationStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2407 {
2408 output << "options_ = initialize_ms_sbvar_options(M_, options_);" << endl
2409 << "options_.datafile = '';" << endl;
2410 options_list.writeOutput(output);
2411 output << "[options_, oo_] = ms_estimation(M_, options_, oo_);" << endl;
2412 }
2413
2414 void
writeJsonOutput(ostream & output) const2415 MSSBVAREstimationStatement::writeJsonOutput(ostream &output) const
2416 {
2417 output << R"({"statementName": "ms_sbvar_estimation")";
2418 if (options_list.getNumberOfOptions())
2419 {
2420 output << ", ";
2421 options_list.writeJsonOutput(output);
2422 }
2423 output << "}";
2424 }
2425
MSSBVARSimulationStatement(OptionsList options_list_arg)2426 MSSBVARSimulationStatement::MSSBVARSimulationStatement(OptionsList options_list_arg) :
2427 options_list(move(options_list_arg))
2428 {
2429 }
2430
2431 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2432 MSSBVARSimulationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2433 {
2434 mod_file_struct.bvar_present = true;
2435 }
2436
2437 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2438 MSSBVARSimulationStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2439 {
2440 output << "options_ = initialize_ms_sbvar_options(M_, options_);" << endl;
2441 options_list.writeOutput(output);
2442
2443 // Redeclare drop option if necessary
2444 if ((options_list.num_options.find("ms.mh_replic") != options_list.num_options.end()
2445 || options_list.num_options.find("ms.thinning_factor") != options_list.num_options.end())
2446 && (options_list.num_options.find("ms.drop") == options_list.num_options.end()))
2447 output << "options_.ms.drop = 0.1*options_.ms.mh_replic*options_.ms.thinning_factor;" << endl;
2448
2449 output << "[options_, oo_] = ms_simulation(M_, options_, oo_);" << endl;
2450 }
2451
2452 void
writeJsonOutput(ostream & output) const2453 MSSBVARSimulationStatement::writeJsonOutput(ostream &output) const
2454 {
2455 output << R"({"statementName": "ms_sbvar_simulation")";
2456 if (options_list.getNumberOfOptions())
2457 {
2458 output << ", ";
2459 options_list.writeJsonOutput(output);
2460 }
2461 output << "}";
2462 }
2463
MSSBVARComputeMDDStatement(OptionsList options_list_arg)2464 MSSBVARComputeMDDStatement::MSSBVARComputeMDDStatement(OptionsList options_list_arg) :
2465 options_list{move(options_list_arg)}
2466 {
2467 }
2468
2469 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2470 MSSBVARComputeMDDStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2471 {
2472 mod_file_struct.bvar_present = true;
2473 }
2474
2475 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2476 MSSBVARComputeMDDStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2477 {
2478 output << "options_ = initialize_ms_sbvar_options(M_, options_);" << endl;
2479 options_list.writeOutput(output);
2480 output << "[options_, oo_] = ms_compute_mdd(M_, options_, oo_);" << endl;
2481 }
2482
2483 void
writeJsonOutput(ostream & output) const2484 MSSBVARComputeMDDStatement::writeJsonOutput(ostream &output) const
2485 {
2486 output << R"({"statementName": "ms_sbvar_compute_mdd")";
2487 if (options_list.getNumberOfOptions())
2488 {
2489 output << ", ";
2490 options_list.writeJsonOutput(output);
2491 }
2492 output << "}";
2493 }
2494
MSSBVARComputeProbabilitiesStatement(OptionsList options_list_arg)2495 MSSBVARComputeProbabilitiesStatement::MSSBVARComputeProbabilitiesStatement(OptionsList options_list_arg) :
2496 options_list{move(options_list_arg)}
2497 {
2498 }
2499
2500 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2501 MSSBVARComputeProbabilitiesStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2502 {
2503 mod_file_struct.bvar_present = true;
2504
2505 if (options_list.num_options.find("ms.real_time_smoothed_probabilities") != options_list.num_options.end()
2506 && options_list.num_options.find("ms.filtered_probabilities") != options_list.num_options.end())
2507 {
2508 cerr << "ERROR: You may only pass one of real_time_smoothed "
2509 << "and filtered_probabilities to ms_compute_probabilities." << endl;
2510 exit(EXIT_FAILURE);
2511 }
2512 }
2513
2514 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2515 MSSBVARComputeProbabilitiesStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2516 {
2517 output << "options_ = initialize_ms_sbvar_options(M_, options_);" << endl;
2518 options_list.writeOutput(output);
2519 output << "[options_, oo_] = ms_compute_probabilities(M_, options_, oo_);" << endl;
2520 }
2521
2522 void
writeJsonOutput(ostream & output) const2523 MSSBVARComputeProbabilitiesStatement::writeJsonOutput(ostream &output) const
2524 {
2525 output << R"({"statementName": "ms_sbvar_compute_probabilities")";
2526 if (options_list.getNumberOfOptions())
2527 {
2528 output << ", ";
2529 options_list.writeJsonOutput(output);
2530 }
2531 output << "}";
2532 }
2533
MSSBVARIrfStatement(SymbolList symbol_list_arg,OptionsList options_list_arg)2534 MSSBVARIrfStatement::MSSBVARIrfStatement(SymbolList symbol_list_arg,
2535 OptionsList options_list_arg) :
2536 symbol_list{move(symbol_list_arg)},
2537 options_list{move(options_list_arg)}
2538 {
2539 }
2540
2541 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2542 MSSBVARIrfStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2543 {
2544 mod_file_struct.bvar_present = true;
2545
2546 bool regime_present = options_list.num_options.find("ms.regime") != options_list.num_options.end();
2547 bool regimes_present = options_list.num_options.find("ms.regimes") != options_list.num_options.end();
2548 bool filtered_probabilities_present = options_list.num_options.find("ms.filtered_probabilities") != options_list.num_options.end();
2549
2550 if ((filtered_probabilities_present && regime_present)
2551 || (filtered_probabilities_present && regimes_present)
2552 || (regimes_present && regime_present))
2553 {
2554 cerr << "ERROR: You may only pass one of regime, regimes and "
2555 << "filtered_probabilities to ms_irf" << endl;
2556 exit(EXIT_FAILURE);
2557 }
2558
2559 try
2560 {
2561 symbol_list.checkPass(warnings, { SymbolType::endogenous });
2562 }
2563 catch (SymbolList::SymbolListException &e)
2564 {
2565 cerr << "ERROR: ms_irf: " << e.message << endl;
2566 exit(EXIT_FAILURE);
2567 }
2568 }
2569
2570 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2571 MSSBVARIrfStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2572 {
2573 output << "options_ = initialize_ms_sbvar_options(M_, options_);" << endl;
2574 symbol_list.writeOutput("var_list_", output);
2575 options_list.writeOutput(output);
2576 output << "[options_, oo_] = ms_irf(var_list_,M_, options_, oo_);" << endl;
2577 }
2578
2579 void
writeJsonOutput(ostream & output) const2580 MSSBVARIrfStatement::writeJsonOutput(ostream &output) const
2581 {
2582 output << R"({"statementName": "ms_sbvar_irf")";
2583 if (options_list.getNumberOfOptions())
2584 {
2585 output << ", ";
2586 options_list.writeJsonOutput(output);
2587 }
2588 if (!symbol_list.empty())
2589 {
2590 output << ", ";
2591 symbol_list.writeJsonOutput(output);
2592 }
2593 output << "}";
2594 }
2595
MSSBVARForecastStatement(OptionsList options_list_arg)2596 MSSBVARForecastStatement::MSSBVARForecastStatement(OptionsList options_list_arg) :
2597 options_list{move(options_list_arg)}
2598 {
2599 }
2600
2601 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2602 MSSBVARForecastStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2603 {
2604 mod_file_struct.bvar_present = true;
2605
2606 if (options_list.num_options.find("ms.regimes") != options_list.num_options.end()
2607 && options_list.num_options.find("ms.regime") != options_list.num_options.end())
2608 {
2609 cerr << "ERROR: You may only pass one of regime and regimes to ms_forecast" << endl;
2610 exit(EXIT_FAILURE);
2611 }
2612 }
2613
2614 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2615 MSSBVARForecastStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2616 {
2617 output << "options_ = initialize_ms_sbvar_options(M_, options_);" << endl;
2618 options_list.writeOutput(output);
2619 output << "[options_, oo_] = ms_forecast(M_, options_, oo_);" << endl;
2620 }
2621
2622 void
writeJsonOutput(ostream & output) const2623 MSSBVARForecastStatement::writeJsonOutput(ostream &output) const
2624 {
2625 output << R"({"statementName": "ms_sbvar_forecast")";
2626 if (options_list.getNumberOfOptions())
2627 {
2628 output << ", ";
2629 options_list.writeJsonOutput(output);
2630 }
2631 output << "}";
2632 }
2633
MSSBVARVarianceDecompositionStatement(OptionsList options_list_arg)2634 MSSBVARVarianceDecompositionStatement::MSSBVARVarianceDecompositionStatement(OptionsList options_list_arg) :
2635 options_list{move(options_list_arg)}
2636 {
2637 }
2638
2639 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2640 MSSBVARVarianceDecompositionStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2641 {
2642 mod_file_struct.bvar_present = true;
2643
2644 bool regime_present = options_list.num_options.find("ms.regime") != options_list.num_options.end();
2645 bool regimes_present = options_list.num_options.find("ms.regimes") != options_list.num_options.end();
2646 bool filtered_probabilities_present = options_list.num_options.find("ms.filtered_probabilities") != options_list.num_options.end();
2647
2648 if ((filtered_probabilities_present && regime_present)
2649 || (filtered_probabilities_present && regimes_present)
2650 || (regimes_present && regime_present))
2651 {
2652 cerr << "ERROR: You may only pass one of regime, regimes and "
2653 << "filtered_probabilities to ms_variance_decomposition" << endl;
2654 exit(EXIT_FAILURE);
2655 }
2656 }
2657
2658 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2659 MSSBVARVarianceDecompositionStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2660 {
2661 output << "options_ = initialize_ms_sbvar_options(M_, options_);" << endl;
2662 options_list.writeOutput(output);
2663 output << "[options_, oo_] = ms_variance_decomposition(M_, options_, oo_);" << endl;
2664 }
2665
2666 void
writeJsonOutput(ostream & output) const2667 MSSBVARVarianceDecompositionStatement::writeJsonOutput(ostream &output) const
2668 {
2669 output << R"({"statementName": "ms_sbvar_variance_decomposition")";
2670 if (options_list.getNumberOfOptions())
2671 {
2672 output << ", ";
2673 options_list.writeJsonOutput(output);
2674 }
2675 output << "}";
2676 }
2677
IdentificationStatement(OptionsList options_list_arg)2678 IdentificationStatement::IdentificationStatement(OptionsList options_list_arg)
2679 : options_list{move(options_list_arg)}
2680 {
2681 if (auto it = options_list.num_options.find("max_dim_cova_group");
2682 it != options_list.num_options.end() && stoi(it->second) == 0)
2683 {
2684 cerr << "ERROR: The max_dim_cova_group option to identification only accepts integers > 0." << endl;
2685 exit(EXIT_FAILURE);
2686 }
2687 }
2688
2689 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2690 IdentificationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2691 {
2692 mod_file_struct.identification_present = true;
2693
2694 if (auto it = options_list.num_options.find("order");
2695 it != options_list.num_options.end())
2696 {
2697 int order = stoi(it->second);
2698 if (order < 1 || order > 3)
2699 {
2700 cerr << "ERROR: the order option of identification command must be between 1 and 3" << endl;
2701
2702 exit(EXIT_FAILURE);
2703 }
2704 mod_file_struct.identification_order = max(mod_file_struct.identification_order, order);
2705 }
2706 else
2707 // The default value for order is 1 (which triggers 2nd order dynamic derivatives, see preprocessor#40)
2708 mod_file_struct.identification_order = max(mod_file_struct.identification_order, 1);
2709 }
2710
2711 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2712 IdentificationStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2713 {
2714 options_list.writeOutput(output, "options_ident");
2715
2716 /* Ensure that nograph, nodisplay and graph_format are also set in top-level
2717 options_.
2718 \todo factorize this code between identification and dynare_sensitivity,
2719 and provide a generic mechanism for this situation (maybe using regexps) */
2720 if (auto it = options_list.num_options.find("nodisplay");
2721 it != options_list.num_options.end())
2722 output << "options_.nodisplay = " << it->second << ";" << endl;
2723 if (auto it = options_list.num_options.find("nograph");
2724 it != options_list.num_options.end())
2725 output << "options_.nograph = " << it->second << ";" << endl;
2726 if (auto it = options_list.string_options.find("graph_format");
2727 it != options_list.string_options.end())
2728 output << "options_.graph_format = '" << it->second << "';" << endl;
2729
2730 output << "dynare_identification(options_ident);" << endl;
2731 }
2732
2733 void
writeJsonOutput(ostream & output) const2734 IdentificationStatement::writeJsonOutput(ostream &output) const
2735 {
2736 output << R"({"statementName": "identification")";
2737 if (options_list.getNumberOfOptions())
2738 {
2739 output << ", ";
2740 options_list.writeJsonOutput(output);
2741 }
2742 output << "}";
2743 }
2744
WriteLatexDynamicModelStatement(const DynamicModel & dynamic_model_arg,bool write_equation_tags_arg)2745 WriteLatexDynamicModelStatement::WriteLatexDynamicModelStatement(const DynamicModel &dynamic_model_arg, bool write_equation_tags_arg) :
2746 dynamic_model{dynamic_model_arg},
2747 write_equation_tags{write_equation_tags_arg}
2748 {
2749 }
2750
2751 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2752 WriteLatexDynamicModelStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2753 {
2754 dynamic_model.writeLatexFile(basename, write_equation_tags);
2755 }
2756
2757 void
writeJsonOutput(ostream & output) const2758 WriteLatexDynamicModelStatement::writeJsonOutput(ostream &output) const
2759 {
2760 output << R"({"statementName": "write_latex_dynamic_model"})";
2761 }
2762
WriteLatexStaticModelStatement(const StaticModel & static_model_arg,bool write_equation_tags_arg)2763 WriteLatexStaticModelStatement::WriteLatexStaticModelStatement(const StaticModel &static_model_arg, bool write_equation_tags_arg) :
2764 static_model(static_model_arg),
2765 write_equation_tags(write_equation_tags_arg)
2766 {
2767 }
2768
2769 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2770 WriteLatexStaticModelStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2771 {
2772 static_model.writeLatexFile(basename, write_equation_tags);
2773 }
2774
2775 void
writeJsonOutput(ostream & output) const2776 WriteLatexStaticModelStatement::writeJsonOutput(ostream &output) const
2777 {
2778 output << R"({"statementName": "write_latex_static_model"})";
2779 }
2780
WriteLatexOriginalModelStatement(const DynamicModel & original_model_arg,bool write_equation_tags_arg)2781 WriteLatexOriginalModelStatement::WriteLatexOriginalModelStatement(const DynamicModel &original_model_arg, bool write_equation_tags_arg) :
2782 original_model{original_model_arg},
2783 write_equation_tags{write_equation_tags_arg}
2784 {
2785 }
2786
2787 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2788 WriteLatexOriginalModelStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2789 {
2790 original_model.writeLatexOriginalFile(basename, write_equation_tags);
2791 }
2792
2793 void
writeJsonOutput(ostream & output) const2794 WriteLatexOriginalModelStatement::writeJsonOutput(ostream &output) const
2795 {
2796 output << R"({"statementName": "write_latex_original_model"})";
2797 }
2798
WriteLatexSteadyStateModelStatement(const SteadyStateModel & steady_state_model_arg)2799 WriteLatexSteadyStateModelStatement::WriteLatexSteadyStateModelStatement(const SteadyStateModel &steady_state_model_arg) :
2800 steady_state_model{steady_state_model_arg}
2801 {
2802 }
2803
2804 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2805 WriteLatexSteadyStateModelStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2806 {
2807 mod_file_struct.write_latex_steady_state_model_present = true;
2808 }
2809
2810 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2811 WriteLatexSteadyStateModelStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2812 {
2813 steady_state_model.writeLatexSteadyStateFile(basename);
2814 }
2815
2816 void
writeJsonOutput(ostream & output) const2817 WriteLatexSteadyStateModelStatement::writeJsonOutput(ostream &output) const
2818 {
2819 output << R"({"statementName": "write_latex_steady_state_model"})";
2820 }
2821
ShockDecompositionStatement(SymbolList symbol_list_arg,OptionsList options_list_arg)2822 ShockDecompositionStatement::ShockDecompositionStatement(SymbolList symbol_list_arg,
2823 OptionsList options_list_arg) :
2824 symbol_list{move(symbol_list_arg)},
2825 options_list{move(options_list_arg)}
2826 {
2827 }
2828
2829 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2830 ShockDecompositionStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2831 {
2832 if (auto it = options_list.num_options.find("shock_decomp.with_epilogue");
2833 it != options_list.num_options.end() && it->second == "true")
2834 mod_file_struct.with_epilogue_option = true;
2835
2836 try
2837 {
2838 symbol_list.checkPass(warnings, { SymbolType::endogenous });
2839 }
2840 catch (SymbolList::SymbolListException &e)
2841 {
2842 cerr << "ERROR: shock_decomposition: " << e.message << endl;
2843 exit(EXIT_FAILURE);
2844 }
2845 }
2846
2847 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2848 ShockDecompositionStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2849 {
2850 options_list.writeOutput(output);
2851 symbol_list.writeOutput("var_list_", output);
2852 output << "oo_ = shock_decomposition(M_,oo_,options_,var_list_,bayestopt_,estim_params_);" << endl;
2853 }
2854
2855 void
writeJsonOutput(ostream & output) const2856 ShockDecompositionStatement::writeJsonOutput(ostream &output) const
2857 {
2858 output << R"({"statementName": "shock_decomposition")";
2859 if (options_list.getNumberOfOptions())
2860 {
2861 output << ", ";
2862 options_list.writeJsonOutput(output);
2863 }
2864 if (!symbol_list.empty())
2865 {
2866 output << ", ";
2867 symbol_list.writeJsonOutput(output);
2868 }
2869 output << "}";
2870 }
2871
RealtimeShockDecompositionStatement(SymbolList symbol_list_arg,OptionsList options_list_arg)2872 RealtimeShockDecompositionStatement::RealtimeShockDecompositionStatement(SymbolList symbol_list_arg,
2873 OptionsList options_list_arg) :
2874 symbol_list{move(symbol_list_arg)},
2875 options_list{move(options_list_arg)}
2876 {
2877 }
2878
2879 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2880 RealtimeShockDecompositionStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2881 {
2882 if (auto it = options_list.num_options.find("shock_decomp.with_epilogue");
2883 it != options_list.num_options.end() && it->second == "true")
2884 mod_file_struct.with_epilogue_option = true;
2885
2886 try
2887 {
2888 symbol_list.checkPass(warnings, { SymbolType::endogenous });
2889 }
2890 catch (SymbolList::SymbolListException &e)
2891 {
2892 cerr << "ERROR: realtime_shock_decomposition: " << e.message << endl;
2893 exit(EXIT_FAILURE);
2894 }
2895 }
2896
2897 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2898 RealtimeShockDecompositionStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2899 {
2900 options_list.writeOutput(output);
2901 symbol_list.writeOutput("var_list_", output);
2902 output << "oo_ = realtime_shock_decomposition(M_,oo_,options_,var_list_,bayestopt_,estim_params_);" << endl;
2903 }
2904
2905 void
writeJsonOutput(ostream & output) const2906 RealtimeShockDecompositionStatement::writeJsonOutput(ostream &output) const
2907 {
2908 output << R"({"statementName": "realtime_shock_decomposition")";
2909 if (options_list.getNumberOfOptions())
2910 {
2911 output << ", ";
2912 options_list.writeJsonOutput(output);
2913 }
2914 if (!symbol_list.empty())
2915 {
2916 output << ", ";
2917 symbol_list.writeJsonOutput(output);
2918 }
2919 output << "}";
2920 }
2921
PlotShockDecompositionStatement(SymbolList symbol_list_arg,OptionsList options_list_arg)2922 PlotShockDecompositionStatement::PlotShockDecompositionStatement(SymbolList symbol_list_arg,
2923 OptionsList options_list_arg) :
2924 symbol_list{move(symbol_list_arg)},
2925 options_list{move(options_list_arg)}
2926 {
2927 }
2928
2929 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2930 PlotShockDecompositionStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2931 {
2932 try
2933 {
2934 symbol_list.checkPass(warnings, { SymbolType::endogenous, SymbolType::epilogue });
2935 }
2936 catch (SymbolList::SymbolListException &e)
2937 {
2938 cerr << "ERROR: plot_shock_decomposition: " << e.message << endl;
2939 exit(EXIT_FAILURE);
2940 }
2941 }
2942
2943 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2944 PlotShockDecompositionStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2945 {
2946 output << "options_ = set_default_plot_shock_decomposition_options(options_);" << endl;
2947 options_list.writeOutput(output);
2948 symbol_list.writeOutput("var_list_", output);
2949 output << "oo_ = plot_shock_decomposition(M_, oo_, options_, var_list_);" << endl;
2950 }
2951
2952 void
writeJsonOutput(ostream & output) const2953 PlotShockDecompositionStatement::writeJsonOutput(ostream &output) const
2954 {
2955 output << R"({"statementName": "plot_shock_decomposition")";
2956 if (options_list.getNumberOfOptions())
2957 {
2958 output << ", ";
2959 options_list.writeJsonOutput(output);
2960 }
2961 if (!symbol_list.empty())
2962 {
2963 output << ", ";
2964 symbol_list.writeJsonOutput(output);
2965 }
2966 output << "}";
2967 }
2968
InitialConditionDecompositionStatement(SymbolList symbol_list_arg,OptionsList options_list_arg)2969 InitialConditionDecompositionStatement::InitialConditionDecompositionStatement(SymbolList symbol_list_arg,
2970 OptionsList options_list_arg) :
2971 symbol_list{move(symbol_list_arg)},
2972 options_list{move(options_list_arg)}
2973 {
2974 }
2975
2976 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)2977 InitialConditionDecompositionStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
2978 {
2979 if (auto it = options_list.num_options.find("initial_condition_decomp.with_epilogue");
2980 it != options_list.num_options.end() && it->second == "true")
2981 mod_file_struct.with_epilogue_option = true;
2982
2983 try
2984 {
2985 symbol_list.checkPass(warnings, { SymbolType::endogenous });
2986 }
2987 catch (SymbolList::SymbolListException &e)
2988 {
2989 cerr << "ERROR: initial_condition_decomposition: " << e.message << endl;
2990 exit(EXIT_FAILURE);
2991 }
2992 }
2993
2994 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const2995 InitialConditionDecompositionStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
2996 {
2997 output << "options_ = set_default_initial_condition_decomposition_options(options_);" << endl;
2998 options_list.writeOutput(output);
2999 symbol_list.writeOutput("var_list_", output);
3000 output << "oo_ = initial_condition_decomposition(M_, oo_, options_, var_list_, bayestopt_, estim_params_);" << endl;
3001 }
3002
3003 void
writeJsonOutput(ostream & output) const3004 InitialConditionDecompositionStatement::writeJsonOutput(ostream &output) const
3005 {
3006 output << R"({"statementName": "initial_condition_decomposition")";
3007 if (options_list.getNumberOfOptions())
3008 {
3009 output << ", ";
3010 options_list.writeJsonOutput(output);
3011 }
3012 if (!symbol_list.empty())
3013 {
3014 output << ", ";
3015 symbol_list.writeJsonOutput(output);
3016 }
3017 output << "}";
3018 }
3019
SqueezeShockDecompositionStatement(SymbolList symbol_list_arg)3020 SqueezeShockDecompositionStatement::SqueezeShockDecompositionStatement(SymbolList symbol_list_arg)
3021 : symbol_list{move(symbol_list_arg)}
3022 {
3023 }
3024
3025 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)3026 SqueezeShockDecompositionStatement::checkPass(ModFileStructure &mod_file_struct,
3027 WarningConsolidation &warnings)
3028 {
3029 try
3030 {
3031 symbol_list.checkPass(warnings, { SymbolType::endogenous });
3032 }
3033 catch (SymbolList::SymbolListException &e)
3034 {
3035 cerr << "ERROR: squeeze_shock_decomposition: " << e.message << endl;
3036 exit(EXIT_FAILURE);
3037 }
3038 }
3039
3040 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const3041 SqueezeShockDecompositionStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
3042 {
3043 if (symbol_list.empty())
3044 output << "oo_ = squeeze_shock_decomposition(M_, oo_, options_);" << endl;
3045 else
3046 {
3047 symbol_list.writeOutput("var_list_", output);
3048 output << "oo_ = squeeze_shock_decomposition(M_, oo_, options_, var_list_);" << endl;
3049 }
3050 }
3051
3052 void
writeJsonOutput(ostream & output) const3053 SqueezeShockDecompositionStatement::writeJsonOutput(ostream &output) const
3054 {
3055 output << R"({"statementName": "squeeze_shock_decomposition")";
3056 if (!symbol_list.empty())
3057 {
3058 output << ", ";
3059 symbol_list.writeJsonOutput(output);
3060 }
3061 output << "}";
3062 }
3063
ConditionalForecastStatement(OptionsList options_list_arg)3064 ConditionalForecastStatement::ConditionalForecastStatement(OptionsList options_list_arg) :
3065 options_list{move(options_list_arg)}
3066 {
3067 }
3068
3069 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)3070 ConditionalForecastStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
3071 {
3072 if (options_list.string_options.find("parameter_set") == options_list.string_options.end())
3073 {
3074 cerr << "ERROR: You must pass the `parameter_set` option to conditional_forecast" << endl;
3075 exit(EXIT_FAILURE);
3076 }
3077 }
3078
3079 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const3080 ConditionalForecastStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
3081 {
3082 options_list.writeOutput(output, "options_cond_fcst_");
3083 output << "imcforecast(constrained_paths_, constrained_vars_, options_cond_fcst_);" << endl;
3084 }
3085
3086 void
writeJsonOutput(ostream & output) const3087 ConditionalForecastStatement::writeJsonOutput(ostream &output) const
3088 {
3089 output << R"({"statementName": "conditional_forecast")";
3090 if (options_list.getNumberOfOptions())
3091 {
3092 output << ", ";
3093 options_list.writeJsonOutput(output);
3094 }
3095 output << "}";
3096 }
3097
PlotConditionalForecastStatement(int periods_arg,SymbolList symbol_list_arg)3098 PlotConditionalForecastStatement::PlotConditionalForecastStatement(int periods_arg, SymbolList symbol_list_arg) :
3099 periods{periods_arg},
3100 symbol_list{move(symbol_list_arg)}
3101 {
3102 }
3103
3104 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)3105 PlotConditionalForecastStatement::checkPass(ModFileStructure &mod_file_struct,
3106 WarningConsolidation &warnings)
3107 {
3108 try
3109 {
3110 symbol_list.checkPass(warnings, { SymbolType::endogenous });
3111 }
3112 catch (SymbolList::SymbolListException &e)
3113 {
3114 cerr << "ERROR: plot_conditional_forecast: " << e.message << endl;
3115 exit(EXIT_FAILURE);
3116 }
3117 }
3118
3119 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const3120 PlotConditionalForecastStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
3121 {
3122 symbol_list.writeOutput("var_list_", output);
3123 if (periods == -1)
3124 output << "plot_icforecast(var_list_,[],options_,oo_);" << endl;
3125 else
3126 output << "plot_icforecast(var_list_, " << periods << ",options_,oo_);" << endl;
3127 }
3128
3129 void
writeJsonOutput(ostream & output) const3130 PlotConditionalForecastStatement::writeJsonOutput(ostream &output) const
3131 {
3132 output << R"({"statementName": "plot_conditional_forecast", )"
3133 << R"("periods": )" << periods;
3134 if (!symbol_list.empty())
3135 {
3136 output << ", ";
3137 symbol_list.writeJsonOutput(output);
3138 }
3139 output << "}";
3140 }
3141
SvarIdentificationStatement(svar_identification_restrictions_t restrictions_arg,bool upper_cholesky_present_arg,bool lower_cholesky_present_arg,bool constants_exclusion_present_arg,const SymbolTable & symbol_table_arg)3142 SvarIdentificationStatement::SvarIdentificationStatement(svar_identification_restrictions_t restrictions_arg,
3143 bool upper_cholesky_present_arg,
3144 bool lower_cholesky_present_arg,
3145 bool constants_exclusion_present_arg,
3146 const SymbolTable &symbol_table_arg) :
3147 restrictions{move(restrictions_arg)},
3148 upper_cholesky_present{upper_cholesky_present_arg},
3149 lower_cholesky_present{lower_cholesky_present_arg},
3150 constants_exclusion_present{constants_exclusion_present_arg},
3151 symbol_table{symbol_table_arg}
3152 {
3153 }
3154
3155 int
getMaxLag() const3156 SvarIdentificationStatement::getMaxLag() const
3157 {
3158 int max_lag = 0;
3159 for (const auto &restriction : restrictions)
3160 if (restriction.lag > max_lag)
3161 max_lag = restriction.lag;
3162
3163 return max_lag;
3164 }
3165
3166 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)3167 SvarIdentificationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
3168 {
3169 // no equations OK with Svar Identification
3170 mod_file_struct.bvar_present = true;
3171 if (!mod_file_struct.svar_identification_present)
3172 mod_file_struct.svar_identification_present = true;
3173 else
3174 {
3175 cerr << "ERROR: You may only have one svar_identification block in your .mod file." << endl;
3176 exit(EXIT_FAILURE);
3177 }
3178
3179 if (upper_cholesky_present && lower_cholesky_present)
3180 {
3181 cerr << "ERROR: Within the svar_identification statement, you may only have one of "
3182 << "upper_cholesky and lower_cholesky." << endl;
3183 exit(EXIT_FAILURE);
3184 }
3185 }
3186
3187 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const3188 SvarIdentificationStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
3189 {
3190 assert(!(upper_cholesky_present && lower_cholesky_present));
3191 output << "%" << endl
3192 << "% SVAR IDENTIFICATION" << endl
3193 << "%" << endl;
3194
3195 if (upper_cholesky_present)
3196 output << "options_.ms.upper_cholesky=1;" << endl;
3197
3198 if (lower_cholesky_present)
3199 output << "options_.ms.lower_cholesky=1;" << endl;
3200
3201 if (constants_exclusion_present)
3202 output << "options_.ms.constants_exclusion=1;" << endl;
3203
3204 if (!upper_cholesky_present && !lower_cholesky_present)
3205 {
3206 int n = symbol_table.endo_nbr();
3207 int m = 1; // this is the constant, not the shocks
3208 int r = getMaxLag();
3209 int k = r*n+m;
3210
3211 if (k < 1)
3212 {
3213 cerr << "ERROR: lag = " << r
3214 << ", number of endogenous variables = " << n
3215 << ", number of exogenous variables = " << m
3216 << ". If this is not a logical error in the specification"
3217 << " of the .mod file, please report it to the Dynare Team." << endl;
3218 exit(EXIT_FAILURE);
3219 }
3220 if (n < 1)
3221 {
3222 cerr << "ERROR: Number of endogenous variables = " << n << "< 1. If this is not a logical "
3223 << "error in the specification of the .mod file, please report it to the Dynare Team." << endl;
3224 exit(EXIT_FAILURE);
3225 }
3226 output << "options_.ms.Qi = cell(" << n << ",1);" << endl
3227 << "options_.ms.Ri = cell(" << n << ",1);" << endl;
3228
3229 for (auto &it : restrictions)
3230 {
3231 assert(it.lag >= 0);
3232 if (it.lag == 0)
3233 output << "options_.ms.Qi{" << it.equation << "}(" << it.restriction_nbr << ", " << it.variable + 1 << ") = ";
3234 else
3235 {
3236 int col = (it.lag-1)*n+it.variable+1;
3237 if (col > k)
3238 {
3239 cerr << "ERROR: lag =" << it.lag << ", num endog vars = " << n << "current endog var index = " << it.variable << ". Index "
3240 << "out of bounds. If the above does not represent a logical error, please report this to the Dynare Team." << endl;
3241 exit(EXIT_FAILURE);
3242 }
3243 output << "options_.ms.Ri{" << it.equation << "}(" << it.restriction_nbr << ", " << col << ") = ";
3244 }
3245 it.value->writeOutput(output);
3246 output << ";" << endl;
3247 }
3248 output << "options_.ms.nlags = " << r << ";" << endl;
3249 }
3250 }
3251
3252 void
writeJsonOutput(ostream & output) const3253 SvarIdentificationStatement::writeJsonOutput(ostream &output) const
3254 {
3255 output << R"({"statementName": "svar_identification")";
3256
3257 if (upper_cholesky_present)
3258 output << R"(, "upper_cholesky": 1)";
3259
3260 if (lower_cholesky_present)
3261 output << R"(, "lower_cholesky": 1)";
3262
3263 if (constants_exclusion_present)
3264 output << R"(, "constants_exclusion": 1)";
3265
3266 if (!upper_cholesky_present && !lower_cholesky_present)
3267 {
3268 output << R"(, "nlags": )" << getMaxLag()
3269 << R"(, "restrictions": [)";
3270
3271 for (auto it = restrictions.begin(); it != restrictions.end(); ++it)
3272 {
3273 if (it != restrictions.begin())
3274 output << ", ";
3275 output << "{"
3276 << R"("equation_number": )" << it->equation << ", "
3277 << R"("restriction_number": )" << it->restriction_nbr << ", "
3278 << R"("variable": ")" << symbol_table.getName(it->variable) << R"(", )"
3279 << R"("expression": ")";
3280 it->value->writeOutput(output);
3281 output << R"("})";
3282 }
3283 output << "]";
3284 }
3285 output << "}";
3286 }
3287
MarkovSwitchingStatement(OptionsList options_list_arg)3288 MarkovSwitchingStatement::MarkovSwitchingStatement(OptionsList options_list_arg) :
3289 options_list{move(options_list_arg)}
3290 {
3291 if (auto it_num = options_list.num_options.find("ms.restrictions");
3292 it_num != options_list.num_options.end())
3293 {
3294 using namespace boost;
3295 auto it_num_regimes = options_list.num_options.find("ms.number_of_regimes");
3296 assert(it_num_regimes != options_list.num_options.end());
3297 auto num_regimes = stoi(it_num_regimes->second);
3298
3299 vector<string> tokenizedRestrictions;
3300 split(tokenizedRestrictions, it_num->second, is_any_of("["), token_compress_on);
3301 for (auto &tokenizedRestriction : tokenizedRestrictions)
3302 if (tokenizedRestriction.size() > 0)
3303 {
3304 vector<string> restriction;
3305 split(restriction, tokenizedRestriction, is_any_of("], "));
3306 for (auto it1 = restriction.begin(); it1 != restriction.end();)
3307 if (it1->empty())
3308 restriction.erase(it1);
3309 else
3310 ++it1;
3311
3312 if (restriction.size() != 3)
3313 {
3314 cerr << "ERROR: restrictions in the subsample statement must be specified in the form "
3315 << "[current_period_regime, next_period_regime, transition_probability]" << endl;
3316 exit(EXIT_FAILURE);
3317 }
3318
3319 try
3320 {
3321 auto from_regime = stoi(restriction[0]);
3322 auto to_regime = stoi(restriction[1]);
3323 if (from_regime > num_regimes || to_regime > num_regimes)
3324 {
3325 cerr << "ERROR: the regimes specified in the restrictions option must be "
3326 << "<= the number of regimes specified in the number_of_regimes option" << endl;
3327 exit(EXIT_FAILURE);
3328 }
3329
3330 if (restriction_map.find({ from_regime, to_regime }) !=
3331 restriction_map.end())
3332 {
3333 cerr << "ERROR: two restrictions were given for: " << from_regime << ", "
3334 << to_regime << endl;
3335 exit(EXIT_FAILURE);
3336 }
3337
3338 auto transition_probability = stod(restriction[2]);
3339 if (transition_probability > 1.0)
3340 {
3341 cerr << "ERROR: the transition probability, " << transition_probability
3342 << " must be less than 1" << endl;
3343 exit(EXIT_FAILURE);
3344 }
3345 restriction_map[{ from_regime, to_regime }] = transition_probability;
3346 }
3347 catch (const invalid_argument &)
3348 {
3349 cerr << "ERROR: The first two arguments for a restriction must be integers "
3350 << "specifying the regime and the last must be a double specifying the "
3351 << "transition probability. You wrote [" << tokenizedRestriction << endl;
3352 exit(EXIT_FAILURE);
3353 }
3354 }
3355 }
3356 }
3357
3358 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)3359 MarkovSwitchingStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
3360 {
3361 auto itChain = options_list.num_options.find("ms.chain");
3362 assert(itChain != options_list.num_options.end());
3363 int chainNumber = stoi(itChain->second);
3364 if (++mod_file_struct.last_markov_switching_chain != chainNumber)
3365 {
3366 cerr << "ERROR: The markov_switching chain option takes consecutive integers "
3367 << "beginning at 1." << endl;
3368 exit(EXIT_FAILURE);
3369 }
3370
3371 if (auto it_num = options_list.num_options.find("ms.restrictions");
3372 it_num != options_list.num_options.end())
3373 {
3374 using namespace boost;
3375 auto it_num_regimes = options_list.num_options.find("ms.number_of_regimes");
3376 assert(it_num_regimes != options_list.num_options.end());
3377 auto num_regimes = stoi(it_num_regimes->second);
3378 vector<double> col_trans_prob_sum(num_regimes, 0);
3379 vector<double> row_trans_prob_sum(num_regimes, 0);
3380 vector<bool> all_restrictions_in_row(num_regimes, true);
3381 vector<bool> all_restrictions_in_col(num_regimes, true);
3382 for (int row = 0; row < num_regimes; row++)
3383 for (int col = 0; col < num_regimes; col++)
3384 if (restriction_map.find({ row+1, col+1 }) != restriction_map.end())
3385 {
3386 row_trans_prob_sum[row] += restriction_map[{ row+1, col+1 }];
3387 col_trans_prob_sum[col] += restriction_map[{ row+1, col+1 }];
3388 }
3389 else
3390 {
3391 all_restrictions_in_row[row] = false;
3392 all_restrictions_in_col[col] = false;
3393 }
3394
3395 for (int i = 0; i < num_regimes; i++)
3396 {
3397 if (all_restrictions_in_row[i])
3398 {
3399 if (row_trans_prob_sum[i] != 1.0)
3400 {
3401 cerr << "ERROR: When all transitions probabilities are specified for a certain "
3402 << "regime, they must sum to 1" << endl;
3403 exit(EXIT_FAILURE);
3404 }
3405 }
3406 else
3407 if (row_trans_prob_sum[i] >= 1.0)
3408 {
3409 cerr << "ERROR: When transition probabilites are not specified for every regime, "
3410 << "their sum must be < 1" << endl;
3411 exit(EXIT_FAILURE);
3412 }
3413
3414 if (all_restrictions_in_col[i])
3415 {
3416 if (col_trans_prob_sum[i] != 1.0)
3417 {
3418 cerr << "ERROR: When all transitions probabilities are specified for a certain "
3419 << "regime, they must sum to 1" << endl;
3420 exit(EXIT_FAILURE);
3421 }
3422 }
3423 else
3424 if (col_trans_prob_sum[i] >= 1.0)
3425 {
3426 cerr << "ERROR: When transition probabilites are not specified for every regime, "
3427 << "their sum must be < 1" << endl;
3428 exit(EXIT_FAILURE);
3429 }
3430 }
3431 }
3432
3433 if (options_list.symbol_list_options.find("ms.parameters") != options_list.symbol_list_options.end())
3434 mod_file_struct.ms_dsge_present = true;
3435 }
3436
3437 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const3438 MarkovSwitchingStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
3439 {
3440 bool isDurationAVec = true;
3441 string infStr("Inf");
3442 OptionsList::num_options_t::const_iterator itChain, itNOR, itDuration;
3443 map<pair<int, int>, double >::const_iterator itR;
3444
3445 itChain = options_list.num_options.find("ms.chain");
3446 assert(itChain != options_list.num_options.end());
3447
3448 itDuration = options_list.num_options.find("ms.duration");
3449 assert(itDuration != options_list.num_options.end());
3450 if (stod(itDuration->second) || infStr.compare(itDuration->second) == 0)
3451 isDurationAVec = false;
3452 output << "options_.ms.duration = " << itDuration->second << ";" << endl;
3453
3454 itNOR = options_list.num_options.find("ms.number_of_regimes");
3455 assert(itNOR != options_list.num_options.end());
3456 for (int i = 0; i < stoi(itNOR->second); i++)
3457 {
3458 output << "options_.ms.ms_chain(" << itChain->second << ").regime("
3459 << i+1 << ").duration = options_.ms.duration";
3460 if (isDurationAVec)
3461 output << "(" << i+1 << ")";
3462 output << ";" << endl;
3463 }
3464
3465 int restrictions_index = 0;
3466 for (itR = restriction_map.begin(); itR != restriction_map.end(); itR++)
3467 output << "options_.ms.ms_chain(" << itChain->second << ").restrictions("
3468 << ++restrictions_index << ") = {[" << itR->first.first << ", "
3469 << itR->first.second << ", " << itR->second << "]};" << endl;
3470 }
3471
3472 void
writeJsonOutput(ostream & output) const3473 MarkovSwitchingStatement::writeJsonOutput(ostream &output) const
3474 {
3475 output << R"({"statementName": "markov_switching")";
3476 if (options_list.getNumberOfOptions())
3477 {
3478 output << ", ";
3479 options_list.writeJsonOutput(output);
3480 }
3481
3482 if (!restriction_map.empty())
3483 output << ", {";
3484 for (auto it = restriction_map.begin(); it != restriction_map.end(); ++it)
3485 {
3486 if (it != restriction_map.begin())
3487 output << ", ";
3488 output << R"({"current_period_regime": )" << it->first.first
3489 << R"(, "next_period_regime": )" << it->first.second
3490 << R"(, "transition_probability": )"<< it->second
3491 << "}";
3492 }
3493 if (!restriction_map.empty())
3494 output << "}";
3495 output << "}";
3496 }
3497
SvarStatement(OptionsList options_list_arg)3498 SvarStatement::SvarStatement(OptionsList options_list_arg) :
3499 options_list{move(options_list_arg)}
3500 {
3501 }
3502
3503 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)3504 SvarStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
3505 {
3506 auto it0 = options_list.string_options.find("ms.coefficients"),
3507 it1 = options_list.string_options.find("ms.variances"),
3508 it2 = options_list.string_options.find("ms.constants");
3509 assert((it0 != options_list.string_options.end()
3510 && it1 == options_list.string_options.end()
3511 && it2 == options_list.string_options.end())
3512 || (it0 == options_list.string_options.end()
3513 && it1 != options_list.string_options.end()
3514 && it2 == options_list.string_options.end())
3515 || (it0 == options_list.string_options.end()
3516 && it1 == options_list.string_options.end()
3517 && it2 != options_list.string_options.end()));
3518 }
3519
3520 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const3521 SvarStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
3522 {
3523 auto it = options_list.num_options.find("ms.chain");
3524 assert(it != options_list.num_options.end());
3525 output << "options_.ms.ms_chain(" << it->second << ")";
3526
3527 if (auto it0 = options_list.string_options.find("ms.coefficients");
3528 it0 != options_list.string_options.end())
3529 output << "." << it0->second;
3530 else if (auto it1 = options_list.string_options.find("ms.variances");
3531 it1 != options_list.string_options.end())
3532 output << "." << it1->second;
3533 else
3534 output << "." << options_list.string_options.find("ms.constants")->second;
3535
3536 output << ".equations = ";
3537 if (auto itv = options_list.vector_int_options.find("ms.equations");
3538 itv != options_list.vector_int_options.end())
3539 {
3540 assert(itv->second.size() >= 1);
3541 if (itv->second.size() > 1)
3542 {
3543 output << "[";
3544 for (int viit : itv->second)
3545 output << viit << ";";
3546 output << "];" << endl;
3547 }
3548 else
3549 output << itv->second.front() << ";" << endl;
3550 }
3551 else
3552 output << "'ALL';" << endl;
3553 }
3554
3555 void
writeJsonOutput(ostream & output) const3556 SvarStatement::writeJsonOutput(ostream &output) const
3557 {
3558 output << R"({"statementName": "svar")";
3559 if (options_list.getNumberOfOptions())
3560 {
3561 output << ", ";
3562 options_list.writeJsonOutput(output);
3563 }
3564 output << "}";
3565 }
3566
3567 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const3568 SvarGlobalIdentificationCheckStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
3569 {
3570 output << "svar_global_identification_check(options_);" << std::endl;
3571 }
3572
3573 void
writeJsonOutput(ostream & output) const3574 SvarGlobalIdentificationCheckStatement::writeJsonOutput(ostream &output) const
3575 {
3576 output << R"({"statementName": "svar_global_identification"})";
3577 }
3578
SetTimeStatement(OptionsList options_list_arg)3579 SetTimeStatement::SetTimeStatement(OptionsList options_list_arg) :
3580 options_list{move(options_list_arg)}
3581 {
3582 }
3583
3584 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const3585 SetTimeStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
3586 {
3587 options_list.writeOutput(output);
3588 }
3589
3590 void
writeJsonOutput(ostream & output) const3591 SetTimeStatement::writeJsonOutput(ostream &output) const
3592 {
3593 output << R"({"statementName": "set_time")";
3594 if (options_list.getNumberOfOptions())
3595 {
3596 output << ", ";
3597 options_list.writeJsonOutput(output);
3598 }
3599 output << "}";
3600 }
3601
EstimationDataStatement(OptionsList options_list_arg)3602 EstimationDataStatement::EstimationDataStatement(OptionsList options_list_arg) :
3603 options_list{move(options_list_arg)}
3604 {
3605 }
3606
3607 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)3608 EstimationDataStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
3609 {
3610 mod_file_struct.estimation_data_statement_present = true;
3611
3612 if (auto it = options_list.num_options.find("nobs");
3613 it != options_list.num_options.end())
3614 if (stoi(it->second) <= 0)
3615 {
3616 cerr << "ERROR: The nobs option of the data statement only accepts positive integers." << endl;
3617 exit(EXIT_FAILURE);
3618 }
3619
3620 if (options_list.string_options.find("file") == options_list.string_options.end()
3621 && options_list.string_options.find("series") == options_list.string_options.end())
3622 {
3623 cerr << "ERROR: The file or series option must be passed to the data statement." << endl;
3624 exit(EXIT_FAILURE);
3625 }
3626
3627 if (options_list.string_options.find("file") != options_list.string_options.end()
3628 && options_list.string_options.find("series") != options_list.string_options.end())
3629 {
3630 cerr << "ERROR: The file and series options cannot be used simultaneously in the data statement." << endl;
3631 exit(EXIT_FAILURE);
3632 }
3633 }
3634
3635 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const3636 EstimationDataStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
3637 {
3638 options_list.writeOutput(output, "options_.dataset");
3639 }
3640
3641 void
writeJsonOutput(ostream & output) const3642 EstimationDataStatement::writeJsonOutput(ostream &output) const
3643 {
3644 output << R"({"statementName": "estimation_data")";
3645 if (options_list.getNumberOfOptions())
3646 {
3647 output << ", ";
3648 options_list.writeJsonOutput(output);
3649 }
3650 output << "}";
3651 }
3652
SubsamplesStatement(string name1_arg,string name2_arg,subsample_declaration_map_t subsample_declaration_map_arg,const SymbolTable & symbol_table_arg)3653 SubsamplesStatement::SubsamplesStatement(string name1_arg,
3654 string name2_arg,
3655 subsample_declaration_map_t subsample_declaration_map_arg,
3656 const SymbolTable &symbol_table_arg) :
3657 name1{move(name1_arg)},
3658 name2{move(name2_arg)},
3659 subsample_declaration_map{move(subsample_declaration_map_arg)},
3660 symbol_table{symbol_table_arg}
3661 {
3662 }
3663
3664 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)3665 SubsamplesStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
3666 {
3667 }
3668
3669 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const3670 SubsamplesStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
3671 {
3672 output << "subsamples_indx = get_new_or_existing_ei_index('subsamples_index', '"
3673 << name1 << "','" << name2 << "');" << endl
3674 << "estimation_info.subsamples_index(subsamples_indx) = {'" << name1;
3675 if (!name2.empty())
3676 output << ":" << name2;
3677 output << "'};" << endl
3678 << "estimation_info.subsamples(subsamples_indx).range = {};" << endl
3679 << "estimation_info.subsamples(subsamples_indx).range_index = {};" << endl;
3680
3681 int map_indx = 1;
3682 for (auto it = subsample_declaration_map.begin();
3683 it != subsample_declaration_map.end(); ++it, map_indx++)
3684 output << "estimation_info.subsamples(subsamples_indx).range_index(" << map_indx << ") = {'"
3685 << it->first << "'};" << endl
3686 << "estimation_info.subsamples(subsamples_indx).range(" << map_indx << ").date1 = "
3687 << it->second.first << ";" << endl
3688 << "estimation_info.subsamples(subsamples_indx).range(" << map_indx << ").date2 = "
3689 << it->second.second << ";" << endl;
3690
3691 // Initialize associated subsample substructures in estimation_info
3692 const SymbolType symb_type = symbol_table.getType(name1);
3693 string lhs_field;
3694 if (symb_type == SymbolType::parameter)
3695 lhs_field = "parameter";
3696 else if (symb_type == SymbolType::exogenous || symb_type == SymbolType::exogenousDet)
3697 lhs_field = "structural_innovation";
3698 else
3699 lhs_field = "measurement_error";
3700
3701 output << "eifind = get_new_or_existing_ei_index('" << lhs_field;
3702
3703 if (!name2.empty())
3704 output << "_corr";
3705 output << "_prior_index', '"
3706 << name1 << "', '";
3707 if (!name2.empty())
3708 output << name2;
3709 output << "');" << endl;
3710
3711 lhs_field = "estimation_info." + lhs_field;
3712 if (!name2.empty())
3713 lhs_field += "_corr";
3714 output << lhs_field << "_prior_index(eifind) = {'" << name1;
3715 if (!name2.empty())
3716 output << ":" << name2;
3717 output << "'};" << endl;
3718
3719 output << lhs_field << "(eifind).subsample_prior = estimation_info.empty_prior;" << endl
3720 << lhs_field << "(eifind).subsample_prior(1:" << subsample_declaration_map.size()
3721 << ") = estimation_info.empty_prior;" << endl
3722 << lhs_field << "(eifind).range_index = estimation_info.subsamples(subsamples_indx).range_index;"
3723 << endl;
3724 }
3725
3726 void
writeJsonOutput(ostream & output) const3727 SubsamplesStatement::writeJsonOutput(ostream &output) const
3728 {
3729 output << R"({"statementName": "subsamples")"
3730 << R"(, "name1": ")" << name1 << R"(")";
3731 if (!name2.empty())
3732 output << R"(, "name2": ")" << name2 << R"(")";
3733
3734 output << R"(, "declarations": {)";
3735 for (auto it = subsample_declaration_map.begin();
3736 it != subsample_declaration_map.end(); ++it)
3737 {
3738 if (it != subsample_declaration_map.begin())
3739 output << ",";
3740 output << "{"
3741 << R"("range_index": ")" << it->first << R"(")"
3742 << R"(, "date1": ")" << it->second.first << R"(")"
3743 << R"(, "date2": ")" << it->second.second << R"(")"
3744 << "}";
3745 }
3746 output << "}"
3747 << "}";
3748 }
3749
SubsamplesEqualStatement(string to_name1_arg,string to_name2_arg,string from_name1_arg,string from_name2_arg,const SymbolTable & symbol_table_arg)3750 SubsamplesEqualStatement::SubsamplesEqualStatement(string to_name1_arg,
3751 string to_name2_arg,
3752 string from_name1_arg,
3753 string from_name2_arg,
3754 const SymbolTable &symbol_table_arg) :
3755 to_name1{move(to_name1_arg)},
3756 to_name2{move(to_name2_arg)},
3757 from_name1{move(from_name1_arg)},
3758 from_name2{move(from_name2_arg)},
3759 symbol_table{symbol_table_arg}
3760 {
3761 }
3762
3763 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const3764 SubsamplesEqualStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
3765 {
3766 output << "subsamples_to_indx = get_new_or_existing_ei_index('subsamples_index', '"
3767 << to_name1 << "','" << to_name2 << "');" << endl
3768 << "estimation_info.subsamples_index(subsamples_to_indx) = {'" << to_name1;
3769 if (!to_name2.empty())
3770 output << ":" << to_name2;
3771 output << "'};" << endl
3772 << "subsamples_from_indx = get_existing_subsamples_indx('" << from_name1 << "','" << from_name2 << "');"
3773 << endl
3774 << "estimation_info.subsamples(subsamples_to_indx) = estimation_info.subsamples(subsamples_from_indx);"
3775 << endl;
3776
3777 // Initialize associated subsample substructures in estimation_info
3778 const SymbolType symb_type = symbol_table.getType(to_name1);
3779 string lhs_field;
3780 if (symb_type == SymbolType::parameter)
3781 lhs_field = "parameter";
3782 else if (symb_type == SymbolType::exogenous || symb_type == SymbolType::exogenousDet)
3783 lhs_field = "structural_innovation";
3784 else
3785 lhs_field = "measurement_error";
3786
3787 output << "eifind = get_new_or_existing_ei_index('" << lhs_field;
3788
3789 if (!to_name2.empty())
3790 output << "_corr";
3791 output << "_prior_index', '"
3792 << to_name1 << "', '";
3793 if (!to_name2.empty())
3794 output << to_name2;
3795 output << "');" << endl;
3796
3797 lhs_field = "estimation_info." + lhs_field;
3798 if (!to_name2.empty())
3799 lhs_field += "_corr";
3800 output << lhs_field << "_prior_index(eifind) = {'" << to_name1;
3801 if (!to_name2.empty())
3802 output << ":" << to_name2;
3803 output << "'};" << endl;
3804
3805 output << lhs_field << "(eifind).subsample_prior = estimation_info.empty_prior;" << endl
3806 << lhs_field << "(eifind).subsample_prior(1:size(estimation_info.subsamples(subsamples_to_indx).range_index,2)) = estimation_info.empty_prior;"
3807 << endl
3808 << lhs_field << "(eifind).range_index = estimation_info.subsamples(subsamples_to_indx).range_index;"
3809 << endl;
3810 }
3811
3812 void
writeJsonOutput(ostream & output) const3813 SubsamplesEqualStatement::writeJsonOutput(ostream &output) const
3814 {
3815 output << R"({"statementName": "subsamples_equal")"
3816 << R"(, "to_name1": ")" << to_name1 << R"(")";
3817 if (!to_name2.empty())
3818 output << R"(, "to_name2": ")" << to_name2 << R"(")";
3819 output << R"(, "from_name1": ")" << from_name1 << R"(")";
3820 if (!from_name2.empty())
3821 output << R"(, "from_name2": ")" << from_name2 << R"(")";
3822 output << "}";
3823 }
3824
JointPriorStatement(vector<string> joint_parameters_arg,PriorDistributions prior_shape_arg,OptionsList options_list_arg)3825 JointPriorStatement::JointPriorStatement(vector<string> joint_parameters_arg,
3826 PriorDistributions prior_shape_arg,
3827 OptionsList options_list_arg) :
3828 joint_parameters{move(joint_parameters_arg)},
3829 prior_shape{prior_shape_arg},
3830 options_list{move(options_list_arg)}
3831 {
3832 }
3833
3834 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)3835 JointPriorStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
3836 {
3837 if (joint_parameters.size() < 2)
3838 {
3839 cerr << "ERROR: you must pass at least two parameters to the joint prior statement" << endl;
3840 exit(EXIT_FAILURE);
3841 }
3842
3843 if (prior_shape == PriorDistributions::noShape)
3844 {
3845 cerr << "ERROR: You must pass the shape option to the prior statement." << endl;
3846 exit(EXIT_FAILURE);
3847 }
3848
3849 if (options_list.num_options.find("mean") == options_list.num_options.end()
3850 && options_list.num_options.find("mode") == options_list.num_options.end())
3851 {
3852 cerr << "ERROR: You must pass at least one of mean and mode to the prior statement." << endl;
3853 exit(EXIT_FAILURE);
3854 }
3855
3856 if (auto it_num = options_list.num_options.find("domain");
3857 it_num != options_list.num_options.end())
3858 {
3859 using namespace boost;
3860 vector<string> tokenizedDomain;
3861 split(tokenizedDomain, it_num->second, is_any_of("[ ]"), token_compress_on);
3862 if (tokenizedDomain.size() != 4)
3863 {
3864 cerr << "ERROR: You must pass exactly two values to the domain option." << endl;
3865 exit(EXIT_FAILURE);
3866 }
3867 }
3868 }
3869
3870 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const3871 JointPriorStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
3872 {
3873 for (const auto &joint_parameter : joint_parameters)
3874 output << "eifind = get_new_or_existing_ei_index('joint_parameter_prior_index', '"
3875 << joint_parameter << "', '');" << endl
3876 << "estimation_info.joint_parameter_prior_index(eifind) = {'" << joint_parameter << "'};" << endl;
3877
3878 output << "key = {[";
3879 for (const auto &joint_parameter : joint_parameters)
3880 output << "get_new_or_existing_ei_index('joint_parameter_prior_index', '" << joint_parameter << "', '') ..."
3881 << endl << " ";
3882 output << "]};" << endl;
3883
3884 string lhs_field("estimation_info.joint_parameter_tmp");
3885
3886 writeOutputHelper(output, "domain", lhs_field);
3887 writeOutputHelper(output, "interval", lhs_field);
3888 writeOutputHelper(output, "mean", lhs_field);
3889 writeOutputHelper(output, "median", lhs_field);
3890 writeOutputHelper(output, "mode", lhs_field);
3891
3892 assert(prior_shape != PriorDistributions::noShape);
3893 output << lhs_field << ".shape = " << static_cast<int>(prior_shape) << ";" << endl;
3894
3895 writeOutputHelper(output, "shift", lhs_field);
3896 writeOutputHelper(output, "stdev", lhs_field);
3897 writeOutputHelper(output, "truncate", lhs_field);
3898 writeOutputHelper(output, "variance", lhs_field);
3899
3900 output << "estimation_info.joint_parameter_tmp = [key, ..." << endl
3901 << " " << lhs_field << ".domain , ..." << endl
3902 << " " << lhs_field << ".interval , ..." << endl
3903 << " " << lhs_field << ".mean , ..." << endl
3904 << " " << lhs_field << ".median , ..." << endl
3905 << " " << lhs_field << ".mode , ..." << endl
3906 << " " << lhs_field << ".shape , ..." << endl
3907 << " " << lhs_field << ".shift , ..." << endl
3908 << " " << lhs_field << ".stdev , ..." << endl
3909 << " " << lhs_field << ".truncate , ..." << endl
3910 << " " << lhs_field << ".variance];" << endl
3911 << "estimation_info.joint_parameter = [estimation_info.joint_parameter; estimation_info.joint_parameter_tmp];" << endl
3912 << "estimation_info=rmfield(estimation_info, 'joint_parameter_tmp');" << endl;
3913 }
3914
3915 void
writeOutputHelper(ostream & output,const string & field,const string & lhs_field) const3916 JointPriorStatement::writeOutputHelper(ostream &output, const string &field, const string &lhs_field) const
3917 {
3918 output << lhs_field << "." << field << " = {";
3919 if (field == "variance")
3920 output << "{";
3921 if (auto itn = options_list.num_options.find(field);
3922 itn != options_list.num_options.end())
3923 output << itn->second;
3924 else
3925 output << "{}";
3926 if (field == "variance")
3927 output << "}";
3928 output << "};" << endl;
3929 }
3930
3931 void
writeJsonOutput(ostream & output) const3932 JointPriorStatement::writeJsonOutput(ostream &output) const
3933 {
3934 output << R"({"statementName": "joint_prior")"
3935 << R"(, "key": [)";
3936 for (auto it = joint_parameters.begin(); it != joint_parameters.end(); ++it)
3937 {
3938 if (it != joint_parameters.begin())
3939 output << ", ";
3940 output << R"(")" << *it << R"(")";
3941 }
3942 output << "]";
3943
3944 if (options_list.getNumberOfOptions())
3945 {
3946 output << ", ";
3947 options_list.writeJsonOutput(output);
3948 }
3949
3950 output << R"(, "shape": )";
3951 switch (prior_shape)
3952 {
3953 case PriorDistributions::beta:
3954 output << R"("beta")";
3955 break;
3956 case PriorDistributions::gamma:
3957 output << R"("gamma")";
3958 break;
3959 case PriorDistributions::normal:
3960 output << R"("normal")";
3961 break;
3962 case PriorDistributions::invGamma:
3963 output << R"("inv_gamma")";
3964 break;
3965 case PriorDistributions::uniform:
3966 output << R"("uniform")";
3967 break;
3968 case PriorDistributions::invGamma2:
3969 output << R"("inv_gamma2")";
3970 break;
3971 case PriorDistributions::dirichlet:
3972 output << R"("dirichlet")";
3973 break;
3974 case PriorDistributions::weibull:
3975 output << R"("weibull")";
3976 break;
3977 case PriorDistributions::noShape:
3978 cerr << "Impossible case." << endl;
3979 exit(EXIT_FAILURE);
3980 }
3981 output << "}";
3982 }
3983
BasicPriorStatement(string name_arg,string subsample_name_arg,PriorDistributions prior_shape_arg,expr_t variance_arg,OptionsList options_list_arg)3984 BasicPriorStatement::BasicPriorStatement(string name_arg,
3985 string subsample_name_arg,
3986 PriorDistributions prior_shape_arg,
3987 expr_t variance_arg,
3988 OptionsList options_list_arg) :
3989 name{move(name_arg)},
3990 subsample_name{move(subsample_name_arg)},
3991 prior_shape{prior_shape_arg},
3992 variance{variance_arg},
3993 options_list{move(options_list_arg)}
3994 {
3995 }
3996
3997 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)3998 BasicPriorStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
3999 {
4000 if (prior_shape == PriorDistributions::noShape)
4001 {
4002 cerr << "ERROR: You must pass the shape option to the prior statement." << endl;
4003 exit(EXIT_FAILURE);
4004 }
4005
4006 if (options_list.num_options.find("mean") == options_list.num_options.end()
4007 && options_list.num_options.find("mode") == options_list.num_options.end())
4008 {
4009 cerr << "ERROR: You must pass at least one of mean and mode to the prior statement." << endl;
4010 exit(EXIT_FAILURE);
4011 }
4012
4013 if (auto it_stdev = options_list.num_options.find("stdev");
4014 (it_stdev == options_list.num_options.end() && !variance)
4015 || (it_stdev != options_list.num_options.end() && variance))
4016 {
4017 cerr << "ERROR: You must pass exactly one of stdev and variance to the prior statement." << endl;
4018 exit(EXIT_FAILURE);
4019 }
4020
4021 if (auto it_num = options_list.num_options.find("domain");
4022 it_num != options_list.num_options.end())
4023 {
4024 using namespace boost;
4025 vector<string> tokenizedDomain;
4026 split(tokenizedDomain, it_num->second, is_any_of("[ ]"), token_compress_on);
4027 if (tokenizedDomain.size() != 4)
4028 {
4029 cerr << "ERROR: You must pass exactly two values to the domain option." << endl;
4030 exit(EXIT_FAILURE);
4031 }
4032 }
4033 }
4034
4035 bool
is_structural_innovation(const SymbolType symb_type) const4036 BasicPriorStatement::is_structural_innovation(const SymbolType symb_type) const
4037 {
4038 if (symb_type == SymbolType::exogenous || symb_type == SymbolType::exogenousDet)
4039 return true;
4040 return false;
4041 }
4042
4043 void
get_base_name(const SymbolType symb_type,string & lhs_field) const4044 BasicPriorStatement::get_base_name(const SymbolType symb_type, string &lhs_field) const
4045 {
4046 if (symb_type == SymbolType::exogenous || symb_type == SymbolType::exogenousDet)
4047 lhs_field = "structural_innovation";
4048 else
4049 lhs_field = "measurement_error";
4050 }
4051
4052 void
writeCommonOutput(ostream & output,const string & lhs_field) const4053 BasicPriorStatement::writeCommonOutput(ostream &output, const string &lhs_field) const
4054 {
4055 output << lhs_field << " = estimation_info.empty_prior;" << endl;
4056
4057 writeCommonOutputHelper(output, "domain", lhs_field);
4058 writeCommonOutputHelper(output, "interval", lhs_field);
4059 writeCommonOutputHelper(output, "mean", lhs_field);
4060 writeCommonOutputHelper(output, "median", lhs_field);
4061 writeCommonOutputHelper(output, "mode", lhs_field);
4062
4063 assert(prior_shape != PriorDistributions::noShape);
4064 output << lhs_field << ".shape = " << static_cast<int>(prior_shape) << ";" << endl;
4065
4066 writeCommonOutputHelper(output, "shift", lhs_field);
4067 writeCommonOutputHelper(output, "stdev", lhs_field);
4068 writeCommonOutputHelper(output, "truncate", lhs_field);
4069
4070 if (variance)
4071 {
4072 output << lhs_field << ".variance = ";
4073 variance->writeOutput(output);
4074 output << ";" << endl;
4075 }
4076 }
4077
4078 void
writeCommonOutputHelper(ostream & output,const string & field,const string & lhs_field) const4079 BasicPriorStatement::writeCommonOutputHelper(ostream &output, const string &field, const string &lhs_field) const
4080 {
4081 if (auto itn = options_list.num_options.find(field);
4082 itn != options_list.num_options.end())
4083 output << lhs_field << "." << field << " = "<< itn->second << ";" << endl;
4084 }
4085
4086 void
writePriorOutput(ostream & output,string & lhs_field,const string & name2) const4087 BasicPriorStatement::writePriorOutput(ostream &output, string &lhs_field, const string &name2) const
4088 {
4089 if (subsample_name.empty())
4090 lhs_field += ".prior(1)";
4091 else
4092 {
4093 output << "subsamples_indx = get_existing_subsamples_indx('" << name << "','" << name2 << "');" << endl
4094 << "eisind = get_subsamples_range_indx(subsamples_indx, '" << subsample_name << "');" << endl;
4095 lhs_field += ".subsample_prior(eisind)";
4096 }
4097 writeCommonOutput(output, lhs_field);
4098 }
4099
4100 void
writeJsonPriorOutput(ostream & output) const4101 BasicPriorStatement::writeJsonPriorOutput(ostream &output) const
4102 {
4103 output << R"(, "name": ")" << name << R"(")"
4104 << R"(, "subsample": ")" << subsample_name << R"(")"
4105 << ", ";
4106 writeJsonShape(output);
4107 if (variance)
4108 {
4109 output << R"(, "variance": ")";
4110 variance->writeJsonOutput(output, {}, {});
4111 output << R"(")";
4112 }
4113 if (options_list.getNumberOfOptions())
4114 {
4115 output << ", ";
4116 options_list.writeJsonOutput(output);
4117 }
4118 }
4119
4120 void
writeJsonShape(ostream & output) const4121 BasicPriorStatement::writeJsonShape(ostream &output) const
4122 {
4123 output << R"("shape": )";
4124 switch (prior_shape)
4125 {
4126 case PriorDistributions::beta:
4127 output << R"("beta")";
4128 break;
4129 case PriorDistributions::gamma:
4130 output << R"("gamma")";
4131 break;
4132 case PriorDistributions::normal:
4133 output << R"("normal")";
4134 break;
4135 case PriorDistributions::invGamma:
4136 output << R"("inv_gamma")";
4137 break;
4138 case PriorDistributions::uniform:
4139 output << R"("uniform")";
4140 break;
4141 case PriorDistributions::invGamma2:
4142 output << R"("inv_gamma2")";
4143 break;
4144 case PriorDistributions::dirichlet:
4145 output << R"("dirichlet")";
4146 break;
4147 case PriorDistributions::weibull:
4148 output << R"("weibull")";
4149 break;
4150 case PriorDistributions::noShape:
4151 assert(prior_shape != PriorDistributions::noShape);
4152 }
4153 }
4154
PriorStatement(string name_arg,string subsample_name_arg,PriorDistributions prior_shape_arg,expr_t variance_arg,OptionsList options_list_arg)4155 PriorStatement::PriorStatement(string name_arg,
4156 string subsample_name_arg,
4157 PriorDistributions prior_shape_arg,
4158 expr_t variance_arg,
4159 OptionsList options_list_arg) :
4160 BasicPriorStatement{move(name_arg), move(subsample_name_arg), prior_shape_arg, variance_arg, move(options_list_arg)}
4161 {
4162 }
4163
4164 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const4165 PriorStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
4166 {
4167 string lhs_field = "estimation_info.parameter(eifind)";
4168 output << "eifind = get_new_or_existing_ei_index('parameter_prior_index', '"
4169 << name << "', '');" << endl
4170 << "estimation_info.parameter_prior_index(eifind) = {'" << name << "'};" << endl;
4171 writePriorOutput(output, lhs_field, "");
4172 }
4173
4174 void
writeJsonOutput(ostream & output) const4175 PriorStatement::writeJsonOutput(ostream &output) const
4176 {
4177 output << R"({"statementName": "prior")";
4178 writeJsonPriorOutput(output);
4179 output << "}";
4180 }
4181
StdPriorStatement(string name_arg,string subsample_name_arg,PriorDistributions prior_shape_arg,expr_t variance_arg,OptionsList options_list_arg,const SymbolTable & symbol_table_arg)4182 StdPriorStatement::StdPriorStatement(string name_arg,
4183 string subsample_name_arg,
4184 PriorDistributions prior_shape_arg,
4185 expr_t variance_arg,
4186 OptionsList options_list_arg,
4187 const SymbolTable &symbol_table_arg) :
4188 BasicPriorStatement{move(name_arg), move(subsample_name_arg), prior_shape_arg, variance_arg, move(options_list_arg)},
4189 symbol_table{symbol_table_arg}
4190 {
4191 }
4192
4193 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const4194 StdPriorStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
4195 {
4196 string lhs_field;
4197 get_base_name(symbol_table.getType(name), lhs_field);
4198 output << "eifind = get_new_or_existing_ei_index('" << lhs_field << "_prior_index', '"
4199 << name << "', '');" << endl
4200 << "estimation_info." << lhs_field << "_prior_index(eifind) = {'" << name << "'};" << endl;
4201
4202 lhs_field = "estimation_info." + lhs_field + "(eifind)";
4203 writePriorOutput(output, lhs_field, "");
4204 }
4205
4206 void
writeJsonOutput(ostream & output) const4207 StdPriorStatement::writeJsonOutput(ostream &output) const
4208 {
4209 output << R"({"statementName": "std_prior")";
4210 writeJsonPriorOutput(output);
4211 output << "}";
4212 }
4213
CorrPriorStatement(string name_arg1,string name_arg2,string subsample_name_arg,PriorDistributions prior_shape_arg,expr_t variance_arg,OptionsList options_list_arg,const SymbolTable & symbol_table_arg)4214 CorrPriorStatement::CorrPriorStatement(string name_arg1, string name_arg2,
4215 string subsample_name_arg,
4216 PriorDistributions prior_shape_arg,
4217 expr_t variance_arg,
4218 OptionsList options_list_arg,
4219 const SymbolTable &symbol_table_arg) :
4220 BasicPriorStatement{move(name_arg1), move(subsample_name_arg), prior_shape_arg, variance_arg, move(options_list_arg)},
4221 name1{move(name_arg2)},
4222 symbol_table{symbol_table_arg}
4223 {
4224 }
4225
4226 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)4227 CorrPriorStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
4228 {
4229 BasicPriorStatement::checkPass(mod_file_struct, warnings);
4230 if (symbol_table.getType(name) != symbol_table.getType(name1))
4231 {
4232 cerr << "ERROR: In the corr(A,B).prior statement, A and B must be of the same type. "
4233 << "In your case, " << name << " and " << name1 << " are of different "
4234 << "types." << endl;
4235 exit(EXIT_FAILURE);
4236 }
4237 }
4238
4239 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const4240 CorrPriorStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
4241 {
4242 string lhs_field;
4243 get_base_name(symbol_table.getType(name), lhs_field);
4244
4245 output << "eifind = get_new_or_existing_ei_index('" << lhs_field << "_corr_prior_index', '"
4246 << name << "', '" << name1 << "');" << endl
4247 << "estimation_info." << lhs_field << "_corr_prior_index(eifind) = {'"
4248 << name << ":" << name1 << "'};" << endl;
4249
4250 lhs_field = "estimation_info." + lhs_field + "_corr(eifind)";
4251 writePriorOutput(output, lhs_field, name1);
4252 }
4253
4254 void
writeJsonOutput(ostream & output) const4255 CorrPriorStatement::writeJsonOutput(ostream &output) const
4256 {
4257 output << R"({"statementName": "corr_prior")"
4258 << R"(, "name2": ")" << name1 << R"(")";
4259 writeJsonPriorOutput(output);
4260 output << "}";
4261 }
4262
PriorEqualStatement(string to_declaration_type_arg,string to_name1_arg,string to_name2_arg,string to_subsample_name_arg,string from_declaration_type_arg,string from_name1_arg,string from_name2_arg,string from_subsample_name_arg,const SymbolTable & symbol_table_arg)4263 PriorEqualStatement::PriorEqualStatement(string to_declaration_type_arg,
4264 string to_name1_arg,
4265 string to_name2_arg,
4266 string to_subsample_name_arg,
4267 string from_declaration_type_arg,
4268 string from_name1_arg,
4269 string from_name2_arg,
4270 string from_subsample_name_arg,
4271 const SymbolTable &symbol_table_arg) :
4272 to_declaration_type{move(to_declaration_type_arg)},
4273 to_name1{move(to_name1_arg)},
4274 to_name2{move(to_name2_arg)},
4275 to_subsample_name{move(to_subsample_name_arg)},
4276 from_declaration_type{move(from_declaration_type_arg)},
4277 from_name1{move(from_name1_arg)},
4278 from_name2{move(from_name2_arg)},
4279 from_subsample_name{move(from_subsample_name_arg)},
4280 symbol_table{symbol_table_arg}
4281 {
4282 }
4283
4284 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)4285 PriorEqualStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
4286 {
4287 if ((to_declaration_type != "par" && to_declaration_type != "std" && to_declaration_type != "corr")
4288 || (from_declaration_type != "par" && from_declaration_type != "std" && from_declaration_type != "corr"))
4289 {
4290 cerr << "Internal Dynare Error" << endl;
4291 exit(EXIT_FAILURE);
4292 }
4293 }
4294
4295 void
get_base_name(const SymbolType symb_type,string & lhs_field) const4296 PriorEqualStatement::get_base_name(const SymbolType symb_type, string &lhs_field) const
4297 {
4298 if (symb_type == SymbolType::exogenous || symb_type == SymbolType::exogenousDet)
4299 lhs_field = "structural_innovation";
4300 else
4301 lhs_field = "measurement_error";
4302 }
4303
4304 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const4305 PriorEqualStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
4306 {
4307 string lhs_field, rhs_field;
4308
4309 if (to_declaration_type == "par")
4310 lhs_field = "parameter";
4311 else
4312 get_base_name(symbol_table.getType(to_name1), lhs_field);
4313
4314 if (from_declaration_type == "par")
4315 rhs_field = "parameter";
4316 else
4317 get_base_name(symbol_table.getType(from_name1), rhs_field);
4318
4319 if (to_declaration_type == "corr")
4320 lhs_field += "_corr";
4321
4322 if (from_declaration_type == "corr")
4323 rhs_field += "_corr";
4324
4325 output << "ei_to_ind = get_new_or_existing_ei_index('" << lhs_field << "_prior_index', '"
4326 << to_name1 << "', '" << to_name2<< "');" << endl
4327 << "ei_from_ind = get_new_or_existing_ei_index('" << rhs_field << "_prior_index', '"
4328 << from_name1 << "', '" << from_name2<< "');" << endl
4329 << "estimation_info." << lhs_field << "_prior_index(ei_to_ind) = {'" << to_name1;
4330
4331 if (to_declaration_type == "corr")
4332 output << ":" << to_name2;
4333 output << "'};" << endl;
4334
4335 if (to_declaration_type == "par")
4336 lhs_field = "parameter";
4337
4338 if (from_declaration_type == "par")
4339 rhs_field = "parameter";
4340
4341 lhs_field = "estimation_info." + lhs_field + "(ei_to_ind)";
4342 rhs_field = "estimation_info." + rhs_field + "(ei_from_ind)";
4343
4344 if (to_subsample_name.empty())
4345 lhs_field += ".prior";
4346 else
4347 {
4348 output << "subsamples_to_indx = get_existing_subsamples_indx('" << to_name1 << "','" << to_name2 << "');" << endl
4349 << "ei_to_ss_ind = get_subsamples_range_indx(subsamples_to_indx, '" << to_subsample_name << "');" << endl;
4350 lhs_field += ".subsample_prior(ei_to_ss_ind)";
4351 }
4352
4353 if (from_subsample_name.empty())
4354 rhs_field += ".prior";
4355 else
4356 {
4357 output << "subsamples_from_indx = get_existing_subsamples_indx('" << from_name1 << "','" << from_name2 << "');" << endl
4358 << "ei_from_ss_ind = get_subsamples_range_indx(subsamples_from_indx, '" << from_subsample_name << "');" << endl;
4359 rhs_field += ".subsample_prior(ei_from_ss_ind)";
4360 }
4361
4362 output << lhs_field << " = " << rhs_field << ";" << endl;
4363 }
4364
4365 void
writeJsonOutput(ostream & output) const4366 PriorEqualStatement::writeJsonOutput(ostream &output) const
4367 {
4368 output << R"({"statementName": "prior_equal")"
4369 << R"(, "to_name1": ")" << to_name1 << R"(")";
4370 if (to_declaration_type == "corr")
4371 output << R"(, "to_name2": ")" << to_name2 << R"(")";
4372 output << R"(, "to_subsample": ")" << to_subsample_name << R"(")"
4373 << R"(, "from_name1": ")" << from_name1 << R"(")";
4374 if (to_declaration_type == "corr")
4375 output << R"(, "from_name2": ")" << from_name2 << R"(")";
4376 output << R"(, "from_subsample": ")" << from_subsample_name << R"(")"
4377 << "}";
4378 }
4379
BasicOptionsStatement(string name_arg,string subsample_name_arg,OptionsList options_list_arg)4380 BasicOptionsStatement::BasicOptionsStatement(string name_arg,
4381 string subsample_name_arg,
4382 OptionsList options_list_arg) :
4383 name{move(name_arg)},
4384 subsample_name{move(subsample_name_arg)},
4385 options_list{move(options_list_arg)}
4386 {
4387 }
4388
4389 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)4390 BasicOptionsStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
4391 {
4392 }
4393
4394 bool
is_structural_innovation(const SymbolType symb_type) const4395 BasicOptionsStatement::is_structural_innovation(const SymbolType symb_type) const
4396 {
4397 return symb_type == SymbolType::exogenous || symb_type == SymbolType::exogenousDet;
4398 }
4399
4400 void
get_base_name(const SymbolType symb_type,string & lhs_field) const4401 BasicOptionsStatement::get_base_name(const SymbolType symb_type, string &lhs_field) const
4402 {
4403 if (symb_type == SymbolType::exogenous || symb_type == SymbolType::exogenousDet)
4404 lhs_field = "structural_innovation";
4405 else
4406 lhs_field = "measurement_error";
4407 }
4408
4409 void
writeCommonOutput(ostream & output,const string & lhs_field) const4410 BasicOptionsStatement::writeCommonOutput(ostream &output, const string &lhs_field) const
4411 {
4412 output << lhs_field << " = estimation_info.empty_options;" << endl;
4413
4414 writeCommonOutputHelper(output, "bounds", lhs_field);
4415 writeCommonOutputHelper(output, "init", lhs_field);
4416 writeCommonOutputHelper(output, "jscale", lhs_field);
4417 }
4418
4419 void
writeCommonOutputHelper(ostream & output,const string & field,const string & lhs_field) const4420 BasicOptionsStatement::writeCommonOutputHelper(ostream &output, const string &field, const string &lhs_field) const
4421 {
4422 if (auto itn = options_list.num_options.find(field);
4423 itn != options_list.num_options.end())
4424 output << lhs_field << "." << field << " = " << itn->second << ";" << endl;
4425 }
4426
4427 void
writeOptionsOutput(ostream & output,string & lhs_field,const string & name2) const4428 BasicOptionsStatement::writeOptionsOutput(ostream &output, string &lhs_field, const string &name2) const
4429 {
4430 if (subsample_name.empty())
4431 lhs_field += ".options(1)";
4432 else
4433 {
4434 output << "subsamples_indx = get_existing_subsamples_indx('" << name << "','" << name2 << "');" << endl
4435 << "eisind = get_subsamples_range_indx(subsamples_indx, '" << subsample_name << "');" << endl;
4436 lhs_field += ".subsample_options(eisind)";
4437 }
4438 writeCommonOutput(output, lhs_field);
4439 }
4440
4441 void
writeJsonOptionsOutput(ostream & output) const4442 BasicOptionsStatement::writeJsonOptionsOutput(ostream &output) const
4443 {
4444 output << R"(, "name": ")" << name << R"(")";
4445 if (!subsample_name.empty())
4446 output << R"(, "subsample_name": ")" << subsample_name << R"(")";
4447 if (options_list.getNumberOfOptions())
4448 {
4449 output << ", ";
4450 options_list.writeJsonOutput(output);
4451 }
4452 }
4453
OptionsStatement(string name_arg,string subsample_name_arg,OptionsList options_list_arg)4454 OptionsStatement::OptionsStatement(string name_arg,
4455 string subsample_name_arg,
4456 OptionsList options_list_arg) :
4457 BasicOptionsStatement{move(name_arg), move(subsample_name_arg), move(options_list_arg)}
4458 {
4459 }
4460
4461 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const4462 OptionsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
4463 {
4464 string lhs_field = "estimation_info.parameter(eifind)";
4465 output << "eifind = get_new_or_existing_ei_index('parameter_options_index', '"
4466 << name << "', '');" << endl
4467 << "estimation_info.parameter_options_index(eifind) = {'" << name << "'};" << endl;
4468 writeOptionsOutput(output, lhs_field, "");
4469 }
4470
4471 void
writeJsonOutput(ostream & output) const4472 OptionsStatement::writeJsonOutput(ostream &output) const
4473 {
4474 output << R"({"statementName": "options")";
4475 writeJsonOptionsOutput(output);
4476 output << "}";
4477 }
4478
StdOptionsStatement(string name_arg,string subsample_name_arg,OptionsList options_list_arg,const SymbolTable & symbol_table_arg)4479 StdOptionsStatement::StdOptionsStatement(string name_arg,
4480 string subsample_name_arg,
4481 OptionsList options_list_arg,
4482 const SymbolTable &symbol_table_arg) :
4483 BasicOptionsStatement{move(name_arg), move(subsample_name_arg), move(options_list_arg)},
4484 symbol_table{symbol_table_arg}
4485 {
4486 }
4487
4488 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const4489 StdOptionsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
4490 {
4491 string lhs_field;
4492 get_base_name(symbol_table.getType(name), lhs_field);
4493 output << "eifind = get_new_or_existing_ei_index('" << lhs_field << "_options_index', '"
4494 << name << "', '');" << endl
4495 << "estimation_info." << lhs_field << "_options_index(eifind) = {'" << name << "'};" << endl;
4496
4497 lhs_field = "estimation_info." + lhs_field + "(eifind)";
4498 writeOptionsOutput(output, lhs_field, "");
4499 }
4500
4501 void
writeJsonOutput(ostream & output) const4502 StdOptionsStatement::writeJsonOutput(ostream &output) const
4503 {
4504 output << R"({"statementName": "std_options")";
4505 writeJsonOptionsOutput(output);
4506 output << "}";
4507 }
4508
CorrOptionsStatement(string name_arg1,string name_arg2,string subsample_name_arg,OptionsList options_list_arg,const SymbolTable & symbol_table_arg)4509 CorrOptionsStatement::CorrOptionsStatement(string name_arg1, string name_arg2,
4510 string subsample_name_arg,
4511 OptionsList options_list_arg,
4512 const SymbolTable &symbol_table_arg) :
4513 BasicOptionsStatement{move(name_arg1), move(subsample_name_arg), move(options_list_arg)},
4514 name1{move(name_arg2)},
4515 symbol_table{symbol_table_arg}
4516 {
4517 }
4518
4519 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)4520 CorrOptionsStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
4521 {
4522 if (symbol_table.getType(name) != symbol_table.getType(name1))
4523 {
4524 cerr << "ERROR: In the corr(A,B).options statement, A and B must be of the same type. "
4525 << "In your case, " << name << " and " << name1 << " are of different "
4526 << "types." << endl;
4527 exit(EXIT_FAILURE);
4528 }
4529 }
4530
4531 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const4532 CorrOptionsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
4533 {
4534 string lhs_field;
4535 get_base_name(symbol_table.getType(name), lhs_field);
4536
4537 output << "eifind = get_new_or_existing_ei_index('" << lhs_field << "_corr_options_index', '"
4538 << name << "', '" << name1 << "');" << endl
4539 << "estimation_info." << lhs_field << "_corr_options_index(eifind) = {'"
4540 << name << ":" << name1 << "'};" << endl;
4541
4542 lhs_field = "estimation_info." + lhs_field + "_corr(eifind)";
4543 writeOptionsOutput(output, lhs_field, name1);
4544 }
4545
4546 void
writeJsonOutput(ostream & output) const4547 CorrOptionsStatement::writeJsonOutput(ostream &output) const
4548 {
4549 output << R"({"statementName": "corr_options")"
4550 << R"(, "name2": ")" << name1 << R"(")";
4551 writeJsonOptionsOutput(output);
4552 output << "}";
4553 }
4554
OptionsEqualStatement(string to_declaration_type_arg,string to_name1_arg,string to_name2_arg,string to_subsample_name_arg,string from_declaration_type_arg,string from_name1_arg,string from_name2_arg,string from_subsample_name_arg,const SymbolTable & symbol_table_arg)4555 OptionsEqualStatement::OptionsEqualStatement(string to_declaration_type_arg,
4556 string to_name1_arg,
4557 string to_name2_arg,
4558 string to_subsample_name_arg,
4559 string from_declaration_type_arg,
4560 string from_name1_arg,
4561 string from_name2_arg,
4562 string from_subsample_name_arg,
4563 const SymbolTable &symbol_table_arg) :
4564 to_declaration_type{move(to_declaration_type_arg)},
4565 to_name1{move(to_name1_arg)},
4566 to_name2{move(to_name2_arg)},
4567 to_subsample_name{move(to_subsample_name_arg)},
4568 from_declaration_type{move(from_declaration_type_arg)},
4569 from_name1{move(from_name1_arg)},
4570 from_name2{move(from_name2_arg)},
4571 from_subsample_name{move(from_subsample_name_arg)},
4572 symbol_table{symbol_table_arg}
4573 {
4574 }
4575
4576 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)4577 OptionsEqualStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
4578 {
4579 if ((to_declaration_type != "par" && to_declaration_type != "std" && to_declaration_type != "corr")
4580 || (from_declaration_type != "par" && from_declaration_type != "std" && from_declaration_type != "corr"))
4581 {
4582 cerr << "Internal Dynare Error" << endl;
4583 exit(EXIT_FAILURE);
4584 }
4585 }
4586
4587 void
writeJsonOutput(ostream & output) const4588 OptionsEqualStatement::writeJsonOutput(ostream &output) const
4589 {
4590 output << R"({"statementName": "options_equal")"
4591 << R"(, "to_name1": ")" << to_name1 << R"(")";
4592 if (to_declaration_type == "corr")
4593 output << R"(, "to_name2": ")" << to_name2 << R"(")";
4594 output << R"(, "to_subsample": ")" << to_subsample_name << R"(")"
4595 << R"(, "from_name1": ")" << from_name1 << R"(")";
4596 if (to_declaration_type == "corr")
4597 output << R"(, "from_name2": ")" << from_name2 << R"(")";
4598 output << R"(, "from_subsample": ")" << from_subsample_name << R"(")"
4599 << "}";
4600 }
4601
4602 void
get_base_name(const SymbolType symb_type,string & lhs_field) const4603 OptionsEqualStatement::get_base_name(const SymbolType symb_type, string &lhs_field) const
4604 {
4605 if (symb_type == SymbolType::exogenous || symb_type == SymbolType::exogenousDet)
4606 lhs_field = "structural_innovation";
4607 else
4608 lhs_field = "measurement_error";
4609 }
4610
4611 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const4612 OptionsEqualStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
4613 {
4614 string lhs_field, rhs_field;
4615
4616 if (to_declaration_type == "par")
4617 lhs_field = "parameter";
4618 else
4619 get_base_name(symbol_table.getType(to_name1), lhs_field);
4620
4621 if (from_declaration_type == "par")
4622 rhs_field = "parameter";
4623 else
4624 get_base_name(symbol_table.getType(from_name1), rhs_field);
4625
4626 if (to_declaration_type == "corr")
4627 lhs_field += "_corr";
4628
4629 if (from_declaration_type == "corr")
4630 rhs_field += "_corr";
4631
4632 output << "ei_to_ind = get_new_or_existing_ei_index('" << lhs_field << "_options_index', '"
4633 << to_name1 << "', '" << to_name2<< "');" << endl
4634 << "ei_from_ind = get_new_or_existing_ei_index('" << rhs_field << "_options_index', '"
4635 << from_name1 << "', '" << from_name2<< "');" << endl
4636 << "estimation_info." << lhs_field << "_options_index(ei_to_ind) = {'" << to_name1;
4637
4638 if (to_declaration_type == "corr")
4639 output << ":" << to_name2;
4640 output << "'};" << endl;
4641
4642 if (to_declaration_type == "par")
4643 lhs_field = "parameter";
4644
4645 if (from_declaration_type == "par")
4646 rhs_field = "parameter";
4647
4648 lhs_field = "estimation_info." + lhs_field + "(ei_to_ind)";
4649 rhs_field = "estimation_info." + rhs_field + "(ei_from_ind)";
4650
4651 if (to_subsample_name.empty())
4652 lhs_field += ".options";
4653 else
4654 {
4655 output << "subsamples_to_indx = get_existing_subsamples_indx('" << to_name1 << "','" << to_name2 << "');" << endl
4656 << "ei_to_ss_ind = get_subsamples_range_indx(subsamples_to_indx, '" << to_subsample_name << "');" << endl;
4657 lhs_field += ".subsample_options(ei_to_ss_ind)";
4658 }
4659
4660 if (from_subsample_name.empty())
4661 rhs_field += ".options";
4662 else
4663 {
4664 output << "subsamples_from_indx = get_existing_subsamples_indx('" << from_name1 << "','" << from_name2 << "');" << endl
4665 << "ei_from_ss_ind = get_subsamples_range_indx(subsamples_from_indx, '" << from_subsample_name << "');" << endl;
4666 rhs_field += ".subsample_options(ei_from_ss_ind)";
4667 }
4668
4669 output << lhs_field << " = " << rhs_field << ";" << endl;
4670 }
4671
CalibSmootherStatement(SymbolList symbol_list_arg,OptionsList options_list_arg)4672 CalibSmootherStatement::CalibSmootherStatement(SymbolList symbol_list_arg,
4673 OptionsList options_list_arg)
4674 : symbol_list{move(symbol_list_arg)}, options_list{move(options_list_arg)}
4675 {
4676 }
4677
4678 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)4679 CalibSmootherStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
4680 {
4681 mod_file_struct.calib_smoother_present = true;
4682 try
4683 {
4684 symbol_list.checkPass(warnings, { SymbolType::endogenous });
4685 }
4686 catch (SymbolList::SymbolListException &e)
4687 {
4688 cerr << "ERROR: calib_smoother: " << e.message << endl;
4689 exit(EXIT_FAILURE);
4690 }
4691 }
4692
4693 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const4694 CalibSmootherStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
4695 {
4696 options_list.writeOutput(output);
4697 if (options_list.string_options.find("parameter_set") == options_list.string_options.end())
4698 output << "options_.parameter_set = 'calibration';" << endl;
4699 symbol_list.writeOutput("var_list_", output);
4700 output << "options_.smoother = true;" << endl
4701 << "options_.order = 1;" << endl
4702 << "[oo_, M_, options_, bayestopt_] = evaluate_smoother(options_.parameter_set, var_list_, M_, oo_, options_, bayestopt_, estim_params_);" << endl;
4703 }
4704
4705 void
writeJsonOutput(ostream & output) const4706 CalibSmootherStatement::writeJsonOutput(ostream &output) const
4707 {
4708 output << R"({"statementName": "calib_smoother")";
4709 if (options_list.getNumberOfOptions())
4710 {
4711 output << ", ";
4712 options_list.writeJsonOutput(output);
4713 }
4714 if (!symbol_list.empty())
4715 {
4716 output << ", ";
4717 symbol_list.writeJsonOutput(output);
4718 }
4719 output << "}";
4720 }
4721
ExtendedPathStatement(OptionsList options_list_arg)4722 ExtendedPathStatement::ExtendedPathStatement(OptionsList options_list_arg)
4723 : options_list{move(options_list_arg)}
4724 {
4725 }
4726
4727 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)4728 ExtendedPathStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
4729 {
4730 mod_file_struct.extended_path_present = true;
4731
4732 if (options_list.num_options.find("periods") == options_list.num_options.end())
4733 {
4734 cerr << "ERROR: the 'periods' option of 'extended_path' is mandatory" << endl;
4735 exit(EXIT_FAILURE);
4736 }
4737
4738 // Fill in option_occbin of mod_file_struct
4739 if (options_list.num_options.find("occbin") != options_list.string_options.end())
4740 mod_file_struct.occbin_option = true;
4741 }
4742
4743 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const4744 ExtendedPathStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
4745 {
4746 // Beware: options do not have the same name in the interface and in the M code...
4747
4748 for (const auto &num_option : options_list.num_options)
4749 if (num_option.first != "periods")
4750 output << "options_." << num_option.first << " = " << num_option.second << ";" << endl;
4751
4752 output << "extended_path([], " << options_list.num_options.find("periods")->second
4753 << ", [], options_, M_, oo_);" << endl;
4754 }
4755
4756 void
writeJsonOutput(ostream & output) const4757 ExtendedPathStatement::writeJsonOutput(ostream &output) const
4758 {
4759 output << R"({"statementName": "extended_path")";
4760 if (options_list.getNumberOfOptions())
4761 {
4762 output << ", ";
4763 options_list.writeJsonOutput(output);
4764 }
4765 output << "}";
4766 }
4767
4768 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const4769 ModelDiagnosticsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
4770 {
4771 output << "model_diagnostics(M_,options_,oo_);" << endl;
4772 }
4773
4774 void
writeJsonOutput(ostream & output) const4775 ModelDiagnosticsStatement::writeJsonOutput(ostream &output) const
4776 {
4777 output << R"({"statementName": "model_diagnostics"})";
4778 }
4779
Smoother2histvalStatement(OptionsList options_list_arg)4780 Smoother2histvalStatement::Smoother2histvalStatement(OptionsList options_list_arg) :
4781 options_list{move(options_list_arg)}
4782 {
4783 }
4784
4785 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const4786 Smoother2histvalStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
4787 {
4788 options_list.writeOutput(output, "options_smoother2histval");
4789 output << "smoother2histval(options_smoother2histval);" << endl;
4790 }
4791
4792 void
writeJsonOutput(ostream & output) const4793 Smoother2histvalStatement::writeJsonOutput(ostream &output) const
4794 {
4795 output << R"({"statementName": "smoother_2_histval")";
4796 if (options_list.getNumberOfOptions())
4797 {
4798 output << ", ";
4799 options_list.writeJsonOutput(output);
4800 }
4801 output << "}";
4802 }
4803
GMMEstimationStatement(SymbolList symbol_list_arg,OptionsList options_list_arg)4804 GMMEstimationStatement::GMMEstimationStatement(SymbolList symbol_list_arg,
4805 OptionsList options_list_arg) :
4806 symbol_list{move(symbol_list_arg)},
4807 options_list{move(options_list_arg)}
4808 {
4809 }
4810
4811 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)4812 GMMEstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
4813 {
4814 try
4815 {
4816 symbol_list.checkPass(warnings, { SymbolType::endogenous });
4817 }
4818 catch (SymbolList::SymbolListException &e)
4819 {
4820 cerr << "ERROR: gmm_estimation: " << e.message << endl;
4821 exit(EXIT_FAILURE);
4822 }
4823 }
4824
4825 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const4826 GMMEstimationStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
4827 {
4828 symbol_list.writeOutput("var_list_", output);
4829 options_list.writeOutput(output);
4830 output << "[M_, oo_, estim_params_, bayestopt_, dataset_, dataset_info] = "
4831 << "GMM_SMM_estimation_core(var_list_, M_, options_, oo_, estim_params_, bayestopt_, dataset_, dataset_info, 'GMM');" << endl;
4832 }
4833
4834 void
writeJsonOutput(ostream & output) const4835 GMMEstimationStatement::writeJsonOutput(ostream &output) const
4836 {
4837 output << R"({"statementName": "gmm_estimation")";
4838 if (options_list.getNumberOfOptions())
4839 {
4840 output << ", ";
4841 options_list.writeJsonOutput(output);
4842 }
4843 if (!symbol_list.empty())
4844 {
4845 output << ", ";
4846 symbol_list.writeJsonOutput(output);
4847 }
4848 output << "}";
4849 }
4850
SMMEstimationStatement(SymbolList symbol_list_arg,OptionsList options_list_arg)4851 SMMEstimationStatement::SMMEstimationStatement(SymbolList symbol_list_arg,
4852 OptionsList options_list_arg) :
4853 symbol_list{move(symbol_list_arg)},
4854 options_list{move(options_list_arg)}
4855 {
4856 }
4857
4858 void
checkPass(ModFileStructure & mod_file_struct,WarningConsolidation & warnings)4859 SMMEstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
4860 {
4861 try
4862 {
4863 symbol_list.checkPass(warnings, { SymbolType::endogenous });
4864 }
4865 catch (SymbolList::SymbolListException &e)
4866 {
4867 cerr << "ERROR: smm_estimation: " << e.message << endl;
4868 exit(EXIT_FAILURE);
4869 }
4870 }
4871
4872 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const4873 SMMEstimationStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
4874 {
4875 symbol_list.writeOutput("var_list_", output);
4876 options_list.writeOutput(output);
4877 output << "[M_, oo_, estim_params_, bayestopt_, dataset_, dataset_info] = "
4878 << "GMM_SMM_estimation_core(var_list_, M_, options_, oo_, estim_params_, bayestopt_, dataset_, dataset_info, 'SMM');" << endl;
4879 }
4880
4881 void
writeJsonOutput(ostream & output) const4882 SMMEstimationStatement::writeJsonOutput(ostream &output) const
4883 {
4884 output << R"({"statementName": "smm_estimation")";
4885 if (options_list.getNumberOfOptions())
4886 {
4887 output << ", ";
4888 options_list.writeJsonOutput(output);
4889 }
4890 if (!symbol_list.empty())
4891 {
4892 output << ", ";
4893 symbol_list.writeJsonOutput(output);
4894 }
4895 output << "}";
4896 }
4897
GenerateIRFsStatement(OptionsList options_list_arg,vector<string> generate_irf_names_arg,vector<map<string,double>> generate_irf_elements_arg)4898 GenerateIRFsStatement::GenerateIRFsStatement(OptionsList options_list_arg,
4899 vector<string> generate_irf_names_arg,
4900 vector<map<string, double>> generate_irf_elements_arg) :
4901 options_list{move(options_list_arg)},
4902 generate_irf_names{move(generate_irf_names_arg)},
4903 generate_irf_elements{move(generate_irf_elements_arg)}
4904 {
4905 }
4906
4907 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const4908 GenerateIRFsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
4909 {
4910 options_list.writeOutput(output);
4911
4912 if (generate_irf_names.empty())
4913 return;
4914
4915 output << "options_.irf_opt.irf_shock_graphtitles = { ";
4916 for (const auto &generate_irf_name : generate_irf_names)
4917 output << "'" << generate_irf_name << "'; ";
4918 output << "};" << endl;
4919
4920 output << "options_.irf_opt.irf_shocks = zeros(M_.exo_nbr, "
4921 << generate_irf_names.size() << ");" << endl;
4922
4923 for (size_t i = 0; i < generate_irf_names.size(); i++)
4924 {
4925 map<string, double> m = generate_irf_elements[i];
4926 for (auto &it : m)
4927 output << "options_.irf_opt.irf_shocks(M_.exo_names == '"
4928 << it.first << "', " << i + 1 << ") = "
4929 << it.second << ";" << endl;
4930 }
4931 }
4932
4933 void
writeJsonOutput(ostream & output) const4934 GenerateIRFsStatement::writeJsonOutput(ostream &output) const
4935 {
4936 output << R"({"statementName": "generate_irfs")";
4937 if (options_list.getNumberOfOptions())
4938 {
4939 output << ", ";
4940 options_list.writeJsonOutput(output);
4941 }
4942
4943 if (!generate_irf_names.empty())
4944 {
4945 output << R"(, "irf_elements": [)";
4946 for (size_t i = 0; i < generate_irf_names.size(); i++)
4947 {
4948 output << R"({"name": ")" << generate_irf_names[i] << R"(", "shocks": [)";
4949 map<string, double> m = generate_irf_elements[i];
4950 size_t idx = 0;
4951 for (auto it = m.begin(); it != m.end(); ++it, idx++)
4952 {
4953 output << R"({"exogenous_variable": ")" << it->first << R"(", )"
4954 << R"("exogenous_variable_value": ")" << it->second << R"("})";
4955 if (idx + 1 < m.size())
4956 output << ", ";
4957 }
4958 output << "]}";
4959 if (i + 1 < generate_irf_names.size())
4960 output << ", ";
4961 }
4962 output << "]";
4963 }
4964 output << "}";
4965 }
4966
VarExpectationModelStatement(string model_name_arg,expr_t expression_arg,string aux_model_name_arg,string horizon_arg,expr_t discount_arg,const SymbolTable & symbol_table_arg)4967 VarExpectationModelStatement::VarExpectationModelStatement(string model_name_arg,
4968 expr_t expression_arg,
4969 string aux_model_name_arg,
4970 string horizon_arg,
4971 expr_t discount_arg,
4972 const SymbolTable &symbol_table_arg) :
4973 model_name{move(model_name_arg)}, expression{expression_arg},
4974 aux_model_name{move(aux_model_name_arg)}, horizon{move(horizon_arg)},
4975 discount{discount_arg}, symbol_table{symbol_table_arg}
4976 {
4977 }
4978
4979 void
substituteUnaryOpNodes(const lag_equivalence_table_t & nodes,ExprNode::subst_table_t & subst_table)4980 VarExpectationModelStatement::substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, ExprNode::subst_table_t &subst_table)
4981 {
4982 vector<BinaryOpNode *> neweqs;
4983 expression = expression->substituteUnaryOpNodes(nodes, subst_table, neweqs);
4984 if (neweqs.size() > 0)
4985 {
4986 cerr << "ERROR: the 'expression' option of var_expectation_model contains a variable with a unary operator that is not present in the VAR model" << endl;
4987 exit(EXIT_FAILURE);
4988 }
4989 }
4990
4991 void
substituteDiff(const lag_equivalence_table_t & nodes,ExprNode::subst_table_t & subst_table)4992 VarExpectationModelStatement::substituteDiff(const lag_equivalence_table_t &nodes, ExprNode::subst_table_t &subst_table)
4993 {
4994 vector<BinaryOpNode *> neweqs;
4995 expression = expression->substituteDiff(nodes, subst_table, neweqs);
4996 if (neweqs.size() > 0)
4997 {
4998 cerr << "ERROR: the 'expression' option of var_expectation_model contains a diff'd variable that is not present in the VAR model" << endl;
4999 exit(EXIT_FAILURE);
5000 }
5001 }
5002
5003 void
matchExpression()5004 VarExpectationModelStatement::matchExpression()
5005 {
5006 try
5007 {
5008 auto vpc = expression->matchLinearCombinationOfVariables();
5009 for (const auto &it : vpc)
5010 {
5011 if (get<1>(it) != 0)
5012 throw ExprNode::MatchFailureException{"lead/lags are not allowed"};
5013 if (symbol_table.getType(get<0>(it)) != SymbolType::endogenous)
5014 throw ExprNode::MatchFailureException{"Variable is not an endogenous"};
5015 vars_params_constants.emplace_back(get<0>(it), get<2>(it), get<3>(it));
5016 }
5017 }
5018 catch (ExprNode::MatchFailureException &e)
5019 {
5020 cerr << "ERROR: expression in var_expectation_model is not of the expected form: " << e.message << endl;
5021 exit(EXIT_FAILURE);
5022 }
5023 }
5024
5025 void
writeOutput(ostream & output,const string & basename,bool minimal_workspace) const5026 VarExpectationModelStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
5027 {
5028 string mstruct = "M_.var_expectation." + model_name;
5029 output << mstruct << ".auxiliary_model_name = '" << aux_model_name << "';" << endl
5030 << mstruct << ".horizon = " << horizon << ';' << endl;
5031
5032 if (!vars_params_constants.size())
5033 {
5034 cerr << "ERROR: VarExpectationModelStatement::writeOutput: matchExpression() has not been called" << endl;
5035 exit(EXIT_FAILURE);
5036 }
5037
5038 ostringstream vars_list, params_list, constants_list;
5039 for (auto it = vars_params_constants.begin(); it != vars_params_constants.end(); ++it)
5040 {
5041 if (it != vars_params_constants.begin())
5042 {
5043 vars_list << ", ";
5044 params_list << ", ";
5045 constants_list << ", ";
5046 }
5047 vars_list << symbol_table.getTypeSpecificID(get<0>(*it))+1;
5048 if (get<1>(*it) == -1)
5049 params_list << "NaN";
5050 else
5051 params_list << symbol_table.getTypeSpecificID(get<1>(*it))+1;
5052 constants_list << get<2>(*it);
5053 }
5054 output << mstruct << ".expr.vars = [ " << vars_list.str() << " ];" << endl
5055 << mstruct << ".expr.params = [ " << params_list.str() << " ];" << endl
5056 << mstruct << ".expr.constants = [ " << constants_list.str() << " ];" << endl;
5057
5058 if (auto disc_var = dynamic_cast<const VariableNode *>(discount);
5059 disc_var)
5060 output << mstruct << ".discount_index = " << symbol_table.getTypeSpecificID(disc_var->symb_id) + 1 << ';' << endl;
5061 else
5062 {
5063 output << mstruct << ".discount_value = ";
5064 discount->writeOutput(output);
5065 output << ';' << endl;
5066 }
5067 output << mstruct << ".param_indices = [ ";
5068 for (int param_id : aux_params_ids)
5069 output << symbol_table.getTypeSpecificID(param_id)+1 << ' ';
5070 output << "];" << endl;
5071 }
5072
5073 void
writeJsonOutput(ostream & output) const5074 VarExpectationModelStatement::writeJsonOutput(ostream &output) const
5075 {
5076 output << R"({"statementName": "var_expectation_model",)"
5077 << R"("model_name": ")" << model_name << R"(", )"
5078 << R"("expression": ")";
5079 expression->writeOutput(output);
5080 output << R"(", )"
5081 << R"("auxiliary_model_name": ")" << aux_model_name << R"(", )"
5082 << R"("horizon": ")" << horizon << R"(", )"
5083 << R"("discount": ")";
5084 discount->writeOutput(output);
5085 output << R"("})";
5086 }
5087