From afe0e475b1a8d9ddb0ff687fa87ef081ad2418c5 Mon Sep 17 00:00:00 2001 From: Houtan Bastani <houtan@dynare.org> Date: Tue, 14 Aug 2018 14:23:21 +0200 Subject: [PATCH] trend_component_model statement --- src/ComputingTasks.cc | 28 ++-- src/ComputingTasks.hh | 11 +- src/DataTree.cc | 4 +- src/DataTree.hh | 8 +- src/DynamicModel.cc | 349 +++++++++++++++++++++------------------- src/DynamicModel.hh | 28 +--- src/DynareBison.yy | 28 +++- src/DynareFlex.ll | 3 + src/Makefile.am | 4 +- src/ModFile.cc | 134 ++++++++------- src/ModFile.hh | 4 + src/ModelTree.cc | 6 +- src/ModelTree.hh | 5 +- src/ParsingDriver.cc | 48 ++++-- src/ParsingDriver.hh | 6 +- src/StaticModel.cc | 6 +- src/StaticModel.hh | 5 +- src/SteadyStateModel.cc | 10 +- src/SteadyStateModel.hh | 6 +- src/SubModel.cc | 288 +++++++++++++++++++++++++++++++++ src/SubModel.hh | 96 +++++++++++ 21 files changed, 767 insertions(+), 310 deletions(-) create mode 100644 src/SubModel.cc create mode 100644 src/SubModel.hh diff --git a/src/ComputingTasks.cc b/src/ComputingTasks.cc index 6a66fba3..992f38a7 100644 --- a/src/ComputingTasks.cc +++ b/src/ComputingTasks.cc @@ -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} { } diff --git a/src/ComputingTasks.hh b/src/ComputingTasks.hh index f6e7a094..cdfe4499 100644 --- a/src/ComputingTasks.hh +++ b/src/ComputingTasks.hh @@ -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; diff --git a/src/DataTree.cc b/src/DataTree.cc index 36f7c08b..b824ccab 100644 --- a/src/DataTree.cc +++ b/src/DataTree.cc @@ -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"); diff --git a/src/DataTree.hh b/src/DataTree.hh index 45c90723..7e0635de 100644 --- a/src/DataTree.hh +++ b/src/DataTree.hh @@ -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(); diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc index 5d89412a..157def47 100644 --- a/src/DynamicModel.cc +++ b/src/DynamicModel.cc @@ -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 diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh index 51b87ff5..90814436 100644 --- a/src/DynamicModel.hh +++ b/src/DynamicModel.hh @@ -250,7 +250,7 @@ private: void findPacExpectationEquationNumbers(vector<int> &eqnumber) const; public: - DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg); + DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg, TrendComponentModelTable &trend_component_model_table_arg); //! Adds a variable node /*! This implementation allows for non-zero lag */ VariableNode *AddVariable(int symb_id, int lag = 0) override; @@ -300,26 +300,12 @@ public: //! Set the equations that have non-zero second derivatives void setNonZeroHessianEquations(map<int, string> &eqs); - //! Get equation info associated with equation tags from var_model - void 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; - - //! Returns the max lag of the VAR - void checkVarMinLag(vector<int> &eqnumber) const; - - //! Returns the max lag of the VAR - int getVarMaxLag(StaticModel &static_model, vector<int> &eqnumber) const; - - // Get equtaino information on diff operator and max lag info - void getVarLhsDiffAndInfo(vector<int> &eqnumber, vector<bool> &diff, - vector<int> &orig_diff_var) const; + //! Fill the Trend Component Model Table + 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); + // void addEquationsForVar(map<string, pair<SymbolList, int>> &var_model_info); //! Get Pac equation parameter info void walkPacParameters(); //! Add var_model info to pac_expectation nodes @@ -439,8 +425,8 @@ public: int getPacMaxLag(const string &pac_model_name) const; //! Table to undiff LHS variables for pac vector z - void 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> getUndiffLHSForPac(const string &aux_model_name, + ExprNode::subst_table_t &diff_subst_table); //! Transforms the model by replacing trend variables with a 1 void removeTrendVariableFromEquations(); diff --git a/src/DynareBison.yy b/src/DynareBison.yy index 87bf4f67..ba29f096 100644 --- a/src/DynareBison.yy +++ b/src/DynareBison.yy @@ -111,7 +111,7 @@ class ParsingDriver; %token PRINT PRIOR_MC PRIOR_TRUNC PRIOR_MODE PRIOR_MEAN POSTERIOR_MODE POSTERIOR_MEAN POSTERIOR_MEDIAN MLE_MODE PRUNING %token <string> QUOTED_STRING %token QZ_CRITERIUM QZ_ZERO_THRESHOLD DSGE_VAR DSGE_VARLAG DSGE_PRIOR_WEIGHT TRUNCATE PIPE_E PIPE_X PIPE_P -%token RELATIVE_IRF REPLIC SIMUL_REPLIC RPLOT SAVE_PARAMS_AND_STEADY_STATE PARAMETER_UNCERTAINTY +%token RELATIVE_IRF REPLIC SIMUL_REPLIC RPLOT SAVE_PARAMS_AND_STEADY_STATE PARAMETER_UNCERTAINTY TRENDS %token SHOCKS SHOCK_DECOMPOSITION SHOCK_GROUPS USE_SHOCK_GROUPS SIGMA_E SIMUL SIMUL_ALGO SIMUL_SEED ENDOGENOUS_TERMINAL_PERIOD %token SMOOTHER SMOOTHER2HISTVAL SQUARE_ROOT_SOLVER STACK_SOLVE_ALGO STEADY_STATE_MODEL SOLVE_ALGO SOLVER_PERIODS ROBUST_LIN_SOLVE %token STDERR STEADY STOCH_SIMUL SYLVESTER SYLVESTER_FIXED_POINT_TOL REGIMES REGIME REALTIME_SHOCK_DECOMPOSITION @@ -120,14 +120,14 @@ class ParsingDriver; %token UNIFORM_PDF UNIT_ROOT_VARS USE_DLL USEAUTOCORR GSA_SAMPLE_FILE USE_UNIVARIATE_FILTERS_IF_SINGULARITY_IS_DETECTED %token VALUES VAR VAREXO VAREXO_DET VARIABLE VAROBS VAREXOBS PREDETERMINED_VARIABLES VAR_EXPECTATION VAR_EXPECTATION_MODEL PLOT_SHOCK_DECOMPOSITION MODEL_LOCAL_VARIABLE %token WRITE_LATEX_DYNAMIC_MODEL WRITE_LATEX_STATIC_MODEL WRITE_LATEX_ORIGINAL_MODEL CROSSEQUATIONS COVARIANCE WRITE_LATEX_STEADY_STATE_MODEL -%token XLS_SHEET XLS_RANGE LMMCP OCCBIN BANDPASS_FILTER COLORMAP VAR_MODEL PAC_MODEL QOQ YOY AOA UNDIFF PAC_EXPECTATION +%token XLS_SHEET XLS_RANGE LMMCP OCCBIN BANDPASS_FILTER COLORMAP VAR_MODEL PAC_MODEL QOQ YOY AOA UNDIFF PAC_EXPECTATION TREND_COMPONENT_MODEL %left EQUAL_EQUAL EXCLAMATION_EQUAL %left LESS GREATER LESS_EQUAL GREATER_EQUAL %left PLUS MINUS %left TIMES DIVIDE %precedence UMINUS UPLUS %nonassoc POWER -%token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN ERF DIFF ADL +%token EXP LOG LN LOG10 SIN COS TAN ASIN ACOS ATAN ERF DIFF ADL AUXILIARY_MODEL_NAME %token SQRT NORMCDF NORMPDF STEADY_STATE EXPECTATION VAR_ESTIMATION /* GSA analysis */ %token DYNARE_SENSITIVITY MORRIS STAB REDFORM PPRIOR PRIOR_RANGE PPOST ILPTAU MORRIS_NLIV @@ -223,6 +223,7 @@ statement : parameters | data | var_model | pac_model + | trend_component_model | restrictions | prior | prior_eq @@ -374,6 +375,18 @@ var_model_options : o_var_name | o_var_eq_tags ; +trend_component_model : TREND_COMPONENT_MODEL '(' trend_component_model_options_list ')' ';' { driver.trend_component_model(); } + ; + +trend_component_model_options_list : trend_component_model_options_list COMMA trend_component_model_options + | trend_component_model_options + ; + +trend_component_model_options : o_trend_component_model_name + | o_trend_component_model_trends + | o_trend_component_model_eq_tags + ; + pac_model : PAC_MODEL '(' pac_model_options_list ')' ';' { driver.pac_model(); } ; pac_model_options_list : pac_model_options_list COMMA pac_model_options @@ -381,11 +394,9 @@ pac_model_options_list : pac_model_options_list COMMA pac_model_options ; pac_model_options : o_pac_name - | o_pac_var_name + | o_pac_aux_model_name | o_pac_discount | o_pac_growth - | UNDIFF '(' QUOTED_STRING COMMA INT_NUMBER ')' - { driver.pac_model_undiff($3, $5); } ; var_expectation_model : VAR_EXPECTATION_MODEL '(' var_expectation_model_options_list ')' ';' @@ -3084,7 +3095,7 @@ o_qz_criterium : QZ_CRITERIUM EQUAL non_negative_number { driver.option_num("qz_ o_qz_zero_threshold : QZ_ZERO_THRESHOLD EQUAL non_negative_number { driver.option_num("qz_zero_threshold", $3); }; o_file : FILE EQUAL filename { driver.option_str("file", $3); }; o_pac_name : MODEL_NAME EQUAL symbol { driver.option_str("pac.model_name", $3); }; -o_pac_var_name : VAR_MODEL_NAME EQUAL symbol { driver.option_str("pac.var_model_name", $3); }; +o_pac_aux_model_name : AUXILIARY_MODEL_NAME EQUAL symbol { driver.option_str("pac.aux_model_name", $3); }; o_pac_discount : DISCOUNT EQUAL symbol { driver.option_str("pac.discount", $3); }; o_pac_growth : GROWTH EQUAL symbol { driver.option_str("pac.growth", $3); }; o_var_name : MODEL_NAME EQUAL symbol { driver.option_str("var.model_name", $3); }; @@ -3101,6 +3112,9 @@ o_nobs : NOBS EQUAL vec_int | NOBS EQUAL vec_int_number { driver.option_vec_int("nobs", $3); } ; +o_trend_component_model_name : MODEL_NAME EQUAL symbol { driver.option_str("trend_component.name", $3); }; +o_trend_component_model_trends : TRENDS EQUAL vec_str { driver.option_vec_str("trend_component.trends", $3); } +o_trend_component_model_eq_tags : EQTAGS EQUAL vec_str { driver.option_vec_str("trend_component.eqtags", $3); } o_conditional_variance_decomposition : CONDITIONAL_VARIANCE_DECOMPOSITION EQUAL vec_int { driver.option_vec_int("conditional_variance_decomposition", $3); } | CONDITIONAL_VARIANCE_DECOMPOSITION EQUAL vec_int_number diff --git a/src/DynareFlex.ll b/src/DynareFlex.ll index 6d41a906..8f0ac71a 100644 --- a/src/DynareFlex.ll +++ b/src/DynareFlex.ll @@ -141,6 +141,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 <INITIAL>simul {BEGIN DYNARE_STATEMENT; return token::SIMUL;} <INITIAL>stoch_simul {BEGIN DYNARE_STATEMENT; return token::STOCH_SIMUL;} <INITIAL>var_model {BEGIN DYNARE_STATEMENT; return token::VAR_MODEL;} +<INITIAL>trend_component_model {BEGIN DYNARE_STATEMENT; return token::TREND_COMPONENT_MODEL;} <INITIAL>var_expectation_model {BEGIN DYNARE_STATEMENT; return token::VAR_EXPECTATION_MODEL;} <INITIAL>pac_model {BEGIN DYNARE_STATEMENT; return token::PAC_MODEL;} <INITIAL>dsample {BEGIN DYNARE_STATEMENT; return token::DSAMPLE;} @@ -348,6 +349,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 <DYNARE_STATEMENT>periods {return token::PERIODS;} <DYNARE_STATEMENT,DYNARE_BLOCK>model_name {return token::MODEL_NAME;} <DYNARE_STATEMENT>var_model_name {return token::VAR_MODEL_NAME;} +<DYNARE_STATEMENT>auxiliary_model_name {return token::AUXILIARY_MODEL_NAME;} <DYNARE_STATEMENT>endogenous_terminal_period {return token::ENDOGENOUS_TERMINAL_PERIOD;} <DYNARE_STATEMENT>sub_draws {return token::SUB_DRAWS;} <DYNARE_STATEMENT>minimal_solving_periods {return token::MINIMAL_SOLVING_PERIODS;} @@ -487,6 +489,7 @@ DATE -?[0-9]+([YyAa]|[Mm]([1-9]|1[0-2])|[Qq][1-4]|[Ww]([1-9]{1}|[1-4][0-9]|5[0-2 } <DYNARE_STATEMENT>write_equation_tags {return token::WRITE_EQUATION_TAGS;} <DYNARE_STATEMENT>eqtags {return token::EQTAGS;} +<DYNARE_STATEMENT>trends {return token::TRENDS;} <DYNARE_STATEMENT>indxap {return token::INDXAP;} <DYNARE_STATEMENT>apband {return token::APBAND;} <DYNARE_STATEMENT>indximf {return token::INDXIMF;} diff --git a/src/Makefile.am b/src/Makefile.am index 35da494f..4fea4104 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -52,7 +52,9 @@ dynare_m_SOURCES = \ SteadyStateModel.cc \ WarningConsolidation.hh \ WarningConsolidation.cc \ - ExtendedPreprocessorTypes.hh + ExtendedPreprocessorTypes.hh \ + SubModel.cc \ + SubModel.hh ACLOCAL_AMFLAGS = -I m4 diff --git a/src/ModFile.cc b/src/ModFile.cc index 815a7d99..6f377258 100644 --- a/src/ModFile.cc +++ b/src/ModFile.cc @@ -30,15 +30,25 @@ #include "ComputingTasks.hh" ModFile::ModFile(WarningConsolidation &warnings_arg) - : expressions_tree(symbol_table, num_constants, external_functions_table), - original_model(symbol_table, num_constants, external_functions_table), - dynamic_model(symbol_table, num_constants, external_functions_table), - trend_dynamic_model(symbol_table, num_constants, external_functions_table), - ramsey_FOC_equations_dynamic_model(symbol_table, num_constants, external_functions_table), - orig_ramsey_dynamic_model(symbol_table, num_constants, external_functions_table), - static_model(symbol_table, num_constants, external_functions_table), - steady_state_model(symbol_table, num_constants, external_functions_table, static_model), - diff_static_model(symbol_table, num_constants, external_functions_table), + : 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), 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) @@ -368,16 +378,10 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const set<string> eqtags; map<string, vector<string>> var_model_eq_tags; map<string, pair<SymbolList, int>> var_model_info_var_expectation; - for (auto & statement : statements) - { - auto *vms = dynamic_cast<VarModelStatement *>(statement); - if (vms != nullptr) - { - vms->getVarModelInfo(var_model_name, var_model_info_var_expectation, var_model_eq_tags); - for (auto & eqtag : var_model_eq_tags[var_model_name]) - eqtags.insert(eqtag); - } - } + + for (auto const &it : trend_component_model_table.getEqTags()) + for (auto &it1 : it.second) + eqtags.insert(it1); if (transform_unary_ops) dynamic_model.substituteUnaryOps(diff_static_model); @@ -389,64 +393,46 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const ExprNode::subst_table_t diff_subst_table; dynamic_model.substituteDiff(diff_static_model, diff_subst_table); + // Fill Trend Component Model Table + dynamic_model.fillTrendComponentModelTable(); + original_model.fillTrendComponentModelTableFromOrigModel(diff_static_model); + // Var Model - map<string, tuple<vector<int>, vector<expr_t>, vector<bool>, vector<int>, int, vector<bool>, vector<int>>> - var_model_info_pac_expectation; for (auto & statement : statements) { - int max_lag; - string var_model_name; - vector<string> eqtags; - vector<expr_t> lhs_expr_t; - vector<bool> nonstationary, diff; - vector<int> lhs, eqnumber, orig_diff_var; - auto *vms = dynamic_cast<VarModelStatement *>(statement); - if (vms != nullptr) - { - vector<set<pair<int, int>>> rhs; - vms->getVarModelInfo(var_model_name, var_model_info_var_expectation, var_model_eq_tags); - eqtags = var_model_eq_tags[var_model_name]; - dynamic_model.getVarModelVariablesFromEqTags(eqtags, - eqnumber, lhs, lhs_expr_t, rhs, nonstationary); - original_model.checkVarMinLag(eqnumber); - 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); - var_model_info_pac_expectation[var_model_name] = - { lhs, lhs_expr_t, diff, orig_diff_var, max_lag, nonstationary, eqnumber }; - } auto *pms = dynamic_cast<PacModelStatement *>(statement); if (pms != nullptr) { - int growth_symb_id; - string pac_model_name; - map<string, int> undiff; - tuple<string, string, string, int, map<string, int>> pac_model_info_pac_expectation; - pms->getPacModelInfoForPacExpectation(pac_model_info_pac_expectation); - tie ( pac_model_name, var_model_name, ignore, growth_symb_id, undiff ) = pac_model_info_pac_expectation; - eqtags = var_model_eq_tags[var_model_name]; - if (!eqtags.empty()) + vector<int> lhs; + vector<bool> nonstationary; + int growth_symb_id, max_lag; + string aux_model_name, pac_model_name; + tie ( pac_model_name, aux_model_name, growth_symb_id ) = + pms->getPacModelInfoForPacExpectation(); + if (trend_component_model_table.isExistingTrendComponentModelName(aux_model_name)) + { + max_lag = trend_component_model_table.getMaxLag(aux_model_name) + 1; + lhs = dynamic_model.getUndiffLHSForPac(aux_model_name, diff_subst_table); + nonstationary = trend_component_model_table.getNonstationary(aux_model_name); + } + else { - tie ( lhs, lhs_expr_t, diff, orig_diff_var, max_lag, nonstationary, eqnumber ) = - var_model_info_pac_expectation[var_model_name]; - if (!undiff.empty()) - { - dynamic_model.getUndiffLHSForPac(lhs, lhs_expr_t, diff, orig_diff_var, eqnumber, undiff, diff_subst_table); - max_lag++; - } - pms->fillUndiffedLHS(lhs); - dynamic_model.walkPacParameters(); - int pac_max_lag = original_model.getPacMaxLag(pac_model_name); - dynamic_model.fillPacExpectationVarInfo(pac_model_name, lhs, max_lag, pac_max_lag, nonstationary, growth_symb_id); - dynamic_model.substitutePacExpectation(); + // 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; + exit(EXIT_FAILURE); } + pms->fillUndiffedLHS(lhs); + dynamic_model.walkPacParameters(); + int pac_max_lag = original_model.getPacMaxLag(pac_model_name); + dynamic_model.fillPacExpectationVarInfo(pac_model_name, lhs, max_lag, + pac_max_lag, nonstationary, growth_symb_id); + dynamic_model.substitutePacExpectation(); } } - + /* if (!var_model_info_var_expectation.empty()) dynamic_model.addEquationsForVar(var_model_info_var_expectation); - + */ if (symbol_table.predeterminedNbr() > 0) dynamic_model.transformPredeterminedVariables(); @@ -542,9 +528,11 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const 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{original_model.getVarMaxLag(diff_static_model, eqnumber)}; + */ + 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 */ @@ -596,13 +584,15 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const 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); + //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; @@ -610,13 +600,15 @@ ModFile::transformPass(bool nostrict, bool stochastic, bool compute_xrefs, const vector<string> eqtags = var_model_eq_tags[var_model_name]; dynamic_model.getVarModelVariablesFromEqTags(eqtags, eqnumber, lhs, lhs_expr_t, rhs, nonstationary); - int max_lag = original_model.getVarMaxLag(diff_static_model, eqnumber); - original_model.getVarLhsDiffAndInfo(eqnumber, diff, orig_diff_var); + + 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); @@ -911,6 +903,8 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool clear_glo symbol_table.writeOutput(mOutputFile); + trend_component_model_table.writeOutput(mOutputFile); + // Initialize M_.Sigma_e, M_.Correlation_matrix, M_.H, and M_.Correlation_matrix_ME mOutputFile << "M_.Sigma_e = zeros(" << symbol_table.exo_nbr() << ", " << symbol_table.exo_nbr() << ");" << endl diff --git a/src/ModFile.hh b/src/ModFile.hh index 1ecac964..2e33b74e 100644 --- a/src/ModFile.hh +++ b/src/ModFile.hh @@ -38,6 +38,7 @@ using namespace std; #include "ConfigFile.hh" #include "WarningConsolidation.hh" #include "ExtendedPreprocessorTypes.hh" +#include "SubModel.hh" //! The abstract representation of a "mod" file class ModFile @@ -51,6 +52,8 @@ public: ExternalFunctionsTable external_functions_table; //! Numerical constants table NumericalConstants num_constants; + //! Trend Component Model Table used for storing info about trend component models + TrendComponentModelTable trend_component_model_table; //! Expressions outside model block DataTree expressions_tree; //! Original model, as declared in the "model" block, that won't be modified by the preprocessor @@ -69,6 +72,7 @@ public: SteadyStateModel steady_state_model; //! Static model used for mapping arguments of diff operator StaticModel diff_static_model; + //! Option linear bool linear; diff --git a/src/ModelTree.cc b/src/ModelTree.cc index 31343942..401ad86b 100644 --- a/src/ModelTree.cc +++ b/src/ModelTree.cc @@ -1003,8 +1003,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) : - DataTree(symbol_table_arg, num_constants_arg, external_functions_table_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), cutoff(1e-15), mfs(0) diff --git a/src/ModelTree.hh b/src/ModelTree.hh index bee2defd..84772d5b 100644 --- a/src/ModelTree.hh +++ b/src/ModelTree.hh @@ -321,7 +321,10 @@ protected: //! Initialize equation_reordered & variable_reordered void initializeVariablesAndEquations(); public: - ModelTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg); + ModelTree(SymbolTable &symbol_table_arg, + NumericalConstants &num_constants_arg, + ExternalFunctionsTable &external_functions_table_arg, + TrendComponentModelTable &trend_component_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 dc97c67c..5265aa82 100644 --- a/src/ParsingDriver.cc +++ b/src/ParsingDriver.cc @@ -348,7 +348,8 @@ ParsingDriver::declare_or_change_type(SymbolType new_type, const string &name) // change in equations in ModelTree auto dm = make_unique<DynamicModel>(mod_file->symbol_table, mod_file->num_constants, - mod_file->external_functions_table); + mod_file->external_functions_table, + mod_file->trend_component_model_table); mod_file->dynamic_model.updateAfterVariableChange(*dm); // remove error messages @@ -1418,6 +1419,30 @@ ParsingDriver::stoch_simul() options_list.clear(); } +void +ParsingDriver::trend_component_model() +{ + OptionsList::string_options_t::const_iterator it = + options_list.string_options.find("trend_component.name"); + if (it == options_list.string_options.end()) + error("You must pass the model_name option to the trend_component_model statement."); + auto name = it->second; + + OptionsList::vec_str_options_t::const_iterator it1 = + options_list.vector_str_options.find("trend_component.eqtags"); + if (it1 == options_list.vector_str_options.end()) + error("You must pass the eqtags option to the trend_component_model statement."); + auto eqtags = it1->second; + + it1 = options_list.vector_str_options.find("trend_component.trends"); + if (it1 == options_list.vector_str_options.end()) + error("You must pass the trends option to the trend_component_model statement."); + auto trends = it1->second; + + mod_file->trend_component_model_table.addTrendComponentModel(name, eqtags, trends); + options_list.clear(); +} + void ParsingDriver::var_model() { @@ -2045,7 +2070,10 @@ ParsingDriver::run_model_comparison() void ParsingDriver::begin_planner_objective() { - planner_objective_statement = new PlannerObjectiveStatement(mod_file->symbol_table, mod_file->num_constants, mod_file->external_functions_table); + planner_objective_statement = new PlannerObjectiveStatement(mod_file->symbol_table, + mod_file->num_constants, + mod_file->external_functions_table, + mod_file->trend_component_model_table); set_current_data_tree(&planner_objective_statement->getPlannerObjective()); } @@ -2527,10 +2555,10 @@ ParsingDriver::pac_model() error("You must pass the model_name option to the pac_model statement."); auto name = it->second; - it = options_list.string_options.find("pac.var_model_name"); + it = options_list.string_options.find("pac.aux_model_name"); if (it == options_list.string_options.end()) - error("You must pass the var_model_name option to the pac_model statement."); - auto var_name = it->second; + error("You must pass the auxiliary_model_name option to the pac_model statement."); + auto aux_model_name = it->second; it = options_list.string_options.find("pac.discount"); if (it == options_list.string_options.end()) @@ -2542,17 +2570,11 @@ ParsingDriver::pac_model() if (it != options_list.string_options.end()) growth = it->second; - mod_file->addStatement(new PacModelStatement(name, var_name, discount, growth, pac_undiff, mod_file->symbol_table)); + mod_file->addStatement(new PacModelStatement(name, aux_model_name, discount, growth, + mod_file->symbol_table)); symbol_list.clear(); options_list.clear(); - pac_undiff.clear(); -} - -void -ParsingDriver::pac_model_undiff(string eqtag, const string &order) -{ - pac_undiff[move(eqtag)] = stoi(order); } expr_t diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh index e055199f..b53af1ab 100644 --- a/src/ParsingDriver.hh +++ b/src/ParsingDriver.hh @@ -242,8 +242,6 @@ private: SymbolList graph_formats; //! Temporary storage for equation tags vector<pair<string, string>> eq_tags; - //! Temporary storage for pac statement undiff option - map<string, int> pac_undiff; //! Map Var name to variables map<string, vector<string>> var_map; @@ -463,6 +461,8 @@ public: void rplot(); //! Writes a stock_simul command void stoch_simul(); + //! Writes a trend component command + void trend_component_model(); //! Writes a var (vector autoregression) command void var_model(); //! Writes a simul command @@ -697,8 +697,6 @@ public: expr_t add_pac_expectation(const string &var_model_name); //! Creates pac_model statement void pac_model(); - //! Add undiff option for pac_model statement - void pac_model_undiff(string eqtag, const string &order); //! Writes token "diff(arg1)" to model tree expr_t add_diff(expr_t arg1); //! Writes token "adl(arg1, lag)" to model tree diff --git a/src/StaticModel.cc b/src/StaticModel.cc index 60ed9fc1..f9834c2f 100644 --- a/src/StaticModel.cc +++ b/src/StaticModel.cc @@ -31,8 +31,10 @@ StaticModel::StaticModel(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), global_temporary_terms(true) { } diff --git a/src/StaticModel.hh b/src/StaticModel.hh index 4fad5171..5374739d 100644 --- a/src/StaticModel.hh +++ b/src/StaticModel.hh @@ -160,7 +160,10 @@ protected: void writeStaticModel(ostream &DynamicOutput, bool use_dll, bool julia) const; void writeStaticModel(const string &dynamic_basename, bool use_dll, bool julia) const; public: - StaticModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants, ExternalFunctionsTable &external_functions_table_arg); + StaticModel(SymbolTable &symbol_table_arg, + NumericalConstants &num_constants, + ExternalFunctionsTable &external_functions_table_arg, + TrendComponentModelTable &trend_component_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 d3bee83b..282d8e1b 100644 --- a/src/SteadyStateModel.cc +++ b/src/SteadyStateModel.cc @@ -22,8 +22,14 @@ #include "SteadyStateModel.hh" -SteadyStateModel::SteadyStateModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg, const StaticModel &static_model_arg) : - DataTree(symbol_table_arg, num_constants_arg, external_functions_table_arg), static_model(static_model_arg) +SteadyStateModel::SteadyStateModel(SymbolTable &symbol_table_arg, + NumericalConstants &num_constants_arg, + ExternalFunctionsTable &external_functions_table_arg, + TrendComponentModelTable &trend_component_model_table_arg, + const StaticModel &static_model_arg) : + DataTree(symbol_table_arg, num_constants_arg, + external_functions_table_arg, trend_component_model_table_arg), + static_model(static_model_arg) { } diff --git a/src/SteadyStateModel.hh b/src/SteadyStateModel.hh index 04166dd8..d3b4e2db 100644 --- a/src/SteadyStateModel.hh +++ b/src/SteadyStateModel.hh @@ -35,7 +35,11 @@ private: const StaticModel &static_model; public: - SteadyStateModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg, ExternalFunctionsTable &external_functions_table_arg, const StaticModel &static_model_arg); + SteadyStateModel(SymbolTable &symbol_table_arg, + NumericalConstants &num_constants_arg, + ExternalFunctionsTable &external_functions_table_arg, + TrendComponentModelTable &trend_component_model_table_arg, + const StaticModel &static_model_arg); //! Add an expression of the form "var = expr;" void addDefinition(int symb_id, expr_t expr); //! Add an expression of the form "[ var1, var2, ... ] = expr;" diff --git a/src/SubModel.cc b/src/SubModel.cc new file mode 100644 index 00000000..2d69b4de --- /dev/null +++ b/src/SubModel.cc @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2018 Dynare Team + * + * This file is part of Dynare. + * + * Dynare is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Dynare is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Dynare. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <algorithm> + +#include "SubModel.hh" + +TrendComponentModelTable::TrendComponentModelTable(SymbolTable &symbol_table_arg) : + symbol_table(symbol_table_arg) +{ +} + +void +TrendComponentModelTable::addTrendComponentModel(string name_arg, + vector<string> eqtags_arg, + vector<string> trend_eqtags_arg) +{ + if (isExistingTrendComponentModelName(name_arg)) + { + cerr << "Error: a trend component model already exists with the name " << name_arg << endl; + exit(EXIT_FAILURE); + } + eqtags[name_arg] = move(eqtags_arg); + trend_eqtags[name_arg] = move(trend_eqtags_arg); + names.insert(move(name_arg)); +} + +void +TrendComponentModelTable::setEqNums(map<string, vector<int>> eqnums_arg) +{ + eqnums = move(eqnums_arg); + setUndiffEqnums(); +} + +void +TrendComponentModelTable::setTrendEqNums(map<string, vector<int>> trend_eqnums_arg) +{ + trend_eqnums = move(trend_eqnums_arg); + setUndiffEqnums(); +} + +void +TrendComponentModelTable::setUndiffEqnums() +{ + if (!nontrend_eqnums.empty() || eqnums.empty() || trend_eqnums.empty()) + return; + + for (const auto &it : eqnums) + { + vector<int> nontrend_vec; + for (auto eq : it.second) + if (find(trend_eqnums[it.first].begin(), trend_eqnums[it.first].end(), eq) + == trend_eqnums[it.first].end()) + nontrend_vec.push_back(eq); + nontrend_eqnums[it.first] = nontrend_vec; + } +} + +void +TrendComponentModelTable::setNonstationary(map<string, vector<bool>> nonstationary_arg) +{ + nonstationary = move(nonstationary_arg); +} + +void +TrendComponentModelTable::setLhs(map<string, vector<int>> lhs_arg) +{ + lhs = move(lhs_arg); +} + +void +TrendComponentModelTable::setRhs(map<string, vector<set<pair<int, int>>>> rhs_arg) +{ + rhs = move(rhs_arg); +} + +void +TrendComponentModelTable::setLhsExprT(map<string, vector<expr_t>> lhs_expr_t_arg) +{ + lhs_expr_t = move(lhs_expr_t_arg); +} + +void +TrendComponentModelTable::setMaxLags(map<string, vector<int>> max_lags_arg) +{ + max_lags = move(max_lags_arg); +} + +void +TrendComponentModelTable::setDiff(map<string, vector<bool>> diff_arg) +{ + diff = move(diff_arg); +} + +void +TrendComponentModelTable::setOrigDiffVar(map<string, vector<int>> orig_diff_var_arg) +{ + orig_diff_var = move(orig_diff_var_arg); +} + +map<string, vector<string>> +TrendComponentModelTable::getEqTags() const +{ + return eqtags; +} + +vector<string> +TrendComponentModelTable::getEqTags(const string &name_arg) const +{ + checkModelName(name_arg); + return eqtags.find(name_arg)->second; +} + +void +TrendComponentModelTable::checkModelName(const string &name_arg) const +{ + if (!isExistingTrendComponentModelName(name_arg)) + { + cerr << name_arg + << " is not a recognized equation tag of a trend component model equation" << endl; + exit(EXIT_FAILURE); + } +} + +vector<bool> +TrendComponentModelTable::getNonstationary(const string &name_arg) const +{ + checkModelName(name_arg); + return nonstationary.find(name_arg)->second; +} + +vector<int> +TrendComponentModelTable::getLhs(const string &name_arg) const +{ + checkModelName(name_arg); + return lhs.find(name_arg)->second; +} + +vector<expr_t> +TrendComponentModelTable::getLhsExprT(const string &name_arg) const +{ + checkModelName(name_arg); + return lhs_expr_t.find(name_arg)->second; +} + +map<string, vector<string>> +TrendComponentModelTable::getTrendEqTags() const +{ + return trend_eqtags; +} + +map<string, vector<int>> +TrendComponentModelTable::getEqNums() const +{ + return eqnums; +} + +vector<int> +TrendComponentModelTable::getNonTrendEqNums(const string &name_arg) const +{ + checkModelName(name_arg); + return nontrend_eqnums.find(name_arg)->second; +} + +vector<int> +TrendComponentModelTable::getEqNums(const string &name_arg) const +{ + checkModelName(name_arg); + return eqnums.find(name_arg)->second; +} + +vector<int> +TrendComponentModelTable::getMaxLags(const string &name_arg) const +{ + checkModelName(name_arg); + return max_lags.find(name_arg)->second; +} + +int +TrendComponentModelTable::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<bool> +TrendComponentModelTable::getDiff(const string &name_arg) const +{ + checkModelName(name_arg); + return diff.find(name_arg)->second; +} + +vector<int> +TrendComponentModelTable::getOrigDiffVar(const string &name_arg) const +{ + checkModelName(name_arg); + return orig_diff_var.find(name_arg)->second; +} + +void +TrendComponentModelTable::writeOutput(ostream &output) const +{ + for (const auto &name : names) + { + output << "M_.trend_component." << name << ".model_name = '" << name << "'" << endl + << "M_.trend_component." << name << ".eqtags = {"; + for (const auto &it : eqtags.at(name)) + output << "'" << it << "'; "; + output << "};" << endl + << "M_.trend_component." << name << ".eqn = ["; + for (auto it : eqnums.at(name)) + output << it + 1 << " "; + output << "];" << endl + << "M_.trend_component." << name << ".trend_eqn = ["; + for (auto it : trend_eqnums.at(name)) + output << it + 1 << " "; + output << "];" << endl + << "M_.trend_component." << name << ".trends = ["; + for (auto it : eqnums.at(name)) + if (find(trend_eqnums.at(name).begin(), trend_eqnums.at(name).end(), it) + == trend_eqnums.at(name).end()) + output << "false "; + else + output << "true "; + output << "];" << endl + << "M_.trend_component." << name << ".lhs = ["; + for (auto it : lhs.at(name)) + output << symbol_table.getTypeSpecificID(it) + 1 << " "; + output << "];" << endl + << "M_.trend_component." << name << ".max_lag = ["; + for (auto it : max_lags.at(name)) + output << it << " "; + output << "];" << endl + << "M_.trend_component." << name << ".diff = ["; + for (const auto &it : diff.at(name)) + output << (it ? "true" : "false") << " "; + output << "];" << endl + << "M_.trend_component." << 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_.trend_component." << name << ".rhs.vars_at_eq{" << i << "}.var = ["; + for (const auto &it1 : it) + output << symbol_table.getTypeSpecificID(it1.first) + 1 << " "; + output << "];" << endl + << "M_.trend_component." << name << ".rhs.vars_at_eq{" << i << "}.lag = ["; + for (const auto &it1 : it) + output << it1.second << " "; + output << "];" << endl; + + i++; + } + } +} + +void +TrendComponentModelTable::writeJsonOutput(ostream &output) const +{ + for (const auto &name : names) + { + if (name != *(names.begin())) + output << ", "; + output << "{\"statementName\": \"trend_component_model\"," + << "\"model_name\": \"" << name << "\"}"; + } +} diff --git a/src/SubModel.hh b/src/SubModel.hh new file mode 100644 index 00000000..e7fa2759 --- /dev/null +++ b/src/SubModel.hh @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2018 Dynare Team + * + * This file is part of Dynare. + * + * Dynare is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Dynare is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Dynare. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef _SUBMODEL_HH +#define _SUBMODEL_HH + +#include <set> +#include <map> +#include <vector> +#include <iostream> + +#include "ExprNode.hh" +#include "SymbolTable.hh" + +using namespace std; + +//! A table with all Trend Component Models in the .mod file +/*! + The unique name of the trend component model is the identifier +*/ +class TrendComponentModelTable +{ +private: + SymbolTable &symbol_table; + set<string> names; + map<string, vector<string>> eqtags, trend_eqtags; + map<string, vector<int>> eqnums, trend_eqnums, nontrend_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: + TrendComponentModelTable(SymbolTable &symbol_table_arg); + + //! Add a trend component model + void addTrendComponentModel(string name, vector<string> eqtags, vector<string> trend_eqtags); + + inline bool isExistingTrendComponentModelName(const string &name_arg) const; + + map<string, vector<string>> getEqTags() const; + vector<string> getEqTags(const string &name_arg) const; + map<string, vector<string>> getTrendEqTags() 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<expr_t> getLhsExprT(const string &name_arg) const; + vector<bool> getDiff(const string &name_arg) const; + vector<int> getOrigDiffVar(const string &name_arg) const; + vector<int> getNonTrendEqNums(const string &name_arg) const; + vector<bool> getNonstationary(const string &name_arg) const; + + void setEqNums(map<string, vector<int>> eqnums_arg); + void setTrendEqNums(map<string, vector<int>> trend_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 setMaxLags(map<string, vector<int>> max_lags_arg); + void setDiff(map<string, vector<bool>> diff_arg); + void setOrigDiffVar(map<string, vector<int>> orig_diff_var_arg); + void setNonstationary(map<string, vector<bool>> nonstationary_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; + void setUndiffEqnums(); +}; + +inline bool +TrendComponentModelTable::isExistingTrendComponentModelName(const string &name_arg) const +{ + return names.find(name_arg) == names.end() ? false : true; +} + +#endif -- GitLab