diff --git a/maca_common/include/LimitedStack.hpp b/maca_common/include/LimitedStack.hpp
index 32422abd60fdf1f344fb2c0d9588e8c763cc289d..06d08608a91588f71a672a45a5d3ad6dfddf062a 100644
--- a/maca_common/include/LimitedStack.hpp
+++ b/maca_common/include/LimitedStack.hpp
@@ -7,6 +7,20 @@
 #define LIMITEDSTACK__H
 
 #include <vector>
+#include <unordered_map>
+#include "Action.hpp"
+
+namespace std
+{
+  template<>
+  struct hash< std::pair<std::string, Action> >
+  {
+    size_t operator()(const std::pair<std::string, Action> &p) const
+    {
+      return 0;
+    }
+  };
+}
 
 template<typename T>
 class LimitedStack
@@ -14,6 +28,7 @@ class LimitedStack
   private :
 
   std::vector<T> data;
+  std::unordered_map<T, int> present;
   int nbElements;
   int lastElementIndex;
 
@@ -39,7 +54,9 @@ class LimitedStack
     if (lastElementIndex >= (int)data.size())
       lastElementIndex = 0;
 
+    present[data[lastElementIndex]]--;
     data[lastElementIndex] = elem;
+    present[data[lastElementIndex]]++;
   }
 
   T pop()
@@ -58,6 +75,7 @@ class LimitedStack
     if (lastElementIndex < 0)
       lastElementIndex = data.size() - 1;
 
+    present[data[elementIndex]]--;
     return data[elementIndex];
   }
 
@@ -79,18 +97,7 @@ class LimitedStack
 
   bool contains(const T & element)
   {
-    int currentIndex = lastElementIndex;
-    for (int i = 0; i < nbElements; i++)
-    {
-      if (data[currentIndex] == element)
-        return true;
-
-      currentIndex--;
-      if (currentIndex < 0)
-        currentIndex = data.size()-1;
-    }
-
-    return false;
+    return present[element] > 0;
   }
 
   unsigned int size()
diff --git a/trainer/src/Trainer.cpp b/trainer/src/Trainer.cpp
index 1c8ed8ac7509015e62567f9673a35414d02fe998..ac5f7e9d6f0887f20456c7f9ab90d8ccf15129f7 100644
--- a/trainer/src/Trainer.cpp
+++ b/trainer/src/Trainer.cpp
@@ -58,7 +58,7 @@ void Trainer::computeScoreOnDev()
   bool justFlipped = false;
   int nbActions = 0;
   int nbActionsCutoff = 2*ProgramParameters::batchSize;
-  float currentSpeed = 0.0;
+  currentSpeed = 0.0;
   auto pastTime = std::chrono::high_resolution_clock::now();
   std::vector<float> entropies;
 
@@ -137,6 +137,7 @@ void Trainer::computeScoreOnDev()
 
       if (ProgramParameters::debug)
       {
+        fprintf(stderr, "Speed : %s actions/s\n", int2humanStr((int)currentSpeed).c_str());
         devConfig->printForDebug(stderr);
         fprintf(stderr, "pAction=<%s> action=<%s>\n", pAction.c_str(), actionName.c_str());
       }
@@ -211,6 +212,7 @@ void Trainer::doStepNoTrain()
   std::string neededActionName = tm.getCurrentClassifier()->getActionName(neededActionIndex);
   if (ProgramParameters::debug)
   {
+    fprintf(stderr, "Speed : %s actions/s\n", int2humanStr((int)currentSpeed).c_str());
     trainConfig.printForDebug(stderr);
     fprintf(stderr, "action=<%s>\n", neededActionName.c_str());
   }
@@ -327,6 +329,7 @@ void Trainer::doStepTrain()
   
     if (ProgramParameters::debug)
     {
+      fprintf(stderr, "Speed : %s actions/s\n", int2humanStr((int)currentSpeed).c_str());
       trainConfig.printForDebug(stderr);
       fprintf(stderr, "pAction=<%s> oAction=<%s> action=<%s>\n", pAction.c_str(), oAction.c_str(), actionName.c_str());
     }
@@ -415,6 +418,7 @@ void Trainer::doStepTrain()
   
     if (ProgramParameters::debug)
     {
+      fprintf(stderr, "Speed : %s actions/s\n", int2humanStr((int)currentSpeed).c_str());
       trainConfig.printForDebug(stderr);
       tm.getCurrentClassifier()->printWeightedActions(stderr, weightedActions, 10);
       fprintf(stderr, "pAction=<%s> oAction=<%s> action=<%s>\n", pAction.c_str(), oAction.c_str(), actionName.c_str());
diff --git a/transition_machine/include/Action.hpp b/transition_machine/include/Action.hpp
index e49e383ca39eafa796c66d44f69246777e71cca8..02203443873739db7fc9d3ed80e8a8357603d279 100644
--- a/transition_machine/include/Action.hpp
+++ b/transition_machine/include/Action.hpp
@@ -6,8 +6,10 @@
 #ifndef ACTION__H
 #define ACTION__H
 
+#include <vector>
 #include <functional>
-#include "Config.hpp"
+
+class Config;
 
 /// @brief An Action is a function that transforms a Config.
 ///
@@ -70,6 +72,8 @@ class Action
   
   public :
 
+  /// @brief Check if this instance is equal to other.
+  bool operator==(const Action & other) const;
   /// @brief Construct an empty Action.
   Action();
   /// @brief Construct an Action given its name.
diff --git a/transition_machine/include/ActionSet.hpp b/transition_machine/include/ActionSet.hpp
index 58b0b753a6526155a45459c3a6e5e56e3c8032ba..17471a33b5ec3f7c2d1a47ac06abbb80ab0c33ba 100644
--- a/transition_machine/include/ActionSet.hpp
+++ b/transition_machine/include/ActionSet.hpp
@@ -7,6 +7,7 @@
 #define ACTIONSET__H
 
 #include <vector>
+#include <map>
 #include "Action.hpp"
 
 /// @brief A set of Action.
diff --git a/transition_machine/src/Action.cpp b/transition_machine/src/Action.cpp
index 403901310dc15d48aa400c8fcf6e5eeafc580267..b67e64d1cfbafd0bf3192b5ef22304d7c7915195 100644
--- a/transition_machine/src/Action.cpp
+++ b/transition_machine/src/Action.cpp
@@ -1,8 +1,14 @@
 #include "Action.hpp"
+#include "Config.hpp"
 #include "ActionBank.hpp"
 #include "util.hpp"
 #include "ProgramParameters.hpp"
 
+bool Action::operator==(const Action & other) const
+{
+  return name == other.name;
+}
+
 void Action::apply(Config & config)
 {
   config.addHashToHistory();
diff --git a/transition_machine/src/ActionBank.cpp b/transition_machine/src/ActionBank.cpp
index 4224c1eecaac2422a7d7ed7939efbad4b090c4c0..6591710ab6bd308118dea4870be11b50d8ec5666 100644
--- a/transition_machine/src/ActionBank.cpp
+++ b/transition_machine/src/ActionBank.cpp
@@ -1,4 +1,5 @@
 #include "ActionBank.hpp"
+#include "Config.hpp"
 #include "util.hpp"
 #include "ProgramParameters.hpp"
 
@@ -190,7 +191,7 @@ std::vector<Action::BasicAction> ActionBank::str2sequence(const std::string & na
     auto undo = [](Config & c, Action::BasicAction & ba)
       {c.stackPush(std::stoi(ba.data));};
     auto appliable = [](Config & c, Action::BasicAction &)
-      {return !c.stackEmpty() && !c.getTape("GOV")[c.stackTop()-c.getHead()].empty();};
+      {return !c.stackEmpty() && (c.endOfTapes() || !c.getTape("GOV")[c.stackTop()-c.getHead()].empty());};
     Action::BasicAction basicAction =
       {Action::BasicAction::Type::Pop, "", apply, undo, appliable};
 
@@ -212,7 +213,7 @@ std::vector<Action::BasicAction> ActionBank::str2sequence(const std::string & na
       };
     auto appliable = [](Config & c, Action::BasicAction &)
       {
-        if (c.stackEmpty())
+        if (c.stackEmpty() || c.endOfTapes())
           return false;
         int b0 = c.getHead();
         int s0 = c.stackTop();
@@ -285,7 +286,7 @@ std::vector<Action::BasicAction> ActionBank::str2sequence(const std::string & na
       };
     auto appliable = [](Config & c, Action::BasicAction &)
       {
-        return !c.stackEmpty() && simpleBufferWriteAppliable(c, "GOV", 0);
+        return !c.stackEmpty() && !c.endOfTapes() && simpleBufferWriteAppliable(c, "GOV", 0);
       };
     Action::BasicAction basicAction =
       {Action::BasicAction::Type::Write, "", apply, undo, appliable};
diff --git a/transition_machine/src/Config.cpp b/transition_machine/src/Config.cpp
index 7b927a1a40a05696735e130f003b73796a7f9e9f..f4612e013bd917937452b8b4e2e461e0703f6768 100644
--- a/transition_machine/src/Config.cpp
+++ b/transition_machine/src/Config.cpp
@@ -169,6 +169,7 @@ void Config::printForDebug(FILE * output)
   }
 
   fprintf(output, "Configuration : %.2f entropy\n", totalEntropy);
+  fprintf(output, "isFinal : %s endOfTapes : %s\n", isFinal() ? "true" : "false", endOfTapes() ? "true" : "false");
 
   for(int i = 0; i < 80; i++)
     fprintf(output, "-%s", i == 80-1 ? "\n" : "");