From c368a11aa58d6495c601022f309470684356d61f Mon Sep 17 00:00:00 2001
From: Houtan Bastani <houtan@dynare.org>
Date: Mon, 11 Sep 2017 18:14:56 +0200
Subject: [PATCH] preprocessor: allow variables that become state variables in
 ramsey_policy to be set in histval. closes #1193

(cherry picked from commit 4cfaa2545e3dfb529f80cd0b901c99b6bdba3acd)
---
 preprocessor/ComputingTasks.cc          |  5 +++++
 preprocessor/ModFile.cc                 | 23 +++++++++++++++++++++++
 preprocessor/NumericalInitialization.cc |  3 +++
 preprocessor/NumericalInitialization.hh |  3 +++
 preprocessor/ParsingDriver.cc           |  8 ++------
 preprocessor/ParsingDriver.hh           |  2 ++
 preprocessor/Statement.hh               |  5 ++++-
 7 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/preprocessor/ComputingTasks.cc b/preprocessor/ComputingTasks.cc
index 30615f63f..a2284842a 100644
--- a/preprocessor/ComputingTasks.cc
+++ b/preprocessor/ComputingTasks.cc
@@ -432,6 +432,11 @@ RamseyPolicyStatement::checkPass(ModFileStructure &mod_file_struct, WarningConso
       mod_file_struct.order_option = max(mod_file_struct.order_option, order + 1);
     }
 
+  OptionsList::symbol_list_options_t::const_iterator itsl =
+    options_list.symbol_list_options.find("instruments");
+  if (itsl != options_list.symbol_list_options.end())
+    mod_file_struct.ramsey_state_variables = itsl->second.get_symbols();
+
   // Fill in mod_file_struct.partial_information
   it = options_list.num_options.find("partial_information");
   if (it != options_list.num_options.end() && it->second == "1")
diff --git a/preprocessor/ModFile.cc b/preprocessor/ModFile.cc
index 8d6150a26..400cb056f 100644
--- a/preprocessor/ModFile.cc
+++ b/preprocessor/ModFile.cc
@@ -141,6 +141,29 @@ ModFile::checkPass(bool nostrict)
       exit(EXIT_FAILURE);
     }
 
+  // Workaround for #1193
+  if (!mod_file_struct.hist_vals_wrong_lag.empty())
+    {
+      for (vector<string>::const_iterator it = mod_file_struct.ramsey_state_variables.begin();
+           it != mod_file_struct.ramsey_state_variables.end(); it++)
+        {
+          int symb_id = symbol_table.getID(*it);
+          map<int,int>::const_iterator it1 = mod_file_struct.hist_vals_wrong_lag.find(symb_id);
+          if (it1 != mod_file_struct.hist_vals_wrong_lag.end() && it1->second < 0)
+            mod_file_struct.hist_vals_wrong_lag.erase(symb_id);
+        }
+
+      if (!mod_file_struct.hist_vals_wrong_lag.empty())
+        {
+          for (map<int, int>::const_iterator it = mod_file_struct.hist_vals_wrong_lag.begin();
+               it != mod_file_struct.hist_vals_wrong_lag.end(); it++)
+            cerr << "ERROR: histval: variable " << symbol_table.getName(it->first)
+                 << " does not appear in the model with the lag " << it->second
+                 << " (see the reference manual for the timing convention in 'histval')" << endl;
+          exit(EXIT_FAILURE);
+        }
+    }
+
   if ((mod_file_struct.ramsey_model_present || mod_file_struct.ramsey_policy_present)
       && mod_file_struct.discretionary_policy_present)
     {
diff --git a/preprocessor/NumericalInitialization.cc b/preprocessor/NumericalInitialization.cc
index 7d9439764..593800fd9 100644
--- a/preprocessor/NumericalInitialization.cc
+++ b/preprocessor/NumericalInitialization.cc
@@ -268,9 +268,11 @@ EndValStatement::writeOutput(ostream &output, const string &basename, bool minim
 }
 
 HistValStatement::HistValStatement(const hist_values_t &hist_values_arg,
+                                   const hist_vals_wrong_lag_t hist_vals_wrong_lag_arg,
                                    const SymbolTable &symbol_table_arg,
                                    const bool &all_values_required_arg) :
   hist_values(hist_values_arg),
+  hist_vals_wrong_lag(hist_vals_wrong_lag_arg),
   symbol_table(symbol_table_arg),
   all_values_required(all_values_required_arg)
 {
@@ -316,6 +318,7 @@ HistValStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidat
       if (unused_endo.size() > 0 || unused_exo.size() > 0)
         exit(EXIT_FAILURE);
     }
+  mod_file_struct.hist_vals_wrong_lag = hist_vals_wrong_lag;
 }
 
 void
diff --git a/preprocessor/NumericalInitialization.hh b/preprocessor/NumericalInitialization.hh
index 2e34677b8..c2a42b166 100644
--- a/preprocessor/NumericalInitialization.hh
+++ b/preprocessor/NumericalInitialization.hh
@@ -103,12 +103,15 @@ public:
     Maps pairs (symbol_id, lag) to expr_t
   */
   typedef map<pair<int, int>, expr_t> hist_values_t;
+  typedef map<int, int> hist_vals_wrong_lag_t;
 private:
   const hist_values_t hist_values;
+  const hist_vals_wrong_lag_t hist_vals_wrong_lag;
   const SymbolTable &symbol_table;
   const bool all_values_required;
 public:
   HistValStatement(const hist_values_t &hist_values_arg,
+                   const hist_vals_wrong_lag_t hist_vals_wrong_lag_arg,
                    const SymbolTable &symbol_table_arg,
                    const bool &all_values_required_arg);
   //! Workaround for trac ticket #157
diff --git a/preprocessor/ParsingDriver.cc b/preprocessor/ParsingDriver.cc
index 32b1b3ac2..9569c27b3 100644
--- a/preprocessor/ParsingDriver.cc
+++ b/preprocessor/ParsingDriver.cc
@@ -549,11 +549,7 @@ ParsingDriver::hist_val(string *name, string *lag, expr_t rhs)
   pair<int, int> key(symb_id, ilag);
 
   if (mod_file->dynamic_model.minLagForSymbol(symb_id) > ilag - 1)
-    {
-      ostringstream s;
-      s << ilag-1;
-      error("histval: variable " + *name + " does not appear in the model with the lag " + s.str() + " (see the reference manual for the timing convention in 'histval')");
-    }
+    hist_vals_wrong_lag[symb_id] = ilag-1;
 
   if (hist_values.find(key) != hist_values.end())
     error("hist_val: (" + *name + ", " + *lag + ") declared twice");
@@ -669,7 +665,7 @@ ParsingDriver::end_endval(bool all_values_required)
 void
 ParsingDriver::end_histval(bool all_values_required)
 {
-  mod_file->addStatement(new HistValStatement(hist_values, mod_file->symbol_table, all_values_required));
+  mod_file->addStatement(new HistValStatement(hist_values, hist_vals_wrong_lag, mod_file->symbol_table, all_values_required));
   hist_values.clear();
 }
 
diff --git a/preprocessor/ParsingDriver.hh b/preprocessor/ParsingDriver.hh
index 80eb4c0a2..f8dbe487b 100644
--- a/preprocessor/ParsingDriver.hh
+++ b/preprocessor/ParsingDriver.hh
@@ -157,6 +157,8 @@ private:
   InitOrEndValStatement::init_values_t init_values;
   //! Temporary storage for histval blocks
   HistValStatement::hist_values_t hist_values;
+  //! Temporary storage for histval blocks
+  HistValStatement::hist_vals_wrong_lag_t hist_vals_wrong_lag;
   //! Temporary storage for homotopy_setup blocks
   HomotopyStatement::homotopy_values_t homotopy_values;
   //! Temporary storage for moment_calibration
diff --git a/preprocessor/Statement.hh b/preprocessor/Statement.hh
index 3e303d8d6..c99d79eb7 100644
--- a/preprocessor/Statement.hh
+++ b/preprocessor/Statement.hh
@@ -117,7 +117,10 @@ public:
   int orig_eq_nbr;
   //! Stores the number of equations added to the Ramsey model
   int ramsey_eq_nbr;
-
+  //! Set list of variables that become state variables when ramsey_policy is used
+  vector<string> ramsey_state_variables;
+  //! Histval values that do not have the appropriate lag
+  map<int, int> hist_vals_wrong_lag;
 };
 
 class Statement
-- 
GitLab