From d511e3ec3a9299ea31d4eaa357c63cc367e33afe Mon Sep 17 00:00:00 2001
From: Michel Juillard <michel.juillard@mjui.fr>
Date: Mon, 29 Jun 2020 11:38:41 +0200
Subject: [PATCH] add deterministic_trends statement (only used by Dynare
 Julia)

---
 src/ComputingTasks.cc | 50 +++++++++++++++++++++++++++++++++++++++++++
 src/ComputingTasks.hh | 14 ++++++++++++
 src/DynareBison.yy    |  4 +++-
 src/DynareFlex.ll     |  1 +
 src/ParsingDriver.cc  | 13 ++++++++---
 src/ParsingDriver.hh  |  1 +
 6 files changed, 79 insertions(+), 4 deletions(-)

diff --git a/src/ComputingTasks.cc b/src/ComputingTasks.cc
index 00f31006..891fa5ca 100644
--- a/src/ComputingTasks.cc
+++ b/src/ComputingTasks.cc
@@ -1647,6 +1647,56 @@ EstimatedParamsBoundsStatement::writeJsonOutput(ostream &output) const
          << "}";
 }
 
+DeterministicTrendsStatement::DeterministicTrendsStatement(trend_elements_t trend_elements_arg,
+                                                       const SymbolTable &symbol_table_arg) :
+  trend_elements{move(trend_elements_arg)},
+  symbol_table{symbol_table_arg}
+{
+}
+
+void
+DeterministicTrendsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
+{
+  output << "options_.trend_coeff = {};" << endl;
+  for (const auto &trend_element : trend_elements)
+    {
+      SymbolType type = symbol_table.getType(trend_element.first);
+      if (type == SymbolType::endogenous)
+        {
+          output << "tmp1 = strmatch('" << trend_element.first << "',M_.endogenous_names,'exact');" << endl;
+          output << "options_.deterministic_trend_coeffs{tmp1} = '";
+          trend_element.second->writeOutput(output);
+          output << "';" << endl;
+        }
+      else
+        cerr << "Warning : Non-variable symbol used in deterministic_trends: " << trend_element.first << endl;
+    }
+}
+
+void
+DeterministicTrendsStatement::writeJsonOutput(ostream &output) const
+{
+  output << R"({"statementName": "deterministic_trends", )"
+         << R"("trends" : {)";
+  bool printed = false;
+  for (const auto &trend_element : trend_elements)
+    {
+      if (symbol_table.getType(trend_element.first) == SymbolType::endogenous)
+        {
+          if (printed)
+            output << ", ";
+          output << R"(")" << trend_element.first << R"(": ")";
+          trend_element.second->writeJsonOutput(output, {}, {});
+          output << R"(")" << endl;
+          printed = true;
+        }
+      else
+        cerr << "Warning : Non-variable symbol used in deterministic_trends: " << trend_element.first << endl;
+    }
+  output << "}"
+         << "}";
+}
+
 ObservationTrendsStatement::ObservationTrendsStatement(trend_elements_t trend_elements_arg,
                                                        const SymbolTable &symbol_table_arg) :
   trend_elements{move(trend_elements_arg)},
diff --git a/src/ComputingTasks.hh b/src/ComputingTasks.hh
index 69ab9d70..d86cb4bc 100644
--- a/src/ComputingTasks.hh
+++ b/src/ComputingTasks.hh
@@ -301,6 +301,20 @@ public:
   void writeJsonOutput(ostream &output) const override;
 };
 
+class DeterministicTrendsStatement : public Statement
+{
+public:
+  using trend_elements_t = map<string, expr_t>;
+private:
+  const trend_elements_t trend_elements;
+  const SymbolTable &symbol_table;
+public:
+  DeterministicTrendsStatement(trend_elements_t trend_elements_arg,
+                             const SymbolTable &symbol_table_arg);
+  void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
+  void writeJsonOutput(ostream &output) const override;
+};
+
 class FilterInitialStateStatement : public Statement
 {
 public:
diff --git a/src/DynareBison.yy b/src/DynareBison.yy
index 1f219c6d..04861ca5 100644
--- a/src/DynareBison.yy
+++ b/src/DynareBison.yy
@@ -106,7 +106,7 @@ class ParsingDriver;
 %token USE_PENALIZED_OBJECTIVE_FOR_HESSIAN INIT_STATE FAST_REALTIME RESCALE_PREDICTION_ERROR_COVARIANCE GENERATE_IRFS
 %token NAN_CONSTANT NO_STATIC NOBS NOCONSTANT NODISPLAY NOCORR NODIAGNOSTIC NOFUNCTIONS NO_HOMOTOPY
 %token NOGRAPH POSTERIOR_NOGRAPH POSTERIOR_GRAPH NOMOMENTS NOPRINT NORMAL_PDF SAVE_DRAWS MODEL_NAME STDERR_MULTIPLES DIAGONAL_ONLY
-%token OBSERVATION_TRENDS OPTIM OPTIM_WEIGHTS ORDER OSR OSR_PARAMS MAX_DIM_COVA_GROUP ADVANCED OUTFILE OUTVARS OVERWRITE DISCOUNT
+%token DETERMINISTIC_TRENDS OBSERVATION_TRENDS OPTIM OPTIM_WEIGHTS ORDER OSR OSR_PARAMS MAX_DIM_COVA_GROUP ADVANCED OUTFILE OUTVARS OVERWRITE DISCOUNT
 %token PARALLEL_LOCAL_FILES PARAMETERS PARAMETER_SET PARTIAL_INFORMATION PERIODS PERIOD PLANNER_OBJECTIVE PLOT_CONDITIONAL_FORECAST PLOT_PRIORS PREFILTER PRESAMPLE
 %token PERFECT_FORESIGHT_SETUP PERFECT_FORESIGHT_SOLVER NO_POSTERIOR_KERNEL_DENSITY FUNCTION
 %token PRINT PRIOR_MC PRIOR_TRUNC PRIOR_MODE PRIOR_MEAN POSTERIOR_MODE POSTERIOR_MEAN POSTERIOR_MEDIAN MLE_MODE PRUNING PARTICLE_FILTER_OPTIONS
@@ -245,6 +245,7 @@ statement : parameters
           | options
           | options_eq
           | varobs
+          | deterministic_trends
           | observation_trends
           | filter_initial_state
           | varexobs
@@ -2080,6 +2081,7 @@ varexobs_list : varexobs_list symbol
               { driver.add_varexobs($1); }
             ;
 
+deterministic_trends : DETERMINISTIC_TRENDS ';' trend_list END ';' { driver.set_deterministic_trends(); };
 observation_trends : OBSERVATION_TRENDS ';' trend_list END ';' { driver.set_trends(); };
 
 trend_list : trend_list trend_element
diff --git a/src/DynareFlex.ll b/src/DynareFlex.ll
index 4771827d..2451d6e6 100644
--- a/src/DynareFlex.ll
+++ b/src/DynareFlex.ll
@@ -213,6 +213,7 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
 <INITIAL>estimated_params_bounds 	{BEGIN DYNARE_BLOCK; return token::ESTIMATED_PARAMS_BOUNDS;}
 <INITIAL>osr_params_bounds              {BEGIN DYNARE_BLOCK; return token::OSR_PARAMS_BOUNDS;}
 <INITIAL>observation_trends {BEGIN DYNARE_BLOCK; return token::OBSERVATION_TRENDS;}
+<INITIAL>deterministic_trends {BEGIN DYNARE_BLOCK; return token::DETERMINISTIC_TRENDS;}
 <INITIAL>optim_weights {BEGIN DYNARE_BLOCK; return token::OPTIM_WEIGHTS;}
 <INITIAL>homotopy_setup {BEGIN DYNARE_BLOCK; return token::HOMOTOPY_SETUP;}
 <INITIAL>conditional_forecast_paths {BEGIN DYNARE_BLOCK; return token::CONDITIONAL_FORECAST_PATHS;}
diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc
index 51cd2943..4945bb47 100644
--- a/src/ParsingDriver.cc
+++ b/src/ParsingDriver.cc
@@ -1873,10 +1873,10 @@ ParsingDriver::set_trends()
 }
 
 void
-ParsingDriver::set_filter_initial_state()
+ParsingDriver::set_deterministic_trends()
 {
-  mod_file->addStatement(make_unique<FilterInitialStateStatement>(filter_initial_state_elements, mod_file->symbol_table));
-  filter_initial_state_elements.clear();
+  mod_file->addStatement(make_unique<DeterministicTrendsStatement>(trend_elements, mod_file->symbol_table));
+  trend_elements.clear();
 }
 
 void
@@ -1888,6 +1888,13 @@ ParsingDriver::set_trend_element(string arg1, expr_t arg2)
   trend_elements[move(arg1)] = arg2;
 }
 
+void
+ParsingDriver::set_filter_initial_state()
+{
+  mod_file->addStatement(make_unique<FilterInitialStateStatement>(filter_initial_state_elements, mod_file->symbol_table));
+  filter_initial_state_elements.clear();
+}
+
 void
 ParsingDriver::set_filter_initial_state_element(const string &name, const string &lag, expr_t rhs)
 {
diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh
index eb200ca3..0811f3bc 100644
--- a/src/ParsingDriver.hh
+++ b/src/ParsingDriver.hh
@@ -597,6 +597,7 @@ public:
   //! Forecast Statement
   void forecast();
   void set_trends();
+  void set_deterministic_trends();
   void set_trend_element(string arg1, expr_t arg2);
   //! filter_initial_state block
   void set_filter_initial_state();
-- 
GitLab