From 011e90a1eb98cf6dcfc5330c141fc4cc42be3adf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org>
Date: Wed, 16 Oct 2024 12:07:32 -0400
Subject: [PATCH] =?UTF-8?q?det=5Fcond=5Fforecast:=20when=20using=20bytecod?=
 =?UTF-8?q?e,=20do=20not=20use=20block=20decomposition=20even=20with=20?=
 =?UTF-8?q?=E2=80=9Cblock=E2=80=9D=20option?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Bytecode does not support conditional forecasting with block
decomposition (since the derivatives w.r.t. exogenous are no longer provided by
the preprocessor when doing block decomposition). In practice trying this would
lead to a crash.
---
 .../det_cond_forecast.m                       | 22 ++++-------
 mex/sources/bytecode/Interpreter.cc           | 39 +------------------
 mex/sources/bytecode/Interpreter.hh           |  2 -
 3 files changed, 9 insertions(+), 54 deletions(-)

diff --git a/matlab/perfect-foresight-models/det_cond_forecast.m b/matlab/perfect-foresight-models/det_cond_forecast.m
index 186db3f6d..f26cdf543 100644
--- a/matlab/perfect-foresight-models/det_cond_forecast.m
+++ b/matlab/perfect-foresight-models/det_cond_forecast.m
@@ -69,6 +69,10 @@ if (range(range.ndat) > dset.dates(dset.nobs)+1 )
     error(['det_cond_forecast: The dseries ' inputname(2) ' finishes at time ' s1{1} ' before the last period of forecast ' s2{1}]);
 end
 
+if options_.block
+    warning('det_cond_forecast: ignoring the block option, which is not compatible with conditional forecasting')
+end
+
 sym_dset = dset(dates(-range(1)):dates(range(range.ndat)));
 periods = options_.periods + M_.maximum_lag + M_.maximum_lead;
 total_periods = periods + range.ndat;
@@ -125,11 +129,7 @@ end
 if options_.bytecode
     save_options_dynatol_f = options_.dynatol.f;
     options_.dynatol.f = 1e-7;
-    if options_.block
-        [endo, exo] = bytecode('extended_path', plan, 'block_decomposed', M_, options_, oo_.endo_simul, oo_.exo_simul, M_.params, oo_.steady_state, options_.periods);
-    else
-        [endo, exo] = bytecode('extended_path', plan, M_, options_, oo_.endo_simul, oo_.exo_simul, M_.params, oo_.steady_state, options_.periods);
-    end
+    [endo, exo] = bytecode('extended_path', plan, M_, options_, oo_.endo_simul, oo_.exo_simul, M_.params, oo_.steady_state, options_.periods);
     options_.dynatol.f = save_options_dynatol_f;
 
     oo_.endo_simul = endo;
@@ -389,11 +389,7 @@ if pf && ~surprise
             if k == 1
                 data1 = M_;
                 if (options_.bytecode)
-                    if options_.block
-                        [~, data1]= bytecode('dynamic','block_decomposed','evaluate', M_, options_, z, zx, M_.params, oo_.steady_state, k, data1);
-                    else
-                        [~, data1]= bytecode('dynamic','evaluate', M_, options_, z, zx, M_.params, oo_.steady_state, k, data1);
-                    end
+                    [~, data1]= bytecode('dynamic','evaluate', M_, options_, z, zx, M_.params, oo_.steady_state, k, data1);
                 else
                     [~, g1b] = feval([M_.fname '.dynamic'], z', zx, M_.params, oo_.steady_state, k);
                     data1.g1_x = g1b(:,end - M_.exo_nbr + 1:end);
@@ -636,11 +632,7 @@ else
                 if k == 1
                     data1 = M_;
                     if (options_.bytecode)
-                        if options_.block
-                            [~, data1]= bytecode('dynamic','block_decomposed','evaluate', M_, options_, z, zx, M_.params, oo_.steady_state, k, data1);
-                        else
-                            [~, data1]= bytecode('dynamic','evaluate', M_, options_, z, zx, M_.params, oo_.steady_state, k, data1);
-                        end
+                        [~, data1]= bytecode('dynamic','evaluate', M_, options_, z, zx, M_.params, oo_.steady_state, k, data1);
                     else
                         [~, g1b] = feval([M_.fname '.dynamic'], z', zx, M_.params, oo_.steady_state, k);
                         data1.g1_x = g1b(:,end - M_.exo_nbr + 1:end);
diff --git a/mex/sources/bytecode/Interpreter.cc b/mex/sources/bytecode/Interpreter.cc
index 9b428922b..124955585 100644
--- a/mex/sources/bytecode/Interpreter.cc
+++ b/mex/sources/bytecode/Interpreter.cc
@@ -652,40 +652,6 @@ Interpreter::simulate_a_block(
   return NO_ERROR_ON_EXIT;
 }
 
-void
-Interpreter::check_for_controlled_exo_validity(const vector<s_plan>& sconstrained_extended_path)
-{
-  vector<int> exogenous {evaluator.getCurrentBlockExogenous()};
-  vector<int> endogenous {evaluator.getCurrentBlockVariables()};
-  for (auto& it : sconstrained_extended_path)
-    {
-      if (ranges::find(endogenous, it.exo_num) != endogenous.end()
-          && ranges::find(exogenous, it.var_num) == exogenous.end())
-        throw FatalException {"\nThe conditional forecast involving as constrained variable "
-                              + symbol_table.getName(SymbolType::endogenous, it.exo_num)
-                              + " and as endogenized exogenous "
-                              + symbol_table.getName(SymbolType::exogenous, it.var_num)
-                              + " that do not appear in block=" + to_string(block_num + 1)
-                              + ")\nYou should not use block in model options"};
-      else if (ranges::find(endogenous, it.exo_num) != endogenous.end()
-               && ranges::find(exogenous, it.var_num) != exogenous.end()
-               && (type == BlockSimulationType::evaluateForward
-                   || type == BlockSimulationType::evaluateBackward))
-        throw FatalException {"\nThe conditional forecast cannot be implemented for the block="
-                              + to_string(block_num + 1)
-                              + ") that has to be evaluated instead to be solved\nYou should not "
-                                "use block in model options"};
-      else if (ranges::find(previous_block_exogenous, it.var_num) != previous_block_exogenous.end())
-        throw FatalException {
-            "\nThe conditional forecast involves in the block " + to_string(block_num + 1)
-            + " the endogenized exogenous "
-            + symbol_table.getName(SymbolType::exogenous, it.var_num)
-            + " that appear also in a previous block\nYou should not use block in model options"};
-    }
-  for (auto it : exogenous)
-    previous_block_exogenous.push_back(it);
-}
-
 pair<bool, vector<int>>
 Interpreter::MainLoop(const string& bin_basename, bool evaluate, int block, bool constrained,
                       const vector<s_plan>& sconstrained_extended_path,
@@ -734,8 +700,8 @@ Interpreter::MainLoop(const string& bin_basename, bool evaluate, int block, bool
       equations = evaluator.getCurrentBlockEquations();
       u_count_int = evaluator.getCurrentBlockUCount();
 
-      if (constrained)
-        check_for_controlled_exo_validity(sconstrained_extended_path);
+      if (constrained && block_decomposed)
+        throw FatalException {"Conditional forecasting is not compatible with block decomposition"};
       if (print)
         {
           if (steady_state)
@@ -904,7 +870,6 @@ Interpreter::extended_path(const string& file_name, bool evaluate, int block, in
   vector<int> blocks;
   for (int t = 0; t < nb_periods; t++)
     {
-      previous_block_exogenous.clear();
       if (old_verbosity >= 1)
         {
           mexPrintf("|%s|", elastic(dates[t], date_length + 2, false).c_str());
diff --git a/mex/sources/bytecode/Interpreter.hh b/mex/sources/bytecode/Interpreter.hh
index fa2f32485..d98a18e15 100644
--- a/mex/sources/bytecode/Interpreter.hh
+++ b/mex/sources/bytecode/Interpreter.hh
@@ -153,7 +153,6 @@ private:
 
   int verbosity; // Corresponds to options_.verbosity
 
-  vector<int> previous_block_exogenous;
   bool print; // Whether the “print” command is requested
   int col_x, col_y;
   vector<double> residual;
@@ -166,7 +165,6 @@ private:
   int simulate_a_block(const vector_table_conditional_local_type& vector_table_conditional_local,
                        bool single_block, const string& bin_base_name);
   static string elastic(string str, unsigned int len, bool left);
-  void check_for_controlled_exo_validity(const vector<s_plan>& sconstrained_extended_path);
   pair<bool, vector<int>>
   MainLoop(const string& bin_basename, bool evaluate, int block, bool constrained,
            const vector<s_plan>& sconstrained_extended_path,
-- 
GitLab