find additive parts to pac equation

issue#70
Houtan Bastani 2019-02-27 23:12:05 +01:00
parent 2312ce13dc
commit 5f013756f2
4 changed files with 172 additions and 151 deletions

View File

@ -3663,8 +3663,8 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block_de
int optim_share_index;
set<pair<int, pair<int, int>>> ar_params_and_vars;
pair<int, pair<vector<int>, vector<bool>>> ec_params_and_vars;
vector<tuple<int, int, int, double>> 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<tuple<int, int, int, double>> 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<pair<string, string>, pa
pair<int, int> lhs (-1, -1);
pair<int, pair<vector<int>, vector<bool>>> ec_params_and_vars;
set<pair<int, pair<int, int>>> ar_params_and_vars;
vector<tuple<int, int, int, double>> non_optim_vars_params_and_constants;
vector<tuple<int, int, int, double>> non_optim_vars_params_and_constants, additive_vars_params_and_constants;
if (equation->containsPacExpectation())
{
int optim_share_index = -1;
set<int> 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<pair<int, int>> 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<pair<string, string>, pa
{
}
equation->arg2->getPacOptimizingShareAndExprNodes(optim_share,
optim_part,
non_optim_part);
auto arg2 = dynamic_cast<BinaryOpNode *>(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<pair<string, string>, 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};
}
}

View File

@ -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<pair<string, string>,
tuple<pair<int, int>, int, set<pair<int, pair<int, int>>>, pair<int, pair<vector<int>, vector<bool>>>, vector<tuple<int, int, int, double>>>> pac_equation_info;
tuple<pair<int, int>, int, set<pair<int, pair<int, int>>>, pair<int, pair<vector<int>, vector<bool>>>, vector<tuple<int, int, int, double>>, vector<tuple<int, int, int, double>>>> pac_equation_info;
//! Table to undiff LHS variables for pac vector z
vector<int> getUndiffLHSForPac(const string &aux_model_name,

View File

@ -680,13 +680,6 @@ NumConstNode::getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<i
{
}
void
NumConstNode::getPacOptimizingShareAndExprNodes(set<int> &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<int, pair<vector<i
{
}
void
VariableNode::getPacOptimizingShareAndExprNodes(set<int> &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, pair<int, pair<vector<in
arg->getPacOptimizingPart(lhs_orig_symb_id, ec_params_and_vars, ar_params_and_vars);
}
void
UnaryOpNode::getPacOptimizingShareAndExprNodes(set<int> &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<int> &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<int> 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<BinaryOpNode *>(bopn->arg1);
auto a2 = dynamic_cast<BinaryOpNode *>(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<int, expr_t>
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<pair<int, int>> 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<VariableNode *>(arg1);
auto *test_arg2 = dynamic_cast<VariableNode *>(arg2);
set<int> params1, params2;
arg1->collectVariables(SymbolType::parameter, params1);
arg2->collectVariables(SymbolType::parameter, params2);
if (dynamic_cast<NumConstNode *>(arg1) != nullptr
|| dynamic_cast<NumConstNode *>(arg2) != nullptr)
set<int> 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<int, expr_t, expr_t, expr_t>
BinaryOpNode::getPacOptimizingShareAndExprNodes(int lhs_symb_id, int lhs_orig_symb_id) const
{
vector<pair<expr_t, int>> terms;
decomposeAdditiveTerms(terms, 1);
for (auto & it : terms)
if (dynamic_cast<PacExpectationNode *>(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<BinaryOpNode *>(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<BinaryOpNode *>(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, pair<int, pair<vector<
arg3->getPacOptimizingPart(lhs_orig_symb_id, ec_params_and_vars, ar_params_and_vars);
}
void
TrinaryOpNode::getPacOptimizingShareAndExprNodes(set<int> &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, pair<in
argument->getPacOptimizingPart(lhs_orig_symb_id, ec_params_and_vars, ar_params_and_vars);
}
void
AbstractExternalFunctionNode::getPacOptimizingShareAndExprNodes(set<int> &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<int, pair<ve
{
}
void
VarExpectationNode::getPacOptimizingShareAndExprNodes(set<int> &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<int, pair<ve
{
}
void
PacExpectationNode::getPacOptimizingShareAndExprNodes(set<int> &optim_share,
expr_t &optim_part,
expr_t &non_optim_part) const
{
}
expr_t
PacExpectationNode::substitutePacExpectation(const string & name, expr_t subexpr)
{

View File

@ -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<int> &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<int> &lhs, map<tuple<int, int, int>, 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<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &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<string, int> &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<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &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<string, int> &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<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &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<string, int> &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<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &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<int, expr_t, expr_t, expr_t> getPacOptimizingShareAndExprNodes(int lhs_symb_id, int lhs_orig_symb_id) const;
pair<int, expr_t> 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<string, int> &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<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &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<string, int> &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<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &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<string, int> &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<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &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<string, int> &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<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &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<string, int> &model_endos_and_lags) const override;