From 8bfe3ef4bc8973589aa35d1a3cb265fb954748ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org> Date: Mon, 15 Apr 2024 18:26:11 +0200 Subject: [PATCH] New syntax for complementarity conditions, using the perpendicular symbol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The symbol can be either input: – as ⟂ in UTF-8 (codepoint U+27C2) – or as _|_ in ASCII The old syntax using the “mcp” tag is now obsolete, but kept for backward compatibility. --- src/DynareBison.yy | 10 +++++++++- src/DynareFlex.ll | 2 ++ src/ParsingDriver.cc | 32 ++++++++++++++++++++++++++++---- src/ParsingDriver.hh | 8 +++++--- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/DynareBison.yy b/src/DynareBison.yy index 60260678..4aed10f5 100644 --- a/src/DynareBison.yy +++ b/src/DynareBison.yy @@ -215,7 +215,7 @@ str_tolower(string s) %token ENDVAL_STEADY STEADY_SOLVE_ALGO STEADY_MAXIT STEADY_TOLF STEADY_TOLX STEADY_MARKOWITZ %token HOMOTOPY_MAX_COMPLETION_SHARE HOMOTOPY_MIN_STEP_SIZE HOMOTOPY_INITIAL_STEP_SIZE HOMOTOPY_STEP_SIZE_INCREASE_SUCCESS_COUNT %token HOMOTOPY_LINEARIZATION_FALLBACK HOMOTOPY_MARGINAL_LINEARIZATION_FALLBACK HOMOTOPY_EXCLUDE_VAREXO FROM_INITVAL_TO_ENDVAL -%token STATIC_MFS RELATIVE_TO_INITVAL MATCHED_IRFS MATCHED_IRFS_WEIGHTS WEIGHTS +%token STATIC_MFS RELATIVE_TO_INITVAL MATCHED_IRFS MATCHED_IRFS_WEIGHTS WEIGHTS PERPENDICULAR %token <vector<string>> SYMBOL_VEC @@ -1011,6 +1011,14 @@ equation : hand_side EQUAL hand_side ';' { $$ = driver.add_model_equal($4, $6, $2); } | '[' tag_pair_list ']' hand_side ';' { $$ = driver.add_model_equal_with_zero_rhs($4, $2); } + | hand_side EQUAL hand_side PERPENDICULAR hand_side ';' + { $$ = driver.add_model_equal($1, $3, {}, $5); } + | hand_side PERPENDICULAR hand_side ';' + { $$ = driver.add_model_equal_with_zero_rhs($1, {}, $3); } + | '[' tag_pair_list ']' hand_side EQUAL hand_side PERPENDICULAR hand_side ';' + { $$ = driver.add_model_equal($4, $6, $2, $8); } + | '[' tag_pair_list ']' hand_side PERPENDICULAR hand_side ';' + { $$ = driver.add_model_equal_with_zero_rhs($4, $2, $6); } ; tag_pair_list : tag_pair_list COMMA tag_pair diff --git a/src/DynareFlex.ll b/src/DynareFlex.ll index 618bf379..13d14405 100644 --- a/src/DynareFlex.ll +++ b/src/DynareFlex.ll @@ -1016,6 +1016,8 @@ DATE -?[0-9]+([ya]|m([1-9]|1[0-2])|q[1-4]) <DYNARE_STATEMENT,DYNARE_BLOCK>nan {return token::NAN_CONSTANT;} <DYNARE_STATEMENT,DYNARE_BLOCK>inf {return token::INF_CONSTANT;} <DYNARE_STATEMENT,DYNARE_BLOCK>constants {return token::CONSTANTS;} +<DYNARE_BLOCK>⟂ {return token::PERPENDICULAR;} +<DYNARE_BLOCK>_\|_ {return token::PERPENDICULAR;} /* options for GSA module by Marco Ratto */ <DYNARE_STATEMENT>identification {return token::IDENTIFICATION;} diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc index c8733c18..7f351fda 100644 --- a/src/ParsingDriver.cc +++ b/src/ParsingDriver.cc @@ -1,5 +1,5 @@ /* - * Copyright © 2003-2023 Dynare Team + * Copyright © 2003-2024 Dynare Team * * This file is part of Dynare. * @@ -2626,7 +2626,8 @@ ParsingDriver::extended_path() } expr_t -ParsingDriver::add_model_equal(expr_t arg1, expr_t arg2, map<string, string> eq_tags) +ParsingDriver::add_model_equal(expr_t arg1, expr_t arg2, map<string, string> eq_tags, + expr_t complementarity_condition) { expr_t id = model_tree->AddEqual(arg1, arg2); @@ -2634,6 +2635,28 @@ ParsingDriver::add_model_equal(expr_t arg1, expr_t arg2, map<string, string> eq_ if (key == "endogenous") declare_or_change_type(SymbolType::endogenous, value); + if (eq_tags.contains("mcp")) + { + if (complementarity_condition) + error("Can't have both an 'mcp' tag and a complementarity condition after the " + "perpendicular symbol"); + else + warning("Specifying complementarity conditions with the 'mcp' tag is obsolete. Please " + "consider switching to the new syntax using the perpendicular symbol."); + } + + if (complementarity_condition) + { + if (auto bcomp = dynamic_cast<BinaryOpNode*>(complementarity_condition); + !(bcomp + && (bcomp->op_code == BinaryOpcode::less || bcomp->op_code == BinaryOpcode::lessEqual + || bcomp->op_code == BinaryOpcode::greater + || bcomp->op_code == BinaryOpcode::greaterEqual))) + error("The complementarity constraint must be an inequality."); + + eq_tags.emplace("mcp", complementarity_condition->toString()); + } + if (eq_tags.contains("static")) { // If the equation is tagged [static] @@ -2723,9 +2746,10 @@ ParsingDriver::add_model_equal(expr_t arg1, expr_t arg2, map<string, string> eq_ } expr_t -ParsingDriver::add_model_equal_with_zero_rhs(expr_t arg, map<string, string> eq_tags) +ParsingDriver::add_model_equal_with_zero_rhs(expr_t arg, map<string, string> eq_tags, + expr_t complementarity_condition) { - return add_model_equal(arg, model_tree->Zero, move(eq_tags)); + return add_model_equal(arg, model_tree->Zero, move(eq_tags), complementarity_condition); } void diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh index 724aabd8..a664d1c5 100644 --- a/src/ParsingDriver.hh +++ b/src/ParsingDriver.hh @@ -1,5 +1,5 @@ /* - * Copyright © 2003-2023 Dynare Team + * Copyright © 2003-2024 Dynare Team * * This file is part of Dynare. * @@ -748,9 +748,11 @@ public: //! Extended path void extended_path(); //! Writes token "arg1=arg2" to model tree - expr_t add_model_equal(expr_t arg1, expr_t arg2, map<string, string> eq_tags); + expr_t add_model_equal(expr_t arg1, expr_t arg2, map<string, string> eq_tags, + expr_t complementarity_condition = nullptr); //! Writes token "arg=0" to model tree - expr_t add_model_equal_with_zero_rhs(expr_t arg, map<string, string> eq_tags); + expr_t add_model_equal_with_zero_rhs(expr_t arg, map<string, string> eq_tags, + expr_t complementarity_condition = nullptr); //! Writes token "arg1+arg2" to model tree expr_t add_plus(expr_t arg1, expr_t arg2); //! Writes token "arg1-arg2" to model tree -- GitLab