diff --git a/src/CodeInterpreter.hh b/src/CodeInterpreter.hh
index 3331375ffc8ab7112d42fa3b3a28dcc19471de39..cbd5fc53e4dfb31c1aaf5b5de745bfe501f805dd 100644
--- a/src/CodeInterpreter.hh
+++ b/src/CodeInterpreter.hh
@@ -105,14 +105,6 @@ enum Tags
 
   };
 
-enum class BlockType
-  {
-   simultans, //!< Simultaneous time separable block
-   prologue, //!< Prologue block (one equation at the beginning, later merged)
-   epilogue, //!< Epilogue block (one equation at the beginning, later merged)
-   simultan //!< Simultaneous time unseparable block
-  };
-
 enum class EquationType
   {
    unknown, //!< Unknown equation type
diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc
index 6e1ed53cb69be10da0877efecdd6d0878e6b14a8..b7ceb6f1c7e9047f7c7b892c4048f92d5748815f 100644
--- a/src/DynamicModel.cc
+++ b/src/DynamicModel.cc
@@ -406,30 +406,10 @@ DynamicModel::writeModelEquationsOrdered_M(const string &basename) const
         output << "function [residual, y, g1, g2, g3, varargout] = dynamic_" << block+1 << "(y, x, params, steady_state, it_, jacobian_eval)" << endl;
       else
         output << "function [residual, y, g1, g2, g3, b, varargout] = dynamic_" << block+1 << "(y, x, params, steady_state, periods, jacobian_eval, y_kmin, y_size, Periods)" << endl;
-      BlockType block_type;
-      if (simulation_type == BlockSimulationType::solveTwoBoundariesComplete
-          || simulation_type == BlockSimulationType::solveTwoBoundariesSimple)
-        block_type = BlockType::simultan;
-      else if (simulation_type == BlockSimulationType::solveForwardComplete
-               || simulation_type == BlockSimulationType::solveBackwardComplete)
-        block_type = BlockType::simultans;
-      else if ((simulation_type == BlockSimulationType::solveForwardSimple
-                || simulation_type == BlockSimulationType::solveBackwardSimple
-                || simulation_type == BlockSimulationType::evaluateBackward
-                || simulation_type == BlockSimulationType::evaluateForward)
-               && blocks[block].first_equation < prologue)
-        block_type = BlockType::prologue;
-      else if ((simulation_type == BlockSimulationType::solveForwardSimple
-                || simulation_type == BlockSimulationType::solveBackwardSimple
-                || simulation_type == BlockSimulationType::evaluateBackward
-                || simulation_type == BlockSimulationType::evaluateForward)
-               && blocks[block].first_equation >= static_cast<int>(equations.size()) - epilogue)
-        block_type = BlockType::epilogue;
-      else
-        block_type = BlockType::simultans;
+
       output << "  % ////////////////////////////////////////////////////////////////////////" << endl
-             << "  % //" << string("                     Block ").substr(int (log10(block + 1))) << block + 1 << " " << BlockType0(block_type)
-             << "          //" << endl
+             << "  % //" << string("                     Block ").substr(int (log10(block + 1))) << block + 1
+             << "                                        //" << endl
              << "  % //                     Simulation type "
              << BlockSim(simulation_type) << "  //" << endl
              << "  % ////////////////////////////////////////////////////////////////////////" << endl;
@@ -4755,7 +4735,7 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO
 
       equationTypeDetermination(first_order_endo_derivatives, 0);
 
-      reduceBlocksAndTypeDetermination();
+      reduceBlockDecomposition();
 
       computeChainRuleJacobian();
 
@@ -4775,7 +4755,7 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO
 
       computeNonSingularNormalization(contemporaneous_jacobian, cutoff, static_jacobian);
 
-      computePrologueAndEpilogue();
+      auto [prologue, epilogue] = computePrologueAndEpilogue();
 
       auto first_order_endo_derivatives = collectFirstOrderDerivativesEndogenous();
 
@@ -4783,9 +4763,9 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO
 
       cout << "Finding the optimal block decomposition of the model ..." << endl;
 
-      computeBlockDecompositionAndFeedbackVariablesForEachBlock();
+      computeBlockDecomposition(prologue, epilogue);
 
-      reduceBlocksAndTypeDetermination();
+      reduceBlockDecomposition();
 
       printBlockDecomposition();
 
diff --git a/src/ModelTree.cc b/src/ModelTree.cc
index 3a00a8ed3abd4a73b73d1a0b9586c7b61eae27d7..1b74c67ee9946a1409331f673ae9283576168fb4 100644
--- a/src/ModelTree.cc
+++ b/src/ModelTree.cc
@@ -161,8 +161,6 @@ ModelTree::ModelTree(const ModelTree &m) :
   eq2block{m.eq2block},
   is_equation_linear{m.is_equation_linear},
   endo2eq{m.endo2eq},
-  epilogue{m.epilogue},
-  prologue{m.prologue},
   cutoff{m.cutoff},
   mfs{m.mfs}
 {
@@ -210,8 +208,6 @@ ModelTree::operator=(const ModelTree &m)
   eq2block = m.eq2block;
   is_equation_linear = m.is_equation_linear;
   endo2eq = m.endo2eq;
-  epilogue = m.epilogue;
-  prologue = m.prologue;
   cutoff = m.cutoff;
   mfs = m.mfs;
 
@@ -403,9 +399,6 @@ ModelTree::evaluateAndReduceJacobian(const eval_context_t &eval_context, double
 void
 ModelTree::select_non_linear_equations_and_variables()
 {
-  prologue = 0;
-  epilogue = 0;
-
   endo2block.resize(endo2eq.size(), 1); // The 1 is a dummy value, distinct from 0
   eq2block.resize(endo2eq.size(), 1);
   int i = 0;
@@ -429,6 +422,7 @@ ModelTree::select_non_linear_equations_and_variables()
   blocks[0].mfs_size = i;
   blocks[0].first_equation = 0;
   computeDynamicStructureOfBlock(0);
+  computeSimulationTypeOfBlock(0);
 }
 
 bool
@@ -459,7 +453,7 @@ ModelTree::computeNaturalNormalization()
   return bool_result;
 }
 
-void
+pair<int, int>
 ModelTree::computePrologueAndEpilogue()
 {
   const int n = equations.size();
@@ -489,7 +483,7 @@ ModelTree::computePrologueAndEpilogue()
 
   bool something_has_been_done;
   // Find the prologue equations and place first the AR(1) shock equations first
-  prologue = 0;
+  int prologue = 0;
   do
     {
       something_has_been_done = false;
@@ -525,7 +519,7 @@ ModelTree::computePrologueAndEpilogue()
   while (something_has_been_done);
   
   // Find the epilogue equations
-  epilogue = 0;
+  int epilogue = 0;
   do
     {
       something_has_been_done = false;
@@ -559,6 +553,8 @@ ModelTree::computePrologueAndEpilogue()
   while (something_has_been_done);
 
   updateReverseVariableEquationOrderings();
+
+  return { prologue, epilogue };
 }
 
 void
@@ -671,6 +667,37 @@ ModelTree::computeDynamicStructureOfBlock(int blk)
     }
 }
 
+void
+ModelTree::computeSimulationTypeOfBlock(int blk)
+{
+  auto &type = blocks[blk].simulation_type;
+  if (blocks[blk].max_endo_lag > 0 && blocks[blk].max_endo_lead > 0)
+    {
+      if (blocks[blk].size == 1)
+        type = BlockSimulationType::solveTwoBoundariesSimple;
+      else
+        type = BlockSimulationType::solveTwoBoundariesComplete;
+    }
+  else if (blocks[blk].size > 1)
+    {
+      if (blocks[blk].max_endo_lead > 0)
+        type = BlockSimulationType::solveBackwardComplete;
+      else
+        type = BlockSimulationType::solveForwardComplete;
+    }
+  else
+    {
+      bool can_eval = (getBlockEquationType(blk, 0) == EquationType::evaluate
+                       || getBlockEquationType(blk, 0) == EquationType::evaluate_s);
+      if (blocks[blk].max_endo_lead > 0)
+        type = can_eval ? BlockSimulationType::evaluateBackward :
+          BlockSimulationType::solveBackwardSimple;
+      else
+        type = can_eval ? BlockSimulationType::evaluateForward :
+          BlockSimulationType::solveForwardSimple;
+    }
+}
+
 pair<lag_lead_vector_t, lag_lead_vector_t>
 ModelTree::getVariableLeadLagByBlock() const
 {
@@ -694,7 +721,7 @@ ModelTree::getVariableLeadLagByBlock() const
 }
 
 void
-ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock()
+ModelTree::computeBlockDecomposition(int prologue, int epilogue)
 {
   int nb_var = symbol_table.endo_nbr();
   int nb_simvars = nb_var - prologue - epilogue;
@@ -812,7 +839,10 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock()
   updateReverseVariableEquationOrderings();
 
   for (int blk = 0; blk < static_cast<int>(blocks.size()); blk++)
-    computeDynamicStructureOfBlock(blk);
+    {
+      computeDynamicStructureOfBlock(blk);
+      computeSimulationTypeOfBlock(blk);
+    }
 }
 
 void
@@ -843,92 +873,46 @@ ModelTree::printBlockDecomposition() const
 }
 
 void
-ModelTree::reduceBlocksAndTypeDetermination()
+ModelTree::reduceBlockDecomposition()
 {
-  for (int blk = 0; blk < static_cast<int>(blocks.size()); blk++)
-    {
-      // Determine the block type
-      BlockSimulationType Simulation_Type;
-      if (blocks[blk].max_endo_lag > 0 && blocks[blk].max_endo_lead > 0)
-        {
-          if (blocks[blk].size == 1)
-            Simulation_Type = BlockSimulationType::solveTwoBoundariesSimple;
-          else
-            Simulation_Type = BlockSimulationType::solveTwoBoundariesComplete;
-        }
-      else if (blocks[blk].size > 1)
-        {
-          if (blocks[blk].max_endo_lead > 0)
-            Simulation_Type = BlockSimulationType::solveBackwardComplete;
-          else
-            Simulation_Type = BlockSimulationType::solveForwardComplete;
-        }
-      else
-        {
-          if (blocks[blk].max_endo_lead > 0)
-            Simulation_Type = BlockSimulationType::solveBackwardSimple;
-          else
-            Simulation_Type = BlockSimulationType::solveForwardSimple;
-        }
-
-      if (blocks[blk].size == 1)
-        {
-          // Determine if the block can simply be evaluated
-          if (getBlockEquationType(blk, 0) == EquationType::evaluate
-              || getBlockEquationType(blk, 0) == EquationType::evaluate_s)
-            {
-              if (Simulation_Type == BlockSimulationType::solveBackwardSimple)
-                Simulation_Type = BlockSimulationType::evaluateBackward;
-              else if (Simulation_Type == BlockSimulationType::solveForwardSimple)
-                Simulation_Type = BlockSimulationType::evaluateForward;
-            }
-
-          /* Try to merge this block with the previous one.
-             This is only possible if the two blocks can simply be evaluated
-             (in the same direction), and if the merge does not break the
-             restrictions on leads/lags. */
-          if (blk > 0)
-            {
-              set<pair<int, int>> endos_and_lags;
-              getBlockEquationExpr(blk, 0)->collectEndogenous(endos_and_lags);
-              bool is_lead = false, is_lag = false;
-              for (int var = 0; var < blocks[blk-1].size; var++)
-                {
-                  is_lag = endos_and_lags.find({ getBlockVariableID(blk-1, var), -1 }) != endos_and_lags.end();
-                  is_lead = endos_and_lags.find({ getBlockVariableID(blk-1, var), 1 }) != endos_and_lags.end();
-                }
-
-              BlockSimulationType prev_Type = blocks[blk-1].simulation_type;
-              if ((prev_Type == BlockSimulationType::evaluateForward
-                   && Simulation_Type == BlockSimulationType::evaluateForward
-                   && !is_lead)
-                  || (prev_Type == BlockSimulationType::evaluateBackward
-                      && Simulation_Type == BlockSimulationType::evaluateBackward
-                      && !is_lag))
-                {
-                  // Merge the current block into the previous one
-                  blocks[blk-1].size++;
-                  blocks[blk-1].mfs_size = blocks[blk-1].size;
-                  /* For max lag/lead, the max of the two blocks is not enough.
-                     We need to consider the case where a variable of the
-                     previous block appears with a lag/lead in the current one
-                     (the reverse case is excluded, by construction). */
-                  computeDynamicStructureOfBlock(blk-1);
-                  blocks.erase(blocks.begin()+blk);
-                  for (auto &b : endo2block)
-                    if (b >= blk)
-                      b--;
-                  for (auto &b : eq2block)
-                    if (b >= blk)
-                      b--;
-                  blk--;
-                  continue;
-                }
-            }
-        }
+  for (int blk = 1; blk < static_cast<int>(blocks.size()); blk++)
+    if (blocks[blk].size == 1)
+      {
+        /* Try to merge this block with the previous one.
+           This is only possible if the two blocks can simply be evaluated
+           (in the same direction), and if the merge does not break the
+           restrictions on leads/lags. */
+        set<pair<int, int>> endos_and_lags;
+        getBlockEquationExpr(blk, 0)->collectEndogenous(endos_and_lags);
+        bool is_lead = false, is_lag = false;
+        for (int var = 0; var < blocks[blk-1].size; var++)
+          {
+            is_lag = endos_and_lags.find({ getBlockVariableID(blk-1, var), -1 }) != endos_and_lags.end();
+            is_lead = endos_and_lags.find({ getBlockVariableID(blk-1, var), 1 }) != endos_and_lags.end();
+          }
 
-      blocks[blk].simulation_type = Simulation_Type;
-    }
+        if ((blocks[blk-1].simulation_type == BlockSimulationType::evaluateForward
+             && blocks[blk].simulation_type == BlockSimulationType::evaluateForward
+             && !is_lead)
+            || (blocks[blk-1].simulation_type == BlockSimulationType::evaluateBackward
+                && blocks[blk].simulation_type == BlockSimulationType::evaluateBackward
+                && !is_lag))
+          {
+            // Merge the current block into the previous one
+            blocks[blk-1].size++;
+            blocks[blk-1].mfs_size = blocks[blk-1].size;
+            computeDynamicStructureOfBlock(blk-1);
+            blocks.erase(blocks.begin()+blk);
+            for (auto &b : endo2block)
+              if (b >= blk)
+                b--;
+            for (auto &b : eq2block)
+              if (b >= blk)
+                b--;
+            blk--;
+            continue;
+          }
+      }
 }
 
 void
diff --git a/src/ModelTree.hh b/src/ModelTree.hh
index c29dbd22e2349b70484de3c5f9e9fb943e58a68f..95764aaa2e2717e3f476d776908629afab7b33e6 100644
--- a/src/ModelTree.hh
+++ b/src/ModelTree.hh
@@ -263,9 +263,6 @@ protected:
   /*! Maps endogenous type specific IDs to equation numbers */
   vector<int> endo2eq;
 
-  //! number of equation in the prologue and in the epilogue
-  int epilogue, prologue;
-
   /* Compute a pseudo-Jacobian whose all elements are either zero or one,
      depending on whether the variable symbolically appears in the equation */
   jacob_map_t computeSymbolicJacobian() const;
@@ -296,25 +293,27 @@ protected:
   pair<jacob_map_t, jacob_map_t> evaluateAndReduceJacobian(const eval_context_t &eval_context, double cutoff, bool verbose) const;
   //! Select and reorder the non linear equations of the model
   void select_non_linear_equations_and_variables();
-  //! Search the equations and variables belonging to the prologue and the epilogue of the model
-  void computePrologueAndEpilogue();
+  /* Search the equations and variables belonging to the prologue and the
+     epilogue of the model.
+     Initializes “eq_idx_block2orig” and “endo_idx_block2orig”.
+     Returns the sizes of the prologue and epilogue. */
+  pair<int, int> computePrologueAndEpilogue();
   //! Determine the type of each equation of model and try to normalize the unnormalized equation
   void equationTypeDetermination(const map<tuple<int, int, int>, expr_t> &first_order_endo_derivatives, int mfs);
   /* Fills the max lags/leads and n_{static,mixed,forward,backward} fields of a
      given block.
      Needs the fields size and first_equation. */
   void computeDynamicStructureOfBlock(int blk);
+  /* Fills the simulation_type field of a given block.
+     Needs the fields size, max_endo_lag and max_endo_lead. */
+  void computeSimulationTypeOfBlock(int blk);
   /* Compute the block decomposition and for a non-recusive block find the minimum feedback set
 
-     Initializes the “blocks” structure, and fills the following fields: size, first_equation,
-     mfs_size, n_static, n_forward, n_backward, n_mixed, maximum lags/leads.
-     Also initializes the endo2block and eq2block structures. */
-  void computeBlockDecompositionAndFeedbackVariablesForEachBlock();
+     Initializes the “blocks”, “endo2block” and “eq2block” structures. */
+  void computeBlockDecomposition(int prologue, int epilogue);
   /* Reduce the number of block by merging the same type of equations in the
-     prologue and the epilogue, and determine the type of each block.
-
-     Fills the “simulation_type” field of the “blocks” structure.  */
-  void reduceBlocksAndTypeDetermination();
+     prologue and the epilogue */
+  void reduceBlockDecomposition();
   /* The 1st output gives, for each equation (in original order) the (max_lag,
      max_lead) across all endogenous that appear in the equation and that
      belong to the same block (i.e. those endogenous are solved in the same
@@ -486,24 +485,6 @@ public:
       }
   }
 
-  inline static string
-  BlockType0(BlockType type)
-  {
-    switch (type)
-      {
-      case BlockType::simultans:
-        return "SIMULTANEOUS TIME SEPARABLE  ";
-      case BlockType::prologue:
-        return "PROLOGUE                     ";
-      case BlockType::epilogue:
-        return "EPILOGUE                     ";
-      case BlockType::simultan:
-        return "SIMULTANEOUS TIME UNSEPARABLE";
-      default:
-        return "UNKNOWN                      ";
-      }
-  }
-
   inline static string
   BlockSim(BlockSimulationType type)
   {
diff --git a/src/StaticModel.cc b/src/StaticModel.cc
index 82ecd946079968a06a2d4be5e6ace8469ba1c42a..aafd62905d30abc1c00cb8f59adbc6c952ac5a83 100644
--- a/src/StaticModel.cc
+++ b/src/StaticModel.cc
@@ -298,27 +298,9 @@ StaticModel::writeModelEquationsOrdered_M(const string &basename) const
       else
         output << "function [residual, y, g1] = static_" << block+1 << "(y, x, params)" << endl;
 
-      BlockType block_type;
-      if (simulation_type == BlockSimulationType::solveForwardComplete
-          || simulation_type == BlockSimulationType::solveBackwardComplete)
-        block_type = BlockType::simultans;
-      else if ((simulation_type == BlockSimulationType::solveForwardSimple
-                || simulation_type == BlockSimulationType::solveBackwardSimple
-                || simulation_type == BlockSimulationType::evaluateBackward
-                || simulation_type == BlockSimulationType::evaluateForward)
-               && blocks[block].first_equation < prologue)
-        block_type = BlockType::prologue;
-      else if ((simulation_type == BlockSimulationType::solveForwardSimple
-                || simulation_type == BlockSimulationType::solveBackwardSimple
-                || simulation_type == BlockSimulationType::evaluateBackward
-                || simulation_type == BlockSimulationType::evaluateForward)
-               && blocks[block].first_equation >= static_cast<int>(equations.size()) - epilogue)
-        block_type = BlockType::epilogue;
-      else
-        block_type = BlockType::simultans;
       output << "  % ////////////////////////////////////////////////////////////////////////" << endl
-             << "  % //" << string("                     Block ").substr(int (log10(block + 1))) << block + 1 << " " << BlockType0(block_type)
-             << "          //" << endl
+             << "  % //" << string("                     Block ").substr(int (log10(block + 1))) << block + 1
+             << "                                        //" << endl
              << "  % //                     Simulation type "
              << BlockSim(simulation_type) << "  //" << endl
              << "  % ////////////////////////////////////////////////////////////////////////" << endl;
@@ -1125,7 +1107,7 @@ StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_co
 
       computeNonSingularNormalization(contemporaneous_jacobian, cutoff, static_jacobian);
 
-      computePrologueAndEpilogue();
+      auto [prologue, epilogue] = computePrologueAndEpilogue();
 
       auto first_order_endo_derivatives = collectFirstOrderDerivativesEndogenous();
 
@@ -1133,9 +1115,9 @@ StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_co
 
       cout << "Finding the optimal block decomposition of the model ..." << endl;
 
-      computeBlockDecompositionAndFeedbackVariablesForEachBlock();
+      computeBlockDecomposition(prologue, epilogue);
 
-      reduceBlocksAndTypeDetermination();
+      reduceBlockDecomposition();
 
       printBlockDecomposition();