From 539fddc9f68c751c3f83559403cc7ef5e7e04e76 Mon Sep 17 00:00:00 2001
From: Houtan Bastani <houtan@dynare.org>
Date: Tue, 21 Aug 2018 11:46:59 +0200
Subject: [PATCH] introduce var model table

---
 src/ComputingTasks.cc   | 155 +-------------------------
 src/ComputingTasks.hh   |  33 +-----
 src/DataTree.cc         |   4 +-
 src/DataTree.hh         |   5 +-
 src/DynamicModel.cc     | 205 +++++++++++++++++++++++++++++++---
 src/DynamicModel.hh     |  16 ++-
 src/ModFile.cc          | 133 +++++++++-------------
 src/ModFile.hh          |   4 +-
 src/ModelTree.cc        |   7 +-
 src/ModelTree.hh        |   3 +-
 src/ParsingDriver.cc    |  42 ++++---
 src/StaticModel.cc      |   7 +-
 src/StaticModel.hh      |   3 +-
 src/SteadyStateModel.cc |   7 +-
 src/SteadyStateModel.hh |   3 +-
 src/SubModel.cc         | 238 ++++++++++++++++++++++++++++++++++++++++
 src/SubModel.hh         |  65 +++++++++++
 17 files changed, 616 insertions(+), 314 deletions(-)

diff --git a/src/ComputingTasks.cc b/src/ComputingTasks.cc
index 992f38a7..ead7e744 100644
--- a/src/ComputingTasks.cc
+++ b/src/ComputingTasks.cc
@@ -380,154 +380,6 @@ PacModelStatement::getPacModelInfoForPacExpectation() const
   return { name, aux_model_name, growth_symb_id };
 }
 
-VarModelStatement::VarModelStatement(SymbolList symbol_list_arg,
-                                     OptionsList options_list_arg,
-                                     string name_arg,
-                                     const SymbolTable &symbol_table_arg) :
-  symbol_list(move(symbol_list_arg)),
-  options_list(move(options_list_arg)),
-  name{move(name_arg)},
-  symbol_table(symbol_table_arg)
-{
-}
-
-void
-VarModelStatement::getVarModelInfo(string &var_model_name,
-                                   map<string, pair<SymbolList, int>> &var_model_info,
-                                   map<string, vector<string>> &var_model_eqtags) const
-{
-  var_model_name = name;
-  if (symbol_list.empty())
-    {
-      auto it = options_list.vector_str_options.find("var.eqtags");
-      var_model_eqtags[name] = it->second;
-    }
-  else
-    {
-      auto it = options_list.num_options.find("var.order");
-      var_model_info[name] = { symbol_list, stoi(it->second) };
-    }
-}
-
-void
-VarModelStatement::fillVarModelInfoFromEquations(vector<int> &eqnumber_arg, vector<int> &lhs_arg,
-                                                 vector<set<pair<int, int>>> &rhs_arg,
-                                                 vector<bool> &nonstationary_arg,
-                                                 vector<bool> &diff_arg,
-                                                 vector<int> &orig_diff_var_arg,
-                                                 int max_lag_arg)
-{
-  eqnumber = eqnumber_arg;
-  lhs = lhs_arg;
-  rhs_by_eq = rhs_arg;
-  nonstationary = nonstationary_arg;
-  diff = diff_arg;
-  orig_diff_var = orig_diff_var_arg;
-  max_lag = max_lag_arg;
-}
-
-void
-VarModelStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
-{
-}
-
-void
-VarModelStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
-{
-  options_list.writeOutput(output);
-  if (!symbol_list.empty())
-    symbol_list.writeOutput("options_.var.var_list_", output);
-
-  output << "M_.var." << name << " = options_.var;" << endl
-         << "options_ = rmfield(options_, 'var');" << endl;
-
-  output << "M_.var." << name << ".eqn = [";
-  for (auto it = eqnumber.begin();
-       it != eqnumber.end(); it++)
-    {
-      if (it != eqnumber.begin())
-        output << " ";
-      output << *it + 1;
-    }
-  output << "];" << endl
-         << "M_.var." << name << ".lhs = [";
-  for (auto it = lhs.begin();
-       it != lhs.end(); it++)
-    {
-      if (it != lhs.begin())
-        output << " ";
-      output << symbol_table.getTypeSpecificID(*it) + 1;
-    }
-  output << "];" << endl
-         << "M_.var." << name << ".max_lag = " << max_lag << ";" << endl
-         << "M_.var." << name << ".nonstationary = [";
-  for (auto it = nonstationary.begin();
-       it != nonstationary.end(); it++)
-    {
-      if (it != nonstationary.begin())
-        output << " ";
-      if (*it)
-        output << "true";
-      else
-        output << "false";
-    }
-  output << "];" << endl
-         << "M_.var." << name << ".diff = [";
-  for (auto it = diff.begin();
-       it != diff.end(); it++)
-    {
-      if (it != diff.begin())
-        output << " ";
-      if (*it)
-        output << "true";
-      else
-        output << "false";
-    }
-  output << "];" << endl
-         << "M_.var." << name << ".orig_diff_var = [";
-  for (auto it = orig_diff_var.begin();
-       it != orig_diff_var.end(); it++)
-    {
-      if (it != orig_diff_var.begin())
-        output << " ";
-      if (*it == -1)
-        output << -1;
-      else
-        output << symbol_table.getTypeSpecificID(*it) + 1;
-    }
-  output << "];" << endl;
-  int i = 1;
-  for (auto it = rhs_by_eq.begin();
-       it != rhs_by_eq.end(); it++, i++)
-    {
-      output << "M_.var." << name << ".rhs.vars_at_eq{" << i << "}.var = [";
-      for (auto it1 = it->begin();
-           it1 != it->end(); it1++)
-        {
-          if (it1 != it->begin())
-            output << " ";
-          output << symbol_table.getTypeSpecificID(it1->first) + 1;
-        }
-      output << "];" << endl
-             << "M_.var." << name << ".rhs.vars_at_eq{" << i << "}.lag = [";
-      for (auto it1 = it->begin();
-           it1 != it->end(); it1++)
-        {
-          if (it1 != it->begin())
-            output << " ";
-          output << it1->second;
-        }
-      output << "];" << endl;
-    }
-}
-
-void
-VarModelStatement::writeJsonOutput(ostream &output) const
-{
-  output << "{\"statementName\": \"var_model\","
-         << "\"model_name\": \"" << name << "\"}";
-}
-
 VarEstimationStatement::VarEstimationStatement(OptionsList options_list_arg) :
   options_list(move(options_list_arg))
 {
@@ -2210,9 +2062,10 @@ ModelComparisonStatement::writeJsonOutput(ostream &output) const
 PlannerObjectiveStatement::PlannerObjectiveStatement(SymbolTable &symbol_table,
                                                      NumericalConstants &num_constants,
                                                      ExternalFunctionsTable &external_functions_table,
-                                                     TrendComponentModelTable &trend_component_model_table_arg) :
-  model_tree{symbol_table, num_constants,
-             external_functions_table, trend_component_model_table_arg}
+                                                     TrendComponentModelTable &trend_component_model_table_arg,
+                                                     VarModelTable &var_model_table_arg) :
+  model_tree{symbol_table, num_constants, external_functions_table,
+             trend_component_model_table_arg, var_model_table_arg}
 {
 }
 
diff --git a/src/ComputingTasks.hh b/src/ComputingTasks.hh
index cdfe4499..ccadaea9 100644
--- a/src/ComputingTasks.hh
+++ b/src/ComputingTasks.hh
@@ -141,36 +141,6 @@ public:
   tuple<string, string, int> getPacModelInfoForPacExpectation() const;
 };
 
-class VarModelStatement : public Statement
-{
-public:
-  const SymbolList symbol_list;
-  const OptionsList options_list;
-  const string name;
-private:
-  const SymbolTable &symbol_table;
-  vector<int> eqnumber, lhs, orig_diff_var;
-  vector<set<pair<int, int>>> rhs_by_eq; // rhs by equation
-  vector<bool> nonstationary, diff;
-  int max_lag;
-public:
-  VarModelStatement(SymbolList symbol_list_arg,
-                    OptionsList options_list_arg,
-                    string name_arg,
-                    const SymbolTable &symbol_table_arg);
-  void getVarModelInfo(string &var_model_name,
-                       map<string, pair<SymbolList, int>> &var_model_info,
-                       map<string, vector<string>> &var_model_eqtags) const;
-  void fillVarModelInfoFromEquations(vector<int> &eqnumber_arg, vector<int> &lhs_arg,
-                                     vector<set<pair<int, int>>> &rhs_arg,
-                                     vector<bool> &nonstationary_arg,
-                                     vector<bool> &diff_arg, vector<int> &orig_diff_var_arg,
-                                     int max_lag_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;
-};
-
 class VarRestrictionsStatement : public Statement
 {
 private:
@@ -541,7 +511,8 @@ public:
   PlannerObjectiveStatement(SymbolTable &symbol_table,
                             NumericalConstants &num_constants,
                             ExternalFunctionsTable &external_functions_table,
-                            TrendComponentModelTable &trend_component_model_table_arg);
+                            TrendComponentModelTable &trend_component_model_table_arg,
+                            VarModelTable &var_model_table_arg);
   /*! \todo check there are only endogenous variables at the current period in the objective
     (no exogenous, no lead/lag) */
   void checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings) override;
diff --git a/src/DataTree.cc b/src/DataTree.cc
index b824ccab..a349c383 100644
--- a/src/DataTree.cc
+++ b/src/DataTree.cc
@@ -29,11 +29,13 @@
 DataTree::DataTree(SymbolTable &symbol_table_arg,
                    NumericalConstants &num_constants_arg,
                    ExternalFunctionsTable &external_functions_table_arg,
-                   TrendComponentModelTable &trend_component_model_table_arg) :
+                   TrendComponentModelTable &trend_component_model_table_arg,
+                   VarModelTable &var_model_table_arg) :
   symbol_table(symbol_table_arg),
   num_constants(num_constants_arg),
   external_functions_table(external_functions_table_arg),
   trend_component_model_table(trend_component_model_table_arg),
+  var_model_table(var_model_table_arg),
   node_counter(0)
 {
   Zero = AddNonNegativeConstant("0");
diff --git a/src/DataTree.hh b/src/DataTree.hh
index 7e0635de..55a7c810 100644
--- a/src/DataTree.hh
+++ b/src/DataTree.hh
@@ -59,6 +59,8 @@ protected:
   ExternalFunctionsTable &external_functions_table;
   //! A reference to the trend component model table
   TrendComponentModelTable &trend_component_model_table;
+  //! A reference to the VAR model table
+  VarModelTable &var_model_table;
 
   //! num_constant_id -> NumConstNode
   using num_const_node_map_t = map<int, NumConstNode *>;
@@ -136,7 +138,8 @@ public:
   DataTree(SymbolTable &symbol_table_arg,
            NumericalConstants &num_constants_arg,
            ExternalFunctionsTable &external_functions_table_arg,
-           TrendComponentModelTable &trend_component_model_table_arg);
+           TrendComponentModelTable &trend_component_model_table_arg,
+           VarModelTable &var_model_table_arg);
   virtual
   ~DataTree();
 
diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index 157def47..dce1b7cd 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -34,9 +34,10 @@
 DynamicModel::DynamicModel(SymbolTable &symbol_table_arg,
                            NumericalConstants &num_constants_arg,
                            ExternalFunctionsTable &external_functions_table_arg,
-                           TrendComponentModelTable &trend_component_model_table_arg) :
-  ModelTree(symbol_table_arg, num_constants_arg,
-            external_functions_table_arg, trend_component_model_table_arg),
+                           TrendComponentModelTable &trend_component_model_table_arg,
+                           VarModelTable &var_model_table_arg) :
+  ModelTree(symbol_table_arg, num_constants_arg, external_functions_table_arg,
+            trend_component_model_table_arg, var_model_table_arg),
   max_lag(0), max_lead(0),
   max_endo_lag(0), max_endo_lead(0),
   max_exo_lag(0), max_exo_lead(0),
@@ -3454,6 +3455,168 @@ DynamicModel::runTrendTest(const eval_context_t &eval_context)
   testTrendDerivativesEqualToZero(eval_context);
 }
 
+void
+DynamicModel::fillVarModelTable() const
+{
+  map<string, vector<int>> eqnums, lhsr;
+  map<string, vector<expr_t>> lhs_expr_tr;
+  map<string, vector<bool>> nonstationaryr;
+  map<string, vector<set<pair<int, int>>>> rhsr;
+  map<string, vector<string>> eqtags = var_model_table.getEqTags();
+
+  for (const auto &it : eqtags)
+    {
+      vector<int> eqnumber, lhs;
+      vector<expr_t> lhs_expr_t;
+      vector<set<pair<int, int>>> rhs;
+      vector<bool> nonstationary;
+
+      for (const auto &eqtag : it.second)
+        {
+          int eqn = -1;
+          set<pair<int, int>> lhs_set, lhs_tmp_set, rhs_set;
+          for (const auto &equation_tag : equation_tags)
+            if (equation_tag.second.first == "name"
+                && equation_tag.second.second == eqtag)
+              {
+                eqn = equation_tag.first;
+                break;
+              }
+
+          if (eqn == -1)
+            {
+              cerr << "ERROR: equation tag '" << eqtag << "' not found" << endl;
+              exit(EXIT_FAILURE);
+            }
+
+          bool nonstationary_bool = false;
+          for (const auto &equation_tag : equation_tags)
+            if (equation_tag.first == eqn)
+              if (equation_tag.second.first == "data_type"
+                  && equation_tag.second.second == "nonstationary")
+                {
+                  nonstationary_bool = true;
+                  break;
+                }
+          nonstationary.push_back(nonstationary_bool);
+
+          equations[eqn]->get_arg1()->collectDynamicVariables(SymbolType::endogenous, lhs_set);
+          equations[eqn]->get_arg1()->collectDynamicVariables(SymbolType::exogenous, lhs_tmp_set);
+          equations[eqn]->get_arg1()->collectDynamicVariables(SymbolType::parameter, lhs_tmp_set);
+
+          if (lhs_set.size() != 1 || !lhs_tmp_set.empty())
+            {
+              cerr << "ERROR: in Equation " << eqtag
+                   << ". A VAR may only have one endogenous variable on the LHS. " << endl;
+              exit(EXIT_FAILURE);
+            }
+
+          auto it = lhs_set.begin();
+          if (it->second != 0)
+            {
+              cerr << "ERROR: in Equation " << eqtag
+                   << ". The variable on the LHS of a VAR may not appear with a lead or a lag. "
+                   << endl;
+              exit(EXIT_FAILURE);
+            }
+
+          eqnumber.push_back(eqn);
+          lhs.push_back(it->first);
+          lhs_set.clear();
+          set<expr_t> lhs_expr_t_set;
+          equations[eqn]->get_arg1()->collectVARLHSVariable(lhs_expr_t_set);
+          lhs_expr_t.push_back(*(lhs_expr_t_set.begin()));
+
+          equations[eqn]->get_arg2()->collectDynamicVariables(SymbolType::endogenous, rhs_set);
+          for (const auto &it : rhs_set)
+            if (it.second > 0)
+              {
+                cerr << "ERROR: in Equation " << eqtag
+                     << ". A VAR may not have leaded or contemporaneous variables on the RHS. " << endl;
+                exit(EXIT_FAILURE);
+              }
+          rhs.push_back(rhs_set);
+        }
+      eqnums[it.first] = eqnumber;
+      lhsr[it.first] = lhs;
+      lhs_expr_tr[it.first] = lhs_expr_t;
+      rhsr[it.first] = rhs;
+      nonstationaryr[it.first] = nonstationary;
+    }
+  var_model_table.setEqNums(eqnums);
+  var_model_table.setLhs(lhsr);
+  var_model_table.setRhs(rhsr);
+  var_model_table.setLhsExprT(lhs_expr_tr);
+  var_model_table.setNonstationary(nonstationaryr);
+}
+
+void
+DynamicModel::fillVarModelTableFromOrigModel(StaticModel &static_model) const
+{
+  map<string, vector<int>> lags, orig_diff_var;
+  map<string, vector<bool>> diff;
+  for (const auto &it : var_model_table.getEqNums())
+    {
+      set<expr_t> lhs;
+      vector<int> orig_diff_var_vec;
+      vector<bool> diff_vec;
+      for (auto eqn : it.second)
+        {
+          // ensure no leads in equations
+          if (equations[eqn]->get_arg2()->VarMinLag() <= 0)
+            {
+              cerr << "ERROR in VAR model Equation (#" << eqn << "). "
+                   << "Leaded exogenous variables "
+                   << "and leaded or contemporaneous endogenous variables not allowed in VAR"
+                   << endl;
+              exit(EXIT_FAILURE);
+            }
+
+          // save lhs variables
+          equations[eqn]->get_arg1()->collectVARLHSVariable(lhs);
+
+          equations[eqn]->get_arg1()->countDiffs() > 0 ?
+            diff_vec.push_back(true) : diff_vec.push_back(false);
+          if (diff_vec.back())
+            {
+              set<pair<int, int>> diff_set;
+              equations[eqn]->get_arg1()->collectDynamicVariables(SymbolType::endogenous, diff_set);
+
+              if (diff_set.size() != 1)
+                {
+                  cerr << "ERROR: problem getting variable for LHS diff operator in equation "
+                       << eqn << endl;
+                  exit(EXIT_FAILURE);
+                }
+              orig_diff_var_vec.push_back(diff_set.begin()->first);
+            }
+          else
+            orig_diff_var_vec.push_back(-1);
+
+        }
+
+      if (it.second.size() != lhs.size())
+        {
+          cerr << "ERROR: The LHS variables of the VAR model are not unique" << endl;
+          exit(EXIT_FAILURE);
+        }
+
+      set<expr_t> lhs_static;
+      for(const auto &lh : lhs)
+        lhs_static.insert(lh->toStatic(static_model));
+
+      vector<int> max_lag;
+      for (auto eqn : it.second)
+        max_lag.push_back(equations[eqn]->get_arg2()->VarMaxLag(static_model, lhs_static));
+      lags[it.first] = max_lag;
+      diff[it.first] = diff_vec;
+      orig_diff_var[it.first] = orig_diff_var_vec;
+    }
+  var_model_table.setDiff(diff);
+  var_model_table.setMaxLags(lags);
+  var_model_table.setOrigDiffVar(orig_diff_var);
+}
+
 void
 DynamicModel::fillTrendComponentModelTable() const
 {
@@ -3530,7 +3693,7 @@ DynamicModel::fillTrendComponentModelTable() const
           if (lhs_set.size() != 1 || !lhs_tmp_set.empty())
             {
               cerr << "ERROR: in Equation " << eqtag
-                   << ". A VAR may only have one endogenous variable on the LHS. " << endl;
+                   << ". A trend component model  may only have one endogenous variable on the LHS. " << endl;
               exit(EXIT_FAILURE);
             }
 
@@ -3538,7 +3701,7 @@ DynamicModel::fillTrendComponentModelTable() const
           if (it->second != 0)
             {
               cerr << "ERROR: in Equation " << eqtag
-                   << ". The variable on the LHS of a VAR may not appear with a lead or a lag. "
+                   << ". The variable on the LHS of a trend component model may not appear with a lead or a lag. "
                    << endl;
               exit(EXIT_FAILURE);
             }
@@ -3555,7 +3718,7 @@ DynamicModel::fillTrendComponentModelTable() const
             if (it->second > 0)
               {
                 cerr << "ERROR: in Equation " << eqtag
-                     << ". A VAR may not have leaded or contemporaneous variables on the RHS. " << endl;
+                     << ". A trend component model may not have leaded or contemporaneous variables on the RHS. " << endl;
                 exit(EXIT_FAILURE);
               }
           rhs.push_back(rhs_set);
@@ -3589,7 +3752,7 @@ DynamicModel::fillTrendComponentModelTableFromOrigModel(StaticModel &static_mode
           // ensure no leads in equations
           if (equations[eqn]->get_arg2()->VarMinLag() <= 0)
             {
-              cerr << "ERROR in VAR Equation (#" << eqn << "). "
+              cerr << "ERROR in trend component model Equation (#" << eqn << "). "
                    << "Leaded exogenous variables "
                    << "and leaded or contemporaneous endogenous variables not allowed in VAR"
                    << endl;
@@ -3621,7 +3784,7 @@ DynamicModel::fillTrendComponentModelTableFromOrigModel(StaticModel &static_mode
 
       if (it.second.size() != lhs.size())
         {
-          cerr << "ERROR: The LHS variables of the VAR are not unique" << endl;
+          cerr << "ERROR: The LHS variables of the trend component model are not unique" << endl;
           exit(EXIT_FAILURE);
         }
 
@@ -3640,19 +3803,23 @@ DynamicModel::fillTrendComponentModelTableFromOrigModel(StaticModel &static_mode
   trend_component_model_table.setMaxLags(lags);
   trend_component_model_table.setOrigDiffVar(orig_diff_var);
 }
-/*
+
 void
-DynamicModel::addEquationsForVar(map<string, pair<SymbolList, int>> &var_model_info)
+DynamicModel::addEquationsForVar()
 {
+  if (var_model_table.empty())
+    return;
+  map<string, pair<SymbolList, int>> var_symbol_list_and_order =
+    var_model_table.getSymbolListAndOrder();
+
   // List of endogenous variables and the minimum lag value that must exist in the model equations
   map<string, int> var_endos_and_lags, model_endos_and_lags;
-  for (map<string, pair<SymbolList, int>>::const_iterator it = var_model_info.begin();
-       it != var_model_info.end(); it++)
+  for (const auto & it : var_symbol_list_and_order)
     for (auto & equation : equations)
-      if (equation->isVarModelReferenced(it->first))
+      if (equation->isVarModelReferenced(it.first))
         {
-          vector<string> symbol_list = it->second.first.get_symbols();
-          int order = it->second.second;
+          vector<string> symbol_list = it.second.first.get_symbols();
+          int order = it.second.second;
           for (vector<string>::const_iterator it1 = symbol_list.begin();
                it1 != symbol_list.end(); it1++)
             if (order > 2)
@@ -3666,7 +3833,8 @@ DynamicModel::addEquationsForVar(map<string, pair<SymbolList, int>> &var_model_i
   if (var_endos_and_lags.empty())
     return;
 
-  // Ensure that the minimum lag value exists in the model equations. If not, add an equation for it
+  // Ensure that the minimum lag value exists in the model equations.
+  // If not, add an equation for it
   for (auto & equation : equations)
     equation->getEndosAndMaxLags(model_endos_and_lags);
 
@@ -3690,9 +3858,10 @@ DynamicModel::addEquationsForVar(map<string, pair<SymbolList, int>> &var_model_i
     }
 
   if (count > 0)
-    cout << "Accounting for var_model lags not in model block: added " << count << " auxiliary variables and equations." << endl;
+    cout << "Accounting for var_model lags not in model block: added "
+         << count << " auxiliary variables and equations." << endl;
 }
-*/
+
 vector<int>
 DynamicModel::getUndiffLHSForPac(const string &aux_model_name,
                                  ExprNode::subst_table_t &diff_subst_table)
diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh
index 90814436..da8d6397 100644
--- a/src/DynamicModel.hh
+++ b/src/DynamicModel.hh
@@ -250,7 +250,11 @@ private:
   void findPacExpectationEquationNumbers(vector<int> &eqnumber) const;
 
 public:
-  DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg, TrendComponentModelTable &trend_component_model_table_arg);
+  DynamicModel(SymbolTable &symbol_table_arg,
+               NumericalConstants &num_constants_arg,
+               ExternalFunctionsTable &external_functions_table_arg,
+               TrendComponentModelTable &trend_component_model_table_arg,
+               VarModelTable &var_model_table_arg);
   //! Adds a variable node
   /*! This implementation allows for non-zero lag */
   VariableNode *AddVariable(int symb_id, int lag = 0) override;
@@ -304,8 +308,14 @@ public:
   void fillTrendComponentModelTable() const;
   void fillTrendComponentModelTableFromOrigModel(StaticModel &static_model) const;
 
-  //! Add aux equations (and aux variables) for variables declared in var_model at max order if they don't already exist
-  //  void addEquationsForVar(map<string, pair<SymbolList, int>> &var_model_info);
+  //! Fill the Var Model Table
+  void fillVarModelTable() const;
+  void fillVarModelTableFromOrigModel(StaticModel &static_model) const;
+
+  //! Add aux equations (and aux variables) for variables declared in var_model
+  //! at max order if they don't already exist
+  void addEquationsForVar();
+
   //! Get Pac equation parameter info
   void walkPacParameters();
   //! Add var_model info to pac_expectation nodes
diff --git a/src/ModFile.cc b/src/ModFile.cc
index 644c7ae3..788801cd 100644
--- a/src/ModFile.cc
+++ b/src/ModFile.cc
@@ -30,25 +30,26 @@
 #include "ComputingTasks.hh"
 
 ModFile::ModFile(WarningConsolidation &warnings_arg)
-  : trend_component_model_table(symbol_table),
-    expressions_tree(symbol_table, num_constants,
-                     external_functions_table, trend_component_model_table),
-    original_model(symbol_table, num_constants,
-                   external_functions_table, trend_component_model_table),
-    dynamic_model(symbol_table, num_constants,
-                  external_functions_table, trend_component_model_table),
-    trend_dynamic_model(symbol_table, num_constants,
-                        external_functions_table, trend_component_model_table),
-    ramsey_FOC_equations_dynamic_model(symbol_table, num_constants,
-                                       external_functions_table, trend_component_model_table),
-    orig_ramsey_dynamic_model(symbol_table, num_constants,
-                              external_functions_table, trend_component_model_table),
-    static_model(symbol_table, num_constants,
-                 external_functions_table, trend_component_model_table),
-    steady_state_model(symbol_table, num_constants,
-                       external_functions_table, trend_component_model_table, static_model),
-    diff_static_model(symbol_table, num_constants,
-                      external_functions_table, trend_component_model_table),
+  : var_model_table(symbol_table),
+    trend_component_model_table(symbol_table),
+    expressions_tree(symbol_table, num_constants, external_functions_table,
+                     trend_component_model_table, var_model_table),
+    original_model(symbol_table, num_constants, external_functions_table,
+                   trend_component_model_table, var_model_table),
+    dynamic_model(symbol_table, num_constants, external_functions_table,
+                  trend_component_model_table, var_model_table),
+    trend_dynamic_model(symbol_table, num_constants, external_functions_table,
+                        trend_component_model_table, var_model_table),
+    ramsey_FOC_equations_dynamic_model(symbol_table, num_constants, external_functions_table,
+                                       trend_component_model_table, var_model_table),
+    orig_ramsey_dynamic_model(symbol_table, num_constants, external_functions_table,
+                              trend_component_model_table, var_model_table),
+    static_model(symbol_table, num_constants, external_functions_table,
+                 trend_component_model_table, var_model_table),
+    steady_state_model(symbol_table, num_constants, external_functions_table,
+                       trend_component_model_table, var_model_table, static_model),
+    diff_static_model(symbol_table, num_constants, external_functions_table,
+                      trend_component_model_table, var_model_table),
     linear(false), block(false), byte_code(false), use_dll(false), no_static(false),
     differentiate_forward_vars(false), nonstationary_variables(false),
     param_used_with_lead_lag(false), warnings(warnings_arg)
@@ -374,19 +375,21 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
     }
 
   // Get all equation tags associated with VARs and Pac Models
-  string var_model_name;
   set<string> eqtags;
-  map<string, vector<string>> var_model_eq_tags;
   map<string, pair<SymbolList, int>> var_model_info_var_expectation;
 
   for (auto const &it : trend_component_model_table.getEqTags())
     for (auto &it1 : it.second)
       eqtags.insert(it1);
 
+  for (auto const &it : var_model_table.getEqTags())
+    for (auto &it1 : it.second)
+      eqtags.insert(it1);
+
   if (transform_unary_ops)
     dynamic_model.substituteUnaryOps(diff_static_model);
   else
-    // substitute only those unary ops that appear in VAR equations
+    // substitute only those unary ops that appear in auxiliary model equations
     dynamic_model.substituteUnaryOps(diff_static_model, eqtags);
 
   // Create auxiliary variable and equations for Diff operators that appear in VAR equations
@@ -396,8 +399,10 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
   // Fill Trend Component Model Table
   dynamic_model.fillTrendComponentModelTable();
   original_model.fillTrendComponentModelTableFromOrigModel(diff_static_model);
+  dynamic_model.fillVarModelTable();
+  original_model.fillVarModelTableFromOrigModel(diff_static_model);
 
-  // Var Model
+  // Pac Model
   for (auto & statement : statements)
     {
       auto *pms = dynamic_cast<PacModelStatement *>(statement);
@@ -415,10 +420,16 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
                lhs = dynamic_model.getUndiffLHSForPac(aux_model_name, diff_subst_table);
                nonstationary = trend_component_model_table.getNonstationary(aux_model_name);
              }
+           else if (var_model_table.isExistingVarModelName(aux_model_name))
+             {
+               max_lag = var_model_table.getMaxLag(aux_model_name) + 1;
+               lhs = var_model_table.getLhs(aux_model_name);
+               nonstationary = var_model_table.getNonstationary(aux_model_name);
+             }
            else
              {
-               // get var_model lhs and max_lag; for now stop with error
-               cerr << "ERROR: var_models not yet supported for use with pac_model" << endl;
+               cerr << "Error: aux_model_name not recognized as VAR model or Trend Component model"
+                    << endl;
                exit(EXIT_FAILURE);
              }
            pms->fillUndiffedLHS(lhs);
@@ -429,10 +440,9 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
            dynamic_model.substitutePacExpectation();
          }
      }
-  /*
-  if (!var_model_info_var_expectation.empty())
-    dynamic_model.addEquationsForVar(var_model_info_var_expectation);
-  */
+
+  dynamic_model.addEquationsForVar();
+
   if (symbol_table.predeterminedNbr() > 0)
     dynamic_model.transformPredeterminedVariables();
 
@@ -507,35 +517,17 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
         continue;
 
       auto &model_name = vems->model_name;
-
-      /* Find the corresponding VM statement and extract information for it;
-         ideally we should have a VarModelTable for that purpose */
-      VarModelStatement *vms = nullptr;
-      for (auto & statement2 : statements)
-        if ((vms = dynamic_cast<VarModelStatement *>(statement2))
-            && vms->name == vems->var_model_name)
-          break;
-      if (!vms)
+      if (!var_model_table.isExistingVarModelName(vems->var_model_name))
         {
-          cerr << "ERROR: var_expectation_model " << model_name << " refers to nonexistent " << vems->var_model_name << " var_model" << endl;
+          cerr << "ERROR: var_expectation_model " << model_name
+               << " refers to nonexistent " << vems->var_model_name << " var_model" << endl;
           exit(EXIT_FAILURE);
         }
-      /* The code below is duplicated further below in this function; but we
-         can't avoid that until the collecting of information about VARs is
-         moved *before* lead/lag substitutions (or even better, in checkPass()) */
-      vector<expr_t> lhs_expr_t;
-      vector<int> lhs, eqnumber;
-      vector<set<pair<int, int>>> rhs;
-      vector<bool> nonstationary;
-      vector<string> eqtags{var_model_eq_tags[var_model_name]};
-      /*
-      dynamic_model.getVarModelVariablesFromEqTags(eqtags,
-                                                   eqnumber, lhs, lhs_expr_t, rhs, nonstationary);
-      */
-      int max_lag = trend_component_model_table.getMaxLag(var_model_name);
 
       /* Create auxiliary parameters and the expression to be substituted to
          the var_expectations statement */
+      int max_lag = var_model_table.getMaxLag(vems->var_model_name);
+      vector<int> lhs = var_model_table.getLhs(vems->var_model_name);
       auto subst_expr = dynamic_model.Zero;
       for (int lag = 0; lag < max_lag; lag++)
         for (auto variable : lhs)
@@ -580,35 +572,8 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const
       dynamic_model.substituteEndoLagGreaterThanTwo(true);
     }
 
-  /* TODO: most of this should rather be done in checkPass(). Also we should
-     probably add a VarModelTable class (similar to SymbolTable) for storing all
-     this information about VAR models, instead of putting it inside the
-     Statement(s) classes */
   dynamic_model.fillTrendComponentModelTable();
-  /*
-  for (auto & statement : statements)
-    {
-      auto *vms = dynamic_cast<VarModelStatement *>(statement);
-      if (vms != nullptr)
-        {
-          string var_model_name;
-          //vms->getVarModelInfo(var_model_name, var_model_info_var_expectation, var_model_eq_tags);
-          vector<expr_t> lhs_expr_t;
-          vector<int> lhs, eqnumber, orig_diff_var;
-          vector<set<pair<int, int>>> rhs;
-          vector<bool> nonstationary, diff;
-          vector<string> eqtags = var_model_eq_tags[var_model_name];
-          dynamic_model.getVarModelVariablesFromEqTags(eqtags,
-                                                       eqnumber, lhs, lhs_expr_t, rhs, nonstationary);
-
-          int max_lag = trend_component_model_table.getMaxLag(var_model_name);
-      //          int max_lag = original_model.getVarMaxLag(diff_static_model, eqnumber);
-          //original_model.getVarLhsDiffAndInfo(eqnumber, diff, orig_diff_var);
-          vms->fillVarModelInfoFromEquations(eqnumber, lhs, rhs, nonstationary,
-                                             diff, orig_diff_var, max_lag);
-        }
-    }
-*/
+
   if (differentiate_forward_vars)
     dynamic_model.differentiateForwardVars(differentiate_forward_vars_subset);
 
@@ -1315,10 +1280,18 @@ ModFile::writeJsonOutputParsingCheck(const string &basename, JsonFileOutputType
   output << ", ";
   dynamic_model.writeJsonOutput(output);
 
+
   if (!statements.empty()
+      || !var_model_table.empty()
       || !trend_component_model_table.empty())
     {
       output << ", \"statements\": [";
+      if (!var_model_table.empty())
+        {
+          var_model_table.writeJsonOutput(output);
+           output << ", ";
+        }
+
       if (!trend_component_model_table.empty())
         {
           trend_component_model_table.writeJsonOutput(output);
diff --git a/src/ModFile.hh b/src/ModFile.hh
index 2e33b74e..f15ccbd8 100644
--- a/src/ModFile.hh
+++ b/src/ModFile.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2017 Dynare Team
+ * Copyright (C) 2006-2018 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -52,6 +52,8 @@ public:
   ExternalFunctionsTable external_functions_table;
   //! Numerical constants table
   NumericalConstants num_constants;
+  //! Var Model Table used for storing info about trend component models
+  VarModelTable var_model_table;
   //! Trend Component Model Table used for storing info about trend component models
   TrendComponentModelTable trend_component_model_table;
   //! Expressions outside model block
diff --git a/src/ModelTree.cc b/src/ModelTree.cc
index 401ad86b..8fa85271 100644
--- a/src/ModelTree.cc
+++ b/src/ModelTree.cc
@@ -1004,9 +1004,10 @@ ModelTree::BlockLinear(const blocks_derivatives_t &blocks_derivatives, const vec
 ModelTree::ModelTree(SymbolTable &symbol_table_arg,
                      NumericalConstants &num_constants_arg,
                      ExternalFunctionsTable &external_functions_table_arg,
-                     TrendComponentModelTable &trend_component_model_table_arg) :
-  DataTree(symbol_table_arg, num_constants_arg,
-           external_functions_table_arg, trend_component_model_table_arg),
+                     TrendComponentModelTable &trend_component_model_table_arg,
+                     VarModelTable &var_model_table_arg) :
+  DataTree(symbol_table_arg, num_constants_arg, external_functions_table_arg,
+           trend_component_model_table_arg, var_model_table_arg),
   cutoff(1e-15),
   mfs(0)
 
diff --git a/src/ModelTree.hh b/src/ModelTree.hh
index 84772d5b..97594d66 100644
--- a/src/ModelTree.hh
+++ b/src/ModelTree.hh
@@ -324,7 +324,8 @@ public:
   ModelTree(SymbolTable &symbol_table_arg,
             NumericalConstants &num_constants_arg,
             ExternalFunctionsTable &external_functions_table_arg,
-            TrendComponentModelTable &trend_component_model_table_arg);
+            TrendComponentModelTable &trend_component_model_table_arg,
+            VarModelTable &var_model_table_arg);
   //! Absolute value under which a number is considered to be zero
   double cutoff;
   //! Compute the minimum feedback set
diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc
index a86b37ff..80bc0642 100644
--- a/src/ParsingDriver.cc
+++ b/src/ParsingDriver.cc
@@ -349,7 +349,8 @@ ParsingDriver::declare_or_change_type(SymbolType new_type, const string &name)
       auto dm = make_unique<DynamicModel>(mod_file->symbol_table,
                                           mod_file->num_constants,
                                           mod_file->external_functions_table,
-                                          mod_file->trend_component_model_table);
+                                          mod_file->trend_component_model_table,
+                                          mod_file->var_model_table);
       mod_file->dynamic_model.updateAfterVariableChange(*dm);
 
       // remove error messages
@@ -1444,25 +1445,34 @@ ParsingDriver::trend_component_model()
 void
 ParsingDriver::var_model()
 {
-  OptionsList::string_options_t::const_iterator it = options_list.string_options.find("var.model_name");
-  if (it == options_list.string_options.end())
+  const auto its = options_list.string_options.find("var.model_name");
+  if (its == options_list.string_options.end())
     error("You must pass the model_name option to the var_model statement.");
-  auto name = it->second;
-
-  if (options_list.vector_str_options.find("var.eqtags") != options_list.vector_str_options.end())
-    if (!symbol_list.empty())
-      error("You cannot pass a symbol list when passing equation tags to the var_model statement");
-    else if (options_list.num_options.find("var.order") != options_list.num_options.end())
-      error("You cannot pass the order option when passing equation tags to the var_model statement");
+  auto name = its->second;
 
+  int order = 0;
+  const auto itn = options_list.num_options.find("var.order");
+  if (itn != options_list.num_options.end())
+    order = stoi(itn->second);
+  else
   if (!symbol_list.empty())
-    if (options_list.num_options.find("var.order") == options_list.num_options.end())
-      error("You must pass the order option when passing a symbol list to the var_model statement");
+    error("You must pass the order option when passing a symbol list to the var_model statement");
 
-  mod_file->addStatement(new VarModelStatement(symbol_list, options_list, name, mod_file->symbol_table));
-  var_map[it->second] = symbol_list.getSymbols();
+  vector<string> eqtags;
+  const auto itvs = options_list.vector_str_options.find("var.eqtags");
+  if (itvs != options_list.vector_str_options.end())
+    {
+      eqtags = itvs->second;
+      if (!symbol_list.empty())
+        error("You cannot pass a symbol list when passing equation tags to the var_model statement");
+      else if (itn != options_list.num_options.end())
+        error("You cannot pass the order option when passing equation tags to the var_model statement");
+    }
+
+  mod_file->var_model_table.addVarModel(name, eqtags, make_pair(symbol_list, order));
   symbol_list.clear();
   options_list.clear();
+  var_map[its->second] = symbol_list.getSymbols();
 }
 
 void
@@ -2071,8 +2081,8 @@ ParsingDriver::begin_planner_objective()
   planner_objective_statement = new PlannerObjectiveStatement(mod_file->symbol_table,
                                                               mod_file->num_constants,
                                                               mod_file->external_functions_table,
-                                                              mod_file->trend_component_model_table);
-
+                                                              mod_file->trend_component_model_table,
+                                                              mod_file->var_model_table);
   set_current_data_tree(&planner_objective_statement->getPlannerObjective());
 }
 
diff --git a/src/StaticModel.cc b/src/StaticModel.cc
index f9834c2f..32ac5ccb 100644
--- a/src/StaticModel.cc
+++ b/src/StaticModel.cc
@@ -32,9 +32,10 @@
 StaticModel::StaticModel(SymbolTable &symbol_table_arg,
                          NumericalConstants &num_constants_arg,
                          ExternalFunctionsTable &external_functions_table_arg,
-                         TrendComponentModelTable &trend_component_model_table_arg) :
-  ModelTree(symbol_table_arg, num_constants_arg,
-            external_functions_table_arg, trend_component_model_table_arg),
+                         TrendComponentModelTable &trend_component_model_table_arg,
+                         VarModelTable &var_model_table_arg) :
+  ModelTree(symbol_table_arg, num_constants_arg, external_functions_table_arg,
+            trend_component_model_table_arg, var_model_table_arg),
   global_temporary_terms(true)
 {
 }
diff --git a/src/StaticModel.hh b/src/StaticModel.hh
index 5374739d..341b36e5 100644
--- a/src/StaticModel.hh
+++ b/src/StaticModel.hh
@@ -163,7 +163,8 @@ public:
   StaticModel(SymbolTable &symbol_table_arg,
               NumericalConstants &num_constants,
               ExternalFunctionsTable &external_functions_table_arg,
-              TrendComponentModelTable &trend_component_model_table_arg);
+              TrendComponentModelTable &trend_component_model_table_arg,
+              VarModelTable &var_model_table_arg);
 
   //! Writes information on block decomposition when relevant
   void writeOutput(ostream &output, bool block) const;
diff --git a/src/SteadyStateModel.cc b/src/SteadyStateModel.cc
index 282d8e1b..0291135f 100644
--- a/src/SteadyStateModel.cc
+++ b/src/SteadyStateModel.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2017 Dynare Team
+ * Copyright (C) 2010-2018 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -26,9 +26,10 @@ SteadyStateModel::SteadyStateModel(SymbolTable &symbol_table_arg,
                                    NumericalConstants &num_constants_arg,
                                    ExternalFunctionsTable &external_functions_table_arg,
                                    TrendComponentModelTable &trend_component_model_table_arg,
+                                   VarModelTable &var_model_table_arg,
                                    const StaticModel &static_model_arg) :
-  DataTree(symbol_table_arg, num_constants_arg,
-           external_functions_table_arg, trend_component_model_table_arg),
+  DataTree(symbol_table_arg, num_constants_arg, external_functions_table_arg,
+           trend_component_model_table_arg, var_model_table_arg),
   static_model(static_model_arg)
 {
 }
diff --git a/src/SteadyStateModel.hh b/src/SteadyStateModel.hh
index d3b4e2db..bf436766 100644
--- a/src/SteadyStateModel.hh
+++ b/src/SteadyStateModel.hh
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2017 Dynare Team
+ * Copyright (C) 2010-2018 Dynare Team
  *
  * This file is part of Dynare.
  *
@@ -39,6 +39,7 @@ public:
                    NumericalConstants &num_constants_arg,
                    ExternalFunctionsTable &external_functions_table_arg,
                    TrendComponentModelTable &trend_component_model_table_arg,
+                   VarModelTable &var_model_table_arg,
                    const StaticModel &static_model_arg);
   //! Add an expression of the form "var = expr;"
   void addDefinition(int symb_id, expr_t expr);
diff --git a/src/SubModel.cc b/src/SubModel.cc
index 0e399796..731993e2 100644
--- a/src/SubModel.cc
+++ b/src/SubModel.cc
@@ -301,3 +301,241 @@ TrendComponentModelTable::writeJsonOutput(ostream &output) const
       output << "]}";
     }
 }
+
+VarModelTable::VarModelTable(SymbolTable &symbol_table_arg) :
+  symbol_table(symbol_table_arg)
+{
+}
+
+void
+VarModelTable::addVarModel(string name_arg, vector<string> eqtags_arg,
+                           pair<SymbolList, int> symbol_list_and_order_arg)
+{
+  if (isExistingVarModelName(name_arg))
+    {
+      cerr << "Error: a VAR model already exists with the name " << name_arg << endl;
+      exit(EXIT_FAILURE);
+    }
+
+  eqtags[name_arg] = move(eqtags_arg);
+  symbol_list_and_order[name_arg] = move(symbol_list_and_order_arg);
+  names.insert(move(name_arg));
+}
+
+map<string, pair<SymbolList, int>>
+VarModelTable::getSymbolListAndOrder() const
+{
+  return symbol_list_and_order;
+}
+
+void
+VarModelTable::writeOutput(ostream &output) const
+{
+  for (const auto &name : names)
+    {
+      output << "M_.var." << name << ".model_name = '" << name << "';" << endl;
+      if (!symbol_list_and_order.empty())
+        {
+          symbol_list_and_order.at(name).first.writeOutput("M_.var." + name + ".var_list_", output);
+          output  << "M_.var." << name << ".order = "
+                  << symbol_list_and_order.at(name).second << ";" << endl;
+        }
+      output << "M_.var." << name << ".eqtags = {";
+      for (const auto &it : eqtags.at(name))
+        output << "'" << it << "'; ";
+      output << "};" << endl
+             << "M_.var." << name << ".eqn = [";
+      for (auto it : eqnums.at(name))
+        output << it + 1 << " ";
+      output << "];" << endl
+             << "M_.var." << name << ".lhs = [";
+      for (auto it : lhs.at(name))
+        output << symbol_table.getTypeSpecificID(it) + 1 << " ";
+      output << "];" << endl
+             << "M_.var." << name << ".max_lag = [";
+      for (auto it : max_lags.at(name))
+        output << it << " ";
+      output << "];" << endl
+             << "M_.var." << name << ".diff = [";
+      for (const auto &it : diff.at(name))
+        output << (it ? "true" : "false") << " ";
+      output << "];" << endl
+             << "M_.var." << name << ".orig_diff_var = [";
+      for (auto it : orig_diff_var.at(name))
+        output << (it >= 0 ? symbol_table.getTypeSpecificID(it) + 1 : -1) << " ";
+      output << "];" << endl;
+
+      int i = 1;
+      for (const auto &it : rhs.at(name))
+        {
+          output << "M_.var." << name << ".rhs.vars_at_eq{" << i << "}.var = [";
+          for (const auto &it1 : it)
+            output << symbol_table.getTypeSpecificID(it1.first) + 1 << " ";
+          output << "];" << endl
+                 << "M_.var." << name << ".rhs.vars_at_eq{" << i << "}.lag = [";
+          for (const auto &it1 : it)
+            output << it1.second << " ";
+          output << "];" << endl;
+
+          i++;
+        }
+    }
+}
+
+void
+VarModelTable::writeJsonOutput(ostream &output) const
+{
+  for (const auto &name : names)
+    {
+      if (name != *(names.begin()))
+        output << ", ";
+      output << "{\"statementName\": \"var_model\","
+             << "\"model_name\": \"" << name << "\",";
+      if (symbol_list_and_order.empty())
+        {
+          output << "\"eqtags\": [";
+          for (const auto &it : eqtags.at(name))
+            {
+              output << "\"" << it << "\"";
+              if (&it != &eqtags.at(name).back())
+                output << ", ";
+            }
+          output << "]";
+        }
+      else
+        {
+          output << "\"order\": \"" << symbol_list_and_order.at(name).second << "\",";
+        }
+      output << "}";
+    }
+}
+
+map<string, vector<string>>
+VarModelTable::getEqTags() const
+{
+  return eqtags;
+}
+
+vector<string>
+VarModelTable::getEqTags(const string &name_arg) const
+{
+  checkModelName(name_arg);
+  return eqtags.find(name_arg)->second;
+}
+
+void
+VarModelTable::checkModelName(const string &name_arg) const
+{
+  if (!isExistingVarModelName(name_arg))
+    {
+      cerr << name_arg
+           << " is not a recognized equation tag of a VAR model equation" << endl;
+      exit(EXIT_FAILURE);
+    }
+}
+
+void
+VarModelTable::setEqNums(map<string, vector<int>> eqnums_arg)
+{
+  eqnums = move(eqnums_arg);
+}
+
+void
+VarModelTable::setLhs(map<string, vector<int>> lhs_arg)
+{
+  lhs = move(lhs_arg);
+}
+
+void
+VarModelTable::setRhs(map<string, vector<set<pair<int, int>>>> rhs_arg)
+{
+  rhs = move(rhs_arg);
+}
+
+void
+VarModelTable::setLhsExprT(map<string, vector<expr_t>> lhs_expr_t_arg)
+{
+  lhs_expr_t = move(lhs_expr_t_arg);
+}
+
+void
+VarModelTable::setNonstationary(map<string, vector<bool>> nonstationary_arg)
+{
+  nonstationary = move(nonstationary_arg);
+}
+
+map<string, vector<int>>
+VarModelTable::getEqNums() const
+{
+  return eqnums;
+}
+
+vector<int>
+VarModelTable::getEqNums(const string &name_arg) const
+{
+  checkModelName(name_arg);
+  return eqnums.find(name_arg)->second;
+}
+
+void
+VarModelTable::setMaxLags(map<string, vector<int>> max_lags_arg)
+{
+  max_lags = move(max_lags_arg);
+}
+
+void
+VarModelTable::setDiff(map<string, vector<bool>> diff_arg)
+{
+  diff = move(diff_arg);
+}
+
+void
+VarModelTable::setOrigDiffVar(map<string, vector<int>> orig_diff_var_arg)
+{
+  orig_diff_var = move(orig_diff_var_arg);
+}
+
+vector<int>
+VarModelTable::getMaxLags(const string &name_arg) const
+{
+  checkModelName(name_arg);
+  return max_lags.find(name_arg)->second;
+}
+
+int
+VarModelTable::getMaxLag(const string &name_arg) const
+{
+  int max_lag_int = 0;
+  for (auto it : getMaxLags(name_arg))
+    max_lag_int = max(max_lag_int, it);
+  return max_lag_int;
+}
+
+vector<int>
+VarModelTable::getLhs(const string &name_arg) const
+{
+  checkModelName(name_arg);
+  return lhs.find(name_arg)->second;
+}
+
+vector<bool>
+VarModelTable::getNonstationary(const string &name_arg) const
+{
+  checkModelName(name_arg);
+  return nonstationary.find(name_arg)->second;
+}
+
+vector<set<pair<int, int>>>
+VarModelTable::getRhs(const string &name_arg) const
+{
+  checkModelName(name_arg);
+  return rhs.find(name_arg)->second;
+}
+
+
+vector<expr_t>
+VarModelTable::getLhsExprT(const string &name_arg) const
+{
+  checkModelName(name_arg);
+  return lhs_expr_t.find(name_arg)->second;
+}
diff --git a/src/SubModel.hh b/src/SubModel.hh
index d03ad0fd..d8b691f0 100644
--- a/src/SubModel.hh
+++ b/src/SubModel.hh
@@ -101,4 +101,69 @@ TrendComponentModelTable::empty() const
   return names.empty();
 }
 
+
+class VarModelTable
+{
+private:
+  SymbolTable &symbol_table;
+  set<string> names;
+  map<string, pair<SymbolList, int>> symbol_list_and_order;
+  map<string, vector<string>> eqtags;
+  map<string, vector<int>> eqnums, max_lags, lhs, orig_diff_var;
+  map<string, vector<set<pair<int, int>>>> rhs;
+  map<string, vector<bool>> diff, nonstationary;
+  map<string, vector<expr_t>> lhs_expr_t;
+public:
+  VarModelTable(SymbolTable &symbol_table_arg);
+
+  //! Add a trend component model
+  void addVarModel(string name, vector<string> eqtags,
+                   pair<SymbolList, int> symbol_list_and_order_arg);
+
+  inline bool isExistingVarModelName(const string &name_arg) const;
+  inline bool empty() const;
+
+  map<string, vector<string>> getEqTags() const;
+  vector<string> getEqTags(const string &name_arg) const;
+  map<string, vector<int>> getEqNums() const;
+  vector<int> getEqNums(const string &name_arg) const;
+  vector<int> getMaxLags(const string &name_arg) const;
+  int getMaxLag(const string &name_arg) const;
+  vector<int> getLhs(const string &name_arg) const;
+  vector<bool> getNonstationary(const string &name_arg) const;
+  map<string, pair<SymbolList, int>> getSymbolListAndOrder() const;
+  vector<set<pair<int, int>>> getRhs(const string &name_arg) const;
+  vector<expr_t> getLhsExprT(const string &name_arg) const;
+
+  void setEqNums(map<string, vector<int>> eqnums_arg);
+  void setLhs(map<string, vector<int>> lhs_arg);
+  void setRhs(map<string, vector<set<pair<int, int>>>> rhs_arg);
+  void setLhsExprT(map<string, vector<expr_t>> lhs_expr_t_arg);
+  void setNonstationary(map<string, vector<bool>> nonstationary_arg);
+  void setDiff(map<string, vector<bool>> diff_arg);
+  void setMaxLags(map<string, vector<int>> max_lags_arg);
+  void setOrigDiffVar(map<string, vector<int>> orig_diff_var_arg);
+
+  //! Write output of this class
+  void writeOutput(ostream &output) const;
+
+  //! Write JSON Output
+  void writeJsonOutput(ostream &output) const;
+
+private:
+  void checkModelName(const string &name_arg) const;
+};
+
+inline bool
+VarModelTable::isExistingVarModelName(const string &name_arg) const
+{
+  return names.find(name_arg) == names.end() ? false : true;
+}
+
+inline bool
+VarModelTable::empty() const
+{
+  return names.empty();
+}
+
 #endif
-- 
GitLab