From 013043b1dde125ddd24a7b3673ff726a3be01e3a Mon Sep 17 00:00:00 2001
From: Houtan Bastani <houtan@dynare.org>
Date: Tue, 27 Dec 2016 13:46:01 +0100
Subject: [PATCH] ramsey_policy: accept all endogenous variables in var_list_,
 even auxiliary variables. closes #1355

---
 preprocessor/ComputingTasks.cc | 37 ++++++++++++++++++++++++++++++----
 preprocessor/ComputingTasks.hh |  7 +++++--
 preprocessor/DynareBison.yy    |  9 ++++++++-
 preprocessor/ModFile.cc        |  8 ++++++++
 preprocessor/ParsingDriver.cc  | 11 ++++++++--
 preprocessor/ParsingDriver.hh  |  6 ++++--
 6 files changed, 67 insertions(+), 11 deletions(-)

diff --git a/preprocessor/ComputingTasks.cc b/preprocessor/ComputingTasks.cc
index b3ee1f0522..f12c408675 100644
--- a/preprocessor/ComputingTasks.cc
+++ b/preprocessor/ComputingTasks.cc
@@ -402,9 +402,11 @@ RamseyConstraintsStatement::writeOutput(ostream &output, const string &basename,
 //   return new RamseyPolicyStatement(new_symbol_list, options_list);
 // }
 
-RamseyPolicyStatement::RamseyPolicyStatement(const SymbolList &symbol_list_arg,
+RamseyPolicyStatement::RamseyPolicyStatement(const SymbolTable &symbol_table_arg,
+                                             const vector<string> &ramsey_policy_list_arg,
                                              const OptionsList &options_list_arg) :
-  symbol_list(symbol_list_arg),
+  symbol_table(symbol_table_arg),
+  ramsey_policy_list(ramsey_policy_list_arg),
   options_list(options_list_arg)
 {
 }
@@ -445,6 +447,25 @@ RamseyPolicyStatement::checkPass(ModFileStructure &mod_file_struct, WarningConso
     mod_file_struct.k_order_solver = true;
 }
 
+void
+RamseyPolicyStatement::checkRamseyPolicyList()
+{
+  for (vector<string>::const_iterator it = ramsey_policy_list.begin();
+       it != ramsey_policy_list.end(); it++)
+    {
+      if (!symbol_table.exists(*it))
+        {
+          cerr << "ERROR: ramsey_policy: " << *it << " was not declared." << endl;
+          exit(EXIT_FAILURE);
+        }
+      if (symbol_table.getType(*it) != eEndogenous)
+        {
+          cerr << "ERROR: ramsey_policy: " << *it << " is not endogenous." << endl;
+          exit(EXIT_FAILURE);
+        }
+    }
+}
+
 void
 RamseyPolicyStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
 {
@@ -456,8 +477,16 @@ RamseyPolicyStatement::writeOutput(ostream &output, const string &basename, bool
     output << "options_.k_order_solver = 1;" << endl;
 
   options_list.writeOutput(output);
-  symbol_list.writeOutput("var_list_", output);
-  output << "ramsey_policy(var_list_);" << endl;
+  output << "var_list_ = char(";
+  for (vector<string>::const_iterator it = ramsey_policy_list.begin();
+       it != ramsey_policy_list.end(); ++it)
+    {
+      if (it != ramsey_policy_list.begin())
+        output << ",";
+      output << "'" << *it << "'";
+    }
+  output << ");" << endl
+         << "ramsey_policy(var_list_);" << endl;
 }
 
 DiscretionaryPolicyStatement::DiscretionaryPolicyStatement(const SymbolList &symbol_list_arg,
diff --git a/preprocessor/ComputingTasks.hh b/preprocessor/ComputingTasks.hh
index 8f0e49252c..a62a02b3b6 100644
--- a/preprocessor/ComputingTasks.hh
+++ b/preprocessor/ComputingTasks.hh
@@ -154,12 +154,15 @@ public:
 class RamseyPolicyStatement : public Statement
 {
 private:
-  const SymbolList symbol_list;
+  const SymbolTable &symbol_table;
+  const vector<string> ramsey_policy_list;
   const OptionsList options_list;
 public:
-  RamseyPolicyStatement(const SymbolList &symbol_list_arg,
+  RamseyPolicyStatement(const SymbolTable &symbol_table_arg,
+                        const vector<string> &ramsey_policy_list_arg,
                         const OptionsList &options_list_arg);
   virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
+  void checkRamseyPolicyList();
   virtual void writeOutput(ostream &output, const string &basename, bool minimal_workspace) const;
 };
 
diff --git a/preprocessor/DynareBison.yy b/preprocessor/DynareBison.yy
index b118955148..358aead34f 100644
--- a/preprocessor/DynareBison.yy
+++ b/preprocessor/DynareBison.yy
@@ -2038,10 +2038,17 @@ ramsey_policy : RAMSEY_POLICY ';'
                 { driver.ramsey_policy(); }
               | RAMSEY_POLICY symbol_list ';'
                 { driver.ramsey_policy(); }
-              | RAMSEY_POLICY '(' ramsey_policy_options_list ')' symbol_list ';'
+              | RAMSEY_POLICY '(' ramsey_policy_options_list ')' ramsey_policy_list ';'
                 { driver.ramsey_policy(); }
               ;
 
+ramsey_policy_list : ramsey_policy_list ramsey_policy_element
+                   | ramsey_policy_element
+                   ;
+
+ramsey_policy_element : symbol { driver.add_to_ramsey_policy_list($1); }
+                      ;
+
 ramsey_constraints : RAMSEY_CONSTRAINTS ';' ramsey_constraints_list END ';'
                      { driver.add_ramsey_constraints_statement(); }
 		   ;
diff --git a/preprocessor/ModFile.cc b/preprocessor/ModFile.cc
index 708a8f6918..862b686640 100644
--- a/preprocessor/ModFile.cc
+++ b/preprocessor/ModFile.cc
@@ -438,6 +438,14 @@ ModFile::transformPass(bool nostrict)
       exit(EXIT_FAILURE);
     }
 
+  if (mod_file_struct.ramsey_policy_present)
+    for (vector<Statement *>::iterator it = statements.begin(); it != statements.end(); it++)
+      {
+        RamseyPolicyStatement *rps = dynamic_cast<RamseyPolicyStatement *>(*it);
+        if (rps != NULL)
+          rps->checkRamseyPolicyList();
+      }
+
   if (mod_file_struct.identification_present && symbol_table.exo_det_nbr() > 0)
     {
       cerr << "ERROR: identification is incompatible with deterministic exogenous variables" << endl;
diff --git a/preprocessor/ParsingDriver.cc b/preprocessor/ParsingDriver.cc
index cd2b7a335d..e68b46ccba 100644
--- a/preprocessor/ParsingDriver.cc
+++ b/preprocessor/ParsingDriver.cc
@@ -1895,9 +1895,16 @@ ParsingDriver::ramsey_policy()
 {
   if (!mod_file->symbol_table.exists("optimal_policy_discount_factor"))
     declare_optimal_policy_discount_factor_parameter(data_tree->One);
-  mod_file->addStatement(new RamseyPolicyStatement(symbol_list, options_list));
-  symbol_list.clear();
+  mod_file->addStatement(new RamseyPolicyStatement(mod_file->symbol_table, ramsey_policy_list, options_list));
   options_list.clear();
+  ramsey_policy_list.clear();
+}
+
+void
+ParsingDriver::add_to_ramsey_policy_list(string *name)
+{
+  ramsey_policy_list.push_back(*name);
+  delete name;
 }
 
 void
diff --git a/preprocessor/ParsingDriver.hh b/preprocessor/ParsingDriver.hh
index 34a312d44b..2eadc53bc8 100644
--- a/preprocessor/ParsingDriver.hh
+++ b/preprocessor/ParsingDriver.hh
@@ -210,7 +210,8 @@ private:
   //! Temporary storage for shock_groups
   vector<string> shock_group;
   vector<ShockGroupsStatement::Group> shock_groups;
-  
+  //! Temporary storage for ramsey policy. Workaround for issue #1355
+  vector<string> ramsey_policy_list;
   //! reset the values for temporary storage
   void reset_current_external_function_options();
   //! Adds a model lagged variable to ModelTree and VariableTable
@@ -717,7 +718,8 @@ public:
   void add_shock_group(string *name);
   //! End shock groups declaration
   void end_shock_groups(const string *name);
-    
+  //! Add an element to the ramsey policy list
+  void add_to_ramsey_policy_list(string *name);
   void smoother2histval();
   void histval_file(string *filename);
   void perfect_foresight_setup();
-- 
GitLab