diff --git a/decoder/src/Decoder.cpp b/decoder/src/Decoder.cpp
index 359bd810419cc4d50ff0d5815fd35212e67e36c3..b06daebc76d4febae6e436f6032a336b43115fd4 100644
--- a/decoder/src/Decoder.cpp
+++ b/decoder/src/Decoder.cpp
@@ -56,7 +56,7 @@ void printAdvancement(Config & config, float currentSpeed)
 {
   if (ProgramParameters::interactive)
   {
-    int totalSize = config.tapes[0].hyp.size();
+    int totalSize = ProgramParameters::tapeSize;
     int steps = config.getHead();
     if (steps && (steps % 200 == 0 || totalSize-steps < 200))
       fprintf(stderr, "Decode : %.2f%%  speed : %s actions/s\r", 100.0*steps/totalSize, int2humanStr((int)currentSpeed).c_str());
@@ -101,7 +101,7 @@ std::pair<float,std::string> getClassifierAction(Config & config, Classifier::We
     if(!action->appliable(config) || nbValidActions-1 != index)
     {
       // First case the analysis is finished but without an empty stack
-      if (config.getHead() == (int)config.tapes[0].ref.size()-1)
+      if (config.endOfTapes())
       {
         while (!config.stackEmpty())
           config.stackPop();
diff --git a/decoder/src/macaon_decode.cpp b/decoder/src/macaon_decode.cpp
index e11ed35128190d8c8fb196f32a1193496a0998a0..4740dc98670d522f9a22365878642edf551dc893 100644
--- a/decoder/src/macaon_decode.cpp
+++ b/decoder/src/macaon_decode.cpp
@@ -47,6 +47,8 @@ po::options_description getOptionsDescription()
       "The name of the buffer's tape that contains the delimiter token for a sequence")
     ("sequenceDelimiter", po::value<std::string>()->default_value("1"),
       "The value of the token that act as a delimiter for sequences")
+    ("tapeSize", po::value<int>()->default_value(100000),
+      "Number of lines in the input file.")
     ("showFeatureRepresentation", po::value<int>()->default_value(0),
       "For each state of the Config, show its feature representation")
     ("interactive", po::value<bool>()->default_value(true),
@@ -141,6 +143,7 @@ int main(int argc, char * argv[])
   ProgramParameters::sequenceDelimiterTape = vm["sequenceDelimiterTape"].as<std::string>();
   ProgramParameters::sequenceDelimiter = vm["sequenceDelimiter"].as<std::string>();
   ProgramParameters::showFeatureRepresentation = vm["showFeatureRepresentation"].as<int>();
+  ProgramParameters::tapeSize = vm["tapeSize"].as<int>();
   ProgramParameters::beamSize = vm["beamSize"].as<int>();
   ProgramParameters::nbChilds = vm["nbChilds"].as<int>();
   ProgramParameters::optimizer = "none";
@@ -171,8 +174,7 @@ int main(int argc, char * argv[])
   TransitionMachine tapeMachine(false);
 
   BD bd(ProgramParameters::bdFilename, ProgramParameters::mcdFilename);
-  Config config(bd);
-  config.readInput(ProgramParameters::input);
+  Config config(bd, ProgramParameters::input);
 
   Decoder decoder(tapeMachine, config);
 
diff --git a/maca_common/include/LimitedArray.hpp b/maca_common/include/LimitedArray.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c830423ee0aab50bd05ff2eaed5cca7d0f4ff86b
--- /dev/null
+++ b/maca_common/include/LimitedArray.hpp
@@ -0,0 +1,62 @@
+/// @file LimitedArray.hpp
+/// @author Franck Dary
+/// @version 1.0
+/// @date 2019-02-08
+
+#ifndef LIMITEDARRAY__H
+#define LIMITEDARRAY__H
+
+#include <vector>
+
+template<typename T>
+class LimitedArray
+{
+  private :
+
+  std::vector<T> data;
+  int nbElements;
+  int lastElementDataIndex;
+  int lastElementRealIndex;
+
+  public :
+
+  LimitedArray(unsigned int limit) : data(limit)
+  {
+    clear();
+  }
+
+  void clear()
+  {
+    nbElements = 0;
+    lastElementDataIndex = -1; 
+    lastElementRealIndex = -1;
+  }
+
+  void push(const T & elem)
+  {
+    nbElements++;
+    if (nbElements > data.size())
+      nbElements = data.size();
+
+    lastElementDataIndex++;
+    if (lastElementDataIndex >= data.size())
+      lastElementDataIndex = 0;
+
+    lastElementRealIndex++;
+
+    data[lastElementDataIndex] = elem;
+  }
+
+  const T & get(unsigned int index)
+  {
+    return data[index % data.size()];
+  }
+
+  int getLastIndex()
+  {
+    return lastElementRealIndex;
+  }
+};
+
+#endif
+
diff --git a/maca_common/include/ProgramParameters.hpp b/maca_common/include/ProgramParameters.hpp
index 6d4692be3cff5f731a81359b56b5dafb52d2a23e..7c35d24ef17d7a0ccb84e227d064afa5661f5047 100644
--- a/maca_common/include/ProgramParameters.hpp
+++ b/maca_common/include/ProgramParameters.hpp
@@ -63,6 +63,7 @@ struct ProgramParameters
   static int nbIndividuals;
   static int beamSize;
   static int nbChilds;
+  static int tapeSize;
 
   private :
 
diff --git a/maca_common/src/ProgramParameters.cpp b/maca_common/src/ProgramParameters.cpp
index 6842ed6cfeab2889f2fdb74cbed9f71aab5c4d7b..6cb84d64a5e8dbc7c2b0e8617b2a85642efd5466 100644
--- a/maca_common/src/ProgramParameters.cpp
+++ b/maca_common/src/ProgramParameters.cpp
@@ -57,4 +57,5 @@ int ProgramParameters::nbErrorsToShow;
 int ProgramParameters::nbIndividuals;
 int ProgramParameters::beamSize;
 int ProgramParameters::nbChilds;
+int ProgramParameters::tapeSize;
 
diff --git a/trainer/src/macaon_train.cpp b/trainer/src/macaon_train.cpp
index b863493487a0f108486e92ba7500431e41e56b81..02f251d6da8ac7c17d622d157ab17ba1f2c1934a 100644
--- a/trainer/src/macaon_train.cpp
+++ b/trainer/src/macaon_train.cpp
@@ -67,6 +67,8 @@ po::options_description getOptionsDescription()
       "Remove identical training examples")
     ("showFeatureRepresentation", po::value<int>()->default_value(0),
       "For each state of the Config, show its feature representation")
+    ("tapeSize", po::value<int>()->default_value(100000),
+      "Number of lines in the input file.")
     ("interactive", po::value<bool>()->default_value(true),
       "Is the shell interactive ? Display advancement informations")
     ("randomEmbeddings", po::value<bool>()->default_value(false),
@@ -204,8 +206,7 @@ void launchTraining()
   TransitionMachine transitionMachine(true);
 
   BD trainBD(ProgramParameters::bdFilename, ProgramParameters::mcdFilename);
-  Config trainConfig(trainBD);
-  trainConfig.readInput(ProgramParameters::trainFilename);
+  Config trainConfig(trainBD, ProgramParameters::trainFilename);
 
   std::unique_ptr<BD> devBD;
   std::unique_ptr<Config> devConfig;
@@ -219,8 +220,7 @@ void launchTraining()
   else
   {
     devBD.reset(new BD(ProgramParameters::bdFilename, ProgramParameters::mcdFilename));
-    devConfig.reset(new Config(*devBD.get()));
-    devConfig->readInput(ProgramParameters::devFilename);
+    devConfig.reset(new Config(*devBD.get(), ProgramParameters::devFilename));
     trainer.reset(new Trainer(transitionMachine, trainBD, trainConfig, devBD.get(), devConfig.get()));
   }
 
@@ -285,6 +285,7 @@ int main(int argc, char * argv[])
   ProgramParameters::dynamicEpoch = vm["epochd"].as<int>();
   ProgramParameters::dynamicProbability = vm["proba"].as<float>();
   ProgramParameters::showFeatureRepresentation = vm["showFeatureRepresentation"].as<int>();
+  ProgramParameters::tapeSize = vm["tapeSize"].as<int>();
   ProgramParameters::iterationSize = vm["iterationSize"].as<int>();
   std::string featureModels = vm["featureModels"].as<std::string>();
   if (!featureModels.empty())
diff --git a/transition_machine/include/Config.hpp b/transition_machine/include/Config.hpp
index f04fe555dc3a94d54b12ca6fd44091346a04eeab..b0c0814b67c85a9672ecc5742075c26e30d1659e 100644
--- a/transition_machine/include/Config.hpp
+++ b/transition_machine/include/Config.hpp
@@ -10,6 +10,9 @@
 #include "BD.hpp"
 #include "File.hpp"
 #include "LimitedStack.hpp"
+#include "LimitedArray.hpp"
+
+//TODO IMPORTANT : il faut faire en sorte que quand on copie 2 configs, chacune ai sa propre version du pointeur vers le fichier input, que les lectures soient independentes.
 
 class Action;
 
@@ -22,25 +25,67 @@ class Config
   /// @brief A Tape of the multi-tapes buffer.
   ///
   /// Each cell can contain a string.
-  struct Tape
+  class Tape
   {
+    private :
+
     /// @brief The name of this Tape.
     std::string name;
     /// @brief Whether or not the content of this Tape is known at the start of the program (it is an input).
     bool isKnown;
-    /// @brief Content of the cells of this Tape, that was given as an input to this program.
-    std::vector<std::string> ref;
-    /// @brief Content of the cells of this Tape, which have been predicted by the program so far.
-    std::vector<std::string> hyp;
     /// @brief The head of this Tape, an index.
     int head;
+    /// @brief Content of the cells of this Tape, that was given as an input to this program.
+    LimitedArray<std::string> ref;
+    /// @brief Content of the cells of this Tape, which have been predicted by the program so far.
+    LimitedArray<std::string> hyp;
+
+    public :
+
     /// @brief Access the value of a cell.
     ///
     /// If isKnown is true, the vector ref will be read, otherwise the vector hyp will be read.
-    /// @param index Index of the cell to access.
+    /// @param relativeIndex Index of the cell to access, relatively to the head.
     ///
     /// @return Value of the cell.
-    const std::string & operator[](int index);
+    const std::string & operator[](int relativeIndex);
+    /// @brief Access the value of a cell of the ref.
+    ///
+    /// @param relativeIndex The index of the cell relatively to the head.
+    ///
+    /// @return The content of the cell.
+    const std::string & getRef(int relativeIndex);
+    /// @brief Access the value of a cell of the hyp.
+    ///
+    /// @param relativeIndex The index of the cell relatively to the head.
+    ///
+    /// @return The content of the cell.
+    const std::string & gethyp(int relativeIndex);
+    /// @brief Return true if the head of this tape is on the last cell.
+    ///
+    /// @return True if the head of this tape is on the last cell.
+    bool headIsAtEnd();
+
+    public :
+
+    /// @brief construct an empty tape. 
+    Tape(const std::string & name, bool isKnown);
+    /// @brief Get the name of this Tape.
+    ///
+    /// @return The name of this Tape.
+    const std::string & getName();
+    /// @brief Set the name of this Tape.
+    ///
+    /// @param name The desired name.
+    void setName(const std::string & name);
+    /// @brief Set if the content of this tape is known or predicted.
+    ///
+    /// @param known The value to set.
+    void setKnown(bool known);
+    /// @brief Move the head of this tape.
+    ///
+    /// @param mvt The relative movement to apply to the head.
+    void moveHead(int mvt);
   };
 
   private :
@@ -62,6 +107,10 @@ class Config
   BD & bd;
   /// @brief The head of this Config. An index of the multi-tapes buffer.
   int head;
+  /// @brief The file containing the input.
+  std::shared_ptr<File> file;
+  /// @brief If the end of input was reached during reading.
+  bool inputAllRead;
 
   public :
 
@@ -77,7 +126,8 @@ class Config
   /// @brief Construct a new Config.
   ///
   /// @param bd The BD that describes the tapes of this Config.
-  Config(BD & bd);
+  /// @param inputFilename The name of the input file.
+  Config(BD & bd, const std::string inputFilename);
   /// @brief Get a Tape by its name.
   ///
   /// @param name The name of the Tape.
@@ -90,10 +140,8 @@ class Config
   ///
   /// @return The corresponding Tape.
   Tape & getTapeByInputCol(int col);
-  /// @brief Read a formated input file (mcf) and use it to fill the tapes.
-  ///
-  /// @param filename The name of the file containing the input.
-  void readInput(const std::string & filename);
+  /// @brief Read a part of a formated input file (mcf) and use it to fill the tapes.
+  void readInput();
   /// @brief Print the Config for debug purposes.
   ///
   /// @param output Where to print.
@@ -215,6 +263,10 @@ class Config
   ///
   /// @return The head of the multi-tapes buffer.
   int getHead() const;
+  /// @brief Return true if the head is at the end of the tapes.
+  ///
+  /// @return True if the head is at the end of the tapes.
+  bool endOfTapes() const;
 };
 
 #endif
diff --git a/transition_machine/src/ActionBank.cpp b/transition_machine/src/ActionBank.cpp
index 0e3787dac1a0a374c64b6df7e69a41667cfba078..2de43a8c4e744c3695452a39657eff12d06926df 100644
--- a/transition_machine/src/ActionBank.cpp
+++ b/transition_machine/src/ActionBank.cpp
@@ -176,7 +176,7 @@ std::vector<Action::BasicAction> ActionBank::str2sequence(const std::string & na
     auto undo = [](Config & c, Action::BasicAction &)
       {c.stackPop();};
     auto appliable = [](Config & c, Action::BasicAction &)
-      {return c.getHead() < (int)c.tapes[0].ref.size()-1;};
+      {return !c.endOfTapes();};
     Action::BasicAction basicAction =
       {Action::BasicAction::Type::Push, "", apply, undo, appliable};
 
@@ -264,7 +264,7 @@ std::vector<Action::BasicAction> ActionBank::str2sequence(const std::string & na
       {
         if (c.stackEmpty())
           return false;
-        return !c.isFinal() && c.getHead() < (int)c.tapes[0].ref.size()-1;
+        return !c.isFinal() && !c.endOfTapes();
       };
     Action::BasicAction basicAction3 =
       {Action::BasicAction::Type::Pop, b1, apply3, undo3, appliable3};
@@ -322,7 +322,7 @@ std::vector<Action::BasicAction> ActionBank::str2sequence(const std::string & na
       };
     auto appliable3 = [](Config & c, Action::BasicAction &)
       {
-        return !c.isFinal() && c.getHead() < (int)c.tapes[0].ref.size()-1;
+        return !c.isFinal() && !c.endOfTapes();
       };
     Action::BasicAction basicAction3 =
       {Action::BasicAction::Type::Push, b1, apply3, undo3, appliable3};
@@ -360,7 +360,7 @@ std::vector<Action::BasicAction> ActionBank::str2sequence(const std::string & na
         for (int i = c.stackSize()-1; i >= 0; i--)
         {
           auto s = c.stackGetElem(i);
-          if (govs.hyp[s].empty() || govs.hyp[s] == "0")
+          if (govs.getHyp(s-b0).empty() || govs.getHyp(s-b0) == "0")
           {
             if (rootIndex == -1)
               rootIndex = s;
@@ -394,7 +394,7 @@ std::vector<Action::BasicAction> ActionBank::str2sequence(const std::string & na
         for (int i = c.stackSize()-1; i >= 0; i--)
         {
           auto s = c.stackGetElem(i);
-          if (govs.hyp[s] == "0")
+          if (govs.getHyp[s-b0] == "0")
           {
             simpleBufferWrite(c, "GOV", "", s-b0);
             break;
@@ -423,7 +423,7 @@ std::vector<Action::BasicAction> ActionBank::str2sequence(const std::string & na
         for (int i = c.stackSize()-1; i >= 0; i--)
         {
           auto s = c.stackGetElem(i);
-          if (labels.hyp[s].empty())
+          if (labels.getHyp(s-b0).empty())
           {
             if (rootIndex == -1)
             {
@@ -446,7 +446,7 @@ std::vector<Action::BasicAction> ActionBank::str2sequence(const std::string & na
         for (int i = c.stackSize()-1; i >= 0; i--)
         {
           auto s = c.stackGetElem(i);
-          if (labels.hyp[s] == "root")
+          if (labels.getHyp(s-b0) == "root")
           {
             simpleBufferWrite(c, "LABEL", "", s-b0);
             break;
@@ -580,7 +580,7 @@ void ActionBank::simpleBufferWrite(Config & config, const std::string & tapeName
 
   int index = config.getHead() + relativeIndex;
 
-  tape.hyp[index] = value;
+  tape.setHyp(index, value);
 }
 
 bool ActionBank::simpleBufferWriteAppliable(Config & config,
@@ -590,10 +590,10 @@ bool ActionBank::simpleBufferWriteAppliable(Config & config,
 
   int index = config.getHead() + relativeIndex;
 
-  if (index == (int)tape.hyp.size()-1)
+  if (c.endOfTapes())
     return true;
 
-  return (!(index < 0 || index >= (int)tape.hyp.size()));
+  return !(index < 0);
 }
 
 bool ActionBank::isRuleAppliable(Config & config,
@@ -609,9 +609,9 @@ void ActionBank::writeRuleResult(Config & config, const std::string & fromTapeNa
   auto & fromTape = config.getTape(fromTapeName);
   auto & toTape = config.getTape(targetTapeName);
 
-  auto & from = fromTape.ref[config.getHead() + relativeIndex];
+  auto & from = fromTape.getRef(relativeIndex);
 
-  toTape.hyp[config.getHead() + relativeIndex] = applyRule(from, rule);
+  toTape.setHyp(config.getHead() + relativeIndex, applyRule(from, rule));
 }
 
 int ActionBank::getLinkLength(const Config & c, const std::string & action)
diff --git a/transition_machine/src/Config.cpp b/transition_machine/src/Config.cpp
index 15f6e745700f420cf01c6a0d8cc5c51565be11b8..2a9b04707c706f0deef4018b592397ea3c066a0d 100644
--- a/transition_machine/src/Config.cpp
+++ b/transition_machine/src/Config.cpp
@@ -4,16 +4,22 @@
 #include "ProgramParameters.hpp"
 #include "Action.hpp"
 
-Config::Config(BD & bd) : bd(bd), tapes(bd.getNbLines()), hashHistory(10), pastActions(100)
+Config::Config(BD & bd, const std::string inputFilename) : bd(bd), hashHistory(10), pastActions(100)
 {
   this->stackHistory = -1;
   this->currentStateName = nullptr;
+  this->inputFilename = inputFilename;
   head = 0;
-  for(unsigned int i = 0; i < tapes.size(); i++)
-  {
-    tapes[i].name = bd.getNameOfLine(i);
-    tapes[i].isKnown = bd.lineIsKnown(i);
-  }
+  inputAllRead = false;
+  for(int i = 0; i < bd.getNbLines(); i++)
+    tapes.emplace_back(bd.getNameOfLine(i), bd.lineIsKnown(i));
+}
+
+Config::Tape::Tape(const std::string & name, bool isKnown) : ref(100), hyp(100)
+{
+  this->head = 0;
+  this->name = name;
+  this->isKnown = isKnown;
 }
 
 Config::Tape & Config::getTape(const std::string & name)
@@ -26,17 +32,22 @@ Config::Tape & Config::getTapeByInputCol(int col)
   return tapes[bd.getLineOfInputCol(col)];
 }
 
-void Config::readInput(const std::string & filename)
+void Config::readInput()
 {
-  this->inputFilename = filename;
-  File file(filename, "r");
+  if (!file.get())
+    file.reset(new File(inputFilename, "r"));
   FILE * fd = file.getDescriptor();
 
   char buffer[10000];
   std::vector<std::string> cols;
   unsigned int usualColsSize = 0;
 
-  while(fscanf(fd, "%[^\n]\n", buffer) == 1)
+  int toRead = 100;
+  int haveRead = 0;
+
+  bool finishedFile = false;
+
+  while(fscanf(fd, "%[^\n]\n", buffer) == 1 && haveRead < toRead)
   {
     cols = split(buffer, '\t');
     if (!usualColsSize)
@@ -53,24 +64,32 @@ void Config::readInput(const std::string & filename)
       {
         auto & tape = getTapeByInputCol(i);
 
-        tape.ref.emplace_back(cols[i]);
+        tape.addToRef(cols[i]);
+        tape.addToHyp("");
       }
+
+    haveRead++;
   }
 
   // Making all tapes the same size
   unsigned int maxTapeSize = 0;
   for(auto & tape : tapes)
-    maxTapeSize = std::max<unsigned int>(maxTapeSize, tape.ref.size());
+    maxTapeSize = std::max<unsigned int>(maxTapeSize, tape.refSize());
 
   for(auto & tape : tapes)
   {
-    while(tape.ref.size() < maxTapeSize)
-      tape.ref.emplace_back();
+    while(tape.refSize() < maxTapeSize)
+      tape.addToRef("");
 
-    tape.hyp.resize(tape.ref.size());
+    while(tape.hypSize() < maxTapeSize)
+      tape.addToHyp("");
 
-    tape.ref.emplace_back("0");
-    tape.hyp.emplace_back("");
+    if (haveRead < toRead)
+    {
+      tape.addToRef("0");
+      tape.addToHyp("");
+      inputAllRead = true;
+    }
   }
 }
 
@@ -107,7 +126,7 @@ void Config::printForDebug(FILE * output)
 
   for(auto & tape : tapes)
   {
-    cols[0].emplace_back(tape.name);
+    cols[0].emplace_back(tape.getName());
 
     for(int i = std::max(0, head-window); i < std::min((int)tape.hyp.size(), head+window); i++)
     {
@@ -170,7 +189,7 @@ void Config::moveHead(int mvt)
     head += mvt;
 
     for (auto & tape : tapes)
-      tape.head += mvt;
+      tape.moveHead(mvt);
   }
 }
 
@@ -199,12 +218,22 @@ void Config::reset()
   readInput(inputFilename);
 }
 
-const std::string & Config::Tape::operator[](int index)
+const std::string & Config::Tape::operator[](int relativeIndex)
 {
   if(isKnown)
-    return ref[index];
+    return getRef[relativeIndex];
+
+  return getHyp[relativeIndex];
+}
+
+const std::string & Config::Tape::getRef(int relativeIndex)
+{
+  return ref[head + relativeIndex];
+}
 
-  return hyp[index];
+const std::string & Config::Tape::gethyp(int relativeIndex)
+{
+  return hyp[head + relativeIndex];
 }
 
 std::string & Config::getCurrentStateName()
@@ -401,3 +430,33 @@ int Config::getHead() const
   return head;
 }
 
+const std::string & Config::Tape::getName()
+{
+  return name;
+}
+
+void Config::Tape::setName(const std::string & name)
+{
+  this->name = name;
+}
+
+void Config::Tape::setKnown(bool known)
+{
+  this->isKnown = known;
+}
+
+void Config::Tape::moveHead(int mvt)
+{
+  head += mvt;
+}
+
+bool Config::endOfTapes() const
+{
+  return inputAllRead && tapes[0].headIsAtEnd();
+}
+
+bool Config::Tape::headIsAtEnd()
+{
+  return head == ref.getLastIndex();
+}
+
diff --git a/transition_machine/src/FeatureBank.cpp b/transition_machine/src/FeatureBank.cpp
index fca1c6021ba23946ab4386c7bf4cc39a9c4c3ce0..4d81ff699e18fd5930c25a0f5298eca37fbd1827 100644
--- a/transition_machine/src/FeatureBank.cpp
+++ b/transition_machine/src/FeatureBank.cpp
@@ -419,11 +419,11 @@ FeatureModel::FeatureValue FeatureBank::aggregateBuffer(Config & c, int from, in
 
   for (auto & tape : c.tapes)
   {
-    Dict * dict = c.getDictOfLine(tape.name);
+    Dict * dict = c.getDictOfLine(tape.getName());
     auto policy = dictPolicy2FeaturePolicy(dict->policy);
     bool ignored = false;
     for (auto & except : exceptions)
-      if (except == tape.name)
+      if (except == tape.getName())
       {
         ignored = true;
         break;
@@ -434,7 +434,7 @@ FeatureModel::FeatureValue FeatureBank::aggregateBuffer(Config & c, int from, in
     for (int i = from; i <= to; i++)
     {
       int index = c.getHead() + i;
-      std::string featName = "b."+std::to_string(i)+"."+tape.name;
+      std::string featName = "b."+std::to_string(i)+"."+tape.getName();
       if(index < 0 || index >= (int)tape.hyp.size())
       {
         result.dicts.emplace_back(dict);
@@ -468,11 +468,11 @@ FeatureModel::FeatureValue FeatureBank::aggregateStack(Config & c, int from, con
 
   for (auto & tape : c.tapes)
   {
-    Dict * dict = c.getDictOfLine(tape.name);
+    Dict * dict = c.getDictOfLine(tape.getName());
     auto policy = dictPolicy2FeaturePolicy(dict->policy);
     bool ignored = false;
     for (auto & except : exceptions)
-      if (except == tape.name)
+      if (except == tape.getName())
       {
         ignored = true;
         break;
@@ -482,7 +482,7 @@ FeatureModel::FeatureValue FeatureBank::aggregateStack(Config & c, int from, con
 
     for (int i = 0; i >= from; i--)
     {
-      std::string featName = "s."+std::to_string(i)+"."+tape.name;
+      std::string featName = "s."+std::to_string(i)+"."+tape.getName();
       if(!c.stackHasIndex(i))
       {
         result.dicts.emplace_back(dict);
diff --git a/transition_machine/src/Oracle.cpp b/transition_machine/src/Oracle.cpp
index 36cdc17d603b0e2cd4c348818baaefee9b6d8582..aab0be882f7dfcb2dd983099adce5957d6ee6380 100644
--- a/transition_machine/src/Oracle.cpp
+++ b/transition_machine/src/Oracle.cpp
@@ -120,16 +120,16 @@ void Oracle::createDatabase()
 
     auto & pos = c.getTape("POS");
 
-    if (c.getHead() > 0 && pos[c.getHead()-1] != pos.ref[c.getHead()-1] && pos[c.getHead()-1] == "det" && pos[c.getHead()] == "prorel")
+    if (c.getHead() > 0 && pos[-1] != pos.getRef(-1) && pos[-1] == "det" && pos[0] == "prorel")
       return std::string("BACK 1");
 
-    if (c.getHead() > 0 && pos[c.getHead()-1] != pos.ref[c.getHead()-1] && pos[c.getHead()-1] == "det" && pos[c.getHead()] == "prep")
+    if (c.getHead() > 0 && pos[-1] != pos.getRef(-1) && pos[-1] == "det" && pos[0] == "prep")
       return std::string("BACK 1");
 
-    if (c.getHead() > 0 && pos[c.getHead()-1] != pos.ref[c.getHead()-1] && pos[c.getHead()-1] == "nc" && pos[c.getHead()] == "nc")
+    if (c.getHead() > 0 && pos[-1] != pos.getRef(-1) && pos[-1] == "nc" && pos[0] == "nc")
       return std::string("BACK 1");
 
-    if (c.getHead() > 0 && pos[c.getHead()-1] != pos.ref[c.getHead()-1] && pos[c.getHead()-1] == "nc" && pos[c.getHead()] == "prep")
+    if (c.getHead() > 0 && pos[-1] != pos.getRef(-1) && pos[-1] == "nc" && pos[0] == "prep")
       return std::string("BACK 1");
 
     return std::string("EPSILON");
@@ -168,9 +168,9 @@ void Oracle::createDatabase()
     if (c.getHead() <= 0)
       return std::string("EPSILON");
 
-    auto & morphoRef = morpho.ref[c.getHead()-1];
-    auto & morpho0 = morpho[c.getHead()-1];
-    auto & morpho1 = morpho[c.getHead()];
+    auto & morphoRef = morpho.getRef(-1);
+    auto & morpho0 = morpho[-1];
+    auto & morpho1 = morpho[0];
 
     if (morpho0 == morphoRef)
       return std::string("EPSILON");
@@ -204,7 +204,7 @@ void Oracle::createDatabase()
   },
   [](Config & c, Oracle *, const std::string & action)
   {
-    return action == "WRITE b.0 POS " + c.getTape("POS").ref[c.getHead()] || c.getHead() >= (int)c.tapes[0].ref.size()-1 ? 0 : 1;
+    return action == "WRITE b.0 POS " + c.getTape("POS").getRef[0] || c.endOfTapes() ? 0 : 1;
   })));
 
   str2oracle.emplace("tokenizer", std::unique_ptr<Oracle>(new Oracle(