From d922ae8ffc2fc846943d6ce21d1e10b52672709c Mon Sep 17 00:00:00 2001
From: Houtan Bastani <houtan@dynare.org>
Date: Thu, 24 Jan 2019 19:35:30 +0100
Subject: [PATCH] pac_model: permit lag on growth option

---
 src/ComputingTasks.cc | 119 +++++++++++++++++++++++++-----------------
 src/ComputingTasks.hh |   9 ++--
 src/DynamicModel.cc   |   6 +--
 src/DynamicModel.hh   |   4 +-
 src/DynareBison.yy    |   6 ++-
 src/ExprNode.cc       |  87 ++++++++++++++++++++++++------
 src/ExprNode.hh       |  33 ++++++++----
 src/ModFile.cc        |   6 +--
 src/ParsingDriver.cc  |  21 ++++----
 src/ParsingDriver.hh  |   8 ++-
 10 files changed, 200 insertions(+), 99 deletions(-)

diff --git a/src/ComputingTasks.cc b/src/ComputingTasks.cc
index 1b19d922..01c2cf84 100644
--- a/src/ComputingTasks.cc
+++ b/src/ComputingTasks.cc
@@ -260,12 +260,14 @@ PriorPosteriorFunctionStatement::writeJsonOutput(ostream &output) const
 PacModelStatement::PacModelStatement(string name_arg,
                                      string aux_model_name_arg,
                                      string discount_arg,
-                                     string growth_arg,
+                                     int growth_symb_id_arg,
+                                     int growth_lag_arg,
                                      const SymbolTable &symbol_table_arg) :
   name{move(name_arg)},
   aux_model_name{move(aux_model_name_arg)},
   discount{move(discount_arg)},
-  growth{move(growth_arg)},
+  growth_symb_id{growth_symb_id_arg},
+  growth_lag{growth_lag_arg},
   symbol_table{symbol_table_arg}
 {
 }
@@ -274,8 +276,24 @@ void
 PacModelStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
 {
   mod_file_struct.pac_params.insert(symbol_table.getID(discount));
-  if (!growth.empty())
-    mod_file_struct.pac_params.insert(symbol_table.getID(growth));
+  if (growth_symb_id >= 0)
+    {
+      switch (symbol_table.getType(growth_symb_id))
+        {
+        case SymbolType::endogenous:
+        case SymbolType::exogenous:
+        case SymbolType::parameter:
+          break;
+        default:
+          {
+            cerr << "ERROR: The Expression passed to the growth option of pac_model must be an "
+                 << "endogenous (lagged or not), exogenous (lagged or not), or parameter" << endl;
+            exit(EXIT_FAILURE);
+          }
+        }
+      mod_file_struct.pac_params.insert(growth_symb_id);
+      mod_file_struct.pac_params.insert(growth_lag);
+    }
 }
 
 void
@@ -290,27 +308,53 @@ PacModelStatement::writeOutput(ostream &output, const string &basename, bool min
   output << "M_.pac." << name << ".auxiliary_model_name = '" << aux_model_name << "';" << endl
          << "M_.pac." << name << ".discount_index = " << symbol_table.getTypeSpecificID(discount) + 1 << ";" << endl;
 
-  if (!growth.empty())
+  if (growth_symb_id >= 0)
     {
-      output << "M_.pac." << name << ".growth_index = " << symbol_table.getTypeSpecificID(growth) + 1 << ";" << endl
-             << "M_.pac." << name << ".growth_type = ";
-      switch(symbol_table.getType(growth))
+      string growth_type;
+      switch (symbol_table.getType(growth_symb_id))
         {
         case SymbolType::endogenous:
-          output << "'endogenous';" << endl;
+          growth_type = "endogenous";
           break;
         case SymbolType::exogenous:
-          output << "'exogenous';" << endl;
+          growth_type = "exogenous";
           break;
         case SymbolType::parameter:
-          output << "'parameter';" << endl;
+          growth_type = "parameter";
           break;
         default:
-          cerr << "pac_model: error encountered in growth type" << endl;
-          exit(EXIT_FAILURE);
+          {
+          }
         }
-    }
 
+      try
+        {
+          // case when this is not the highest lag of the growth variable
+          int aux_symb_id = symbol_table.searchAuxiliaryVars(growth_symb_id, growth_lag);
+          output << "M_.pac." << name << ".growth_index = " << symbol_table.getTypeSpecificID(aux_symb_id) + 1 << ";" << endl
+                 << "M_.pac." << name << ".growth_lag = 0;" << endl
+                 << "M_.pac." << name << ".growth_type = '" << growth_type << "';" << endl;
+        }
+      catch (...)
+        {
+          try
+            {
+              // case when this is the highest lag of the growth variable
+              int tmp_growth_lag = growth_lag + 1;
+              int aux_symb_id = symbol_table.searchAuxiliaryVars(growth_symb_id, tmp_growth_lag);
+              output << "M_.pac." << name << ".growth_index = " << symbol_table.getTypeSpecificID(aux_symb_id) + 1 << ";" << endl
+                     << "M_.pac." << name << ".growth_lag = -1;" << endl
+                     << "M_.pac." << name << ".growth_type = '" << growth_type << "';" << endl;
+            }
+          catch (...)
+            {
+              // case when there is no aux var for the variable
+              output << "M_.pac." << name << ".growth_index = " << symbol_table.getTypeSpecificID(growth_symb_id) + 1 << ";" << endl
+                     << "M_.pac." << name << ".growth_lag = " << growth_lag << ";" << endl
+                     << "M_.pac." << name << ".growth_type = '" << growth_type << "';" << endl;
+            }
+        }
+    }
   output << "M_.pac." << name << ".lhs = [";
   for (auto it = lhs.begin(); it !=lhs.end(); it++)
     {
@@ -319,24 +363,6 @@ PacModelStatement::writeOutput(ostream &output, const string &basename, bool min
       output << *it + 1;
     }
   output << "];" << endl;
-  /*
-         << "M_.pac." << name << ".undiff_eqtags = {";
-  for (auto it = undiff.begin(); it != undiff.end(); it++)
-    {
-      if (it != undiff.begin())
-        output << "; ";
-      output << "'" << it->first << "'";
-    }
-  output << "};" << endl
-         << "M_.pac." << name << ".undiff_num = [";
-  for (auto it = undiff.begin(); it != undiff.end(); it++)
-    {
-      if (it != undiff.begin())
-        output << " ";
-      output << it->second;
-    }
-  output << "];" << endl;
-  */
 }
 
 void
@@ -347,37 +373,36 @@ PacModelStatement::writeJsonOutput(ostream &output) const
          << "\"auxiliary_model_name\": \"" << aux_model_name << "\","
          << "\"discount_index\": " << symbol_table.getTypeSpecificID(discount) + 1;
 
-  if (!growth.empty())
+  if (growth_symb_id >= 0)
     {
-      output << ","
-             << "\"growth_index\": " << symbol_table.getTypeSpecificID(growth) + 1 << ","
-             << "\"growth_type\": ";
-      switch(symbol_table.getType(growth))
+      string growth_type;
+      switch (symbol_table.getType(growth_symb_id))
         {
         case SymbolType::endogenous:
-          output << "\"endogenous\"" << endl;
+          growth_type = "endogenous";
           break;
         case SymbolType::exogenous:
-          output << "\"exogenous\"" << endl;
+          growth_type = "exogenous";
           break;
         case SymbolType::parameter:
-          output << "\"parameter\"" << endl;
+          growth_type = "parameter";
           break;
         default:
-          cerr << "pac_model: error encountered in growth type" << endl;
-          exit(EXIT_FAILURE);
+          {
+          }
         }
+      output << ","
+             << "\"growth_index\": " << symbol_table.getTypeSpecificID(growth_symb_id) + 1 << ","
+             << "\"growth_lag\": " << growth_lag << ","
+             << "\"growth_type\": " << "\"" << growth_type << "\"" << endl;
     }
   output << "}";
 }
 
-tuple<string, string, int>
+tuple<string, string, int, int>
 PacModelStatement::getPacModelInfoForPacExpectation() const
 {
-  int growth_symb_id = -1;
-  if (!growth.empty())
-    growth_symb_id = symbol_table.getID(growth);
-  return { name, aux_model_name, growth_symb_id };
+  return { name, aux_model_name, growth_symb_id, growth_lag };
 }
 
 VarEstimationStatement::VarEstimationStatement(OptionsList options_list_arg) :
diff --git a/src/ComputingTasks.hh b/src/ComputingTasks.hh
index f28d47d2..f61b52f3 100644
--- a/src/ComputingTasks.hh
+++ b/src/ComputingTasks.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2018 Dynare Team
+ * Copyright (C) 2003-2019 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -140,20 +140,21 @@ private:
   const string name;
   const string aux_model_name;
   const string discount;
-  const string growth;
+  const int growth_symb_id, growth_lag;
   const SymbolTable &symbol_table;
   vector<int> lhs;
 public:
   PacModelStatement(string name_arg,
                     string aux_model_name_arg,
                     string discount_arg,
-                    string growth_arg,
+                    int growth_symb_id_arg,
+                    int growth_lag_arg,
                     const SymbolTable &symbol_table_arg);
   void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
   void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const override;
   void writeJsonOutput(ostream &output) const override;
   void fillUndiffedLHS(vector<int> &lhs);
-  tuple<string, string, int> getPacModelInfoForPacExpectation() const;
+  tuple<string, string, int, int> getPacModelInfoForPacExpectation() const;
 };
 
 class VarRestrictionsStatement : public Statement
diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index fbd878af..16d69326 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2018 Dynare Team
+ * Copyright (C) 2003-2019 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -4318,11 +4318,11 @@ DynamicModel::fillPacExpectationVarInfo(string &pac_model_name,
                                         int max_lag,
                                         int pac_max_lag,
                                         vector<bool> &nonstationary,
-                                        int growth_symb_id)
+                                        int growth_symb_id, int growth_lag)
 {
   for (size_t i = 0; i < equations.size(); i++)
     equations[i]->fillPacExpectationVarInfo(pac_model_name, lhs, max_lag,
-                                            pac_max_lag, nonstationary, growth_symb_id, i);
+                                            pac_max_lag, nonstationary, growth_symb_id, growth_lag, i);
 }
 
 void
diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh
index 2bbdb5c7..0f77e8f8 100644
--- a/src/DynamicModel.hh
+++ b/src/DynamicModel.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2018 Dynare Team
+ * Copyright (C) 2003-2019 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -351,7 +351,7 @@ public:
                                  int max_lag,
                                  int pac_max_lag,
                                  vector<bool> &nonstationary,
-                                 int growth_symb_id);
+                                 int growth_symb_id, int growth_lag);
 
   //! Substitutes pac_expectation operator
   void substitutePacExpectation();
diff --git a/src/DynareBison.yy b/src/DynareBison.yy
index 9b30df42..9d3cfecb 100644
--- a/src/DynareBison.yy
+++ b/src/DynareBison.yy
@@ -1,6 +1,6 @@
 // -*- C++ -*-
 /*
- * Copyright (C) 2003-2018 Dynare Team
+ * Copyright (C) 2003-2019 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -3130,7 +3130,9 @@ o_file : FILE EQUAL filename { driver.option_str("file", $3); };
 o_pac_name : MODEL_NAME EQUAL symbol { driver.option_str("pac.model_name", $3); };
 o_pac_aux_model_name : AUXILIARY_MODEL_NAME EQUAL symbol { driver.option_str("pac.aux_model_name", $3); };
 o_pac_discount : DISCOUNT EQUAL symbol { driver.option_str("pac.discount", $3); };
-o_pac_growth : GROWTH EQUAL symbol { driver.option_str("pac.growth", $3); };
+o_pac_growth : GROWTH EQUAL symbol { driver.set_pac_growth($3, 0); }
+             | GROWTH EQUAL symbol '(' MINUS INT_NUMBER ')' { driver.set_pac_growth($3, stoi($6)); }
+             ;
 o_var_name : MODEL_NAME EQUAL symbol { driver.option_str("var.model_name", $3); };
 o_var_order : ORDER EQUAL INT_NUMBER { driver.option_num("var.order", $3); };
 o_series : SERIES EQUAL symbol { driver.option_str("series", $3); };
diff --git a/src/ExprNode.cc b/src/ExprNode.cc
index d6ac99cb..f6e52e48 100644
--- a/src/ExprNode.cc
+++ b/src/ExprNode.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2018 Dynare Team
+ * Copyright (C) 2007-2019 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -638,6 +638,12 @@ NumConstNode::containsExogenous() const
   return false;
 }
 
+bool
+NumConstNode::containsParameter() const
+{
+  return false;
+}
+
 expr_t
 NumConstNode::replaceTrendVar() const
 {
@@ -687,7 +693,7 @@ NumConstNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pa
 }
 
 void
-NumConstNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg)
+NumConstNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag_arg, int equation_number_arg)
 {
 }
 
@@ -1865,6 +1871,12 @@ VariableNode::containsExogenous() const
   return (get_type() == SymbolType::exogenous || get_type() == SymbolType::exogenousDet);
 }
 
+bool
+VariableNode::containsParameter() const
+{
+  return get_type() == SymbolType::parameter ? true : false;
+}
+
 expr_t
 VariableNode::replaceTrendVar() const
 {
@@ -1980,7 +1992,7 @@ VariableNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pa
 }
 
 void
-VariableNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg)
+VariableNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag_arg, int equation_number_arg)
 {
 }
 
@@ -3729,6 +3741,12 @@ UnaryOpNode::containsExogenous() const
   return arg->containsExogenous();
 }
 
+bool
+UnaryOpNode::containsParameter() const
+{
+  return arg->containsParameter();
+}
+
 expr_t
 UnaryOpNode::replaceTrendVar() const
 {
@@ -3790,9 +3808,9 @@ UnaryOpNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pai
 }
 
 void
-UnaryOpNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg)
+UnaryOpNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag_arg, int equation_number_arg)
 {
-  arg->fillPacExpectationVarInfo(model_name_arg, lhs_arg, max_lag_arg, pac_max_lag_arg, nonstationary_arg, growth_symb_id_arg, equation_number_arg);
+  arg->fillPacExpectationVarInfo(model_name_arg, lhs_arg, max_lag_arg, pac_max_lag_arg, nonstationary_arg, growth_symb_id_arg, growth_lag_arg, equation_number_arg);
 }
 
 bool
@@ -5407,6 +5425,12 @@ BinaryOpNode::containsExogenous() const
   return (arg1->containsExogenous() || arg2->containsExogenous());
 }
 
+bool
+BinaryOpNode::containsParameter() const
+{
+  return (arg1->containsParameter() || arg2->containsParameter());
+}
+
 expr_t
 BinaryOpNode::replaceTrendVar() const
 {
@@ -5815,10 +5839,10 @@ BinaryOpNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pa
 }
 
 void
-BinaryOpNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg)
+BinaryOpNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag_arg, int equation_number_arg)
 {
-  arg1->fillPacExpectationVarInfo(model_name_arg, lhs_arg, max_lag_arg, pac_max_lag_arg, nonstationary_arg, growth_symb_id_arg, equation_number_arg);
-  arg2->fillPacExpectationVarInfo(model_name_arg, lhs_arg, max_lag_arg, pac_max_lag_arg, nonstationary_arg, growth_symb_id_arg, equation_number_arg);
+  arg1->fillPacExpectationVarInfo(model_name_arg, lhs_arg, max_lag_arg, pac_max_lag_arg, nonstationary_arg, growth_symb_id_arg, growth_lag_arg, equation_number_arg);
+  arg2->fillPacExpectationVarInfo(model_name_arg, lhs_arg, max_lag_arg, pac_max_lag_arg, nonstationary_arg, growth_symb_id_arg, growth_lag_arg, equation_number_arg);
 }
 
 bool
@@ -6670,6 +6694,12 @@ TrinaryOpNode::containsExogenous() const
   return (arg1->containsExogenous() || arg2->containsExogenous() || arg3->containsExogenous());
 }
 
+bool
+TrinaryOpNode::containsParameter() const
+{
+  return (arg1->containsParameter() || arg2->containsParameter() || arg3->containsParameter());
+}
+
 expr_t
 TrinaryOpNode::replaceTrendVar() const
 {
@@ -6739,11 +6769,11 @@ TrinaryOpNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, p
 }
 
 void
-TrinaryOpNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg)
+TrinaryOpNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag_arg, int equation_number_arg)
 {
-  arg1->fillPacExpectationVarInfo(model_name_arg, lhs_arg, max_lag_arg, pac_max_lag_arg, nonstationary_arg, growth_symb_id_arg, equation_number_arg);
-  arg2->fillPacExpectationVarInfo(model_name_arg, lhs_arg, max_lag_arg, pac_max_lag_arg, nonstationary_arg, growth_symb_id_arg, equation_number_arg);
-  arg3->fillPacExpectationVarInfo(model_name_arg, lhs_arg, max_lag_arg, pac_max_lag_arg, nonstationary_arg, growth_symb_id_arg, equation_number_arg);
+  arg1->fillPacExpectationVarInfo(model_name_arg, lhs_arg, max_lag_arg, pac_max_lag_arg, nonstationary_arg, growth_symb_id_arg, growth_lag_arg, equation_number_arg);
+  arg2->fillPacExpectationVarInfo(model_name_arg, lhs_arg, max_lag_arg, pac_max_lag_arg, nonstationary_arg, growth_symb_id_arg, growth_lag_arg, equation_number_arg);
+  arg3->fillPacExpectationVarInfo(model_name_arg, lhs_arg, max_lag_arg, pac_max_lag_arg, nonstationary_arg, growth_symb_id_arg, growth_lag_arg, equation_number_arg);
 }
 
 bool
@@ -7223,6 +7253,15 @@ AbstractExternalFunctionNode::containsExogenous() const
   return false;
 }
 
+bool
+AbstractExternalFunctionNode::containsParameter() const
+{
+  for (auto argument : arguments)
+    if (argument->containsParameter())
+      return true;
+  return false;
+}
+
 expr_t
 AbstractExternalFunctionNode::replaceTrendVar() const
 {
@@ -7290,10 +7329,10 @@ AbstractExternalFunctionNode::addParamInfoToPac(pair<int, int> &lhs_arg, int opt
 }
 
 void
-AbstractExternalFunctionNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg)
+AbstractExternalFunctionNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag_arg, int equation_number_arg)
 {
   for (auto argument : arguments)
-    argument->fillPacExpectationVarInfo(model_name_arg, lhs_arg, max_lag_arg, pac_max_lag_arg, nonstationary_arg, growth_symb_id_arg, equation_number_arg);
+    argument->fillPacExpectationVarInfo(model_name_arg, lhs_arg, max_lag_arg, pac_max_lag_arg, nonstationary_arg, growth_symb_id_arg, growth_lag_arg, equation_number_arg);
 }
 
 bool
@@ -8827,6 +8866,13 @@ VarExpectationNode::containsExogenous() const
   exit(EXIT_FAILURE);
 }
 
+bool
+VarExpectationNode::containsParameter() const
+{
+  cerr << "VarExpectationNode::containsParameter not implemented." << endl;
+  exit(EXIT_FAILURE);
+}
+
 bool
 VarExpectationNode::isNumConstNodeEqualTo(double value) const
 {
@@ -8912,7 +8958,7 @@ VarExpectationNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_a
 }
 
 void
-VarExpectationNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg)
+VarExpectationNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag_arg, int equation_number_arg)
 {
 }
 
@@ -9371,6 +9417,12 @@ PacExpectationNode::containsExogenous() const
   return false;
 }
 
+bool
+PacExpectationNode::containsParameter() const
+{
+  return false;
+}
+
 bool
 PacExpectationNode::isNumConstNodeEqualTo(double value) const
 {
@@ -9505,7 +9557,7 @@ PacExpectationNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_a
 
 
 void
-PacExpectationNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg)
+PacExpectationNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag_arg, int equation_number_arg)
 {
   if (model_name != model_name_arg)
     return;
@@ -9514,6 +9566,7 @@ PacExpectationNode::fillPacExpectationVarInfo(string &model_name_arg, vector<int
   max_lag = max_lag_arg;
   pac_max_lag = pac_max_lag_arg;
   growth_symb_id = growth_symb_id_arg;
+  growth_lag = growth_lag_arg;
   equation_number = equation_number_arg;
 
   for (vector<bool>::const_iterator it = nonstationary_arg.begin();
@@ -9574,7 +9627,7 @@ PacExpectationNode::substitutePacExpectation(map<const PacExpectationNode *, con
                                                            SymbolType::parameter);
       subExpr = datatree.AddPlus(subExpr,
                                  datatree.AddTimes(datatree.AddVariable(growth_param_index),
-                                                   datatree.AddVariable(growth_symb_id)));
+                                                   datatree.AddVariable(growth_symb_id, growth_lag)));
     }
 
   subst_table[const_cast<PacExpectationNode *>(this)] = dynamic_cast<BinaryOpNode *>(subExpr);
diff --git a/src/ExprNode.hh b/src/ExprNode.hh
index e9095fef..71b1d34a 100644
--- a/src/ExprNode.hh
+++ b/src/ExprNode.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2018 Dynare Team
+ * Copyright (C) 2007-2019 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -526,6 +526,9 @@ class ExprNode
       //! Returns true if the expression contains one or several exogenous variable
       virtual bool containsExogenous() const = 0;
 
+      //! Returns true if the expression contains one or several parameters
+      virtual bool containsParameter() const = 0;
+
       //! Returns the maximum number of nested diffs in the expression
       virtual int countDiffs() const = 0;
 
@@ -603,7 +606,7 @@ class ExprNode
       virtual void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) = 0;
 
       //! Fills var_model info for pac_expectation node
-      virtual void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) = 0;
+      virtual void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag, int equation_number_arg) = 0;
 
       //! Fills the AR matrix structure
       virtual void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const = 0;
@@ -715,6 +718,7 @@ public:
   bool isNumConstNodeEqualTo(double value) const override;
   bool containsEndogenous() const override;
   bool containsExogenous() const override;
+  bool containsParameter() const override;
   int countDiffs() const override;
   bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
   expr_t replaceTrendVar() const override;
@@ -723,7 +727,7 @@ public:
   expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
   bool isInStaticForm() const override;
   void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
-  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
+  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag, int equation_number_arg) override;
   void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
   void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
   bool containsPacExpectation(const string &pac_model_name = "") const override;
@@ -804,6 +808,7 @@ public:
   bool isNumConstNodeEqualTo(double value) const override;
   bool containsEndogenous() const override;
   bool containsExogenous() const override;
+  bool containsParameter() const override;
   int countDiffs() const override;
   bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
   expr_t replaceTrendVar() const override;
@@ -812,7 +817,7 @@ public:
   expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
   bool isInStaticForm() const override;
   void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
-  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
+  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag, int equation_number_arg) override;
   void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
   void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
   bool containsPacExpectation(const string &pac_model_name = "") const override;
@@ -921,6 +926,7 @@ public:
   bool isNumConstNodeEqualTo(double value) const override;
   bool containsEndogenous() const override;
   bool containsExogenous() const override;
+  bool containsParameter() const override;
   int countDiffs() const override;
   bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
   expr_t replaceTrendVar() const override;
@@ -929,7 +935,7 @@ public:
   expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
   bool isInStaticForm() const override;
   void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
-  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
+  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag, int equation_number_arg) override;
   void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
   void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
   bool containsPacExpectation(const string &pac_model_name = "") const override;
@@ -1045,6 +1051,7 @@ public:
   bool isNumConstNodeEqualTo(double value) const override;
   bool containsEndogenous() const override;
   bool containsExogenous() const override;
+  bool containsParameter() const override;
   int countDiffs() const override;
   bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
   expr_t replaceTrendVar() const override;
@@ -1059,7 +1066,7 @@ public:
   expr_t getNonZeroPartofEquation() const;
   bool isInStaticForm() const override;
   void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
-  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
+  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag, int equation_number_arg) override;
   void fillAutoregressiveRowHelper(expr_t arg1, expr_t arg2,
                                    int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const;
   void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
@@ -1170,6 +1177,7 @@ public:
   bool isNumConstNodeEqualTo(double value) const override;
   bool containsEndogenous() const override;
   bool containsExogenous() const override;
+  bool containsParameter() const override;
   int countDiffs() const override;
   bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
   expr_t replaceTrendVar() const override;
@@ -1178,7 +1186,7 @@ public:
   expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
   bool isInStaticForm() const override;
   void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
-  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
+  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag, int equation_number_arg) override;
   void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
   void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
   bool containsPacExpectation(const string &pac_model_name = "") const override;
@@ -1295,6 +1303,7 @@ public:
   bool isNumConstNodeEqualTo(double value) const override;
   bool containsEndogenous() const override;
   bool containsExogenous() const override;
+  bool containsParameter() const override;
   int countDiffs() const override;
   bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
   void writePrhs(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms, const string &ending) const;
@@ -1304,7 +1313,7 @@ public:
   expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
   bool isInStaticForm() const override;
   void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
-  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
+  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag, int equation_number_arg) override;
   void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
   void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
   bool containsPacExpectation(const string &pac_model_name = "") const override;
@@ -1508,6 +1517,7 @@ public:
   void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
   bool containsEndogenous() const override;
   bool containsExogenous() const override;
+  bool containsParameter() const override;
   int countDiffs() const override;
   bool isNumConstNodeEqualTo(double value) const override;
   expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
@@ -1518,7 +1528,7 @@ public:
   expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
   bool isInStaticForm() const override;
   void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
-  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
+  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag, int equation_number_arg) override;
   void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
   void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
   bool containsPacExpectation(const string &pac_model_name = "") const override;
@@ -1541,7 +1551,7 @@ public:
   const string model_name;
 private:
   string var_model_name;
-  int growth_symb_id;
+  int growth_symb_id, growth_lag;
   bool stationary_vars_present, nonstationary_vars_present;
   vector<int> lhs;
   pair<int, int> lhs_pac_var;
@@ -1608,6 +1618,7 @@ public:
   void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
   bool containsEndogenous() const override;
   bool containsExogenous() const override;
+  bool containsParameter() const override;
   int countDiffs() const override;
   bool isNumConstNodeEqualTo(double value) const override;
   expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
@@ -1618,7 +1629,7 @@ public:
   expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
   bool isInStaticForm() const override;
   void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
-  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
+  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag, int equation_number_arg) override;
   void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
   void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
   bool containsPacExpectation(const string &pac_model_name = "") const override;
diff --git a/src/ModFile.cc b/src/ModFile.cc
index 25ef0a78..8557d682 100644
--- a/src/ModFile.cc
+++ b/src/ModFile.cc
@@ -419,9 +419,9 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
          {
            vector<int> lhs;
            vector<bool> nonstationary;
-           int growth_symb_id, max_lag;
+           int growth_symb_id, growth_lag, max_lag;
            string aux_model_name, pac_model_name;
-           tie ( pac_model_name, aux_model_name, growth_symb_id ) =
+           tie ( pac_model_name, aux_model_name, growth_symb_id, growth_lag ) =
              pms->getPacModelInfoForPacExpectation();
            if (trend_component_model_table.isExistingTrendComponentModelName(aux_model_name))
              {
@@ -447,7 +447,7 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
            dynamic_model.walkPacParameters();
            int pac_max_lag = original_model.getPacMaxLag(pac_model_name);
            dynamic_model.fillPacExpectationVarInfo(pac_model_name, lhs, max_lag,
-                                                   pac_max_lag, nonstationary, growth_symb_id);
+                                                   pac_max_lag, nonstationary, growth_symb_id, growth_lag);
            dynamic_model.substitutePacExpectation();
          }
      }
diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc
index 77c9f1e8..5fdf87c6 100644
--- a/src/ParsingDriver.cc
+++ b/src/ParsingDriver.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2018 Dynare Team
+ * Copyright (C) 2003-2019 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -2625,18 +2625,21 @@ ParsingDriver::pac_model()
     error("You must pass the discount option to the pac_model statement.");
   auto discount = it->second;
 
-  string growth;
-  it = options_list.string_options.find("pac.growth");
-  if (it != options_list.string_options.end())
-    growth = it->second;
-
-  mod_file->addStatement(make_unique<PacModelStatement>(name, aux_model_name, discount, growth,
+  mod_file->addStatement(make_unique<PacModelStatement>(name, aux_model_name, discount,
+                                                        pac_growth_symb_id, pac_growth_lag,
                                                         mod_file->symbol_table));
-
-  symbol_list.clear();
+  pac_growth_symb_id = -1;
+  pac_growth_lag = 0;
   options_list.clear();
 }
 
+void
+ParsingDriver::set_pac_growth(const string &name, int lag)
+{
+  pac_growth_symb_id = mod_file->symbol_table.getID(name);
+  pac_growth_lag = -lag;
+}
+
 expr_t
 ParsingDriver::add_exp(expr_t arg1)
 {
diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh
index c3c4aacf..a806eb53 100644
--- a/src/ParsingDriver.hh
+++ b/src/ParsingDriver.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2018 Dynare Team
+ * Copyright (C) 2003-2019 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -254,6 +254,10 @@ private:
 
   WarningConsolidation &warnings;
 
+  //! Temporary storage for growth declared in pac_model
+  int pac_growth_symb_id = -1;
+  int pac_growth_lag = 0;
+
   bool nostrict;
 
   vector<pair<string, string>> model_errors;
@@ -727,6 +731,8 @@ public:
   expr_t add_pac_expectation(const string &var_model_name);
   //! Creates pac_model statement
   void pac_model();
+  //! Adds growth for pac
+  void set_pac_growth(const string &name, int lag = 0);
   //! Writes token "diff(arg1)" to model tree
   expr_t add_diff(expr_t arg1);
   //! Writes token "adl(arg1, lag)" to model tree
-- 
GitLab