From cb19ece049a99a8740fb1bff0560b5c0bedadd1b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org>
Date: Wed, 8 Sep 2021 17:06:10 +0200
Subject: [PATCH] estimated_params*: add a check that prevents (apparently)
 recursive prior definitions

Closes: #77
---
 src/ComputingTasks.cc | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/src/ComputingTasks.cc b/src/ComputingTasks.cc
index 46214752..8cf7f930 100644
--- a/src/ComputingTasks.cc
+++ b/src/ComputingTasks.cc
@@ -20,6 +20,8 @@
 #include <cassert>
 #include <iostream>
 #include <sstream>
+#include <algorithm>
+#include <iterator>
 
 using namespace std;
 
@@ -1401,6 +1403,41 @@ AbstractEstimatedParamsStatement::commonCheckPass() const
             }
         }
     }
+
+  /* Check that a parameter declared in this block is not used in expressions
+     associated to other parameters in the same block (see issue #77) */
+  // First compute the symbol IDs of parameters declared in this block
+  set<int> declared_params;
+  transform(already_declared.begin(), already_declared.end(), inserter(declared_params, declared_params.end()),
+            [&](const string &name) { return symbol_table.getID(name); });
+  // Then look for (apparently) recursive definitions
+  for (const auto &it : estim_params_list)
+    {
+      set<int> used_params;
+      it.init_val->collectVariables(SymbolType::parameter, used_params);
+      it.low_bound->collectVariables(SymbolType::parameter, used_params);
+      it.up_bound->collectVariables(SymbolType::parameter, used_params);
+      it.mean->collectVariables(SymbolType::parameter, used_params);
+      it.std->collectVariables(SymbolType::parameter, used_params);
+      it.p3->collectVariables(SymbolType::parameter, used_params);
+      it.p4->collectVariables(SymbolType::parameter, used_params);
+      it.jscale->collectVariables(SymbolType::parameter, used_params);
+      vector<int> intersect;
+      set_intersection(declared_params.begin(), declared_params.end(),
+                       used_params.begin(), used_params.end(),
+                       back_inserter(intersect));
+      if (intersect.size() > 0)
+        {
+          cerr << "ERROR: in `" << blockName() << "' block, the value of estimated parameter "
+               << symbol_table.getName(intersect[0]) << " is used in the declaration for ";
+          if (it.type == 3)
+            cerr << "correlation between " << it.name << " and " << it.name2;
+          else // either a parameter, the stderr of an exo, or the measurement error of an endo
+            cerr << "symbol " << it.name;
+          cerr << ". This behaviour is undefined." << endl;
+          exit(EXIT_FAILURE);
+        }
+    }
 }
 
 EstimatedParamsStatement::EstimatedParamsStatement(vector<EstimationParams> estim_params_list_arg,
-- 
GitLab