From 96a5949d9edebadc0c6fac5a7066cd4927dd3eff Mon Sep 17 00:00:00 2001
From: Houtan Bastani <houtan@dynare.org>
Date: Fri, 6 Mar 2015 15:58:11 +0100
Subject: [PATCH] preprocessor: remove extraneous varexo, update model and
 statements, #841

---
 DataTree.hh                |  3 +-
 DynamicModel.cc            | 16 +++++++
 DynamicModel.hh            |  3 ++
 ExprNode.cc                | 71 ++++++++++++++++++++++++++++
 ExprNode.hh                | 14 +++++-
 ModFile.cc                 | 13 ++++++
 NumericalInitialization.cc | 94 +++++++++++++++++++++++++++++++++++++-
 NumericalInitialization.hh | 10 +++-
 Statement.cc               |  8 +++-
 Statement.hh               |  9 +++-
 SymbolTable.cc             | 37 ++++++++++++++-
 SymbolTable.hh             |  4 +-
 12 files changed, 272 insertions(+), 10 deletions(-)

diff --git a/DataTree.hh b/DataTree.hh
index d7c53645..f81f19e6 100644
--- a/DataTree.hh
+++ b/DataTree.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2014 Dynare Team
+ * Copyright (C) 2003-2015 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -233,6 +233,7 @@ public:
   //! Returns the minimum lag (as a negative number) of the given symbol in the whole data tree (and not only in the equations !!)
   /*! Returns 0 if the symbol is not used */
   int minLagForSymbol(int symb_id) const;
+  inline SymbolTable *getSymbolTable() const { return &symbol_table; };
   //! Write the Header for getPowerDeriv when use_dll is used
   void writePowerDerivCHeader(ostream &output) const;
   //! Write getPowerDeriv
diff --git a/DynamicModel.cc b/DynamicModel.cc
index 645fa646..a4997e02 100644
--- a/DynamicModel.cc
+++ b/DynamicModel.cc
@@ -3425,6 +3425,22 @@ DynamicModel::writeDynamicFile(const string &basename, bool block, bool bytecode
     writeDynamicMFile(t_basename);
 }
 
+void
+DynamicModel::reindexEquations(DynamicModel &dynamic_model, SymbolTable &orig_symbol_table)
+{
+  map<int, expr_t> orig_local_variables_table = local_variables_table;
+  local_variables_table.clear();
+  for (map<int, expr_t>::const_iterator it = orig_local_variables_table.begin();
+       it != orig_local_variables_table.end(); it++)
+    dynamic_model.AddLocalVariable(symbol_table.getID(orig_symbol_table.getName(it->first)),
+                                   it->second->cloneDynamicReindex(dynamic_model, orig_symbol_table));
+
+  vector<BinaryOpNode *>eqbak = equations;
+  equations.clear();
+  for (size_t i = 0; i < eqbak.size(); i++)
+    dynamic_model.addEquation(eqbak[i]->cloneDynamicReindex(dynamic_model, orig_symbol_table), equations_lineno[i]);
+}
+
 void
 DynamicModel::cloneDynamic(DynamicModel &dynamic_model) const
 {
diff --git a/DynamicModel.hh b/DynamicModel.hh
index 8efbc5d3..b13d23e1 100644
--- a/DynamicModel.hh
+++ b/DynamicModel.hh
@@ -235,6 +235,9 @@ public:
   /*! It assumes that the dynamic model given in argument has just been allocated */
   void cloneDynamic(DynamicModel &dynamic_model) const;
 
+  //! reindex equations after change in symbol_table
+  void reindexEquations(DynamicModel &dynamic_model, SymbolTable &orig_symbol_table);
+
   //! Replaces model equations with derivatives of Lagrangian w.r.t. endogenous
   void computeRamseyPolicyFOCs(const StaticModel &static_model);
   //! Replaces the model equations in dynamic_model with those in this model
diff --git a/ExprNode.cc b/ExprNode.cc
index d61ebb56..66cd230e 100644
--- a/ExprNode.cc
+++ b/ExprNode.cc
@@ -354,6 +354,12 @@ NumConstNode::cloneDynamic(DataTree &dynamic_datatree) const
   return dynamic_datatree.AddNonNegativeConstant(datatree.num_constants.get(id));
 }
 
+expr_t
+NumConstNode::cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const
+{
+  return dynamic_datatree.AddNonNegativeConstant(datatree.num_constants.get(id));
+}
+
 int
 NumConstNode::maxEndoLead() const
 {
@@ -988,6 +994,12 @@ VariableNode::cloneDynamic(DataTree &dynamic_datatree) const
   return dynamic_datatree.AddVariable(symb_id, lag);
 }
 
+expr_t
+VariableNode::cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const
+{
+  return dynamic_datatree.AddVariable(dynamic_datatree.symbol_table.getID(orig_symbol_table.getName(symb_id)), lag);
+}
+
 int
 VariableNode::maxEndoLead() const
 {
@@ -2234,6 +2246,13 @@ UnaryOpNode::cloneDynamic(DataTree &dynamic_datatree) const
   return buildSimilarUnaryOpNode(substarg, dynamic_datatree);
 }
 
+expr_t
+UnaryOpNode::cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const
+{
+  expr_t substarg = arg->cloneDynamicReindex(dynamic_datatree, orig_symbol_table);
+  return buildSimilarUnaryOpNode(substarg, dynamic_datatree);
+}
+
 int
 UnaryOpNode::maxEndoLead() const
 {
@@ -3452,6 +3471,14 @@ BinaryOpNode::cloneDynamic(DataTree &dynamic_datatree) const
   return buildSimilarBinaryOpNode(substarg1, substarg2, dynamic_datatree);
 }
 
+expr_t
+BinaryOpNode::cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const
+{
+  expr_t substarg1 = arg1->cloneDynamicReindex(dynamic_datatree, orig_symbol_table);
+  expr_t substarg2 = arg2->cloneDynamicReindex(dynamic_datatree, orig_symbol_table);
+  return buildSimilarBinaryOpNode(substarg1, substarg2, dynamic_datatree);
+}
+
 int
 BinaryOpNode::maxEndoLead() const
 {
@@ -4120,6 +4147,15 @@ TrinaryOpNode::cloneDynamic(DataTree &dynamic_datatree) const
   return buildSimilarTrinaryOpNode(substarg1, substarg2, substarg3, dynamic_datatree);
 }
 
+expr_t
+TrinaryOpNode::cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const
+{
+  expr_t substarg1 = arg1->cloneDynamicReindex(dynamic_datatree, orig_symbol_table);
+  expr_t substarg2 = arg2->cloneDynamicReindex(dynamic_datatree, orig_symbol_table);
+  expr_t substarg3 = arg3->cloneDynamicReindex(dynamic_datatree, orig_symbol_table);
+  return buildSimilarTrinaryOpNode(substarg1, substarg2, substarg3, dynamic_datatree);
+}
+
 int
 TrinaryOpNode::maxEndoLead() const
 {
@@ -4689,6 +4725,17 @@ ExternalFunctionNode::cloneDynamic(DataTree &dynamic_datatree) const
   return dynamic_datatree.AddExternalFunction(symb_id, dynamic_arguments);
 }
 
+expr_t
+ExternalFunctionNode::cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const
+{
+  vector<expr_t> dynamic_arguments;
+  for (vector<expr_t>::const_iterator it = arguments.begin();
+       it != arguments.end(); it++)
+    dynamic_arguments.push_back((*it)->cloneDynamicReindex(dynamic_datatree, orig_symbol_table));
+  return dynamic_datatree.AddExternalFunction(dynamic_datatree.symbol_table.getID(orig_symbol_table.getName(symb_id)),
+                                              dynamic_arguments);
+}
+
 int
 AbstractExternalFunctionNode::maxEndoLead() const
 {
@@ -5182,6 +5229,18 @@ FirstDerivExternalFunctionNode::cloneDynamic(DataTree &dynamic_datatree) const
                                                         inputIndex);
 }
 
+expr_t
+FirstDerivExternalFunctionNode::cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const
+{
+  vector<expr_t> dynamic_arguments;
+  for (vector<expr_t>::const_iterator it = arguments.begin();
+       it != arguments.end(); it++)
+    dynamic_arguments.push_back((*it)->cloneDynamicReindex(dynamic_datatree, orig_symbol_table));
+  return dynamic_datatree.AddFirstDerivExternalFunction(dynamic_datatree.symbol_table.getID(orig_symbol_table.getName(symb_id)),
+                                                        dynamic_arguments,
+                                                        inputIndex);
+}
+
 expr_t
 FirstDerivExternalFunctionNode::buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const
 {
@@ -5417,6 +5476,18 @@ SecondDerivExternalFunctionNode::cloneDynamic(DataTree &dynamic_datatree) const
                                                          inputIndex1, inputIndex2);
 }
 
+expr_t
+SecondDerivExternalFunctionNode::cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const
+{
+  vector<expr_t> dynamic_arguments;
+  for (vector<expr_t>::const_iterator it = arguments.begin();
+       it != arguments.end(); it++)
+    dynamic_arguments.push_back((*it)->cloneDynamicReindex(dynamic_datatree, orig_symbol_table));
+  return dynamic_datatree.AddSecondDerivExternalFunction(dynamic_datatree.symbol_table.getID(orig_symbol_table.getName(symb_id)),
+                                                         dynamic_arguments,
+                                                         inputIndex1, inputIndex2);
+}
+
 expr_t
 SecondDerivExternalFunctionNode::buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const
 {
diff --git a/ExprNode.hh b/ExprNode.hh
index b008333c..b6c7b9b9 100644
--- a/ExprNode.hh
+++ b/ExprNode.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2014 Dynare Team
+ * Copyright (C) 2007-2015 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -407,6 +407,9 @@ public:
   //! Add ExprNodes to the provided datatree
   virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const = 0;
 
+  //! Add ExprNodes to the provided datatree, changing the symbol id from those provided in orig_symbol_table
+  virtual expr_t cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const = 0;
+
   //! Move a trend variable with lag/lead to time t by dividing/multiplying by its growth factor
   virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const = 0;
 
@@ -467,6 +470,7 @@ public:
   virtual expr_t replaceTrendVar() const;
   virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const;
   virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
+  virtual expr_t cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const;
   virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
   virtual bool isInStaticForm() const;
 };
@@ -529,6 +533,7 @@ public:
   virtual expr_t replaceTrendVar() const;
   virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const;
   virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
+  virtual expr_t cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const;
   virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
   virtual bool isInStaticForm() const;
 };
@@ -606,6 +611,7 @@ public:
   virtual expr_t replaceTrendVar() const;
   virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const;
   virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
+  virtual expr_t cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const;
   virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
   virtual bool isInStaticForm() const;
 };
@@ -696,6 +702,7 @@ public:
   virtual expr_t replaceTrendVar() const;
   virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const;
   virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
+  virtual expr_t cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const;
   virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
   //! Function to write out the oPowerNode in expr_t terms as opposed to writing out the function itself
   expr_t unpackPowerDeriv() const;
@@ -766,6 +773,7 @@ public:
   virtual expr_t replaceTrendVar() const;
   virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const;
   virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
+  virtual expr_t cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const;
   virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
   virtual bool isInStaticForm() const;
 };
@@ -841,6 +849,7 @@ public:
   virtual expr_t replaceTrendVar() const;
   virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const;
   virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const = 0;
+  virtual expr_t cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const = 0;
   virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const;
   virtual bool isInStaticForm() const;
 };
@@ -871,6 +880,7 @@ public:
   virtual expr_t toStatic(DataTree &static_datatree) const;
   virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const;
   virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
+  virtual expr_t cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const;
 };
 
 class FirstDerivExternalFunctionNode : public AbstractExternalFunctionNode
@@ -905,6 +915,7 @@ public:
   virtual expr_t toStatic(DataTree &static_datatree) const;
   virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const;
   virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
+  virtual expr_t cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const;
 };
 
 class SecondDerivExternalFunctionNode : public AbstractExternalFunctionNode
@@ -941,6 +952,7 @@ public:
   virtual expr_t toStatic(DataTree &static_datatree) const;
   virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const;
   virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const;
+  virtual expr_t cloneDynamicReindex(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table) const;
 };
 
 #endif
diff --git a/ModFile.cc b/ModFile.cc
index 847fc7e3..1d1df2a5 100644
--- a/ModFile.cc
+++ b/ModFile.cc
@@ -307,6 +307,19 @@ ModFile::checkPass()
 void
 ModFile::transformPass(bool nostrict)
 {
+  // Remove unused exogenous from symbol table and update dynamic_model
+  set<int> unusedExo = dynamic_model.findUnusedExogenous();
+  if (unusedExo.size() > 0)
+    {
+      SymbolTable orig_symbol_table = symbol_table;
+      symbol_table.rmExo(unusedExo);
+      dynamic_model.reindexEquations(dynamic_model, orig_symbol_table);
+      vector<Statement *> orig_statements = statements;
+      statements.clear();
+      for (vector<Statement *>::iterator it = orig_statements.begin(); it != orig_statements.end(); it++)
+        addStatement((*it)->cloneAndReindexSymbIds(dynamic_model, orig_symbol_table));
+    }
+
   // Save the original model (must be done before any model transformations by preprocessor)
   dynamic_model.cloneDynamic(original_model);
 
diff --git a/NumericalInitialization.cc b/NumericalInitialization.cc
index 3df225fc..4937308c 100644
--- a/NumericalInitialization.cc
+++ b/NumericalInitialization.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2014 Dynare Team
+ * Copyright (C) 2003-2015 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -73,6 +73,24 @@ InitParamStatement::fillEvalContext(eval_context_t &eval_context) const
     }
 }
 
+Statement *
+InitParamStatement::cloneAndReindexSymbIds(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table)
+{
+  SymbolTable *new_symbol_table =  dynamic_datatree.getSymbolTable();
+  try
+    {
+      cout << orig_symbol_table.getName(symb_id) << " " << symb_id << "->" << new_symbol_table->getID(orig_symbol_table.getName(symb_id)) << endl;
+      return new InitParamStatement(new_symbol_table->getID(orig_symbol_table.getName(symb_id)),
+                                    param_value->cloneDynamicReindex(dynamic_datatree, orig_symbol_table),
+                                    *new_symbol_table);
+    }
+  catch (SymbolTable::UnknownSymbolIDException &e)
+    {
+      cerr << "ERROR: encountered in InitParamStatement::cloneAndReindexSymbIds. Should not arrive here" << endl;
+      exit(EXIT_FAILURE);
+    }
+}
+
 InitOrEndValStatement::InitOrEndValStatement(const init_values_t &init_values_arg,
                                              const SymbolTable &symbol_table_arg,
                                              const bool &all_values_required_arg) :
@@ -208,6 +226,27 @@ InitValStatement::writeOutputPostInit(ostream &output) const
          <<"end;" << endl;
 }
 
+Statement *
+InitValStatement::cloneAndReindexSymbIds(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table)
+{
+  init_values_t new_init_values;
+  SymbolTable *new_symbol_table =  dynamic_datatree.getSymbolTable();
+  try
+    {
+      for (init_values_t::const_iterator it=init_values.begin();
+           it != init_values.end(); it++)
+        new_init_values.push_back(make_pair(new_symbol_table->getID(orig_symbol_table.getName(it->first)),
+                                            it->second->cloneDynamicReindex(dynamic_datatree, orig_symbol_table)));
+    }
+  catch (SymbolTable::UnknownSymbolIDException &e)
+    {
+      cerr << "ERROR: A variable in the initval statement was not found in the symbol table" << endl
+           << "       This likely means that you have declared a varexo that is not used in the model" << endl;
+      exit(EXIT_FAILURE);
+    }
+  return new InitValStatement(new_init_values, *new_symbol_table, all_values_required);
+}
+
 EndValStatement::EndValStatement(const init_values_t &init_values_arg,
                                  const SymbolTable &symbol_table_arg,
                                  const bool &all_values_required_arg) :
@@ -254,6 +293,27 @@ EndValStatement::writeOutput(ostream &output, const string &basename) const
   writeInitValues(output);
 }
 
+Statement *
+EndValStatement::cloneAndReindexSymbIds(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table)
+{
+  init_values_t new_init_values;
+  SymbolTable *new_symbol_table = dynamic_datatree.getSymbolTable();
+  try
+    {
+      for (init_values_t::const_iterator it=init_values.begin();
+           it != init_values.end(); it++)
+        new_init_values.push_back(make_pair(new_symbol_table->getID(orig_symbol_table.getName(it->first)),
+                                            it->second->cloneDynamicReindex(dynamic_datatree, orig_symbol_table)));
+    }
+  catch (SymbolTable::UnknownSymbolIDException &e)
+    {
+      cerr << "ERROR: A variable in the endval statement was not found in the symbol table" << endl
+           << "       This likely means that you have declared a varexo that is not used in the model" << endl;
+      exit(EXIT_FAILURE);
+    }
+  return new EndValStatement(new_init_values, *new_symbol_table, all_values_required);
+}
+
 HistValStatement::HistValStatement(const hist_values_t &hist_values_arg,
                                    const SymbolTable &symbol_table_arg) :
   hist_values(hist_values_arg),
@@ -320,6 +380,28 @@ HistValStatement::writeOutput(ostream &output, const string &basename) const
     }
 }
 
+Statement *
+HistValStatement::cloneAndReindexSymbIds(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table)
+{
+  hist_values_t new_hist_values;
+  SymbolTable *new_symbol_table = dynamic_datatree.getSymbolTable();
+  try
+    {
+      for (hist_values_t::const_iterator it=hist_values.begin();
+           it != hist_values.end(); it++)
+        new_hist_values[make_pair(new_symbol_table->getID(orig_symbol_table.getName(it->first.first)),
+                                  it->first.second)] =
+          it->second->cloneDynamicReindex(dynamic_datatree, orig_symbol_table);
+    }
+  catch (SymbolTable::UnknownSymbolIDException &e)
+    {
+      cerr << "ERROR: A variable in the hist_val statement was not found in the symbol table" << endl
+           << "       This likely means that you have declared a varexo that is not used in the model" << endl;
+      exit(EXIT_FAILURE);
+    }
+  return new HistValStatement(new_hist_values, *new_symbol_table);
+}
+
 InitvalFileStatement::InitvalFileStatement(const string &filename_arg) :
   filename(filename_arg)
 {
@@ -393,9 +475,10 @@ SaveParamsAndSteadyStateStatement::writeOutput(ostream &output, const string &ba
   output << "save_params_and_steady_state('" << filename << "');" << endl;
 }
 
-LoadParamsAndSteadyStateStatement::LoadParamsAndSteadyStateStatement(const string &filename,
+LoadParamsAndSteadyStateStatement::LoadParamsAndSteadyStateStatement(const string &filename_arg,
                                                                      const SymbolTable &symbol_table_arg,
                                                                      WarningConsolidation &warnings) :
+  filename(filename_arg),
   symbol_table(symbol_table_arg)
 {
   cout << "Reading " << filename << "." << endl;
@@ -465,3 +548,10 @@ LoadParamsAndSteadyStateStatement::fillEvalContext(eval_context_t &eval_context)
        it != content.end(); it++)
     eval_context[it->first] = atof(it->second.c_str());
 }
+
+Statement *
+LoadParamsAndSteadyStateStatement::cloneAndReindexSymbIds(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table)
+{
+  WarningConsolidation warnings(false);
+  return new LoadParamsAndSteadyStateStatement(filename, *(dynamic_datatree.getSymbolTable()), warnings);
+}
diff --git a/NumericalInitialization.hh b/NumericalInitialization.hh
index c61d41e1..913e2730 100644
--- a/NumericalInitialization.hh
+++ b/NumericalInitialization.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2014 Dynare Team
+ * Copyright (C) 2003-2015 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -44,6 +44,7 @@ public:
   virtual void writeCOutput(ostream &output, const string &basename);
   //! Fill eval context with parameter value
   void fillEvalContext(eval_context_t &eval_context) const;
+  virtual Statement *cloneAndReindexSymbIds(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table);
 };
 
 class InitOrEndValStatement : public Statement
@@ -80,6 +81,7 @@ public:
   virtual void writeOutput(ostream &output, const string &basename) const;
   //! Writes initializations for oo_.exo_simul and oo_.exo_det_simul
   void writeOutputPostInit(ostream &output) const;
+  virtual Statement *cloneAndReindexSymbIds(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table);
 };
 
 class EndValStatement : public InitOrEndValStatement
@@ -91,6 +93,7 @@ public:
   //! Workaround for trac ticket #35
   virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
   virtual void writeOutput(ostream &output, const string &basename) const;
+  virtual Statement *cloneAndReindexSymbIds(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table);
 };
 
 class HistValStatement : public Statement
@@ -111,6 +114,7 @@ public:
   //! Workaround for trac ticket #157
   virtual void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings);
   virtual void writeOutput(ostream &output, const string &basename) const;
+  virtual Statement *cloneAndReindexSymbIds(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table);
 };
 
 class InitvalFileStatement : public Statement
@@ -158,17 +162,19 @@ public:
 class LoadParamsAndSteadyStateStatement : public Statement
 {
 private:
+  const string filename;
   const SymbolTable &symbol_table;
   //! Content of the file
   /*! Maps symbol ID to numeric value (stored as string) */
   map<int, string> content;
 public:
-  LoadParamsAndSteadyStateStatement(const string &filename,
+  LoadParamsAndSteadyStateStatement(const string &filename_arg,
                                     const SymbolTable &symbol_table_arg,
                                     WarningConsolidation &warnings);
   virtual void writeOutput(ostream &output, const string &basename) const;
   //! Fill eval context with parameters/variables values
   void fillEvalContext(eval_context_t &eval_context) const;
+  virtual Statement *cloneAndReindexSymbIds(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table);
 };
 
 #endif
diff --git a/Statement.cc b/Statement.cc
index d4d522e7..2b3cd8c6 100644
--- a/Statement.cc
+++ b/Statement.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2014 Dynare Team
+ * Copyright (C) 2006-2015 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -73,6 +73,12 @@ Statement::computingPass()
 {
 }
 
+Statement *
+Statement::cloneAndReindexSymbIds(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table)
+{
+  return this;
+}
+
 NativeStatement::NativeStatement(const string &native_statement_arg) :
   native_statement(native_statement_arg)
 {
diff --git a/Statement.hh b/Statement.hh
index 5bdade39..30643596 100644
--- a/Statement.hh
+++ b/Statement.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2014 Dynare Team
+ * Copyright (C) 2006-2015 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -27,6 +27,8 @@
 
 #include "SymbolList.hh"
 #include "WarningConsolidation.hh"
+#include "SymbolTable.hh"
+#include "DataTree.hh"
 
 class ModFileStructure
 {
@@ -136,6 +138,11 @@ public:
   */
   virtual void writeOutput(ostream &output, const string &basename) const = 0;
   virtual void writeCOutput(ostream &output, const string &basename);
+  //! clone a statement while updating all symbol ids that are contained within it.
+  /* Symbol id's are updated from the symbol table contained in dynamic_datatree
+     The original symbol table is contained in orig_symbol_table
+   */
+  virtual Statement *cloneAndReindexSymbIds(DataTree &dynamic_datatree, SymbolTable &orig_symbol_table);
 };
 
 class NativeStatement : public Statement
diff --git a/SymbolTable.cc b/SymbolTable.cc
index 9d43b791..490dbb31 100644
--- a/SymbolTable.cc
+++ b/SymbolTable.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2014 Dynare Team
+ * Copyright (C) 2003-2015 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -21,6 +21,7 @@
 #include <sstream>
 #include <iostream>
 #include <cassert>
+#include <list>
 
 #include "SymbolTable.hh"
 
@@ -473,6 +474,40 @@ SymbolTable::addLeadAuxiliaryVarInternal(bool endo, int index) throw (FrozenExce
   return symb_id;
 }
 
+void
+SymbolTable::rmExo(set<int> &unused) throw (FrozenException)
+{
+  if (frozen)
+    throw FrozenException();
+
+  list<int> idxs;
+  for (set<int>::const_iterator it = unused.begin(); it != unused.end(); it++)
+    {
+      string name = getName(*it);
+      idxs.push_back(symbol_table[name]);
+      symbol_table.erase(name);
+      size--;
+    }
+
+  idxs.sort();
+  idxs.reverse();
+  for (list<int>::const_iterator it = idxs.begin(); it != idxs.end(); it++)
+    {
+      type_table.erase(type_table.begin() + *it);
+      name_table.erase(name_table.begin() + *it);
+      tex_name_table.erase(tex_name_table.begin() + *it);
+      long_name_table.erase(long_name_table.begin() + *it);
+    }
+
+  symbol_table.clear();
+  int i = 0;
+  for (vector<string>::const_iterator it=name_table.begin();
+       it != name_table.end(); it++)
+    symbol_table[*it] = i++;
+
+  assert(size == symbol_table.size());
+}
+
 int
 SymbolTable::addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag) throw (FrozenException)
 {
diff --git a/SymbolTable.hh b/SymbolTable.hh
index 3e4c47e1..85267fe6 100644
--- a/SymbolTable.hh
+++ b/SymbolTable.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003-2014 Dynare Team
+ * Copyright (C) 2003-2015 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -303,6 +303,8 @@ public:
   bool isAuxiliaryVariable(int symb_id) const;
   //! Get list of endogenous variables without aux vars
   set <int> getOrigEndogenous() const;
+  //! Remove exogenous variables contained in the set
+  void rmExo(set<int> &unused) throw (FrozenException);
 };
 
 inline bool
-- 
GitLab