From 53b2a1e926cf12f6107e6e2e568dc462de795acb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org>
Date: Mon, 27 Jan 2020 15:58:13 +0100
Subject: [PATCH] Do not simplify constant equations which have a tag attached

In particular, in the case of an 'mcp' tag, this could lead to a convergence
failure.

Ref. dynare#1697

(cherry picked from commit bef537d40accd597c19f112471974b726c9c9890)
---
 src/ModelTree.cc | 12 +++++++-----
 src/ModelTree.hh |  6 ++++--
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/src/ModelTree.cc b/src/ModelTree.cc
index f6ec39b3..ba5b30e8 100644
--- a/src/ModelTree.cc
+++ b/src/ModelTree.cc
@@ -2019,22 +2019,24 @@ ModelTree::simplifyEquations()
 {
   size_t last_subst_table_size = 0;
   map<VariableNode *, NumConstNode *> subst_table;
-  findConstantEquations(subst_table);
+  // Equations with tags are excluded, in particular because of MCPs, see dynare#1697
+  findConstantEquationsWithoutTags(subst_table);
   while (subst_table.size() != last_subst_table_size)
     {
       last_subst_table_size = subst_table.size();
       for (auto &equation : equations)
         equation = dynamic_cast<BinaryOpNode *>(equation->replaceVarsInEquation(subst_table));
       subst_table.clear();
-      findConstantEquations(subst_table);
+      findConstantEquationsWithoutTags(subst_table);
     }
 }
 
 void
-ModelTree::findConstantEquations(map<VariableNode *, NumConstNode *> &subst_table) const
+ModelTree::findConstantEquationsWithoutTags(map<VariableNode *, NumConstNode *> &subst_table) const
 {
-  for (auto &equation : equations)
-    equation->findConstantEquations(subst_table);
+  for (size_t i = 0; i < equations.size(); i++)
+    if (getEquationTags(i).empty())
+      equations[i]->findConstantEquations(subst_table);
 }
 
 void
diff --git a/src/ModelTree.hh b/src/ModelTree.hh
index 5d7ad1cb..7f5c5686 100644
--- a/src/ModelTree.hh
+++ b/src/ModelTree.hh
@@ -374,12 +374,14 @@ public:
   bool isNonstationary(int symb_id) const;
   void set_cutoff_to_zero();
   //! Simplify model equations: if a variable is equal to a constant, replace that variable elsewhere in the model
+  /*! Equations with tags are excluded, in particular because of MCPs, see
+      dynare#1697 */
   void simplifyEquations();
   /*! Reorder auxiliary variables so that they appear in recursive order in
       set_auxiliary_variables.m and dynamic_set_auxiliary_series.m */
   void reorderAuxiliaryEquations();
-  //! Find equations where variable is equal to a constant
-  void findConstantEquations(map<VariableNode *, NumConstNode *> &subst_table) const;
+  //! Find equations of the form “variable=constant”, excluding equations with tags
+  void findConstantEquationsWithoutTags(map<VariableNode *, NumConstNode *> &subst_table) const;
   //! Helper for writing the Jacobian elements in MATLAB and C
   /*! Writes either (i+1,j+1) or [i+j*no_eq] */
   void jacobianHelper(ostream &output, int eq_nb, int col_nb, ExprNodeOutputType output_type) const;
-- 
GitLab