Commit 539fddc9 authored by Houtan Bastani's avatar Houtan Bastani
Browse files

introduce var model table

parent 6015b0e5
......@@ -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}
{
}
......
......@@ -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;
......
......@@ -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");
......
......@@ -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();
......
......@@ -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)
......
......@@ -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
......
......@@ -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