PAC MCE: fix incorrect detection of the target variable

The detection of the target EC variable to be used when constructing the
forward-looking expectation variable is rather fragile.

When the PAC model is written with an (non-)optimizing share of agents,
restrict the identification of the target variable to the optimizing
expression, to minimize the risk of wrong identification.

By the way, add a few comments, and a small simplification.
issue#70
Sébastien Villemot 2020-07-10 14:55:28 +02:00 committed by Stéphane Adjemian (Charybdis)
parent 51b3d5c68f
commit 16f9168fda
Signed by: stepan
GPG Key ID: 295C1FE89E17EB3C
3 changed files with 19 additions and 5 deletions

View File

@ -3997,11 +3997,9 @@ DynamicModel::getPacTargetSymbId(const string &pac_model_name) const
for (auto &equation : equations)
if (equation->containsPacExpectation(pac_model_name))
{
pair<int, int> lhs(-1, -1);
set<pair<int, int>> lhss;
equation->arg1->collectDynamicVariables(SymbolType::endogenous, lhss);
lhs = *lhss.begin();
int lhs_symb_id = lhs.first;
int lhs_symb_id = lhss.begin()->first;
int lhs_orig_symb_id = lhs_symb_id;
if (symbol_table.isAuxiliaryVariable(lhs_symb_id))
try
@ -4011,7 +4009,17 @@ DynamicModel::getPacTargetSymbId(const string &pac_model_name) const
catch (...)
{
}
return equation->arg2->getPacTargetSymbId(lhs_symb_id, lhs_orig_symb_id);
auto barg2 = dynamic_cast<BinaryOpNode *>(equation->arg2);
assert(barg2);
auto [optim_share_index, optim_part, non_optim_part, additive_part]
= barg2->getPacOptimizingShareAndExprNodes(lhs_symb_id, lhs_orig_symb_id);
/* The algorithm for identifying the target is fragile. Hence, if there
is an optimization part, we restrict the search to that part to
avoid wrong results. */
if (optim_part)
return optim_part->getPacTargetSymbId(lhs_symb_id, lhs_orig_symb_id);
else
return equation->arg2->getPacTargetSymbId(lhs_symb_id, lhs_orig_symb_id);
}
return -1;
}

View File

@ -4939,8 +4939,11 @@ BinaryOpNode::getPacTargetSymbIdHelper(int lhs_symb_id, int undiff_lhs_symb_id,
{
int id = datatree.symbol_table.getUltimateOrigSymbID(it.first);
if (id == lhs_symb_id || id == undiff_lhs_symb_id)
found_lagged_lhs = true;
found_lagged_lhs = true; // This expression contains the (lagged) LHS
if (id != lhs_symb_id && id != undiff_lhs_symb_id)
/* The first variable that is not the (lagged) LHS is a
candidate for the target. FIXME: What happens if there are several
such variables? The detection order is not meaningful */
if (target_symb_id < 0)
target_symb_id = it.first;
}

View File

@ -480,6 +480,9 @@ public:
virtual int PacMaxLag(int lhs_symb_id) const = 0;
//! Get the target variable of the PAC model
/* The algorithm is rather crude. For a BinaryOpNode, it inspects both
arguments. If one of the argument contains the (lagged) LHS, the first
variable that is not the (lagged) LHS is returned as the target */
virtual int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const = 0;
virtual expr_t undiff() const = 0;