From d18138e410faa6e5663d291af07743d00f787918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org> Date: Thu, 23 Mar 2023 17:58:20 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Incorrect=20stochastic=20transfo?= =?UTF-8?q?rmation=20with=20endo=20lead=20=E2=A9=BE=202=20or=20exo=20lead?= =?UTF-8?q?=20=E2=A9=BE=201=20in=20external=20functions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If an endogenous with a lead ⩾ 2 or an exogenous with a lead ⩾ 1 appeared in the argument(s) of a call to an external function, the auxiliary variable transformation was incorrect (the variable was replaced inside the function call, while it is the whole function call that has to be replaced). This could lead to incorrect results in stochastic contexts, when the external function is nonlinear. (manually cherry picked from commit 712b11a04575e15f0a5080b469fcd4d7e02b597f) --- src/ExprNode.cc | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/ExprNode.cc b/src/ExprNode.cc index a697f645..d1ab8690 100644 --- a/src/ExprNode.cc +++ b/src/ExprNode.cc @@ -6600,10 +6600,17 @@ AbstractExternalFunctionNode::decreaseLeadsLagsPredeterminedVariables() const expr_t AbstractExternalFunctionNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const { - vector<expr_t> arguments_subst; - for (auto argument : arguments) - arguments_subst.push_back(argument->substituteEndoLeadGreaterThanTwo(subst_table, neweqs, deterministic_model)); - return buildSimilarExternalFunctionNode(arguments_subst, datatree); + if (maxEndoLead() < 2) + return const_cast<AbstractExternalFunctionNode *>(this); + else if (deterministic_model) + { + vector<expr_t> arguments_subst; + for (auto argument : arguments) + arguments_subst.push_back(argument->substituteEndoLeadGreaterThanTwo(subst_table, neweqs, deterministic_model)); + return buildSimilarExternalFunctionNode(arguments_subst, datatree); + } + else + return createEndoLeadAuxiliaryVarForMyself(subst_table, neweqs); } expr_t @@ -6618,10 +6625,17 @@ AbstractExternalFunctionNode::substituteEndoLagGreaterThanTwo(subst_table_t &sub expr_t AbstractExternalFunctionNode::substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const { - vector<expr_t> arguments_subst; - for (auto argument : arguments) - arguments_subst.push_back(argument->substituteExoLead(subst_table, neweqs, deterministic_model)); - return buildSimilarExternalFunctionNode(arguments_subst, datatree); + if (maxExoLead() == 0) + return const_cast<AbstractExternalFunctionNode *>(this); + else if (deterministic_model) + { + vector<expr_t> arguments_subst; + for (auto argument : arguments) + arguments_subst.push_back(argument->substituteExoLead(subst_table, neweqs, deterministic_model)); + return buildSimilarExternalFunctionNode(arguments_subst, datatree); + } + else + return createExoLeadAuxiliaryVarForMyself(subst_table, neweqs); } expr_t -- GitLab