diff --git a/reading_machine/include/Transition.hpp b/reading_machine/include/Transition.hpp
index e574f9db0ac35e748a818c4e57db6c44c1430a07..bedf5de4cbaa634c2a139c95e844cc57d6053c5c 100644
--- a/reading_machine/include/Transition.hpp
+++ b/reading_machine/include/Transition.hpp
@@ -24,7 +24,8 @@ class Transition
   void initDeprel(std::string label);
   void initEagerLeft();
   void initEagerRight();
-  void initReduce();
+  void initReduce_strict();
+  void initReduce_relaxed();
   void initEOS(int bufferIndex);
   void initNothing();
   void initIgnoreChar();
diff --git a/reading_machine/src/Transition.cpp b/reading_machine/src/Transition.cpp
index 6fac88efc436c7a19e2c6d931c181b23daa05146..7bc41350cd0457f1c0caa8ad0ab0c671771b36e8 100644
--- a/reading_machine/src/Transition.cpp
+++ b/reading_machine/src/Transition.cpp
@@ -11,8 +11,10 @@ Transition::Transition(const std::string & name)
       [this](auto sm){(initAdd(sm[3], sm[1], sm[2], sm[4]));}},
     {std::regex("SHIFT"),
       [this](auto){initShift();}},
-    {std::regex("REDUCE"),
-      [this](auto){initReduce();}},
+    {std::regex("REDUCE_strict"),
+      [this](auto){initReduce_strict();}},
+    {std::regex("REDUCE_relaxed"),
+      [this](auto){initReduce_relaxed();}},
     {std::regex("eager_LEFT_rel (.+)"),
       [this](auto sm){(initEagerLeft_rel(sm[1]));}},
     {std::regex("eager_RIGHT_rel (.+)"),
@@ -449,7 +451,7 @@ void Transition::initEagerRight()
   };
 }
 
-void Transition::initReduce()
+void Transition::initReduce_strict()
 {
   sequence.emplace_back(Action::assertIsNotEmpty(Config::headColName, Config::Object::Stack, 0));
   sequence.emplace_back(Action::popStack());
@@ -485,6 +487,41 @@ void Transition::initReduce()
   };
 }
 
+void Transition::initReduce_relaxed()
+{
+  sequence.emplace_back(Action::popStack());
+
+  cost = [](const Config & config)
+  {
+    if (!config.isToken(config.getStack(0)))
+      return 0;
+
+    int cost = 0;
+
+    auto stackIndex = config.getStack(0);
+    auto stackGovIndex = config.getConst(Config::headColName, stackIndex, 0);
+
+    for (int i = config.getWordIndex(); config.has(0, i, 0); ++i)
+    {
+      if (!config.isToken(i))
+        continue;
+
+      auto otherGovIndex = config.getConst(Config::headColName, i, 0);
+
+      if (stackGovIndex == std::to_string(i) || otherGovIndex == std::to_string(stackIndex))
+        ++cost;
+
+      if (config.getConst(Config::EOSColName, i, 0) == Config::EOSSymbol1)
+        break;
+    }
+
+    if (config.getConst(Config::EOSColName, config.getStack(0), 0) == Config::EOSSymbol1)
+      ++cost;
+
+    return cost;
+  };
+}
+
 void Transition::initEOS(int bufferIndex)
 {
   sequence.emplace_back(Action::setRoot(bufferIndex));