diff --git a/src/ModFile.cc b/src/ModFile.cc index d2195270ebd940ff1318a31acd93194ae5b19461..7f1e5d4a520c5bf757b12f4f3f0e5fdb5d7871d0 100644 --- a/src/ModFile.cc +++ b/src/ModFile.cc @@ -519,6 +519,8 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const epilogue.detrend(trend_symbols, nonstationary_symbols); } + epilogue.toStatic(); + mod_file_struct.orig_eq_nbr = dynamic_model.equation_number(); if (mod_file_struct.ramsey_model_present) { diff --git a/src/ModelEquationBlock.cc b/src/ModelEquationBlock.cc index 690b88e7d799373dc31ed66f0666d1fbca840a8b..9107b1b4af62bb1c6ca32dfe1ab27656b7c28c85 100644 --- a/src/ModelEquationBlock.cc +++ b/src/ModelEquationBlock.cc @@ -295,8 +295,8 @@ Epilogue::Epilogue(SymbolTable &symbol_table_arg, Epilogue::Epilogue(const Epilogue &m) : DynamicModel {m} { - for (const auto &it : m.def_table) - def_table.emplace_back(it.first, it.second->clone(*this)); + for (const auto &it : m.dynamic_def_table) + dynamic_def_table.emplace_back(it.first, it.second->clone(*this)); } Epilogue & @@ -304,9 +304,9 @@ Epilogue::operator=(const Epilogue &m) { DynamicModel::operator=(m); - def_table.clear(); - for (const auto &it : m.def_table) - def_table.emplace_back(it.first, it.second->clone(*this)); + dynamic_def_table.clear(); + for (const auto &it : m.dynamic_def_table) + dynamic_def_table.emplace_back(it.first, it.second->clone(*this)); return *this; } @@ -314,17 +314,17 @@ Epilogue::operator=(const Epilogue &m) void Epilogue::addDefinition(int symb_id, expr_t expr) { - def_table.emplace_back(symb_id, expr); + dynamic_def_table.emplace_back(symb_id, expr); } void Epilogue::checkPass(WarningConsolidation &warnings) const { - if (def_table.size() == 0) + if (dynamic_def_table.size() == 0) return; vector<int> so_far_defined; - for (const auto & it : def_table) + for (const auto & it : dynamic_def_table) if (find(so_far_defined.begin(), so_far_defined.end(), it.first) != so_far_defined.end()) { cerr << "WARNING: in the 'epilogue' block, variable '" << it.first @@ -335,25 +335,32 @@ Epilogue::checkPass(WarningConsolidation &warnings) const so_far_defined.push_back(it.first); } +void +Epilogue::toStatic() +{ + for (const auto & [symb_id, expr] : dynamic_def_table) + static_def_table.emplace_back(make_pair(symb_id, expr->toStatic(*this))); +} + void Epilogue::detrend(const map<int, expr_t> & trend_symbols_map, const nonstationary_symbols_map_t & nonstationary_symbols_map) { for (auto it = nonstationary_symbols_map.crbegin(); it != nonstationary_symbols_map.crend(); it++) - for (auto & [symb_id, expr] : def_table) + for (auto & [symb_id, expr] : dynamic_def_table) { expr = expr->detrend(it->first, it->second.first, it->second.second); assert(expr != nullptr); } - for (auto & [symb_id, expr] : def_table) + for (auto & [symb_id, expr] : dynamic_def_table) { expr = expr->removeTrendLeadLag(trend_symbols_map); assert(expr != nullptr); } - for (auto & [symb_id, expr] : def_table) + for (auto & [symb_id, expr] : dynamic_def_table) { expr = expr->replaceTrendVar(); assert(expr != nullptr); @@ -363,10 +370,17 @@ Epilogue::detrend(const map<int, expr_t> & trend_symbols_map, void Epilogue::writeEpilogueFile(const string &basename) const { - if (def_table.size() == 0) + if (dynamic_def_table.empty()) return; - string filename = packageDir(basename) + "/epilogue.m"; + writeEpilogueFile(basename, true); + writeEpilogueFile(basename, false); +} + +void +Epilogue::writeEpilogueFile(const string & basename, bool dynamic_file) const +{ + string filename = packageDir(basename) + "/epilogue_" + (dynamic_file ? "dynamic" : "static") + ".m"; ofstream output; output.open(filename, ios::out | ios::binary); if (!output.is_open()) @@ -375,26 +389,33 @@ Epilogue::writeEpilogueFile(const string &basename) const exit(EXIT_FAILURE); } - ExprNodeOutputType output_type = ExprNodeOutputType::epilogueFile; - output << "function dseries__ = epilogue(params, dseries__)" << endl - << "% function dseries__ = epilogue(params, dseries__)" << endl + output << "function dseries__ = epilogue_" << (dynamic_file ? "dynamic" : "static") << "(params, dseries__)" << endl + << "% function dseries__ = epilogue_" << (dynamic_file ? "dynamic" : "static") << "(params, dseries__)" << endl << "% Epilogue file generated by Dynare preprocessor" << endl << endl << "simul_end_date = lastdate(dseries__);" << endl; + int def_table_idx = 0; deriv_node_temp_terms_t tef_terms; temporary_terms_t temporary_terms; temporary_terms_idxs_t temporary_terms_idxs; - for (const auto & it : def_table) - if (it.second->containsExternalFunction()) - it.second->writeExternalFunctionOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms); + for (const auto & [symb_id, expr] : dynamic_def_table) + { + if (expr->containsExternalFunction()) + if (dynamic_file) + expr->writeExternalFunctionOutput(output, ExprNodeOutputType::epilogueFile, temporary_terms, temporary_terms_idxs, tef_terms); + else + static_def_table.at(def_table_idx).second->writeExternalFunctionOutput(output, ExprNodeOutputType::epilogueFile, temporary_terms, temporary_terms_idxs, tef_terms); + def_table_idx++; + } output << endl; - for (const auto & it : def_table) + def_table_idx = 0; + for (const auto & [symb_id, expr] : dynamic_def_table) { - int max_lag = it.second->maxLagWithDiffsExpanded(); + int max_lag = expr->maxLagWithDiffsExpanded(); set<int> used_symbols; - it.second->collectVariables(SymbolType::endogenous, used_symbols); - it.second->collectVariables(SymbolType::exogenous, used_symbols); - it.second->collectVariables(SymbolType::epilogue, used_symbols); + expr->collectVariables(SymbolType::endogenous, used_symbols); + expr->collectVariables(SymbolType::exogenous, used_symbols); + expr->collectVariables(SymbolType::epilogue, used_symbols); output << "simul_begin_date = firstobservedperiod(dseries__{"; for (auto it1 = used_symbols.begin(); it1 != used_symbols.end(); it1++) @@ -403,13 +424,20 @@ Epilogue::writeEpilogueFile(const string &basename) const output << ", "; output << "'" << symbol_table.getName(*it1) << "'"; } - output << "}) + " << max_lag << " + 1;" << endl - << "if ~dseries__.exist('" << symbol_table.getName(it.first) << "')" << endl - << " dseries__ = [dseries__ dseries(NaN(dseries__.nobs,1), dseries__.firstdate, '" << symbol_table.getName(it.first)<< "')];" << endl + if (dynamic_file) + output << "}) + " << max_lag << " + 1;" << endl; + else + output << "});" << endl; + output << "if ~dseries__.exist('" << symbol_table.getName(symb_id) << "')" << endl + << " dseries__ = [dseries__ dseries(NaN(dseries__.nobs,1), dseries__.firstdate, '" << symbol_table.getName(symb_id)<< "')];" << endl << "end" << endl << "from simul_begin_date to simul_end_date do " - << "dseries__." << symbol_table.getName(it.first) << "(t) = "; - it.second->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms); + << "dseries__." << symbol_table.getName(symb_id) << "(t) = "; + if (dynamic_file) + expr->writeOutput(output, ExprNodeOutputType::epilogueFile, temporary_terms, temporary_terms_idxs, tef_terms); + else + static_def_table.at(def_table_idx).second->writeOutput(output, ExprNodeOutputType::epilogueFile, temporary_terms, temporary_terms_idxs, tef_terms); + def_table_idx++; output << ";" << endl << endl; } output << "end" << endl; @@ -419,17 +447,17 @@ Epilogue::writeEpilogueFile(const string &basename) const void Epilogue::writeOutput(ostream &output) const { - if (def_table.empty()) + if (dynamic_def_table.empty()) return; int idx = 1; - output << "M_.epilogue_names = cell(" << def_table.size() << ",1);" << endl; - for (const auto & [symb_id, expr] : def_table) + output << "M_.epilogue_names = cell(" << dynamic_def_table.size() << ",1);" << endl; + for (const auto & [symb_id, expr] : dynamic_def_table) output << "M_.epilogue_names{" << idx++ << "} = '" << symbol_table.getName(symb_id) << "';" << endl; set<int> endogs; - for (const auto & [symb_id, expr] : def_table) + for (const auto & [symb_id, expr] : dynamic_def_table) expr->collectVariables(SymbolType::endogenous, endogs); SymbolList symbol_list; diff --git a/src/ModelEquationBlock.hh b/src/ModelEquationBlock.hh index 434ecbf9ee5d73a20a2147fdb19bde0ecf93a32c..05f2b398b5b65b9e91702b1930c0259f5f8da3d6 100644 --- a/src/ModelEquationBlock.hh +++ b/src/ModelEquationBlock.hh @@ -70,7 +70,7 @@ class Epilogue : public DynamicModel { private: //! Associates a set of symbol IDs (the variable(s) assigned in a given statement) to an expression (their assigned value) - vector<pair<int, expr_t>> def_table; + vector<pair<int, expr_t>> dynamic_def_table, static_def_table; public: Epilogue(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, @@ -89,6 +89,9 @@ public: //! Checks that no variable is declared twice void checkPass(WarningConsolidation &warnings) const; + //! Creates static epilogue equations + void toStatic(); + //! Deal with trend variables in the epilogue block void detrend(const map<int, expr_t> & trend_symbols_map, const nonstationary_symbols_map_t & nonstationary_symbols_map); @@ -98,6 +101,9 @@ public: //! Write Output void writeOutput(ostream &output) const; +private: + //! Helper for public writeEpilogueFile + void writeEpilogueFile(const string & basename, bool dynamic_file) const; };