Commit afe0e475 authored by Houtan Bastani's avatar Houtan Bastani
Browse files

trend_component_model statement

parent 618147a1
......@@ -258,16 +258,14 @@ PriorPosteriorFunctionStatement::writeJsonOutput(ostream &output) const
}
PacModelStatement::PacModelStatement(string name_arg,
string var_name_arg,
string aux_model_name_arg,
string discount_arg,
string growth_arg,
map<string, int> undiff_arg,
const SymbolTable &symbol_table_arg) :
name{move(name_arg)},
var_name{move(var_name_arg)},
aux_model_name{move(aux_model_name_arg)},
discount{move(discount_arg)},
growth{move(growth_arg)},
undiff{move(undiff_arg)},
symbol_table{symbol_table_arg}
{
}
......@@ -289,7 +287,7 @@ PacModelStatement::fillUndiffedLHS(vector<int> &lhs_arg)
void
PacModelStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
output << "M_.pac." << name << ".var_model_name = '" << var_name << "';" << endl
output << "M_.pac." << name << ".auxiliary_model_name = '" << aux_model_name << "';" << endl
<< "M_.pac." << name << ".discount_index = " << symbol_table.getTypeSpecificID(discount) + 1 << ";" << endl;
if (!growth.empty())
......@@ -320,7 +318,8 @@ PacModelStatement::writeOutput(ostream &output, const string &basename, bool min
output << " ";
output << *it + 1;
}
output << "];" << endl
output << "];" << endl;
/*
<< "M_.pac." << name << ".undiff_eqtags = {";
for (auto it = undiff.begin(); it != undiff.end(); it++)
{
......@@ -337,6 +336,7 @@ PacModelStatement::writeOutput(ostream &output, const string &basename, bool min
output << it->second;
}
output << "];" << endl;
*/
}
void
......@@ -344,7 +344,7 @@ PacModelStatement::writeJsonOutput(ostream &output) const
{
output << "{\"statementName\": \"pac_model\","
<< "\"model_name\": \"" << name << "\","
<< "\"var_model_name\": \"" << var_name << "\","
<< "\"auxiliary_model_name\": \"" << aux_model_name << "\","
<< "\"discount_index\": " << symbol_table.getTypeSpecificID(discount) + 1;
if (!growth.empty())
......@@ -371,13 +371,13 @@ PacModelStatement::writeJsonOutput(ostream &output) const
output << "}";
}
void
PacModelStatement::getPacModelInfoForPacExpectation(tuple<string, string, string, int, map<string, int>> &pac_model_info) const
tuple<string, string, int>
PacModelStatement::getPacModelInfoForPacExpectation() const
{
int growth_symb_id = -1;
if (!growth.empty())
growth_symb_id = symbol_table.getID(growth);
pac_model_info = { name, var_name, discount, growth_symb_id, undiff };
return { name, aux_model_name, growth_symb_id };
}
VarModelStatement::VarModelStatement(SymbolList symbol_list_arg,
......@@ -2207,8 +2207,12 @@ ModelComparisonStatement::writeJsonOutput(ostream &output) const
output << "}";
}
PlannerObjectiveStatement::PlannerObjectiveStatement(SymbolTable &symbol_table, NumericalConstants &num_constants, ExternalFunctionsTable &external_functions_table) :
model_tree{symbol_table, num_constants, external_functions_table}
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}
{
}
......
......@@ -123,24 +123,22 @@ class PacModelStatement : public Statement
{
private:
const string name;
const string var_name;
const string aux_model_name;
const string discount;
const string growth;
const map<string, int> undiff;
const SymbolTable &symbol_table;
vector<int> lhs;
public:
PacModelStatement(string name_arg,
string var_name_arg,
string aux_model_name_arg,
string discount_arg,
string growth_arg,
map<string, int> undiff_arg,
const SymbolTable &symbol_table_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;
void fillUndiffedLHS(vector<int> &lhs);
void getPacModelInfoForPacExpectation(tuple<string, string, string, int, map<string, int>> &pac_model_info) const;
tuple<string, string, int> getPacModelInfoForPacExpectation() const;
};
class VarModelStatement : public Statement
......@@ -542,7 +540,8 @@ private:
public:
PlannerObjectiveStatement(SymbolTable &symbol_table,
NumericalConstants &num_constants,
ExternalFunctionsTable &external_functions_table);
ExternalFunctionsTable &external_functions_table,
TrendComponentModelTable &trend_component_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;
......
......@@ -28,10 +28,12 @@
DataTree::DataTree(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg) :
ExternalFunctionsTable &external_functions_table_arg,
TrendComponentModelTable &trend_component_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),
node_counter(0)
{
Zero = AddNonNegativeConstant("0");
......
......@@ -34,6 +34,7 @@ using namespace std;
#include "NumericalConstants.hh"
#include "ExternalFunctionsTable.hh"
#include "ExprNode.hh"
#include "SubModel.hh"
class DataTree
{
......@@ -56,6 +57,8 @@ protected:
NumericalConstants &num_constants;
//! A reference to the external functions table
ExternalFunctionsTable &external_functions_table;
//! A reference to the trend component model table
TrendComponentModelTable &trend_component_model_table;
//! num_constant_id -> NumConstNode
using num_const_node_map_t = map<int, NumConstNode *>;
......@@ -130,7 +133,10 @@ private:
inline expr_t AddTrinaryOp(expr_t arg1, TrinaryOpcode op_code, expr_t arg2, expr_t arg3);
public:
DataTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg);
DataTree(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg,
TrendComponentModelTable &trend_component_model_table_arg);
virtual
~DataTree();
......
......@@ -33,8 +33,10 @@
DynamicModel::DynamicModel(SymbolTable &symbol_table_arg,
NumericalConstants &num_constants_arg,
ExternalFunctionsTable &external_functions_table_arg) :
ModelTree(symbol_table_arg, num_constants_arg, external_functions_table_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),
max_lag(0), max_lead(0),
max_endo_lag(0), max_endo_lead(0),
max_exo_lag(0), max_exo_lead(0),
......@@ -3453,153 +3455,192 @@ DynamicModel::runTrendTest(const eval_context_t &eval_context)
}
void
DynamicModel::getVarModelVariablesFromEqTags(vector<string> &var_model_eqtags,
vector<int> &eqnumber,
vector<int> &lhs,
vector<expr_t> &lhs_expr_t,
vector<set<pair<int, int>>> &rhs,
vector<bool> &nonstationary) const
DynamicModel::fillTrendComponentModelTable() const
{
for (vector<string>::const_iterator itvareqs = var_model_eqtags.begin();
itvareqs != var_model_eqtags.end(); itvareqs++)
map<string, vector<int>> eqnums, trend_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 = trend_component_model_table.getEqTags();
map<string, vector<string>> trend_eqtags = trend_component_model_table.getTrendEqTags();
for (const auto &it : trend_eqtags)
{
int eqn = -1;
set<pair<int, int>> lhs_set, lhs_tmp_set, rhs_set;
string eqtag (*itvareqs);
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)
vector<int> trend_eqnumber;
for (const auto &eqtag : it.second)
{
cerr << "ERROR: equation tag '" << eqtag << "' not found" << endl;
exit(EXIT_FAILURE);
}
int eqn = -1;
for (const auto &equation_tag : equation_tags)
if (equation_tag.second.first == "name"
&& equation_tag.second.second == eqtag)
{
eqn = equation_tag.first;
break;
}
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")
if (eqn == -1)
{
nonstationary_bool = true;
break;
cerr << "ERROR: trend equation tag '" << eqtag << "' not found" << endl;
exit(EXIT_FAILURE);
}
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);
trend_eqnumber.push_back(eqn);
}
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 (it = rhs_set.begin(); it != rhs_set.end(); it++)
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);
trend_eqnums[it.first] = trend_eqnumber;
}
}
void
DynamicModel::checkVarMinLag(vector<int> &eqnumber) const
{
int eqn = 1;
for (vector<int>::const_iterator it = eqnumber.begin();
it != eqnumber.end(); it++, eqn++)
for (const auto &it : eqtags)
{
int min_lag = -1;
min_lag = equations[*it]->get_arg2()->VarMinLag();
if (min_lag <= 0)
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)
{
cerr << "ERROR in VAR Equation #" << eqn << ". "
<< "Leaded exogenous variables and leaded or contemporaneous endogenous variables not allowed in VAR";
exit(EXIT_FAILURE);
}
}
}
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;
}
int
DynamicModel::getVarMaxLag(StaticModel &static_model, vector<int> &eqnumber) const
{
set<expr_t> lhs;
for (vector<int>::const_iterator it = eqnumber.begin();
it != eqnumber.end(); it++)
equations[*it]->get_arg1()->collectVARLHSVariable(lhs);
if (eqn == -1)
{
cerr << "ERROR: equation tag '" << eqtag << "' not found" << endl;
exit(EXIT_FAILURE);
}
if (eqnumber.size() != lhs.size())
{
cerr << "The LHS variables of the VAR are not unique" << 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);
}
set<expr_t> lhs_static;
for(auto lh : lhs)
lhs_static.insert(lh->toStatic(static_model));
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);
}
int max_lag = 0;
for (vector<int>::const_iterator it = eqnumber.begin();
it != eqnumber.end(); it++)
max_lag = max(max_lag,
equations[*it]->get_arg2()->VarMaxLag(static_model, lhs_static));
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()));
return max_lag;
equations[eqn]->get_arg2()->collectDynamicVariables(SymbolType::endogenous, rhs_set);
for (it = rhs_set.begin(); it != rhs_set.end(); it++)
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;
}
trend_component_model_table.setEqNums(eqnums);
trend_component_model_table.setTrendEqNums(trend_eqnums);
trend_component_model_table.setLhs(lhsr);
trend_component_model_table.setRhs(rhsr);
trend_component_model_table.setLhsExprT(lhs_expr_tr);
trend_component_model_table.setNonstationary(nonstationaryr);
}
void
DynamicModel::getVarLhsDiffAndInfo(vector<int> &eqnumber, vector<bool> &diff,
vector<int> &orig_diff_var) const
DynamicModel::fillTrendComponentModelTableFromOrigModel(StaticModel &static_model) const
{
for (vector<int>::const_iterator it = eqnumber.begin();
it != eqnumber.end(); it++)
map<string, vector<int>> lags, orig_diff_var;
map<string, vector<bool>> diff;
for (const auto &it : trend_component_model_table.getEqNums())
{
equations[*it]->get_arg1()->countDiffs() > 0 ? diff.push_back(true) : diff.push_back(false);
if (diff.back())
set<expr_t> lhs;
vector<int> orig_diff_var_vec;
vector<bool> diff_vec;
for (auto eqn : it.second)
{
set<pair<int, int>> diff_set;
equations[*it]->get_arg1()->collectDynamicVariables(SymbolType::endogenous, diff_set);
if (diff_set.size() != 1)
// ensure no leads in equations
if (equations[eqn]->get_arg2()->VarMinLag() <= 0)
{
cerr << "ERROR: problem getting variable for LHS diff operator in equation " << *it << endl;
cerr << "ERROR in VAR Equation (#" << eqn << "). "
<< "Leaded exogenous variables "
<< "and leaded or contemporaneous endogenous variables not allowed in VAR"
<< endl;
exit(EXIT_FAILURE);
}
orig_diff_var.push_back(diff_set.begin()->first);
// 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);
}
else
orig_diff_var.push_back(-1);
if (it.second.size() != lhs.size())
{
cerr << "ERROR: The LHS variables of the VAR 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;
}
trend_component_model_table.setDiff(diff);
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)
{
......@@ -3651,34 +3692,20 @@ 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;
}
void
DynamicModel::getUndiffLHSForPac(vector<int> &lhs, vector<expr_t> &lhs_expr_t, vector<bool> &diff, vector<int> &orig_diff_var,
vector<int> &eqnumber, map<string, int> &undiff, ExprNode::subst_table_t &diff_subst_table)
*/
vector<int>
DynamicModel::getUndiffLHSForPac(const string &aux_model_name,
ExprNode::subst_table_t &diff_subst_table)
{
if (undiff.empty())
return;
for (map<string, int>::const_iterator it = undiff.begin();
it != undiff.end(); it++)
vector<expr_t> lhs_expr_t = trend_component_model_table.getLhsExprT(aux_model_name);
vector<int> lhs = trend_component_model_table.getLhs(aux_model_name);
vector<bool> diff = trend_component_model_table.getDiff(aux_model_name);
vector<int> orig_diff_var = trend_component_model_table.getOrigDiffVar(aux_model_name);
vector<int> eqnumber = trend_component_model_table.getEqNums(aux_model_name);
vector<int> nontrend_eqnums = trend_component_model_table.getNonTrendEqNums(aux_model_name);
for (auto eqn : nontrend_eqnums)
{
int eqn = -1;
string eqtag (it->first);
for (vector<pair<int, pair<string, string>>>::const_iterator iteqtag =
equation_tags.begin(); iteqtag != equation_tags.end(); iteqtag++)
if (iteqtag->second.first == "name"
&& iteqtag->second.second == eqtag)
{
eqn = iteqtag->first;
break;
}
if (eqn == -1)
{
cerr << "ERROR: undiff equation tag '" << eqtag << "' not found" << endl;
exit(EXIT_FAILURE);
}
int i = 0;
for (vector<int>::const_iterator it1 = eqnumber.begin();
it1 != eqnumber.end(); it1++, i++)
......@@ -3693,9 +3720,9 @@ DynamicModel::getUndiffLHSForPac(vector<int> &lhs, vector<expr_t> &lhs_expr_t, v
if (diff.at(i) != true)
{
cerr << "ERROR: the variable on the LHS of equation #" << eqn << " (VAR equation #" << i
<< " with equation tag '" << eqtag
<< "') does not have the diff operator applied to it yet you are trying to undiff it." << endl;
cerr << "ERROR: the variable on the LHS of equation #" << eqn
<< " does not have the diff operator applied to it yet you are trying to undiff it."
<< endl;
exit(EXIT_FAILURE);
}
......@@ -3716,20 +3743,10 @@ DynamicModel::getUndiffLHSForPac(vector<int> &lhs, vector<expr_t> &lhs_expr_t, v
exit(EXIT_FAILURE);
}
for (int j = it->second; j > 0; j--)
if (printerr)
{
cerr << "You are undiffing the LHS of equation #" << eqn << " "
<< it->second << " times but it has only been diffed " << j << " time(s)" << endl;
exit(EXIT_FAILURE);
}
else
{
node = node->undiff();
it1 = diff_subst_table.find(node);
if (it1 == diff_subst_table.end())
printerr = true;
}
node = node->undiff();
it1 = diff_subst_table.find(node);
if (it1 == diff_subst_table.end())
printerr = true;
if (printerr)
{ // we have undiffed something like diff(x), hence x is not in diff_subst_table
......@@ -3742,6 +3759,7 @@ DynamicModel::getUndiffLHSForPac(vector<int> &lhs, vector<expr_t> &lhs_expr_t, v
lhs.at(i) = const_cast<VariableNode *>(it1->second)->get_symb_id();
}
}
return lhs;
}
void
......@@ -3807,7 +3825,8 @@ DynamicModel::fillPacExpectationVarInfo(string &pac_model_name,
int growth_symb_id)
{
for (size_t i = 0; i < equations.size(); i++)
equations[i]->fillPacExpectationVarInfo(pac_model_name, lhs, max_lag, pac_max_lag, nonstationary, growth_symb_id, i);
equations[i]->fillPacExpectationVarInfo(pac_model_name, lhs, max_lag,
pac_max_lag, nonstationary, growth_symb_id, i);
}
void
......
......@@ -250,7 +250,7 @@ private:
void findPacExpectationEquationNumbers(vector<int> &eqnumber) const;