From 5f013756f23fe89ec946fcff2cfdad7627693e12 Mon Sep 17 00:00:00 2001 From: Houtan Bastani Date: Wed, 27 Feb 2019 23:12:05 +0100 Subject: [PATCH] find additive parts to pac equation --- src/DynamicModel.cc | 72 ++++++++++++--- src/DynamicModel.hh | 2 +- src/ExprNode.cc | 210 ++++++++++++++++++++++---------------------- src/ExprNode.hh | 39 ++------ 4 files changed, 172 insertions(+), 151 deletions(-) diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc index 7bc4574e..28ab0c6c 100644 --- a/src/DynamicModel.cc +++ b/src/DynamicModel.cc @@ -3663,8 +3663,8 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block_de int optim_share_index; set>> ar_params_and_vars; pair, vector>> ec_params_and_vars; - vector> non_optim_vars_params_and_constants; - tie(lhs_pac_var, optim_share_index, ar_params_and_vars, ec_params_and_vars, non_optim_vars_params_and_constants) = pit.second; + vector> non_optim_vars_params_and_constants, additive_vars_params_and_constants; + tie(lhs_pac_var, optim_share_index, ar_params_and_vars, ec_params_and_vars, non_optim_vars_params_and_constants, additive_vars_params_and_constants) = pit.second; string substruct = pit.first.first + ".equations." + pit.first.second + "."; output << modstruct << "pac." << substruct << "lhs_var = " @@ -3733,6 +3733,43 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block_de output << get<3>(it) << " "; output << "];" << endl; } + if (!additive_vars_params_and_constants.empty()) + { + output << modstruct << "pac." << substruct << "additive.params = ["; + for (auto & it : additive_vars_params_and_constants) + if (get<2>(it) >= 0) + output << symbol_table.getTypeSpecificID(get<2>(it)) + 1 << " "; + else + output << "NaN "; + output << "];" << endl + << modstruct << "pac." << substruct << "additive.vars = ["; + for (auto & it : additive_vars_params_and_constants) + output << symbol_table.getTypeSpecificID(get<0>(it)) + 1 << " "; + output << "];" << endl + << modstruct << "pac." << substruct << "additive.isendo = ["; + for (auto & it : additive_vars_params_and_constants) + switch (symbol_table.getType(get<0>(it))) + { + case SymbolType::endogenous: + output << "true "; + break; + case SymbolType::exogenous: + output << "false "; + break; + default: + cerr << "expecting endogenous or exogenous" << endl; + exit(EXIT_FAILURE); + } + output << "];" << endl + << modstruct << "pac." << substruct << "additive.lags = ["; + for (auto & it : additive_vars_params_and_constants) + output << get<1>(it) << " "; + output << "];" << endl + << modstruct << "pac." << substruct << "additive.scaling_factor = ["; + for (auto & it : additive_vars_params_and_constants) + output << get<3>(it) << " "; + output << "];" << endl; + } // Create empty h0 and h1 substructures that will be overwritten later if not empty output << modstruct << "pac." << substruct << "h0_param_indices = [];" << endl << modstruct << "pac." << substruct << "h1_param_indices = [];" << endl; @@ -4384,18 +4421,17 @@ DynamicModel::walkPacParameters(const string &name, map, pa pair lhs (-1, -1); pair, vector>> ec_params_and_vars; set>> ar_params_and_vars; - vector> non_optim_vars_params_and_constants; + vector> non_optim_vars_params_and_constants, additive_vars_params_and_constants; if (equation->containsPacExpectation()) { - int optim_share_index = -1; - set optim_share; - expr_t optim_part = nullptr; - expr_t non_optim_part = nullptr; + int optim_share_index; + expr_t optim_part, non_optim_part, additive_part; set> lhss; equation->arg1->collectDynamicVariables(SymbolType::endogenous, lhss); lhs = *(lhss.begin()); - int lhs_orig_symb_id = lhs.first; + int lhs_symb_id = lhs.first; + int lhs_orig_symb_id = lhs_symb_id; if (symbol_table.isAuxiliaryVariable(lhs_orig_symb_id)) try { @@ -4405,22 +4441,29 @@ DynamicModel::walkPacParameters(const string &name, map, pa { } - equation->arg2->getPacOptimizingShareAndExprNodes(optim_share, - optim_part, - non_optim_part); + auto arg2 = dynamic_cast(equation->arg2); + if (arg2 == nullptr) + { + cerr << "Pac equation in incorrect format" << endl; + exit(EXIT_FAILURE); + } + tie(optim_share_index, optim_part, non_optim_part, additive_part) = + arg2->getPacOptimizingShareAndExprNodes(lhs_symb_id, lhs_orig_symb_id); + if (optim_part == nullptr) equation->arg2->getPacOptimizingPart(lhs_orig_symb_id, ec_params_and_vars, ar_params_and_vars); else { - optim_share_index = *(optim_share.begin()); optim_part->getPacOptimizingPart(lhs_orig_symb_id, ec_params_and_vars, ar_params_and_vars); try { non_optim_vars_params_and_constants = non_optim_part->matchLinearCombinationOfVariables(); + if (additive_part != nullptr) + additive_vars_params_and_constants = additive_part->matchLinearCombinationOfVariables(); } catch (ExprNode::MatchFailureException &e) { - cerr << "Error in parsing non-optimizing agents part of PAC equation: " + cerr << "Error in parsing non-optimizing agents or additive part of PAC equation: " << e.message << endl; exit(EXIT_FAILURE); } @@ -4452,7 +4495,8 @@ DynamicModel::walkPacParameters(const string &name, map, pa string eq = "eq" + to_string(i++); pac_equation_info[{name, eq}] = {lhs, optim_share_index, ar_params_and_vars, ec_params_and_vars, - non_optim_vars_params_and_constants}; + non_optim_vars_params_and_constants, + additive_vars_params_and_constants}; eqtag_and_lag[{name, eqtag}] = {eq, 0}; } } diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh index 1293e31d..99759db4 100644 --- a/src/DynamicModel.hh +++ b/src/DynamicModel.hh @@ -487,7 +487,7 @@ public: //! (pac_model_name, standardized_eqtag) -> //! (lhs, optim_share_index, ar_params_and_vars, ec_params_and_vars, non_optim_vars_params_and_constants) map, - tuple, int, set>>, pair, vector>>, vector>>> pac_equation_info; + tuple, int, set>>, pair, vector>>, vector>, vector>>> pac_equation_info; //! Table to undiff LHS variables for pac vector z vector getUndiffLHSForPac(const string &aux_model_name, diff --git a/src/ExprNode.cc b/src/ExprNode.cc index c5ccc66e..614a8080 100644 --- a/src/ExprNode.cc +++ b/src/ExprNode.cc @@ -680,13 +680,6 @@ NumConstNode::getPacOptimizingPart(int lhs_orig_symb_id, pair &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const -{ -} - bool NumConstNode::isVarModelReferenced(const string &model_info_name) const { @@ -1981,13 +1974,6 @@ VariableNode::getPacOptimizingPart(int lhs_orig_symb_id, pair &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const -{ -} - bool VariableNode::isVarModelReferenced(const string &model_info_name) const { @@ -3800,14 +3786,6 @@ UnaryOpNode::getPacOptimizingPart(int lhs_orig_symb_id, pairgetPacOptimizingPart(lhs_orig_symb_id, ec_params_and_vars, ar_params_and_vars); } -void -UnaryOpNode::getPacOptimizingShareAndExprNodes(set &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const -{ - arg->getPacOptimizingShareAndExprNodes(optim_share, optim_part, non_optim_part); -} - bool UnaryOpNode::isVarModelReferenced(const string &model_info_name) const { @@ -5678,67 +5656,122 @@ BinaryOpNode::isParamTimesEndogExpr() const return false; } -void -BinaryOpNode::getPacOptimizingShareAndExprNodes(set &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const +bool +BinaryOpNode::getPacNonOptimizingPartHelper(BinaryOpNode *bopn, int optim_share) const { - if (optim_part != nullptr && non_optim_part != nullptr) - return; + set params; + bopn->collectVariables(SymbolType::parameter, params); + if (params.size() == 1 && *(params.begin()) == optim_share) + return true; + return false; +} - if (op_code == BinaryOpcode::times) +expr_t +BinaryOpNode::getPacNonOptimizingPart(BinaryOpNode *bopn, int optim_share) const +{ + auto a1 = dynamic_cast(bopn->arg1); + auto a2 = dynamic_cast(bopn->arg2); + if (a1 == nullptr && a2 == nullptr) + return nullptr; + + if (a1 != nullptr) + if (getPacNonOptimizingPartHelper(a1, optim_share)) + return bopn->arg2; + + if (a2 != nullptr) + if (getPacNonOptimizingPartHelper(a2, optim_share)) + return bopn->arg1; + + return nullptr; +} + +pair +BinaryOpNode::getPacOptimizingShareAndExprNodesHelper(BinaryOpNode *bopn, int lhs_symb_id, int lhs_orig_symb_id) const +{ + int optim_param_symb_id = -1; + expr_t optim_part = nullptr; + set> endogs; + bopn->collectDynamicVariables(SymbolType::endogenous, endogs); + int target_symb_id = getPacTargetSymbIdHelper(lhs_symb_id, lhs_orig_symb_id, endogs); + if (target_symb_id >= 0) { - auto *test_arg1 = dynamic_cast(arg1); - auto *test_arg2 = dynamic_cast(arg2); - - set params1, params2; - arg1->collectVariables(SymbolType::parameter, params1); - arg2->collectVariables(SymbolType::parameter, params2); - - if (dynamic_cast(arg1) != nullptr - || dynamic_cast(arg2) != nullptr) + set params; + if (bopn->arg1->isParamTimesEndogExpr() && !bopn->arg2->isParamTimesEndogExpr()) { - cerr << "Error: Please do not use hard-coded parameter values in the PAC equation" - << endl; - exit(EXIT_FAILURE); + optim_part = bopn->arg1; + bopn->arg2->collectVariables(SymbolType::parameter, params); + optim_param_symb_id = *(params.begin()); } + else if (bopn->arg2->isParamTimesEndogExpr() && !bopn->arg1->isParamTimesEndogExpr()) + { + optim_part = bopn->arg2; + bopn->arg1->collectVariables(SymbolType::parameter, params); + optim_param_symb_id = *(params.begin()); + } + } + return {optim_param_symb_id, optim_part}; +} - if (optim_part == nullptr) - if (test_arg1 != nullptr || test_arg2 != nullptr) - if (params1.size() == 1 || params2.size() == 1) - if (arg2->isParamTimesEndogExpr()) - { - // arg1 is the share of optimizing agents - optim_part = arg2; - optim_share.emplace(*(params1.begin())); - } - else if (arg1->isParamTimesEndogExpr()) - { - optim_part = arg1; - optim_share.emplace(*(params2.begin())); - } +tuple +BinaryOpNode::getPacOptimizingShareAndExprNodes(int lhs_symb_id, int lhs_orig_symb_id) const +{ + vector> terms; + decomposeAdditiveTerms(terms, 1); + for (auto & it : terms) + if (dynamic_cast(it.first) != nullptr) + // if the pac_expectation operator is additive in the expression + // there are no optimizing shares + return {-1, nullptr, nullptr, nullptr}; - if (non_optim_part == nullptr) - if (params1.size() == 1 && - arg1 == datatree.AddMinus(datatree.One, datatree.AddVariable(*(params1.begin())))) - // arg1 is the non-optimizing share - non_optim_part = arg2; - else if (params2.size() == 1 && - arg2 == datatree.AddMinus(datatree.One, datatree.AddVariable(*(params2.begin())))) - non_optim_part = arg1; - } - else if (op_code == BinaryOpcode::plus) + int optim_share; + expr_t optim_part, non_optim_part, additive_part; + optim_part = non_optim_part = additive_part = nullptr; + + for (auto it = terms.begin(); it != terms.end(); it++) { - arg1->getPacOptimizingShareAndExprNodes(optim_share, optim_part, non_optim_part); - arg2->getPacOptimizingShareAndExprNodes(optim_share, optim_part, non_optim_part); + auto bopn = dynamic_cast(it->first); + if (bopn != nullptr) + { + tie(optim_share, optim_part) = + getPacOptimizingShareAndExprNodesHelper(bopn, lhs_symb_id, lhs_orig_symb_id); + if (optim_share >= 0 && optim_part != nullptr) + { + terms.erase(it); + break; + } + } } - else if (op_code == BinaryOpcode::divide) - return; - else + + if (optim_part == nullptr) + return {-1, nullptr, nullptr, nullptr}; + + for (auto it = terms.begin(); it != terms.end(); it++) { - cerr << "Notation error in PAC equation" << endl; - exit(EXIT_FAILURE); + auto bopn = dynamic_cast(it->first); + if (bopn != nullptr) + { + non_optim_part = getPacNonOptimizingPart(bopn, optim_share); + if (non_optim_part != nullptr) + { + terms.erase(it); + break; + } + } } + + if (non_optim_part == nullptr) + return {-1, nullptr, nullptr, nullptr}; + + if (non_optim_part != nullptr) + { + additive_part = datatree.Zero; + for (auto it : terms) + additive_part = datatree.AddPlus(additive_part, it.first); + if (additive_part == datatree.Zero) + additive_part = nullptr; + } + + return {optim_share, optim_part, non_optim_part, additive_part}; } void @@ -6904,16 +6937,6 @@ TrinaryOpNode::getPacOptimizingPart(int lhs_orig_symb_id, pairgetPacOptimizingPart(lhs_orig_symb_id, ec_params_and_vars, ar_params_and_vars); } -void -TrinaryOpNode::getPacOptimizingShareAndExprNodes(set &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const -{ - arg1->getPacOptimizingShareAndExprNodes(optim_share, optim_part, non_optim_part); - arg2->getPacOptimizingShareAndExprNodes(optim_share, optim_part, non_optim_part); - arg3->getPacOptimizingShareAndExprNodes(optim_share, optim_part, non_optim_part); -} - bool TrinaryOpNode::isVarModelReferenced(const string &model_info_name) const { @@ -7470,15 +7493,6 @@ AbstractExternalFunctionNode::getPacOptimizingPart(int lhs_orig_symb_id, pairgetPacOptimizingPart(lhs_orig_symb_id, ec_params_and_vars, ar_params_and_vars); } -void -AbstractExternalFunctionNode::getPacOptimizingShareAndExprNodes(set &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const -{ - for (auto argument : arguments) - argument->getPacOptimizingShareAndExprNodes(optim_share, optim_part, non_optim_part); -} - bool AbstractExternalFunctionNode::isVarModelReferenced(const string &model_info_name) const { @@ -9110,13 +9124,6 @@ VarExpectationNode::getPacOptimizingPart(int lhs_orig_symb_id, pair &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const -{ -} - expr_t VarExpectationNode::substituteStaticAuxiliaryVariable() const { @@ -9595,13 +9602,6 @@ PacExpectationNode::getPacOptimizingPart(int lhs_orig_symb_id, pair &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const -{ -} - expr_t PacExpectationNode::substitutePacExpectation(const string & name, expr_t subexpr) { diff --git a/src/ExprNode.hh b/src/ExprNode.hh index 15aab148..fc45c1f0 100644 --- a/src/ExprNode.hh +++ b/src/ExprNode.hh @@ -597,13 +597,6 @@ class ExprNode //! param * (endog op endog op ...) + param * (endog op endog op ...) + ... virtual bool isParamTimesEndogExpr() const = 0; - //! Finds the share of optimizing agents in the PAC equation, - //! the expr node associated with it, - //! and the expr node associated with the non-optimizing part - virtual void getPacOptimizingShareAndExprNodes(set &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const = 0; - //! Fills the AR matrix structure virtual void fillAutoregressiveRow(int eqn, const vector &lhs, map, expr_t> &AR) const = 0; @@ -736,9 +729,6 @@ public: bool containsPacExpectation(const string &pac_model_name = "") const override; void getPacOptimizingPart(int lhs_orig_symb_id, pair, vector>> &ec_params_and_vars, set>> ¶ms_and_vars) const override; - void getPacOptimizingShareAndExprNodes(set &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const override; bool isParamTimesEndogExpr() const override; bool isVarModelReferenced(const string &model_info_name) const override; void getEndosAndMaxLags(map &model_endos_and_lags) const override; @@ -826,9 +816,6 @@ public: bool containsPacExpectation(const string &pac_model_name = "") const override; void getPacOptimizingPart(int lhs_orig_symb_id, pair, vector>> &ec_params_and_vars, set>> ¶ms_and_vars) const override; - void getPacOptimizingShareAndExprNodes(set &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const override; bool isParamTimesEndogExpr() const override; bool isVarModelReferenced(const string &model_info_name) const override; void getEndosAndMaxLags(map &model_endos_and_lags) const override; @@ -944,9 +931,6 @@ public: bool containsPacExpectation(const string &pac_model_name = "") const override; void getPacOptimizingPart(int lhs_orig_symb_id, pair, vector>> &ec_params_and_vars, set>> ¶ms_and_vars) const override; - void getPacOptimizingShareAndExprNodes(set &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const override; bool isParamTimesEndogExpr() const override; bool isVarModelReferenced(const string &model_info_name) const override; void getEndosAndMaxLags(map &model_endos_and_lags) const override; @@ -1080,9 +1064,14 @@ public: bool containsPacExpectation(const string &pac_model_name = "") const override; void getPacOptimizingPart(int lhs_orig_symb_id, pair, vector>> &ec_params_and_vars, set>> ¶ms_and_vars) const override; - void getPacOptimizingShareAndExprNodes(set &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const override; + + //! Finds the share of optimizing agents in the PAC equation, + //! the expr node associated with it, + //! and the expr node associated with the non-optimizing part + tuple getPacOptimizingShareAndExprNodes(int lhs_symb_id, int lhs_orig_symb_id) const; + pair getPacOptimizingShareAndExprNodesHelper(BinaryOpNode *bopn, int lhs_symb_id, int lhs_orig_symb_id) const; + expr_t getPacNonOptimizingPart(BinaryOpNode *bopn, int optim_share) const; + bool getPacNonOptimizingPartHelper(BinaryOpNode *bopn, int optim_share) const; bool isParamTimesEndogExpr() const override; bool isVarModelReferenced(const string &model_info_name) const override; void getEndosAndMaxLags(map &model_endos_and_lags) const override; @@ -1195,9 +1184,6 @@ public: bool containsPacExpectation(const string &pac_model_name = "") const override; void getPacOptimizingPart(int lhs_orig_symb_id, pair, vector>> &ec_params_and_vars, set>> ¶ms_and_vars) const override; - void getPacOptimizingShareAndExprNodes(set &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const override; bool isParamTimesEndogExpr() const override; bool isVarModelReferenced(const string &model_info_name) const override; void getEndosAndMaxLags(map &model_endos_and_lags) const override; @@ -1322,9 +1308,6 @@ public: bool containsPacExpectation(const string &pac_model_name = "") const override; void getPacOptimizingPart(int lhs_orig_symb_id, pair, vector>> &ec_params_and_vars, set>> ¶ms_and_vars) const override; - void getPacOptimizingShareAndExprNodes(set &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const override; bool isParamTimesEndogExpr() const override; bool isVarModelReferenced(const string &model_info_name) const override; void getEndosAndMaxLags(map &model_endos_and_lags) const override; @@ -1537,9 +1520,6 @@ public: bool containsPacExpectation(const string &pac_model_name = "") const override; void getPacOptimizingPart(int lhs_orig_symb_id, pair, vector>> &ec_params_and_vars, set>> ¶ms_and_vars) const override; - void getPacOptimizingShareAndExprNodes(set &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const override; bool isParamTimesEndogExpr() const override; bool isVarModelReferenced(const string &model_info_name) const override; void getEndosAndMaxLags(map &model_endos_and_lags) const override; @@ -1625,9 +1605,6 @@ public: bool containsPacExpectation(const string &pac_model_name = "") const override; void getPacOptimizingPart(int lhs_orig_symb_id, pair, vector>> &ec_params_and_vars, set>> ¶ms_and_vars) const override; - void getPacOptimizingShareAndExprNodes(set &optim_share, - expr_t &optim_part, - expr_t &non_optim_part) const override; bool isParamTimesEndogExpr() const override; bool isVarModelReferenced(const string &model_info_name) const override; void getEndosAndMaxLags(map &model_endos_and_lags) const override;