From 4111bc8cfcf6a36e538575dd901b98ba523e457c Mon Sep 17 00:00:00 2001
From: Houtan Bastani <houtan@dynare.org>
Date: Wed, 11 Dec 2019 15:49:29 +0100
Subject: [PATCH] epilogue: create _dynamic and _static files

#36
---
 src/ModFile.cc            |  2 +
 src/ModelEquationBlock.cc | 94 +++++++++++++++++++++++++--------------
 src/ModelEquationBlock.hh |  8 +++-
 3 files changed, 70 insertions(+), 34 deletions(-)

diff --git a/src/ModFile.cc b/src/ModFile.cc
index d2195270..7f1e5d4a 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 690b88e7..9107b1b4 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 434ecbf9..05f2b398 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;
 };
 
 
-- 
GitLab