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