From a8fce06dc46ca09329e6899e1fde47f2cd81809b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org>
Date: Thu, 18 Nov 2021 17:08:08 +0100
Subject: [PATCH] =?UTF-8?q?PAC:=20new=20options=20=E2=80=9Cauxname?=
 =?UTF-8?q?=E2=80=9D=20and=20=E2=80=9Ckind=E2=80=9D=20to=20=E2=80=9Cpac=5F?=
 =?UTF-8?q?model=E2=80=9D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/DynamicModel.cc  | 10 ++++++++--
 src/DynamicModel.hh  |  2 ++
 src/DynareBison.yy   |  4 ++++
 src/DynareFlex.ll    | 10 +++++-----
 src/ParsingDriver.cc | 17 ++++++++++++++++-
 src/ParsingDriver.hh |  8 +++++++-
 src/SubModel.cc      | 33 ++++++++++++++++++++++++++++++++-
 src/SubModel.hh      |  6 +++++-
 8 files changed, 79 insertions(+), 11 deletions(-)

diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index 6a4885da..37ee1ec0 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -3898,6 +3898,7 @@ DynamicModel::computePacModelConsistentExpectationSubstitution(const string &nam
                                                                int discount_symb_id,
                                                                int pac_eq_max_lag,
                                                                expr_t growth_correction_term,
+                                                               string auxname,
                                                                ExprNode::subst_table_t &diff_subst_table,
                                                                map<string, int> &pac_aux_var_symb_ids,
                                                                map<string, vector<int>> &pac_aux_param_symb_ids,
@@ -3916,7 +3917,9 @@ DynamicModel::computePacModelConsistentExpectationSubstitution(const string &nam
   int neqs = 0;
 
   // Create the endogenous representing Z₁ (no orig_expr is given since its definition is recursive)
-  int mce_z1_symb_id = symbol_table.addPacExpectationAuxiliaryVar("mce_Z1_" + name, nullptr);
+  if (auxname.empty())
+    auxname = "mce_Z1_" + name;
+  int mce_z1_symb_id = symbol_table.addPacExpectationAuxiliaryVar(auxname, nullptr);
   pac_aux_var_symb_ids[name] = mce_z1_symb_id;
 
   expr_t A = One;
@@ -4032,6 +4035,7 @@ DynamicModel::computePacBackwardExpectationSubstitution(const string &name,
                                                         int max_lag,
                                                         const string &aux_model_type,
                                                         expr_t growth_correction_term,
+                                                        string auxname,
                                                         map<string, int> &pac_aux_var_symb_ids,
                                                         map<string, vector<int>> &pac_aux_param_symb_ids,
                                                         map<string, expr_t> &pac_expectation_substitution)
@@ -4072,7 +4076,9 @@ DynamicModel::computePacBackwardExpectationSubstitution(const string &name,
 
   subExpr = AddPlus(subExpr, growth_correction_term);
 
-  int expect_var_id = symbol_table.addPacExpectationAuxiliaryVar("pac_expectation_" + name, subExpr);
+  if (auxname.empty())
+    auxname = "pac_expectation_" + name;
+  int expect_var_id = symbol_table.addPacExpectationAuxiliaryVar(auxname, subExpr);
   expr_t neweq = AddEqual(AddVariable(expect_var_id), subExpr);
   addEquation(neweq, -1);
   addAuxEquation(neweq);
diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh
index 6907bcda..0605849c 100644
--- a/src/DynamicModel.hh
+++ b/src/DynamicModel.hh
@@ -563,6 +563,7 @@ public:
   void computePacModelConsistentExpectationSubstitution(const string &name,
                                                         int discount_symb_id, int pac_eq_max_lag,
                                                         expr_t growth_correction_term,
+                                                        string auxname,
                                                         ExprNode::subst_table_t &diff_subst_table,
                                                         map<string, int> &pac_aux_var_symb_ids,
                                                         map<string, vector<int>> &pac_aux_param_symb_ids,
@@ -578,6 +579,7 @@ public:
                                                  int max_lag,
                                                  const string &aux_model_type,
                                                  expr_t growth_correction_term,
+                                                 string auxname,
                                                  map<string, int> &pac_aux_var_symb_ids,
                                                  map<string, vector<int>> &pac_aux_param_symb_ids,
                                                  map<string, expr_t> &pac_expectation_substitution);
diff --git a/src/DynareBison.yy b/src/DynareBison.yy
index 87c0f9ba..5c091413 100644
--- a/src/DynareBison.yy
+++ b/src/DynareBison.yy
@@ -441,6 +441,8 @@ pac_model_options : o_pac_name
                   | o_pac_aux_model_name
                   | o_pac_discount
                   | o_pac_growth
+                  | o_pac_auxname
+                  | o_pac_kind
                   ;
 
 var_expectation_model : VAR_EXPECTATION_MODEL '(' var_expectation_model_options_list ')' ';'
@@ -3549,6 +3551,8 @@ 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 { driver.begin_pac_growth(); } EQUAL hand_side { driver.set_pac_growth($4); };
+o_pac_auxname : AUXNAME EQUAL symbol { driver.set_pac_auxname($3); };
+o_pac_kind : KIND EQUAL pac_target_kind { driver.set_pac_kind($3); };
 o_var_name : MODEL_NAME EQUAL symbol { driver.option_str("var.model_name", $3); };
 o_series : SERIES EQUAL symbol { driver.option_str("series", $3); };
 o_datafile : DATAFILE EQUAL filename { driver.option_str("datafile", $3); };
diff --git a/src/DynareFlex.ll b/src/DynareFlex.ll
index f9be86f9..e35d9253 100644
--- a/src/DynareFlex.ll
+++ b/src/DynareFlex.ll
@@ -803,21 +803,21 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4])
 <DYNARE_BLOCK>restriction {return token::RESTRICTION;}
 <DYNARE_BLOCK>component {return token::COMPONENT;}
 <DYNARE_BLOCK>target {return token::TARGET;}
-<DYNARE_BLOCK>auxname {return token::AUXNAME;}
+<DYNARE_BLOCK,DYNARE_STATEMENT>auxname {return token::AUXNAME;}
 <DYNARE_BLOCK>auxname_target_nonstationary {return token::AUXNAME_TARGET_NONSTATIONARY;}
-<DYNARE_BLOCK>kind {
+<DYNARE_BLOCK,DYNARE_STATEMENT>kind {
   yylval->build<string>(yytext);
   return token::KIND;
 }
-<DYNARE_BLOCK>ll {
+<DYNARE_BLOCK,DYNARE_STATEMENT>ll {
   yylval->build<string>(yytext);
   return token::LL;
 }
-<DYNARE_BLOCK>dl {
+<DYNARE_BLOCK,DYNARE_STATEMENT>dl {
   yylval->build<string>(yytext);
   return token::DL;
 }
-<DYNARE_BLOCK>dd {
+<DYNARE_BLOCK,DYNARE_STATEMENT>dd {
   yylval->build<string>(yytext);
   return token::DD;
 }
diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc
index 215148a4..820576d1 100644
--- a/src/ParsingDriver.cc
+++ b/src/ParsingDriver.cc
@@ -2635,6 +2635,8 @@ ParsingDriver::begin_pac_model()
 {
   parsing_pac_model = true;
   pac_growth = nullptr;
+  pac_auxname.clear();
+  pac_kind = PacTargetKind::unspecified;
   options_list.clear();
 }
 
@@ -2657,7 +2659,8 @@ ParsingDriver::pac_model()
   auto discount = it->second;
   check_symbol_is_parameter(discount);
 
-  mod_file->pac_model_table.addPacModel(name, aux_model_name, discount, pac_growth);
+  mod_file->pac_model_table.addPacModel(name, aux_model_name, discount, pac_growth,
+                                        pac_auxname, pac_kind);
   parsing_pac_model = false;
 }
 
@@ -2668,6 +2671,18 @@ ParsingDriver::set_pac_growth(expr_t pac_growth_arg)
   reset_data_tree();
 }
 
+void
+ParsingDriver::set_pac_auxname(string auxname)
+{
+  pac_auxname = move(auxname);
+}
+
+void
+ParsingDriver::set_pac_kind(PacTargetKind kind)
+{
+  pac_kind = kind;
+}
+
 expr_t
 ParsingDriver::add_exp(expr_t arg1)
 {
diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh
index 8c9d08fb..78063f70 100644
--- a/src/ParsingDriver.hh
+++ b/src/ParsingDriver.hh
@@ -258,8 +258,10 @@ private:
 
   WarningConsolidation &warnings;
 
-  //! Temporary storage for growth declared in pac_model
+  //! Temporary storage for several options of pac_model
   expr_t pac_growth;
+  string pac_auxname;
+  PacTargetKind pac_kind;
 
   bool nostrict;
 
@@ -752,6 +754,10 @@ public:
   void pac_model();
   //! Adds growth for pac
   void set_pac_growth(expr_t pac_growth_arg);
+  //! Sets the value of “auxname” option for the current “pac_model”
+  void set_pac_auxname(string auxname);
+  //! Sets the value of “kind” option for the current “pac_model”
+  void set_pac_kind(PacTargetKind kind);
   //! Writes token "diff(arg1)" to model tree
   expr_t add_diff(expr_t arg1);
   //! Writes token "adl(arg1, lag)" to model tree
diff --git a/src/SubModel.cc b/src/SubModel.cc
index 73d2ce57..8d59e5dd 100644
--- a/src/SubModel.cc
+++ b/src/SubModel.cc
@@ -760,7 +760,7 @@ PacModelTable::PacModelTable(SymbolTable &symbol_table_arg) :
 }
 
 void
-PacModelTable::addPacModel(string name_arg, string aux_model_name_arg, string discount_arg, expr_t growth_arg)
+PacModelTable::addPacModel(string name_arg, string aux_model_name_arg, string discount_arg, expr_t growth_arg, string auxname_arg, PacTargetKind kind_arg)
 {
   if (isExistingPacModelName(name_arg))
     {
@@ -772,6 +772,8 @@ PacModelTable::addPacModel(string name_arg, string aux_model_name_arg, string di
   discount[name_arg] = move(discount_arg);
   growth[name_arg] = growth_arg;
   original_growth[name_arg] = growth_arg;
+  auxname[name_arg] = move(auxname_arg);
+  kind[name_arg] = kind_arg;
   names.insert(move(name_arg));
 }
 
@@ -801,6 +803,28 @@ PacModelTable::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation
         gv->collectVariables(SymbolType::exogenous, mod_file_struct.pac_params);
       }
 
+  for (auto &[name, auxn] : auxname)
+    if (!auxn.empty() && target_info.find(name) != target_info.end())
+      {
+        cerr << "ERROR: for PAC model '" << name << "', it is not possible to declare an 'auxname' option in the 'pac_model' command when there is also a 'pac_target_info' block" << endl;
+        exit(EXIT_FAILURE);
+      }
+
+  for (auto &[name, k] : kind)
+    if (k != PacTargetKind::unspecified)
+      {
+        if (target_info.find(name) != target_info.end())
+          {
+            cerr << "ERROR: for PAC model '" << name << "', it is not possible to declare a 'kind' option in the 'pac_model' command when there is also a 'pac_target_info' block" << endl;
+            exit(EXIT_FAILURE);
+          }
+        if (aux_model_name[name].empty())
+          {
+            cerr << "ERROR: for PAC model '" << name << "', it is not possible to declare a 'kind' option in the 'pac_model' command since this is a MCE model" << endl;
+            exit(EXIT_FAILURE);
+          }
+      }
+
   for (const auto &[name, ti] : target_info)
     for (auto &[expr, gv, auxname, kind, coeff, growth_neutrality_param, h_indices, original_gv, gv_info] : get<2>(ti))
       if (gv)
@@ -1073,6 +1097,7 @@ PacModelTable::transformPass(const lag_equivalence_table_t &unary_ops_nodes,
                                                                            symbol_table.getID(discount[name]),
                                                                            pacEquationMaxLag(name),
                                                                            growth_correction_term,
+                                                                           auxname[name],
                                                                            diff_subst_table,
                                                                            aux_var_symb_ids,
                                                                            aux_param_symb_ids,
@@ -1093,6 +1118,7 @@ PacModelTable::transformPass(const lag_equivalence_table_t &unary_ops_nodes,
             dynamic_model.computePacBackwardExpectationSubstitution(name, lhs[name], max_lag,
                                                                     aux_model_type[name],
                                                                     growth_correction_term,
+                                                                    auxname[name],
                                                                     aux_var_symb_ids,
                                                                     aux_param_symb_ids,
                                                                     pac_expectation_substitution);
@@ -1209,6 +1235,11 @@ PacModelTable::writeOutput(const string &basename, ostream &output) const
   for (auto &[model, type] : aux_model_type)
       output << "M_.pac." << model << ".auxiliary_model_type = '" << type << "';" << endl;
 
+  for (auto &[name, k] : kind)
+    if (!aux_model_name.empty())
+      output << "M_.pac." << name << ".kind = '"
+             << (k == PacTargetKind::unspecified ? "" : kindToString(k)) << "';" << endl;
+
   for (auto &[name, val] : equation_info)
     {
       auto [lhs_pac_var, optim_share_index, ar_params_and_vars, ec_params_and_vars, non_optim_vars_params_and_constants, additive_vars_params_and_constants, optim_additive_vars_params_and_constants] = val;
diff --git a/src/SubModel.hh b/src/SubModel.hh
index 74d924c7..dcbf8a05 100644
--- a/src/SubModel.hh
+++ b/src/SubModel.hh
@@ -206,6 +206,10 @@ private:
      Each tuple represents a term: (endo_id, lag, param_id, constant) */
   using growth_info_t = vector<tuple<int, int, int, double>>;
   map<string, growth_info_t> growth_info;
+  // The “auxname” option of pac_model (empty if not passed)
+  map<string, string> auxname;
+  // The “kind” option of pac_model (“undefined” if not passed)
+  map<string, PacTargetKind> kind;
 
   /* Stores the name of the PAC equation associated to the model.
      pac_model_name → eq_name */
@@ -268,7 +272,7 @@ private:
 
 public:
   explicit PacModelTable(SymbolTable &symbol_table_arg);
-  void addPacModel(string name_arg, string aux_model_name_arg, string discount_arg, expr_t growth_arg);
+  void addPacModel(string name_arg, string aux_model_name_arg, string discount_arg, expr_t growth_arg, string auxname_arg, PacTargetKind kind_arg);
   bool isExistingPacModelName(const string &name_arg) const;
   bool empty() const;
   void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
-- 
GitLab