diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc index 7de06f1f..c159c26b 100644 --- a/src/DynamicModel.cc +++ b/src/DynamicModel.cc @@ -3997,11 +3997,9 @@ DynamicModel::getPacTargetSymbId(const string &pac_model_name) const for (auto &equation : equations) if (equation->containsPacExpectation(pac_model_name)) { - pair lhs(-1, -1); set> 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(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; } diff --git a/src/ExprNode.cc b/src/ExprNode.cc index a83bb6d2..8b321d62 100644 --- a/src/ExprNode.cc +++ b/src/ExprNode.cc @@ -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; } diff --git a/src/ExprNode.hh b/src/ExprNode.hh index e6c8f1e3..25909fff 100644 --- a/src/ExprNode.hh +++ b/src/ExprNode.hh @@ -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;